diff options
| author | christos <christos@NetBSD.org> | 2020-03-18 19:05:13 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2020-03-18 19:05:13 +0000 |
| commit | 3c275423b220ac99ab95dad65655cf289396d996 (patch) | |
| tree | 73743e75eacf0dc1765b5f331b5f85871aa36ffc /external/ibm-public | |
| parent | e09e275d5c939fe7af6818b3b9bc7362671d4791 (diff) | |
merge postfix-3.5.0
Diffstat (limited to 'external/ibm-public')
435 files changed, 20513 insertions, 6663 deletions
diff --git a/external/ibm-public/postfix/dist/README_FILES/ADDRESS_VERIFICATION_README b/external/ibm-public/postfix/dist/README_FILES/ADDRESS_VERIFICATION_README index 1374a8a2871..f21058c6111 100644 --- a/external/ibm-public/postfix/dist/README_FILES/ADDRESS_VERIFICATION_README +++ b/external/ibm-public/postfix/dist/README_FILES/ADDRESS_VERIFICATION_README @@ -47,11 +47,9 @@ could include the Postfix MTA itself, or some remote MTAs (SMTP interruptus). Probe messages are like normal mail, except that they are never delivered, deferred or bounced; probe messages are always discarded. - probe Postfix message -> mail - queue - Postfix Postfix -> + Postfix Postfix -> queue Internet -> SMTP <-> verify server server | v @@ -62,7 +60,6 @@ deferred or bounced; probe messages are always discarded. ^ | v - Address verification @@ -167,6 +164,12 @@ same address repeatedly. # Postfix 2.6 and later privacy feature. # unverified_recipient_reject_reason = Address lookup failed + # Postfix 3.2 and earlier workaround. + # Do not set enable_original_recipient=no. This prevents Postfix + # from saving the recipient address verification result under + # the original address, when the address verification probe + # message goes through address aliasing or canonical mapping. + The "reject_unknown_recipient_domain" restriction blocks mail for non-existent domains. Putting this before "reject_unverified_recipient" avoids the overhead of generating unnecessary probe messages. @@ -207,6 +210,12 @@ verification for specific domains that often appear in forged email. # Note 2: Avoid hash files here. Use btree or lmdb instead. address_verify_map = btree:/var/lib/postfix/verify + # Postfix 3.2 and earlier workaround. + # Do not set enable_original_recipient=no. This prevents Postfix + # from saving the sender address verification result under the + # original address, when the address verification probe message + # goes through address aliasing or canonical mapping. + /etc/postfix/sender_access: # Don't do this when you handle lots of email. aol.com reject_unverified_sender diff --git a/external/ibm-public/postfix/dist/README_FILES/INSTALL b/external/ibm-public/postfix/dist/README_FILES/INSTALL index e6645dbbc93..c1be6e52611 100644 --- a/external/ibm-public/postfix/dist/README_FILES/INSTALL +++ b/external/ibm-public/postfix/dist/README_FILES/INSTALL @@ -357,7 +357,7 @@ inconsistent results with different versions of the make(1) command. postfix-files will automatically include files under the directory postfix- files.d. Thanks to this, you can install or deinstall a database plugin package without having to edit postfix-files or dynamicmaps.cf. Instead, - you give that plugin its own configuration files dynamicmaps.cf.d and + you give that plugin its own configuration files under dynamicmaps.cf.d and postfix-files.d, and you add or remove those configuration files along with the database plugin dynamically-linked object. @@ -516,110 +516,122 @@ The general method to override Postfix compile-time features is as follows: The following is an extensive list of names and values. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -|NNaammee//VVaalluuee |DDeessccrriippttiioonn | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies one or more non-default object | -| |libraries. Postfix 3.0 and later specify some | -| |of their database library dependencies with | -|AUXLIBS="object_library..." |AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB, | -| |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 is gcc. | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies non-default compiler arguments, for | -|CCARGS="compiler_arguments..."|example, a non-default include directory. The | -| |following directives turn off Postfix features| -| |at compile time: | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with Berkeley DB support. By | -|| |default, Berkeley DB support is compiled in on| -||-DNO_DB |platforms that are known to support this | -|| |feature. If you override this, then you | -|| |probably should also override DEF_DB_TYPE as | -|| |described in section 4.6. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -||-DNO_DNSSEC |Do not build with DNSSEC support, even if the | -|| |resolver library appears to support it. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with Solaris /dev/poll support. | -||-DNO_DEVPOLL |By default, /dev/poll support is compiled in | -|| |on Solaris versions that are known to support | -|| |this feature. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with Linux EPOLL support. By | -||-DNO_EPOLL |default, EPOLL support is compiled in on | -|| |platforms that are known to support this | -|| |feature. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with EAI (SMTPUTF8) support. By | -||-DNO_EAI |default, EAI support is compiled in when the | -|| |"icuuc" library and header files are found. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not require support for C99 "inline" | -||-DNO_INLINE |functions. Instead, implement argument | -|| |typechecks for non-printf/scanf-like functions| -|| |with ternary operators and unreachable code. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with IPv6 support. By default, | -|| |IPv6 support is compiled in on platforms that | -||-DNO_IPV6 |are known to have IPv6 support. Note: this | -|| |directive is for debugging and testing only. | -|| |It is not guaranteed to work on all platforms.| -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with FreeBSD / NetBSD / OpenBSD /| -||-DNO_KQUEUE |MacOSX KQUEUE support. By default, KQUEUE | -|| |support is compiled in on platforms that are | -|| |known to support it. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with NIS or NISPLUS support. NIS | -||-DNO_NIS |is not available on some recent Linux | -|| |distributions. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with NISPLUS support. NISPLUS is | -||-DNO_NISPLUS |not available on some recent Solaris | -|| |distributions. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Do not build with PCRE support. By default, | -||-DNO_PCRE |PCRE support is compiled in when the pcre- | -|| |config utility is installed. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Disable support for POSIX getpwnam_r/ | -||-DNO_POSIX_GETPW_R |getpwuid_r. By default Postfix uses these | -|| |where they are known to be available. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -|| |Use setjmp()/longjmp() instead of sigsetjmp()/| -||-DNO_SIGSETJMP |siglongjmp(). By default, Postfix uses | -|| |sigsetjmp()/siglongjmp() when they are known | -|| |to be available. | -|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies a non-default compiler debugging | -|DEBUG=debug_level |level. The default is "-g". Specify DEBUG= to | -| |turn off debugging. | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies a non-default optimization level. | -|OPT=optimization_level |The default is "-O". Specify OPT= to turn off | -| |optimization. | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies non-default compiler options for | -|SHLIB_CFLAGS=flags |building Postfix dynamically-linked libraries | -| |and database plugins. The typical default is | -| |"-fPIC". | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies a non-default runpath for Postfix | -|SHLIB_RPATH=rpath |dynamically-linked libraries. The typical | -| |default is "'-Wl,-rpath,${SHLIB_DIR}'". | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies a non-default suffix for Postfix | -|SHLIB_SUFFIX=suffix |dynamically-linked libraries and database | -| |plugins. The typical default is ".so". | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | -| |Specifies non-default compiler warning options| -|WARN="warning_flags..." |for use when "make" is invoked in a source | -| |subdirectory only. | -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|NNaammee//VVaalluuee |DDeessccrriippttiioonn | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies one or more non-default object | +| |libraries. Postfix 3.0 and later specify some| +| |of their database library dependencies with | +|AUXLIBS="object_library..." |AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB, | +| |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 is gcc. | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies non-default compiler arguments, for| +|CCARGS="compiler_arguments..." |example, a non-default include directory. The| +| |following directives turn off Postfix | +| |features at compile time: | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with Berkeley DB support. By | +|| |default, Berkeley DB support is compiled in | +||-DNO_DB |on platforms that are known to support this | +|| |feature. If you override this, then you | +|| |probably should also override DEF_DB_TYPE as | +|| |described in section 4.6. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +||-DNO_DNSSEC |Do not build with DNSSEC support, even if the| +|| |resolver library appears to support it. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with Solaris /dev/poll support. | +||-DNO_DEVPOLL |By default, /dev/poll support is compiled in | +|| |on Solaris versions that are known to support| +|| |this feature. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with Linux EPOLL support. By | +||-DNO_EPOLL |default, EPOLL support is compiled in on | +|| |platforms that are known to support this | +|| |feature. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with EAI (SMTPUTF8) support. By | +||-DNO_EAI |default, EAI support is compiled in when the | +|| |"icuuc" library and header files are found. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not require support for C99 "inline" | +|| |functions. Instead, implement argument | +||-DNO_INLINE |typechecks for non-printf/scanf-like | +|| |functions with ternary operators and | +|| |unreachable code. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with IPv6 support. By default, | +|| |IPv6 support is compiled in on platforms that| +|| |are known to have IPv6 support. Note: this | +||-DNO_IPV6 |directive is for debugging And testing only. | +|| |It is not guaranteed to work on all | +|| |platforms. If you don't want IPv6 support, | +|| |set "inet_protocols = ipv4" in main.cf. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with FreeBSD / NetBSD / OpenBSD | +||-DNO_KQUEUE |/ MacOSX KQUEUE support. By default, KQUEUE | +|| |support is compiled in on platforms that are | +|| |known to support it. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with NIS or NISPLUS support. NIS| +||-DNO_NIS |is not available on some recent Linux | +|| |distributions. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with NISPLUS support. NISPLUS is| +||-DNO_NISPLUS |not available on some recent Solaris | +|| |distributions. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with PCRE support. By default, | +||-DNO_PCRE |PCRE support is compiled in when the pcre- | +|| |config utility is installed. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Disable support for POSIX getpwnam_r/ | +||-DNO_POSIX_GETPW_R |getpwuid_r. By default Postfix uses these | +|| |where they are known to be available. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Use setjmp()/longjmp() instead of sigsetjmp | +||-DNO_SIGSETJMP |()/siglongjmp(). By default, Postfix uses | +|| |sigsetjmp()/siglongjmp() when they are known | +|| |to be available. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Use sprintf() instead of snprintf(). By | +||-DNO_SNPRINTF |default, Postfix uses snprintf() except on | +|| |ancient systems. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies a non-default compiler debugging | +|DEBUG=debug_level |level. The default is "-g". Specify DEBUG= to| +| |turn off debugging. | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies a non-default optimization level. | +|OPT=optimization_level |The default is "-O". Specify OPT= to turn off| +| |optimization. | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies options for the postfix-install | +|POSTFIX_INSTALL_OPTS=-option...|command, separated by whitespace. Currently, | +| |the only supported option is "-keep-build- | +| |mtime". | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies non-default compiler options for | +|SHLIB_CFLAGS=flags |building Postfix dynamically-linked libraries| +| |and database plugins. The typical default is | +| |"-fPIC". | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies a non-default runpath for Postfix | +|SHLIB_RPATH=rpath |dynamically-linked libraries. The typical | +| |default is "'-Wl,-rpath,${SHLIB_DIR}'". | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies a non-default suffix for Postfix | +|SHLIB_SUFFIX=suffix |dynamically-linked libraries and database | +| |plugins. The typical default is ".so". | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +| |Specifies non-default compiler warning | +|WARN="warning_flags..." |options for use when "make" is invoked in a | +| |source subdirectory only. | +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | 44..88 -- SSuuppppoorrtt ffoorr tthhoouussaannddss ooff pprroocceesssseess diff --git a/external/ibm-public/postfix/dist/README_FILES/TLS_README b/external/ibm-public/postfix/dist/README_FILES/TLS_README index b8d27a0de1b..2dd2348ebd1 100644 --- a/external/ibm-public/postfix/dist/README_FILES/TLS_README +++ b/external/ibm-public/postfix/dist/README_FILES/TLS_README @@ -2,25 +2,17 @@ PPoossttffiixx TTLLSS SSuuppppoorrtt ------------------------------------------------------------------------------- -WWAARRNNIINNGG - -By turning on TLS support in Postfix, you not only get the ability to encrypt -mail and to authenticate remote SMTP clients or servers. You also turn on -thousands and thousands of lines of OpenSSL library code. Assuming that OpenSSL -is written as carefully as Wietse's own code, every 1000 lines introduce one -additional bug into Postfix. - WWhhaatt PPoossttffiixx TTLLSS ssuuppppoorrtt ddooeess ffoorr yyoouu Transport Layer Security (TLS, formerly called SSL) provides certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. - NOTE: This document describes a TLS user interface that was introduced - with Postfix version 2.3. Support for an older user interface is documented - in TLS_LEGACY_README, which also describes the differences between Postfix - and the third-party patch on which Postfix version 2.2 TLS support was - based. +NOTE: By turning on TLS support in Postfix, you not only get the ability to +encrypt mail and to authenticate remote SMTP clients or servers. You also turn +on hundreds of thousands of lines of OpenSSL library code. Assuming that +OpenSSL is written as carefully as Wietse's own code, every 1000 lines +introduce one additional bug into Postfix. Topics covered in this document: @@ -70,6 +62,7 @@ SSMMTTPP SSeerrvveerr ssppeecciiffiicc sseettttiinnggs Topics covered in this section: * Server-side certificate and private key configuration + * Server-side forward-secrecy configuration * Server-side TLS activity logging * Enabling TLS in the Postfix SMTP server * Client certificate verification @@ -98,22 +91,29 @@ require a server certificate. For servers that are nnoott public Internet MX hosts, Postfix supports configurations with no certificates. This entails the use of just the anonymous -TLS ciphers, which are not supported by typical SMTP clients. Since such -clients will not, as a rule, fall back to plain text after a TLS handshake -failure, a certificate-less Postfix SMTP server will be unable to receive email -from most TLS enabled clients. To avoid accidental configurations with no -certificates, Postfix enables certificate-less operation only when the -administrator explicitly sets "smtpd_tls_cert_file = none". This ensures that -new Postfix SMTP server configurations will not accidentally run with no +TLS ciphers, which are not supported by typical SMTP clients. Since some +clients may not fall back to plain text after a TLS handshake failure, a +certificate-less Postfix SMTP server will be unable to receive email from some +TLS-enabled clients. To avoid accidental configurations with no certificates, +Postfix enables certificate-less operation only when the administrator +explicitly sets "smtpd_tls_cert_file = none". This ensures that new Postfix +SMTP server configurations will not accidentally enable TLS without certificates. +Note that server certificates are nnoott optional in TLS 1.3. To run without +certificates you'd have to disable the TLS 1.3 protocol by including '!TLSv1.3' +in "smtpd_tls_protocols" and perhaps also "smtpd_tls_mandatory_protocols". It +is simpler instead to just configure a certificate chain. Certificate-less +operation is not recommended. + RSA, DSA and ECDSA (Postfix >= 2.6) certificates are supported. Most sites only have RSA certificates. You can configure all three at the same time, in which case the ciphersuite negotiated with the remote SMTP client determines which -certificate is used. If your DNS zone is signed, and you want to publish RFC -6698 TLSA records, these must match any of the configured certificates. Since -the best practice is to publish "3 1 1" certificate associations, create a -separate TLSA record for each public-key certificate digest. +certificate is used. If your DNS zone is signed, and you want to publish DANE +TLSA (RFC 6698, RFC 7671, RFC 7672) records, these must match all of the +configured certificate chains. Since the best practice is to publish "3 1 1" +certificate associations, create a separate TLSA record to match each public- +key certificate digest. CCrreeaattiinngg tthhee sseerrvveerr cceerrttiiffiiccaattee ffiillee @@ -135,10 +135,9 @@ assume that the certificate for "server.example.com" was issued by % ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> sseerrvveerr..ppeemm - * If you publish RFC 6698 TLSA "2 0 1" or "2 1 1" records to specify root CA - certificate digests, you must include the corresponding root CA - certificates in the "server.pem" certificate file. See the documentation of - the tls_dane_trust_anchor_digest_enable main.cf parameter. + * If you publish DANE TLSA (RFC 6698, RFC 7671, RFC 7672) "2 0 1" or "2 1 1" + records to specify root CA certificate digests, you must include the + corresponding root CA certificates in the "server.pem" certificate file. % ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm rroooott..ppeemm >> sseerrvveerr..ppeemm @@ -150,11 +149,9 @@ assume that the certificate for "server.example.com" was issued by any other digest of a CA certificate, but it is expected that SHA256 will be by far the most common digest for TLSA. - As a best practice, publish either "3 0 1" or "3 1 1" TLSA associations - that specify the SHA256 digest of the server certificate public key with - the alias-expanded hostname of each STARTTLS capable SMTP server. These - continue to work when a certificate is renewed with the same public/private - key pair. + As a best practice, publish "3 1 1" TLSA associations that specify the + SHA256 digest of the server's public key. These continue to work unmodified + when a certificate is renewed with the same public/private key pair. For instructions on how to compute the digest of a certificate or its public key for use in TLSA records, see the documentation of the @@ -175,6 +172,47 @@ $smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory. CCoonnffiigguurriinngg tthhee sseerrvveerr cceerrttiiffiiccaattee aanndd kkeeyy ffiilleess +Example: Postfix >= 3.4 all-in-one chain file(s). One or more chain files that +start with a key that is immediately followed by the corresponding certificate +and any additional issuer certificates. A single file can hold multiple (key, +cert, [chain]) sequences, one per algorithm. It is typically simpler to keep +the chain for each algorithm in its own file. Most users are likely to deploy +just a single RSA chain, but with OpenSSL 1.1.1, it is possible to deploy up to +five chains, one each for RSA, ECDSA, ED25519, ED448 and even the obsolete DSA. + + # Postfix >= 3.4. Preferred configuration interface. Each file + # starts with the private key, followed by the corresponding + # certificate, and any intermediate issuer certificates. The root CA + # cert may also be needed when published as a DANE trust anchor. + # + smtpd_tls_chain_files = + /etc/postfix/rsa.pem, + /etc/postfix/ecdsa.pem, + /etc/postfix/ed25519.pem, + /etc/postfix/ed448.pem + +You can also store the keys separately from their certificates, again provided +each is listed before the corresponding certificate chain. Storing a key and +its associated certificate chain in separate files is not recommended, because +this is prone to race conditions during key rollover, as there is no way to +update multiple files atomically. + + # Postfix >= 3.4. + # Storing keys separately from the associated certificates is not + # recommended. + smtpd_tls_chain_files = + /etc/postfix/rsakey.pem, + /etc/postfix/rsacerts.pem, + /etc/postfix/ecdsakey.pem, + /etc/postfix/ecdsacerts.pem + +The below examples show the legacy algorithm-specific configurations for +Postfix 3.3 and older. With Postfix <= 3.3, even if the key is stored in the +same file as the certificate, the file is read twice and a (brief) race +condition still exists during key rollover. While Postfix >= 3.4 avoids the +race when the key and certificate are in the same file, you should use the new +"smtpd_tls_chain_files" interface shown above. + RSA key and certificate examples: /etc/postfix/main.cf: @@ -190,8 +228,8 @@ Their DSA counterparts: Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 1.0.0): /etc/postfix/main.cf: - # Most clients will not be ECDSA capable, so you will likely also need - # an RSA or DSA certificate and private key. + # Some clients will not be ECDSA capable, so you will likely still need + # an RSA certificate and private key. # smtpd_tls_eccert_file = /etc/postfix/server-ecdsa.pem smtpd_tls_eckey_file = $smtpd_tls_eccert_file @@ -200,6 +238,8 @@ TLS without certificates for servers serving exclusively anonymous-cipher capable clients: /etc/postfix/main.cf: + # Not recommended: breaks TLS 1.3 and clients that don't support + # anonymous cipher suites. smtpd_tls_cert_file = none To verify a remote SMTP client certificate, the Postfix SMTP server needs to @@ -241,6 +281,14 @@ Example: smtpd_tls_CAfile = /etc/postfix/CAcert.pem smtpd_tls_CApath = /etc/postfix/certs +SSeerrvveerr--ssiiddee ffoorrwwaarrdd--sseeccrreeccyy ccoonnffiigguurraattiioonn + +If you want to take maximal advantage of ciphers that offer forward secrecy see +the Getting started section of FORWARD_SECRECY_README. The full document +conveniently presents all information about Postfix forward secrecy support in +one place: what forward secrecy is, how to tweak settings, and what you can +expect to see when Postfix uses ciphers with forward secrecy. + SSeerrvveerr--ssiiddee TTLLSS aaccttiivviittyy llooggggiinngg To get additional information about Postfix SMTP server TLS activity you can @@ -605,7 +653,10 @@ source code. For a server that is not a public Internet MX host, Postfix supports configurations with no server certificates that use oonnllyy the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" and not -specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. +specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. Such +configurations may not interoperate with some clients, and require that TLSv1.3 +be explicitly disabled. Therefore, they are not recommended, it is better and +simpler to just configure a suitable certificate. Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3, with high grade ciphers: @@ -621,11 +672,22 @@ ciphers: # Legacy syntax: smtpd_tls_mandatory_protocols = TLSv1 +With Postfix >= 3.4, specify instead a single file that holds the key followed +by the corresponding certificate and any associated issuing certificates, +leaving the "smtpd_tls_cert_file" and "smtpd_tls_key_file" and related DSA and +ECDSA parameters empty. + + /etc/postfix/main.cf: + smtpd_tls_chain_files = /etc/postfix/rsachain.pem + smtpd_tls_cert_file = + smtpd_tls_key_file = + ... + If you want to take maximal advantage of ciphers that offer forward secrecy see the Getting started section of FORWARD_SECRECY_README. The full document -conveniently presents all information about Postfix "perfect" forward secrecy -support in one place: what forward secrecy is, how to tweak settings, and what -you can expect to see when Postfix uses ciphers with forward secrecy. +conveniently presents all information about Postfix forward secrecy support in +one place: what forward secrecy is, how to tweak settings, and what you can +expect to see when Postfix uses ciphers with forward secrecy. Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS servers to preempt the TLS client's cipher-suite preference list. This is @@ -659,11 +721,12 @@ Example: smtpd_starttls_timeout = 300s With Postfix 2.8 and later, the tls_disable_workarounds parameter specifies a -list or bit-mask of OpenSSL bug work-arounds to disable. This may be necessary -if one of the work-arounds enabled by default in OpenSSL proves to pose a -security risk, or introduces an unexpected interoperability issue. Some bug -work-arounds known to be problematic are disabled in the default value of the -parameter when linked with an OpenSSL library that could be vulnerable. +list or bit-mask of default-enabled OpenSSL bug work-arounds to disable. This +may be necessary if one of the work-arounds enabled by default in OpenSSL +proves to pose a security risk, or introduces an unexpected interoperability +issue. The list of enabled bug work-arounds is OpenSSL-release-specific. See +the tls_disable_workarounds parameter documentation for the list of supported +values. Example: @@ -676,16 +739,9 @@ mask of OpenSSL options to enable. Specify one or more of the named options below, or a hexadecimal bitmask of options found in the ssl.h file corresponding to the run-time OpenSSL library. While it may be reasonable to turn off all bug workarounds (see above), it is not a good idea to attempt to -turn on all features. +turn on all features. See the tls_ssl_options parameter documentation for the +list of supported values. -LLEEGGAACCYY__SSEERRVVEERR__CCOONNNNEECCTT - See SSL_CTX_set_options(3). -NNOO__TTIICCKKEETT - See SSL_CTX_set_options(3). -NNOO__CCOOMMPPRREESSSSIIOONN - Disable SSL compression even if supported by the OpenSSL library. - Compression is CPU-intensive, and compression before encryption does not - always improve security. Example: /etc/postfix/main.cf: @@ -706,6 +762,7 @@ Topics covered in this section: * Configuring TLS in the SMTP/LMTP client * Client-side TLS activity logging * Client-side certificate and private key configuration + * Client-side TLS connection reuse * Client-side TLS session cache * Client TLS limitations * Per-destination TLS policy @@ -830,7 +887,7 @@ interoperability and security guidelines. Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for mail delivery to -the public Internet. Most MX hosts do not support TLS at all, and some of those +the public Internet. Some MX hosts do not support TLS at all, and some of those that do have broken implementations. On a host that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level. @@ -882,15 +939,15 @@ not specified consistently. DDAANNEE TTLLSS aauutthheennttiiccaattiioonn.. -The Postfix SMTP client supports two TLS security levels based on RFC6698 DANE -TLSA records. The opportunistic "dane" level and the mandatory "dane-only" -level. +The Postfix SMTP client supports two TLS security levels based on DANE TLSA +(RFC 6698, RFC 7671, RFC 7672) records. The opportunistic "dane" level and the +mandatory "dane-only" level. The "dane" level is a stronger form of opportunistic TLS that is resistant to man in the middle and downgrade attacks when the destination domain uses DNSSEC to publish DANE TLSA records for its MX hosts. If a remote SMTP server has -"usable" (see RFC 6698) DANE TLSA records, the server connection will be -authenticated. When DANE authentication fails, there is no fallback to +"usable" (see section 3 of RFC 7672) DANE TLSA records, the server connection +will be authenticated. When DANE authentication fails, there is no fallback to unauthenticated or plaintext delivery. If TLSA records are published for a given remote SMTP server (implying TLS @@ -918,40 +975,25 @@ TLSA records validated with DNSSEC. For TLSA policy to be in effect, the destination domain's containing DNS zone must be signed and the Postfix SMTP client's operating system must be configured to send its DNS queries to a recursive DNS nameserver that is able to validate the signed records. Each MX -host's DNS zone needs to also be signed, and needs to publish DANE TLSA (RFC -6698) records that specify how that MX host's TLS certificate is to be -verified. +host's DNS zone needs to also be signed, and needs to publish DANE TLSA (see +section 3 of RFC 7672) records that specify how that MX host's TLS certificate +is to be verified. TLSA records do not preempt the normal SMTP MX host selection algorithm, if some MX hosts support TLSA and others do not, TLS security will vary from delivery to delivery. It is up to the domain owner to configure their MX hosts and their DNS sensibly. To configure the Postfix SMTP client for DNSSEC lookups see the documentation for the smtp_dns_support_level main.cf parameter. The -tls_dane_trust_anchor_digest_enable main.cf parameter controls support for -trust-anchor digest TLSA records. The tls_dane_digests and -tls_dane_digest_agility parameters control the list of supported digests and -digest downgrade attack resistance. - -DANE for SMTP MTAs deviates in some details from the baseline DANE protocol in -RFC 6698. Most notably, it is not expected that SMTP MTAs can reasonably -include every public CA that a remote SMTP server's administrator may believe -to be well-known. Nor is there an interactive user to "click OK" when -authentication fails. - -Therefore, certificate usages "0" and "1" from RFC 6698 which are intended to -"constrain" existing PKI trust, are not supported. TLSA records with usage "0" -are treated as "unusable". TLSA records with usage "1" are instead treated as -"trust assertions" and mapped to usage "3". Specifically, with certificate -usage "1", Postfix will not require the remote SMTP server's certificate to be -trusted with respect to any locally defined public CAs, it is the domain -owner's responsibility to ensure that the certificate associations in their -TLSA records are appropriate to authenticate their SMTP servers. - -The Postfix SMTP client supports only certificate usages "2" and "3" (with "1" -treated as though it were "3"). See tls_dane_trust_anchor_digest_enable for -usage "2" usability considerations. Support for certificate usage "1" is an -experiment, it may be withdrawn in the future. Server operators SHOULD NOT -publish TLSA records with usage "1". +tls_dane_digests parameter controls the list of supported digests. + +As explained in section 3 of RFC 7672, certificate usages "0" and "1", which +are intended to "constrain" existing Web-PKI trust, are not supported with MTA- +to-MTA SMTP. Rather, TLSA records with usages "0" and "1" are treated as +"unusable". + +The Postfix SMTP client supports only certificate usages "2" and "3". +Experimental support for silently mapping certificate usage "1" to "3" has been +withdrawn starting with Postfix 3.2. When usable TLSA records are obtained for the remote SMTP server the Postfix SMTP client sends the SNI TLS extension in its SSL client hello message. This @@ -962,7 +1004,7 @@ For purposes of protocol and cipher selection, the "dane" security level is treated like a "mandatory" TLS security level, and weak ciphers and protocols are disabled. Since DANE authenticates server certificates the "aNULL" cipher- suites are transparently excluded at this level, no need to configure this -manually. RFC 6698 (DANE) TLS authentication is available with Postfix 2.11 and +manually. RFC 7672 (DANE) TLS authentication is available with Postfix 2.11 and later. When a DANE TLSA record specifies a trust-anchor (TA) certificate (that is an @@ -1172,8 +1214,8 @@ SMTP server, and any untrusted issuing parent certificates will be ignored. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory certificate trust chain and subject name verification is not viable -as a default Internet mail delivery policy. Most MX hosts do not support TLS at -all, and a significant portion of TLS enabled MTAs use self-signed +as a default Internet mail delivery policy. Some MX hosts do not support TLS at +all, and a significant portion of TLS-enabled MTAs use self-signed certificates, or certificates that are signed by a private Certification Authority. On a machine that delivers mail to the Internet, you should not configure mandatory server certificate verification as a default policy. @@ -1233,8 +1275,8 @@ SMTP server, and any untrusted issuing parent certificates will be ignored. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory secure server certificate verification is not viable as a default -Internet mail delivery policy. Most MX hosts do not support TLS at all, and a -significant portion of TLS enabled MTAs use self-signed certificates, or +Internet mail delivery policy. Some MX hosts do not support TLS at all, and a +significant portion of TLS-enabled MTAs use self-signed certificates, or certificates that are signed by a private Certification Authority. On a machine that delivers mail to the Internet, you should not configure secure TLS verification as a default policy. @@ -1356,17 +1398,18 @@ them. The recommended setting is to let the defaults stand: # Postfix >= 2.6 smtp_tls_eccert_file = smtp_tls_eckey_file = + # Postfix >= 3.4 + smtp_tls_chain_files = The best way to use the default settings is to comment out the above parameters in main.cf if present. During TLS startup negotiation the Postfix SMTP client may present a -certificate to the remote SMTP server. The Netscape client is rather clever -here and lets the user select between only those certificates that match CA -certificates offered by the remote SMTP server. As the Postfix SMTP client uses -the "SSL_connect()" function from the OpenSSL package, this is not possible and -we have to choose just one certificate. So for now the default is to use _no_ -certificate and key unless one is explicitly specified here. +certificate to the remote SMTP server. Browsers typically let the user select +among the certificates that match the CA names indicated by the remote SMTP +server. The Postfix SMTP client does not yet have a mechanism to select from +multiple candidate certificates on the fly, and supports a single set of +certificates (at most one per public key algorithm). RSA, DSA and ECDSA (Postfix >= 2.6) certificates are supported. You can configure all three at the same time, in which case the cipher used determines @@ -1378,28 +1421,76 @@ as the Postfix SMTP server. If a certificate is to be presented, it must be in accessible without password. Both parts (certificate and private key) may be in the same file. +With OpenSSL 1.1.1 and Postfix >= 3.4 it is also possible to configure Ed25519 +and Ed448 certificates. Rather than add two more pairs of key and certificate +parameters, Postfix 3.4 introduces a new "smtp_tls_chain_files" parameter which +specifies all the configured certificates at once, and handles files that hold +both the key and the associated certificates in one pass, thereby avoiding +potential race conditions during key rollover. + To enable remote SMTP servers to verify the Postfix SMTP client certificate, the issuing CA certificates must be made available to the server. You should include the required certificates in the client certificate file, the client certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "client.example.com" was issued by "intermediate -CA" which itself has a certificate issued by "root CA". Create the client.pem -file with: +CA" which itself has a certificate issued by "root CA". As the "root" super- +user create the client.pem file with: - % ccaatt cclliieenntt__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> cclliieenntt..ppeemm + # uummaasskk 007777 + # ccaatt cclliieenntt__kkeeyy..ppeemm cclliieenntt__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> cchhaaiinn..ppeemm A Postfix SMTP client certificate supplied here must be usable as SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. A server that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA certificate here. Leaving it out -of the "client.pem" file reduces the overhead of the TLS exchange. +of the "chain.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. +Example: Postfix >= 3.4 all-in-one chain file(s). One or more chain files that +start with a key that is immediately followed by the corresponding certificate +and any additional issuer certificates. A single file can hold multiple (key, +cert, [chain]) sequences, one per algorithm. It is typically simpler to keep +the chain for each algorithm in its own file. Most users are likely to deploy +at most a single RSA chain, but with OpenSSL 1.1.1, it is possible to deploy up +five chains, one each for RSA, ECDSA, ED25519, ED448 and even the obsolete DSA. + + # Postfix >= 3.4. Preferred configuration interface. Each file + # starts with the private key, followed by the corresponding + # certificate, and any intermediate issuer certificates. + # + smtp_tls_chain_files = + /etc/postfix/rsa.pem, + /etc/postfix/ecdsa.pem, + /etc/postfix/ed25519.pem, + /etc/postfix/ed448.pem + +You can also store the keys separately from their certificates, again provided +each is listed before the corresponding certificate chain. Storing a key and +its associated certificate chain in separate files is not recommended, because +this is prone to race conditions during key rollover, as there is no way to +update multiple files atomically. + + # Postfix >= 3.4. + # Storing keys separately from the associated certificates is not + # recommended. + smtp_tls_chain_files = + /etc/postfix/rsakey.pem, + /etc/postfix/rsacerts.pem, + /etc/postfix/ecdsakey.pem, + /etc/postfix/ecdsacerts.pem + +The below examples show the legacy algorithm-specific configurations for +Postfix 3.3 and older. With Postfix <= 3.3, even if the key is stored in the +same file as the certificate, the file is read twice and a (brief) race +condition still exists during key rollover. While Postfix >= 3.4 avoids the +race when the key and certificate are in the same file, you should use the new +"smtp_tls_chain_files" interface shown above. + RSA key and certificate examples: /etc/postfix/main.cf: @@ -1446,6 +1537,43 @@ Example: smtp_tls_CAfile = /etc/postfix/CAcert.pem smtp_tls_CApath = /etc/postfix/certs +CClliieenntt--ssiiddee TTLLSS ccoonnnneeccttiioonn rreeuussee + +Historically, the Postfix SMTP client has supported multiple deliveries per +plaintext connection. Postfix 3.4 introduces support for multiple deliveries +per TLS-encrypted connection. Multiple deliveries per connection improve mail +delivery performance, especially for destinations that throttle clients that +don't combine deliveries. + +To enable multiple deliveries per TLS connection, specify: + + /etc/postfix/main.cf: + smtp_tls_connection_reuse = yes + +Alternatively, specify the attribute "connection_reuse=yes" in an +smtp_tls_policy_maps entry. + +The implementation of TLS connection reuse relies on the same scache(8) service +as used for delivering plaintext SMTP mail, the same tlsproxy(8) daemon as used +by the postscreen(8) service, and relies on the same hints from the qmgr(8) +daemon. See "Postfix Connection Cache" for a description of the underlying +connection reuse infrastructure. + +Initial SMTP handshake: + + smtp(8) -> remote SMTP server + +Reused SMTP/TLS connection, or new SMTP/TLS connection: + + smtp(8) -> tlsproxy(8) -> remote SMTP server + +Cached SMTP/TLS connection: + + scache(8) -> tlsproxy(8) -> remote SMTP server + +As of Postfix 3.4, TLS connection reuse is disabled by default. This may change +once the impact on over-all performance is understood. + CClliieenntt--ssiiddee TTLLSS sseessssiioonn ccaacchhee The remote SMTP server and the Postfix SMTP client negotiate a session, which @@ -1613,7 +1741,10 @@ 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. + 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. eennccrryypptt Mandatory encryption. Mail is delivered only if the remote SMTP server offers STARTTLS and the TLS handshake succeeds. At this level and higher, @@ -1629,7 +1760,7 @@ ddaannee 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 6698 (DANE) TLS authentication and DNSSEC support is + the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 and later. ddaannee--oonnllyy Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA @@ -1637,7 +1768,7 @@ ddaannee--oonnllyy 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 6698 (DANE) TLS authentication and DNSSEC support is + TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 and later. ffiinnggeerrpprriinntt Certificate fingerprint verification. Available with Postfix 2.5 and later. @@ -2142,7 +2273,10 @@ SSeellff--ssiiggnneedd sseerrvveerr cceerrttiiffiiccaa The following commands (credits: Viktor Dukhovni) generate and install a 2048- bit RSA private key and 10-year self-signed certificate for the local Postfix -system. This requires super-user privileges. +system. This requires super-user privileges. (By using date-specific filenames +for the certificate and key files, and updating main.cf with new filenames, a +potential race condition in which the key and certificate might not match is +avoided). # dir="$(postconf -h config_directory)" # fqdn=$(postconf -h myhostname) diff --git a/external/ibm-public/postfix/dist/conf/main.cf b/external/ibm-public/postfix/dist/conf/main.cf index 6368fb0006e..3e2e9e69c35 100644 --- a/external/ibm-public/postfix/dist/conf/main.cf +++ b/external/ibm-public/postfix/dist/conf/main.cf @@ -1,4 +1,4 @@ -# $NetBSD: main.cf,v 1.7 2017/02/21 01:13:21 pgoyette Exp $ +# $NetBSD: main.cf,v 1.8 2020/03/18 19:05:13 christos Exp $ # # Global Postfix configuration file. This file lists only a subset # of all parameters. For the syntax, and for a complete parameter @@ -262,7 +262,7 @@ unknown_local_recipient_reject_code = 550 # # By default (mynetworks_style = subnet), Postfix "trusts" SMTP # clients in the same IP subnetworks as the local machine. -# On Linux, this does works correctly only with interfaces specified +# On Linux, this works correctly only with interfaces specified # with the "ifconfig" command. # # Specify "mynetworks_style = class" when Postfix should "trust" SMTP @@ -636,7 +636,7 @@ debugger_command = # >$config_directory/$process_name.$process_id.log & sleep 5 # # Another possibility is to run gdb under a detached screen session. -# To attach to the screen sesssion, su root and run "screen -r +# To attach to the screen session, su root and run "screen -r # <id_string>" where <id_string> uniquely matches one of the detached # sessions (from "screen -list"). # diff --git a/external/ibm-public/postfix/dist/conf/master.cf b/external/ibm-public/postfix/dist/conf/master.cf index 4026ef0e530..0acbd2186ee 100644 --- a/external/ibm-public/postfix/dist/conf/master.cf +++ b/external/ibm-public/postfix/dist/conf/master.cf @@ -1,4 +1,4 @@ -# $NetBSD: master.cf,v 1.8 2017/02/14 01:16:43 christos Exp $ +# $NetBSD: master.cf,v 1.9 2020/03/18 19:05:13 christos Exp $ # # # Postfix master process configuration file. For details on the format @@ -20,6 +20,7 @@ # -o syslog_name=postfix/submission # -o smtpd_tls_security_level=encrypt # -o smtpd_sasl_auth_enable=yes +# -o smtpd_tls_auth_only=yes # -o smtpd_reject_unlisted_recipient=no # -o smtpd_client_restrictions=$mua_client_restrictions # -o smtpd_helo_restrictions=$mua_helo_restrictions @@ -54,6 +55,7 @@ proxymap unix - - n - - proxymap proxywrite unix - - n - 1 proxymap smtp unix - - n - - smtp relay unix - - n - - smtp + -o syslog_name=postfix/$service_name # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 showq unix n - n - - showq error unix - - n - - error @@ -64,6 +66,7 @@ virtual unix - n n - - virtual lmtp unix - - n - - lmtp anvil unix - - n - 1 anvil scache unix - - n - 1 scache +postlog unix-dgram n - n - 1 postlogd # # ==================================================================== # Interfaces to non-Postfix software. Be sure to examine the manual @@ -78,7 +81,7 @@ scache unix - - n - 1 scache # Also specify in main.cf: maildrop_destination_recipient_limit=1 # #maildrop unix - n n - - pipe -# flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient} +# flags=DRXhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient} # # ==================================================================== # @@ -97,7 +100,7 @@ scache unix - - n - 1 scache # Also specify in main.cf: cyrus_destination_recipient_limit=1 # #cyrus unix - n n - - pipe -# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user} +# flags=DRX user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user} # # ==================================================================== # @@ -128,5 +131,5 @@ scache unix - - n - 1 scache # ${nexthop} ${user} ${extension} # #mailman unix - n n - - pipe -# flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py +# flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py # ${nexthop} ${user} diff --git a/external/ibm-public/postfix/dist/conf/post-install b/external/ibm-public/postfix/dist/conf/post-install index aa6b2d141ba..255ff2868cf 100644 --- a/external/ibm-public/postfix/dist/conf/post-install +++ b/external/ibm-public/postfix/dist/conf/post-install @@ -1,5 +1,5 @@ #!/bin/sh -# $NetBSD: post-install,v 1.2 2017/02/14 01:16:43 christos Exp $ +# $NetBSD: post-install,v 1.3 2020/03/18 19:05:13 christos Exp $ # # To view the formatted manual page of this file, type: @@ -202,6 +202,11 @@ # IBM T.J. Watson Research # P.O. Box 704 # Yorktown Heights, NY 10598, USA +# +# Wietse Venema +# Google, Inc. +# 111 8th Avenue +# New York, NY 10011, USA #-- umask 022 @@ -884,6 +889,16 @@ EOF # permit_mynetworks permit_sasl_authenticated \ # defer_unauth_destination" || exit 1 # } + + # Postfix 3.4 + # Add a postlog service entry. + + grep '^postlog' $config_directory/master.cf >/dev/null || { + echo Editing $config_directory/master.cf, adding missing entry for postlog unix-domain datagram service + cat >>$config_directory/master.cf <<EOF || exit 1 +postlog unix-dgram n - n - 1 postlogd +EOF + } } # A reminder if this is the first time Postfix is being installed. diff --git a/external/ibm-public/postfix/dist/conf/postfix-files b/external/ibm-public/postfix/dist/conf/postfix-files index 3f0480d9804..a51810877f6 100644 --- a/external/ibm-public/postfix/dist/conf/postfix-files +++ b/external/ibm-public/postfix/dist/conf/postfix-files @@ -1,4 +1,4 @@ -# $NetBSD: postfix-files,v 1.6 2017/02/14 01:16:43 christos Exp $ +# $NetBSD: postfix-files,v 1.7 2020/03/18 19:05:13 christos Exp $ # # Commented out entries mean files not installed under NetBSD. # @@ -112,6 +112,7 @@ $daemon_directory/postfix-script:f:root:-:755 $daemon_directory/postfix-tls-script:f:root:-:755 $daemon_directory/postfix-wrapper:f:root:-:755 $daemon_directory/postmulti-script:f:root:-:755 +$daemon_directory/postlogd:f:root:-:755 $daemon_directory/postscreen:f:root:-:755 $daemon_directory/proxymap:f:root:-:755 $daemon_directory/qmgr:f:root:-:755 @@ -224,6 +225,7 @@ $manpage_directory/man8/nqmgr.8:f:root:-:644:o $manpage_directory/man8/oqmgr.8:f:root:-:644: $manpage_directory/man8/pickup.8:f:root:-:644 $manpage_directory/man8/pipe.8:f:root:-:644 +$manpage_directory/man8/postlogd.8:f:root:-:644 $manpage_directory/man8/postscreen.8:f:root:-:644 $manpage_directory/man8/proxymap.8:f:root:-:644 $manpage_directory/man8/qmgr.8:f:root:-:644 @@ -431,6 +433,7 @@ $html_directory/postlock.1.html:f:root:-:644 $html_directory/postlog.1.html:f:root:-:644 $html_directory/postmap.1.html:f:root:-:644 $html_directory/postmulti.1.html:f:root:-:644 +$html_directory/postlogd.8.html:f:root:-:644 $html_directory/postqueue.1.html:f:root:-:644 $html_directory/postscreen.8.html:f:root:-:644 $html_directory/postsuper.1.html:f:root:-:644 diff --git a/external/ibm-public/postfix/dist/conf/postfix-script b/external/ibm-public/postfix/dist/conf/postfix-script index eea2ef594df..ef1591ad9aa 100644 --- a/external/ibm-public/postfix/dist/conf/postfix-script +++ b/external/ibm-public/postfix/dist/conf/postfix-script @@ -1,5 +1,5 @@ #!/bin/sh -# $NetBSD: postfix-script,v 1.2 2017/02/14 01:16:43 christos Exp $ +# $NetBSD: postfix-script,v 1.3 2020/03/18 19:05:13 christos Exp $ # #++ @@ -25,6 +25,11 @@ # IBM T.J. Watson Research # P.O. Box 704 # Yorktown Heights, NY 10598, USA +# +# Wietse Venema +# Google, Inc. +# 111 8th Avenue +# New York, NY 10011, USA #-- # Avoid POSIX death due to SIGHUP when some parent process exits. @@ -119,7 +124,7 @@ stop_msg) echo "Stop postfix" ;; -start) +start|start-fg) $daemon_directory/master -t 2>/dev/null || { $FATAL the Postfix mail system is already running @@ -136,12 +141,34 @@ start) # Foreground this so it can be stopped. All inodes are cached. $daemon_directory/postfix-script check-warn fi - $INFO starting the Postfix mail system - # NOTE: wait in foreground process to get the initialization status. - $daemon_directory/master -w || { - $FATAL "mail system startup failed" - exit 1 - } + $INFO starting the Postfix mail system || exit 1 + case $1 in + start) + # NOTE: wait in foreground process to get the initialization status. + $daemon_directory/master -w || { + $FATAL "mail system startup failed" + exit 1 + } + ;; + start-fg) + # Foreground start-up is incompatible with multi-instance mode. + # Use "exec $daemon_directory/master" only if PID == 1. + # Otherwise, doing so would break process group management, + # and "postfix stop" would kill too many processes. + case $instances in + "") case $$ in + 1) exec $daemon_directory/master -i + $FATAL "cannot start-fg the master daemon" + exit 1;; + *) $daemon_directory/master -s;; + esac + ;; + *) $FATAL "start-fg does not support multi_instance_directories" + exit 1 + ;; + esac + ;; + esac ;; drain) @@ -243,6 +270,18 @@ check-fatal) exit 1 } + maillog_file=`$command_directory/postconf -h maillog_file` || { + $FATAL cannot execute $command_directory/postconf! + exit 1 + } + test -n "$maillog_file" && { + $command_directory/postconf -M postlog/unix-dgram 2>/dev/null \ + | grep . >/dev/null || { + $FATAL "missing 'postlog' service in master.cf - run 'postfix upgrade-configuration'" + exit 1 + } + } + # See if all queue files are in the right place. This is slow. # We must scan all queues for mis-named queue files before the # mail system can run. @@ -368,9 +407,41 @@ tls) "$@" ;; +logrotate) + case $# in + 1) ;; + *) $FATAL "usage postfix $1 (no arguments)"; exit 1;; + esac + for name in maillog_file maillog_file_compressor \ + maillog_file_rotate_suffix + do + value="`$command_directory/postconf -h $name`" + case "$value" in + "") $FATAL "empty '$name' parameter value - logfile rotation failed" + exit 1;; + esac + eval $name='"$value"'; + done + + case "$maillog_file" in + /dev/*) $FATAL "not rotating '$maillog_file'"; exit 1;; + esac + + errors=`( + suffix="\`date +$maillog_file_rotate_suffix\`" || exit 1 + mv "$maillog_file" "$maillog_file.$suffix" || exit 1 + $daemon_directory/master -t 2>/dev/null || + kill -HUP \`sed 1q pid/master.pid\` || exit 1 + sleep 1 + "$maillog_file_compressor" "$maillog_file.$suffix" || exit 1 + ) 2>&1` || { + $FATAL "logfile '$maillog_file' rotation failed: $errors" + exit 1 + } + ;; + *) - $ERROR "unknown command: '$1'" - $FATAL "usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration)" + $FATAL "unknown command: '$1'. Usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration, logrotate)" exit 1 ;; diff --git a/external/ibm-public/postfix/dist/conf/postfix-tls-script b/external/ibm-public/postfix/dist/conf/postfix-tls-script index 496872cc721..4a47b952b9f 100644 --- a/external/ibm-public/postfix/dist/conf/postfix-tls-script +++ b/external/ibm-public/postfix/dist/conf/postfix-tls-script @@ -1,5 +1,5 @@ #!/bin/sh -# $NetBSD: postfix-tls-script,v 1.2 2017/02/14 01:16:43 christos Exp $ +# $NetBSD: postfix-tls-script,v 1.3 2020/03/18 19:05:13 christos Exp $ # #++ @@ -1101,7 +1101,7 @@ output-server-tlsa) done set_fqdn "${hostname}" - # Here positional arguments are keyfiles for which we ouput "3 1 1" + # Here positional arguments are keyfiles for which we output "3 1 1" # TLSA RRs, as many keyfiles as the user wants. By default the live # RSA and/or ECDSA keys. shift `expr $OPTIND - 1` diff --git a/external/ibm-public/postfix/dist/html/ADDRESS_VERIFICATION_README.html b/external/ibm-public/postfix/dist/html/ADDRESS_VERIFICATION_README.html index c1b431cf5aa..e5cb09b41f8 100644 --- a/external/ibm-public/postfix/dist/html/ADDRESS_VERIFICATION_README.html +++ b/external/ibm-public/postfix/dist/html/ADDRESS_VERIFICATION_README.html @@ -298,6 +298,12 @@ the same address repeatedly. </p> ... # Postfix 2.6 and later privacy feature. # <a href="postconf.5.html#unverified_recipient_reject_reason">unverified_recipient_reject_reason</a> = Address lookup failed + + # Postfix 3.2 and earlier workaround. + # Do not set <a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a>=no. This prevents Postfix + # from saving the recipient address verification result under + # the original address, when the address verification probe + # message goes through address aliasing or canonical mapping. </pre> </blockquote> @@ -348,6 +354,12 @@ in forged email. </p> # Note 1: Be sure to read the "<a href="#caching">Caching</a>" section below! # Note 2: Avoid hash files here. Use btree or lmdb instead. <a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/verify + + # Postfix 3.2 and earlier workaround. + # Do not set <a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a>=no. This prevents Postfix + # from saving the sender address verification result under the + # original address, when the address verification probe message + # goes through address aliasing or canonical mapping. /etc/postfix/sender_access: # Don't do this when you handle lots of email. diff --git a/external/ibm-public/postfix/dist/html/INSTALL.html b/external/ibm-public/postfix/dist/html/INSTALL.html index c8491ac8531..8d90fb56cbd 100644 --- a/external/ibm-public/postfix/dist/html/INSTALL.html +++ b/external/ibm-public/postfix/dist/html/INSTALL.html @@ -566,7 +566,7 @@ configuration file postfix-files will automatically include files under the directory postfix-files.d. Thanks to this, you can install or deinstall a database plugin package without having to edit postfix-files or dynamicmaps.cf. Instead, you give that plugin its -own configuration files dynamicmaps.cf.d and postfix-files.d, and +own configuration files under dynamicmaps.cf.d and postfix-files.d, and you add or remove those configuration files along with the database plugin dynamically-linked object. </p> @@ -686,7 +686,7 @@ listed below. See the <a href="postconf.5.html">postconf(5)</a> manpage for a de <tr> <td><a href="postconf.5.html#newaliases_path">newaliases_path</a></td> <td>/usr/bin/newaliases</td> </tr> -<tr> <td>openssl_path</td> <td>openssl</td> </tr> +<tr> <td><a href="postconf.5.html#openssl_path">openssl_path</a></td> <td>openssl</td> </tr> <tr> <td><a href="postconf.5.html#queue_directory">queue_directory</a></td> <td>/var/spool/postfix</td> </tr> @@ -837,7 +837,9 @@ unreachable code. </td> </tr> <tr> <td> </td> <td> -DNO_IPV6 </td> <td> Do not build with IPv6 support. By default, IPv6 support is compiled in on platforms that are known to have IPv6 support. Note: this directive is for debugging -and testing only. It is not guaranteed to work on all platforms. +And testing only. It is not guaranteed to work on all platforms. +If you don't want IPv6 support, set "<a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4" in +<a href="postconf.5.html">main.cf</a>. </td> </tr> <tr> <td> </td> <td> -DNO_KQUEUE </td> <td> Do not build with FreeBSD @@ -866,6 +868,10 @@ these where they are known to be available. </td> </tr> By default, Postfix uses <tt>sigsetjmp()/siglongjmp()</tt> when they are known to be available. </td> </tr> +<tr> <td> </td> <td> -DNO_SNPRINTF </td> <td> Use <tt>sprintf()</tt> +instead of <tt>snprintf()</tt>. By default, Postfix uses +<tt>snprintf()</tt> except on ancient systems. </td> </tr> + <tr> <td colspan="2"> DEBUG=debug_level </td> <td> Specifies a non-default compiler debugging level. The default is "<tt>-g</tt>". Specify DEBUG= to turn off debugging. </td> </tr> @@ -874,6 +880,11 @@ Specify DEBUG= to turn off debugging. </td> </tr> a non-default optimization level. The default is "<tt>-O</tt>". Specify OPT= to turn off optimization. </td> </tr> +<tr> <td colspan="2"> POSTFIX_INSTALL_OPTS=-option... </td> <td> +Specifies options for the <tt>postfix-install</tt> command, separated +by whitespace. Currently, the only supported option is +"<tt>-keep-build-mtime</tt>". </td> </tr> + <tr> <td colspan="2"> SHLIB_CFLAGS=flags </td> <td> Specifies non-default compiler options for building Postfix dynamically-linked libraries and database plugins. The typical default is "-fPIC". diff --git a/external/ibm-public/postfix/dist/html/TLS_README.html b/external/ibm-public/postfix/dist/html/TLS_README.html index addb511c39c..7fdd502010a 100644 --- a/external/ibm-public/postfix/dist/html/TLS_README.html +++ b/external/ibm-public/postfix/dist/html/TLS_README.html @@ -18,15 +18,6 @@ <hr> -<h2> WARNING </h2> - -<p> By turning on TLS support in Postfix, you not only get the -ability to encrypt mail and to authenticate remote SMTP clients or servers. -You also turn on thousands and thousands of lines of OpenSSL library -code. Assuming that OpenSSL is written as carefully as Wietse's -own code, every 1000 lines introduce one additional bug into -Postfix. </p> - <h2> What Postfix TLS support does for you </h2> <p> Transport Layer Security (TLS, formerly called SSL) provides @@ -34,13 +25,12 @@ certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. </p> -<blockquote> <p> <a name="client_tls_obs"></a> <a -name="client_tls_harden"></a> NOTE: This document describes a TLS -user interface that was introduced with Postfix version 2.3. Support -for an older user interface is documented in <a href="TLS_LEGACY_README.html">TLS_LEGACY_README</a>, -which also describes the differences between Postfix and the -third-party patch on which Postfix version 2.2 TLS support was -based. </p> </blockquote> +<p> NOTE: By turning on TLS support in Postfix, you not only get +the ability to encrypt mail and to authenticate remote SMTP clients +or servers. You also turn on hundreds of thousands of lines of +OpenSSL library code. Assuming that OpenSSL is written as carefully +as Wietse's own code, every 1000 lines introduce one additional bug +into Postfix. </p> <p> Topics covered in this document: </p> @@ -135,6 +125,8 @@ align="center" bgcolor="#f0f0ff"> smtp<br> session<br> key cache <li><a href="#server_cert_key">Server-side certificate and private key configuration </a> +<li><a href="#server_pfs">Server-side forward-secrecy configuration </a> + <li><a href="#server_logging"> Server-side TLS activity logging </a> @@ -175,26 +167,32 @@ or similar software, it will only negotiate TLS ciphersuites that require a server certificate. </p> <p> For servers that are <b>not</b> public Internet MX hosts, Postfix -supports configurations with no certificates. This entails the -use of just the anonymous TLS ciphers, which are not supported by -typical SMTP clients. Since such clients will not, as a rule, fall -back to plain text after a TLS handshake failure, a certificate-less -Postfix SMTP server will -be unable to receive email from most TLS enabled clients. To avoid -accidental configurations with no certificates, Postfix enables -certificate-less operation only when the administrator explicitly sets -"<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none". This ensures that new Postfix -SMTP server configurations will not accidentally run with no -certificates. </p> +supports configurations with no certificates. This entails the use of +just the anonymous TLS ciphers, which are not supported by typical SMTP +clients. Since some clients may not fall back to plain text after a TLS +handshake failure, a certificate-less Postfix SMTP server will be unable +to receive email from some TLS-enabled clients. To avoid accidental +configurations with no certificates, Postfix enables certificate-less +operation only when the administrator explicitly sets +"<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none". This ensures that new Postfix SMTP server +configurations will not accidentally enable TLS without certificates. </p> + +<p> Note that server certificates are <b>not</b> optional in TLS 1.3. To +run without certificates you'd have to disable the TLS 1.3 protocol by +including '!TLSv1.3' in "<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a>" and perhaps also +"<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a>". It is simpler instead to just +configure a certificate chain. Certificate-less operation is not +recommended. <p> <p> RSA, DSA and ECDSA (Postfix ≥ 2.6) certificates are supported. Most sites only have RSA certificates. You can configure all three at the same time, in which case the ciphersuite negotiated with the remote SMTP client determines which certificate is used. If your -DNS zone is signed, and you want to publish <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> TLSA records, -these must match any of the configured certificates. Since the -best practice is to publish "3 1 1" certificate associations, create -a separate TLSA record for each public-key certificate digest. </p> +DNS zone is signed, and you want to publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>, +<a href="http://tools.ietf.org/html/rfc7671">RFC 7671</a>, <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) records, these must match all of the configured +certificate chains. Since the best practice is to publish "3 1 1" +certificate associations, create a separate TLSA record to match +each public-key certificate digest. </p> <h4> Creating the server certificate file </h4> @@ -226,11 +224,10 @@ size of the server TLS handshake. </p> </pre> </blockquote> -<li> <p> If you publish <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> TLSA "2 0 1" or "2 1 1" records to -specify root CA certificate digests, you must include the corresponding -root CA certificates in the "server.pem" certificate file. See the -documentation of the <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> <a href="postconf.5.html">main.cf</a> -parameter. </p> +<li> <p> If you publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>, <a href="http://tools.ietf.org/html/rfc7671">RFC 7671</a>, <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) +"2 0 1" or "2 1 1" records to specify root CA certificate digests, +you must include the corresponding root CA certificates in the +"server.pem" certificate file. </p> <blockquote> <pre> @@ -247,11 +244,10 @@ applies to "2 0 2" and "2 1 2" TLSA records or any other digest of a CA certificate, but it is expected that SHA256 will be by far the most common digest for TLSA. </p> -<p> As a best practice, publish either "3 0 1" or "3 1 1" TLSA -associations that specify the SHA256 digest of the server certificate -public key with the alias-expanded hostname of each STARTTLS capable -SMTP server. These continue to work when a certificate is renewed -with the same public/private key pair. </p> +<p> As a best practice, publish "3 1 1" TLSA associations that specify +the SHA256 digest of the server's public key. These continue to work +unmodified when a certificate is renewed with the same public/private +key pair. </p> </ul> @@ -277,6 +273,58 @@ directory. </p> <h4> Configuring the server certificate and key files </h4> +<p> Example: Postfix ≥ 3.4 all-in-one chain file(s). One or more +chain files that start with a key that is immediately followed by the +corresponding certificate and any additional issuer certificates. A +single file can hold multiple <i>(key, cert, [chain])</i> sequences, one +per algorithm. It is typically simpler to keep the chain for each +algorithm in its own file. Most users are likely to deploy just a +single RSA chain, but with OpenSSL 1.1.1, it is possible to deploy up to +five chains, one each for RSA, ECDSA, ED25519, ED448 and even the +obsolete DSA. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. Preferred configuration interface. Each file + # starts with the private key, followed by the corresponding + # certificate, and any intermediate issuer certificates. The root CA + # cert may also be needed when published as a DANE trust anchor. + # + <a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a> = + /etc/postfix/rsa.pem, + /etc/postfix/ecdsa.pem, + /etc/postfix/ed25519.pem, + /etc/postfix/ed448.pem +</pre> +</blockquote> + +<p> You can also store the keys separately from their certificates, again +provided each is listed before the corresponding certificate chain. Storing a +key and its associated certificate chain in separate files is not recommended, +because this is prone to race conditions during key rollover, as there is no +way to update multiple files atomically. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. + # Storing keys separately from the associated certificates is not + # recommended. + <a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a> = + /etc/postfix/rsakey.pem, + /etc/postfix/rsacerts.pem, + /etc/postfix/ecdsakey.pem, + /etc/postfix/ecdsacerts.pem +</pre> +</blockquote> + +<p> The below examples show the legacy algorithm-specific configurations +for Postfix 3.3 and older. With Postfix ≤ 3.3, even if the key is +stored in the same file as the certificate, the file is read twice and a +(brief) race condition still exists during key rollover. While Postfix +≥ 3.4 avoids the race when the key and certificate are in the same +file, you should use the new "<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>" interface shown +above. <p> + <p> RSA key and certificate examples: </p> <blockquote> @@ -302,8 +350,8 @@ directory. </p> <blockquote> <pre> /etc/postfix/<a href="postconf.5.html">main.cf</a>: - # Most clients will not be ECDSA capable, so you will likely also need - # an RSA or DSA certificate and private key. + # Some clients will not be ECDSA capable, so you will likely still need + # an RSA certificate and private key. # <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a> = /etc/postfix/server-ecdsa.pem <a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a> = $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a> @@ -316,6 +364,8 @@ anonymous-cipher capable clients: </p> <blockquote> <pre> /etc/postfix/<a href="postconf.5.html">main.cf</a>: + # Not recommended: breaks TLS 1.3 and clients that don't support + # anonymous cipher suites. <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none </pre> </blockquote> @@ -370,6 +420,18 @@ the TLS handshake when client certificates are requested. </p> </pre> </blockquote> +<h3><a name="server_pfs"> Server-side forward-secrecy configuration </a> </h3> + +<p> If you want to take maximal advantage of ciphers that offer <a +href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see +the <a href="FORWARD_SECRECY_README.html#quick-start">Getting +started</a> section of <a +href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The +full document conveniently presents all information about Postfix +forward secrecy support in one place: what forward secrecy is, how +to tweak settings, and what you can expect to see when Postfix uses +ciphers with forward secrecy. </p> + <h3><a name="server_logging"> Server-side TLS activity logging </a> </h3> <p> To get additional information about Postfix SMTP server TLS @@ -850,7 +912,11 @@ without corresponding changes to the Postfix source code. </p> supports configurations with no <a href="#server_cert_key">server certificates</a> that use <b>only</b> the anonymous ciphers. This is enabled by explicitly setting "<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none" -and not specifying an <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> or <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. </p> +and not specifying an <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> or <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. +Such configurations may not interoperate with some clients, and require +that TLSv1.3 be explicitly disabled. Therefore, they are not +recommended, it is better and simpler to just configure a suitable +certificate. </p> <p> Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3, with high grade ciphers: </p> @@ -870,15 +936,30 @@ with high grade ciphers: </p> </pre> </blockquote> +<p> With Postfix ≥ 3.4, specify instead a single file that holds the +key followed by the corresponding certificate and any associated issuing +certificates, leaving the "<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>" and "<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a>" +and related DSA and ECDSA parameters empty. </p> + +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a> = /etc/postfix/rsachain.pem + <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = + <a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> = + ... +</pre> +</blockquote> + <p> If you want to take maximal advantage of ciphers that offer <a href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see the <a href="FORWARD_SECRECY_README.html#quick-start">Getting started</a> section of <a href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The full document conveniently presents all information about Postfix -"perfect" forward secrecy support in one place: what forward secrecy -is, how to tweak settings, and what you can expect to see when -Postfix uses ciphers with forward secrecy. </p> +forward secrecy support in one place: what forward secrecy is, how +to tweak settings, and what you can expect to see when Postfix uses +ciphers with forward secrecy. </p> <p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS servers to preempt the TLS client's cipher-suite preference list. @@ -919,12 +1000,13 @@ handshake procedures. </p> </blockquote> <p> With Postfix 2.8 and later, the <a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> parameter -specifies a list or bit-mask of OpenSSL bug work-arounds to disable. This -may be necessary if one of the work-arounds enabled by default in -OpenSSL proves to pose a security risk, or introduces an unexpected -interoperability issue. Some bug work-arounds known to be problematic -are disabled in the default value of the parameter when linked with -an OpenSSL library that could be vulnerable. </p> +specifies a list or bit-mask of default-enabled OpenSSL bug +work-arounds to disable. This may be necessary if one of the +work-arounds enabled by default in OpenSSL proves to pose a security +risk, or introduces an unexpected interoperability issue. The list +of enabled bug work-arounds is OpenSSL-release-specific. See the +<a href="postconf.5.html#tls_disable_workarounds">tls_disable_workarounds</a> parameter documentation for the list of +supported values.</p> <p> Example: </p> @@ -942,19 +1024,8 @@ more of the named options below, or a hexadecimal bitmask of options found in the ssl.h file corresponding to the run-time OpenSSL library. While it may be reasonable to turn off all bug workarounds (see above), it is not a good idea to attempt to turn on all features. -</p> - -<dl> - -<dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3).</dd> - -<dt><b>NO_TICKET</b></dt> <dd>See SSL_CTX_set_options(3).</dd> - -<dt><b>NO_COMPRESSION</b></dt> <dd>Disable SSL compression even if -supported by the OpenSSL library. Compression is CPU-intensive, -and compression before encryption does not always improve security. </dd> - -</dl> +See the <a href="postconf.5.html#tls_ssl_options">tls_ssl_options</a> parameter documentation for the list of +supported values. </p> <p> Example: </p> @@ -988,6 +1059,8 @@ solution. </p> <li><a href="#client_cert_key">Client-side certificate and private key configuration </a> +<li><a href="#client_tls_reuse">Client-side TLS connection reuse</a> + <li><a href="#client_tls_cache">Client-side TLS session cache</a> <li><a href="#client_tls_limits"> Client TLS limitations </a> @@ -1144,7 +1217,7 @@ parameters includes useful interoperability and security guidelines. <p> Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for -mail delivery to the public Internet. Most MX hosts do not support TLS at +mail delivery to the public Internet. Some MX hosts do not support TLS at all, and some of those that do have broken implementations. On a host that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level. </p> @@ -1208,16 +1281,17 @@ just in case the transport table entries are not specified consistently. </p> <h4><a name="client_tls_dane">DANE TLS authentication.</a> </h4> <p> The Postfix SMTP client supports two TLS security levels based -on <a href="http://tools.ietf.org/html/rfc6698">RFC6698</a> DANE TLSA records. The opportunistic "dane" level and -the mandatory "dane-only" level. </p> +on DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>, <a href="http://tools.ietf.org/html/rfc7671">RFC 7671</a>, <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) records. The opportunistic +"dane" level and the mandatory "dane-only" level. </p> <p> The "dane" level is a stronger form of <a href="#client_tls_may">opportunistic</a> TLS that is resistant to man in the middle and downgrade attacks when the destination domain uses DNSSEC to publish DANE TLSA records for its MX hosts. If a -remote SMTP server has "usable" (see <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>) DANE TLSA records, -the server connection will be authenticated. When DANE authentication -fails, there is no fallback to unauthenticated or plaintext delivery. </p> +remote SMTP server has "usable" (see section 3 of <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) DANE +TLSA records, the server connection will be authenticated. When +DANE authentication fails, there is no fallback to unauthenticated +or plaintext delivery. </p> <p> If TLSA records are published for a given remote SMTP server (implying TLS support), but are all "unusable" due to unsupported @@ -1248,9 +1322,9 @@ to be in effect, the destination domain's containing DNS zone must be signed and the Postfix SMTP client's operating system must be configured to send its DNS queries to a recursive DNS nameserver that is able to validate the signed records. Each MX host's DNS -zone needs to also be signed, and needs to publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>) -records that specify how that MX host's TLS certificate is to be -verified. </p> +zone needs to also be signed, and needs to publish DANE TLSA (see +section 3 of <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) records that specify how that MX host's TLS +certificate is to be verified. </p> <p> TLSA records do not preempt the normal SMTP MX host selection algorithm, if some MX hosts support TLSA and others do @@ -1258,35 +1332,17 @@ not, TLS security will vary from delivery to delivery. It is up to the domain owner to configure their MX hosts and their DNS sensibly. To configure the Postfix SMTP client for DNSSEC lookups see the documentation for the <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a> <a href="postconf.5.html">main.cf</a> -parameter. The <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> <a href="postconf.5.html">main.cf</a> parameter -controls support for trust-anchor digest TLSA records. The -<a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a> and tls_dane_digest_agility parameters control -the list of supported digests and digest downgrade attack resistance. -</p> +parameter. The <a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a> parameter controls the list of +supported digests. </p> -<p> DANE for SMTP MTAs deviates in some details from the baseline -DANE protocol in <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>. Most notably, it is not expected that -SMTP MTAs can reasonably include every public CA that a remote SMTP -server's administrator may believe to be well-known. Nor is there -an interactive user to "click OK" when authentication fails. </p> - -<p> Therefore, certificate usages "0" and "1" from <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> which -are intended to "constrain" existing PKI trust, are not supported. -TLSA records with usage "0" are treated as "unusable". TLSA records -with usage "1" are instead treated as "trust assertions" and mapped -to usage "3". Specifically, with certificate usage "1", Postfix -will not require the remote SMTP server's certificate to be trusted -with respect to any locally defined public CAs, it is the domain -owner's responsibility to ensure that the certificate associations -in their TLSA records are appropriate to authenticate their SMTP -servers. </p> +<p> As explained in section 3 of <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>, certificate usages "0" +and "1", which are intended to "constrain" existing Web-PKI trust, +are not supported with MTA-to-MTA SMTP. Rather, TLSA records with +usages "0" and "1" are treated as "unusable". </p> <p> The Postfix SMTP client supports only certificate usages "2" -and "3" (with "1" treated as though it were "3"). See -<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> for usage "2" usability -considerations. Support for certificate usage "1" is an experiment, -it may be withdrawn in the future. Server operators SHOULD NOT -publish TLSA records with usage "1". </p> +and "3". Experimental support for silently mapping certificate +usage "1" to "3" has been withdrawn starting with Postfix 3.2. </p> <p> When usable TLSA records are obtained for the remote SMTP server the Postfix SMTP client sends the SNI TLS extension in its SSL @@ -1298,8 +1354,8 @@ records. </p> security level is treated like a "mandatory" TLS security level, and weak ciphers and protocols are disabled. Since DANE authenticates server certificates the "aNULL" cipher-suites are transparently -excluded at this level, no need to configure this manually. <a href="http://tools.ietf.org/html/rfc6698">RFC</a> -<a href="http://tools.ietf.org/html/rfc6698">6698</a> (DANE) TLS authentication is available with Postfix 2.11 and +excluded at this level, no need to configure this manually. <a href="http://tools.ietf.org/html/rfc7672">RFC</a> +<a href="http://tools.ietf.org/html/rfc7672">7672</a> (DANE) TLS authentication is available with Postfix 2.11 and later. </p> <p> When a DANE TLSA record specifies a trust-anchor (TA) certificate @@ -1561,8 +1617,8 @@ parent certificates will be ignored. </p> <p> Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory certificate trust chain and subject name verification -is not viable as a default Internet mail delivery policy. Most MX hosts -do not support TLS at all, and a significant portion of TLS enabled +is not viable as a default Internet mail delivery policy. Some MX hosts +do not support TLS at all, and a significant portion of TLS-enabled MTAs use self-signed certificates, or certificates that are signed by a private Certification Authority. On a machine that delivers mail to the Internet, you should not configure mandatory server certificate @@ -1635,8 +1691,8 @@ parent certificates will be ignored. </p> <p> Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory secure server certificate verification is not -viable as a default Internet mail delivery policy. Most MX hosts -do not support TLS at all, and a significant portion of TLS enabled +viable as a default Internet mail delivery policy. Some MX hosts +do not support TLS at all, and a significant portion of TLS-enabled MTAs use self-signed certificates, or certificates that are signed by a private Certification Authority. On a machine that delivers mail to the Internet, you should not configure secure TLS verification @@ -1797,24 +1853,24 @@ well without them. The recommended setting is to let the defaults stand: </p> # Postfix ≥ 2.6 <a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a> = <a href="postconf.5.html#smtp_tls_eckey_file">smtp_tls_eckey_file</a> = + # Postfix ≥ 3.4 + <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> = </pre> </blockquote> <p> The best way to use the default settings is to comment out the above parameters in <a href="postconf.5.html">main.cf</a> if present. </p> -<p> During TLS startup negotiation the Postfix SMTP client may present -a certificate to the remote SMTP server. The Netscape client is -rather clever here and lets the user select between only those -certificates that match CA certificates offered by the remote SMTP -server. As the Postfix SMTP client uses the "SSL_connect()" function -from the OpenSSL package, this is not possible and we have to choose -just one certificate. So for now the default is to use _no_ -certificate and key unless one is explicitly specified here. </p> +<p> During TLS startup negotiation the Postfix SMTP client may present a +certificate to the remote SMTP server. Browsers typically let the user +select among the certificates that match the CA names indicated by the +remote SMTP server. The Postfix SMTP client does not yet have a mechanism +to select from multiple candidate certificates on the fly, and supports a +single set of certificates (at most one per public key algorithm). </p> <p> RSA, DSA and ECDSA (Postfix ≥ 2.6) certificates are supported. You can configure all three at the same time, in which case the -cipher used determines which certificate is presented. </p> +cipher used determines which certificate is presented. </p> <p> It is possible for the Postfix SMTP client to use the same key/certificate pair as the Postfix SMTP server. If a certificate @@ -1823,6 +1879,14 @@ must not be encrypted, meaning: it must be accessible without password. Both parts (certificate and private key) may be in the same file. </p> +<p> With OpenSSL 1.1.1 and Postfix ≥ 3.4 it is also possible to +configure Ed25519 and Ed448 certificates. Rather than add two more +pairs of key and certificate parameters, Postfix 3.4 introduces a new +"<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>" parameter which specifies all the configured +certificates at once, and handles files that hold both the key and the +associated certificates in one pass, thereby avoiding potential race +conditions during key rollover. </p> + <p> To enable remote SMTP servers to verify the Postfix SMTP client certificate, the issuing CA certificates must be made available to the server. You should include the required certificates in the client @@ -1831,11 +1895,12 @@ CA(s) (bottom-up order). </p> <p> Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". -Create the client.pem file with: </p> +As the "root" super-user create the client.pem file with: </p> <blockquote> <pre> -% <b>cat client_cert.pem intermediate_CA.pem > client.pem </b> +# <b>umask 077</b> +# <b>cat client_key.pem client_cert.pem intermediate_CA.pem > chain.pem </b> </pre> </blockquote> @@ -1845,13 +1910,64 @@ sslclient ..." test. </p> <p> A server that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA -certificate here. Leaving it out of the "client.pem" file reduces +certificate here. Leaving it out of the "chain.pem" file reduces the overhead of the TLS exchange. </p> <p> If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> or install it in the $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> directory. </p> +<p> Example: Postfix ≥ 3.4 all-in-one chain file(s). One or more +chain files that start with a key that is immediately followed by the +corresponding certificate and any additional issuer certificates. A +single file can hold multiple <i>(key, cert, [chain])</i> sequences, one +per algorithm. It is typically simpler to keep the chain for each +algorithm in its own file. Most users are likely to deploy at most a +single RSA chain, but with OpenSSL 1.1.1, it is possible to deploy up +five chains, one each for RSA, ECDSA, ED25519, ED448 and even the +obsolete DSA. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. Preferred configuration interface. Each file + # starts with the private key, followed by the corresponding + # certificate, and any intermediate issuer certificates. + # + <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> = + /etc/postfix/rsa.pem, + /etc/postfix/ecdsa.pem, + /etc/postfix/ed25519.pem, + /etc/postfix/ed448.pem +</pre> +</blockquote> + +<p> You can also store the keys separately from their certificates, again +provided each is listed before the corresponding certificate chain. Storing a +key and its associated certificate chain in separate files is not recommended, +because this is prone to race conditions during key rollover, as there is no +way to update multiple files atomically. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. + # Storing keys separately from the associated certificates is not + # recommended. + <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> = + /etc/postfix/rsakey.pem, + /etc/postfix/rsacerts.pem, + /etc/postfix/ecdsakey.pem, + /etc/postfix/ecdsacerts.pem +</pre> +</blockquote> + +<p> The below examples show the legacy algorithm-specific configurations +for Postfix 3.3 and older. With Postfix ≤ 3.3, even if the key is +stored in the same file as the certificate, the file is read twice and a +(brief) race condition still exists during key rollover. While Postfix +≥ 3.4 avoids the race when the key and certificate are in the same +file, you should use the new "<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>" interface shown +above. <p> + <p> RSA key and certificate examples: </p> <blockquote> @@ -1921,6 +2037,49 @@ when the certificate is needed. </p> </pre> </blockquote> +<h3><a name="client_tls_reuse">Client-side TLS connection reuse</a> </h3> + +<p> Historically, the Postfix SMTP client has supported multiple +deliveries per plaintext connection. Postfix 3.4 introduces support +for multiple deliveries per TLS-encrypted connection. Multiple +deliveries per connection improve mail delivery performance, +especially for destinations that throttle clients that don't combine +deliveries. </p> + +<p> To enable multiple deliveries per TLS connection, specify:</p> + +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> = yes +</pre> +</blockquote> + +<p> Alternatively, specify the attribute "connection_reuse=yes" in +an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> entry. </p> + +<p> The implementation of TLS connection reuse relies on the same +<a href="scache.8.html">scache(8)</a> service as used for delivering plaintext SMTP mail, the +same <a href="tlsproxy.8.html">tlsproxy(8)</a> daemon as used by the <a href="postscreen.8.html">postscreen(8)</a> service, and +relies on the same hints from the <a href="qmgr.8.html">qmgr(8)</a> daemon. + +See "<a href="CONNECTION_CACHE_README.html">Postfix Connection +Cache</a>" for a description of the underlying connection reuse +infrastructure. </p> + +<p> Initial SMTP handshake:</p> +<pre> <a href="smtp.8.html">smtp(8)</a> -> remote SMTP server</pre> + +<p> Reused SMTP/TLS connection, or new SMTP/TLS connection: </p> +<pre> <a href="smtp.8.html">smtp(8)</a> -> <a href="tlsproxy.8.html">tlsproxy(8)</a> -> remote SMTP server </pre> + +<p> Cached SMTP/TLS connection:</p> +<pre> <a href="scache.8.html">scache(8)</a> -> <a href="tlsproxy.8.html">tlsproxy(8)</a> -> remote SMTP server</pre> + +<p> As of Postfix 3.4, TLS connection reuse is disabled by default. +This may change once the impact on over-all performance is understood. +</p> + <h3><a name="client_tls_cache">Client-side TLS session cache</a> </h3> <p> The remote SMTP server and the Postfix SMTP client negotiate a @@ -2122,7 +2281,10 @@ additional attributes are supported at this level. </dd> The optional "ciphers", "exclude" and "protocols" attributes (available for opportunistic TLS with Postfix ≥ 2.6) override the "<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>", "<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>" and "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>" -configuration parameters. </dd> +configuration parameters. At this level and higher, the optional +"servername" attribute (available with Postfix ≥ 3.4) overrides the +global "<a href="postconf.5.html#smtp_tls_servername">smtp_tls_servername</a>" parameter, enabling per-destination +configuration of the SNI extension sent to the remote SMTP server. </dd> <dt><b>encrypt</b></dt> <dd><a href="#client_tls_encrypt"> Mandatory encryption</a>. Mail is delivered only if the remote SMTP server offers STARTTLS @@ -2141,7 +2303,7 @@ found, but none are usable, the effective security level is <a href="#client_tls_encrypt">encrypt</a>. When usable TLSA records are obtained for the remote SMTP server, SSLv2+3 are automatically disabled (see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate -must match the TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication +must match the TLSA records. <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 and later. </dd> <dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>. @@ -2150,7 +2312,7 @@ 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 <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate must -match the TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication and +match the TLSA records. <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 and later. </dd> <dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate @@ -2808,6 +2970,9 @@ DANE TLSA records. See the <a href="postfix-tls.1.html">postfix-tls(1)</a> docu <p> The following commands (credits: Viktor Dukhovni) generate and install a 2048-bit RSA private key and 10-year self-signed certificate for the local Postfix system. This requires super-user privileges. +(By using date-specific filenames for the certificate and key files, +and updating <a href="postconf.5.html">main.cf</a> with new filenames, a potential race condition +in which the key and certificate might not match is avoided). </p> <blockquote> diff --git a/external/ibm-public/postfix/dist/html/postconf.5.html b/external/ibm-public/postfix/dist/html/postconf.5.html index bcad1f48c35..91c359077bc 100644 --- a/external/ibm-public/postfix/dist/html/postconf.5.html +++ b/external/ibm-public/postfix/dist/html/postconf.5.html @@ -43,25 +43,30 @@ that starts with whitespace continues a logical line. </p> <ul> <li> <p> The expressions "$name" and "${name}" are recursively -replaced with the value of the named parameter, except where noted. +replaced with the value of the named parameter. The parameter name +must contain only characters from the set [a-zA-Z0-9_]. An undefined parameter value is replaced with the empty value. </p> <li> <p> The expressions "${name?value}" and "${name?{value}}" are -replaced with "value" when "$name" is non-empty. These forms are +replaced with "value" when "$name" is non-empty. The parameter name +must contain only characters from the set [a-zA-Z0-9_]. These forms are supported with Postfix versions ≥ 2.2 and ≥ 3.0, respectively. </p> -<li> <p> The expressions "${name:value}" and "${name?{value}}" are -replaced with "value" when "$name" is empty. These forms are supported -with Postfix versions ≥ 2.2 and ≥ 3.0, respectively. </p> +<li> <p> The expressions "${name:value}" and "${name:{value}}" are +replaced with "value" when "$name" is empty. The parameter name must +contain only characters from the set [a-zA-Z0-9_]. These forms are +supported with Postfix versions ≥ 2.2 and ≥ 3.0, respectively. +</p> <li> <p> The expression "${name?{value1}:{value2}}" is replaced with "value1" when "$name" is non-empty, and with "value2" when "$name" is empty. The "{}" is required for "value1", optional for -"value2". This form is supported with Postfix versions ≥ 3.0. -</p> +"value2". The parameter name must contain only characters from the +set [a-zA-Z0-9_]. This form is supported with Postfix versions +≥ 3.0. </p> -<li> <p> The first item inside "${...}" may be a logical expression +<li> <p> The first item inside "${...}" may be a relational expression of the form: "{value3} == {value4}". Besides the "==" (equality) operator Postfix supports "!=" (inequality), "<", "≤", "≥", and ">". The comparison is numerical when both operands are all @@ -69,7 +74,7 @@ digits, otherwise the comparison is lexicographical. These forms are supported with Postfix versions ≥ 3.0. </p> <li> <p> Each "value" is subject to recursive named parameter and -logical expression evaluation, except where noted. </p> +relational expression evaluation, except where noted. </p> <li> <p> Whitespace before or after each "{value}" is ignored. </p> @@ -778,16 +783,22 @@ cannot match Postfix access tables, because the address is ambiguous. <p> A list of non-default Postfix configuration directories that may -be specified with "-c <a href="postconf.5.html#config_directory">config_directory</a>" on the command line, or -via the MAIL_CONFIG environment parameter. +be specified with "-c <a href="postconf.5.html#config_directory">config_directory</a>" on the command line (in the +case of <a href="sendmail.1.html">sendmail(1)</a>, with the "-C" option), or via the MAIL_CONFIG +environment parameter. </p> <p> -This list must be specified in the default Postfix configuration -directory, and is used by set-gid Postfix commands such as <a href="postqueue.1.html">postqueue(1)</a> +This list must be specified in the default Postfix <a href="postconf.5.html">main.cf</a> file, +and will be used by set-gid Postfix commands such as <a href="postqueue.1.html">postqueue(1)</a> and <a href="postdrop.1.html">postdrop(1)</a>. </p> +<p> +Specify absolute pathnames, separated by comma or space. Note: $name +expansion is not supported. +</p> + </DD> @@ -1466,8 +1477,10 @@ The location of all postfix administrative commands. external command. Failure to change directory causes the delivery to be deferred. </p> -<p> The following $name expansions are done on <a href="postconf.5.html#command_execution_directory">command_execution_directory</a> -before the directory is changed. Expansion happens in the context +<p> The <a href="postconf.5.html#command_execution_directory">command_execution_directory</a> value is not subject to Postfix +configuration parameter $name expansion. Instead, the following +$name expansions are done on <a href="postconf.5.html#command_execution_directory">command_execution_directory</a> before the +directory is used. Expansion happens in the context of the delivery request. The result of $name expansion is filtered with the character set that is specified with the <a href="postconf.5.html#execution_directory_expansion_filter">execution_directory_expansion_filter</a> parameter. </p> @@ -1939,7 +1952,7 @@ is no maximum, it doesn't make much sense to use values above say <p> The only reason why the value of 2 is not the default is the way this parameter affects the delivery of mailing-list mail. In the -worst case, their delivery can take somewhere between (cost+1/cost) +worst case, delivery can take somewhere between (cost+1/cost) and (cost/cost-1) times more than if the preemptive scheduler was disabled. The default value of 5 turns out to provide reasonable message response times while making sure the mailing-list deliveries @@ -2023,6 +2036,12 @@ text of successful or unsuccessful deliveries. This does not allow the replacement of a successful status code (2.X.X) with an unsuccessful status code (4.X.X or 5.X.X) or vice versa. </p> +<p> Note: the (smtp|lmtp)_delivery_status_filter is applied only +once per recipient: when delivery is successful, when delivery is +rejected with 5XX, or when there are no more alternate MX or A +destinations. Use <a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> or <a href="postconf.5.html#lmtp_reply_filter">lmtp_reply_filter</a> to inspect +responses for all delivery attempts. </p> + <p> The following parameters can be used to implement a filter for specific delivery agents: <a href="postconf.5.html#lmtp_delivery_status_filter">lmtp_delivery_status_filter</a>, <a href="postconf.5.html#local_delivery_status_filter">local_delivery_status_filter</a>, <a href="postconf.5.html#pipe_delivery_status_filter">pipe_delivery_status_filter</a>, @@ -2257,8 +2276,14 @@ is the <a href="master.5.html">master.cf</a> name of the message delivery transp (default: 0s)</b></DT><DD> <p> The default amount of delay that is inserted between individual -deliveries to the same destination; the resulting behavior depends -on the value of the corresponding per-destination recipient limit. +message deliveries to the same destination and over the same message +delivery transport. Specify a non-zero value to rate-limit those +message deliveries to at most one per $<a href="postconf.5.html#default_destination_rate_delay">default_destination_rate_delay</a>. +</p> + +<p> The resulting behavior depends on the value of the corresponding +per-destination recipient limit. + </p> <ul> @@ -2437,7 +2462,9 @@ This feature is available in Postfix 2.0 and later. </p> <p> -The template is subject to exactly one level of $name substitution: +The template does not support Postfix configuration parameter $name +substitution. Instead, it supports exactly one level of $name +substitution for the following attributes: </p> <dl> @@ -2632,7 +2659,9 @@ domain. Specify a string of the form <i>transport:nexthop</i>, where <i>transport</i> is the name of a mail delivery transport defined in <a href="master.5.html">master.cf</a>. The <i>:nexthop</i> destination is optional; its syntax is documented -in the manual page of the corresponding delivery agent. +in the manual page of the corresponding delivery agent. In the case of +SMTP or LMTP, specify one or more destinations separated by comma or +whitespace (with Postfix 3.5 and later). </p> <p> @@ -2650,9 +2679,10 @@ Example: (default: 0s)</b></DT><DD> <p> The default amount of delay that is inserted between individual -deliveries over the same message delivery transport, regardless of -destination. If non-zero, all deliveries over the same message -delivery transport will happen one at a time. </p> +message deliveries over the same message delivery transport, +regardless of destination. Specify a non-zero value to rate-limit +those message deliveries to at most one per $<a href="postconf.5.html#default_transport_rate_delay">default_transport_rate_delay</a>. +</p> <p>Use <a href="postconf.5.html#transport_transport_rate_delay"><i>transport</i>_transport_rate_delay</a> to specify a transport-specific override, where the initial <i>transport</i> is @@ -3081,6 +3111,22 @@ with older Postfix versions). </p> </DD> +<DT><b><a name="enable_idna2003_compatibility">enable_idna2003_compatibility</a> +(default: no)</b></DT><DD> + +<p> Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF-8 domain names to/from the ASCII form that is +used for DNS lookups. Specify "yes" for compatibility with Postfix +≤ 3.1 (not recommended). This affects the conversion of domain +names that contain for example the German sz and the Greek zeta. +See <a href="http://unicode.org/cldr/utility/idna.jsp">http://unicode.org/cldr/utility/idna.jsp</a> for more examples. +</p> + +<p> This feature is available in Postfix 3.2 and later. </p> + + +</DD> + <DT><b><a name="enable_long_queue_ids">enable_long_queue_ids</a> (default: no)</b></DT><DD> @@ -3170,22 +3216,39 @@ name changes. </p> <DT><b><a name="enable_original_recipient">enable_original_recipient</a> (default: yes)</b></DT><DD> -<p> Enable support for the X-Original-To message header. This header -is needed for multi-recipient mailboxes. </p> +<p> Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). </p> -<p> When this parameter is set to yes, the <a href="cleanup.8.html">cleanup(8)</a> daemon performs -duplicate elimination on distinct pairs of (original recipient, -rewritten recipient), and generates non-empty original recipient -queue file records. </p> +<p> The original recipient address is used as follows: </p> -<p> When this parameter is set to no, the <a href="cleanup.8.html">cleanup(8)</a> daemon performs -duplicate elimination on the rewritten recipient address only, and -generates empty original recipient queue file records. </p> +<dl> -<p> This feature is available in Postfix 2.1 and later. With Postfix -version 2.0, support for the X-Original-To message header is always turned -on. Postfix versions before 2.0 have no support for the X-Original-To -message header. </p> +<dt> Final delivery </dt> <dd> With "<a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> = +yes", the original recipient address is stored in the <b>X-Original-To</b> +message header. This header may be used to distinguish between +different recipients that share the same mailbox. </dd> + +<dt> Recipient deduplication </dt> <dd> With "<a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> += yes", the <a href="cleanup.8.html">cleanup(8)</a> daemon performs duplicate recipient elimination +based on the content of (original recipient, maybe-rewritten +recipient) pairs. Otherwise, the <a href="cleanup.8.html">cleanup(8)</a> daemon performs duplicate +recipient elimination based only on the maybe-rewritten recipient +address. </dd> + +</dl> + +<p> Note: with Postfix ≤ 3.2 the "setting <a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> += <b>no</b>" breaks address verification for addresses that are +aliased or otherwise rewritten (Postfix is unable to store the +address verification result under the original probe destination +address; instead, it can store the result only under the rewritten +address). </p> + +<p> This feature is available in Postfix 2.1 and later. Postfix +version 2.0 behaves as if this parameter is always set to <b>yes</b>. +Postfix versions before 2.0 have no support for the original recipient +address. </p> </DD> @@ -3232,10 +3295,11 @@ outside the allowed set are replaced by underscores. </p> (default: no)</b></DT><DD> <p> -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. Normally, Postfix sets the envelope -sender address to the name of the "owner-aliasname" alias. +When delivering to an alias "<i>aliasname</i>" that has an +"owner-<i>aliasname</i>" companion alias, set the envelope sender +address to the expansion of the "owner-<i>aliasname</i>" alias. +Normally, Postfix sets the envelope sender address to the name of +the "owner-<i>aliasname</i>" alias. </p> @@ -3253,7 +3317,8 @@ time keeping on System-V-ish systems. <p> Specify a list of names and/or name=value pairs, separated by whitespace or comma. Specify "{ name=value }" to protect whitespace -or comma in parameter values (whitespace after "{" and before "}" +or comma in parameter values (whitespace after the opening "{" and +before the closing "}" is ignored). The form name=value is supported with Postfix version 2.1 and later; the use of {} is supported with Postfix 3.0 and later. </p> @@ -3499,8 +3564,10 @@ allowed set are replaced by underscores. file with user-specified delivery methods. The first file that is found is used. </p> -<p> The following $name expansions are done on <a href="postconf.5.html#forward_path">forward_path</a> before -the search actually happens. The result of $name expansion is +<p> The <a href="postconf.5.html#forward_path">forward_path</a> value is not subject to Postfix configuration +parameter $name expansion. Instead, the following $name expansions +are done on <a href="postconf.5.html#forward_path">forward_path</a> before the search actually happens. +The result of $name expansion is filtered with the character set that is specified with the <a href="postconf.5.html#forward_expansion_filter">forward_expansion_filter</a> parameter. </p> @@ -3657,6 +3724,52 @@ message headers, as specified in the <a href="header_checks.5.html">header_check </DD> +<DT><b><a name="header_from_format">header_from_format</a> +(default: standard)</b></DT><DD> + +<p> The format of the Postfix-generated <b>From:</b> header. This +setting affects the appearance of 'full name' information when a +local program such as /bin/mail submits a message without From: +header through the Postfix <a href="sendmail.1.html">sendmail(1)</a> command. </p> + +<p> Specify one of the following: </p> + +<dl> + +<dt><b>standard</b> (default)</dt> <dd> Produce a header formatted +as "<b>From:</b> <i>name</i><b> <</b><i>address</i><b>></b>". +This is the default as of Postfix 3.3.</dd> + +<dt><b>obsolete</b></dt> <dd>Produce a header formatted as "<b>From:</b> +<i>address</i> <b>(</b><i>name</i><b>)</b>". This is the behavior +prior to Postfix 3.3. </dd> + +</dl> + +<p> Notes: </p> + +<ul> + +<li> <p> Postfix generates the format "<b>From:</b> <i>address</i>" +when <i>name</i> information is unavailable or the envelope sender +address is empty. This is the same behavior as prior to Postfix +3.3. </p> + +<li> <p> In the <b>standard</b> form, the <i>name</i> will be quoted +if it contains <b>specials</b> as defined in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a>, or the "!%" +address operators. </p> + +<li> <p> The Postfix <a href="sendmail.1.html">sendmail(1)</a> command gets <i>name</i> information +from the <b>-F</b> command-line option, from the <b>NAME</b> +environment variable, or from the UNIX password file. </p> + +</ul> + +<p> This feature is available in Postfix 3.3 and later. </p> + + +</DD> + <DT><b><a name="header_size_limit">header_size_limit</a> (default: 102400)</b></DT><DD> @@ -3755,17 +3868,18 @@ mis-delivery of mail. <DT><b><a name="import_environment">import_environment</a> (default: see "postconf -d" output)</b></DT><DD> -<p> -The list of environment parameters that a Postfix process will -import from a non-Postfix parent process. Examples of relevant -parameters: -</p> +<p> The list of environment parameters that a privileged Postfix +process will import from a non-Postfix parent process, or name=value +environment overrides. Unprivileged utilities will enforce the +name=value overrides, but otherwise will not change their process +environment. Examples of relevant parameters: </p> <dl> <dt><b>TZ</b></dt> -<dd>Needed for sane time keeping on most System-V-ish systems. </dd> +<dd>May be needed for sane time keeping on most System-V-ish systems. +</dd> <dt><b>DISPLAY</b></dt> @@ -3783,7 +3897,8 @@ parameters: <p> Specify a list of names and/or name=value pairs, separated by whitespace or comma. Specify "{ name=value }" to protect whitespace -or comma in parameter values (whitespace after "{" and before "}" +or comma in parameter values (whitespace after the opening "{" and +before the closing "}" is ignored). The form name=value is supported with Postfix version 2.1 and later; the use of {} is supported with Postfix 3.0 and later. </p> @@ -3931,6 +4046,49 @@ Examples: </DD> +<DT><b><a name="info_log_address_format">info_log_address_format</a> +(default: external)</b></DT><DD> + +<p> The email address form that will be used in non-debug logging +(info, warning, etc.). As of Postfix 3.5 when an address localpart +contains spaces or other special characters, the localpart will be +quoted, for example: </p> + +<blockquote> +<pre> + from=<"name with spaces"@example.com> +</pre> +</blockquote> + +<p> Older Postfix versions would log the internal (unquoted) form: </p> + +<blockquote> +<pre> + from=<name with spaces@example.com> +</pre> +</blockquote> + +<p> The external and internal forms are identical for the vast +majority of email addresses that contain no spaces or other special +characters in the localpart. </p> + +<p> The logging in external form is consistent with the address +form that Postfix 3.2 and later prefer for most table lookups. This +is therefore the more useful form for non-debug logging. </p> + +<p> Specify "<b>info_log_address_format = internal</b>" for backwards +compatibility. </p> + +<p> Postfix uses the unquoted form internally, because an attacker +can specify an email address in different forms by playing games +with quotes and backslashes. An attacker should not be able to use +such games to circumvent Postfix access policies. </p> + +<p> This feature is available in Postfix 3.5 and later. </p> + + +</DD> + <DT><b><a name="initial_destination_concurrency">initial_destination_concurrency</a> (default: 5)</b></DT><DD> @@ -4115,6 +4273,17 @@ existing LMTP-based content filters. </p> </DD> +<DT><b><a name="lmtp_balance_inet_protocols">lmtp_balance_inet_protocols</a> +(default: yes)</b></DT><DD> + +<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> +configuration parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.3 and later. </p> + + +</DD> + <DT><b><a name="lmtp_bind_address">lmtp_bind_address</a> (default: empty)</b></DT><DD> @@ -5016,6 +5185,7 @@ parameter. See there for details. </p> <p> The default TCP port that the Postfix LMTP client connects to. +Specify a symbolic name (see services(5)) or a numeric port. </p> @@ -5065,6 +5235,17 @@ configuration parameter. See there for details. </p> </DD> +<DT><b><a name="lmtp_tls_chain_files">lmtp_tls_chain_files</a> +(default: empty)</b></DT><DD> + +<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> configuration +parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="lmtp_tls_ciphers">lmtp_tls_ciphers</a> (default: medium)</b></DT><DD> @@ -5076,6 +5257,17 @@ parameter. See there for details. </p> </DD> +<DT><b><a name="lmtp_tls_connection_reuse">lmtp_tls_connection_reuse</a> +(default: no)</b></DT><DD> + +<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> configuration +parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="lmtp_tls_dcert_file">lmtp_tls_dcert_file</a> (default: empty)</b></DT><DD> @@ -5309,6 +5501,17 @@ parameter. See there for details. </p> </DD> +<DT><b><a name="lmtp_tls_servername">lmtp_tls_servername</a> +(default: empty)</b></DT><DD> + +<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_servername">smtp_tls_servername</a> configuration +parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="lmtp_tls_session_cache_database">lmtp_tls_session_cache_database</a> (default: empty)</b></DT><DD> @@ -5676,7 +5879,9 @@ as undeliverable. </p> <p> -The following $name expansions are done on <a href="postconf.5.html#luser_relay">luser_relay</a>: +The <a href="postconf.5.html#luser_relay">luser_relay</a> value is not subject to Postfix configuration +parameter $name expansion. Instead, the following $name expansions +are done: </p> <dl> @@ -5941,7 +6146,7 @@ it easier to specify shell syntax (see example below). <p> If you can, avoid shell meta characters because they will force Postfix to run an expensive shell process. If you're delivering -via Procmail then running a shell won't make a noticeable difference +via "procmail" then running a shell won't make a noticeable difference in the total cost. </p> @@ -6077,6 +6282,65 @@ substitutions in regular expression maps. </p> </DD> +<DT><b><a name="maillog_file">maillog_file</a> +(default: empty)</b></DT><DD> + +<p> The name of an optional logfile that is written by the Postfix +<a href="postlogd.8.html">postlogd(8)</a> service. An empty value selects logging to syslogd(8). +Specify "/dev/stdout" to select logging to standard output. Stdout +logging requires that Postfix is started with "postfix start-fg". +</p> + +<p> Note 1: The <a href="postconf.5.html#maillog_file">maillog_file</a> parameter value must contain a prefix +that is specified with the <a href="postconf.5.html#maillog_file_prefixes">maillog_file_prefixes</a> parameter. </p> + +<p> Note 2: Some Postfix non-daemon programs may still log information +to syslogd(8), before they have processed their configuration +parameters and command-line options. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="maillog_file_compressor">maillog_file_compressor</a> +(default: gzip)</b></DT><DD> + +<p> The program to run after rotating $<a href="postconf.5.html#maillog_file">maillog_file</a> with "postfix +logrotate". The command is run with the rotated logfile name as its +first argument. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="maillog_file_prefixes">maillog_file_prefixes</a> +(default: /var, /dev/stdout)</b></DT><DD> + +<p> A list of allowed prefixes for a <a href="postconf.5.html#maillog_file">maillog_file</a> value. This is a +safety feature to contain the damage from a single configuration +mistake. Specify one or more prefix strings, separated by comma or +whitespace. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="maillog_file_rotate_suffix">maillog_file_rotate_suffix</a> +(default: %Y%M%d-%H%M%S)</b></DT><DD> + +<p> The format of the suffix to append to $<a href="postconf.5.html#maillog_file">maillog_file</a> while rotating +the file with "postfix logrotate". See strftime(3) for syntax. The +default suffix, YYYYMMDD-HHMMSS, allows logs to be rotated frequently. +</p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="mailq_path">mailq_path</a> (default: see "postconf -d" output)</b></DT><DD> @@ -6222,7 +6486,7 @@ Example: <p> Optional list of user names that are not subjected to address -masquerading, even when their address matches $<a href="postconf.5.html#masquerade_domains">masquerade_domains</a>. +masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquerade_domains</a>. </p> <p> @@ -6539,8 +6803,9 @@ for a list of available macro names and their meanings. </p> <DT><b><a name="milter_default_action">milter_default_action</a> (default: tempfail)</b></DT><DD> -<p> The default action when a Milter (mail filter) application is -unavailable or mis-configured. Specify one of the following: </p> +<p> The default action when a Milter (mail filter) response is +unavailable (for example, bad Postfix configuration or Milter +failure). Specify one of the following: </p> <dl compact> @@ -7345,10 +7610,10 @@ This feature is available in Postfix 3.1 and later. (default: yes)</b></DT><DD> <p> -Give special treatment to owner-listname and listname-request -address localparts: don't split such addresses when the -<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is set to "-". This feature is useful for -mailing lists. +Enable special treatment for owner-<i>listname</i> entries in the +<a href="aliases.5.html">aliases(5)</a> file, and don't split owner-<i>listname</i> and +<i>listname</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> +is set to "-". This feature is useful for mailing lists. </p> @@ -7461,6 +7726,36 @@ is rejected by the <b><a href="postconf.5.html#reject_plaintext_session">reject_ </DD> +<DT><b><a name="postlog_service_name">postlog_service_name</a> +(default: postlog)</b></DT><DD> + +<p> The name of the <a href="postlogd.8.html">postlogd(8)</a> service entry in <a href="master.5.html">master.cf</a>. +This service appends logfile records to the file specified +with the <a href="postconf.5.html#maillog_file">maillog_file</a> parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="postlogd_watchdog_timeout">postlogd_watchdog_timeout</a> +(default: 10s)</b></DT><DD> + +<p> How much time a <a href="postlogd.8.html">postlogd(8)</a> process may take to process a request +before it is terminated by a built-in watchdog timer. This is a +safety mechanism that prevents <a href="postlogd.8.html">postlogd(8)</a> from becoming non-responsive +due to a bug in Postfix itself or in system software. This limit +cannot be set under 10s. </p> + +<p> Specify a non-zero time value (an integral value plus an optional +one-letter suffix that specifies the time unit). Time units: s +(seconds), m (minutes), h (hours), d (days), w (weeks). </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="postmulti_control_commands">postmulti_control_commands</a> (default: reload flush)</b></DT><DD> @@ -7547,7 +7842,7 @@ to the configured before/after 220 greeting tests. </dd> <pre> /etc/postfix/<a href="postconf.5.html">main.cf</a>: <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, - <a href="cidr_table.5.html">cidr</a>:/etc/postfix/postscreen_access.cidr + <a href="cidr_table.5.html">cidr</a>:/etc/postfix/postscreen_access.cidr <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> = enforce </pre> @@ -8347,6 +8642,18 @@ response. See <a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer< </DD> +<DT><b><a name="postscreen_reject_footer_maps">postscreen_reject_footer_maps</a> +(default: $<a href="postconf.5.html#smtpd_reject_footer_maps">smtpd_reject_footer_maps</a>)</b></DT><DD> + +<p> Optional lookup table for information that is appended after a 4XX +or 5XX <a href="postscreen.8.html">postscreen(8)</a> server response. See <a href="postconf.5.html#smtpd_reject_footer_maps">smtpd_reject_footer_maps</a> for +further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="postscreen_tls_security_level">postscreen_tls_security_level</a> (default: $<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b></DT><DD> @@ -8367,7 +8674,7 @@ for details. </p> proxy agent. When a proxy agent is used, this protocol conveys local and remote address and port information. Specify "<a href="postconf.5.html#postscreen_upstream_proxy_protocol">postscreen_upstream_proxy_protocol</a> = haproxy" to enable the haproxy -protocol. <p> +protocol; version 2 is supported with Postfix 3.5 and later. <p> <p> This feature is available in Postfix 2.10 and later. </p> @@ -9431,7 +9738,7 @@ This feature is available in Postfix 2.0 and later. (default: empty)</b></DT><DD> <p> -The next-hop destination of non-local mail; overrides non-local +The next-hop destination(s) for non-local mail; overrides non-local domains in recipient addresses. This information is overruled with <a href="postconf.5.html#relay_transport">relay_transport</a>, <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>, <a href="postconf.5.html#default_transport">default_transport</a>, <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> @@ -9445,9 +9752,11 @@ gateway host instead. </p> <p> -In the case of SMTP, specify a domain name, hostname, hostname:port, -[hostname]:port, [hostaddress] or [hostaddress]:port. The form -[hostname] turns off MX lookups. +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. </p> <p> @@ -9462,7 +9771,7 @@ Examples: <pre> <a href="postconf.5.html#relayhost">relayhost</a> = $<a href="postconf.5.html#mydomain">mydomain</a> <a href="postconf.5.html#relayhost">relayhost</a> = [gateway.example.com] -<a href="postconf.5.html#relayhost">relayhost</a> = uucphost +<a href="postconf.5.html#relayhost">relayhost</a> = mail1.example:587, mail2.example:587 <a href="postconf.5.html#relayhost">relayhost</a> = [an.ip.add.ress] </pre> @@ -9560,7 +9869,8 @@ Postfix releases, the behavior is as if this parameter is set to "yes". </p> <p> As documented in <a href="aliases.5.html">aliases(5)</a>, when an alias <i>name</i> has a -companion alias named owner-<i>name</i>, delivery errors will be +companion alias named owner-<i>name</i>, this will replace the +envelope sender address, so that delivery errors will be reported to the owner alias instead of the sender. This configuration is recommended for mailing lists. <p> @@ -9590,7 +9900,9 @@ to other mailing list members. </p> <p> Unfortunately, older Postfix releases reset the owner-alias attribute when delivering mail to a child alias that does not have -its own owner alias. The <a href="local.8.html">local(8)</a> delivery agent then attempts to +its own owner alias. To be precise, this resets only the decision +to create a new queue file, not the decision to override the envelope +sender address. The <a href="local.8.html">local(8)</a> delivery agent then attempts to deliver local addresses as soon as they come out of child alias expansion. If delivery to any address from child alias expansion fails with a temporary error condition, the entire mailing list may @@ -9922,6 +10234,34 @@ submit mail into the Postfix queue. </DD> +<DT><b><a name="service_name">service_name</a> +(read-only)</b></DT><DD> + +<p> The <a href="master.5.html">master.cf</a> service name of a Postfix daemon process. This +can be used to distinguish the logging from different services that +use the same program name. </p> + +<p> Example <a href="master.5.html">master.cf</a> entries: </p> + +<pre> +# Distinguish inbound MTA logging from submission and smtps logging. +smtp inet n - n - - smtpd +submission inet n - n - - smtpd + -o <a href="postconf.5.html#syslog_name">syslog_name</a>=postfix/$<a href="postconf.5.html#service_name">service_name</a> +smtps inet n - n - - smtpd + -o <a href="postconf.5.html#syslog_name">syslog_name</a>=postfix/$<a href="postconf.5.html#service_name">service_name</a> +</pre> + +<pre> +# Distinguish outbound MTA logging from inbound relay logging. +smtp unix - - n - - smtp +relay unix - - n - - smtp + -o <a href="postconf.5.html#syslog_name">syslog_name</a>=postfix/$<a href="postconf.5.html#service_name">service_name</a> +</pre> + + +</DD> + <DT><b><a name="service_throttle_time">service_throttle_time</a> (default: 60s)</b></DT><DD> @@ -9993,8 +10333,8 @@ files in the compiled-in default $<a href="postconf.5.html#shlib_directory">shli <p> Display the name of the recipient table in the "User unknown" -responses. The extra detail makes trouble shooting easier but also -reveals information that is nobody elses business. +responses. The extra detail makes troubleshooting easier but also +reveals information that is nobody else's business. </p> <p> @@ -10111,6 +10451,23 @@ the word "ESMTP" appears in the server greeting banner (example: </DD> +<DT><b><a name="smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> +(default: yes)</b></DT><DD> + +<p> 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 <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>. </p> + +<p> This avoids an interoperability problem when a destination resolves +to primarily IPv6 addresses, the smtp_address_limit feature eliminates +most or all IPv4 addresses, and the destination is not reachable over +IPv6. </p> + +<p> This feature is available in Postfix 3.3 and later. </p> + + +</DD> + <DT><b><a name="smtp_bind_address">smtp_bind_address</a> (default: empty)</b></DT><DD> @@ -10708,7 +11065,7 @@ itself is not configured to use DNSSEC. </p> <p> When using Postfix DANE support the "<a href="postconf.5.html#smtp_host_lookup">smtp_host_lookup</a>" parameter should include "dns", as <a -href="https://tools.ietf.org/html/rfc6698">DANE</a> is not applicable +href="https://tools.ietf.org/html/rfc7672">DANE</a> is not applicable to hosts resolved via "native" lookups. </p> <p> As mentioned above, Postfix is not a validating <a @@ -11653,6 +12010,17 @@ during TLS startup and shutdown handshake procedures. </p> </DD> +<DT><b><a name="smtp_tcp_port">smtp_tcp_port</a> +(default: smtp)</b></DT><DD> + +<p> +The default TCP port that the Postfix SMTP client connects to. +Specify a symbolic name (see services(5)) or a numeric port. +</p> + + +</DD> + <DT><b><a name="smtp_tls_CAfile">smtp_tls_CAfile</a> (default: empty)</b></DT><DD> @@ -11664,7 +12032,7 @@ chroot jail. If the number of trusted roots is large, consider using present in the chroot jail if the <a href="smtp.8.html">smtp(8)</a> client is chrooted. This file may also be used to augment the client certificate trust chain, but it is best to include all the required certificates directly in -$<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>. </p> +$<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> (or, Postfix ≥ 3.4 $<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>). </p> <p> Specify "<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> = /path/to/system_CA_file" to use ONLY the system-supplied default Certification Authority certificates. @@ -11735,9 +12103,10 @@ the Postfix SMTP client TLS session. </p> (default: empty)</b></DT><DD> <p> File with the Postfix SMTP client RSA certificate in PEM format. -This file may also contain the Postfix SMTP client private RSA key, -and these may be the same as the Postfix SMTP server RSA certificate and key -file. </p> +This file may also contain the Postfix SMTP client private RSA key, and +these may be the same as the Postfix SMTP server RSA certificate and key +file. With Postfix ≥ 3.4 the preferred way to configure client keys +and certificates is via the "<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>" parameter. </p> <p> Do not configure client certificates unless you <b>must</b> present client TLS certificates to one or more servers. Client certificates are @@ -11748,10 +12117,13 @@ well without them. The recommended setting is to let the defaults stand: </p> <pre> <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = <a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> = -<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> = -<a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> = <a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a> = <a href="postconf.5.html#smtp_tls_eckey_file">smtp_tls_eckey_file</a> = +# Obsolete DSA parameters +<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> = +<a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> = +# Postfix ≥ 3.4 interface +<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> = </pre> </blockquote> @@ -11766,13 +12138,19 @@ CA(s) (bottom-up order). </p> <p> Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". -Create the client.pem file with "cat client_cert.pem intermediate_CA.pem -root_CA.pem > client.pem". </p> +As the "root" super-user create the client.pem file with: </p> + +<blockquote> +<pre> +# <b>umask 077</b> +# <b>cat client_key.pem client_cert.pem intermediate_CA.pem > chain.pem </b> +</pre> +</blockquote> <p> If you also want to verify remote SMTP server certificates issued by these CAs, you can add the CA certificates to the <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>, in which case it is not necessary to have them in the <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>, -<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> or <a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>. </p> +<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> (obsolete) or <a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>. </p> <p> A certificate supplied here must be usable as an SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. </p> @@ -11780,7 +12158,7 @@ and hence pass the "openssl verify -purpose sslclient ..." test. </p> <p> Example: </p> <pre> -<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = /etc/postfix/client.pem +<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = /etc/postfix/chain.pem </pre> <p> This feature is available in Postfix 2.2 and later. </p> @@ -11788,6 +12166,158 @@ and hence pass the "openssl verify -purpose sslclient ..." test. </p> </DD> +<DT><b><a name="smtp_tls_chain_files">smtp_tls_chain_files</a> +(default: empty)</b></DT><DD> + +<p> List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. The file names +are separated by commas and/or whitespace. This parameter obsoletes the +legacy algorithm-specific key and certificate file settings. When this +parameter is non-empty, the legacy parameters are ignored, and a warning +is logged if any are also non-empty. </p> + +<p> With the proliferation of multiple private key algorithms—which, +as of OpenSSL 1.1.1, include DSA (obsolete), RSA, ECDSA, Ed25519 +and Ed448—it is increasingly impractical to use separate +parameters to configure the key and certificate chain for each +algorithm. Therefore, Postfix now supports storing multiple keys and +corresponding certificate chains in a single file or in a set of files. + +<p> Each key must appear <b>immediately before</b> the corresponding +certificate, optionally followed by additional issuer certificates that +complete the certificate chain for that key. When multiple files are +specified, they are equivalent to a single file that is concatenated +from those files in the given order. Thus, while a key must always +precede its certificate and issuer chain, it can be in a separate file, +so long as that file is listed immediately before the file that holds +the corresponding certificate chain. Once all the files are +concatenated, the sequence of PEM objects must be: <i>key1, cert1, +[chain1], key2, cert2, [chain2], ..., keyN, certN, [chainN].</i> </p> + +<p> Storing the private key in the same file as the corresponding +certificate is more reliable. With the key and certificate in separate +files, there is a chance that during key rollover a Postfix process +might load a private key and certificate from separate files that don't +match. Various operational errors may even result in a persistent +broken configuration in which the certificate does not match the private +key. </p> + +<p> The file or files must contain at most one key of each type. If, +for example, two or more RSA keys and corresponding chains are listed, +depending on the version of OpenSSL either only the last one will be +used or an configuration error may be detected. Note that while +"Ed25519" and "Ed448" are considered separate algorithms, the various +ECDSA curves (typically one of prime256v1, secp384r1 or secp521r1) are +considered as different parameters of a single "ECDSA" algorithm, so it +is not presently possible to configure keys for more than one ECDSA +curve. </p> + +<p> +Example (separate files for each key and corresponding certificate chain): +</p> +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> = + ${<a href="postconf.5.html#config_directory">config_directory</a>}/ed25519.pem, + ${<a href="postconf.5.html#config_directory">config_directory</a>}/ed448.pem, + ${<a href="postconf.5.html#config_directory">config_directory</a>}/rsa.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed25519.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed448.pem: + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/rsa.pem: + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> +Example (all keys and certificates in a single file): +</p> +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/chains.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/chains.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="smtp_tls_cipherlist">smtp_tls_cipherlist</a> (default: empty)</b></DT><DD> @@ -11830,6 +12360,22 @@ and opportunistic TLS always uses "export" or better (i.e. all) ciphers. </p> </DD> +<DT><b><a name="smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> +(default: no)</b></DT><DD> + +<p> Try to make multiple deliveries per TLS-encrypted connection. +This uses the <a href="tlsproxy.8.html">tlsproxy(8)</a> service to encrypt an SMTP connection, +uses the <a href="scache.8.html">scache(8)</a> service to save that connection, and relies on +hints from the <a href="qmgr.8.html">qmgr(8)</a> daemon. </p> + +<p> See "<a href="TLS_README.html#client_tls_reuse">Client-side +TLS connection reuse</a>" for background details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="smtp_tls_dane_insecure_mx_policy">smtp_tls_dane_insecure_mx_policy</a> (default: dane)</b></DT><DD> @@ -11873,7 +12419,8 @@ policy is backwards-compatible with earlier Postfix versions. (default: empty)</b></DT><DD> <p> File with the Postfix SMTP client DSA certificate in PEM format. -This file may also contain the Postfix SMTP client private DSA key. </p> +This file may also contain the Postfix SMTP client private DSA key. +The DSA algorithm is obsolete and should not be used. </p> <p> See the discussion under <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> for more details. </p> @@ -11894,7 +12441,8 @@ This file may also contain the Postfix SMTP client private DSA key. </p> <p> File with the Postfix SMTP client DSA private key in PEM format. This file may be combined with the Postfix SMTP client DSA certificate -file specified with $<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>. </p> +file specified with $<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>. The DSA algorithm is obsolete +and should not be used. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -11910,7 +12458,9 @@ to anyone else. </p> (default: empty)</b></DT><DD> <p> File with the Postfix SMTP client ECDSA certificate in PEM format. -This file may also contain the Postfix SMTP client ECDSA private key. </p> +This file may also contain the Postfix SMTP client ECDSA private key. +With Postfix ≥ 3.4 the preferred way to configure client keys and +certificates is via the "<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>" parameter. </p> <p> See the discussion under <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> for more details. </p> @@ -11931,8 +12481,10 @@ compiled and linked with OpenSSL 1.0.0 or later. </p> (default: $<a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>)</b></DT><DD> <p> File with the Postfix SMTP client ECDSA private key in PEM format. -This file may be combined with the Postfix SMTP client ECDSA -certificate file specified with $<a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>. </p> +This file may be combined with the Postfix SMTP client ECDSA certificate +file specified with $<a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>. With Postfix ≥ 3.4 the +preferred way to configure client keys and certificates is via the +"<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -12182,7 +12734,9 @@ are not prepared to handle the new TLSA RRset. </p> <p> File with the Postfix SMTP client RSA private key in PEM format. This file may be combined with the Postfix SMTP client RSA certificate -file specified with $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>. </p> +file specified with $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>. With Postfix ≥ 3.4 the +preferred way to configure client keys and certificates is via the +"<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -12342,8 +12896,10 @@ matches the underlying OpenSSL interface semantics. <p> The range of protocols advertised by an SSL/TLS client must be contiguous. When a protocol version is enabled, disabling any -higher version implicitly disables all versions above that higher -version. Thus, for example: </p> +higher version implicitly disables all versions above that higher version. +Thus, for example (assuming the OpenSSL library supports both SSLv2 +and SSLv3): +</p> <blockquote> <pre> <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !TLSv1 @@ -12360,6 +12916,10 @@ disabled except by also disabling "TLSv1" (typically leaving just versions of Postfix ≥ 2.10 can explicitly disable support for "TLSv1.1" or "TLSv1.2". </p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> At the <a href="TLS_README.html#client_tls_dane">dane</a> and <a href="TLS_README.html#client_tls_dane">dane-only</a> security levels, when usable TLSA records are obtained for the remote SMTP @@ -12533,11 +13093,13 @@ security are: </p> <dt><b><a href="TLS_README.html#client_tls_may">may</a></b></dt> <dd>Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces -interoperability. The optional "ciphers", "exclude" and "protocols" +interoperability. The optional "ciphers", "exclude", and "protocols" attributes (available for opportunistic TLS with Postfix ≥ 2.6) -override the "<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>", "<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>" and -"<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>" configuration parameters. When opportunistic TLS -handshakes fail, Postfix retries the connection with TLS disabled. +and "connection_reuse" attribute (Postfix ≥ 3.4) override the +"<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>", "<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>", "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>", +and +"<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a>" configuration parameters. When opportunistic +TLS handshakes fail, Postfix retries the connection with TLS disabled. This allows mail delivery to sites with non-interoperable TLS implementations.</dd> @@ -12545,9 +13107,11 @@ implementations.</dd> <dd>Mandatory TLS encryption. At this level and higher, the optional "protocols" attribute overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> parameter, the optional "ciphers" attribute -overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a> parameter, and the +overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a> parameter, the optional "exclude" attribute (Postfix ≥ 2.6) overrides the <a href="postconf.5.html">main.cf</a> -<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a> parameter. In the policy table, +<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a> parameter, and the optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the +<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. In the policy table, multiple protocols or excluded ciphers must be separated by colons, as attribute values may not contain whitespace or commas. </dd> @@ -12559,20 +13123,24 @@ href="TLS_README.html#client_tls_may">may</a>. If TLSA records are found, but none are usable, the effective security level is <a href="TLS_README.html#client_tls_encrypt">encrypt</a>. When usable TLSA records are obtained for the remote SMTP server, the -server certificate must match the TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) +server certificate must match the TLSA records. <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and DNSSEC support is available with Postfix -2.11 and later. </dd> +2.11 and later. The optional "connection_reuse" attribute (Postfix +≥ 3.4) overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. +</dd> <dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt> <dd>Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA records in DNSSEC. If no TLSA records are found, or none are usable, no connection is made to the server. When usable TLSA records are obtained for the remote SMTP server, the -server certificate must match the TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS +server certificate must match the TLSA records. <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 -and later. </dd> +and later. The optional "connection_reuse" attribute (Postfix ≥ +3.4) overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. +</dd> -<dt><b><a href="TLS_README.html#client_tls_fingerprint">fingerprint</a></b></dt> +<dt><b><a href="TLS_README.html#client_tls_fprint">fingerprint</a></b></dt> <dd>Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted Certification Authorities. The certificate @@ -12586,7 +13154,8 @@ algorithm used to calculate the fingerprint is selected by the be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) -digits. </dd> +digits. The optional "connection_reuse" attribute (Postfix ≥ 3.4) +overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd> <dt><b><a href="TLS_README.html#client_tls_verify">verify</a></b></dt> <dd>Mandatory TLS verification. At this security @@ -12596,7 +13165,9 @@ unauthenticated DNS MX lookups. The optional "match" attribute overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_verify_cert_match">smtp_tls_verify_cert_match</a> 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. </dd> +"secure" policy, described below. The optional "connection_reuse" +attribute (Postfix ≥ 3.4) overrides the <a href="postconf.5.html">main.cf</a> +<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd> <dt><b><a href="TLS_README.html#client_tls_secure">secure</a></b></dt> <dd>Secure-channel TLS. At this security level, DNS @@ -12614,7 +13185,9 @@ routing 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. </dd> +verification of a new MX host fails. The optional "connection_reuse" +attribute (Postfix ≥ 3.4) overrides the <a href="postconf.5.html">main.cf</a> +<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd> </dl> @@ -12672,11 +13245,13 @@ and "TLSv1". </p> <p> The range of protocols advertised by an SSL/TLS client must be contiguous. When a protocol version is enabled, disabling any -higher version implicitly disables all versions above that higher -version. Thus, for example: </p> +higher version implicitly disables all versions above that higher version. +Thus, for example (assuming the OpenSSL library supports both SSLv2 +and SSLv3): +</p> <blockquote> <pre> -<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !TLSv1 +<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> = !SSLv2, !TLSv1 </pre> </blockquote> <p> also disables any protocols version higher than TLSv1 leaving @@ -12687,6 +13262,10 @@ and "TLSv1.2". The latest patch levels of Postfix ≥ 2.6, and all versions of Postfix ≥ 2.10 can explicitly disable support for "TLSv1.1" or "TLSv1.2"</p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 for opportunistic TLS set "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> = !SSLv2". To exclude both "SSLv2" and "SSLv3" set @@ -12818,7 +13397,7 @@ in effect, the destination domain's containing DNS zone must be signed and the Postfix SMTP client's operating system must be configured to send its DNS queries to a recursive DNS nameserver that is able to validate the signed records. Each MX host's DNS -zone should also be signed, and should publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>) +zone should also be signed, and should publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) records that specify how that MX host's TLS certificate is to be verified. TLSA records do not preempt the normal SMTP MX host selection algorithm, if some MX hosts support TLSA and others do @@ -12833,17 +13412,17 @@ purposes of protocol and cipher selection, the "dane" security level is treated like a "mandatory" TLS security level, and weak ciphers and protocols are disabled. Since DANE authenticates server certificates the "aNULL" cipher-suites are transparently excluded -at this level, no need to configure this manually. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) +at this level, no need to configure this manually. <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication is available with Postfix 2.11 and later. </dd> <dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt> <dd>Mandatory DANE TLS. This is just like "dane" above, but DANE TLSA authentication is required. There is no fallback to "may" or -"encrypt" when TLSA records are missing or unusable. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> +"encrypt" when TLSA records are missing or unusable. <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication is available with Postfix 2.11 and later. </dd> -<dt><b><a href="TLS_README.html#client_tls_fingerprint">fingerprint</a></b></dt> +<dt><b><a href="TLS_README.html#client_tls_fprint">fingerprint</a></b></dt> <dd>Certificate fingerprint verification. At this security level, there are no trusted Certification Authorities. The certificate trust chain, expiration date, etc., are @@ -12939,6 +13518,42 @@ Examples: </DD> +<DT><b><a name="smtp_tls_servername">smtp_tls_servername</a> +(default: empty)</b></DT><DD> + +<p> Optional name to send to the remote SMTP server in the TLS Server +Name Indication (SNI) extension. The SNI extension is always on when +DANE is used to authenticate the server, and in that case the SNI name +sent is the one required by <a href="http://tools.ietf.org/html/rfc7672">RFC7672</a> and this parameter is ignored. </p> + +<p> Some SMTP servers use the received SNI name to select an appropriate +certificate chain to present to the client. While this may improve +interoperability with such servers, it may reduce interoperability with +other servers that choose to abort the connection when they don't have a +certificate chain configured for the requested name. Such servers +should select a default certificate chain and continue the handshake, +but some may not. Therefore, absent DANE, no SNI name is sent by +default. </p> + +<p> The SNI name must be either a valid DNS hostname, or else one of the +special values <b>hostname</b> or <b>nexthop</b>, which select either the +remote hostname or the nexthop domain respectively. DNS names for SNI must be +in A-label (punycode) form. Invalid DNS names log a configuration error +warning and mail delivery is deferred. </p> + +<p> Except when using a <a href="postconf.5.html#relayhost">relayhost</a> to forward all email, the only +sensible non-empty <a href="postconf.5.html">main.cf</a> setting for this parameter is +<b>hostname</b>. Other non-empty values are only practical on a +per-destination basis via the <b>servername</b> attribute of the Postfix +TLS <a href="TLS_README.html#client_tls_policy">policy table</a>. When +in doubt, leave this parameter empty, and configure per-destination SNI +as needed. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> (default: empty)</b></DT><DD> @@ -13025,9 +13640,9 @@ trust-anchor files are used at all, they will be specified on a per-destination basis via the "tafile" attribute of the "verify" and "secure" levels in <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>. </p> -<p> The underlying mechanism is in support of <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE TLSA), -which defines mechanisms for a client to securely determine server -TLS certificates via DNS. </p> +<p> The underlying mechanism is in support of <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE TLSA), +which defines mechanisms for an SMTP client MTA to securely determine +server TLS certificates via DNS. </p> <p> If you want your trust anchors to be public keys, with OpenSSL you can extract a single PEM public key from a PEM X.509 file @@ -13617,15 +14232,28 @@ client network address information. <dt><b><a name="check_ccert_access">check_ccert_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt> -<dd> Use the remote SMTP client certificate fingerprint or the public key +<dd> By default use the remote SMTP client certificate fingerprint +or the public key fingerprint (Postfix 2.9 and later) as lookup key for the specified <a href="access.5.html">access(5)</a> database; with Postfix version 2.2, also require that the remote SMTP client certificate is verified successfully. The fingerprint digest algorithm is configurable via the <a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> parameter (hard-coded as md5 prior to -Postfix version 2.5). This feature is available with Postfix version +Postfix version 2.5). This feature requires "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> += yes" and is available with Postfix version 2.2 and later. </dd> +<br> + +<dd> Alternatively, <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> accepts an explicit search +order (Postfix 3.5 and later). The default search order as described +above corresponds with: </dd> + +<dd> <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> { <a href="DATABASE_README.html">type:table</a>, { search_order = cert_fingerprint, +pubkey_fingerprint } } </dd> + +<dd> The commas are optional. </dd> + <dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt> <dd>Search the specified access database for the client hostname, @@ -13724,7 +14352,8 @@ CA. Otherwise, clients with a third-party certificate would also be allowed to relay. Specify "<a href="postconf.5.html#tls_append_default_CA">tls_append_default_CA</a> = no" when the trusted CA is specified with <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> or <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>, to prevent Postfix from appending the system-supplied default CAs. -This feature is available with Postfix version 2.2.</dd> +This feature requires "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = yes" and is available +with Postfix version 2.2 and later.</dd> <dt><b><a name="permit_tls_clientcerts">permit_tls_clientcerts</a></b></dt> @@ -13733,8 +14362,8 @@ fingerprint or public key fingerprint (Postfix 2.9 and later) is listed in $<a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a>. The fingerprint digest algorithm is configurable via the <a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> parameter (hard-coded as md5 prior to -Postfix version 2.5). This feature is available with Postfix version -2.2. </dd> +Postfix version 2.5). This feature requires "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> += yes" and is available with Postfix version 2.2 and later.</dd> <dt><b><a name="reject_rbl_client">reject_rbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt> @@ -13812,7 +14441,7 @@ available in Postfix 2.8 and later. </dd> <dt><b><a name="reject_unknown_client_hostname">reject_unknown_client_hostname</a></b> (with Postfix < 2.3: reject_unknown_client)</dt> <dd>Reject the request when 1) the client IP address->name mapping -fails, 2) the name->address mapping fails, or 3) the name->address +fails, or 2) the name->address mapping fails, or 3) the name->address mapping does not match the client IP address. <br> This is a stronger restriction than the <a href="postconf.5.html#reject_unknown_reverse_client_hostname">reject_unknown_reverse_client_hostname</a> feature, which triggers only under condition 1) above. <br> The @@ -14340,7 +14969,8 @@ Use C like escapes to specify special characters such as whitespace. </p> <p> -This parameter is not subjected to $parameter expansion. +The <a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> value is not subject to Postfix configuration +parameter $name expansion. </p> <p> @@ -14627,6 +15257,39 @@ from the list. </p> </DD> +<DT><b><a name="smtpd_milter_maps">smtpd_milter_maps</a> +(default: empty)</b></DT><DD> + +<p> Lookup tables with Milter settings per remote SMTP client IP +address. The lookup result overrides the <a href="postconf.5.html#smtpd_milters">smtpd_milters</a> setting, +and has the same syntax. </p> + +<p> Note: lookup tables cannot return empty responses. Specify a +lookup result of DISABLE (case does not matter) to indicate that +Milter support should be disabled. </p> + +<p> Example to disable Milters for local clients: </p> + +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtpd_milter_maps">smtpd_milter_maps</a> = <a href="cidr_table.5.html">cidr</a>:/etc/postfix/smtpd_milter_map + <a href="postconf.5.html#smtpd_milters">smtpd_milters</a> = inet:host:port, { inet:host:port, ... }, ... +</pre> + +<pre> +/etc/postfix/smtpd_milter_map: + # Disable Milters for local clients. + 127.0.0.0/8 DISABLE + 192.168.0.0/16 DISABLE + ::/64 DISABLE + 2001:db8::/32 DISABLE +</pre> + +<p> This feature is available in Postfix 3.2 and later. </p> + + +</DD> + <DT><b><a name="smtpd_milters">smtpd_milters</a> (default: empty)</b></DT><DD> @@ -15071,7 +15734,8 @@ lookup problem with Postfix prior to version 2.0. <dt><b><a name="reject_non_fqdn_recipient">reject_non_fqdn_recipient</a></b></dt> -<dd>Reject the request when the RCPT TO address is not in +<dd>Reject the request when the RCPT TO address specifies a +domain that is not in fully-qualified domain form, as required by the RFC. <br> The <a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> parameter specifies the response code for rejected requests (default: 504). </dd> @@ -15150,8 +15814,9 @@ numerical response code when an address probe failed due to a temporary problem (default: 450). <br> The <a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> parameter specifies the action after address probe failure due to a temporary problem (default: -<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>). <br> This feature is available in Postfix 2.1 -and later. </dd> +<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>). <br> This feature breaks for aliased addresses +with "<a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> = no" (Postfix ≤ 3.2). <br> +This feature is available in Postfix 2.1 and later. </dd> </dl> @@ -15222,9 +15887,15 @@ be truncated before it is logged to the remote SMTP client's maillog file, or before it is returned to the sender in a delivery status notification. </p> -<p> This feature supports a limited number of $name attributes in -the footer text. These are replaced by their current value for the -SMTP session: </p> +<p> The template text is not subject to Postfix configuration +parameter $name expansion. Instead, this feature supports a limited +number of $name attributes in the footer text. These attributes are +replaced with their current value for the SMTP session. </p> + +<p> Note: specify $$name in footer text that is looked up from +<a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>:-based <a href="postconf.5.html#smtpd_reject_footer_maps">smtpd_reject_footer_maps</a>, otherwise the +Postfix server will not use the footer text and will log a warning +instead. </p> <dl> @@ -15272,6 +15943,24 @@ text (Postfix 2.10 and later). </p> </DD> +<DT><b><a name="smtpd_reject_footer_maps">smtpd_reject_footer_maps</a> +(default: empty)</b></DT><DD> + +<p> Lookup tables, indexed by the complete Postfix SMTP server 4xx or +5xx response, with reject footer templates. See <a href="postconf.5.html#smtpd_reject_footer">smtpd_reject_footer</a> +for details. </p> + +<p> +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. +</p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (default: yes)</b></DT><DD> @@ -15599,6 +16288,26 @@ releases it was called <b><a href="postconf.5.html#smtpd_sasl_application_name"> </DD> +<DT><b><a name="smtpd_sasl_response_limit">smtpd_sasl_response_limit</a> +(default: 12288)</b></DT><DD> + +<p> The maximum length of a SASL client's response to a server challenge. +When the client's "initial response" is longer than the normal limit for +SMTP commands, the client must omit its initial response, and wait for an +empty server challenge; it can then send what would have been its "initial +response" as a response to the empty server challenge. <a href="http://tools.ietf.org/html/rfc4954">RFC4954</a> requires the +server to accept client responses up to at least 12288 octets of +base64-encoded text. The default value is therefore also the minimum value +accepted for this parameter.</p> + +<p> This feature is available in Postfix 3.4 and later. Prior versions use +"<a href="postconf.5.html#line_length_limit">line_length_limit</a>", which may need to be raised to accommodate larger client +responses, as may be needed with GSSAPI authentication of Windows AD users +who are members of many groups. </p> + + +</DD> + <DT><b><a name="smtpd_sasl_security_options">smtpd_sasl_security_options</a> (default: noanonymous)</b></DT><DD> @@ -15825,8 +16534,9 @@ feature is available in Postfix version 2.11 and later. </dd> <dt><b><a name="reject_non_fqdn_sender">reject_non_fqdn_sender</a></b></dt> -<dd>Reject the request when the MAIL FROM address is not in -fully-qualified domain form, as required by the RFC. <br> The +<dd>Reject the request when the MAIL FROM address specifies a +domain that is not in +fully-qualified domain form as required by the RFC. <br> The <a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> parameter specifies the response code for rejected requests (default: 504). </dd> @@ -15893,8 +16603,10 @@ change into 550 when you are confident that it is safe to do so). code when an address probe failed due to a temporary problem (default: 450). <br> The <a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> parameter specifies the action after address probe failure due to a temporary -problem (default: <a href="postconf.5.html#defer_if_permit">defer_if_permit</a>). <br> This feature is available -in Postfix 2.1 and later. </dd> +problem (default: <a href="postconf.5.html#defer_if_permit">defer_if_permit</a>). <br> This feature breaks for +aliased addresses with "<a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> = no" (Postfix +≤ 3.2). <br> This feature is available in Postfix 2.1 and later. +</dd> </dl> @@ -16166,7 +16878,9 @@ but not any CAs it delegates to. </p> (default: empty)</b></DT><DD> <p> File with the Postfix SMTP server RSA certificate in PEM format. -This file may also contain the Postfix SMTP server private RSA key. </p> +This file may also contain the Postfix SMTP server private RSA key. +With Postfix ≥ 3.4 the preferred way to configure server keys and +certificates is via the "<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>" parameter. </p> <p> Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a @@ -16175,15 +16889,22 @@ able to authenticate the server, but unless it is running Postfix 2.3 or similar software, it will still insist on a server certificate. </p> <p> For servers that are <b>not</b> public Internet MX hosts, Postfix -2.3 supports configurations with no certificates. This entails the -use of just the anonymous TLS ciphers, which are not supported by -typical SMTP clients. Since such clients will not, as a rule, fall -back to plain text after a TLS handshake failure, the server will -be unable to receive email from TLS enabled clients. To avoid -accidental configurations with no certificates, Postfix 2.3 enables -certificate-less operation only when the administrator explicitly -sets "<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none". This ensures that new Postfix -configurations will not accidentally run with no certificates. </p> +supports configurations with no certificates. This entails the use of +just the anonymous TLS ciphers, which are not supported by typical SMTP +clients. Since some clients may not fall back to plain text after a TLS +handshake failure, a certificate-less Postfix SMTP server will be unable +to receive email from some TLS-enabled clients. To avoid accidental +configurations with no certificates, Postfix enables certificate-less +operation only when the administrator explicitly sets +"<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none". This ensures that new Postfix SMTP server +configurations will not accidentally enable TLS without certificates. </p> + +<p> Note that server certificates are not optional in TLS 1.3. To run +without certificates you'd have to disable the TLS 1.3 protocol by +including '!TLSv1.3' in "<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a>" and perhaps also +"<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a>". It is simpler instead to just +configure a certificate chain. Certificate-less operation is not +recommended. <p> <p> Both RSA and DSA certificates are supported. When both types are present, the cipher used determines which certificate will be @@ -16203,8 +16924,8 @@ root_CA.pem > server.pem". </p> <p> If you also want to verify client certificates issued by these CAs, you can add the CA certificates to the <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>, in which -case it is not necessary to have them in the <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> or -<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>. </p> +case it is not necessary to have them in the <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>, +<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> (obsolete) or <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. </p> <p> A certificate supplied here must be usable as an SSL server certificate and hence pass the "openssl verify -purpose sslserver ..." test. </p> @@ -16220,6 +16941,164 @@ and hence pass the "openssl verify -purpose sslserver ..." test. </p> </DD> +<DT><b><a name="smtpd_tls_chain_files">smtpd_tls_chain_files</a> +(default: empty)</b></DT><DD> + +<p> List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. The file names +are separated by commas and/or whitespace. This parameter obsoletes the +legacy algorithm-specific key and certificate file settings. When this +parameter is non-empty, the legacy parameters are ignored, and a warning +is logged if any are also non-empty. </p> + +<p> With the proliferation of multiple private key algorithms—which, +as of OpenSSL 1.1.1, include DSA (obsolete), RSA, ECDSA, Ed25519 +and Ed448—it is increasingly impractical to use separate +parameters to configure the key and certificate chain for each +algorithm. Therefore, Postfix now supports storing multiple keys and +corresponding certificate chains in a single file or in a set of files. + +<p> Each key must appear <b>immediately before</b> the corresponding +certificate, optionally followed by additional issuer certificates that +complete the certificate chain for that key. When multiple files are +specified, they are equivalent to a single file that is concatenated +from those files in the given order. Thus, while a key must always +precede its certificate and issuer chain, it can be in a separate file, +so long as that file is listed immediately before the file that holds +the corresponding certificate chain. Once all the files are +concatenated, the sequence of PEM objects must be: <i>key1, cert1, +[chain1], key2, cert2, [chain2], ..., keyN, certN, [chainN].</i> </p> + +<p> Storing the private key in the same file as the corresponding +certificate is more reliable. With the key and certificate in separate +files, there is a chance that during key rollover a Postfix process +might load a private key and certificate from separate files that don't +match. Various operational errors may even result in a persistent +broken configuration in which the certificate does not match the private +key. </p> + +<p> The file or files must contain at most one key of each type. If, +for example, two or more RSA keys and corresponding chains are listed, +depending on the version of OpenSSL either only the last one will be +used or an configuration error may be detected. Note that while +"Ed25519" and "Ed448" are considered separate algorithms, the various +ECDSA curves (typically one of prime256v1, secp384r1 or secp521r1) are +considered as different parameters of a single "ECDSA" algorithm, so it +is not presently possible to configure keys for more than one ECDSA +curve. </p> + +<p> RSA is still the most widely supported algorithm. Presently (late +2018), ECDSA support is common, but not yet universal, and Ed25519 and +Ed448 support is mostly absent. Therefore, an RSA key should generally +be configured, along with any additional keys for the other algorithms +when desired. </p> + +<p> +Example (separate files for each key and corresponding certificate chain): +</p> +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a> = + ${<a href="postconf.5.html#config_directory">config_directory</a>}/ed25519.pem, + ${<a href="postconf.5.html#config_directory">config_directory</a>}/ed448.pem, + ${<a href="postconf.5.html#config_directory">config_directory</a>}/rsa.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed25519.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed448.pem: + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/rsa.pem: + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> +Example (all keys and certificates in a single file): +</p> +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + <a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/chains.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/chains.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> (default: empty)</b></DT><DD> @@ -16266,7 +17145,8 @@ and opportunistic TLS always uses "export" or better (i.e. all) ciphers. </p> (default: empty)</b></DT><DD> <p> File with the Postfix SMTP server DSA certificate in PEM format. -This file may also contain the Postfix SMTP server private DSA key. </p> +This file may also contain the Postfix SMTP server private DSA key. +The DSA algorithm is obsolete and should not be used. </p> <p> See the discussion under <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> for more details. </p> @@ -16353,7 +17233,8 @@ configuration parameter. </p> <p> File with the Postfix SMTP server DSA private key in PEM format. This file may be combined with the Postfix SMTP server DSA certificate -file specified with $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>. </p> +file specified with $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>. The DSA algorithm is obsolete +and should not be used. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -16369,7 +17250,9 @@ to anyone else. </p> (default: empty)</b></DT><DD> <p> File with the Postfix SMTP server ECDSA certificate in PEM format. -This file may also contain the Postfix SMTP server private ECDSA key. </p> +This file may also contain the Postfix SMTP server private ECDSA key. +With Postfix ≥ 3.4 the preferred way to configure server keys and +certificates is via the "<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>" parameter. </p> <p> See the discussion under <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> for more details. </p> @@ -16390,7 +17273,9 @@ compiled and linked with OpenSSL 1.0.0 or later. </p> <p> File with the Postfix SMTP server ECDSA private key in PEM format. This file may be combined with the Postfix SMTP server ECDSA certificate -file specified with $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. </p> +file specified with $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. With Postfix ≥ 3.4 the +preferred way to configure server keys and certificates is via the +"<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -16429,6 +17314,11 @@ as 128 bit strength ECC. Barring significant progress in attacks on elliptic curve crypto-systems, the "strong" curve is sufficient for most users. </dd> +<dt><b>auto</b></dt> <dd> Use the most preferred curve that is +supported by both the client and the server. This setting requires +Postfix ≥ 3.2 compiled and linked with OpenSSL ≥ 1.0.2. This +is the default setting under the above conditions. </dd> + </dl> <p> If you want to take maximal advantage of ciphers that offer <a @@ -16594,7 +17484,9 @@ to Postfix 2.9.6 or later. </p> <p> File with the Postfix SMTP server RSA private key in PEM format. This file may be combined with the Postfix SMTP server RSA certificate -file specified with $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>. </p> +file specified with $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>. With Postfix ≥ 3.4 the +preferred way to configure server keys and certificates is via the +"<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -16753,6 +17645,10 @@ disabled. The latest patch levels of Postfix ≥ 2.6, and all versions of Postfix ≥ 2.10 can disable support for "TLSv1.1" or "TLSv1.2". </p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> Example: </p> <pre> @@ -16784,6 +17680,10 @@ and "TLSv1.2". The latest patch levels of Postfix ≥ 2.6, and all versions of Postfix ≥ 2.10 can disable support for "TLSv1.1" or "TLSv1.2". </p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 for opportunistic TLS set "<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> = !SSLv2". To exclude both "SSLv2" and "SSLv3" set @@ -16967,7 +17867,7 @@ purpose. </p> proxy agent. When a proxy agent is used, this protocol conveys local and remote address and port information. Specify "<a href="postconf.5.html#smtpd_upstream_proxy_protocol">smtpd_upstream_proxy_protocol</a> = haproxy" to enable the haproxy -protocol. </p> +protocol; version 2 is supported with Postfix 3.5 and later. </p> <p> NOTE: To use the nginx proxy with <a href="smtpd.8.html">smtpd(8)</a>, enable the XCLIENT protocol with <a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a>. This supports SASL @@ -17335,8 +18235,8 @@ errors while accessing the Postfix <a href="postconf.5.html">main.cf</a> configu (default: see "postconf -d" output)</b></DT><DD> <p> -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". </p> <p> @@ -17422,63 +18322,14 @@ bytes (equivalent to 256 bits) is sufficient to generate a 128bit <DT><b><a name="tls_dane_digest_agility">tls_dane_digest_agility</a> (default: on)</b></DT><DD> -<p> Configure DANE TLSA digest algorithm agility. When digest -algorithm agility is enabled, and the server and client support a -common strong digest algorithm, TLSA records with weaker digest -algorithms are ignored. </p> - -<p> Specify one of the following: </p> - -<dl> - -<dt><b>off</b></dt> -<dd> DANE verification examines each well-formed record in the TLSA -RRset whose matching type is either "0" (no hash used) or is one of -the digest algorithms listed in $<a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a>. This setting -is not recommended. </dd> - -<dt><b>on</b></dt> -<dd> From each group of well-formed TLSA RRs a non-zero digest -matching type with the same certificate usage and selector, DANE -verification examines only those records whose matching type has -the highest precedence (appear earliest in $<a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a>). -</dd> +<p> Configure <a href="http://tools.ietf.org/html/rfc7671">RFC7671</a> DANE TLSA digest algorithm agility. +Do not change this setting from its default value. </p> -<dt><b>maybe</b></dt> -<dd> For compatibility with digest algorithm agility, each certificate -or public key whose digest is included in a DANE TLSA RRset, SHOULD -be published with the same set of digest matching type values as -any other with the same usage and selector. Therefore, compatible -TLSA RRsets will contain an identical count of well-formed RRs with -each non-zero digest matching type for any fixed combination of -usage and selector. When this constraint is violated, or any of -the digest records are malformed, digest algorithm agility will -disabled. Otherwise, digest algorithm agility is enabled. </dd> +<p> See Section 8 of <a href="http://tools.ietf.org/html/rfc7671">RFC7671</a> for correct key rotation procedures. </p> -</dl> - -<p> Digest algorithm agility ensures that the strongest digest -supported by both the Postfix SMTP client and the remote server is -used, and weaker digests are ignored. This supports non-disruptive -deprecation of outdated digest algorithms. </p> - -<p> To ensure compatibility with digest algorithm agility during -key rotation, when a certificate or public key is being replaced -with another, and both are published during the transition, both -the old and the new certificate MUST be specified with the same set -of digests. One can change the list of digest algorithms later, -once old keys are retired. At any given time, change either the -list of digests without changing the list of certificates or public -keys or the list of certificates or public keys without changing -the list of digests. Full value matching type "0" records are not -subject to this constraint, but are discouraged due to the size of -the resulting DNS records. </p> - -<p> It is expected that this algorithm agility mechanism will be -published in a standards track RFC for SMTP with DANE, and also in -an eventual update to <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>. </p> - -<p> This feature is available in Postfix 2.11 and later. </p> +<p> This feature is available in Postfix 2.11 through 3.1. Postfix +3.2 and later ignore this configuration parameter and behave as +though it were set to "on". </p> </DD> @@ -17486,10 +18337,11 @@ an eventual update to <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>. <DT><b><a name="tls_dane_digests">tls_dane_digests</a> (default: sha512 sha256)</b></DT><DD> -<p> <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> TLSA resource-record "matching type" digest algorithms -in descending preference order. All the specified algorithms must -be supported by the underlying OpenSSL library, otherwise the Postfix -SMTP client will not support DANE TLSA security. </p> +<p> DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>, <a href="http://tools.ietf.org/html/rfc7671">RFC 7671</a>, <a href="http://tools.ietf.org/html/rfc7672">RFC 7672</a>) resource-record "matching +type" digest algorithms in descending preference order. All the +specified algorithms must be supported by the underlying OpenSSL +library, otherwise the Postfix SMTP client will not support DANE +TLSA security. </p> <p> Specify a list of digest names separated by commas and/or whitespace. Each digest name may be followed by an optional @@ -17514,16 +18366,6 @@ seriously compromised and servers have had ample time to update their TLSA records you should not omit any standard digests, just arrange them in order from strongest to weakest. </p> -<p> When for a particular combination of "certificate usage" and -"selector" the TLSA RRset contains records with more than one digest -matching type, the tls_dane_digest_agility parameter determines -whether all the RRs are used, or only those with the most preferred -digest matching type. </p> - -<p> The <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> parameter controls -whether any digest TLSA records are acceptable in usage "2" (trust -anchor assertion) TLSA records. </p> - <p> This feature is available in Postfix 2.11 and later. </p> @@ -17532,31 +18374,15 @@ anchor assertion) TLSA records. </p> <DT><b><a name="tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> (default: yes)</b></DT><DD> -<p> <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> trust-anchor digest support in the Postfix TLS library. -Enable support for <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE TLSA) DNS records that contain -digests of trust-anchors with certificate usage "2". In this case -the certificate usage logically requires the server administrator -to configure the server to include the trust-anchor certificate in -the server's SSL certificate chain. If enough domains mess this -up, you can disable support for these TLSA records, but you'll no -longer have secure connections that get it right and only publish -trust anchor records. </p> - -<p> At the <a href="TLS_README.html#client_tls_dane">dane</a> -security level, when a TLSA RRset includes only unusable associations, -the Postfix SMTP client will automatically switch the connection -to the <a href="TLS_README.html#client_tls_encrypt">encrypt</a> -security level. At the <a -href="TLS_README.html#client_tls_dane">dane-only</a> security level, -the server in question is skipped and delivery is deferred if no -secure servers are found. </p> - -<p> The <a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a> parameter controls the list of digest -algorithms that are supported in TLSA records. The tls_dane_digest_agility -parameter controls digest algorithm downgrade attack resistance. -</p> +<p> Enable support for <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE TLSA) DNS records that contain +digests of trust-anchors with certificate usage "2". Do not change +this setting from its default value. </p> -<p> This feature is available in Postfix 2.11 and later. </p> +<p> This feature is available in Postfix 2.11 through 3.1. It has +been withdrawn in Postfix 3.2, as trust-anchor TLSA records are now +widely used and have proved sufficiently reliable. Postfix 3.2 and +later ignore this configuration parameter and behaves as though it +were set to "yes". </p> </DD> @@ -17597,44 +18423,46 @@ you can only disable one of these via the hexadecimal syntax above. </p> <dl> -<dt><b>MICROSOFT_SESS_ID_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>CRYPTOPRO_TLSEXT_BUG</b></dt> <dd>New with GOST support in +OpenSSL 1.0.0.</dd> -<dt><b>NETSCAPE_CHALLENGE_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>DONT_INSERT_EMPTY_FRAGMENTS</b></dt> <dd>See +SSL_CTX_set_options(3)</dd> <dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3)</dd> -<dt><b>NETSCAPE_REUSE_CIPHER_CHANGE_BUG</b></dt> <dd> also aliased -as <b>CVE-2010-4180</b>. Postfix 2.8 disables this work-around by -default with OpenSSL versions that may predate the fix. Fixed in -OpenSSL 0.9.8q and OpenSSL 1.0.0c.</dd> - -<dt><b>SSLREF2_REUSE_CERT_TYPE_BUG</b></dt> <dd>See -SSL_CTX_set_options(3)</dd> - <dt><b>MICROSOFT_BIG_SSLV3_BUFFER</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>MICROSOFT_SESS_ID_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> + <dt><b>MSIE_SSLV2_RSA_PADDING</b></dt> <dd> also aliased as <b>CVE-2005-2969</b>. Postfix 2.8 disables this work-around by default with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.7h and OpenSSL 0.9.8a.</dd> +<dt><b>NETSCAPE_CHALLENGE_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> + +<dt><b>NETSCAPE_REUSE_CIPHER_CHANGE_BUG</b></dt> <dd> also aliased +as <b>CVE-2010-4180</b>. Postfix 2.8 disables this work-around by +default with OpenSSL versions that may predate the fix. Fixed in +OpenSSL 0.9.8q and OpenSSL 1.0.0c.</dd> + <dt><b>SSLEAY_080_CLIENT_DH_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> -<dt><b>TLS_D5_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>SSLREF2_REUSE_CERT_TYPE_BUG</b></dt> <dd>See +SSL_CTX_set_options(3)</dd> <dt><b>TLS_BLOCK_PADDING_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>TLS_D5_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> + <dt><b>TLS_ROLLBACK_BUG</b></dt> <dd>See SSL_CTX_set_options(3). This is disabled in OpenSSL 0.9.7 and later. Nobody should still be using 0.9.6! </dd> -<dt><b>DONT_INSERT_EMPTY_FRAGMENTS</b></dt> <dd>See -SSL_CTX_set_options(3)</dd> - -<dt><b>CRYPTOPRO_TLSEXT_BUG</b></dt> <dd>New with GOST support in -OpenSSL 1.0.0.</dd> +<dt><b>TLSEXT_PADDING</b></dt><dd>Postfix ≥ 3.4. See SSL_CTX_set_options(3).</dd> </dl> @@ -17643,6 +18471,33 @@ OpenSSL 1.0.0.</dd> </DD> +<DT><b><a name="tls_eecdh_auto_curves">tls_eecdh_auto_curves</a> +(default: see "postconf -d" output)</b></DT><DD> + +<p> The prioritized list of elliptic curves supported by the Postfix +SMTP client and server. These curves are used by the Postfix SMTP +server when "<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = auto". The selected curves +must be implemented by OpenSSL and be standardized for use in TLS +(<a href="http://tools.ietf.org/html/rfc4492">RFC 4492</a> or its imminent successor). It is unwise to list only +"bleeding-edge" curves supported by a small subset of clients. The +default list is suitable for most users. </p> + +<p> Postfix skips curve names that are unknown to OpenSSL, or that +are known but not yet implemented. This makes it possible to +"anticipate" support for curves that should be used once they become +available. In particular, in some OpenSSL versions, the new <a href="http://tools.ietf.org/html/rfc8031">RFC</a> +<a href="http://tools.ietf.org/html/rfc8031">8031</a> curves "X25519" and "X448" may be known by name, but ECDH +support for either or both may be missing. These curves may appear +in the default value of this parameter, even though they'll only +be usable with later versions of OpenSSL. </p> + +<p> This feature is available in Postfix 3.2 and later, when it is +compiled and linked with OpenSSL 1.0.2 or later on platforms where +EC algorithms have not been disabled by the vendor. </p> + + +</DD> + <DT><b><a name="tls_eecdh_strong_curve">tls_eecdh_strong_curve</a> (default: prime256v1)</b></DT><DD> @@ -17656,11 +18511,11 @@ reported by ecparam(1) with the "-list_curves" option) and be one of the curves listed in Section 5.1.1 of <a href="http://tools.ietf.org/html/rfc4492">RFC 4492</a>. You should not generally change this setting. Remote SMTP client implementations must support this curve for EECDH key exchange to take place. It -is unwise to choose an "exotic" curve supported by only a small subset -of clients. </p> +is unwise to choose an "bleeding-edge" curve supported by only a +small subset of clients. </p> <p> The default "strong" curve is rated in NSA <a -href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite +href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite B</a> for information classified up to SECRET. </p> <p> Note: elliptic curve names are poorly standardized; different @@ -17701,7 +18556,7 @@ curve must be implemented by OpenSSL (as reported by ecparam(1) with the of <a href="http://tools.ietf.org/html/rfc4492">RFC 4492</a>. You should not generally change this setting. </p> <p> This default "ultra" curve is rated in NSA <a -href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite +href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite B</a> for information classified up to TOP SECRET. </p> <p> If you want to take maximal advantage of ciphers that offer <a @@ -17738,6 +18593,18 @@ encouraged to not change this setting. </p> </DD> +<DT><b><a name="tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> +(default: yes)</b></DT><DD> + +<p> A workaround for implementations that hang Postfix while shutting +down a TLS session, until Postfix times out. With this enabled, +Postfix will not wait for the remote TLS peer to respond to a TLS +'close' notification. This behavior is recommended for TLSv1.0 and +later. </p> + + +</DD> + <DT><b><a name="tls_high_cipherlist">tls_high_cipherlist</a> (default: see "postconf -d" output)</b></DT><DD> @@ -17923,6 +18790,116 @@ gives timeout errors. </p> </DD> +<DT><b><a name="tls_server_sni_maps">tls_server_sni_maps</a> +(default: empty)</b></DT><DD> + +<p> Optional lookup tables that map names received from remote SMTP +clients via the TLS Server Name Indication (SNI) extension to the +appropriate keys and certificate chains. This parameter is implemented +in the Postfix TLS library, and applies to both <a href="smtpd.8.html">smtpd(8)</a> and the SMTP +server mode of <a href="tlsproxy.8.html">tlsproxy(8)</a>. </p> + +<p> When this parameter is non-empty, the Postfix SMTP server enables +SNI extension processing, and logs SNI values that are invalid or +don't match an entry in the the specified tables. When an entry +does match, the SNI name is logged as part of the connection summary +at log levels 1 and higher. </p> + +<p> The lookup key is either the verbatim SNI domain name or an +ancestor domain prefixed with a leading dot. For internationalized +domains, the lookup key must be in IDNA 2008 A-label form (as +required in the TLS SNI extension). </p> + +<p> The syntax of the lookup value is the same as with the +<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> parameter (see there for additional details), +but here scoped to just TLS connections in which the client sends +a matching SNI domain name. </p> + +<p> Example: </p> +<blockquote> +<pre> +/etc/postfix/<a href="postconf.5.html">main.cf</a>: + # + # The indexed SNI table must be created with "postmap -F" + # + indexed = ${<a href="postconf.5.html#default_database_type">default_database_type</a>}:${<a href="postconf.5.html#config_directory">config_directory</a>}/ + <a href="postconf.5.html#tls_server_sni_maps">tls_server_sni_maps</a> = ${indexed}sni +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/sni: + # + # The example.com domain has both an RSA and ECDSA certificate + # chain. The chain files MUST start with the private key, + # with the certificate chain next, starting with the leaf + # (server) certificate, and then the issuer certificates. + # + example.com /etc/postfix/sni-chains/rsa2048.example.com.pem, + /etc/postfix/sni-chains/ecdsa-p256.example.com.pem + # + # The example.net domain has a wildcard certificate, and two + # additional DNS names. So its certificate chain is also used + # with any subdomain, plus the additional names. + # + example.net /etc/postfix/sni-chains/example.net.pem + .example.net /etc/postfix/sni-chains/example.net.pem + example.info /etc/postfix/sni-chains/example.net.pem + example.org /etc/postfix/sni-chains/example.net.pem +</pre> +</blockquote> + +<p> Note that the SNI lookup tables should also have entries for +the domains that correspond to the Postfix SMTP server's default +certificate(s). This ensures that the remote SMTP client's TLS SNI +extension gets a positive response when it specifies one of the +Postfix SMTP server's <a href="ADDRESS_CLASS_README.html#default_domain_class">default domains</a>, and ensures that the Postfix +SMTP server will not log an SNI name mismatch for such a domain. +The Postfix SMTP server's default certificates are then only used +when the client sends no SNI or when it sends SNI with a domain +that the server knows no certificate(s) for. </p> + +<p> The mapping from an SNI domain name to a certificate chain is indirect. In +the input source files for "cdb", "hash", "btree" or other tables that are +converted to on-disk indexed files via <a href="postmap.1.html">postmap(1)</a>, the value specified for each +key is a list of filenames. When <a href="postmap.1.html">postmap(1)</a> is used with the <b>-F</b> option, +the generated table stores for each lookup key the base64-encoded contents of +the associated files. When querying tables via <b>postmap -Fq</b>, the table +value is decoded from base64, yielding the original file content, plus a new +line. </p> + +<p> With "regexp", "pcre", "inline", "texthash", "static" and similar +tables that are interpreted at run-time, and don't have a separate +source format, the table value is again a list files, that are loaded +into memory when the table is opened. </p> + +<p> With tables whose content is managed outside of Postfix, such +as LDAP, MySQL, PostgreSQL, socketmap and tcp, the value must be a +concatenation of the desired PEM keys and certificate chains, that +is then further encoded to yield a single-line base64 string. +Creation of such tables and secure storage (the value includes +private key material) are outside the responsibility of Postfix. </p> + +<p> With "socketmap" and "tcp" the data will be transmitted in the clear, and +there is no query access control, so these are generally unsuitable for storing +SNI chains. With LDAP and SQL, you should restrict read access and use TLS to +protect the sensitive data in transit. </p> + +<p> Typically there is only one private key and its chain of certificates +starting with the "leaf" certificate corresponding to that key, and +continuing with the appropriate intermediate issuer CA certificates, +with each certificate ideally followed by its issuer. Servers +that have keys and certificates for more than one algorithm (e.g. +both an RSA key and an ECDSA key, or even RSA, ECDSA and Ed25519) +can use multiple chains concatenated together, with the key always +listed before the corresponding certificates. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="tls_session_ticket_cipher">tls_session_ticket_cipher</a> (default: Postfix ≥ 3.0: aes-256-cbc, Postfix < 3.0: aes-128-cbc)</b></DT><DD> @@ -17981,18 +18958,36 @@ in its value are enabled (see openssl/ssl.h and SSL_CTX_set_options(3)). You can only enable options not already controlled by other Postfix settings. For example, you cannot disable protocols or enable server cipher preference. Do not attempt to turn all features by -specifying 0xFFFFFFFF, this is unlikely to be a good idea. </p> +specifying 0xFFFFFFFF, this is unlikely to be a good idea. Some +bug work-arounds are also valid here, allowing them to be re-enabled +if/when they're no longer enabled by default. The supported values +include: </p> <dl> +<dt><b>ENABLE_MIDDLEBOX_COMPAT</b></dt> <dd>Postfix ≥ 3.4. See +SSL_CTX_set_options(3).</dd> + <dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3).</dd> -<dt><b>NO_TICKET</b></dt> <dd>See SSL_CTX_set_options(3).</dd> +<dt><b>NO_TICKET</b></dt> <dd>Enabled by default when needed in +fully-patched Postfix ≥ 2.7. Not needed at all for Postfix ≥ +2.11, unless for some reason you do not want to support TLS session +resumption. Best not set explicitly. See SSL_CTX_set_options(3).</dd> <dt><b>NO_COMPRESSION</b></dt> <dd>Disable SSL compression even if supported by the OpenSSL library. Compression is CPU-intensive, and compression before encryption does not always improve security. </dd> +<dt><b>NO_RENEGOTIATION</b></dt> <dd>Postfix ≥ 3.4. This can +reduce opportunities for a potential CPU exhaustion attack. See +SSL_CTX_set_options(3).</dd> + +<dt><b>NO_SESSION_RESUMPTION_ON_RENEGOTIATION</b></dt> <dd>Postfix +≥ 3.4. See SSL_CTX_set_options(3).</dd> + +<dt><b>PRIORITIZE_CHACHA</b></dt> <dd>Postfix ≥ 3.4. See SSL_CTX_set_options(3).</dd> + </dl> <p> This feature is available in Postfix 2.11 and later. </p> @@ -18056,6 +19051,219 @@ of TLS. </p> </DD> +<DT><b><a name="tlsproxy_client_CAfile">tlsproxy_client_CAfile</a> +(default: $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>)</b></DT><DD> + +<p> A file containing CA certificates of root CAs trusted to sign +either remote TLS server certificates or intermediate CA certificates. +See <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_CApath">tlsproxy_client_CApath</a> +(default: $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a>)</b></DT><DD> + +<p> Directory with PEM format Certification Authority certificates +that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client uses to verify a remote TLS +server certificate. See <a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_cert_file">tlsproxy_client_cert_file</a> +(default: $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>)</b></DT><DD> + +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client RSA certificate in PEM +format. See <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"<a href="postconf.5.html#tlsproxy_client_chain_files">tlsproxy_client_chain_files</a>" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_chain_files">tlsproxy_client_chain_files</a> +(default: $<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>)</b></DT><DD> + +<p> Files with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client keys and certificate +chains in PEM format. See <a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_dcert_file">tlsproxy_client_dcert_file</a> +(default: $<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>)</b></DT><DD> + +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client DSA certificate in PEM +format. See <a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> for further details. DSA is obsolete and +should not be used. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_dkey_file">tlsproxy_client_dkey_file</a> +(default: $<a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a>)</b></DT><DD> + +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client DSA private key in PEM +format. See <a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> for further details. DSA is obsolete and +should not be used. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_eccert_file">tlsproxy_client_eccert_file</a> +(default: $<a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>)</b></DT><DD> + +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client ECDSA certificate in PEM +format. See <a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a> for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"<a href="postconf.5.html#tlsproxy_client_chain_files">tlsproxy_client_chain_files</a>" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_eckey_file">tlsproxy_client_eckey_file</a> +(default: $<a href="postconf.5.html#smtp_tls_eckey_file">smtp_tls_eckey_file</a>)</b></DT><DD> + +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client ECDSA private key in PEM +format. See <a href="postconf.5.html#smtp_tls_eckey_file">smtp_tls_eckey_file</a> for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"<a href="postconf.5.html#tlsproxy_client_chain_files">tlsproxy_client_chain_files</a>" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_enforce_tls">tlsproxy_client_enforce_tls</a> +(default: $<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>)</b></DT><DD> + +<p> Enforcement mode: require that SMTP servers use TLS encryption. +See <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_fingerprint_digest">tlsproxy_client_fingerprint_digest</a> +(default: $<a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a>)</b></DT><DD> + +<p> The message digest algorithm used to construct remote TLS server +certificate fingerprints. See <a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a> for +further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_key_file">tlsproxy_client_key_file</a> +(default: $<a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a>)</b></DT><DD> + +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client RSA private key in PEM +format. See <a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> for further details. The preferred way to +configure tlsproxy client keys and certificates is via the +"<a href="postconf.5.html#tlsproxy_client_chain_files">tlsproxy_client_chain_files</a>" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_loglevel">tlsproxy_client_loglevel</a> +(default: $<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a>)</b></DT><DD> + +<p> Enable additional Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client logging of TLS +activity. See <a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_loglevel_parameter">tlsproxy_client_loglevel_parameter</a> +(default: <a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a>)</b></DT><DD> + +<p> The name of the parameter that provides the <a href="postconf.5.html#tlsproxy_client_loglevel">tlsproxy_client_loglevel</a> +value. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_per_site">tlsproxy_client_per_site</a> +(default: $<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>)</b></DT><DD> + +<p> Optional lookup tables with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client TLS +usage policy by next-hop destination and by remote TLS server +hostname. See <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_policy_maps">tlsproxy_client_policy_maps</a> +(default: $<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>)</b></DT><DD> + +<p> Optional lookup tables with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> client TLS +security policy by next-hop destination. See <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> +for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_scert_verifydepth">tlsproxy_client_scert_verifydepth</a> +(default: $<a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a>)</b></DT><DD> + +<p> The verification depth for remote TLS server certificates. +See <a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_security_level">tlsproxy_client_security_level</a> +(default: $<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>)</b></DT><DD> + +<p> The default TLS security level for the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> +client. See <a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + +<DT><b><a name="tlsproxy_client_use_tls">tlsproxy_client_use_tls</a> +(default: $<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>)</b></DT><DD> + +<p> Opportunistic mode: use TLS when a remote server announces TLS +support. See <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="tlsproxy_enforce_tls">tlsproxy_enforce_tls</a> (default: $<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b></DT><DD> @@ -18143,13 +19351,26 @@ file. See <a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_ <p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server RSA certificate in PEM format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server -private RSA key. See <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> for further details. </p> +private RSA key. See <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> for further details. With +Postfix ≥ 3.4 the preferred way to configure tlsproxy server keys and +certificates is via the "<a href="postconf.5.html#tlsproxy_tls_chain_files">tlsproxy_tls_chain_files</a>" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> </DD> +<DT><b><a name="tlsproxy_tls_chain_files">tlsproxy_tls_chain_files</a> +(default: $<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>)</b></DT><DD> + +<p> Files with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server keys and certificate +chains in PEM format. See <a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a> for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + + +</DD> + <DT><b><a name="tlsproxy_tls_ciphers">tlsproxy_tls_ciphers</a> (default: $<a href="postconf.5.html#smtpd_tls_ciphers">smtpd_tls_ciphers</a>)</b></DT><DD> @@ -18167,8 +19388,8 @@ for further details. </p> <p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server DSA certificate in PEM format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server -private DSA key. See <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> for further details. -</p> +private DSA key. DSA is obsolete and should not be used. See +<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> for further details. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -18205,9 +19426,10 @@ result export-grade cipher suites are by default not used. </p> (default: $<a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a>)</b></DT><DD> <p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server DSA private key in PEM -format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> -server DSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>. -See <a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> for further details. </p> +format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server +DSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>. DSA is +obsolete and should not be used. See <a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> for further +details. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -18217,10 +19439,11 @@ See <a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> for fu <DT><b><a name="tlsproxy_tls_eccert_file">tlsproxy_tls_eccert_file</a> (default: $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>)</b></DT><DD> -<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server ECDSA certificate in -PEM format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> -server private ECDSA key. See <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a> for further -details. </p> +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server ECDSA certificate in PEM +format. This file may also contain the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server +private ECDSA key. See <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a> for further details. With +Postfix ≥ 3.4 the preferred way to configure tlsproxy server keys and +certificates is via the "<a href="postconf.5.html#tlsproxy_tls_chain_files">tlsproxy_tls_chain_files</a>" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -18230,10 +19453,12 @@ details. </p> <DT><b><a name="tlsproxy_tls_eckey_file">tlsproxy_tls_eckey_file</a> (default: $<a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a>)</b></DT><DD> -<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server ECDSA private key in -PEM format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> -server ECDSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. -See <a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a> for further details. </p> +<p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server ECDSA private key in PEM +format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server +ECDSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. See +<a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a> for further details. With Postfix ≥ 3.4 the +preferred way to configure tlsproxy server keys and certificates is via +the "<a href="postconf.5.html#tlsproxy_tls_chain_files">tlsproxy_tls_chain_files</a>" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -18281,9 +19506,11 @@ fingerprints. See <a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_t (default: $<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a>)</b></DT><DD> <p> File with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server RSA private key in PEM -format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> -server RSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>. -See <a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> for further details. </p> +format. This file may be combined with the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server +RSA certificate file specified with $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>. See +<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> for further details. With Postfix ≥ 3.4 the +preferred way to configure tlsproxy server keys and certificates is via +the "<a href="postconf.5.html#tlsproxy_tls_chain_files">tlsproxy_tls_chain_files</a>" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -18416,7 +19643,7 @@ cannot be set under 10s. </p> one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). </p> -<p> This feature is available in Postfix 2.8. </p> +<p> This feature is available in Postfix 2.8 and later </p> </DD> @@ -18871,7 +20098,7 @@ Do not change this unless you have a complete understanding of <a href="http://t (default: $<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b></DT><DD> <p> The Postfix SMTP server's action when <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> -fails due to an temporary error condition. Specify "defer" to defer +fails due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request diff --git a/external/ibm-public/postfix/dist/makedefs b/external/ibm-public/postfix/dist/makedefs index 8f7860110e3..93731c2afd3 100644 --- a/external/ibm-public/postfix/dist/makedefs +++ b/external/ibm-public/postfix/dist/makedefs @@ -1,5 +1,8 @@ #!/bin/sh +# To view the formatted manual page of this file, type: +# POSTFIXSOURCE/mantools/srctoman - makedefs | nroff -man + #++ # NAME # makedefs 1 @@ -13,21 +16,24 @@ # output stream that can be prepended to template Makefiles. # These macros implement an internal interface and are subject # to change without notice. -# +# NAME=VALUE OVERRIDES +# .ad +# .fi # Default settings can be overruled by specifying them as # environment variables (or as name=value pairs on the "make" # command line). Use quotes if variables contain whitespace # or shell meta characters. # -# The command "make makefiles name=value..." will replace the -# string MAIL_VERSION at the end of a parameter value with -# the Postfix release version. Do not try to specify something -# like $mail_version on this command line. This produces -# inconsistent results with different versions of the make(1) -# command. +# The command "\fBmake makefiles name=value...\fR" will replace +# the string \fBMAIL_VERSION\fR at the end of a value with the +# Postfix version (\fImajor.minor.patchlevel\fR for a stable +# release, \fImajor.minor-date\fR for a development release). +# Do not try to specify something like \fB$mail_version\fR: +# that produces inconsistent results with different implementations +# of the make(1) command. # .IP \fBAUXLIBS=\fIobject_library...\fR # Specifies one or more non-default object libraries. Postfix -# 2,12 and later specify some of their database library +# 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. @@ -54,11 +60,11 @@ # are known to support it. # .IP \fB-DNO_EAI\fR # Do not build with EAI (SMTPUTF8) support. By default, EAI -# support is compiled in when the "icuuc" library and header -# files are found. +# support is compiled in when the "pkg-config" command is +# found, or the deprecated "icu-config" command. # .IP \fB-DNO_INLINE\fR # Do not require support for C99 "inline" functions. Instead, -# implement argument typechecks for non-printf/scanf-like +# implement argument typechecks for non-(printf/scanf)-like # functions with ternary operators and unreachable code. # .IP \fB-DNO_IPV6\fR # Do not build with IPv6 support. @@ -66,7 +72,12 @@ # are known to have IPv6 support. # # Note: this directive is for debugging and testing only. It -# is not guaranteed to work on all platforms. +# is not guaranteed to work on all platforms. If you don't +# want IPv6 support, set "inet_protocols = ipv4" in main.cf. +# .IP \fB-DNO_IP_CYRUS_SASL_AUTH\fR +# Don't pass remote SMTP client and Postfix SMTP server IP +# address and port information to the Cyrus SASL library. +# This is compatible with Postfix < 3.2. # .IP \fB-DNO_KQUEUE\fR # Do not build with FreeBSD/NetBSD/OpenBSD/MacOSX KQUEUE support. # By default, KQUEUE support is compiled in on platforms that @@ -87,6 +98,9 @@ # Use setjmp()/longjmp() instead of sigsetjmp()/siglongjmp(). # By default, Postfix uses sigsetjmp()/siglongjmp() when they # appear to work. +# .IP \fB-DNO_SNPRINTF\fR +# Use sprintf() instead of snprintf(). By default, Postfix +# uses snprintf() except on ancient systems. # .RE # .IP \fBDEBUG=\fIdebug_level\fR # Specifies a non-default debugging level. The default is \fB-g\fR. @@ -94,6 +108,10 @@ # .IP \fBOPT=\fIoptimization_level\fR # Specifies a non-default optimization level. The default is \fB-O\fR. # Specify \fBOPT=\fR to turn off optimization. +# .IP \fBPOSTFIX_INSTALL_OPTS=\fI-option...\fR +# Specifies options for the postfix-install command, separated +# by whitespace. Currently, the only supported option is +# \fB-keep-build-mtime\fR. # .IP \fBSHLIB_CFLAGS=\fIflags\fR # Override the compiler flags (typically, "-fPIC") for Postfix # dynamically-linked libraries and database plugins. @@ -126,7 +144,6 @@ # This feature was introduced with Postfix 3.0. # .IP \fBpie=yes\fR # .IP \fBpie=no\fR -# # Enable (disable) Postfix builds with position-independent # executables, on platforms where this is supported. # @@ -272,6 +289,15 @@ case "$SYSTEM.$RELEASE" in : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"} : ${PLUGIN_LD="${CC} -shared"} ;; + FreeBSD.11*) SYSTYPE=FREEBSD11 + : ${CC=cc} + : ${SHLIB_SUFFIX=.so} + : ${SHLIB_CFLAGS=-fPIC} + : ${SHLIB_LD="${CC} -shared"' -Wl,-soname,${LIB}'} + : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'} + : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"} + : ${PLUGIN_LD="${CC} -shared"} + ;; DragonFly.*) SYSTYPE=DRAGONFLY ;; OpenBSD.2*) SYSTYPE=OPENBSD2 @@ -358,6 +384,10 @@ case "$SYSTEM.$RELEASE" in case $RELEASE in 5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP -DNO_POSIX_GETPW_R";; esac + # Solaris 2.6 added snprintf() + case $RELEASE in + 5.[0-5]) CCARGS="$CCARGS -DNO_SNPRINTF";; + esac # Solaris 8 added IPv6 and /dev/poll case $RELEASE in 5.[0-7]|5.[0-7].*) CCARGS="$CCARGS -DNO_IPV6 -DNO_DEVPOLL";; @@ -367,7 +397,11 @@ case "$SYSTEM.$RELEASE" in case $RELEASE in 5.[0-8]|5.[0-8].*) CCARGS="$CCARGS -DNO_CLOSEFROM -DNO_DEV_URANDOM -DNO_FUTIMESAT -DSTREAM_CONNECTIONS";; esac - # Somewhere NISPLUS went away. + # Solaris 10 added setenv(), unsetenv(). + case $RELEASE in + 5.[0-9]|5.[0-9].*) CCARGS="$CCARGS -DMISSING_SETENV";; + esac + # NISPLUS was removed after Solaris 10. case $RELEASE in 5.[0-9][0-9]*) CCARGS="$CCARGS -DNO_NISPLUS";; esac @@ -523,7 +557,7 @@ EOF : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"} : ${PLUGIN_LD="${CC-gcc} -shared"} ;; - Linux.[34].*) SYSTYPE=LINUX$RELEASE_MAJOR + Linux.[345].*) SYSTYPE=LINUX$RELEASE_MAJOR case "$CCARGS" in *-DNO_DB*) ;; *-DHAS_DB*) ;; @@ -610,7 +644,7 @@ EOF ;; HP-UX.A.09.*) SYSTYPE=HPUX9 SYSLIBS=-ldbm - CCARGS="$CCARGS -DMISSING_USLEEP" + CCARGS="$CCARGS -DMISSING_USLEEP -DNO_SNPRINTF" if [ -f /usr/lib/libdb.a ]; then CCARGS="$CCARGS -DHAS_DB" SYSLIBS="$SYSLIBS -ldb" @@ -619,6 +653,7 @@ HP-UX.A.09.*) SYSTYPE=HPUX9 HP-UX.B.10.*) SYSTYPE=HPUX10 CCARGS="$CCARGS `nm /usr/lib/libc.a 2>/dev/null | (grep usleep >/dev/null || echo '-DMISSING_USLEEP')`" + CCARGS="$CCARGS -DNO_SNPRINTF" if [ -f /usr/lib/libdb.a ]; then CCARGS="$CCARGS -DHAS_DB" SYSLIBS=-ldb @@ -756,9 +791,11 @@ esac # Look for the ICU library and enable unicode email if available. # case "$CCARGS" in -*-DNO_EAI*) ;; - *) icu_cppflags=`(icu-config --cppflags) 2>/dev/null` && { - icu_ldflags=`(icu-config --ldflags) 2>/dev/null` && { +*-DNO_EAI*) CCARGS="$CCARGS "'-DDEF_SMTPUTF8_ENABLE=\"no\"';; + *) icu_cppflags=`((pkg-config --cflags icu-uc icu-i18n) || + (icu-config --cppflags)) 2>/dev/null` && { + icu_ldflags=`((pkg-config --libs icu-uc icu-i18n) || + (icu-config --ldflags)) 2>/dev/null` && { trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15 cat >makedefs.test.c <<'EOF' #include <unicode/uidna.h> @@ -790,7 +827,7 @@ EOF fi rm -f makedefs.test makedefs.test.[co] } - } || CCARGS="$CCARGS -DNO_EAI" + } || CCARGS="$CCARGS -DNO_EAI"' -DDEF_SMTPUTF8_ENABLE=\"no\"' esac # @@ -1160,6 +1197,16 @@ case "$pie" in *) error "Specify \"pie=yes\" or \"pie=no\"";; esac +# Don't permit random overrides. +allowed_user_install_opts="-keep-build-mtime" +for opt in $POSTFIX_INSTALL_OPTS +do + (for allowed in -keep-build-mtime + do + test "$opt" = "$allowed" && exit 0 + done; exit 1) || error "invalid option '$opt' in POSTFIX_INSTALL_OPTS" +done + # Finally... sed 's/ */ /g' <<EOF @@ -1196,5 +1243,6 @@ PLUGIN_MAP_OBJ_UPDATE = $PLUGIN_MAP_OBJ_UPDATE PLUGIN_MAP_SO_MAKE = $PLUGIN_MAP_SO_MAKE PLUGIN_MAP_SO_UPDATE = $PLUGIN_MAP_SO_UPDATE PLUGIN_LD = $PLUGIN_LD +POSTFIX_INSTALL_OPTS = $POSTFIX_INSTALL_OPTS # Application-specific rules. EOF diff --git a/external/ibm-public/postfix/dist/man/man1/makedefs.1 b/external/ibm-public/postfix/dist/man/man1/makedefs.1 index 5dceadb69a8..9687836e285 100644 --- a/external/ibm-public/postfix/dist/man/man1/makedefs.1 +++ b/external/ibm-public/postfix/dist/man/man1/makedefs.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: makedefs.1,v 1.1.1.1 2020/03/18 18:59:30 christos Exp $ +.\" $NetBSD: makedefs.1,v 1.2 2020/03/18 19:05:14 christos Exp $ .\" .TH MAKEDEFS 1 .ad diff --git a/external/ibm-public/postfix/dist/man/man1/postalias.1 b/external/ibm-public/postfix/dist/man/man1/postalias.1 index aed5a8e2b29..aa41a02ef3c 100644 --- a/external/ibm-public/postfix/dist/man/man1/postalias.1 +++ b/external/ibm-public/postfix/dist/man/man1/postalias.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postalias.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postalias.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTALIAS 1 .ad @@ -87,6 +87,10 @@ Search the specified maps for \fIkey\fR and write the first value found to the standard output stream. The exit status is zero when the requested information was found. +Note: this performs a single query with the key as specified, +and does not make iterative queries with substrings of the +key as described in the aliases(5) manual page. + If a key value of \fB\-\fR is specified, the program reads key values from the standard input stream and writes one line of \fIkey: value\fR output for each key that was found. The exit @@ -153,7 +157,7 @@ The name of the alias database source file when creating a database. .ad .fi Problems are logged to the standard error stream and to -\fBsyslogd\fR(8). No output means that +\fBsyslogd\fR(8) or \fBpostlogd\fR(8). No output means that no problems were detected. Duplicate entries are skipped and are flagged with a warning. @@ -194,14 +198,18 @@ hash or btree tables. .IP "\fBdefault_database_type (see 'postconf -d' output)\fR" The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1) and \fBpostmap\fR(1) commands. +.IP "\fBimport_environment (see 'postconf -d' output)\fR" +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBsmtputf8_enable (yes)\fR" Enable preliminary SMTPUTF8 support for the protocols described in RFC 6531..6533. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .SH "STANDARDS" .na .nf @@ -215,6 +223,7 @@ postconf(1), supported database types postconf(5), configuration parameters postmap(1), create/update/query lookup tables newaliases(1), Sendmail compatibility interface. +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man1/postcat.1 b/external/ibm-public/postfix/dist/man/man1/postcat.1 index 5820cdd7874..aea59bea36f 100644 --- a/external/ibm-public/postfix/dist/man/man1/postcat.1 +++ b/external/ibm-public/postfix/dist/man/man1/postcat.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postcat.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postcat.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTCAT 1 .ad @@ -81,6 +81,10 @@ The text below provides only a parameter summary. See .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 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 +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top\-level queue directory. .SH "FILES" diff --git a/external/ibm-public/postfix/dist/man/man1/postconf.1 b/external/ibm-public/postfix/dist/man/man1/postconf.1 index 6e87ff4c788..5a76d43afdf 100644 --- a/external/ibm-public/postfix/dist/man/man1/postconf.1 +++ b/external/ibm-public/postfix/dist/man/man1/postconf.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postconf.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postconf.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTCONF 1 .ad @@ -87,14 +87,14 @@ Postfix configuration utility By default, the \fBpostconf\fR(1) command displays the values of \fBmain.cf\fR configuration parameters, and warns about possible mis\-typed parameter names (Postfix 2.9 and later). -It can also change \fBmain.cf\fR configuration +The command can also change \fBmain.cf\fR configuration parameter values, or display other configuration information about the Postfix mail system. Options: .IP \fB\-a\fR -List the available SASL server plug\-in types. The SASL -plug\-in type is selected with the \fBsmtpd_sasl_type\fR +List the available SASL plug\-in types for the Postfix SMTP +server. The plug\-in type is selected with the \fBsmtpd_sasl_type\fR configuration parameter by specifying one of the names listed below. .RS @@ -109,9 +109,9 @@ support. .IP This feature is available with Postfix 2.3 and later. .IP \fB\-A\fR -List the available SASL client plug\-in types. The SASL -plug\-in type is selected with the \fBsmtp_sasl_type\fR or -\fBlmtp_sasl_type\fR configuration parameters by specifying +List the available SASL plug\-in types for the Postfix SMTP +client. The plug\-in type is selected with the \fBsmtp_sasl_type\fR +or \fBlmtp_sasl_type\fR configuration parameters by specifying one of the names listed below. .RS .IP \fBcyrus\fR @@ -122,18 +122,14 @@ Cyrus SASL support. This feature is available with Postfix 2.3 and later. .IP "\fB\-b\fR [\fItemplate_file\fR]" Display the message text that appears at the beginning of -delivery status notification (DSN) messages, replacing +delivery status notification (DSN) messages, expanding $\fBname\fR expressions with actual values as described in \fBbounce\fR(5). -To override the built\-in templates, specify a template file -name at the end of the \fBpostconf\fR(1) command line, or -specify a file name in \fBmain.cf\fR with the -\fBbounce_template_file\fR parameter. - -To force selection of the built\-in templates, specify an -empty template file name on the \fBpostconf\fR(1) command -line (in shell language: ""). +To override the \fBbounce_template_file\fR parameter setting, +specify a template file name at the end of the "\fBpostconf +\-b\fR" 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. .IP "\fB\-c \fIconfig_dir\fR" @@ -175,7 +171,7 @@ command line. With \fB\-F\fR, edit the \fBmaster.cf\fR configuration file, and replace one or more service fields with new values as -specied with "\fIservice/type/field=value\fR" on the +specified with "\fIservice/type/field=value\fR" on the \fBpostconf\fR(1) command line. Currently, the "command" field contains the command name and command arguments. this may change in the near future, so that the "command" field @@ -184,7 +180,7 @@ pseudofield contains the command arguments. With \fB\-P\fR, edit the \fBmaster.cf\fR configuration file, and add or update one or more service parameter settings -(\-o parameter=value settings) with new values as specied +(\-o parameter=value settings) with new values as specified with "\fIservice/type/parameter=value\fR" on the \fBpostconf\fR(1) command line. @@ -253,20 +249,26 @@ with support for Berkeley DB databases. .IP \fBcdb\fR A read\-optimized structure with no support for incremental updates. Available on systems with support for CDB databases. + +This feature is available with Postfix 2.2 and later. .IP \fBcidr\fR A table that associates values with Classless Inter\-Domain Routing (CIDR) patterns. This is described in \fBcidr_table\fR(5). + +This feature is available with Postfix 2.2 and later. .IP \fBdbm\fR An indexed file type based on hashing. Available on systems with support for DBM databases. .IP \fBenviron\fR The UNIX process environment array. The lookup key is the -variable name. Originally implemented for testing, someone -may find this useful someday. +environment variable name; the table name is ignored. Originally +implemented for testing, someone may find this useful someday. .IP \fBfail\fR A table that reliably fails all requests. The lookup table name is used for logging. This table exists to simplify Postfix error tests. + +This feature is available with Postfix 2.9 and later. .IP \fBhash\fR An indexed file type based on hashing. Available on systems with support for Berkeley DB databases. @@ -274,10 +276,14 @@ with support for Berkeley DB databases. A non\-shared, in\-memory lookup table. Example: "\fBinline:{ \fIkey\fB=\fIvalue\fB, { \fIkey\fB = \fItext with whitespace or comma\fB }}\fR". Key\-value pairs are separated by -whitespace or comma; whitespace after "\fB{\fR" and before "\fB}\fR" -is ignored. Inline tables eliminate the need to create a +whitespace or comma; with a key\-value pair inside "\fB{}\fR", +whitespace is ignored after the opening "\fB{\fR", around +the "\fB=\fR" between key and value, and before the closing +"\fB}\fR". Inline tables eliminate the need to create a database file for just a few fixed elements. See also the \fIstatic:\fR map type. + +This feature is available with Postfix 3.0 and later. .IP \fBinternal\fR A non\-shared, in\-memory hash table. Its content are lost when a process terminates. @@ -285,11 +291,15 @@ when a process terminates. OpenLDAP LMDB database (a memory\-mapped, persistent file). Available on systems with support for LMDB databases. This is described in \fBlmdb_table\fR(5). + +This feature is available with Postfix 2.11 and later. .IP "\fBldap\fR (read\-only)" LDAP database client. This is described in \fBldap_table\fR(5). .IP "\fBmemcache\fR" Memcache database client. This is described in \fBmemcache_table\fR(5). + +This feature is available with Postfix 2.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). @@ -299,6 +309,8 @@ The file format is described in \fBpcre_table\fR(5). .IP "\fBpgsql\fR (read\-only)" PostgreSQL database client. This is described in \fBpgsql_table\fR(5). + +This feature is available with Postfix 2.1 and later. .IP "\fBpipemap\fR (read\-only)" A lookup table that constructs a pipeline of tables. Example: "\fBpipemap:{\fItype_1:name_1, ..., type_n:name_n\fB}\fR". @@ -310,9 +322,13 @@ produces no result. The first and last characters of the "pipemap:" table name must be "\fB{\fR" and "\fB}\fR". Within these, individual maps are separated with comma or whitespace. + +This feature is available with Postfix 3.0 and later. .IP "\fBproxy\fR" Postfix \fBproxymap\fR(8) client for shared access to Postfix databases. The table name syntax is \fItype\fB:\fIname\fR. + +This feature is available with Postfix 2.0 and later. .IP "\fBrandmap\fR (read\-only)" An in\-memory table that performs random selection. Example: "\fBrandmap:{\fIresult_1, ..., result_n\fB}\fR". Each table query @@ -321,26 +337,38 @@ and last characters of the "randmap:" table name must be "\fB{\fR" and "\fB}\fR". 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. .IP "\fBregexp\fR (read\-only)" A lookup table based on regular expressions. The file format is described in \fBregexp_table\fR(5). .IP \fBsdbm\fR An indexed file type based on hashing. Available on systems with support for SDBM databases. + +This feature is available with Postfix 2.2 and later. .IP "\fBsocketmap\fR (read\-only)" Sendmail\-style socketmap client. The table name is \fBinet\fR:\fIhost\fR:\fIport\fR:\fIname\fR for a TCP/IP server, or \fBunix\fR:\fIpathname\fR:\fIname\fR for a UNIX\-domain server. This is described in \fBsocketmap_table\fR(5). + +This feature is available with Postfix 2.10 and later. .IP "\fBsqlite\fR (read\-only)" SQLite database. This is described in \fBsqlite_table\fR(5). + +This feature is available with Postfix 2.8 and later. .IP "\fBstatic\fR (read\-only)" A table that always returns its name as lookup result. For example, \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup result. Specify "\fBstatic:{ \fItext with whitespace\fB }\fR" when the result contains whitespace; -this form ignores whitespace after "\fB{\fR" and before +this form ignores whitespace after the opening "\fB{\fR" +and before the closing "\fB}\fR". See also the \fIinline:\fR map. + +The form "\fBstatic:{\fItext\fB}\fR is available with Postfix +3.0 and later. .IP "\fBtcp\fR (read\-only)" TCP/IP client. The protocol is described in \fBtcp_table\fR(5). .IP "\fBtexthash\fR (read\-only)" @@ -348,10 +376,14 @@ Produces similar results as hash: files, except that you don't need to run the \fBpostmap\fR(1) command before you can use the file, and that it does not detect changes after the file is read. + +This feature is available with Postfix 2.8 and later. .IP "\fBunionmap\fR (read\-only)" 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 \fBpipemap\fR. + +This feature is available with Postfix 3.0 and later. .IP "\fBunix\fR (read\-only)" A limited view of the UNIX authentication database. The following tables are implemented: @@ -394,7 +426,13 @@ and "*" wildcard support was added with Postfix 2.11. Show only configuration parameters that have explicit \fIname=value\fR settings in \fBmain.cf\fR. Specify \fB\-nf\fR to fold long lines for human readability (Postfix 2.9 and -later). +later). To show settings that differ from built\-in defaults +only, use the following bash syntax: +.nf + comm \-23 <(postconf \-n) <(postconf \-d) +.fi +Replace "\-23" with "\-12" to show settings that duplicate +built\-in defaults. .IP "\fB\-o \fIname=value\fR" Override \fBmain.cf\fR parameter settings. @@ -421,14 +459,10 @@ Display the templates for text that appears at the beginning of delivery status notification (DSN) messages, without expanding $\fBname\fR expressions. -To override the built\-in templates, specify a template file -name at the end of the \fBpostconf\fR(1) command line, or -specify a file name in \fBmain.cf\fR with the -\fBbounce_template_file\fR parameter. - -To force selection of the built\-in templates, specify an -empty template file name on the \fBpostconf\fR(1) command -line (in shell language: ""). +To override the \fBbounce_template_file\fR parameter setting, +specify a template file name at the end of the "\fBpostconf +\-t\fR" 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. .IP "\fB\-T \fImode\fR" @@ -470,7 +504,7 @@ and remove one or more service entries as specified with With \fB\-P\fR, edit the \fBmaster.cf\fR configuration file, and remove one or more service parameter settings (\-o -parameter=value settings) as specied with +parameter=value settings) as specified with "\fIservice/type/parameter\fR" on the \fBpostconf\fR(1) command line. diff --git a/external/ibm-public/postfix/dist/man/man1/postdrop.1 b/external/ibm-public/postfix/dist/man/man1/postdrop.1 index 3b8eeb2e89d..c75f70b14f1 100644 --- a/external/ibm-public/postfix/dist/man/man1/postdrop.1 +++ b/external/ibm-public/postfix/dist/man/man1/postdrop.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postdrop.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postdrop.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTDROP 1 .ad @@ -42,7 +42,8 @@ it can connect to Postfix daemon processes. .ad .fi Fatal errors: malformed input, I/O error, out of memory. Problems -are logged to \fBsyslogd\fR(8) and to the standard error stream. +are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8) and to +the standard error stream. When the input is incomplete, or when the process receives a HUP, INT, QUIT or TERM signal, the queue file is deleted. .SH "ENVIRONMENT" @@ -72,21 +73,23 @@ The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. .IP "\fBalternate_config_directories (empty)\fR" A list of non\-default Postfix configuration directories that may -be specified with "\-c config_directory" on the command line, or -via the MAIL_CONFIG environment parameter. +be specified with "\-c config_directory" on the command line (in the +case of \fBsendmail\fR(1), with the "\-C" option), or via the MAIL_CONFIG +environment parameter. .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 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 Postfix process will -import from a non\-Postfix parent process. +The list of environment parameters 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" The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .IP "\fBtrigger_timeout (10s)\fR" The time limit for sending a trigger to a Postfix daemon (for example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon). @@ -104,6 +107,7 @@ command (and with the privileged \fBpostdrop\fR(1) helper command). .nf sendmail(1), compatibility interface postconf(5), configuration parameters +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man1/postfix.1 b/external/ibm-public/postfix/dist/man/man1/postfix.1 index bd340aad570..1a800ed953a 100644 --- a/external/ibm-public/postfix/dist/man/man1/postfix.1 +++ b/external/ibm-public/postfix/dist/man/man1/postfix.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postfix.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postfix.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTFIX 1 .ad @@ -39,6 +39,17 @@ and create missing directories. .IP \fBstart\fR Start the Postfix mail system. This also runs the configuration check described above. +.IP \fBstart\-fg\fR +Like \fBstart\fR, but keep the \fBmaster\fR(8) daemon running +in the foreground, and enable \fBmaster\fR(8) "init" mode +when running as PID 1. +This command requires that multi\-instance support is +disabled (i.e. the multi_instance_directories parameter +value must be empty). When running Postfix inside a container, +mount the container host's /dev/log socket inside the +container (example: "docker run \-v /dev/log:/dev/log ...") +and specify a distinct Postfix "syslog_name" prefix that +identifies logging from the Postfix instance. .IP \fBstop\fR Stop the Postfix mail system in an orderly fashion. If possible, running processes are allowed to terminate at @@ -74,6 +85,14 @@ already installed Postfix system. This feature is available in Postfix 2.1 and later. With Postfix 2.0 and earlier, use "\fB$config_directory/post\-install set\-permissions\fR". +.IP "\fBlogrotate\fR" +Rotate the logfile specified with $maillog_file, by appending +a time\-stamp suffix that is formatted according to +$maillog_file_rotate_suffix, and by compressing the file +with the command specified with $maillog_file_compressor. +This will not rotate /dev/* files. +.sp +This feature is available in Postfix 3.4 and later. .IP "\fBtls\fR \fIsubcommand\fR" Enable opportunistic TLS in the Postfix SMTP client or server, and manage Postfix SMTP server TLS private keys and @@ -127,6 +146,15 @@ commands that run as a descendant of the current process. This is set when the \-v command\-line option is present. .IP \fBMAIL_DEBUG\fR This is set when the \-D command\-line option is present. +.PP +When the internal logging service is enabled (by setting a +non\-empty maillog_file parameter value) the postfix(1) +command exports settings that are used by child processes +before they have processed main.cf or command\-line settings. +.IP \fBPOSTLOG_SERVICE +The name of the public postlog service endpoint. +.IP \fBPOSTLOG_HOSTNAME +The hostname to prepend to internal logging. .SH "CONFIGURATION PARAMETERS" .na .nf @@ -189,13 +217,14 @@ The location of the OpenSSL command line program \fBopenssl\fR(1). .PP Other configuration parameters: .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a Postfix process will -import from a non\-Postfix parent process. +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 2.6 and later: .IP "\fBmulti_instance_directories (empty)\fR" @@ -215,6 +244,21 @@ The optional instance name of this Postfix instance. .IP "\fBmulti_instance_enable (no)\fR" Allow this Postfix instance to be started, stopped, etc., by a multi\-instance manager. +.PP +Available in Postfix version 3.4 and later: +.IP "\fBmaillog_file (empty)\fR" +The name of an optional logfile that is written by the Postfix +\fBpostlogd\fR(8) service. +.IP "\fBmaillog_file_compressor (gzip)\fR" +The program to run after rotating $maillog_file with "postfix +logrotate". +.IP "\fBmaillog_file_prefixes (/var, /dev/stdout)\fR" +A list of allowed prefixes for a maillog_file value. +.IP "\fBmaillog_file_rotate_suffix (%Y%M%d\-%H%M%S)\fR" +The format of the suffix to append to $maillog_file while rotating +the file with "postfix logrotate". +.IP "\fBpostlog_service_name (postlog)\fR" +The name of the \fBpostlogd\fR(8) service entry in master.cf. .SH "FILES" .na .nf @@ -300,6 +344,7 @@ master(8), Postfix master daemon oqmgr(8), old Postfix queue manager pickup(8), Postfix local mail pickup pipe(8), deliver mail to non\-Postfix command +postlogd(8), Postfix internal logging service postscreen(8), Postfix zombie blocker proxymap(8), Postfix lookup table proxy server qmgr(8), Postfix queue manager diff --git a/external/ibm-public/postfix/dist/man/man1/postkick.1 b/external/ibm-public/postfix/dist/man/man1/postkick.1 index 9069faced10..866efed59d1 100644 --- a/external/ibm-public/postfix/dist/man/man1/postkick.1 +++ b/external/ibm-public/postfix/dist/man/man1/postkick.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postkick.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postkick.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTKICK 1 .ad @@ -67,6 +67,10 @@ configuration files. .IP "\fBapplication_event_drain_time (100s)\fR" 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 +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top\-level queue directory. .SH "FILES" diff --git a/external/ibm-public/postfix/dist/man/man1/postlock.1 b/external/ibm-public/postfix/dist/man/man1/postlock.1 index 494204fdfb4..7e43f2d110a 100644 --- a/external/ibm-public/postfix/dist/man/man1/postlock.1 +++ b/external/ibm-public/postfix/dist/man/man1/postlock.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postlock.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postlock.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTLOCK 1 .ad @@ -100,6 +100,10 @@ The delay between attempts to fork() a child process. .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 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 +process will import from a non\-Postfix parent process, or name=value +environment overrides. .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man1/postlog.1 b/external/ibm-public/postfix/dist/man/man1/postlog.1 index 2c3429fd8ec..1bd9e546618 100644 --- a/external/ibm-public/postfix/dist/man/man1/postlog.1 +++ b/external/ibm-public/postfix/dist/man/man1/postlog.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postlog.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postlog.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTLOG 1 .ad @@ -25,15 +25,18 @@ line as one record. If no \fItext\fR is specified on the command line, \fBpostlog\fR(1) reads from standard input and logs each input line as one record. -Logging is sent to \fBsyslogd\fR(8); when the standard error stream -is connected to a terminal, logging is sent there as well. +By default, logging is sent to \fBsyslogd\fR(8) or +\fBpostlogd\fR(8); when the +standard error stream is connected to a terminal, logging +is sent there as well. The following options are implemented: .IP "\fB\-c \fIconfig_dir\fR" Read the \fBmain.cf\fR configuration file in the named directory instead of the default configuration directory. -.IP \fB\-i\fR -Include the process ID in the logging tag. +.IP "\fB\-i\fR (obsolete)" +Include the process ID in the logging tag. This flag is ignored as +of Postfix 3.4, where the PID is always included. .IP "\fB\-p \fIpriority\fR (default: \fBinfo\fR)" Specifies the logging severity: \fBinfo\fR, \fBwarn\fR, \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1 @@ -67,16 +70,28 @@ The text below provides only a parameter summary. See .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 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 +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.4 and later: +.IP "\fBmaillog_file (empty)\fR" +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. .SH "SEE ALSO" .na .nf postconf(5), configuration parameters -syslogd(8), syslog daemon +postlogd(8), Postfix logging +syslogd(8), system logging .SH "LICENSE" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man1/postmap.1 b/external/ibm-public/postfix/dist/man/man1/postmap.1 index 73781f9ace1..a33f1525d83 100644 --- a/external/ibm-public/postfix/dist/man/man1/postmap.1 +++ b/external/ibm-public/postfix/dist/man/man1/postmap.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postmap.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postmap.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTMAP 1 .ad @@ -11,19 +11,14 @@ Postfix lookup table management .na .nf .fi -\fBpostmap\fR [\fB\-NbfhimnoprsuUvw\fR] [\fB\-c \fIconfig_dir\fR] +\fBpostmap\fR [\fB\-bfFhimnNoprsuUvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-d \fIkey\fR] [\fB\-q \fIkey\fR] [\fIfile_type\fR:]\fIfile_name\fR ... .SH DESCRIPTION .ad .fi The \fBpostmap\fR(1) command creates or queries one or more Postfix -lookup tables, or updates an existing one. The input and output -file formats are expected to be compatible with: - -.nf - \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR -.fi +lookup tables, or updates an existing one. If the result files do not exist they will be created with the same group and other read permissions as their source file. @@ -52,9 +47,20 @@ A logical line starts with non\-whitespace text. A line that starts with whitespace continues a logical line. .PP The \fIkey\fR and \fIvalue\fR are processed as is, except that -surrounding white space is stripped off. Unlike with Postfix alias -databases, quotes cannot be used to protect lookup keys that contain -special characters such as `#' or whitespace. +surrounding white space is stripped off. Whitespace in lookup +keys is supported as of Postfix 3.2. + +When the \fB\-F\fR option is given, the \fIvalue\fR must +specify one or more filenames separated by comma and/or +whitespace; \fBpostmap\fR(1) will concatenate the file +content (with a newline character inserted between files) +and will store the base64\-encoded result instead of the +\fIvalue\fR. + +When the \fIkey\fR specifies email address information, the +localpart should be enclosed with double quotes if required +by RFC 5322. For example, an address localpart that contains +";", or a localpart that starts or ends with ".". By default the lookup key is mapped to lowercase to make the lookups case insensitive; as of Postfix 2.3 this case @@ -72,7 +78,7 @@ information with $\fInumber\fR substitutions. .IP \fB\-b\fR Enable message body query mode. When reading lookup keys from standard input with "\fB\-q \-\fR", process the input -as if it is an email message in RFC 2822 format. Each line +as if it is an email message in RFC 5322 format. Each line of body content becomes one lookup key. .sp By default, the \fB\-b\fR option starts generating lookup @@ -106,10 +112,16 @@ a table. With Postfix version 2.3 and later, this option has no effect for regular expression tables. There, case folding is controlled by appending a flag to a pattern. +.IP \fB\-F\fR +When querying a map, or listing a map, base64\-decode each +value. When creating a map from source file, process each +value as a list of filenames, concatenate the content of +those files, and store the base64\-encoded result instead +of the value (see INPUT FORMAT for details). .IP \fB\-h\fR Enable message header query mode. When reading lookup keys from standard input with "\fB\-q \-\fR", process the input -as if it is an email message in RFC 2822 format. Each +as if it is an email message in RFC 5322 format. Each logical header line becomes one lookup key. A multi\-line header becomes one lookup key with one or more embedded newline characters. @@ -158,6 +170,11 @@ Search the specified maps for \fIkey\fR and write the first value found to the standard output stream. The exit status is zero when the requested information was found. +Note: this performs a single query with the key as specified, +and does not make iterative queries with substrings of the +key as described for access(5), canonical(5), transport(5), +virtual(5) and other Postfix table\-driven features. + If a key value of \fB\-\fR is specified, the program reads key values from the standard input stream and writes one line of \fIkey value\fR output for each key that was found. The exit @@ -227,7 +244,7 @@ The name of the lookup table source file when rebuilding a database. .ad .fi Problems are logged to the standard error stream and to -\fBsyslogd\fR(8). +\fBsyslogd\fR(8) or \fBpostlogd\fR(8). No output means that no problems were detected. Duplicate entries are skipped and are flagged with a warning. @@ -264,20 +281,25 @@ configuration files. .IP "\fBdefault_database_type (see 'postconf -d' output)\fR" The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1) and \fBpostmap\fR(1) commands. +.IP "\fBimport_environment (see 'postconf -d' output)\fR" +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBsmtputf8_enable (yes)\fR" Enable preliminary SMTPUTF8 support for the protocols described in RFC 6531..6533. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .SH "SEE ALSO" .na .nf postalias(1), create/update/query alias database postconf(1), supported database types postconf(5), configuration parameters +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man1/postmulti.1 b/external/ibm-public/postfix/dist/man/man1/postmulti.1 index 108160282fe..4c9fa9a5c16 100644 --- a/external/ibm-public/postfix/dist/man/man1/postmulti.1 +++ b/external/ibm-public/postfix/dist/man/man1/postmulti.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postmulti.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postmulti.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTMULTI 1 .ad @@ -23,10 +23,10 @@ Postfix multi\-instance manager [\fB\-i \fIname\fR] \fBpostmulti\fR \fB\-p\fR [\fB\-av\fR] [\fB\-g \fIgroup\fR] -[\fB\-i \fIname\fR] \fIcommand...\fR +[\fB\-i \fIname\fR] \fIpostfix\-command...\fR \fBpostmulti\fR \fB\-x\fR [\fB\-aRv\fR] [\fB\-g \fIgroup\fR] -[\fB\-i \fIname\fR] \fIcommand...\fR +[\fB\-i \fIname\fR] \fIunix\-command...\fR .ti -4 \fBLife\-cycle management:\fR @@ -117,8 +117,8 @@ This option cannot be used with \fB\-p\fR. List Postfix instances with their instance name, instance group name, enable/disable status and configuration directory. .SH "Postfix\-wrapper mode" -.IP \fB\-p\fR -Invoke \fBpostfix(1)\fR to execute the specified \fIcommand\fR. +.IP "\fB\-p \fIpostfix\-command\fR" +Invoke \fBpostfix(1)\fR to execute \fIpostfix\-command\fR. This option implements the \fBpostfix\-wrapper\fR(5) interface. .RS .IP \(bu @@ -148,8 +148,8 @@ invoke \fBpostmulti\fR(1) as follows: # postmulti \-g msa \-p start .RE .SH "Command mode" -.IP \fB\-x\fR -Execute the specified \fIcommand\fR for all Postfix instances. +.IP "\fB\-x \fIunix\-command\fR" +Execute the specified \fIunix\-command\fR for all Postfix instances. The command runs with appropriate environment settings for MAIL_CONFIG, command_directory, daemon_directory, config_directory, queue_directory, data_directory, @@ -344,8 +344,9 @@ configuration files. .IP "\fBdaemon_directory (see 'postconf -d' output)\fR" The directory with Postfix support programs and daemon programs. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a Postfix process will -import from a non\-Postfix parent process. +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBmulti_instance_directories (empty)\fR" An optional list of non\-default Postfix configuration directories; these directories belong to additional Postfix instances that share @@ -371,8 +372,8 @@ treats as "control" commands, that operate on running instances. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix 3.0 and later: .IP "\fBmeta_directory (see 'postconf -d' output)\fR" @@ -428,3 +429,8 @@ Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA + +Wietse Venema +Google, Inc. +111 8th Avenue +New York, NY 10011, USA diff --git a/external/ibm-public/postfix/dist/man/man1/postqueue.1 b/external/ibm-public/postfix/dist/man/man1/postqueue.1 index a9ded7246ba..10dc719fbf1 100644 --- a/external/ibm-public/postfix/dist/man/man1/postqueue.1 +++ b/external/ibm-public/postfix/dist/man/man1/postqueue.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postqueue.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postqueue.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTQUEUE 1 .ad @@ -81,6 +81,11 @@ selected for delivery. .IP \fB!\fR The message is in the \fBhold\fR queue, i.e. no further delivery attempt will be made until the mail is taken off hold. +.IP \fB#\fR +The message is forced to expire. See the \fBpostsuper\fR(1) +options \fB\-e\fR or \fB\-f\fR. +.sp +This feature is available in Postfix 3.5 and later. .RE .IP "\fB\-s \fIsite\fR" Schedule immediate delivery of all mail that is queued for the named @@ -126,6 +131,11 @@ The number of bytes in the message header and body. This number does not include message envelope information. It is approximately equal to the number of bytes that would be transmitted via SMTP including the <CR><LF> line endings. +.IP \fBforced_expire\fR +The message is forced to expire (\fBtrue\fR or \fBfalse\fR). +See the \fBpostsuper\fR(1) options \fB\-e\fR or \fB\-f\fR. +.sp +This feature is available in Postfix 3.5 and later. .IP \fBsender\fR The envelope sender address. .IP \fBrecipients\fR @@ -153,8 +163,8 @@ RFC 7159 (JSON notation) .SH DIAGNOSTICS .ad .fi -Problems are logged to \fBsyslogd\fR(8) and to the standard error -stream. +Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8), +and to the standard error stream. .SH "ENVIRONMENT" .na .nf @@ -182,8 +192,9 @@ The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. .IP "\fBalternate_config_directories (empty)\fR" A list of non\-default Postfix configuration directories that may -be specified with "\-c config_directory" on the command line, or -via the MAIL_CONFIG environment parameter. +be specified with "\-c config_directory" on the command line (in the +case of \fBsendmail\fR(1), with the "\-C" option), or via the MAIL_CONFIG +environment parameter. .IP "\fBconfig_directory (see 'postconf -d' output)\fR" The default location of the Postfix main.cf and master.cf configuration files. @@ -193,15 +204,16 @@ The location of all postfix administrative commands. Optional list of destinations that are eligible for per\-destination logfiles with mail that is queued to those destinations. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a Postfix process will -import from a non\-Postfix parent process. +The list of environment parameters 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" The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .IP "\fBtrigger_timeout (10s)\fR" The time limit for sending a trigger to a Postfix daemon (for example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon). @@ -223,6 +235,8 @@ showq(8), list mail queue flush(8), fast flush service sendmail(1), Sendmail\-compatible user interface postsuper(1), privileged queue operations +postlogd(8), Postfix logging +syslogd(8), system logging .SH "README FILES" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man1/postsuper.1 b/external/ibm-public/postfix/dist/man/man1/postsuper.1 index 35eca19d535..6a19eabee72 100644 --- a/external/ibm-public/postfix/dist/man/man1/postsuper.1 +++ b/external/ibm-public/postfix/dist/man/man1/postsuper.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: postsuper.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postsuper.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTSUPER 1 .ad @@ -12,7 +12,8 @@ Postfix superintendent .nf .fi \fBpostsuper\fR [\fB\-psSv\fR] -[\fB\-c \fIconfig_dir\fR] [\fB\-d \fIqueue_id\fR] + [\fB\-c \fIconfig_dir\fR] [\fB\-d \fIqueue_id\fR] + [\fB\-e \fIqueue_id\fR] [\fB\-f \fIqueue_id\fR] [\fB\-h \fIqueue_id\fR] [\fB\-H \fIqueue_id\fR] [\fB\-r \fIqueue_id\fR] [\fIdirectory ...\fR] .SH DESCRIPTION @@ -26,8 +27,9 @@ such as listing or flushing the mail queue. By default, \fBpostsuper\fR(1) performs the operations requested with the \fB\-s\fR and \fB\-p\fR command\-line options on all Postfix queue -directories \- this includes the \fBincoming\fR, \fBactive\fR and -\fBdeferred\fR directories with mail files and the \fBbounce\fR, +directories \- this includes the \fBincoming\fR, \fBactive\fR, +\fBdeferred\fR, and \fBhold\fR directories with message +files and the \fBbounce\fR, \fBdefer\fR, \fBtrace\fR and \fBflush\fR directories with log files. Options: @@ -40,16 +42,17 @@ Delete one message with the named queue ID from the named mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and \fBdeferred\fR). -If a \fIqueue_id\fR of \fB\-\fR is specified, the program reads -queue IDs from standard input. For example, to delete all mail +To delete multiple files, specify the \fB\-d\fR option multiple +times, or specify a \fIqueue_id\fR of \fB\-\fR to read queue IDs +from standard input. For example, to delete all mail with exactly one recipient \fBuser@example.com\fR: .sp .nf -mailq | tail +2 | grep \-v '^ *(' | awk \'BEGIN { RS = "" } +mailq | tail \-n +2 | grep \-v '^ *(' | awk 'BEGIN { RS = "" } # $7=sender, $8=recipient1, $9=recipient2 { if ($8 == "user@example.com" && $9 == "") print $1 } -\' | tr \-d '*!' | postsuper \-d \- + ' | tr \-d '*!' | postsuper \-d \- .fi .sp Specify "\fB\-d ALL\fR" to remove all messages; for example, specify @@ -79,14 +82,49 @@ can distinguish within a second). \fBpostsuper\fR(1) deletes the new message, instead of the old message that it should have deleted. .RE +.IP "\fB\-e \fIqueue_id\fR" +.IP "\fB\-f \fIqueue_id\fR" +Request forced expiration for one message with the named +queue ID in the named mail queue(s) (default: \fBhold\fR, +\fBincoming\fR, \fBactive\fR and \fBdeferred\fR). +.RS +.IP \(bu +The message will be returned to the sender when the queue +manager attempts to deliver that message (note that Postfix +will never deliver messages in the \fBhold\fR queue). +.IP \(bu +The \fB\-e\fR and \fB\-f\fR options both request forced +expiration. The difference is that \fB\-f\fR will also release +a message if it is in the \fBhold\fR queue. With \fB\-e\fR, such +a message would not be returned to the sender until it is +released with \fB\-f\fR or \fB\-H\fR. +.IP \(bu +When a deferred message is force\-expired, the return message +will state the reason for the delay. Otherwise, the reason +will be "message is administratively expired". +.RE +.IP +To expire multiple files, specify the \fB\-e\fR or \fB\-f\fR +option multiple times, or specify a \fIqueue_id\fR of \fB\-\fR +to read queue IDs from standard input (see the \fB\-d\fR option +above for an example, but be sure to replace \fB\-d\fR in +the example). +.sp +Specify "\fB\-e ALL\fR" or "\fB\-f ALL\fR" to expire all +messages; for example, specify "\fB\-e ALL deferred\fR" to +expire all mail in the \fBdeferred\fR queue. As a safety +measure, the word \fBALL\fR must be specified in upper case. +.sp +These features are available in Postfix 3.5 and later. .IP "\fB\-h \fIqueue_id\fR" Put mail "on hold" so that no attempt is made to deliver it. Move one message with the named queue ID from the named mail queue(s) (default: \fBincoming\fR, \fBactive\fR and \fBdeferred\fR) to the \fBhold\fR queue. -If a \fIqueue_id\fR of \fB\-\fR is specified, the program reads -queue IDs from standard input. +To hold multiple files, specify the \fB\-h\fR option multiple +times, or specify a \fIqueue_id\fR of \fB\-\fR to read queue IDs +from standard input. .sp Specify "\fB\-h ALL\fR" to hold all messages; for example, specify "\fB\-h ALL deferred\fR" to hold all mail in the \fBdeferred\fR queue. @@ -104,8 +142,9 @@ Release mail that was put "on hold". Move one message with the named queue ID from the named mail queue(s) (default: \fBhold\fR) to the \fBdeferred\fR queue. -If a \fIqueue_id\fR of \fB\-\fR is specified, the program reads -queue IDs from standard input. +To release multiple files, specify the \fB\-H\fR option multiple +times, or specify a \fIqueue_id\fR of \fB\-\fR to read queue IDs +from standard input. .sp Note: specify "\fBpostsuper \-r\fR" to release mail that was kept on hold for a significant fraction of \fB$maximal_queue_lifetime\fR @@ -119,15 +158,16 @@ This feature is available in Postfix 2.0 and later. .IP \fB\-p\fR Purge old temporary files that are left over after system or software crashes. +The \fB\-p\fR, \fB\-s\fR, and \fB\-S\fR operations are done +before other operations. .IP "\fB\-r \fIqueue_id\fR" Requeue the message with the named queue ID from the named mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and \fBdeferred\fR). -To requeue multiple messages, specify multiple \fB\-r\fR -command\-line options. -Alternatively, if a \fIqueue_id\fR of \fB\-\fR is specified, -the program reads queue IDs from standard input. +To requeue multiple files, specify the \fB\-r\fR option multiple +times, or specify a \fIqueue_id\fR of \fB\-\fR to read queue IDs +from standard input. .sp Specify "\fB\-r ALL\fR" to requeue all messages. As a safety measure, the word \fBALL\fR must be specified in upper case. @@ -167,6 +207,8 @@ This feature is available in Postfix 1.1 and later. .IP \fB\-s\fR Structure check and structure repair. This should be done once before Postfix startup. +The \fB\-p\fR, \fB\-s\fR, and \fB\-S\fR operations are done +before other operations. .RS .IP \(bu Rename files whose name does not match the message file inode @@ -201,6 +243,8 @@ A redundant version of \fB\-s\fR that requires that long file names also match the message file inode number. This option exists for testing purposes, and is available with Postfix 2.9 and later. +The \fB\-p\fR, \fB\-s\fR, and \fB\-S\fR operations are done +before other operations. .IP \fB\-v\fR Enable verbose logging for debugging purposes. Multiple \fB\-v\fR options make the software increasingly verbose. @@ -208,12 +252,16 @@ options make the software increasingly verbose. .ad .fi Problems are reported to the standard error stream and to -\fBsyslogd\fR(8). +\fBsyslogd\fR(8) or \fBpostlogd\fR(8). -\fBpostsuper\fR(1) reports the number of messages deleted with \fB\-d\fR, -the number of messages requeued with \fB\-r\fR, and the number of -messages whose queue file name was fixed with \fB\-s\fR. The report -is written to the standard error stream and to \fBsyslogd\fR(8). +\fBpostsuper\fR(1) reports the number of messages deleted +with \fB\-d\fR, the number of messages expired with \fB\-e\fR, +the number of messages expired or released with \fB\-f\fR, +the number of messages held or released with \fB\-h\fR or +\fB\-H\fR, the number of messages requeued with \fB\-r\fR, +and the number of messages whose queue file name was fixed +with \fB\-s\fR. The report is written to the standard error +stream and to \fBsyslogd\fR(8) or \fBpostlogd\fR(8). .SH "ENVIRONMENT" .na .nf @@ -244,13 +292,17 @@ the hash_queue_names parameter. .IP "\fBhash_queue_names (deferred, defer)\fR" 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 +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 2.9 and later: .IP "\fBenable_long_queue_ids (no)\fR" @@ -260,6 +312,8 @@ Enable long, non\-repeating, queue IDs (queue file names). .nf sendmail(1), Sendmail\-compatible user interface postqueue(1), unprivileged queue operations +postlogd(8), Postfix logging +syslogd(8), system logging .SH "LICENSE" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man1/posttls-finger.1 b/external/ibm-public/postfix/dist/man/man1/posttls-finger.1 index d8e9a2b50b3..63c65e88672 100644 --- a/external/ibm-public/postfix/dist/man/man1/posttls-finger.1 +++ b/external/ibm-public/postfix/dist/man/man1/posttls-finger.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: posttls-finger.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: posttls-finger.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTTLS-FINGER 1 .ad @@ -123,6 +123,16 @@ smtp_tls_mandatory_ciphers for details. .IP "\fB\-h \fIhost_lookup\fR (default: \fBdns\fR)" The hostname lookup methods used for the connection. See the documentation of smtp_host_lookup for syntax and semantics. +.IP "\fB\-H \fIchainfiles\fR (default: \fInone\fR)\fR" +List of files with a sequence PEM\-encoded TLS client certificate +chains. The list can be built\-up incrementally, by specifying +the option multiple times, or all at once via a comma or +whitespace separated list of filenames. Each chain starts with +a private key, which is followed immediately by the +corresponding certificate, and optionally by additional issuer +certificates. Each new key begins a new chain for the +corresponding algorithm. This option is mutually exclusive with +the below \fB\-k\fR and \fB\-K\fR options. .IP "\fB\-k \fIcertfile\fR (default: \fIkeyfile\fR)\fR" File with PEM\-encoded TLS client certificate chain. This defaults to \fIkeyfile\fR if one is specified. @@ -234,6 +244,12 @@ seconds. Report whether the session is re\-used. Retry if a new server is encountered, up to 5 times or as specified with the \fB\-m\fR option. By default reconnection is disabled, specify a positive delay to enable this behavior. +.IP "\fB\-s \fIservername\fR" +The server name to send with the TLS Server Name Indication (SNI) +extension. When the server has DANE TLSA records, this parameter +is ignored and the TLSA base domain is used instead. Otherwise, SNI is +not used by default, but can be enabled by specifying the desired value +with this option. .IP "\fB\-S\fR" Disable SMTP; that is, connect to an LMTP server. The default port for LMTP over TCP is 24. Alternative ports can specified by appending @@ -253,6 +269,9 @@ provided on port 465 by servers that are compatible with the ad\-hoc SMTP in SSL protocol, rather than the standard STARTTLS protocol. The destination \fIdomain\fR:\fIport\fR should of course provide such a service. +.IP "\fB\-X\fR" +Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode, +for program development only. .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]" Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default port is \fBsmtp\fR (or 24 with LMTP). With SMTP an MX lookup is @@ -317,4 +336,9 @@ IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA +Wietse Venema +Google, Inc. +111 8th Avenue +New York, NY 10011, USA + Viktor Dukhovni diff --git a/external/ibm-public/postfix/dist/man/man1/sendmail.1 b/external/ibm-public/postfix/dist/man/man1/sendmail.1 index cbdefdc48ad..d786b182efd 100644 --- a/external/ibm-public/postfix/dist/man/man1/sendmail.1 +++ b/external/ibm-public/postfix/dist/man/man1/sendmail.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: sendmail.1,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: sendmail.1,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SENDMAIL 1 .ad @@ -115,6 +115,11 @@ The path name of the Postfix \fBmain.cf\fR file, or of its parent directory. This information is ignored with Postfix versions before 2.3. +With Postfix version 3.2 and later, a non\-default directory +must be authorized in the default \fBmain.cf\fR file, through +the alternate_config_directories or multi_instance_directories +parameters. + With all Postfix versions, you can specify a directory pathname with the MAIL_CONFIG environment variable to override the location of configuration files. @@ -262,8 +267,8 @@ inputs. .SH DIAGNOSTICS .ad .fi -Problems are logged to \fBsyslogd\fR(8) and to the standard error -stream. +Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8), +and to the standard error stream. .SH "ENVIRONMENT" .na .nf @@ -303,7 +308,7 @@ line endings from <CR><LF> into UNIX format (<LF>). .nf .ad .fi -The DEBUG_README file gives examples of how to trouble shoot a +The DEBUG_README file gives examples of how to troubleshoot a Postfix system. .IP "\fBdebugger_command (empty)\fR" The external command to execute when a Postfix daemon program is @@ -390,6 +395,10 @@ and \fBpostmap\fR(1) commands. .IP "\fBdelay_warning_time (0h)\fR" The time after which the sender receives a copy of the message headers of mail that is still queued. +.IP "\fBimport_environment (see 'postconf -d' output)\fR" +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBmail_owner (postfix)\fR" The UNIX system account that owns the Postfix queue and most Postfix daemon processes. @@ -402,8 +411,21 @@ append the specified domain name to incomplete addresses. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Postfix 3.2 and later: +.IP "\fBalternate_config_directories (empty)\fR" +A list of non\-default Postfix configuration directories that may +be specified with "\-c config_directory" on the command line (in the +case of \fBsendmail\fR(1), with the "\-C" option), or via the MAIL_CONFIG +environment parameter. +.IP "\fBmulti_instance_directories (empty)\fR" +An optional list of non\-default Postfix configuration directories; +these directories belong to additional Postfix instances that share +the Postfix executable files and documentation with the default +Postfix instance, and that are started, stopped, etc., together +with the default Postfix instance. .SH "FILES" .na .nf @@ -421,6 +443,7 @@ postalias(1), create/update/query alias database postdrop(1), mail posting utility postfix(1), mail system control postqueue(1), mail queue control +postlogd(8), Postfix logging syslogd(8), system logging .SH "README_FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man5/access.5 b/external/ibm-public/postfix/dist/man/man5/access.5 index eca17f6bc59..979cb749cc4 100644 --- a/external/ibm-public/postfix/dist/man/man5/access.5 +++ b/external/ibm-public/postfix/dist/man/man5/access.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: access.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: access.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH ACCESS 5 .ad @@ -123,43 +123,33 @@ string \fBsmtpd_access_maps\fR is not listed in the Postfix .IP \fInet.work.addr\fR .IP \fInet.work\fR .IP \fInet\fR -Matches the specified IPv4 host address or subnetwork. An -IPv4 host address is a sequence of four decimal octets -separated by ".". +Matches a remote IPv4 host address or network address range. +Specify one to four decimal octets separated by ".". Do not +specify "[]" , "/", leading zeros, or hexadecimal forms. -Subnetworks are matched by repeatedly truncating the last -".octet" from the remote IPv4 host address string until a +Network ranges are matched by repeatedly truncating the last +".octet" from a remote IPv4 host address string, until a match is found in the access table, or until further truncation is not possible. -NOTE 1: The access map lookup key must be in canonical form: -do not specify unnecessary null characters, and do not -enclose network address information with "[]" characters. - -NOTE 2: use the \fBcidr\fR lookup table type to specify +NOTE: use the \fBcidr\fR lookup table type to specify network/netmask patterns. See \fBcidr_table\fR(5) for details. .IP \fInet:work:addr:ess\fR .IP \fInet:work:addr\fR .IP \fInet:work\fR .IP \fInet\fR -Matches the specified IPv6 host address or subnetwork. An -IPv6 host address is a sequence of three to eight hexadecimal -octet pairs separated by ":". - -Subnetworks are matched by repeatedly truncating the last -":octetpair" from the remote IPv6 host address string until -a match is found in the access table, or until further -truncation is not possible. - -NOTE 1: the truncation and comparison are done with the -string representation of the IPv6 host address. Thus, not -all the ":" subnetworks will be tried. +Matches a remote IPv6 host address or network address range. +Specify three to eight hexadecimal octet pairs separated +by ":", using the compressed form "::" for a sequence of +zero\-valued octet pairs. Do not specify "[]", "/", leading +zeros, or non\-compressed forms. -NOTE 2: The access map lookup key must be in canonical form: -do not specify unnecessary null characters, and do not -enclose network address information with "[]" characters. +A network range is matched by repeatedly truncating the +last ":octetpair" from the compressed\-form remote IPv6 host +address string, until a match is found in the access table, +or until further truncation is not possible. -NOTE 3: use the \fBcidr\fR lookup table type to specify +NOTE: use the \fBcidr\fR lookup table type to specify network/netmask patterns. See \fBcidr_table\fR(5) for details. IPv6 support is available in Postfix 2.2 and later. @@ -255,7 +245,8 @@ Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR, Send one copy of the message to the specified recipient. .sp If multiple BCC actions are specified within the same SMTP -MAIL transaction, only the last action will be used. +MAIL transaction, with Postfix 3.0 only the last action +will be used. .sp This feature is available in Postfix 3.0 and later. .IP "\fBDISCARD \fIoptional text...\fR diff --git a/external/ibm-public/postfix/dist/man/man5/aliases.5 b/external/ibm-public/postfix/dist/man/man5/aliases.5 index 354ec4967e6..27ef08a55e4 100644 --- a/external/ibm-public/postfix/dist/man/man5/aliases.5 +++ b/external/ibm-public/postfix/dist/man/man5/aliases.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: aliases.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: aliases.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH ALIASES 5 .ad @@ -58,9 +58,12 @@ Use double quotes when the name contains any special characters such as whitespace, `#', `:', or `@'. The \fIname\fR is folded to lowercase, in order to make database lookups case insensitive. .PP -In addition, when an alias exists for \fBowner\-\fIname\fR, delivery -diagnostics are directed to that address, instead of to the originator -of the message. +In addition, when an alias exists for \fBowner\-\fIname\fR, +this will override the envelope sender address, so that +delivery diagnostics are directed to \fBowner\-\fIname\fR, +instead of the originator of the message (for details, see +\fBowner_request_special\fR, \fBexpand_owner_alias\fR and +\fBreset_owner_alias\fR). 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. @@ -157,37 +160,37 @@ agent will terminate with a fatal error. The following \fBmain.cf\fR parameters are especially relevant. The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. -.IP \fBalias_database\fR -List of alias databases that are updated by the -\fBnewaliases\fR(1) command. -.IP \fBalias_maps\fR -List of alias databases queried by the \fBlocal\fR(8) delivery agent. -.IP \fBallow_mail_to_commands\fR -Restrict the usage of mail delivery to external command. -.IP \fBallow_mail_to_files\fR -Restrict the usage of mail delivery to external file. -.IP \fBexpand_owner_alias\fR -When delivering to an alias that has an \fBowner\-\fR companion alias, -set the envelope sender address to the right\-hand side of the -owner alias, instead using of the left\-hand side address. -.IP \fBpropagate_unmatched_extensions\fR -A list of address rewriting or forwarding mechanisms that -propagate an address extension from the original address -to the result. Specify zero or more of \fBcanonical\fR, -\fBvirtual\fR, \fBalias\fR, \fBforward\fR, \fBinclude\fR, -or \fBgeneric\fR. -.IP \fBowner_request_special\fR -Give special treatment to \fBowner\-\fIlistname\fR and -\fIlistname\fB\-request\fR -addresses. -.IP \fBrecipient_delimiter\fR -Delimiter that separates recipients from address extensions. +.IP "\fBalias_database (see 'postconf -d' output)\fR" +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. +.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" +Restrict \fBlocal\fR(8) mail delivery to external files. +.IP "\fBexpand_owner_alias (no)\fR" +When delivering to an alias "\fIaliasname\fR" that has an +"owner\-\fIaliasname\fR" companion alias, set the envelope sender +address to the expansion of the "owner\-\fIaliasname\fR" alias. +.IP "\fBpropagate_unmatched_extensions (canonical, virtual)\fR" +What address lookup tables copy an address extension from the lookup +key to the lookup result. +.IP "\fBowner_request_special (yes)\fR" +Enable special treatment for owner\-\fIlistname\fR entries in the +\fBaliases\fR(5) file, and don't split owner\-\fIlistname\fR and +\fIlistname\fR\-request address localparts when the recipient_delimiter +is set to "\-". +.IP "\fBrecipient_delimiter (empty)\fR" +The set of characters that can separate a user name from its +extension (example: user+foo), or a .forward file name from its +extension (example: .forward+foo). .PP Available in Postfix version 2.3 and later: -.IP \fBfrozen_delivered_to\fR -Update the local(8) delivery agent's Delivered\-To: address -(see prepend_delivered_header) only once, at the start of -a delivery; do not update the Delivered\-To: address while +.IP "\fBfrozen_delivered_to (yes)\fR" +Update the \fBlocal\fR(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. .SH "STANDARDS" .na diff --git a/external/ibm-public/postfix/dist/man/man5/canonical.5 b/external/ibm-public/postfix/dist/man/man5/canonical.5 index 70eb7177619..69a514057d6 100644 --- a/external/ibm-public/postfix/dist/man/man5/canonical.5 +++ b/external/ibm-public/postfix/dist/man/man5/canonical.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: canonical.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: canonical.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH CANONICAL 5 .ad @@ -90,8 +90,12 @@ starts with whitespace continues a logical line. .ad .fi 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: +tables such as NIS, LDAP or SQL, each \fIuser\fR@\fIdomain\fR +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. .IP "\fIuser\fR@\fIdomain address\fR" Replace \fIuser\fR@\fIdomain\fR by \fIaddress\fR. This form has the highest precedence. @@ -118,6 +122,23 @@ 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. +.sp +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: + +.nf + smtpd_recipient_restrictions = + ... + reject_unauth_destination + check_recipient_access + inline:{example.com=reject_unverified_recipient} + unverified_recipient_reject_code = 550 +.fi + +In the above example, Postfix may contact a remote server +if the recipient is rewritten to a remote address. .SH "RESULT ADDRESS REWRITING" .na .nf @@ -195,56 +216,58 @@ The table format does not understand quoting conventions. The following \fBmain.cf\fR parameters are especially relevant. The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. -.IP \fBcanonical_classes\fR -What addresses are subject to canonical address mapping. -.IP \fBcanonical_maps\fR -List of canonical mapping tables. -.IP \fBrecipient_canonical_maps\fR -Address mapping lookup table for envelope and header recipient -addresses. -.IP \fBsender_canonical_maps\fR -Address mapping lookup table for envelope and header sender -addresses. -.IP \fBpropagate_unmatched_extensions\fR -A list of address rewriting or forwarding mechanisms that propagate -an address extension from the original address to the result. -Specify zero or more of \fBcanonical\fR, \fBvirtual\fR, \fBalias\fR, -\fBforward\fR, \fBinclude\fR, or \fBgeneric\fR. +.IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR" +What addresses are subject to canonical_maps address mapping. +.IP "\fBcanonical_maps (empty)\fR" +Optional address mapping lookup tables for message headers and +envelopes. +.IP "\fBrecipient_canonical_maps (empty)\fR" +Optional address mapping lookup tables for envelope and header +recipient addresses. +.IP "\fBsender_canonical_maps (empty)\fR" +Optional address mapping lookup tables for envelope and header +sender addresses. +.IP "\fBpropagate_unmatched_extensions (canonical, virtual)\fR" +What address lookup tables copy an address extension from the lookup +key to the lookup result. .PP Other parameters of interest: -.IP \fBinet_interfaces\fR -The network interface addresses that this system receives mail on. -You need to stop and start Postfix when this parameter changes. -.IP \fBlocal_header_rewrite_clients\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. -.IP \fBproxy_interfaces\fR -Other interfaces that this machine receives mail on by way of a -proxy agent or network address translator. -.IP \fBmasquerade_classes\fR -List of address classes subject to masquerading: zero or more of -\fBenvelope_sender\fR, \fBenvelope_recipient\fR, \fBheader_sender\fR, -\fBheader_recipient\fR. -.IP \fBmasquerade_domains\fR -List of domains that hide their subdomain structure. -.IP \fBmasquerade_exceptions\fR -List of user names that are not subject to address masquerading. -.IP \fBmydestination\fR -List of domains that this mail system considers local. -.IP \fBmyorigin\fR -The domain that is appended to locally\-posted mail. -.IP \fBowner_request_special\fR -Give special treatment to \fBowner\-\fIxxx\fR and \fIxxx\fB\-request\fR -addresses. -.IP \fBremote_header_rewrite_domain\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. +.IP "\fBinet_interfaces (all)\fR" +The 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. +.IP "\fBproxy_interfaces (empty)\fR" +The 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. +.IP "\fBmasquerade_domains (empty)\fR" +Optional list of domains whose subdomain structure will be stripped +off in email addresses. +.IP "\fBmasquerade_exceptions (empty)\fR" +Optional list of user names that are not subjected to address +masquerading, even when their address matches $masquerade_domains. +.IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" +The list of domains that are delivered via the $local_transport +mail delivery transport. +.IP "\fBmyorigin ($myhostname)\fR" +The domain name that locally\-posted mail appears to come +from, and that locally posted mail is delivered to. +.IP "\fBowner_request_special (yes)\fR" +Enable special treatment for owner\-\fIlistname\fR entries in the +\fBaliases\fR(5) file, and don't split owner\-\fIlistname\fR and +\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. .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man5/cidr_table.5 b/external/ibm-public/postfix/dist/man/man5/cidr_table.5 index b0bce3cb49f..ba915e57941 100644 --- a/external/ibm-public/postfix/dist/man/man5/cidr_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/cidr_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: cidr_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: cidr_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH CIDR_TABLE 5 .ad @@ -35,30 +35,42 @@ described in the SYNOPSIS above. .ad .fi The general form of a Postfix CIDR table is: -.IP "\fInetwork_address\fB/\fInetwork_mask result\fR" -When a search string matches the specified network block, -use the corresponding \fIresult\fR value. Specify -0.0.0.0/0 to match every IPv4 address, and ::/0 to match -every IPv6 address. - -An IPv4 network address is a sequence of four decimal octets -separated by ".", and an IPv6 network address is a sequence -of three to eight hexadecimal octet pairs separated by ":". - -The \fInetwork_mask\fR is the number of high\-order bits in -the \fInetwork_address\fR that the search string must match. - -Before comparisons are made, lookup keys and table entries -are converted from string to binary. Therefore table entries -will be matched regardless of redundant zero characters. - -Note: address information may be enclosed inside "[]" but -this form is not required. - -IPv6 support is available in Postfix 2.2 and later. -.IP "\fInetwork_address result\fR" -When a search string matches the specified network address, -use the corresponding \fIresult\fR value. +.IP "\fIpattern result\fR" +When a search string matches the specified \fIpattern\fR, use +the corresponding \fIresult\fR value. The \fIpattern\fR must be +in \fInetwork/prefix\fR or \fInetwork_address\fR form (see +ADDRESS PATTERN SYNTAX below). +.IP "\fB!\fIpattern result\fR" +When a search string does not match the specified \fIpattern\fR, +use the specified \fIresult\fR value. The \fIpattern\fR must +be in \fInetwork/prefix\fR or \fInetwork_address\fR form (see +ADDRESS PATTERN SYNTAX below). +.sp +This feature is available in Postfix 3.2 and later. +.IP "\fBif \fIpattern\fR" +.IP "\fBendif\fR" +When a search string matches the specified \fIpattern\fR, match +that search string against the patterns between \fBif\fR and +\fBendif\fR. The \fIpattern\fR must be in \fInetwork/prefix\fR or +\fInetwork_address\fR form (see ADDRESS PATTERN SYNTAX below). The +\fBif\fR..\fBendif\fR can nest. +.sp +Note: do not prepend whitespace to text between +\fBif\fR..\fBendif\fR. +.sp +This feature is available in Postfix 3.2 and later. +.IP "\fBif !\fIpattern\fR" +.IP "\fBendif\fR" +When a search string does not match the specified \fIpattern\fR, +match that search string against the patterns between \fBif\fR and +\fBendif\fR. The \fIpattern\fR must be in \fInetwork/prefix\fR or +\fInetwork_address\fR form (see ADDRESS PATTERN SYNTAX below). The +\fBif\fR..\fBendif\fR can nest. +.sp +Note: do not prepend whitespace to text between +\fBif\fR..\fBendif\fR. +.sp +This feature is available in Postfix 3.2 and later. .IP "blank lines and comments" Empty lines and whitespace\-only lines are ignored, as are lines whose first non\-whitespace character is a `#'. @@ -72,6 +84,34 @@ starts with whitespace continues a logical line. .fi Patterns are applied in the order as specified in the table, until a pattern is found that matches the search string. +.SH "ADDRESS PATTERN SYNTAX" +.na +.nf +.ad +.fi +Postfix CIDR tables are pattern\-based. A pattern is either +a \fInetwork_address\fR which requires an exact match, or a +\fInetwork_address/prefix_length\fR where the \fIprefix_length\fR +part specifies the length of the \fInetwork_address\fR prefix +that must be matched (the other bits in the \fInetwork_address\fR +part must be zero). + +An IPv4 network address is a sequence of four decimal octets +separated by ".", and an IPv6 network address is a sequence +of three to eight hexadecimal octet pairs separated by ":" +or "::", where the latter is short\-hand for a sequence of +one or more all\-zero octet pairs. The pattern 0.0.0.0/0 +matches every IPv4 address, and ::/0 matches every IPv6 +address. IPv6 support is available in Postfix 2.2 and +later. + +Before comparisons are made, lookup keys and table entries +are converted from string to binary. Therefore, IPv6 patterns +will be matched regardless of leading zeros (a leading zero in +an IPv4 address octet indicates octal notation). + +Note: address information may be enclosed inside "[]" but +this form is not required. .SH "EXAMPLE SMTPD ACCESS MAP" .na .nf @@ -84,6 +124,8 @@ pattern is found that matches the search string. # before more general blacklist entries. 192.168.1.1 OK 192.168.0.0/16 REJECT + 2001:db8::1 OK + 2001:db8::/32 REJECT .fi .SH "SEE ALSO" .na diff --git a/external/ibm-public/postfix/dist/man/man5/generic.5 b/external/ibm-public/postfix/dist/man/man5/generic.5 index dce6325cd36..d98e85ca70d 100644 --- a/external/ibm-public/postfix/dist/man/man5/generic.5 +++ b/external/ibm-public/postfix/dist/man/man5/generic.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: generic.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: generic.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH GENERIC 5 .ad @@ -82,8 +82,12 @@ starts with whitespace continues a logical line. .ad .fi 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: +tables such as NIS, LDAP or SQL, each \fIuser\fR@\fIdomain\fR +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. .IP "\fIuser\fR@\fIdomain address\fR" Replace \fIuser\fR@\fIdomain\fR by \fIaddress\fR. This form has the highest precedence. diff --git a/external/ibm-public/postfix/dist/man/man5/header_checks.5 b/external/ibm-public/postfix/dist/man/man5/header_checks.5 index 1e5586aa539..ef9b603a560 100644 --- a/external/ibm-public/postfix/dist/man/man5/header_checks.5 +++ b/external/ibm-public/postfix/dist/man/man5/header_checks.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: header_checks.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: header_checks.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH HEADER_CHECKS 5 .ad @@ -284,13 +284,25 @@ This feature is available in Postfix 2.0 and later. This feature is not supported with smtp header/body checks. .IP \fBIGNORE\fR Delete the current line from the input, and inspect -the next input line. +the next input line. See \fBSTRIP\fR for an alternative +that logs the action. .IP "\fBINFO \fIoptional text...\fR Log an "info:" record with the \fIoptional text...\fR (or log a generic text), and inspect the next input line. This action is useful for routine logging or for debugging. .sp This feature is available in Postfix 2.8 and later. +.IP "\fBPASS \fIoptional text...\fR" +Log a "pass:" record with the \fIoptional text...\fR (or +log a generic text), and turn off header, body, and Milter +inspection for the remainder of this message. +.sp +Note: this feature relies on trust in information that is +easy to forge. +.sp +This feature is available in Postfix 3.2 and later. +.sp +This feature is not supported with smtp header/body checks. .IP "\fBPREPEND \fItext...\fR" Prepend one line with the specified text, and inspect the next input line. @@ -361,6 +373,13 @@ text...\fR, Postfix inserts a default enhanced status code of "5.7.1". .sp This feature is not supported with smtp header/body checks. +.IP "\fBSTRIP \fIoptional text...\fR" +Log a "strip:" record with the \fIoptional text...\fR (or +log a generic text), delete the input line from the input, +and inspect the next input line. See \fBIGNORE\fR for a +silent alternative. +.sp +This feature is available in Postfix 3.2 and later. .IP "\fBWARN \fIoptional text...\fR Log a "warning:" record with the \fIoptional text...\fR (or log a generic text), and inspect the next input line. This diff --git a/external/ibm-public/postfix/dist/man/man5/ldap_table.5 b/external/ibm-public/postfix/dist/man/man5/ldap_table.5 index cdfe16483cd..798bc4a33d5 100644 --- a/external/ibm-public/postfix/dist/man/man5/ldap_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/ldap_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: ldap_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: ldap_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH LDAP_TABLE 5 .ad @@ -34,35 +34,11 @@ the Postfix main.cf file, and can specify the parameters described below. An example is given at the end of this manual. This configuration method is available with Postfix version -2.1 and later. See the section "BACKWARDS COMPATIBILITY" +2.1 and later. See the section "OBSOLETE MAIN.CF PARAMETERS" below for older Postfix versions. For details about LDAP SSL and STARTTLS, see the section on SSL and STARTTLS below. -.SH "BACKWARDS COMPATIBILITY" -.na -.nf -.ad -.fi -For backwards compatibility with Postfix version 2.0 and earlier, -LDAP parameters can also be defined in main.cf. Specify -as LDAP source a name that doesn't begin with a slash or -a dot. The LDAP 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 "ldap:\fIldapsource\fR", the "server_host" -parameter below would be defined in main.cf as -"\fIldapsource\fR_server_host". - -Note: with this form, the passwords for the LDAP sources are -written in main.cf, which is normally world\-readable. Support -for this form will be removed in a future Postfix version. - -For backwards compatibility with the pre -2.2 LDAP clients, \fBresult_filter\fR can for now be used instead -of \fBresult_format\fR, when the latter parameter is not also set. -The new name better reflects the function of the parameter. This -compatibility interface may be removed in a future release. .SH "LIST MEMBERSHIP" .na .nf @@ -704,6 +680,34 @@ whose mailacceptinggeneralid attribute is "ldapuser", read the "maildrop" attributes of those found, and build a list of their maildrops, which will be treated as RFC822 addresses to which the message will be delivered. +.SH "OBSOLETE MAIN.CF PARAMETERS" +.na +.nf +.ad +.fi +For backwards compatibility with Postfix version 2.0 and earlier, +LDAP parameters can also be defined in main.cf. Specify +as LDAP source a name that doesn't begin with a slash or +a dot. The LDAP 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 "ldap:\fIldapsource\fR", the "server_host" +parameter below would be defined in main.cf as +"\fIldapsource\fR_server_host". + +Note: with this form, the passwords for the LDAP sources are +written in main.cf, which is normally world\-readable. Support +for this form will be removed in a future Postfix version. +.SH "OTHER OBSOLETE FEATURES" +.na +.nf +.ad +.fi +For backwards compatibility with the pre +2.2 LDAP clients, \fBresult_filter\fR can for now be used instead +of \fBresult_format\fR, when the latter parameter is not also set. +The new name better reflects the function of the parameter. This +compatibility interface may be removed in a future release. .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man5/master.5 b/external/ibm-public/postfix/dist/man/man5/master.5 index e5644c332a8..a8bd96630a0 100644 --- a/external/ibm-public/postfix/dist/man/man5/master.5 +++ b/external/ibm-public/postfix/dist/man/man5/master.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: master.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: master.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH MASTER 5 .ad @@ -69,8 +69,8 @@ via the network. The service name is specified as \fIhost:port\fR, denoting the host and port on which new connections should be accepted. The host part (and colon) may be omitted. Either -host or port may be given in symbolic form (host or service -name) or in numeric form (IP address or port number). +host or port may be given in symbolic form (see \fBhosts\fR(5) or +\fBservices\fR(5)) or in numeric form (IP address or port number). Host information may be enclosed inside "[]"; this form is necessary only with IPv6 addresses. .sp @@ -87,8 +87,8 @@ Note: with Postfix version 2.2 and later specify of hard\-coding loopback IP address information in master.cf or in main.cf. .IP \fBunix\fR -The service listens on a UNIX\-domain socket and is accessible -for local clients only. +The service listens on a UNIX\-domain stream socket and is +accessible for local clients only. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the \fBqueue_directory\fR @@ -96,7 +96,14 @@ configuration parameter in main.cf). .sp On Solaris 8 and earlier systems the \fBunix\fR type is implemented with streams sockets. -.IP \fBfifo\fR +.IP \fBunix\-dgram\fR +The service listens on a UNIX\-domain datagram socket and is +accessible for local clients only. + +The service name is a pathname relative to the Postfix +queue directory (pathname controlled with the \fBqueue_directory\fR +configuration parameter in main.cf). +.IP "\fBfifo\fR (obsolete)" The service listens on a FIFO (named pipe) and is accessible for local clients only. @@ -104,9 +111,9 @@ The service name is a pathname relative to the Postfix queue directory (pathname controlled with the \fBqueue_directory\fR configuration parameter in main.cf). .IP \fBpass\fR -The service listens on a UNIX\-domain socket, and is accessible -to local clients only. It receives one open connection (file -descriptor passing) per connection request. +The service listens on a UNIX\-domain stream socket, and is +accessible to local clients only. It receives one open +connection (file descriptor passing) per connection request. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the \fBqueue_directory\fR @@ -141,7 +148,7 @@ most of the purpose of having that service in the first place. .sp The files in the examples/chroot\-setup subdirectory of the -Postfix source archive show set up a Postfix chroot environment +Postfix source show how to set up a Postfix chroot environment on a variety of systems. See also BASIC_CONFIGURATION_README for issues related to running daemons chrooted. .IP "\fBWake up time (default: 0)\fR" diff --git a/external/ibm-public/postfix/dist/man/man5/mysql_table.5 b/external/ibm-public/postfix/dist/man/man5/mysql_table.5 index 03c70d0f5ee..b51c10f95b1 100644 --- a/external/ibm-public/postfix/dist/man/man5/mysql_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/mysql_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: mysql_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: mysql_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH MYSQL_TABLE 5 .ad @@ -30,43 +30,6 @@ table in main.cf, for example: The file /etc/postfix/mysql\-aliases.cf has the same format as the Postfix main.cf file, and can specify the parameters described below. -.SH "BACKWARDS COMPATIBILITY" -.na -.nf -.ad -.fi -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:\fImysqlname\fR", the parameter "hosts" -below would be defined in main.cf as "\fImysqlname\fR_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 will be removed in a future Postfix version. - -Normally, the SQL query is specified via a single \fBquery\fR -parameter (described in more detail below). When this -parameter is not specified in the map definition, Postfix -reverts to an older interface, with the SQL query constructed -from the \fBselect_field\fR, \fBtable\fR, \fBwhere_field\fR -and \fBadditional_conditions\fR parameters. The old interface -will be gradually phased out. To migrate to the new interface -set: - -.nf - \fBquery\fR = SELECT [\fIselect_field\fR] - FROM [\fItable\fR] - WHERE [\fIwhere_field\fR] = '%s' - [\fIadditional_conditions\fR] -.fi - -Insert the value, not the name, of each legacy parameter. Note -that the \fBadditional_conditions\fR parameter is optional -and if not empty, will always start with \fBAND\fR. .SH "LIST MEMBERSHIP" .na .nf @@ -134,6 +97,11 @@ e.g. query = SELECT replacement FROM aliases WHERE mailbox = '%s' .fi +By default, every query must return a result set (instead +of storing its results in a table); with "\fBrequire_result_set += no\fR" (Postfix 3.2 and later), the absence of a result +set is treated as "not found". + This parameter supports the following '%' expansions: .RS .IP "\fB%%\fR" @@ -260,11 +228,18 @@ limit to 1 ensures that lookups do not return multiple values. .IP "\fBoption_file\fR" Read options from the given file instead of the default my.cnf -location. +location. This reads options from the \fB[client]\fR option +group, optionally followed by options from the group given +with \fBoption_group\fR. .sp This parameter is available with Postfix 2.11 and later. -.IP "\fBoption_group\fR" -Read options from the given group. +.IP "\fBoption_group (default: Postfix >=3.2: client, <= 3.1: empty)\fR" +Read options from the given group of the mysql options file, +after reading options from the \fB[client]\fR group. +.sp +Postfix 3.2 and later read \fB[client]\fR option group +settings by default. To disable this specify no \fBoption_file\fR +and specify "\fBoption_group =\fR" (i.e. an empty value). .sp Postfix 3.1 and earlier don't read \fB[client]\fR option group settings unless a non\-empty \fBoption_file\fR or @@ -272,6 +247,12 @@ group settings unless a non\-empty \fBoption_file\fR or specify, for example, "\fBoption_group = client\fR". .sp This parameter is available with Postfix 2.11 and later. +.IP "\fBrequire_result_set (default: yes)\fR" +If "\fByes\fR", require that every query returns a result +set. If "\fBno\fR", treat the absence of a result set as +"not found". +.sp +This parameter is available with Postfix 3.2 and later. .IP "\fBtls_cert_file\fR" File containing client's X509 certificate. .sp @@ -296,6 +277,61 @@ Verify that the server's name matches the common name in the certificate. .sp This parameter is available with Postfix 2.11 and later. +.SH "USING MYSQL STORED PROCEDURES" +.na +.nf +.ad +.fi +Postfix 3.2 and later support calling a stored procedure +instead of using a SELECT statement in the query, e.g. + +.nf + \fBquery\fR = CALL lookup('%s') +.fi + +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 set (instead of storing its results +in a table). With "\fBrequire_result_set = no\fR", 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 that return a result (instead of storing +their results in a table). + +The following is an example of a stored procedure returning +a single result set: + +.nf +CREATE [DEFINER=`user`@`host`] PROCEDURE +`lookup`(IN `param` VARCHAR(255)) + READS SQL DATA + SQL SECURITY INVOKER + BEGIN + select goto from alias where address=param; + END +.fi +.SH "OBSOLETE MAIN.CF PARAMETERS" +.na +.nf +.ad +.fi +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:\fImysqlname\fR", the parameter "hosts" +would be defined in main.cf as "\fImysqlname\fR_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 will be removed in a future Postfix version. .SH "OBSOLETE QUERY INTERFACE" .na .nf @@ -303,7 +339,7 @@ This parameter is available with Postfix 2.11 and later. .fi This section describes an interface that is deprecated as of Postfix 2.2. It is replaced by the more general \fBquery\fR -interface described above. If the \fBquery\fR parameter +interface described above. If the \fBquery\fR 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. @@ -382,3 +418,10 @@ Liviu Daia Institute of Mathematics of the Romanian Academy P.O. BOX 1\-764 RO\-014700 Bucharest, ROMANIA + +Stored\-procedure support by John Fawcett. + +Wietse Venema +Google, Inc. +111 8th Avenue +New York, NY 10011, USA diff --git a/external/ibm-public/postfix/dist/man/man5/pgsql_table.5 b/external/ibm-public/postfix/dist/man/man5/pgsql_table.5 index 209fefa46d1..5c3411a5143 100644 --- a/external/ibm-public/postfix/dist/man/man5/pgsql_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/pgsql_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: pgsql_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: pgsql_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH PGSQL_TABLE 5 .ad @@ -30,51 +30,6 @@ PostgreSQL source as a lookup table in main.cf, for example: The file /etc/postfix/pgsql\-aliases.cf has the same format as the Postfix main.cf file, and can specify the parameters described below. -.SH "BACKWARDS COMPATIBILITY" -.na -.nf -.ad -.fi -For compatibility with other Postfix lookup tables, PostgreSQL -parameters can also be defined in main.cf. In order to do -that, specify as PostgreSQL source a name that doesn't begin -with a slash or a dot. The PostgreSQL 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 "pgsql:\fIpgsqlname\fR", -the parameter "hosts" below would be defined in main.cf as -"\fIpgsqlname\fR_hosts". - -Note: with this form, the passwords for the PostgreSQL sources -are written in main.cf, which is normally world\-readable. -Support for this form will be removed in a future Postfix -version. - -Normally, the SQL query is specified via a single \fBquery\fR -parameter (described in more detail below). When this -parameter is not specified in the map definition, Postfix -reverts to an older interface, with the SQL query -constructed from the \fBselect_function\fR, \fBselect_field\fR, -\fBtable\fR, \fBwhere_field\fR and \fBadditional_conditions\fR -parameters. The old interface will be gradually phased -out. To migrate to the new interface set: - -.nf - \fBquery\fR = SELECT \fIselect_function\fR('%s') -.fi - -or in the absence of \fBselect_function\fR, the lower precedence: - -.nf - \fBquery\fR = SELECT \fIselect_field\fR - FROM \fItable\fR - WHERE \fIwhere_field\fR = '%s' - \fIadditional_conditions\fR -.fi - -Use the value, not the name, of each legacy parameter. Note -that the \fBadditional_conditions\fR parameter is optional -and if not empty, will always start with \fBAND\fR. .SH "LIST MEMBERSHIP" .na .nf @@ -101,24 +56,22 @@ return the key itself or a constant value. .ad .fi .IP "\fBhosts\fR" -The hosts that Postfix will try to connect to and query from. -Specify \fIunix:\fR for UNIX\-domain sockets, \fIinet:\fR for TCP -connections (default). Example: +The hosts that Postfix will try to connect to and query +from. Besides a \fBpostgresql://\fR connection URI, this +setting supports the historical forms \fBunix:/\fIpathname\fR +for UNIX\-domain sockets and \fBinet:\fIhost:port\fR for TCP +connections, where the \fBunix:\fR and \fBinet:\fR prefixes +are accepted and ignored for backwards compatibility. +Examples: .nf + hosts = postgresql://username@example.com/tablename?sslmode=require hosts = host1.some.domain host2.some.domain:port hosts = unix:/file/name .fi -The hosts are tried in random order, with all connections over -UNIX domain sockets being tried before those over TCP. The -connections are automatically closed after being idle for about -1 minute, and are re\-opened as necessary. - -NOTE: the \fIunix:\fR and \fIinet:\fR prefixes are accepted for -backwards compatibility reasons, but are actually ignored. -The PostgreSQL client library will always try to connect to an -UNIX socket if the name starts with a slash, and will try a TCP -connection otherwise. +The hosts are tried in random order. The connections are +automatically closed after being idle for about 1 minute, +and are re\-opened as necessary. .IP "\fBuser, password\fR" The user name and password to log into the pgsql server. Example: @@ -259,6 +212,25 @@ 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 +For compatibility with other Postfix lookup tables, PostgreSQL +parameters can also be defined in main.cf. In order to do +that, specify as PostgreSQL source a name that doesn't begin +with a slash or a dot. The PostgreSQL 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 "pgsql:\fIpgsqlname\fR", +the parameter "hosts" would be defined in main.cf as +"\fIpgsqlname\fR_hosts". + +Note: with this form, the passwords for the PostgreSQL sources +are written in main.cf, which is normally world\-readable. +Support for this form will be removed in a future Postfix +version. .SH "OBSOLETE QUERY INTERFACES" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man5/postconf.5 b/external/ibm-public/postfix/dist/man/man5/postconf.5 index 01f56df71ed..a85540ac069 100644 --- a/external/ibm-public/postfix/dist/man/man5/postconf.5 +++ b/external/ibm-public/postfix/dist/man/man5/postconf.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: postconf.5,v 1.15 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postconf.5,v 1.16 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTCONF 5 .SH NAME @@ -35,30 +35,34 @@ A parameter value may refer to other parameters. .RS .IP \(bu The expressions "$name" and "${name}" are recursively replaced with -the value of the named parameter. An undefined parameter value is -replaced with the empty value. +the value of the named parameter. The parameter name must contain +only characters from the set [a-zA-Z0-9_]. An undefined parameter +value is replaced with the empty value. .IP \(bu The expressions "${name?value}" and "${name?{value}}" are replaced -with "value" when "$name" is non-empty. These forms are supported -with Postfix versions >= 2.2 and >= 3.0, respectively. +with "value" when "$name" is non-empty. The parameter name must +contain only characters from the set [a-zA-Z0-9_]. These forms are +supported with Postfix versions >= 2.2 and >= 3.0, respectively. .IP \(bu The expressions "${name:value}" and "${name:{value}}" are replaced -with "value" when "$name" is empty. These forms are supported with -Postfix versions >= 2.2 and >= 3.0, respectively. +with "value" when "$name" is empty. The parameter name must contain +only characters from the set [a-zA-Z0-9_]. These forms are supported +with Postfix versions >= 2.2 and >= 3.0, respectively. .IP \(bu The expression "${name?{value1}:{value2}}" is replaced with "value1" when "$name" is non-empty, and with "value2" when "$name" is empty. -The "{}" is required for "value1", optional for "value2". This form -is supported with Postfix versions >= 3.0. +The "{}" is required for "value1", optional for "value2". The +parameter name must contain only characters from the set [a-zA-Z0-9_]. +This form is supported with Postfix versions >= 3.0. .IP \(bu -The first item inside "${...}" may be a logical expression of the +The first item inside "${...}" may be a relational expression of the form: "{value3} == {value4}". Besides the "==" (equality) operator Postfix supports "!=" (inequality), "<", "<=", ">=", and ">". The comparison is numerical when both operands are all digits, otherwise the comparison is lexicographical. These forms are supported with Postfix versions >= 3.0. .IP \(bu -Each "value" is subject to recursive named parameter and logical +Each "value" is subject to recursive named parameter and relational expression evaluation, except where noted. .IP \(bu Whitespace before or after each "{value}" is ignored. @@ -459,12 +463,16 @@ routing can match Postfix access tables. By default, such addresses cannot match Postfix access tables, because the address is ambiguous. .SH alternate_config_directories (default: empty) A list of non\-default Postfix configuration directories that may -be specified with "\-c config_directory" on the command line, or -via the MAIL_CONFIG environment parameter. +be specified with "\-c config_directory" on the command line (in the +case of \fBsendmail\fR(1), with the "\-C" option), or via the MAIL_CONFIG +environment parameter. .PP -This list must be specified in the default Postfix configuration -directory, and is used by set\-gid Postfix commands such as \fBpostqueue\fR(1) +This list must be specified in the default Postfix main.cf file, +and will be used by set\-gid Postfix commands such as \fBpostqueue\fR(1) and \fBpostdrop\fR(1). +.PP +Specify absolute pathnames, separated by comma or space. Note: $name +expansion is not supported. .SH always_add_missing_headers (default: no) Always add (Resent\-) From:, To:, Date: or Message\-ID: headers when not present. Postfix 2.6 and later add these headers only @@ -852,8 +860,10 @@ The \fBlocal\fR(8) delivery agent working directory for delivery to external command. Failure to change directory causes the delivery to be deferred. .PP -The following $name expansions are done on command_execution_directory -before the directory is changed. Expansion happens in the context +The command_execution_directory value is not subject to Postfix +configuration parameter $name expansion. Instead, the following +$name expansions are done on command_execution_directory before the +directory is used. Expansion happens in the context of the delivery request. The result of $name expansion is filtered with the character set that is specified with the execution_directory_expansion_filter parameter. @@ -1181,7 +1191,7 @@ is no maximum, it doesn't make much sense to use values above say .PP The only reason why the value of 2 is not the default is the way this parameter affects the delivery of mailing\-list mail. In the -worst case, their delivery can take somewhere between (cost+1/cost) +worst case, delivery can take somewhere between (cost+1/cost) and (cost/cost\-1) times more than if the preemptive scheduler was disabled. The default value of 5 turns out to provide reasonable message response times while making sure the mailing\-list deliveries @@ -1237,6 +1247,12 @@ text of successful or unsuccessful deliveries. This does not allow the replacement of a successful status code (2.X.X) with an unsuccessful status code (4.X.X or 5.X.X) or vice versa. .PP +Note: the (smtp|lmtp)_delivery_status_filter is applied only +once per recipient: when delivery is successful, when delivery is +rejected with 5XX, or when there are no more alternate MX or A +destinations. Use smtp_reply_filter or lmtp_reply_filter to inspect +responses for all delivery attempts. +.PP The following parameters can be used to implement a filter for specific delivery agents: lmtp_delivery_status_filter, local_delivery_status_filter, pipe_delivery_status_filter, @@ -1437,8 +1453,12 @@ is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. .SH default_destination_rate_delay (default: 0s) The default amount of delay that is inserted between individual -deliveries to the same destination; the resulting behavior depends -on the value of the corresponding per\-destination recipient limit. +message deliveries to the same destination and over the same message +delivery transport. Specify a non\-zero value to rate\-limit those +message deliveries to at most one per $default_destination_rate_delay. +.PP +The resulting behavior depends on the value of the corresponding +per\-destination recipient limit. .IP \(bu With a corresponding per\-destination recipient limit > 1, the rate delay specifies the time between deliveries to the @@ -1547,7 +1567,9 @@ by specific entries in the optional rbl_reply_maps lookup table. .PP This feature is available in Postfix 2.0 and later. .PP -The template is subject to exactly one level of $name substitution: +The template does not support Postfix configuration parameter $name +substitution. Instead, it supports exactly one level of $name +substitution for the following attributes: .IP "\fB$client\fR" The client hostname and IP address, formatted as name[address]. .br @@ -1678,7 +1700,9 @@ domain. Specify a string of the form \fItransport:nexthop\fR, where \fItransport\fR is the name of a mail delivery transport defined in master.cf. The \fI:nexthop\fR destination is optional; its syntax is documented -in the manual page of the corresponding delivery agent. +in the manual page of the corresponding delivery agent. In the case of +SMTP or LMTP, specify one or more destinations separated by comma or +whitespace (with Postfix 3.5 and later). .PP Example: .PP @@ -1691,9 +1715,9 @@ default_transport = uucp:relayhostname .ft R .SH default_transport_rate_delay (default: 0s) The default amount of delay that is inserted between individual -deliveries over the same message delivery transport, regardless of -destination. If non\-zero, all deliveries over the same message -delivery transport will happen one at a time. +message deliveries over the same message delivery transport, +regardless of destination. Specify a non\-zero value to rate\-limit +those message deliveries to at most one per $default_transport_rate_delay. .PP Use \fItransport\fR_transport_rate_delay to specify a transport\-specific override, where the initial \fItransport\fR is @@ -1909,6 +1933,15 @@ non\-standard Errors\-To: message header, instead of the envelope sender address (this feature is removed with Postfix version 2.2, is turned off by default with Postfix version 2.1, and is always turned on with older Postfix versions). +.SH enable_idna2003_compatibility (default: no) +Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF\-8 domain names to/from the ASCII form that is +used for DNS lookups. Specify "yes" for compatibility with Postfix +<= 3.1 (not recommended). This affects the conversion of domain +names that contain for example the German sz and the Greek zeta. +See http://unicode.org/cldr/utility/idna.jsp for more examples. +.PP +This feature is available in Postfix 3.2 and later. .SH enable_long_queue_ids (default: no) Enable long, non\-repeating, queue IDs (queue file names). The benefit of non\-repeating names is simpler logfile analysis and @@ -1986,22 +2019,38 @@ name changes. .PP This feature is available in Postfix 2.9 and later. .SH enable_original_recipient (default: yes) -Enable support for the X\-Original\-To message header. This header -is needed for multi\-recipient mailboxes. -.PP -When this parameter is set to yes, the \fBcleanup\fR(8) daemon performs -duplicate elimination on distinct pairs of (original recipient, -rewritten recipient), and generates non\-empty original recipient -queue file records. -.PP -When this parameter is set to no, the \fBcleanup\fR(8) daemon performs -duplicate elimination on the rewritten recipient address only, and -generates empty original recipient queue file records. -.PP -This feature is available in Postfix 2.1 and later. With Postfix -version 2.0, support for the X\-Original\-To message header is always turned -on. Postfix versions before 2.0 have no support for the X\-Original\-To -message header. +Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). +.PP +The original recipient address is used as follows: +.IP "Final delivery" +With "enable_original_recipient = +yes", the original recipient address is stored in the \fBX\-Original\-To\fR +message header. This header may be used to distinguish between +different recipients that share the same mailbox. +.br +.IP "Recipient deduplication" +With "enable_original_recipient += yes", the \fBcleanup\fR(8) daemon performs duplicate recipient elimination +based on the content of (original recipient, maybe\-rewritten +recipient) pairs. Otherwise, the \fBcleanup\fR(8) daemon performs duplicate +recipient elimination based only on the maybe\-rewritten recipient +address. +.br +.br +.PP +Note: with Postfix <= 3.2 the "setting enable_original_recipient += \fBno\fR" breaks address verification for addresses that are +aliased or otherwise rewritten (Postfix is unable to store the +address verification result under the original probe destination +address; instead, it can store the result only under the rewritten +address). +.PP +This feature is available in Postfix 2.1 and later. Postfix +version 2.0 behaves as if this parameter is always set to \fByes\fR. +Postfix versions before 2.0 have no support for the original recipient +address. .SH error_notice_recipient (default: postmaster) The recipient of postmaster notifications about mail delivery problems that are caused by policy, resource, software or protocol @@ -2019,10 +2068,11 @@ outside the allowed set are replaced by underscores. .PP This feature is available in Postfix 2.2 and later. .SH expand_owner_alias (default: no) -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. Normally, Postfix sets the envelope -sender address to the name of the "owner\-aliasname" alias. +When delivering to an alias "\fIaliasname\fR" that has an +"owner\-\fIaliasname\fR" companion alias, set the envelope sender +address to the expansion of the "owner\-\fIaliasname\fR" alias. +Normally, Postfix sets the envelope sender address to the name of +the "owner\-\fIaliasname\fR" alias. .SH export_environment (default: see "postconf \-d" output) The list of environment variables that a Postfix process will export to non\-Postfix processes. The TZ variable is needed for sane @@ -2030,7 +2080,8 @@ time keeping on System\-V\-ish systems. .PP Specify a list of names and/or name=value pairs, separated by whitespace or comma. Specify "{ name=value }" to protect whitespace -or comma in parameter values (whitespace after "{" and before "}" +or comma in parameter values (whitespace after the opening "{" and +before the closing "}" is ignored). The form name=value is supported with Postfix version 2.1 and later; the use of {} is supported with Postfix 3.0 and later. @@ -2165,8 +2216,10 @@ The \fBlocal\fR(8) delivery agent search list for finding a .forward file with user\-specified delivery methods. The first file that is found is used. .PP -The following $name expansions are done on forward_path before -the search actually happens. The result of $name expansion is +The forward_path value is not subject to Postfix configuration +parameter $name expansion. Instead, the following $name expansions +are done on forward_path before the search actually happens. +The result of $name expansion is filtered with the character set that is specified with the forward_expansion_filter parameter. .IP "\fB$user\fR" @@ -2265,6 +2318,42 @@ The limit is enforced by the \fBcleanup\fR(8) server. .SH header_checks (default: empty) Optional lookup tables for content inspection of primary non\-MIME message headers, as specified in the \fBheader_checks\fR(5) manual page. +.SH header_from_format (default: standard) +The format of the Postfix\-generated \fBFrom:\fR header. This +setting affects the appearance of 'full name' information when a +local program such as /bin/mail submits a message without From: +header through the Postfix \fBsendmail\fR(1) command. +.PP +Specify one of the following: +.IP "\fBstandard\fR (default)" +Produce a header formatted +as "\fBFrom:\fR \fIname\fR\fB <\fR\fIaddress\fR\fB>\fR". +This is the default as of Postfix 3.3. +.br +.IP "\fBobsolete\fR" +Produce a header formatted as "\fBFrom:\fR +\fIaddress\fR \fB(\fR\fIname\fR\fB)\fR". This is the behavior +prior to Postfix 3.3. +.br +.br +.PP +Notes: +.IP \(bu +Postfix generates the format "\fBFrom:\fR \fIaddress\fR" +when \fIname\fR information is unavailable or the envelope sender +address is empty. This is the same behavior as prior to Postfix +3.3. +.IP \(bu +In the \fBstandard\fR form, the \fIname\fR will be quoted +if it contains \fBspecials\fR as defined in RFC 5322, or the "!%" +address operators. +.IP \(bu +The Postfix \fBsendmail\fR(1) command gets \fIname\fR information +from the \fB\-F\fR command\-line option, from the \fBNAME\fR +environment variable, or from the UNIX password file. +.br +.PP +This feature is available in Postfix 3.3 and later. .SH header_size_limit (default: 102400) The maximal amount of memory in bytes for storing a message header. If a header is larger, the excess is discarded. The limit is @@ -2311,11 +2400,13 @@ Specify "ignore_mx_lookup_error = yes" to force a DNS A record lookup instead. This violates the SMTP standard and can result in mis\-delivery of mail. .SH import_environment (default: see "postconf \-d" output) -The list of environment parameters that a Postfix process will -import from a non\-Postfix parent process. Examples of relevant -parameters: +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. Unprivileged utilities will enforce the +name=value overrides, but otherwise will not change their process +environment. Examples of relevant parameters: .IP "\fBTZ\fR" -Needed for sane time keeping on most System\-V\-ish systems. +May be needed for sane time keeping on most System\-V\-ish systems. .br .IP "\fBDISPLAY\fR" Needed for debugging Postfix daemons with an X\-windows debugger. @@ -2330,7 +2421,8 @@ Needed to make "\fBpostfix \-c\fR" work. .PP Specify a list of names and/or name=value pairs, separated by whitespace or comma. Specify "{ name=value }" to protect whitespace -or comma in parameter values (whitespace after "{" and before "}" +or comma in parameter values (whitespace after the opening "{" and +before the closing "}" is ignored). The form name=value is supported with Postfix version 2.1 and later; the use of {} is supported with Postfix 3.0 and later. @@ -2447,6 +2539,51 @@ inet_protocols = ipv4, ipv6 .fi .ad .ft R +.SH info_log_address_format (default: external) +The email address form that will be used in non\-debug logging +(info, warning, etc.). As of Postfix 3.5 when an address localpart +contains spaces or other special characters, the localpart will be +quoted, for example: +.sp +.in +4 +.nf +.na +.ft C + from=<"name with spaces"@example.com> +.fi +.ad +.ft R +.in -4 +.PP +Older Postfix versions would log the internal (unquoted) form: +.sp +.in +4 +.nf +.na +.ft C + from=<name with spaces@example.com> +.fi +.ad +.ft R +.in -4 +.PP +The external and internal forms are identical for the vast +majority of email addresses that contain no spaces or other special +characters in the localpart. +.PP +The logging in external form is consistent with the address +form that Postfix 3.2 and later prefer for most table lookups. This +is therefore the more useful form for non\-debug logging. +.PP +Specify "\fBinfo_log_address_format = internal\fR" for backwards +compatibility. +.PP +Postfix uses the unquoted form internally, because an attacker +can specify an email address in different forms by playing games +with quotes and backslashes. An attacker should not be able to use +such games to circumvent Postfix access policies. +.PP +This feature is available in Postfix 3.5 and later. .SH initial_destination_concurrency (default: 5) The initial per\-destination concurrency level for parallel delivery to the same destination. @@ -2538,6 +2675,11 @@ server performs final delivery, and send "delivered" delivery status notifications instead of "relayed". The default setting is backwards compatible to avoid the infinitesimal possibility of breaking existing LMTP\-based content filters. +.SH lmtp_balance_inet_protocols (default: yes) +The LMTP\-specific version of the smtp_balance_inet_protocols +configuration parameter. See there for details. +.PP +This feature is available in Postfix 3.3 and later. .SH lmtp_bind_address (default: empty) The LMTP\-specific version of the smtp_bind_address configuration parameter. See there for details. @@ -2994,6 +3136,7 @@ parameter. See there for details. This feature is available in Postfix 2.3 and later. .SH lmtp_tcp_port (default: 24) The default TCP port that the Postfix LMTP client connects to. +Specify a symbolic name (see \fBservices\fR(5)) or a numeric port. .SH lmtp_tls_CAfile (default: empty) The LMTP\-specific version of the smtp_tls_CAfile configuration parameter. See there for details. @@ -3014,11 +3157,21 @@ The LMTP\-specific version of the smtp_tls_cert_file configuration parameter. See there for details. .PP This feature is available in Postfix 2.3 and later. +.SH lmtp_tls_chain_files (default: empty) +The LMTP\-specific version of the smtp_tls_chain_files configuration +parameter. See there for details. +.PP +This feature is available in Postfix 3.4 and later. .SH lmtp_tls_ciphers (default: medium) The LMTP\-specific version of the smtp_tls_ciphers configuration parameter. See there for details. .PP This feature is available in Postfix 2.6 and later. +.SH lmtp_tls_connection_reuse (default: no) +The LMTP\-specific version of the smtp_tls_connection_reuse configuration +parameter. See there for details. +.PP +This feature is available in Postfix 3.4 and later. .SH lmtp_tls_dcert_file (default: empty) The LMTP\-specific version of the smtp_tls_dcert_file configuration parameter. See there for details. @@ -3126,6 +3279,11 @@ The LMTP\-specific version of the smtp_tls_security_level configuration parameter. See there for details. .PP This feature is available in Postfix 2.3 and later. +.SH lmtp_tls_servername (default: empty) +The LMTP\-specific version of the smtp_tls_servername configuration +parameter. See there for details. +.PP +This feature is available in Postfix 3.4 and later. .SH lmtp_tls_session_cache_database (default: empty) The LMTP\-specific version of the smtp_tls_session_cache_database configuration parameter. See there for details. @@ -3384,7 +3542,9 @@ By default, mail for unknown recipients in domains that match $mydestination, $inet_interfaces or $proxy_interfaces is returned as undeliverable. .PP -The following $name expansions are done on luser_relay: +The luser_relay value is not subject to Postfix configuration +parameter $name expansion. Instead, the following $name expansions +are done: .IP "\fB$domain\fR" The recipient domain. .br @@ -3554,7 +3714,7 @@ it easier to specify shell syntax (see example below). .PP If you can, avoid shell meta characters because they will force Postfix to run an expensive shell process. If you're delivering -via Procmail then running a shell won't make a noticeable difference +via "procmail" then running a shell won't make a noticeable difference in the total cost. .PP Note: if you use the mailbox_command feature to deliver mail @@ -3637,6 +3797,39 @@ For safety reasons, this feature does not allow $number substitutions in regular expression maps. .PP This feature is available in Postfix 2.3 and later. +.SH maillog_file (default: empty) +The name of an optional logfile that is written by the Postfix +\fBpostlogd\fR(8) service. An empty value selects logging to \fBsyslogd\fR(8). +Specify "/dev/stdout" to select logging to standard output. Stdout +logging requires that Postfix is started with "postfix start\-fg". +.PP +Note 1: The maillog_file parameter value must contain a prefix +that is specified with the maillog_file_prefixes parameter. +.PP +Note 2: Some Postfix non\-daemon programs may still log information +to \fBsyslogd\fR(8), before they have processed their configuration +parameters and command\-line options. +.PP +This feature is available in Postfix 3.4 and later. +.SH maillog_file_compressor (default: gzip) +The program to run after rotating $maillog_file with "postfix +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_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 +mistake. Specify one or more prefix strings, separated by comma or +whitespace. +.PP +This feature is available in Postfix 3.4 and later. +.SH maillog_file_rotate_suffix (default: %Y%M%d\-%H%M%S) +The format of the suffix to append to $maillog_file while rotating +the file with "postfix logrotate". See \fBstrftime\fR(3) for syntax. The +default suffix, YYYYMMDD\-HHMMSS, allows logs to be rotated frequently. +.PP +This feature is available in Postfix 3.4 and later. .SH mailq_path (default: see "postconf \-d" output) Sendmail compatibility feature that specifies where the Postfix \fBmailq\fR(1) command is installed. This command can be used to @@ -3724,7 +3917,7 @@ masquerade_domains = $mydomain .ft R .SH masquerade_exceptions (default: empty) Optional list of user names that are not subjected to address -masquerading, even when their address matches $masquerade_domains. +masquerading, even when their addresses match $masquerade_domains. .PP By default, address masquerading makes no exceptions. .PP @@ -3936,8 +4129,9 @@ for a list of available macro names and their meanings. .PP This feature is available in Postfix 2.3 and later. .SH milter_default_action (default: tempfail) -The default action when a Milter (mail filter) application is -unavailable or mis\-configured. Specify one of the following: +The default action when a Milter (mail filter) response is +unavailable (for example, bad Postfix configuration or Milter +failure). Specify one of the following: .IP "accept" Proceed as if the mail filter was not present. .br @@ -4472,10 +4666,10 @@ Example: .PP This feature is available in Postfix 3.1 and later. .SH owner_request_special (default: yes) -Give special treatment to owner\-listname and listname\-request -address localparts: don't split such addresses when the -recipient_delimiter is set to "\-". This feature is useful for -mailing lists. +Enable special treatment for owner\-\fIlistname\fR entries in the +\fBaliases\fR(5) file, and don't split owner\-\fIlistname\fR and +\fIlistname\fR\-request address localparts when the recipient_delimiter +is set to "\-". This feature is useful for mailing lists. .SH parent_domain_matches_subdomains (default: see "postconf \-d" output) A list of Postfix features where the pattern "example.com" also matches subdomains of example.com, @@ -4529,6 +4723,24 @@ The numerical Postfix SMTP server response code when a request is rejected by the \fBreject_plaintext_session\fR restriction. .PP This feature is available in Postfix 2.3 and later. +.SH postlog_service_name (default: postlog) +The name of the \fBpostlogd\fR(8) service entry in master.cf. +This service appends logfile records to the file specified +with the maillog_file parameter. +.PP +This feature is available in Postfix 3.4 and later. +.SH postlogd_watchdog_timeout (default: 10s) +How much time a \fBpostlogd\fR(8) process may take to process a request +before it is terminated by a built\-in watchdog timer. This is a +safety mechanism that prevents \fBpostlogd\fR(8) from becoming non\-responsive +due to a bug in Postfix itself or in system software. This limit +cannot be set under 10s. +.PP +Specify a non\-zero time value (an integral value plus an optional +one\-letter suffix that specifies the time unit). Time units: s +(seconds), m (minutes), h (hours), d (days), w (weeks). +.PP +This feature is available in Postfix 3.4 and later. .SH postmulti_control_commands (default: reload flush) The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats as "control" commands, that operate on running instances. For @@ -4605,7 +4817,7 @@ Example: .ft C /etc/postfix/main.cf: postscreen_access_list = permit_mynetworks, - cidr:/etc/postfix/postscreen_access.cidr + cidr:/etc/postfix/postscreen_access.cidr postscreen_blacklist_action = enforce .fi .ad @@ -5140,6 +5352,12 @@ Optional information that is appended after a 4XX or 5XX response. See smtpd_reject_footer for further details. .PP This feature is available in Postfix 2.8 and later. +.SH postscreen_reject_footer_maps (default: $smtpd_reject_footer_maps) +Optional lookup table for information that is appended after a 4XX +or 5XX \fBpostscreen\fR(8) server response. See smtpd_reject_footer_maps for +further details. +.PP +This feature is available in Postfix 3.4 and later. .SH postscreen_tls_security_level (default: $smtpd_tls_security_level) The SMTP TLS security level for the \fBpostscreen\fR(8) server; when a non\-empty value is specified, this overrides the obsolete parameters @@ -5152,7 +5370,7 @@ The name of the proxy protocol used by an optional before\-postscreen proxy agent. When a proxy agent is used, this protocol conveys local and remote address and port information. Specify "postscreen_upstream_proxy_protocol = haproxy" to enable the haproxy -protocol. +protocol; version 2 is supported with Postfix 3.5 and later. .PP This feature is available in Postfix 2.10 and later. .SH postscreen_upstream_proxy_timeout (default: 5s) @@ -5815,7 +6033,7 @@ file. .PP This feature is available in Postfix 2.0 and later. .SH relayhost (default: empty) -The next\-hop destination of non\-local mail; overrides non\-local +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 @@ -5825,9 +6043,11 @@ 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, specify a domain name, hostname, hostname:port, -[hostname]:port, [hostaddress] or [hostaddress]:port. The form -[hostname] turns off MX lookups. +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. .PP If you're connected via UUCP, see the UUCP_README file for useful information. @@ -5839,7 +6059,7 @@ Examples: .ft C relayhost = $mydomain relayhost = [gateway.example.com] -relayhost = uucphost +relayhost = mail1.example:587, mail2.example:587 relayhost = [an.ip.add.ress] .fi .ad @@ -5917,7 +6137,8 @@ Postfix releases, the behavior is as if this parameter is set to "yes". .PP As documented in \fBaliases\fR(5), when an alias \fIname\fR has a -companion alias named owner\-\fIname\fR, delivery errors will be +companion alias named owner\-\fIname\fR, this will replace the +envelope sender address, so that delivery errors will be reported to the owner alias instead of the sender. This configuration is recommended for mailing lists. .PP @@ -5947,7 +6168,9 @@ to other mailing list members. .PP Unfortunately, older Postfix releases reset the owner\-alias attribute when delivering mail to a child alias that does not have -its own owner alias. The \fBlocal\fR(8) delivery agent then attempts to +its own owner alias. To be precise, this resets only the decision +to create a new queue file, not the decision to override the envelope +sender address. The \fBlocal\fR(8) delivery agent then attempts to deliver local addresses as soon as they come out of child alias expansion. If delivery to any address from child alias expansion fails with a temporary error condition, the entire mailing list may @@ -6153,6 +6376,36 @@ This feature is available in Postfix 2.9 and later. A Sendmail compatibility feature that specifies the location of the Postfix \fBsendmail\fR(1) command. This command can be used to submit mail into the Postfix queue. +.SH service_name (read\-only) +The master.cf service name of a Postfix daemon process. This +can be used to distinguish the logging from different services that +use the same program name. +.PP +Example master.cf entries: +.PP +.nf +.na +.ft C +# Distinguish inbound MTA logging from submission and smtps logging. +smtp inet n \- n \- \- smtpd +submission inet n \- n \- \- smtpd + \-o syslog_name=postfix/$service_name +smtps inet n \- n \- \- smtpd + \-o syslog_name=postfix/$service_name +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +# Distinguish outbound MTA logging from inbound relay logging. +smtp unix \- \- n \- \- smtp +relay unix \- \- n \- \- smtp + \-o syslog_name=postfix/$service_name +.fi +.ad +.ft R .SH service_throttle_time (default: 60s) How long the Postfix \fBmaster\fR(8) waits before forking a server that appears to be malfunctioning. @@ -6194,8 +6447,8 @@ files in the compiled\-in default $shlib_directory location. This feature is available in Postfix 3.0 and later. .SH show_user_unknown_table_name (default: yes) Display the name of the recipient table in the "User unknown" -responses. The extra detail makes trouble shooting easier but also -reveals information that is nobody elses business. +responses. The extra detail makes troubleshooting easier but also +reveals information that is nobody else's business. .PP This feature is available in Postfix 2.0 and later. .SH showq_service_name (default: showq) @@ -6282,6 +6535,17 @@ With "smtp_always_send_ehlo = no", the Postfix SMTP client sends EHLO only when the word "ESMTP" appears in the server greeting banner (example: 220 spike.porcupine.org ESMTP Postfix). +.SH smtp_balance_inet_protocols (default: yes) +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. +.PP +This avoids an interoperability problem when a destination resolves +to primarily IPv6 addresses, the smtp_address_limit feature eliminates +most or all IPv4 addresses, and the destination is not reachable over +IPv6. +.PP +This feature is available in Postfix 3.3 and later. .SH smtp_bind_address (default: empty) An optional numerical network address that the Postfix SMTP client should bind to when making an IPv4 connection. @@ -7310,6 +7574,9 @@ Time limit for Postfix SMTP client write and read operations during TLS startup and shutdown handshake procedures. .PP This feature is available in Postfix 2.2 and later. +.SH smtp_tcp_port (default: smtp) +The default TCP port that the Postfix SMTP client connects to. +Specify a symbolic name (see \fBservices\fR(5)) or a numeric port. .SH smtp_tls_CAfile (default: empty) A file containing CA certificates of root CAs trusted to sign either remote SMTP server certificates or intermediate CA certificates. @@ -7319,7 +7586,7 @@ smtp_tls_CApath instead, but note that the latter directory must be present in the chroot jail if the \fBsmtp\fR(8) client is chrooted. This file may also be used to augment the client certificate trust chain, but it is best to include all the required certificates directly in -$smtp_tls_cert_file. +$smtp_tls_cert_file (or, Postfix >= 3.4 $smtp_tls_chain_files). .PP Specify "smtp_tls_CAfile = /path/to/system_CA_file" to use ONLY the system\-supplied default Certification Authority certificates. @@ -7377,9 +7644,10 @@ the Postfix SMTP client TLS session. This feature is available in Postfix 2.7. .SH smtp_tls_cert_file (default: empty) File with the Postfix SMTP client RSA certificate in PEM format. -This file may also contain the Postfix SMTP client private RSA key, -and these may be the same as the Postfix SMTP server RSA certificate and key -file. +This file may also contain the Postfix SMTP client private RSA key, and +these may be the same as the Postfix SMTP server RSA certificate and key +file. With Postfix >= 3.4 the preferred way to configure client keys +and certificates is via the "smtp_tls_chain_files" parameter. .PP Do not configure client certificates unless you \fBmust\fR present client TLS certificates to one or more servers. Client certificates are @@ -7392,10 +7660,13 @@ well without them. The recommended setting is to let the defaults stand: .ft C smtp_tls_cert_file = smtp_tls_key_file = -smtp_tls_dcert_file = -smtp_tls_dkey_file = smtp_tls_eccert_file = smtp_tls_eckey_file = +# Obsolete DSA parameters +smtp_tls_dcert_file = +smtp_tls_dkey_file = +# Postfix >= 3.4 interface +smtp_tls_chain_files = .fi .ad .ft R @@ -7412,13 +7683,23 @@ CA(s) (bottom\-up order). .PP Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". -Create the client.pem file with "cat client_cert.pem intermediate_CA.pem -root_CA.pem > client.pem". +As the "root" super\-user create the client.pem file with: +.sp +.in +4 +.nf +.na +.ft C +# \fBumask 077\fR +# \fBcat client_key.pem client_cert.pem intermediate_CA.pem > chain.pem \fR +.fi +.ad +.ft R +.in -4 .PP If you also want to verify remote SMTP server certificates issued by these CAs, you can add the CA certificates to the smtp_tls_CAfile, in which case it is not necessary to have them in the smtp_tls_cert_file, -smtp_tls_dcert_file or smtp_tls_eccert_file. +smtp_tls_dcert_file (obsolete) or smtp_tls_eccert_file. .PP A certificate supplied here must be usable as an SSL client certificate and hence pass the "openssl verify \-purpose sslclient ..." test. @@ -7428,12 +7709,180 @@ Example: .nf .na .ft C -smtp_tls_cert_file = /etc/postfix/client.pem +smtp_tls_cert_file = /etc/postfix/chain.pem .fi .ad .ft R .PP This feature is available in Postfix 2.2 and later. +.SH smtp_tls_chain_files (default: empty) +List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. The file names +are separated by commas and/or whitespace. This parameter obsoletes the +legacy algorithm\-specific key and certificate file settings. When this +parameter is non\-empty, the legacy parameters are ignored, and a warning +is logged if any are also non\-empty. +.PP +With the proliferation of multiple private key algorithms-which, +as of OpenSSL 1.1.1, include DSA (obsolete), RSA, ECDSA, Ed25519 +and Ed448-it is increasingly impractical to use separate +parameters to configure the key and certificate chain for each +algorithm. Therefore, Postfix now supports storing multiple keys and +corresponding certificate chains in a single file or in a set of files. +.PP +Each key must appear \fBimmediately before\fR the corresponding +certificate, optionally followed by additional issuer certificates that +complete the certificate chain for that key. When multiple files are +specified, they are equivalent to a single file that is concatenated +from those files in the given order. Thus, while a key must always +precede its certificate and issuer chain, it can be in a separate file, +so long as that file is listed immediately before the file that holds +the corresponding certificate chain. Once all the files are +concatenated, the sequence of PEM objects must be: \fIkey1, cert1, +[chain1], key2, cert2, [chain2], ..., keyN, certN, [chainN].\fR +.PP +Storing the private key in the same file as the corresponding +certificate is more reliable. With the key and certificate in separate +files, there is a chance that during key rollover a Postfix process +might load a private key and certificate from separate files that don't +match. Various operational errors may even result in a persistent +broken configuration in which the certificate does not match the private +key. +.PP +The file or files must contain at most one key of each type. If, +for example, two or more RSA keys and corresponding chains are listed, +depending on the version of OpenSSL either only the last one will be +used or an configuration error may be detected. Note that while +"Ed25519" and "Ed448" are considered separate algorithms, the various +ECDSA curves (typically one of prime256v1, secp384r1 or secp521r1) are +considered as different parameters of a single "ECDSA" algorithm, so it +is not presently possible to configure keys for more than one ECDSA +curve. +.PP +Example (separate files for each key and corresponding certificate chain): +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/main.cf: + smtp_tls_chain_files = + ${config_directory}/ed25519.pem, + ${config_directory}/ed448.pem, + ${config_directory}/rsa.pem +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/ed25519.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/ed448.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/rsa.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.PP +Example (all keys and certificates in a single file): +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/main.cf: + smtp_tls_chain_files = ${config_directory}/chains.pem +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/chains.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.PP +This feature is available in Postfix 3.4 and later. .SH smtp_tls_cipherlist (default: empty) Obsolete Postfix < 2.3 control for the Postfix SMTP client TLS cipher list. As this feature applies to all TLS security levels, it is easy @@ -7464,6 +7913,16 @@ ciphers on a per\-destination basis. This feature is available in Postfix 2.6 and later. With earlier Postfix releases only the smtp_tls_mandatory_ciphers parameter is implemented, and opportunistic TLS always uses "export" or better (i.e. all) ciphers. +.SH smtp_tls_connection_reuse (default: no) +Try to make multiple deliveries per TLS\-encrypted connection. +This uses the \fBtlsproxy\fR(8) service to encrypt an SMTP connection, +uses the \fBscache\fR(8) service to save that connection, and relies on +hints from the \fBqmgr\fR(8) daemon. +.PP +See "Client\-side +TLS connection reuse" for background details. +.PP +This feature is available in Postfix 3.4 and later. .SH smtp_tls_dane_insecure_mx_policy (default: dane) The TLS policy for MX hosts with "secure" TLSA records when the nexthop destination security level is \fBdane\fR, but the MX @@ -7496,6 +7955,7 @@ policy is backwards\-compatible with earlier Postfix versions. .SH smtp_tls_dcert_file (default: empty) File with the Postfix SMTP client DSA certificate in PEM format. This file may also contain the Postfix SMTP client private DSA key. +The DSA algorithm is obsolete and should not be used. .PP See the discussion under smtp_tls_cert_file for more details. .PP @@ -7513,7 +7973,8 @@ This feature is available in Postfix 2.2 and later. .SH smtp_tls_dkey_file (default: $smtp_tls_dcert_file) File with the Postfix SMTP client DSA private key in PEM format. This file may be combined with the Postfix SMTP client DSA certificate -file specified with $smtp_tls_dcert_file. +file specified with $smtp_tls_dcert_file. The DSA algorithm is obsolete +and should not be used. .PP The private key must be accessible without a pass\-phrase, i.e. it must not be encrypted. File permissions should grant read\-only @@ -7524,6 +7985,8 @@ This feature is available in Postfix 2.2 and later. .SH smtp_tls_eccert_file (default: empty) File with the Postfix SMTP client ECDSA certificate in PEM format. This file may also contain the Postfix SMTP client ECDSA private key. +With Postfix >= 3.4 the preferred way to configure client keys and +certificates is via the "smtp_tls_chain_files" parameter. .PP See the discussion under smtp_tls_cert_file for more details. .PP @@ -7541,8 +8004,10 @@ 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_eckey_file (default: $smtp_tls_eccert_file) File with the Postfix SMTP client ECDSA private key in PEM format. -This file may be combined with the Postfix SMTP client ECDSA -certificate file specified with $smtp_tls_eccert_file. +This file may be combined with the Postfix SMTP client ECDSA certificate +file specified with $smtp_tls_eccert_file. With Postfix >= 3.4 the +preferred way to configure client keys and certificates is via the +"smtp_tls_chain_files" parameter. .PP The private key must be accessible without a pass\-phrase, i.e. it must not be encrypted. File permissions should grant read\-only @@ -7787,7 +8252,9 @@ This feature is available in Postfix 2.11. .SH smtp_tls_key_file (default: $smtp_tls_cert_file) File with the Postfix SMTP client RSA private key in PEM format. This file may be combined with the Postfix SMTP client RSA certificate -file specified with $smtp_tls_cert_file. +file specified with $smtp_tls_cert_file. With Postfix >= 3.4 the +preferred way to configure client keys and certificates is via the +"smtp_tls_chain_files" parameter. .PP The private key must be accessible without a pass\-phrase, i.e. it must not be encrypted. File permissions should grant read\-only @@ -7925,8 +8392,9 @@ matches the underlying OpenSSL interface semantics. .PP The range of protocols advertised by an SSL/TLS client must be contiguous. When a protocol version is enabled, disabling any -higher version implicitly disables all versions above that higher -version. Thus, for example: +higher version implicitly disables all versions above that higher version. +Thus, for example (assuming the OpenSSL library supports both SSLv2 +and SSLv3): .sp .in +4 .nf @@ -7948,6 +8416,10 @@ disabled except by also disabling "TLSv1" (typically leaving just versions of Postfix >= 2.10 can explicitly disable support for "TLSv1.1" or "TLSv1.2". .PP +OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +>= 3.4 (or patch releases >= 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". +.PP At the dane and dane\-only security levels, when usable TLSA records are obtained for the remote SMTP @@ -8106,11 +8578,13 @@ No TLS. No additional attributes are supported at this level. .IP "\fBmay\fR" Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces -interoperability. The optional "ciphers", "exclude" and "protocols" +interoperability. 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. When opportunistic TLS -handshakes fail, Postfix retries the connection with TLS disabled. +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. When opportunistic +TLS handshakes fail, Postfix retries the connection with TLS disabled. This allows mail delivery to sites with non\-interoperable TLS implementations. .br @@ -8118,9 +8592,11 @@ implementations. Mandatory TLS encryption. 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 +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. In the policy table, +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 protocols or excluded ciphers must be separated by colons, as attribute values may not contain whitespace or commas. .br @@ -8130,18 +8606,20 @@ 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, the -server certificate must match the TLSA records. RFC 6698 (DANE) +server certificate must match the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix -2.11 and later. +2.11 and later. The optional "connection_reuse" attribute (Postfix +>= 3.4) overrides the main.cf smtp_tls_connection_reuse parameter. .br .IP "\fBdane\-only\fR" Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA records in DNSSEC. If no TLSA records are found, or none are usable, no connection is made to the server. When usable TLSA records are obtained for the remote SMTP server, the -server certificate must match the TLSA records. RFC 6698 (DANE) TLS +server certificate must match the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 -and later. +and later. The optional "connection_reuse" attribute (Postfix >= +3.4) overrides the main.cf smtp_tls_connection_reuse parameter. .br .IP "\fBfingerprint\fR" Certificate fingerprint @@ -8157,7 +8635,8 @@ algorithm used to calculate the fingerprint is selected by the 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. +digits. The optional "connection_reuse" attribute (Postfix >= 3.4) +overrides the main.cf smtp_tls_connection_reuse parameter. .br .IP "\fBverify\fR" Mandatory TLS verification. At this security @@ -8167,7 +8646,9 @@ 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. +"secure" policy, described below. 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 @@ -8185,7 +8666,9 @@ routing 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. +verification of a new MX host fails. The optional "connection_reuse" +attribute (Postfix >= 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. .br .br .PP @@ -8243,14 +8726,15 @@ and "TLSv1". .PP The range of protocols advertised by an SSL/TLS client must be contiguous. When a protocol version is enabled, disabling any -higher version implicitly disables all versions above that higher -version. Thus, for example: +higher version implicitly disables all versions above that higher version. +Thus, for example (assuming the OpenSSL library supports both SSLv2 +and SSLv3): .sp .in +4 .nf .na .ft C -smtp_tls_mandatory_protocols = !SSLv2, !TLSv1 +smtp_tls_protocols = !SSLv2, !TLSv1 .fi .ad .ft R @@ -8263,6 +8747,10 @@ and "TLSv1.2". The latest patch levels of Postfix >= 2.6, and all versions of Postfix >= 2.10 can explicitly disable support for "TLSv1.1" or "TLSv1.2" .PP +OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +>= 3.4 (or patch releases >= 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". +.PP To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 for opportunistic TLS set "smtp_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set @@ -8380,7 +8868,7 @@ in effect, the destination domain's containing DNS zone must be signed and the Postfix SMTP client's operating system must be configured to send its DNS queries to a recursive DNS nameserver that is able to validate the signed records. Each MX host's DNS -zone should also be signed, and should publish DANE TLSA (RFC 6698) +zone should also be signed, and should publish DANE TLSA (RFC 7672) records that specify how that MX host's TLS certificate is to be verified. TLSA records do not preempt the normal SMTP MX host selection algorithm, if some MX hosts support TLSA and others do @@ -8395,13 +8883,13 @@ purposes of protocol and cipher selection, the "dane" security level is treated like a "mandatory" TLS security level, and weak ciphers and protocols are disabled. Since DANE authenticates server certificates the "aNULL" cipher\-suites are transparently excluded -at this level, no need to configure this manually. RFC 6698 (DANE) +at this level, no need to configure this manually. RFC 7672 (DANE) TLS authentication is available with Postfix 2.11 and later. .br .IP "\fBdane\-only\fR" Mandatory DANE TLS. This is just like "dane" above, but DANE TLSA authentication is required. There is no fallback to "may" or -"encrypt" when TLSA records are missing or unusable. RFC 6698 +"encrypt" when TLSA records are missing or unusable. RFC 7672 (DANE) TLS authentication is available with Postfix 2.11 and later. .br .IP "\fBfingerprint\fR" @@ -8518,6 +9006,36 @@ smtp_tls_fingerprint_cert_match = .ft R .PP This feature is available in Postfix 2.3 and later. +.SH smtp_tls_servername (default: empty) +Optional name to send to the remote SMTP server in the TLS Server +Name Indication (SNI) extension. The SNI extension is always on when +DANE is used to authenticate the server, and in that case the SNI name +sent is the one required by RFC7672 and this parameter is ignored. +.PP +Some SMTP servers use the received SNI name to select an appropriate +certificate chain to present to the client. While this may improve +interoperability with such servers, it may reduce interoperability with +other servers that choose to abort the connection when they don't have a +certificate chain configured for the requested name. Such servers +should select a default certificate chain and continue the handshake, +but some may not. Therefore, absent DANE, no SNI name is sent by +default. +.PP +The SNI name must be either a valid DNS hostname, or else one of the +special values \fBhostname\fR or \fBnexthop\fR, which select either the +remote hostname or the nexthop domain respectively. DNS names for SNI must be +in A\-label (punycode) form. Invalid DNS names log a configuration error +warning and mail delivery is deferred. +.PP +Except when using a relayhost to forward all email, the only +sensible non\-empty main.cf setting for this parameter is +\fBhostname\fR. Other non\-empty values are only practical on a +per\-destination basis via the \fBservername\fR attribute of the Postfix +TLS policy table. When +in doubt, leave this parameter empty, and configure per\-destination SNI +as needed. +.PP +This feature is available in Postfix 3.4 and later. .SH smtp_tls_session_cache_database (default: empty) Name of the file containing the optional Postfix SMTP client TLS session cache. Specify a database type that supports enumeration, @@ -8593,9 +9111,9 @@ trust\-anchor files are used at all, they will be specified on a per\-destination basis via the "tafile" attribute of the "verify" and "secure" levels in smtp_tls_policy_maps. .PP -The underlying mechanism is in support of RFC 6698 (DANE TLSA), -which defines mechanisms for a client to securely determine server -TLS certificates via DNS. +The underlying mechanism is in support of RFC 7672 (DANE TLSA), +which defines mechanisms for an SMTP client MTA to securely determine +server TLS certificates via DNS. .PP If you want your trust anchors to be public keys, with OpenSSL you can extract a single PEM public key from a PEM X.509 file @@ -9000,15 +9518,27 @@ restriction that matches wins. The following restrictions are specific to client hostname or client network address information. .IP "\fBcheck_ccert_access \fItype:table\fR\fR" -Use the remote SMTP client certificate fingerprint or the public key +By default use the remote SMTP client certificate fingerprint +or the public key fingerprint (Postfix 2.9 and later) as lookup key for the specified \fBaccess\fR(5) database; with Postfix version 2.2, also require that the remote SMTP client certificate is verified successfully. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard\-coded as md5 prior to -Postfix version 2.5). This feature is available with Postfix version +Postfix version 2.5). This feature requires "smtpd_tls_ask_ccert += yes" and is available with Postfix version 2.2 and later. .br +.br +Alternatively, check_ccert_access accepts an explicit search +order (Postfix 3.5 and later). The default search order as described +above corresponds with: +.br +check_ccert_access { type:table, { search_order = cert_fingerprint, +pubkey_fingerprint } } +.br +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 @@ -9094,7 +9624,8 @@ CA. Otherwise, clients with a third\-party certificate would also be allowed to relay. Specify "tls_append_default_CA = no" when the trusted CA is specified with smtpd_tls_CAfile or smtpd_tls_CApath, to prevent Postfix from appending the system\-supplied default CAs. -This feature is available with Postfix version 2.2. +This feature requires "smtpd_tls_ask_ccert = yes" and is available +with Postfix version 2.2 and later. .br .IP "\fBpermit_tls_clientcerts\fR" Permit the request when the remote SMTP client certificate @@ -9102,8 +9633,8 @@ fingerprint or public key fingerprint (Postfix 2.9 and later) is listed in $relay_clientcerts. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard\-coded as md5 prior to -Postfix version 2.5). This feature is available with Postfix version -2.2. +Postfix version 2.5). This feature requires "smtpd_tls_ask_ccert += yes" and is available with Postfix version 2.2 and later. .br .IP "\fBreject_rbl_client \fIrbl_domain=d.d.d.d\fR\fR" Reject the request when the reversed client network address is @@ -9180,7 +9711,7 @@ available in Postfix 2.8 and later. .br .IP "\fBreject_unknown_client_hostname\fR (with Postfix < 2.3: reject_unknown_client)" Reject the request when 1) the client IP address\->name mapping -fails, 2) the name\->address mapping fails, or 3) the name\->address +fails, or 2) the name\->address mapping fails, or 3) the name\->address mapping does not match the client IP address. .br This is a @@ -9610,7 +10141,8 @@ What characters are allowed in $name expansions of RBL reply templates. Characters not in the allowed set are replaced by "_". Use C like escapes to specify special characters such as whitespace. .PP -This parameter is not subjected to $parameter expansion. +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_forbidden_commands (default: CONNECT, GET, POST) @@ -9825,6 +10357,41 @@ Examples: .ft R .PP This feature is available in Postfix 2.10 and later. +.SH smtpd_milter_maps (default: empty) +Lookup tables with Milter settings per remote SMTP client IP +address. The lookup result overrides the smtpd_milters setting, +and has the same syntax. +.PP +Note: lookup tables cannot return empty responses. Specify a +lookup result of DISABLE (case does not matter) to indicate that +Milter support should be disabled. +.PP +Example to disable Milters for local clients: +.PP +.nf +.na +.ft C +/etc/postfix/main.cf: + smtpd_milter_maps = cidr:/etc/postfix/smtpd_milter_map + smtpd_milters = inet:host:port, { inet:host:port, ... }, ... +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +/etc/postfix/smtpd_milter_map: + # Disable Milters for local clients. + 127.0.0.0/8 DISABLE + 192.168.0.0/16 DISABLE + ::/64 DISABLE + 2001:db8::/32 DISABLE +.fi +.ad +.ft R +.PP +This feature is available in Postfix 3.2 and later. .SH smtpd_milters (default: empty) A list of Milter (mail filter) applications for new mail that arrives via the Postfix \fBsmtpd\fR(8) server. Specify space or comma as @@ -10092,7 +10659,8 @@ lookup problem with Postfix prior to version 2.0. .br .br .IP "\fBreject_non_fqdn_recipient\fR" -Reject the request when the RCPT TO address is not in +Reject the request when the RCPT TO address specifies a +domain that is not in fully\-qualified domain form, as required by the RFC. .br The @@ -10175,8 +10743,10 @@ unverified_recipient_tempfail_action parameter specifies the action after address probe failure due to a temporary problem (default: defer_if_permit). .br -This feature is available in Postfix 2.1 -and later. +This feature breaks for aliased addresses +with "enable_original_recipient = no" (Postfix <= 3.2). +.br +This feature is available in Postfix 2.1 and later. .br .br .PP @@ -10246,9 +10816,15 @@ be truncated before it is logged to the remote SMTP client's maillog file, or before it is returned to the sender in a delivery status notification. .PP -This feature supports a limited number of $name attributes in -the footer text. These are replaced by their current value for the -SMTP session: +The template text is not subject to Postfix configuration +parameter $name expansion. Instead, this feature supports a limited +number of $name attributes in the footer text. These attributes are +replaced with their current value for the SMTP session. +.PP +Note: specify $$name in footer text that is looked up from +regexp: or pcre:\-based smtpd_reject_footer_maps, otherwise the +Postfix server will not use the footer text and will log a warning +instead. .IP "\fBclient_address\fR" The Client IP address that is logged in the maillog file. @@ -10289,6 +10865,16 @@ This suppresses the line break between the reply text and the footer text (Postfix 2.10 and later). .PP This feature is available in Postfix 2.8 and later. +.SH smtpd_reject_footer_maps (default: empty) +Lookup tables, indexed by the complete Postfix SMTP server 4xx or +5xx response, with reject footer templates. See smtpd_reject_footer +for details. +.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 +This feature is available in Postfix 3.4 and later. .SH smtpd_reject_unlisted_recipient (default: yes) Request that the Postfix SMTP server rejects mail for unknown recipient addresses, even when no explicit reject_unlisted_recipient @@ -10532,6 +11118,20 @@ configuration file or rendezvous point. .PP This feature is available in Postfix 2.3 and later. In earlier releases it was called \fBsmtpd_sasl_application_name\fR. +.SH smtpd_sasl_response_limit (default: 12288) +The maximum length of a SASL client's response to a server challenge. +When the client's "initial response" is longer than the normal limit for +SMTP commands, the client must omit its initial response, and wait for an +empty server challenge; it can then send what would have been its "initial +response" as a response to the empty server challenge. RFC4954 requires the +server to accept client responses up to at least 12288 octets of +base64\-encoded text. The default value is therefore also the minimum value +accepted for this parameter. +.PP +This feature is available in Postfix 3.4 and later. Prior versions use +"line_length_limit", which may need to be raised to accommodate larger client +responses, as may be needed with GSSAPI authentication of Windows AD users +who are members of many groups. .SH smtpd_sasl_security_options (default: noanonymous) Postfix SMTP server SASL security options; as of Postfix 2.3 the list of available @@ -10680,8 +11280,9 @@ FROM addresses that are known in $smtpd_sender_login_maps. This feature is available in Postfix version 2.11 and later. .br .IP "\fBreject_non_fqdn_sender\fR" -Reject the request when the MAIL FROM address is not in -fully\-qualified domain form, as required by the RFC. +Reject the request when the MAIL FROM address specifies a +domain that is not in +fully\-qualified domain form as required by the RFC. .br The non_fqdn_reject_code parameter specifies the response code for @@ -10754,8 +11355,11 @@ The unverified_sender_tempfail_action parameter specifies the action after address probe failure due to a temporary problem (default: defer_if_permit). .br -This feature is available -in Postfix 2.1 and later. +This feature breaks for +aliased addresses with "enable_original_recipient = no" (Postfix +<= 3.2). +.br +This feature is available in Postfix 2.1 and later. .br .br .PP @@ -10958,6 +11562,8 @@ This feature is available in Postfix 2.2 and later. .SH smtpd_tls_cert_file (default: empty) File with the Postfix SMTP server RSA certificate in PEM format. This file may also contain the Postfix SMTP server private RSA key. +With Postfix >= 3.4 the preferred way to configure server keys and +certificates is via the "smtpd_tls_chain_files" parameter. .PP Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a @@ -10966,15 +11572,22 @@ able to authenticate the server, but unless it is running Postfix 2.3 or similar software, it will still insist on a server certificate. .PP For servers that are \fBnot\fR public Internet MX hosts, Postfix -2.3 supports configurations with no certificates. This entails the -use of just the anonymous TLS ciphers, which are not supported by -typical SMTP clients. Since such clients will not, as a rule, fall -back to plain text after a TLS handshake failure, the server will -be unable to receive email from TLS enabled clients. To avoid -accidental configurations with no certificates, Postfix 2.3 enables -certificate\-less operation only when the administrator explicitly -sets "smtpd_tls_cert_file = none". This ensures that new Postfix -configurations will not accidentally run with no certificates. +supports configurations with no certificates. This entails the use of +just the anonymous TLS ciphers, which are not supported by typical SMTP +clients. Since some clients may not fall back to plain text after a TLS +handshake failure, a certificate\-less Postfix SMTP server will be unable +to receive email from some TLS\-enabled clients. To avoid accidental +configurations with no certificates, Postfix enables certificate\-less +operation only when the administrator explicitly sets +"smtpd_tls_cert_file = none". This ensures that new Postfix SMTP server +configurations will not accidentally enable TLS without certificates. +.PP +Note that server certificates are not optional in TLS 1.3. To run +without certificates you'd have to disable the TLS 1.3 protocol by +including '!TLSv1.3' in "smtpd_tls_protocols" and perhaps also +"smtpd_tls_mandatory_protocols". It is simpler instead to just +configure a certificate chain. Certificate\-less operation is not +recommended. .PP Both RSA and DSA certificates are supported. When both types are present, the cipher used determines which certificate will be @@ -10994,8 +11607,8 @@ root_CA.pem > server.pem". .PP If you also want to verify client certificates issued by these CAs, you can add the CA certificates to the smtpd_tls_CAfile, in which -case it is not necessary to have them in the smtpd_tls_cert_file or -smtpd_tls_dcert_file. +case it is not necessary to have them in the smtpd_tls_cert_file, +smtpd_tls_dcert_file (obsolete) or smtpd_tls_eccert_file. .PP A certificate supplied here must be usable as an SSL server certificate and hence pass the "openssl verify \-purpose sslserver ..." test. @@ -11011,6 +11624,180 @@ smtpd_tls_cert_file = /etc/postfix/server.pem .ft R .PP This feature is available in Postfix 2.2 and later. +.SH smtpd_tls_chain_files (default: empty) +List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. The file names +are separated by commas and/or whitespace. This parameter obsoletes the +legacy algorithm\-specific key and certificate file settings. When this +parameter is non\-empty, the legacy parameters are ignored, and a warning +is logged if any are also non\-empty. +.PP +With the proliferation of multiple private key algorithms-which, +as of OpenSSL 1.1.1, include DSA (obsolete), RSA, ECDSA, Ed25519 +and Ed448-it is increasingly impractical to use separate +parameters to configure the key and certificate chain for each +algorithm. Therefore, Postfix now supports storing multiple keys and +corresponding certificate chains in a single file or in a set of files. +.PP +Each key must appear \fBimmediately before\fR the corresponding +certificate, optionally followed by additional issuer certificates that +complete the certificate chain for that key. When multiple files are +specified, they are equivalent to a single file that is concatenated +from those files in the given order. Thus, while a key must always +precede its certificate and issuer chain, it can be in a separate file, +so long as that file is listed immediately before the file that holds +the corresponding certificate chain. Once all the files are +concatenated, the sequence of PEM objects must be: \fIkey1, cert1, +[chain1], key2, cert2, [chain2], ..., keyN, certN, [chainN].\fR +.PP +Storing the private key in the same file as the corresponding +certificate is more reliable. With the key and certificate in separate +files, there is a chance that during key rollover a Postfix process +might load a private key and certificate from separate files that don't +match. Various operational errors may even result in a persistent +broken configuration in which the certificate does not match the private +key. +.PP +The file or files must contain at most one key of each type. If, +for example, two or more RSA keys and corresponding chains are listed, +depending on the version of OpenSSL either only the last one will be +used or an configuration error may be detected. Note that while +"Ed25519" and "Ed448" are considered separate algorithms, the various +ECDSA curves (typically one of prime256v1, secp384r1 or secp521r1) are +considered as different parameters of a single "ECDSA" algorithm, so it +is not presently possible to configure keys for more than one ECDSA +curve. +.PP +RSA is still the most widely supported algorithm. Presently (late +2018), ECDSA support is common, but not yet universal, and Ed25519 and +Ed448 support is mostly absent. Therefore, an RSA key should generally +be configured, along with any additional keys for the other algorithms +when desired. +.PP +Example (separate files for each key and corresponding certificate chain): +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/main.cf: + smtpd_tls_chain_files = + ${config_directory}/ed25519.pem, + ${config_directory}/ed448.pem, + ${config_directory}/rsa.pem +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/ed25519.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/ed448.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/rsa.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.PP +Example (all keys and certificates in a single file): +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/main.cf: + smtpd_tls_chain_files = ${config_directory}/chains.pem +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/chains.pem: + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- + \-\-\-\-\-BEGIN PRIVATE KEY\-\-\-\-\- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + \-\-\-\-\-END PRIVATE KEY\-\-\-\-\- + \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + \-\-\-\-\-END CERTIFICATE\-\-\-\-\- +.fi +.ad +.ft R +.in -4 +.PP +This feature is available in Postfix 3.4 and later. .SH smtpd_tls_cipherlist (default: empty) Obsolete Postfix < 2.3 control for the Postfix SMTP server TLS cipher list. It is easy to create interoperability problems by choosing @@ -11043,6 +11830,7 @@ and opportunistic TLS always uses "export" or better (i.e. all) ciphers. .SH smtpd_tls_dcert_file (default: empty) File with the Postfix SMTP server DSA certificate in PEM format. This file may also contain the Postfix SMTP server private DSA key. +The DSA algorithm is obsolete and should not be used. .PP See the discussion under smtpd_tls_cert_file for more details. .PP @@ -11123,7 +11911,8 @@ This feature is available with Postfix version 2.2. .SH smtpd_tls_dkey_file (default: $smtpd_tls_dcert_file) File with the Postfix SMTP server DSA private key in PEM format. This file may be combined with the Postfix SMTP server DSA certificate -file specified with $smtpd_tls_dcert_file. +file specified with $smtpd_tls_dcert_file. The DSA algorithm is obsolete +and should not be used. .PP The private key must be accessible without a pass\-phrase, i.e. it must not be encrypted. File permissions should grant read\-only @@ -11134,6 +11923,8 @@ This feature is available in Postfix 2.2 and later. .SH smtpd_tls_eccert_file (default: empty) File with the Postfix SMTP server ECDSA certificate in PEM format. This file may also contain the Postfix SMTP server private ECDSA key. +With Postfix >= 3.4 the preferred way to configure server keys and +certificates is via the "smtpd_tls_chain_files" parameter. .PP See the discussion under smtpd_tls_cert_file for more details. .PP @@ -11152,7 +11943,9 @@ compiled and linked with OpenSSL 1.0.0 or later. .SH smtpd_tls_eckey_file (default: $smtpd_tls_eccert_file) File with the Postfix SMTP server ECDSA private key in PEM format. This file may be combined with the Postfix SMTP server ECDSA certificate -file specified with $smtpd_tls_eccert_file. +file specified with $smtpd_tls_eccert_file. With Postfix >= 3.4 the +preferred way to configure server keys and certificates is via the +"smtpd_tls_chain_files" parameter. .PP The private key must be accessible without a pass\-phrase, i.e. it must not be encrypted. File permissions should grant read\-only @@ -11184,6 +11977,12 @@ as 128 bit strength ECC. Barring significant progress in attacks on elliptic curve crypto\-systems, the "strong" curve is sufficient for most users. .br +.IP "\fBauto\fR" +Use the most preferred curve that is +supported by both the client and the server. This setting requires +Postfix >= 3.2 compiled and linked with OpenSSL >= 1.0.2. This +is the default setting under the above conditions. +.br .br .PP If you want to take maximal advantage of ciphers that offer forward secrecy see @@ -11357,7 +12156,9 @@ This feature is available in Postfix 2.5 and later. .SH smtpd_tls_key_file (default: $smtpd_tls_cert_file) File with the Postfix SMTP server RSA private key in PEM format. This file may be combined with the Postfix SMTP server RSA certificate -file specified with $smtpd_tls_cert_file. +file specified with $smtpd_tls_cert_file. With Postfix >= 3.4 the +preferred way to configure server keys and certificates is via the +"smtpd_tls_chain_files" parameter. .PP The private key must be accessible without a pass\-phrase, i.e. it must not be encrypted. File permissions should grant read\-only @@ -11492,6 +12293,10 @@ disabled. The latest patch levels of Postfix >= 2.6, and all versions of Postfix >= 2.10 can disable support for "TLSv1.1" or "TLSv1.2". .PP +OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +>= 3.4 (or patch releases >= 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". +.PP Example: .PP .nf @@ -11521,6 +12326,10 @@ and "TLSv1.2". The latest patch levels of Postfix >= 2.6, and all versions of Postfix >= 2.10 can disable support for "TLSv1.1" or "TLSv1.2". .PP +OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +>= 3.4 (or patch releases >= 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". +.PP To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 for opportunistic TLS set "smtpd_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set @@ -11669,7 +12478,7 @@ The name of the proxy protocol used by an optional before\-smtpd proxy agent. When a proxy agent is used, this protocol conveys local and remote address and port information. Specify "smtpd_upstream_proxy_protocol = haproxy" to enable the haproxy -protocol. +protocol; version 2 is supported with Postfix 3.5 and later. .PP NOTE: To use the nginx proxy with \fBsmtpd\fR(8), enable the XCLIENT protocol with smtpd_authorized_xclient_hosts. This supports SASL @@ -11888,8 +12697,8 @@ process initialization will be logged with the default facility. Examples are errors while parsing the command line arguments, and errors while accessing the Postfix main.cf configuration file. .SH syslog_name (default: see "postconf \-d" output) -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Warning: a non\-default syslog_name setting takes effect only after a Postfix process has completed initialization. Errors during @@ -11956,64 +12765,20 @@ bytes (equivalent to 256 bits) is sufficient to generate a 128bit .PP This feature is available in Postfix 2.2 and later. .SH tls_dane_digest_agility (default: on) -Configure DANE TLSA digest algorithm agility. When digest -algorithm agility is enabled, and the server and client support a -common strong digest algorithm, TLSA records with weaker digest -algorithms are ignored. +Configure RFC7671 DANE TLSA digest algorithm agility. +Do not change this setting from its default value. .PP -Specify one of the following: -.IP "\fBoff\fR" -DANE verification examines each well\-formed record in the TLSA -RRset whose matching type is either "0" (no hash used) or is one of -the digest algorithms listed in $tls_dane_digests. This setting -is not recommended. -.br -.IP "\fBon\fR" -From each group of well\-formed TLSA RRs a non\-zero digest -matching type with the same certificate usage and selector, DANE -verification examines only those records whose matching type has -the highest precedence (appear earliest in $tls_dane_digests). -.br -.IP "\fBmaybe\fR" -For compatibility with digest algorithm agility, each certificate -or public key whose digest is included in a DANE TLSA RRset, SHOULD -be published with the same set of digest matching type values as -any other with the same usage and selector. Therefore, compatible -TLSA RRsets will contain an identical count of well\-formed RRs with -each non\-zero digest matching type for any fixed combination of -usage and selector. When this constraint is violated, or any of -the digest records are malformed, digest algorithm agility will -disabled. Otherwise, digest algorithm agility is enabled. -.br -.br -.PP -Digest algorithm agility ensures that the strongest digest -supported by both the Postfix SMTP client and the remote server is -used, and weaker digests are ignored. This supports non\-disruptive -deprecation of outdated digest algorithms. -.PP -To ensure compatibility with digest algorithm agility during -key rotation, when a certificate or public key is being replaced -with another, and both are published during the transition, both -the old and the new certificate MUST be specified with the same set -of digests. One can change the list of digest algorithms later, -once old keys are retired. At any given time, change either the -list of digests without changing the list of certificates or public -keys or the list of certificates or public keys without changing -the list of digests. Full value matching type "0" records are not -subject to this constraint, but are discouraged due to the size of -the resulting DNS records. -.PP -It is expected that this algorithm agility mechanism will be -published in a standards track RFC for SMTP with DANE, and also in -an eventual update to RFC 6698. +See Section 8 of RFC7671 for correct key rotation procedures. .PP -This feature is available in Postfix 2.11 and later. +This feature is available in Postfix 2.11 through 3.1. Postfix +3.2 and later ignore this configuration parameter and behave as +though it were set to "on". .SH tls_dane_digests (default: sha512 sha256) -RFC 6698 TLSA resource\-record "matching type" digest algorithms -in descending preference order. All the specified algorithms must -be supported by the underlying OpenSSL library, otherwise the Postfix -SMTP client will not support DANE TLSA security. +DANE TLSA (RFC 6698, RFC 7671, RFC 7672) resource\-record "matching +type" digest algorithms in descending preference order. All the +specified algorithms must be supported by the underlying OpenSSL +library, otherwise the Postfix SMTP client will not support DANE +TLSA security. .PP Specify a list of digest names separated by commas and/or whitespace. Each digest name may be followed by an optional @@ -12038,41 +12803,17 @@ seriously compromised and servers have had ample time to update their TLSA records you should not omit any standard digests, just arrange them in order from strongest to weakest. .PP -When for a particular combination of "certificate usage" and -"selector" the TLSA RRset contains records with more than one digest -matching type, the tls_dane_digest_agility parameter determines -whether all the RRs are used, or only those with the most preferred -digest matching type. -.PP -The tls_dane_trust_anchor_digest_enable parameter controls -whether any digest TLSA records are acceptable in usage "2" (trust -anchor assertion) TLSA records. -.PP This feature is available in Postfix 2.11 and later. .SH tls_dane_trust_anchor_digest_enable (default: yes) -RFC 6698 trust\-anchor digest support in the Postfix TLS library. Enable support for RFC 6698 (DANE TLSA) DNS records that contain -digests of trust\-anchors with certificate usage "2". In this case -the certificate usage logically requires the server administrator -to configure the server to include the trust\-anchor certificate in -the server's SSL certificate chain. If enough domains mess this -up, you can disable support for these TLSA records, but you'll no -longer have secure connections that get it right and only publish -trust anchor records. -.PP -At the dane -security level, when a TLSA RRset includes only unusable associations, -the Postfix SMTP client will automatically switch the connection -to the encrypt -security level. At the dane\-only security level, -the server in question is skipped and delivery is deferred if no -secure servers are found. -.PP -The tls_dane_digests parameter controls the list of digest -algorithms that are supported in TLSA records. The tls_dane_digest_agility -parameter controls digest algorithm downgrade attack resistance. -.PP -This feature is available in Postfix 2.11 and later. +digests of trust\-anchors with certificate usage "2". Do not change +this setting from its default value. +.PP +This feature is available in Postfix 2.11 through 3.1. It has +been withdrawn in Postfix 3.2, as trust\-anchor TLSA records are now +widely used and have proved sufficiently reliable. Postfix 3.2 and +later ignore this configuration parameter and behaves as though it +were set to "yes". .SH tls_disable_workarounds (default: see "postconf \-d" output) List or bit\-mask of OpenSSL bug work\-arounds to disable. .PP @@ -12104,61 +12845,85 @@ of specific named bug work\-arounds chosen from the list below. It is possible that your OpenSSL version includes new bug work\-arounds added after your Postfix source code was last updated, in that case you can only disable one of these via the hexadecimal syntax above. -.IP "\fBMICROSOFT_SESS_ID_BUG\fR" -See SSL_CTX_\fBset_options\fR(3) +.IP "\fBCRYPTOPRO_TLSEXT_BUG\fR" +New with GOST support in +OpenSSL 1.0.0. .br -.IP "\fBNETSCAPE_CHALLENGE_BUG\fR" -See SSL_CTX_\fBset_options\fR(3) +.IP "\fBDONT_INSERT_EMPTY_FRAGMENTS\fR" +See +SSL_CTX_\fBset_options\fR(3) .br .IP "\fBLEGACY_SERVER_CONNECT\fR" See SSL_CTX_\fBset_options\fR(3) .br -.IP "\fBNETSCAPE_REUSE_CIPHER_CHANGE_BUG\fR" -also aliased -as \fBCVE\-2010\-4180\fR. Postfix 2.8 disables this work\-around by -default with OpenSSL versions that may predate the fix. Fixed in -OpenSSL 0.9.8q and OpenSSL 1.0.0c. -.br -.IP "\fBSSLREF2_REUSE_CERT_TYPE_BUG\fR" -See -SSL_CTX_\fBset_options\fR(3) -.br .IP "\fBMICROSOFT_BIG_SSLV3_BUFFER\fR" See SSL_CTX_\fBset_options\fR(3) .br +.IP "\fBMICROSOFT_SESS_ID_BUG\fR" +See SSL_CTX_\fBset_options\fR(3) +.br .IP "\fBMSIE_SSLV2_RSA_PADDING\fR" also aliased as \fBCVE\-2005\-2969\fR. Postfix 2.8 disables this work\-around by default with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.7h and OpenSSL 0.9.8a. .br +.IP "\fBNETSCAPE_CHALLENGE_BUG\fR" +See SSL_CTX_\fBset_options\fR(3) +.br +.IP "\fBNETSCAPE_REUSE_CIPHER_CHANGE_BUG\fR" +also aliased +as \fBCVE\-2010\-4180\fR. Postfix 2.8 disables this work\-around by +default with OpenSSL versions that may predate the fix. Fixed in +OpenSSL 0.9.8q and OpenSSL 1.0.0c. +.br .IP "\fBSSLEAY_080_CLIENT_DH_BUG\fR" See SSL_CTX_\fBset_options\fR(3) .br -.IP "\fBTLS_D5_BUG\fR" -See SSL_CTX_\fBset_options\fR(3) +.IP "\fBSSLREF2_REUSE_CERT_TYPE_BUG\fR" +See +SSL_CTX_\fBset_options\fR(3) .br .IP "\fBTLS_BLOCK_PADDING_BUG\fR" See SSL_CTX_\fBset_options\fR(3) .br +.IP "\fBTLS_D5_BUG\fR" +See SSL_CTX_\fBset_options\fR(3) +.br .IP "\fBTLS_ROLLBACK_BUG\fR" See SSL_CTX_\fBset_options\fR(3). This is disabled in OpenSSL 0.9.7 and later. Nobody should still be using 0.9.6! .br -.IP "\fBDONT_INSERT_EMPTY_FRAGMENTS\fR" -See -SSL_CTX_\fBset_options\fR(3) -.br -.IP "\fBCRYPTOPRO_TLSEXT_BUG\fR" -New with GOST support in -OpenSSL 1.0.0. +.IP "\fBTLSEXT_PADDING\fR" +Postfix >= 3.4. See SSL_CTX_\fBset_options\fR(3). .br .br .PP This feature is available in Postfix 2.8 and later. +.SH tls_eecdh_auto_curves (default: see "postconf \-d" output) +The prioritized list of elliptic curves supported by the Postfix +SMTP client and server. These curves are used by the Postfix SMTP +server when "smtpd_tls_eecdh_grade = auto". The selected curves +must be implemented by OpenSSL and be standardized for use in TLS +(RFC 4492 or its imminent successor). It is unwise to list only +"bleeding\-edge" curves supported by a small subset of clients. The +default list is suitable for most users. +.PP +Postfix skips curve names that are unknown to OpenSSL, or that +are known but not yet implemented. This makes it possible to +"anticipate" support for curves that should be used once they become +available. In particular, in some OpenSSL versions, the new RFC +8031 curves "X25519" and "X448" may be known by name, but ECDH +support for either or both may be missing. These curves may appear +in the default value of this parameter, even though they'll only +be usable with later versions of OpenSSL. +.PP +This feature is available in Postfix 3.2 and later, when it is +compiled and linked with OpenSSL 1.0.2 or later on platforms where +EC algorithms have not been disabled by the vendor. .SH tls_eecdh_strong_curve (default: prime256v1) The elliptic curve used by the Postfix SMTP server for sensibly strong @@ -12170,8 +12935,8 @@ reported by \fBecparam\fR(1) with the "\-list_curves" option) and be one of the curves listed in Section 5.1.1 of RFC 4492. You should not generally change this setting. Remote SMTP client implementations must support this curve for EECDH key exchange to take place. It -is unwise to choose an "exotic" curve supported by only a small subset -of clients. +is unwise to choose an "bleeding\-edge" curve supported by only a +small subset of clients. .PP The default "strong" curve is rated in NSA Suite B for information classified up to SECRET. @@ -12230,6 +12995,12 @@ the default cipherlist for the SMTP server. You are strongly encouraged to not change this setting. .PP This feature is available in Postfix 2.3 and later. +.SH tls_fast_shutdown_enable (default: yes) +A workaround for implementations that hang Postfix while shutting +down a TLS session, until Postfix times out. With this enabled, +Postfix will not wait for the remote TLS peer to respond to a TLS +'close' notification. This behavior is recommended for TLSv1.0 and +later. .SH tls_high_cipherlist (default: see "postconf \-d" output) The OpenSSL cipherlist for "high" grade ciphers. This defines the meaning of the "high" setting in smtpd_tls_ciphers, @@ -12349,6 +13120,119 @@ Note: on OpenBSD systems specify /dev/arandom when /dev/urandom gives timeout errors. .PP This feature is available in Postfix 2.2 and later. +.SH tls_server_sni_maps (default: empty) +Optional lookup tables that map names received from remote SMTP +clients via the TLS Server Name Indication (SNI) extension to the +appropriate keys and certificate chains. This parameter is implemented +in the Postfix TLS library, and applies to both \fBsmtpd\fR(8) and the SMTP +server mode of \fBtlsproxy\fR(8). +.PP +When this parameter is non\-empty, the Postfix SMTP server enables +SNI extension processing, and logs SNI values that are invalid or +don't match an entry in the the specified tables. When an entry +does match, the SNI name is logged as part of the connection summary +at log levels 1 and higher. +.PP +The lookup key is either the verbatim SNI domain name or an +ancestor domain prefixed with a leading dot. For internationalized +domains, the lookup key must be in IDNA 2008 A\-label form (as +required in the TLS SNI extension). +.PP +The syntax of the lookup value is the same as with the +smtp_tls_chain_files parameter (see there for additional details), +but here scoped to just TLS connections in which the client sends +a matching SNI domain name. +.PP +Example: +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/main.cf: + # + # The indexed SNI table must be created with "postmap \-F" + # + indexed = ${default_database_type}:${config_directory}/ + tls_server_sni_maps = ${indexed}sni +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/sni: + # + # The example.com domain has both an RSA and ECDSA certificate + # chain. The chain files MUST start with the private key, + # with the certificate chain next, starting with the leaf + # (server) certificate, and then the issuer certificates. + # + example.com /etc/postfix/sni\-chains/rsa2048.example.com.pem, + /etc/postfix/sni\-chains/ecdsa\-p256.example.com.pem + # + # The example.net domain has a wildcard certificate, and two + # additional DNS names. So its certificate chain is also used + # with any subdomain, plus the additional names. + # + example.net /etc/postfix/sni\-chains/example.net.pem + .example.net /etc/postfix/sni\-chains/example.net.pem + example.info /etc/postfix/sni\-chains/example.net.pem + example.org /etc/postfix/sni\-chains/example.net.pem +.fi +.ad +.ft R +.in -4 +.PP +Note that the SNI lookup tables should also have entries for +the domains that correspond to the Postfix SMTP server's default +certificate(s). This ensures that the remote SMTP client's TLS SNI +extension gets a positive response when it specifies one of the +Postfix SMTP server's default domains, and ensures that the Postfix +SMTP server will not log an SNI name mismatch for such a domain. +The Postfix SMTP server's default certificates are then only used +when the client sends no SNI or when it sends SNI with a domain +that the server knows no certificate(s) for. +.PP +The mapping from an SNI domain name to a certificate chain is indirect. In +the input source files for "cdb", "hash", "btree" or other tables that are +converted to on\-disk indexed files via \fBpostmap\fR(1), the value specified for each +key is a list of filenames. When \fBpostmap\fR(1) is used with the \fB\-F\fR option, +the generated table stores for each lookup key the base64\-encoded contents of +the associated files. When querying tables via \fBpostmap \-Fq\fR, the table +value is decoded from base64, yielding the original file content, plus a new +line. +.PP +With "regexp", "pcre", "inline", "texthash", "static" and similar +tables that are interpreted at run\-time, and don't have a separate +source format, the table value is again a list files, that are loaded +into memory when the table is opened. +.PP +With tables whose content is managed outside of Postfix, such +as LDAP, MySQL, PostgreSQL, socketmap and tcp, the value must be a +concatenation of the desired PEM keys and certificate chains, that +is then further encoded to yield a single\-line base64 string. +Creation of such tables and secure storage (the value includes +private key material) are outside the responsibility of Postfix. +.PP +With "socketmap" and "tcp" the data will be transmitted in the clear, and +there is no query access control, so these are generally unsuitable for storing +SNI chains. With LDAP and SQL, you should restrict read access and use TLS to +protect the sensitive data in transit. +.PP +Typically there is only one private key and its chain of certificates +starting with the "leaf" certificate corresponding to that key, and +continuing with the appropriate intermediate issuer CA certificates, +with each certificate ideally followed by its issuer. Servers +that have keys and certificates for more than one algorithm (e.g. +both an RSA key and an ECDSA key, or even RSA, ECDSA and Ed25519) +can use multiple chains concatenated together, with the key always +listed before the corresponding certificates. +.PP +This feature is available in Postfix 3.4 and later. .SH tls_session_ticket_cipher (default: Postfix >= 3.0: aes\-256\-cbc, Postfix < 3.0: aes\-128\-cbc) Algorithm used to encrypt RFC5077 TLS session tickets. This algorithm must use CBC mode, have a 128\-bit block size, and must @@ -12399,18 +13283,40 @@ in its value are enabled (see openssl/ssl.h and SSL_CTX_\fBset_options\fR(3)). You can only enable options not already controlled by other Postfix settings. For example, you cannot disable protocols or enable server cipher preference. Do not attempt to turn all features by -specifying 0xFFFFFFFF, this is unlikely to be a good idea. +specifying 0xFFFFFFFF, this is unlikely to be a good idea. Some +bug work\-arounds are also valid here, allowing them to be re\-enabled +if/when they're no longer enabled by default. The supported values +include: +.IP "\fBENABLE_MIDDLEBOX_COMPAT\fR" +Postfix >= 3.4. See +SSL_CTX_\fBset_options\fR(3). +.br .IP "\fBLEGACY_SERVER_CONNECT\fR" See SSL_CTX_\fBset_options\fR(3). .br .IP "\fBNO_TICKET\fR" -See SSL_CTX_\fBset_options\fR(3). +Enabled by default when needed in +fully\-patched Postfix >= 2.7. Not needed at all for Postfix >= +2.11, unless for some reason you do not want to support TLS session +resumption. Best not set explicitly. See SSL_CTX_\fBset_options\fR(3). .br .IP "\fBNO_COMPRESSION\fR" Disable SSL compression even if supported by the OpenSSL library. Compression is CPU\-intensive, and compression before encryption does not always improve security. .br +.IP "\fBNO_RENEGOTIATION\fR" +Postfix >= 3.4. This can +reduce opportunities for a potential CPU exhaustion attack. See +SSL_CTX_\fBset_options\fR(3). +.br +.IP "\fBNO_SESSION_RESUMPTION_ON_RENEGOTIATION\fR" +Postfix +>= 3.4. See SSL_CTX_\fBset_options\fR(3). +.br +.IP "\fBPRIORITIZE_CHACHA\fR" +Postfix >= 3.4. See SSL_CTX_\fBset_options\fR(3). +.br .br .PP This feature is available in Postfix 2.11 and later. @@ -12458,6 +13364,111 @@ service maintains TLS session caches and other information in support of TLS. .PP This feature is available in Postfix 2.11 and later. +.SH tlsproxy_client_CAfile (default: $smtp_tls_CAfile) +A file containing CA certificates of root CAs trusted to sign +either remote TLS server certificates or intermediate CA certificates. +See smtp_tls_CAfile for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_CApath (default: $smtp_tls_CApath) +Directory with PEM format Certification Authority certificates +that the Postfix \fBtlsproxy\fR(8) client uses to verify a remote TLS +server certificate. See smtp_tls_CApath for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_cert_file (default: $smtp_tls_cert_file) +File with the Postfix \fBtlsproxy\fR(8) client RSA certificate in PEM +format. See smtp_tls_cert_file for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_chain_files (default: $smtp_tls_chain_files) +Files with the Postfix \fBtlsproxy\fR(8) client keys and certificate +chains in PEM format. See smtp_tls_chain_files for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_dcert_file (default: $smtp_tls_dcert_file) +File with the Postfix \fBtlsproxy\fR(8) client DSA certificate in PEM +format. See smtp_tls_dcert_file for further details. DSA is obsolete and +should not be used. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_dkey_file (default: $smtp_tls_dkey_file) +File with the Postfix \fBtlsproxy\fR(8) client DSA private key in PEM +format. See smtp_tls_dkey_file for further details. DSA is obsolete and +should not be used. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_eccert_file (default: $smtp_tls_eccert_file) +File with the Postfix \fBtlsproxy\fR(8) client ECDSA certificate in PEM +format. See smtp_tls_eccert_file for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_eckey_file (default: $smtp_tls_eckey_file) +File with the Postfix \fBtlsproxy\fR(8) client ECDSA private key in PEM +format. See smtp_tls_eckey_file for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_enforce_tls (default: $smtp_enforce_tls) +Enforcement mode: require that SMTP servers use TLS encryption. +See smtp_enforce_tls for further details. +.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 +certificate fingerprints. See smtp_tls_fingerprint_digest for +further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_key_file (default: $smtp_tls_key_file) +File with the Postfix \fBtlsproxy\fR(8) client RSA private key in PEM +format. See smtp_tls_key_file for further details. The preferred way to +configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_loglevel (default: $smtp_tls_loglevel) +Enable additional Postfix \fBtlsproxy\fR(8) client logging of TLS +activity. See smtp_tls_loglevel for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_loglevel_parameter (default: smtp_tls_loglevel) +The name of the parameter that provides the tlsproxy_client_loglevel +value. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_per_site (default: $smtp_tls_per_site) +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 available in Postfix 3.4 and later. +.SH tlsproxy_client_policy_maps (default: $smtp_tls_policy_maps) +Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS +security policy by next\-hop destination. See smtp_tls_policy_maps +for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_scert_verifydepth (default: $smtp_tls_scert_verifydepth) +The verification depth for remote TLS server certificates. +See smtp_tls_scert_verifydepth for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_security_level (default: $smtp_tls_security_level) +The default TLS security level for the Postfix \fBtlsproxy\fR(8) +client. See smtp_tls_security_level for further details. +.PP +This feature is available in Postfix 3.4 and later. +.SH tlsproxy_client_use_tls (default: $smtp_use_tls) +Opportunistic mode: use TLS when a remote server announces TLS +support. See smtp_use_tls for further details. +.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 @@ -12501,9 +13512,16 @@ This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_cert_file (default: $smtpd_tls_cert_file) File with the Postfix \fBtlsproxy\fR(8) server RSA certificate in PEM format. This file may also contain the Postfix \fBtlsproxy\fR(8) server -private RSA key. See smtpd_tls_cert_file for further details. +private RSA key. See smtpd_tls_cert_file for further details. With +Postfix >= 3.4 the preferred way to configure tlsproxy server keys and +certificates is via the "tlsproxy_tls_chain_files" parameter. .PP This feature is available in Postfix 2.8 and later. +.SH tlsproxy_tls_chain_files (default: $smtpd_tls_chain_files) +Files with the Postfix \fBtlsproxy\fR(8) server keys and certificate +chains in PEM format. See smtpd_tls_chain_files for further details. +.PP +This feature is available in Postfix 3.4 and later. .SH tlsproxy_tls_ciphers (default: $smtpd_tls_ciphers) The minimum TLS cipher grade that the Postfix \fBtlsproxy\fR(8) server will use with opportunistic TLS encryption. See smtpd_tls_ciphers @@ -12513,7 +13531,8 @@ This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_dcert_file (default: $smtpd_tls_dcert_file) File with the Postfix \fBtlsproxy\fR(8) server DSA certificate in PEM format. This file may also contain the Postfix \fBtlsproxy\fR(8) server -private DSA key. See smtpd_tls_dcert_file for further details. +private DSA key. DSA is obsolete and should not be used. See +smtpd_tls_dcert_file for further details. .PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_dh1024_param_file (default: $smtpd_tls_dh1024_param_file) @@ -12532,23 +13551,27 @@ result export\-grade cipher suites are by default not used. This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_dkey_file (default: $smtpd_tls_dkey_file) File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM -format. This file may be combined with the Postfix \fBtlsproxy\fR(8) -server DSA certificate file specified with $smtpd_tls_dcert_file. -See smtpd_tls_dkey_file for further details. +format. This file may be combined with the Postfix \fBtlsproxy\fR(8) server +DSA certificate file specified with $smtpd_tls_dcert_file. DSA is +obsolete and should not be used. See smtpd_tls_dkey_file for further +details. .PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_eccert_file (default: $smtpd_tls_eccert_file) -File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in -PEM format. This file may also contain the Postfix \fBtlsproxy\fR(8) -server private ECDSA key. See smtpd_tls_eccert_file for further -details. +File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in PEM +format. This file may also contain the Postfix \fBtlsproxy\fR(8) server +private ECDSA key. See smtpd_tls_eccert_file for further details. With +Postfix >= 3.4 the preferred way to configure tlsproxy server keys and +certificates is via the "tlsproxy_tls_chain_files" parameter. .PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_eckey_file (default: $smtpd_tls_eckey_file) -File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in -PEM format. This file may be combined with the Postfix \fBtlsproxy\fR(8) -server ECDSA certificate file specified with $smtpd_tls_eccert_file. -See smtpd_tls_eckey_file for further details. +File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in PEM +format. This file may be combined with the Postfix \fBtlsproxy\fR(8) server +ECDSA certificate file specified with $smtpd_tls_eccert_file. See +smtpd_tls_eckey_file for further details. With Postfix >= 3.4 the +preferred way to configure tlsproxy server keys and certificates is via +the "tlsproxy_tls_chain_files" parameter. .PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_eecdh_grade (default: $smtpd_tls_eecdh_grade) @@ -12571,9 +13594,11 @@ fingerprints. See smtpd_tls_fingerprint_digest for further details. This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_key_file (default: $smtpd_tls_key_file) File with the Postfix \fBtlsproxy\fR(8) server RSA private key in PEM -format. This file may be combined with the Postfix \fBtlsproxy\fR(8) -server RSA certificate file specified with $smtpd_tls_cert_file. -See smtpd_tls_key_file for further details. +format. This file may be combined with the Postfix \fBtlsproxy\fR(8) server +RSA certificate file specified with $smtpd_tls_cert_file. See +smtpd_tls_key_file for further details. With Postfix >= 3.4 the +preferred way to configure tlsproxy server keys and certificates is via +the "tlsproxy_tls_chain_files" parameter. .PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_loglevel (default: $smtpd_tls_loglevel) @@ -12646,7 +13671,7 @@ Specify a non\-zero time value (an integral value plus an optional one\-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). .PP -This feature is available in Postfix 2.8. +This feature is available in Postfix 2.8 and later .SH trace_service_name (default: trace) The name of the trace service. This service is implemented by the \fBbounce\fR(8) daemon and maintains a record @@ -12924,7 +13949,7 @@ with 450 when the mapping failed due to a temporary error condition. Do not change this unless you have a complete understanding of RFC 5321. .SH unknown_helo_hostname_tempfail_action (default: $reject_tempfail_action) The Postfix SMTP server's action when reject_unknown_helo_hostname -fails due to an temporary error condition. Specify "defer" to defer +fails due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request diff --git a/external/ibm-public/postfix/dist/man/man5/socketmap_table.5 b/external/ibm-public/postfix/dist/man/man5/socketmap_table.5 index c110f4bf33c..570d4e4f7ee 100644 --- a/external/ibm-public/postfix/dist/man/man5/socketmap_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/socketmap_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: socketmap_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: socketmap_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SOCKETMAP_TABLE 5 .ad @@ -35,7 +35,7 @@ socketmap client request (see "REQUEST FORMAT" below). .fi Socketmaps use a simple protocol: the client sends one request, and the server sends one reply. Each request and -reply are sent as one netstring object. +each reply are sent as one netstring object. .SH "REQUEST FORMAT" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man5/sqlite_table.5 b/external/ibm-public/postfix/dist/man/man5/sqlite_table.5 index a793c24bedb..b16c8eee2c1 100644 --- a/external/ibm-public/postfix/dist/man/man5/sqlite_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/sqlite_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: sqlite_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: sqlite_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SQLITE_TABLE 5 .ad @@ -30,39 +30,6 @@ table in main.cf, for example: The file /etc/postfix/sqlite\-aliases.cf has the same format as the Postfix main.cf file, and can specify the parameters described below. -.SH "BACKWARDS COMPATIBILITY" -.na -.nf -.ad -.fi -For compatibility with other Postfix lookup tables, SQLite -parameters can also be defined in main.cf. In order to do that, -specify as SQLite source a name that doesn't begin with a slash -or a dot. The SQLite 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 "sqlite:\fIsqlitename\fR", the parameter "query" -below would be defined in main.cf as "\fIsqlitename\fR_query". - -Normally, the SQL query is specified via a single \fBquery\fR -parameter (described in more detail below). When this -parameter is not specified in the map definition, Postfix -reverts to an older interface, with the SQL query constructed -from the \fBselect_field\fR, \fBtable\fR, \fBwhere_field\fR -and \fBadditional_conditions\fR parameters. The old interface -will be gradually phased out. To migrate to the new interface -set: - -.nf - \fBquery\fR = SELECT [\fIselect_field\fR] - FROM [\fItable\fR] - WHERE [\fIwhere_field\fR] = '%s' - [\fIadditional_conditions\fR] -.fi - -Insert the value, not the name, of each legacy parameter. Note -that the \fBadditional_conditions\fR parameter is optional -and if not empty, will always start with \fBAND\fR. .SH "LIST MEMBERSHIP" .na .nf @@ -225,6 +192,19 @@ 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 +For compatibility with other Postfix lookup tables, SQLite +parameters can also be defined in main.cf. In order to do that, +specify as SQLite source a name that doesn't begin with a slash +or a dot. The SQLite 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 "sqlite:\fIsqlitename\fR", the parameter "query" +would be defined in main.cf as "\fIsqlitename\fR_query". .SH "OBSOLETE QUERY INTERFACE" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man5/tcp_table.5 b/external/ibm-public/postfix/dist/man/man5/tcp_table.5 index 587e0cc3fae..2d1f2aad0f7 100644 --- a/external/ibm-public/postfix/dist/man/man5/tcp_table.5 +++ b/external/ibm-public/postfix/dist/man/man5/tcp_table.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: tcp_table.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: tcp_table.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH TCP_TABLE 5 .ad @@ -43,12 +43,17 @@ Send and receive operations must complete in 100 seconds. .nf .ad .fi -Each request specifies a command, a lookup key, and possibly a -lookup result. +The tcp_table protocol supports only the lookup request. +The request has the following form: .IP "\fBget\fR SPACE \fIkey\fR NEWLINE" Look up data under the specified key. -.IP "\fBput\fR SPACE \fIkey\fR SPACE \fIvalue\fR NEWLINE" -This request is currently not implemented. +.PP +Postfix will not generate partial search keys such as domain +names without one or more subdomains, network addresses +without one or more least\-significant octets, or email +addresses without the localpart, address extension or domain +portion. This behavior is also found with cidr:, pcre:, and +regexp: tables. .SH "REPLY FORMAT" .na .nf @@ -58,7 +63,6 @@ Each reply specifies a status code and text. Replies must be no longer than 4096 characters including the newline terminator. .IP "\fB500\fR SPACE \fItext\fR NEWLINE" In case of a lookup request, the requested data does not exist. -In case of an update request, the request was rejected. The text describes the nature of the problem. .IP "\fB400\fR SPACE \fItext\fR NEWLINE" This indicates an error condition. The text describes the nature of diff --git a/external/ibm-public/postfix/dist/man/man5/transport.5 b/external/ibm-public/postfix/dist/man/man5/transport.5 index 67419d1b537..deae0d50845 100644 --- a/external/ibm-public/postfix/dist/man/man5/transport.5 +++ b/external/ibm-public/postfix/dist/man/man5/transport.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: transport.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: transport.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH TRANSPORT 5 .ad @@ -145,13 +145,18 @@ The transport field specifies the name of a mail delivery transport (the first name of a mail delivery service entry in the Postfix \fBmaster.cf\fR file). -The interpretation of the nexthop field is transport -dependent. In the case of SMTP, specify a service on a non\-default +The nexthop field usually specifies one recipient domain +or hostname. In the case of the Postfix SMTP/LMTP client, +the nexthop field may contain a list of nexthop destinations +separated by comma or whitespace (Postfix 3.5 and later). + +The syntax of a nexthop destination is transport dependent. +With SMTP, specify a service on a non\-default port as \fIhost\fR:\fIservice\fR, and disable MX (mail exchanger) DNS lookups with [\fIhost\fR] or [\fIhost\fR]:\fIport\fR. The [] form is required when you specify an IP address instead of a hostname. -A null \fItransport\fR and null \fInexthop\fR result means "do +A null \fItransport\fR and null \fInexthop\fR field means "do not change": use the delivery transport and nexthop information that would be used when the entire transport table did not exist. @@ -209,8 +214,8 @@ In the above example, the [] suppress MX lookups. This prevents mail routing loops when your machine is primary MX host for \fBexample.com\fR. -In the case of delivery via SMTP, one may specify -\fIhostname\fR:\fIservice\fR instead of just a host: +In the case of delivery via SMTP or LMTP, one may specify +\fIhost\fR:\fIservice\fR instead of just a host: .nf \fBexample.com smtp:bar.example:2025\fR @@ -220,6 +225,16 @@ This directs mail for \fIuser\fR@\fBexample.com\fR to host \fBbar.example\fR port \fB2025\fR. Instead of a numerical port a symbolic name may be used. Specify [] around the hostname if MX lookups must be disabled. +Deliveries via SMTP or LMTP support multiple destinations +(Postfix >= 3.5): + +.nf + \fBexample.com smtp:bar.example, foo.example\fR +.fi + +This tries to deliver to \fBbar.example\fR before trying +to deliver to \fBfoo.example\fR. + The error mailer can be used to bounce mail: .nf @@ -273,14 +288,15 @@ Results are the same as with indexed file lookups. The following \fBmain.cf\fR parameters are especially relevant. The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. -.IP \fBempty_address_recipient\fR -The address that is looked up instead of the null sender address. -.IP \fBparent_domain_matches_subdomains\fR -List of Postfix features that use \fIdomain.tld\fR patterns -to match \fIsub.domain.tld\fR (as opposed to -requiring \fI.domain.tld\fR patterns). -.IP \fBtransport_maps\fR -List of transport lookup tables. +.IP "\fBempty_address_recipient (MAILER\-DAEMON)\fR" +The recipient of mail addressed to the null address. +.IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR" +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 "\fBtransport_maps (empty)\fR" +Optional lookup tables with mappings from recipient address to +(message delivery transport, next\-hop destination). .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man5/virtual.5 b/external/ibm-public/postfix/dist/man/man5/virtual.5 index e521a0e29ba..7373fbefda9 100644 --- a/external/ibm-public/postfix/dist/man/man5/virtual.5 +++ b/external/ibm-public/postfix/dist/man/man5/virtual.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: virtual.5,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: virtual.5,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH VIRTUAL 5 .ad @@ -88,8 +88,12 @@ starts with whitespace continues a logical line. .ad .fi 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: +tables such as NIS, LDAP or SQL, each \fIuser\fR@\fIdomain\fR +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. .IP "\fIuser\fR@\fIdomain address, address, ...\fR" Redirect mail for \fIuser\fR@\fIdomain\fR to \fIaddress\fR. This form has the highest precedence. @@ -113,6 +117,23 @@ 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. +.sp +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: + +.nf + smtpd_recipient_restrictions = + ... + reject_unauth_destination + check_recipient_access + inline:{example.com=reject_unverified_recipient} + unverified_recipient_reject_code = 550 +.fi + +In the above example, Postfix may contact a remote server +if the recipient is aliased to a remote address. .SH "RESULT ADDRESS REWRITING" .na .nf @@ -248,31 +269,35 @@ The following \fBmain.cf\fR parameters are especially relevant to 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\fR -List of virtual aliasing tables. -.IP \fBvirtual_alias_domains\fR -List of virtual alias domains. This uses the same syntax -as the \fBmydestination\fR parameter. -.IP \fBpropagate_unmatched_extensions\fR -A list of address rewriting or forwarding mechanisms that propagate -an address extension from the original address to the result. -Specify zero or more of \fBcanonical\fR, \fBvirtual\fR, \fBalias\fR, -\fBforward\fR, \fBinclude\fR, or \fBgeneric\fR. +.IP "\fBvirtual_alias_maps ($virtual_maps)\fR" +Optional lookup tables that alias specific mail addresses or domains +to other local or remote address. +.IP "\fBvirtual_alias_domains ($virtual_alias_maps)\fR" +Postfix is 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 "\fBpropagate_unmatched_extensions (canonical, virtual)\fR" +What address lookup tables copy an address extension from the lookup +key to the lookup result. .PP Other parameters of interest: -.IP \fBinet_interfaces\fR -The network interface addresses that this system receives mail on. -You need to stop and start Postfix when this parameter changes. -.IP \fBmydestination\fR -List of domains that this mail system considers local. -.IP \fBmyorigin\fR -The domain that is appended to any address that does not have a domain. -.IP \fBowner_request_special\fR -Give special treatment to \fBowner\-\fIxxx\fR and \fIxxx\fB\-request\fR -addresses. -.IP \fBproxy_interfaces\fR -Other interfaces that this machine receives mail on by way of a -proxy agent or network address translator. +.IP "\fBinet_interfaces (all)\fR" +The 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. +.IP "\fBmyorigin ($myhostname)\fR" +The domain name that locally\-posted mail appears to come +from, and that locally posted mail is delivered to. +.IP "\fBowner_request_special (yes)\fR" +Enable special treatment for owner\-\fIlistname\fR entries in the +\fBaliases\fR(5) file, and don't split owner\-\fIlistname\fR and +\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 +on by way of a proxy or network address translation unit. .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man8/anvil.8 b/external/ibm-public/postfix/dist/man/man8/anvil.8 index cd09e6309b5..172c9c08e0b 100644 --- a/external/ibm-public/postfix/dist/man/man8/anvil.8 +++ b/external/ibm-public/postfix/dist/man/man8/anvil.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: anvil.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: anvil.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH ANVIL 8 .ad @@ -187,7 +187,8 @@ the time unit over which state is kept. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Upon exit, and every \fBanvil_status_update_time\fR seconds, the server logs the maximal count and rate values measured, @@ -255,8 +256,12 @@ The process name of a Postfix command or daemon process. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man8/bounce.8 b/external/ibm-public/postfix/dist/man/man8/bounce.8 index f4a266dcbae..e4cae8b2564 100644 --- a/external/ibm-public/postfix/dist/man/man8/bounce.8 +++ b/external/ibm-public/postfix/dist/man/man8/bounce.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: bounce.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: bounce.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH BOUNCE 8 .ad @@ -56,7 +56,8 @@ RFC 6533 (Internationalized Delivery Status Notifications) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH "CONFIGURATION PARAMETERS" .na .nf @@ -126,13 +127,17 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix 3.0 and later: .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "FILES" .na .nf @@ -147,6 +152,7 @@ qmgr(8), queue manager postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/cleanup.8 b/external/ibm-public/postfix/dist/man/man8/cleanup.8 index 62d05774369..eb76f4391f4 100644 --- a/external/ibm-public/postfix/dist/man/man8/cleanup.8 +++ b/external/ibm-public/postfix/dist/man/man8/cleanup.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: cleanup.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: cleanup.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH CLEANUP 8 .ad @@ -66,7 +66,8 @@ RFC 5322 (Internet Message Format) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -288,7 +289,7 @@ Optional list of domains whose subdomain structure will be stripped off in email addresses. .IP "\fBmasquerade_exceptions (empty)\fR" Optional list of user names that are not subjected to address -masquerading, even when their address matches $masquerade_domains. +masquerading, even when their addresses match $masquerade_domains. .IP "\fBpropagate_unmatched_extensions (canonical, virtual)\fR" What address lookup tables copy an address extension from the lookup key to the lookup result. @@ -372,6 +373,12 @@ in RFC 6531..6533. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBenable_idna2003_compatibility (no)\fR" +Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF\-8 domain names to/from the ASCII form that is +used for DNS lookups. .SH "MISCELLANEOUS CONTROLS" .na .nf @@ -415,12 +422,23 @@ the sender. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 2.1 and later: .IP "\fBenable_original_recipient (yes)\fR" -Enable support for the X\-Original\-To message header. +Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "FILES" .na .nf @@ -438,6 +456,7 @@ virtual(5), virtual alias lookup table format postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/discard.8 b/external/ibm-public/postfix/dist/man/man8/discard.8 index 92831709cef..33dc283dd9a 100644 --- a/external/ibm-public/postfix/dist/man/man8/discard.8 +++ b/external/ibm-public/postfix/dist/man/man8/discard.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: discard.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: discard.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH DISCARD 8 .ad @@ -45,7 +45,8 @@ RFC 3463 (Enhanced Status Codes) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Depending on the setting of the \fBnotify_classes\fR parameter, the postmaster is notified of bounces and of other trouble. @@ -90,8 +91,12 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf @@ -101,6 +106,7 @@ error(8), Postfix error delivery agent postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/dnsblog.8 b/external/ibm-public/postfix/dist/man/man8/dnsblog.8 index 7ccb4eb4c04..0dde8ffbe8b 100644 --- a/external/ibm-public/postfix/dist/man/man8/dnsblog.8 +++ b/external/ibm-public/postfix/dist/man/man8/dnsblog.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: dnsblog.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: dnsblog.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH DNSBLOG 8 .ad @@ -30,12 +30,14 @@ If the IP address is listed under the DNS white/blacklist, the query arguments plus an address list with the resulting IP addresses, separated by whitespace, and the reply TTL. Otherwise it replies with the query arguments plus an empty -address list and the reply TTL (\-1 if unavailable). Finally, -The \fBdnsblog\fR(8) server closes the connection. +address list and the reply TTL; the reply TTL is \-1 if there +is no reply, or a negative reply that contains no SOA record. +Finally, the \fBdnsblog\fR(8) server closes the connection. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH "CONFIGURATION PARAMETERS" .na .nf @@ -69,23 +71,28 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf smtpd(8), Postfix SMTP server postconf(5), configuration parameters -syslogd(5), system logging +postlogd(8), Postfix logging +syslogd(8), system logging .SH "LICENSE" .na .nf .ad .fi The Secure Mailer license must be distributed with this software. -.SH "HISTORY" -.na -.nf +.SH HISTORY +.ad +.fi .ad .fi This service was introduced with Postfix version 2.8. diff --git a/external/ibm-public/postfix/dist/man/man8/error.8 b/external/ibm-public/postfix/dist/man/man8/error.8 index 4e5c40d2707..aaf22ebce0f 100644 --- a/external/ibm-public/postfix/dist/man/man8/error.8 +++ b/external/ibm-public/postfix/dist/man/man8/error.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: error.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: error.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH ERROR 8 .ad @@ -46,7 +46,8 @@ RFC 3463 (Enhanced Status Codes) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Depending on the setting of the \fBnotify_classes\fR parameter, the postmaster is notified of bounces and of other trouble. @@ -100,8 +101,12 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf @@ -111,6 +116,7 @@ discard(8), Postfix discard delivery agent postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/flush.8 b/external/ibm-public/postfix/dist/man/man8/flush.8 index bcee2e5e58d..d04f716e63e 100644 --- a/external/ibm-public/postfix/dist/man/man8/flush.8 +++ b/external/ibm-public/postfix/dist/man/man8/flush.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: flush.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: flush.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH FLUSH 8 .ad @@ -65,7 +65,8 @@ The fast flush server can run chrooted at fixed low privilege. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -130,8 +131,12 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "FILES" .na .nf @@ -144,6 +149,7 @@ qmgr(8), queue manager postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/local.8 b/external/ibm-public/postfix/dist/man/man8/local.8 index b748d553de7..d7c7971a1e0 100644 --- a/external/ibm-public/postfix/dist/man/man8/local.8 +++ b/external/ibm-public/postfix/dist/man/man8/local.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: local.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: local.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH LOCAL 8 .ad @@ -342,7 +342,8 @@ RFC 3463 (Enhanced status codes) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Corrupted message files are marked so that the queue manager can move them to the \fBcorrupt\fR queue afterwards. @@ -397,13 +398,14 @@ The text below provides only a parameter summary. See .IP "\fBbiff (yes)\fR" Whether or not to use the local biff service. .IP "\fBexpand_owner_alias (no)\fR" -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. +When delivering to an alias "\fIaliasname\fR" that has an +"owner\-\fIaliasname\fR" companion alias, set the envelope sender +address to the expansion of the "owner\-\fIaliasname\fR" alias. .IP "\fBowner_request_special (yes)\fR" -Give special treatment to owner\-listname and listname\-request -address localparts: don't split such addresses when the -recipient_delimiter is set to "\-". +Enable special treatment for owner\-\fIlistname\fR entries in the +\fBaliases\fR(5) file, and don't split owner\-\fIlistname\fR and +\fIlistname\fR\-request address localparts when the recipient_delimiter +is set to "\-". .IP "\fBsun_mailtool_compatibility (no)\fR" Obsolete SUN mailtool compatibility feature. .PP @@ -502,6 +504,11 @@ Time limit for delivery to external commands. The maximal number of addresses remembered by the address duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or for \fBshowq\fR(8) queue displays. +.IP "\fBmailbox_size_limit (51200000)\fR" +The maximal size of any \fBlocal\fR(8) individual mailbox or maildir +file, or zero (no limit). +.PP +Implemented in the qmgr(8) daemon: .IP "\fBlocal_destination_concurrency_limit (2)\fR" The maximal number of parallel deliveries via the local mail delivery transport to the same recipient (when @@ -511,9 +518,6 @@ parallel deliveries to the same local domain (when .IP "\fBlocal_destination_recipient_limit (1)\fR" The maximal number of recipients per message delivery via the local mail delivery transport. -.IP "\fBmailbox_size_limit (51200000)\fR" -The maximal size of any \fBlocal\fR(8) individual mailbox or maildir -file, or zero (no limit). .SH "SECURITY CONTROLS" .na .nf @@ -592,8 +596,21 @@ before mail delivery is attempted. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix version 3.3 and later: +.IP "\fBenable_original_recipient (yes)\fR" +Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "FILES" .na .nf @@ -611,6 +628,7 @@ postalias(1), create/update alias database aliases(5), format of alias database postconf(5), configuration parameters master(5), generic daemon options +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/master.8 b/external/ibm-public/postfix/dist/man/man8/master.8 index 976af884dd1..3e5181b74c1 100644 --- a/external/ibm-public/postfix/dist/man/man8/master.8 +++ b/external/ibm-public/postfix/dist/man/man8/master.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: master.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: master.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH MASTER 8 .ad @@ -10,7 +10,7 @@ Postfix master process .SH "SYNOPSIS" .na .nf -\fBmaster\fR [\fB\-Ddtvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-e \fIexit_time\fR] +\fBmaster\fR [\fB\-Dditvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-e \fIexit_time\fR] .SH DESCRIPTION .ad .fi @@ -45,6 +45,18 @@ for debugging only. .IP "\fB\-e \fIexit_time\fR" Terminate the master process after \fIexit_time\fR seconds. Child processes terminate at their convenience. +.IP \fB\-i\fR +Enable \fBinit\fR mode: do not become a session or process +group leader; and similar to \fB\-s\fR, do not redirect stdout +to /dev/null, so that "maillog_file = /dev/stdout" works. +This mode is allowed only if the process ID equals 1. +.sp +This feature is available in Postfix 3.3 and later. +.IP \fB\-s\fR +Do not redirect stdout to /dev/null, so that "maillog_file += /dev/stdout" works. +.sp +This feature is available in Postfix 3.4 and later. .IP \fB\-t\fR Test mode. Return a zero exit status when the \fBmaster.pid\fR lock file does not exist or when that file is not locked. This is evidence @@ -81,7 +93,8 @@ processes to finish what they are doing. .SH DIAGNOSTICS .ad .fi -Problems are reported to \fBsyslogd\fR(8). The exit status +Problems are reported to \fBsyslogd\fR(8) or \fBpostlogd\fR(8). +The exit status is non\-zero in case of problems, including problems while initializing as a master daemon process in the background. .SH "ENVIRONMENT" @@ -146,8 +159,9 @@ mail on. 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 Postfix process will -import from a non\-Postfix parent process. +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBmail_owner (postfix)\fR" The UNIX system account that owns the Postfix queue and most Postfix daemon processes. @@ -160,8 +174,12 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "FILES" .na .nf @@ -183,6 +201,7 @@ qmgr(8), queue manager verify(8), address verification master(5), master.cf configuration file syntax postconf(5), main.cf configuration file syntax +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/oqmgr.8 b/external/ibm-public/postfix/dist/man/man8/oqmgr.8 index f993dfa57d9..78f7b1abd33 100644 --- a/external/ibm-public/postfix/dist/man/man8/oqmgr.8 +++ b/external/ibm-public/postfix/dist/man/man8/oqmgr.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: oqmgr.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: oqmgr.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH OQMGR 8 .ad @@ -149,7 +149,8 @@ privilege in a chrooted environment. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to the \fBsyslog\fR(8) daemon. +Problems and transactions are logged to the \fBsyslogd\fR(8) +or \fBpostlogd\fR(8) daemon. Corrupted message files are saved to the \fBcorrupt\fR queue for further inspection. @@ -220,31 +221,44 @@ to the same destination. .IP "\fBdefault_destination_concurrency_limit (20)\fR" The default maximal number of parallel deliveries to the same destination. -.IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +A transport\-specific override for the +default_destination_concurrency_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. .PP Available in Postfix version 2.5 and later: -.IP "\fItransport\fB_initial_destination_concurrency ($initial_destination_concurrency)\fR" -Initial concurrency for delivery via the named message -\fItransport\fR. +.IP "\fBtransport_initial_destination_concurrency ($initial_destination_concurrency)\fR" +A transport\-specific override for the initial_destination_concurrency +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .IP "\fBdefault_destination_concurrency_failed_cohort_limit (1)\fR" How many pseudo\-cohorts must suffer connection or handshake failure before a specific destination is considered unavailable (and further delivery is suspended). -.IP "\fItransport\fB_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" +A transport\-specific override for the +default_destination_concurrency_failed_cohort_limit parameter value, +where \fItransport\fR is the master.cf name of the message delivery +transport. .IP "\fBdefault_destination_concurrency_negative_feedback (1)\fR" The per\-destination amount of delivery concurrency negative feedback, after a delivery completes with a connection or handshake failure. -.IP "\fItransport\fB_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" +A transport\-specific override for the +default_destination_concurrency_negative_feedback parameter value, +where \fItransport\fR is the master.cf name of the message delivery +transport. .IP "\fBdefault_destination_concurrency_positive_feedback (1)\fR" The per\-destination amount of delivery concurrency positive feedback, after a delivery completes without connection or handshake failure. -.IP "\fItransport\fB_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" +A transport\-specific override for the +default_destination_concurrency_positive_feedback parameter value, +where \fItransport\fR is the master.cf name of the message delivery +transport. .IP "\fBdestination_concurrency_feedback_debug (no)\fR" Make the queue manager's feedback algorithm verbose for performance analysis purposes. @@ -255,8 +269,11 @@ analysis purposes. .fi .IP "\fBdefault_destination_recipient_limit (50)\fR" The default maximal number of recipients per message delivery. -.IP \fItransport\fB_destination_recipient_limit\fR -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +A transport\-specific override for the +default_destination_recipient_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. .SH "OTHER RESOURCE AND RATE CONTROLS" .na .nf @@ -287,18 +304,22 @@ bounce_queue_lifetime limit. Available in Postfix version 2.5 and later: .IP "\fBdefault_destination_rate_delay (0s)\fR" The default amount of delay that is inserted between individual -deliveries to the same destination; the resulting behavior depends -on the value of the corresponding per\-destination recipient limit. -.IP "\fItransport\fB_destination_rate_delay $default_destination_rate_delay\fR" -Idem, for delivery via the named message \fItransport\fR. +message deliveries to the same destination and over the same message +delivery transport. +.IP "\fBtransport_destination_rate_delay ($default_destination_rate_delay)\fR" +A transport\-specific override for the default_destination_rate_delay +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .PP Available in Postfix version 3.1 and later: .IP "\fBdefault_transport_rate_delay (0s)\fR" The default amount of delay that is inserted between individual -deliveries over the same message delivery transport, regardless of -destination. -.IP "\fItransport\fB_transport_rate_delay $default_transport_rate_delay\fR" -Idem, for delivery via the named message \fItransport\fR. +message deliveries over the same message delivery transport, +regardless of destination. +.IP "\fBtransport_transport_rate_delay ($default_transport_rate_delay)\fR" +A transport\-specific override for the default_transport_rate_delay +parameter value, where the initial \fItransport\fR in the parameter +name is the master.cf name of the message delivery transport. .SH "SAFETY CONTROLS" .na .nf @@ -341,13 +362,22 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 3.0 and later: .IP "\fBconfirm_delay_cleared (no)\fR" After sending a "your message is delayed" notification, inform the sender when the delay clears up. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "FILES" .na .nf @@ -365,6 +395,7 @@ bounce(8), delivery status reports postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/pickup.8 b/external/ibm-public/postfix/dist/man/man8/pickup.8 index 63288746f34..84366fa409b 100644 --- a/external/ibm-public/postfix/dist/man/man8/pickup.8 +++ b/external/ibm-public/postfix/dist/man/man8/pickup.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: pickup.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: pickup.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH PICKUP 8 .ad @@ -41,7 +41,8 @@ that is sent to its public service endpoint. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -100,8 +101,17 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "SEE ALSO" .na .nf @@ -111,6 +121,7 @@ postdrop(1), mail posting agent postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/pipe.8 b/external/ibm-public/postfix/dist/man/man8/pipe.8 index dd56e4fefd8..36219e3bd46 100644 --- a/external/ibm-public/postfix/dist/man/man8/pipe.8 +++ b/external/ibm-public/postfix/dist/man/man8/pipe.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: pipe.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: pipe.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH PIPE 8 .ad @@ -203,7 +203,7 @@ shell meta characters by a shell command interpreter. .sp Specify "{" and "}" around command arguments that contain whitespace (Postfix 3.0 and later). Whitespace -after "{" and before "}" is ignored. +after the opening "{" and before the closing "}" is ignored. .sp In the command argument vector, the following macros are recognized and replaced with corresponding information from the Postfix queue @@ -347,7 +347,8 @@ delivery status notifications (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 \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Corrupted message files are marked so that the queue manager can move them to the \fBcorrupt\fR queue for further inspection. .SH "SECURITY" @@ -376,22 +377,22 @@ The text below provides only a parameter summary. See .fi In the text below, \fItransport\fR is the first field in a \fBmaster.cf\fR entry. -.IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -Limit the number of parallel deliveries to the same destination, -for delivery via the named \fItransport\fR. -The limit is enforced by the Postfix queue manager. -.IP "\fItransport\fB_destination_recipient_limit ($default_destination_recipient_limit)\fR" -Limit the number of recipients per message delivery, for delivery -via the named \fItransport\fR. -The limit is enforced by the Postfix queue manager. -.IP "\fItransport\fB_time_limit ($command_time_limit)\fR" -Limit the time for delivery to external command, for delivery via -the named \fItransport\fR. -The limit is enforced by the pipe delivery agent. - -Postfix 2.4 and later support a suffix that specifies the -time unit: s (seconds), m (minutes), h (hours), d (days), -w (weeks). The default time unit is seconds. +.IP "\fBtransport_time_limit ($command_time_limit)\fR" +A transport\-specific override for the command_time_limit parameter +value, where \fItransport\fR is the master.cf name of the message +delivery transport. +.PP +Implemented in the qmgr(8) daemon: +.IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +A transport\-specific override for the +default_destination_concurrency_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. +.IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +A transport\-specific override for the +default_destination_recipient_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. .SH "MISCELLANEOUS CONTROLS" .na .nf @@ -434,14 +435,27 @@ extension (example: .forward+foo). .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 3.0 and later: .IP "\fBpipe_delivery_status_filter ($default_delivery_status_filter)\fR" Optional filter for the \fBpipe\fR(8) delivery agent to change the delivery status code or explanatory text of successful or unsuccessful deliveries. +.PP +Available in Postfix version 3.3 and later: +.IP "\fBenable_original_recipient (yes)\fR" +Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "SEE ALSO" .na .nf @@ -450,6 +464,7 @@ bounce(8), delivery status reports postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/postlogd.8 b/external/ibm-public/postfix/dist/man/man8/postlogd.8 index 8fac39ba637..d24daa663bf 100644 --- a/external/ibm-public/postfix/dist/man/man8/postlogd.8 +++ b/external/ibm-public/postfix/dist/man/man8/postlogd.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: postlogd.8,v 1.1.1.1 2020/03/18 18:59:30 christos Exp $ +.\" $NetBSD: postlogd.8,v 1.2 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTLOGD 8 .ad diff --git a/external/ibm-public/postfix/dist/man/man8/postscreen.8 b/external/ibm-public/postfix/dist/man/man8/postscreen.8 index 71f03166439..1c23d7a710a 100644 --- a/external/ibm-public/postfix/dist/man/man8/postscreen.8 +++ b/external/ibm-public/postfix/dist/man/man8/postscreen.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: postscreen.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: postscreen.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH POSTSCREEN 8 .ad @@ -24,9 +24,9 @@ delays the onset of server overload conditions. This program should not be used on SMTP ports that receive mail from end\-user clients (MUAs). In a typical deployment, -\fBpostscreen\fR(8) handles the MX service on TCP port 25, -while MUA clients submit mail via the \fBsubmission\fR -service on TCP port 587 which requires client authentication. +\fBpostscreen\fR(8) handles the MX service on TCP port 25, and +\fBsmtpd\fR(8) receives mail from MUAs on the \fBsubmission\fR +service (TCP port 587) which requires client authentication. Alternatively, a site could set up a dedicated, non\-postscreen, "port 25" server that provides \fBsubmission\fR service and client authentication, but no MX service. @@ -73,6 +73,7 @@ RFC 1985 (ETRN command) RFC 2034 (SMTP Enhanced Status Codes) RFC 2821 (SMTP protocol) Not: RFC 2920 (SMTP Pipelining) +RFC 3030 (CHUNKING without BINARYMIME) RFC 3207 (STARTTLS command) RFC 3461 (SMTP DSN Extension) RFC 3463 (Enhanced Status Codes) @@ -80,7 +81,8 @@ RFC 5321 (SMTP protocol, including multi\-line 220 banners) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -89,22 +91,14 @@ currently does not announce support for AUTH, XCLIENT or XFORWARD. If you need to make these services available on port 25, then do not enable the optional "after 220 -server greeting" tests, and do not use DNSBLs that reject -traffic from dial\-up and residential networks. +server greeting" tests. -The optional "after 220 server greeting" tests involve -\fBpostscreen\fR(8)'s built\-in SMTP protocol engine. When -these tests succeed, \fBpostscreen\fR(8) adds the client -to the temporary whitelist, but it cannot hand off the -"live" connection to a Postfix SMTP server process in the -middle of a session. Instead, \fBpostscreen\fR(8) defers -attempts to deliver mail with a 4XX status, and waits for -the client to disconnect. When the client connects again, -\fBpostscreen\fR(8) will allow the client to talk to a -Postfix SMTP server process (provided that the whitelist -status has not expired). \fBpostscreen\fR(8) mitigates -the impact of this limitation by giving the "after 220 -server greeting" tests a long expiration time. +The optional "after 220 server greeting" tests may result in +unexpected delivery delays from senders that retry email delivery +from a different IP address. Reason: after passing these tests a +new client must disconnect, and reconnect from the same IP +address before it can deliver mail. See POSTSCREEN_README, section +"Tests after the 220 SMTP server greeting", for a discussion. .SH "CONFIGURATION PARAMETERS" .na .nf @@ -145,6 +139,11 @@ response to a remote SMTP client. Available in Postfix version 3.1 and later: .IP "\fBdns_ncache_ttl_fix_enable (no)\fR" Enable a workaround for future libc incompatibility. +.PP +Available in Postfix version 3.4 and later: +.IP "\fBpostscreen_reject_footer_maps ($smtpd_reject_footer_maps)\fR" +Optional lookup table for information that is appended after a 4XX +or 5XX \fBpostscreen\fR(8) server response. .SH "TROUBLE SHOOTING CONTROLS" .na .nf @@ -407,14 +406,24 @@ The process name of a Postfix command or daemon process. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "SEE ALSO" .na .nf smtpd(8), Postfix SMTP server tlsproxy(8), Postfix TLS proxy server dnsblog(8), DNS black/whitelist logger +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/proxymap.8 b/external/ibm-public/postfix/dist/man/man8/proxymap.8 index da0d4a38b85..2a072994c0b 100644 --- a/external/ibm-public/postfix/dist/man/man8/proxymap.8 +++ b/external/ibm-public/postfix/dist/man/man8/proxymap.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: proxymap.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: proxymap.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH PROXYMAP 8 .ad @@ -138,7 +138,8 @@ does not match the provider of its content. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -199,6 +200,10 @@ caches, pseudo\-random numbers). .IP "\fBproxy_write_maps (see 'postconf -d' output)\fR" The lookup tables that the \fBproxymap\fR(8) server is allowed to access for the read\-write service. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man8/qmgr.8 b/external/ibm-public/postfix/dist/man/man8/qmgr.8 index 3bccfbe488e..f9a751bc039 100644 --- a/external/ibm-public/postfix/dist/man/man8/qmgr.8 +++ b/external/ibm-public/postfix/dist/man/man8/qmgr.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: qmgr.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: qmgr.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH QMGR 8 .ad @@ -153,7 +153,8 @@ privilege in a chrooted environment. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to the syslog daemon. +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Corrupted message files are saved to the \fBcorrupt\fR queue for further inspection. @@ -214,24 +215,32 @@ The minimal number of in\-memory recipients for any message. .IP "\fBdefault_recipient_limit (20000)\fR" The default per\-transport upper limit on the number of in\-memory recipients. -.IP "\fItransport\fB_recipient_limit ($default_recipient_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_recipient_limit ($default_recipient_limit)\fR" +A transport\-specific override for the default_recipient_limit +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .IP "\fBdefault_extra_recipient_limit (1000)\fR" The default value for the extra per\-transport limit imposed on the number of in\-memory recipients. -.IP "\fItransport\fB_extra_recipient_limit ($default_extra_recipient_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_extra_recipient_limit ($default_extra_recipient_limit)\fR" +A transport\-specific override for the default_extra_recipient_limit +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .PP Available in Postfix version 2.4 and later: .IP "\fBdefault_recipient_refill_limit (100)\fR" The default per\-transport limit on the number of recipients refilled at once. -.IP "\fItransport\fB_recipient_refill_limit ($default_recipient_refill_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_recipient_refill_limit ($default_recipient_refill_limit)\fR" +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. -.IP "\fItransport\fB_recipient_refill_delay ($default_recipient_refill_delay)\fR" -Idem, for delivery via the named message \fItransport\fR. +.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 +the message delivery transport. .SH "DELIVERY CONCURRENCY CONTROLS" .na .nf @@ -243,31 +252,44 @@ to the same destination. .IP "\fBdefault_destination_concurrency_limit (20)\fR" The default maximal number of parallel deliveries to the same destination. -.IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +A transport\-specific override for the +default_destination_concurrency_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. .PP Available in Postfix version 2.5 and later: -.IP "\fItransport\fB_initial_destination_concurrency ($initial_destination_concurrency)\fR" -Initial concurrency for delivery via the named message -\fItransport\fR. +.IP "\fBtransport_initial_destination_concurrency ($initial_destination_concurrency)\fR" +A transport\-specific override for the initial_destination_concurrency +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .IP "\fBdefault_destination_concurrency_failed_cohort_limit (1)\fR" How many pseudo\-cohorts must suffer connection or handshake failure before a specific destination is considered unavailable (and further delivery is suspended). -.IP "\fItransport\fB_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" +A transport\-specific override for the +default_destination_concurrency_failed_cohort_limit parameter value, +where \fItransport\fR is the master.cf name of the message delivery +transport. .IP "\fBdefault_destination_concurrency_negative_feedback (1)\fR" The per\-destination amount of delivery concurrency negative feedback, after a delivery completes with a connection or handshake failure. -.IP "\fItransport\fB_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" +A transport\-specific override for the +default_destination_concurrency_negative_feedback parameter value, +where \fItransport\fR is the master.cf name of the message delivery +transport. .IP "\fBdefault_destination_concurrency_positive_feedback (1)\fR" The per\-destination amount of delivery concurrency positive feedback, after a delivery completes without connection or handshake failure. -.IP "\fItransport\fB_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" +A transport\-specific override for the +default_destination_concurrency_positive_feedback parameter value, +where \fItransport\fR is the master.cf name of the message delivery +transport. .IP "\fBdestination_concurrency_feedback_debug (no)\fR" Make the queue manager's feedback algorithm verbose for performance analysis purposes. @@ -278,8 +300,11 @@ analysis purposes. .fi .IP "\fBdefault_destination_recipient_limit (50)\fR" The default maximal number of recipients per message delivery. -.IP "\fItransport\fB_destination_recipient_limit ($default_destination_recipient_limit)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +A transport\-specific override for the +default_destination_recipient_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. .SH "MESSAGE SCHEDULING CONTROLS" .na .nf @@ -288,23 +313,31 @@ Idem, for delivery via the named message \fItransport\fR. .IP "\fBdefault_delivery_slot_cost (5)\fR" How often the Postfix queue manager's scheduler is allowed to preempt delivery of one message with another. -.IP "\fItransport\fB_delivery_slot_cost ($default_delivery_slot_cost)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_delivery_slot_cost ($default_delivery_slot_cost)\fR" +A transport\-specific override for the default_delivery_slot_cost +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .IP "\fBdefault_minimum_delivery_slots (3)\fR" How many recipients a message must have in order to invoke the Postfix queue manager's scheduling algorithm at all. -.IP "\fItransport\fB_minimum_delivery_slots ($default_minimum_delivery_slots)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_minimum_delivery_slots ($default_minimum_delivery_slots)\fR" +A transport\-specific override for the default_minimum_delivery_slots +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .IP "\fBdefault_delivery_slot_discount (50)\fR" The default value for transport\-specific _delivery_slot_discount settings. -.IP "\fItransport\fB_delivery_slot_discount ($default_delivery_slot_discount)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_delivery_slot_discount ($default_delivery_slot_discount)\fR" +A transport\-specific override for the default_delivery_slot_discount +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .IP "\fBdefault_delivery_slot_loan (3)\fR" The default value for transport\-specific _delivery_slot_loan settings. -.IP "\fItransport\fB_delivery_slot_loan ($default_delivery_slot_loan)\fR" -Idem, for delivery via the named message \fItransport\fR. +.IP "\fBtransport_delivery_slot_loan ($default_delivery_slot_loan)\fR" +A transport\-specific override for the default_delivery_slot_loan +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .SH "OTHER RESOURCE AND RATE CONTROLS" .na .nf @@ -335,18 +368,22 @@ bounce_queue_lifetime limit. Available in Postfix version 2.5 and later: .IP "\fBdefault_destination_rate_delay (0s)\fR" The default amount of delay that is inserted between individual -deliveries to the same destination; the resulting behavior depends -on the value of the corresponding per\-destination recipient limit. -.IP "\fItransport\fB_destination_rate_delay $default_destination_rate_delay\fR" -Idem, for delivery via the named message \fItransport\fR. +message deliveries to the same destination and over the same message +delivery transport. +.IP "\fBtransport_destination_rate_delay ($default_destination_rate_delay)\fR" +A transport\-specific override for the default_destination_rate_delay +parameter value, where \fItransport\fR is the master.cf name of +the message delivery transport. .PP Available in Postfix version 3.1 and later: .IP "\fBdefault_transport_rate_delay (0s)\fR" The default amount of delay that is inserted between individual -deliveries over the same message delivery transport, regardless of -destination. -.IP "\fItransport\fB_transport_rate_delay $default_transport_rate_delay\fR" -Idem, for delivery via the named message \fItransport\fR. +message deliveries over the same message delivery transport, +regardless of destination. +.IP "\fBtransport_transport_rate_delay ($default_transport_rate_delay)\fR" +A transport\-specific override for the default_transport_rate_delay +parameter value, where the initial \fItransport\fR in the parameter +name is the master.cf name of the message delivery transport. .SH "SAFETY CONTROLS" .na .nf @@ -389,13 +426,22 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 3.0 and later: .IP "\fBconfirm_delay_cleared (no)\fR" After sending a "your message is delayed" notification, inform the sender when the delay clears up. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "FILES" .na .nf @@ -413,6 +459,7 @@ bounce(8), delivery status reports postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/qmqpd.8 b/external/ibm-public/postfix/dist/man/man8/qmqpd.8 index 6d2aff7db36..f26b8029164 100644 --- a/external/ibm-public/postfix/dist/man/man8/qmqpd.8 +++ b/external/ibm-public/postfix/dist/man/man8/qmqpd.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: qmqpd.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: qmqpd.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH QMQPD 8 .ad @@ -33,7 +33,8 @@ run chrooted at fixed low privilege. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -80,6 +81,12 @@ in RFC 6531..6533. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBenable_idna2003_compatibility (no)\fR" +Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF\-8 domain names to/from the ASCII form that is +used for DNS lookups. .SH "RESOURCE AND RATE CONTROLS" .na .nf @@ -150,8 +157,8 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .IP "\fBverp_delimiter_filter (\-=+)\fR" The characters Postfix accepts as VERP delimiter characters on the Postfix \fBsendmail\fR(1) command line and in SMTP commands. @@ -160,12 +167,17 @@ Available in Postfix version 2.5 and later: .IP "\fBqmqpd_client_port_logging (no)\fR" Enable logging of the remote QMQP client port in addition to the hostname and IP address. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf http://cr.yp.to/proto/qmqp.html, QMQP protocol cleanup(8), message canonicalization master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/scache.8 b/external/ibm-public/postfix/dist/man/man8/scache.8 index 8ee7e060a77..9aee0554753 100644 --- a/external/ibm-public/postfix/dist/man/man8/scache.8 +++ b/external/ibm-public/postfix/dist/man/man8/scache.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: scache.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: scache.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SCACHE 8 .ad @@ -75,7 +75,8 @@ not be used to store information that is security sensitive. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -131,14 +132,19 @@ The process name of a Postfix command or daemon process. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf smtp(8), SMTP client postconf(5), configuration parameters master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/showq.8 b/external/ibm-public/postfix/dist/man/man8/showq.8 index ba97068f162..0a10aa86ec1 100644 --- a/external/ibm-public/postfix/dist/man/man8/showq.8 +++ b/external/ibm-public/postfix/dist/man/man8/showq.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: showq.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: showq.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SHOWQ 8 .ad @@ -40,7 +40,8 @@ outside world. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH "CONFIGURATION PARAMETERS" .na .nf @@ -82,12 +83,16 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 2.9 and later: .IP "\fBenable_long_queue_ids (no)\fR" Enable long, non\-repeating, queue IDs (queue file names). +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "FILES" .na .nf @@ -100,6 +105,7 @@ cleanup(8), canonicalize and enqueue mail qmgr(8), queue manager postconf(5), configuration parameters master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/smtp.8 b/external/ibm-public/postfix/dist/man/man8/smtp.8 index 2ed138a3c51..b481318828f 100644 --- a/external/ibm-public/postfix/dist/man/man8/smtp.8 +++ b/external/ibm-public/postfix/dist/man/man8/smtp.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: smtp.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: smtp.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SMTP 8 .ad @@ -10,7 +10,7 @@ Postfix SMTP+LMTP client .SH "SYNOPSIS" .na .nf -\fBsmtp\fR [generic Postfix daemon options] +\fBsmtp\fR [generic Postfix daemon options] [flags=DORX] .SH DESCRIPTION .ad .fi @@ -48,6 +48,8 @@ specific destinations. .nf .ad .fi +The Postfix SMTP+LMTP client supports multiple destinations +separated by comma or whitespace (Postfix 3.5 and later). SMTP destinations have the following form: .IP \fIdomainname\fR .IP \fIdomainname\fR:\fIport\fR @@ -67,6 +69,8 @@ must be formatted as [\fBipv6\fR:\fIaddress\fR]. .nf .ad .fi +The Postfix SMTP+LMTP client supports multiple destinations +separated by comma or whitespace (Postfix 3.5 and later). LMTP destinations have the following form: .IP \fBunix\fR:\fIpathname\fR Connect to the local UNIX\-domain server that is bound to the specified @@ -82,12 +86,68 @@ remote host. If no port is specified, connect to the port defined as If no such service is found, the \fBlmtp_tcp_port\fR configuration parameter (default value of 24) will be used. An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. -.PP -.SH "SECURITY" +.SH "SINGLE-RECIPIENT DELIVERY" .na .nf .ad .fi +By default, the Postfix SMTP+LMTP client delivers mail to +multiple recipients per delivery request. This is undesirable +when prepending a \fBDelivered\-to:\fR or \fBX\-Original\-To:\fR +message header. To prevent Postfix from sending multiple +recipients per delivery request, specify +.sp +.nf + \fItransport\fB_destination_recipient_limit = 1\fR +.fi + +in the Postfix \fBmain.cf\fR file, where \fItransport\fR +is the name in the first column of the Postfix \fBmaster.cf\fR +entry for this mail delivery service. +.SH "COMMAND ATTRIBUTE SYNTAX" +.na +.nf +.ad +.fi +.IP "\fBflags=DORX\fR (optional)" +Optional message processing flags. +.RS +.IP \fBD\fR +Prepend a "\fBDelivered\-To: \fIrecipient\fR" message header +with the envelope recipient address. Note: for this to work, +the \fItransport\fB_destination_recipient_limit\fR must be +1 (see SINGLE\-RECIPIENT DELIVERY above for details). +.sp +The \fBD\fR flag also enforces loop detection: if a message +already contains a \fBDelivered\-To:\fR header with the same +recipient address, then the message is returned as +undeliverable. The address comparison is case insensitive. +.sp +This feature is available as of Postfix 3.5. +.IP \fBO\fR +Prepend an "\fBX\-Original\-To: \fIrecipient\fR" message +header with the recipient address as given to Postfix. Note: +for this to work, the +\fItransport\fB_destination_recipient_limit\fR must be 1 +(see SINGLE\-RECIPIENT DELIVERY above for details). +.sp +This feature is available as of Postfix 3.5. +.IP \fBR\fR +Prepend a "\fBReturn\-Path: <\fIsender\fB>\fR" message header +with the envelope sender address. +.sp +This feature is available as of Postfix 3.5. +.IP \fBX\fR +Indicates that the delivery is final. This flag affects +the status reported in "success" DSN (delivery status +notification) messages, and changes it from "relayed" into +"delivered". +.sp +This feature is available as of Postfix 3.5. +.RE +.SH "SECURITY" +.na +.nf 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 @@ -118,7 +178,8 @@ RFC 7672 (SMTP security via opportunistic DANE TLS) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Corrupted message files are marked so that the queue manager can move them to the \fBcorrupt\fR queue for further inspection. @@ -128,11 +189,10 @@ other trouble. .SH BUGS .ad .fi -SMTP and LMTP connection caching does not work with TLS. The necessary -support for TLS object passivation and re\-activation does not -exist without closing the session, which defeats the purpose. +SMTP and LMTP connection reuse for TLS (without closing the +SMTP or LMTP connection) is not supported before Postfix 3.4. -SMTP and LMTP connection caching assumes that SASL credentials +SMTP and LMTP connection reuse assumes that SASL credentials are valid for all destinations that map onto the same IP address and TCP port. .SH "CONFIGURATION PARAMETERS" @@ -287,6 +347,17 @@ delivery status code or explanatory text of successful or unsuccessful deliveries. .IP "\fBsmtp_dns_reply_filter (empty)\fR" Optional filter for Postfix SMTP client DNS lookup results. +.PP +Available in Postfix version 3.3 and later: +.IP "\fBsmtp_balance_inet_protocols (yes)\fR" +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. +.PP +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.). .SH "MIME PROCESSING CONTROLS" .na .nf @@ -484,6 +555,13 @@ Available in Postfix version 2.8 and later: .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR" List or bit\-mask of OpenSSL bug work\-arounds to disable. .PP +Available in Postfix version 2.11\-3.1: +.IP "\fBtls_dane_digest_agility (on)\fR" +Configure RFC7671 DANE TLSA digest algorithm agility. +.IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR" +Enable support for RFC 6698 (DANE TLSA) DNS records that contain +digests of trust\-anchors with certificate usage "2". +.PP Available in Postfix version 2.11 and later: .IP "\fBsmtp_tls_trust_anchor_file (empty)\fR" Zero or more PEM\-format files with trust\-anchor certificates @@ -491,8 +569,6 @@ and/or public keys. .IP "\fBsmtp_tls_force_insecure_host_tlsa_lookup (no)\fR" Lookup the associated DANE TLSA RRset even when a hostname is not an alias and its address records lie in an unsigned zone. -.IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR" -RFC 6698 trust\-anchor digest support in the Postfix TLS library. .IP "\fBtlsmgr_service_name (tlsmgr)\fR" The name of the \fBtlsmgr\fR(8) service entry in master.cf. .PP @@ -506,6 +582,21 @@ Available in Postfix version 3.1 and later: The TLS policy for MX hosts with "secure" TLSA records when the nexthop destination security level is \fBdane\fR, but the MX record was found via an "insecure" MX lookup. +.PP +Available in Postfix version 3.4 and later: +.IP "\fBsmtp_tls_connection_reuse (no)\fR" +Try to make multiple deliveries per TLS\-encrypted connection. +.IP "\fBsmtp_tls_chain_files (empty)\fR" +List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. +.IP "\fBsmtp_tls_servername (empty)\fR" +Optional name to send to the remote SMTP server in the TLS Server +Name Indication (SNI) extension. +.PP +Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later: +.IP "\fBtls_fast_shutdown_enable (yes)\fR" +A workaround for implementations that hang Postfix while shutting +down a TLS session, until Postfix times out. .SH "OBSOLETE STARTTLS CONTROLS" .na .nf @@ -535,12 +626,6 @@ cipher list. .nf .ad .fi -.IP "\fBsmtp_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -The maximal number of parallel deliveries to the same destination -via the smtp message delivery transport. -.IP "\fBsmtp_destination_recipient_limit ($default_destination_recipient_limit)\fR" -The maximal number of recipients per message for the smtp -message delivery transport. .IP "\fBsmtp_connect_timeout (30s)\fR" The Postfix SMTP client time limit for completing a TCP connection, or zero (use the operating system built\-in time limit). @@ -621,6 +706,22 @@ Available in Postfix version 2.11 and later: When SMTP connection caching is enabled, the number of times that an SMTP session may be reused before it is closed, or zero (no limit). +.PP +Available in Postfix version 3.4 and later: +.IP "\fBsmtp_tls_connection_reuse (no)\fR" +Try to make multiple deliveries per TLS\-encrypted connection. +.PP +Implemented in the qmgr(8) daemon: +.IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +A transport\-specific override for the +default_destination_concurrency_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. +.IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +A transport\-specific override for the +default_destination_recipient_limit parameter value, where +\fItransport\fR is the master.cf name of the message delivery +transport. .SH "SMTPUTF8 CONTROLS" .na .nf @@ -633,6 +734,12 @@ in RFC 6531..6533. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBenable_idna2003_compatibility (no)\fR" +Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF\-8 domain names to/from the ASCII form that is +used for DNS lookups. .SH "TROUBLE SHOOTING CONTROLS" .na .nf @@ -725,8 +832,8 @@ Randomize the order of equal\-preference MX host addresses. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available with Postfix 2.2 and earlier: .IP "\fBfallback_relay (empty)\fR" @@ -747,6 +854,14 @@ Available with Postfix 3.1 and later: .IP "\fBlmtp_fallback_relay (empty)\fR" Optional list of relay hosts for LMTP destinations that can't be found or that are unreachable. +.PP +Available with Postfix 3.2 and later: +.IP "\fBsmtp_tcp_port (smtp)\fR" +The default TCP port that the Postfix SMTP client connects to. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf @@ -760,6 +875,7 @@ postconf(5), configuration parameters master(5), generic daemon options master(8), process manager tlsmgr(8), TLS session and PRNG management +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/smtpd.8 b/external/ibm-public/postfix/dist/man/man8/smtpd.8 index 6a91740b763..4dd717eed12 100644 --- a/external/ibm-public/postfix/dist/man/man8/smtpd.8 +++ b/external/ibm-public/postfix/dist/man/man8/smtpd.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: smtpd.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: smtpd.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SMTPD 8 .ad @@ -58,6 +58,7 @@ RFC 2034 (SMTP enhanced status codes) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) RFC 2920 (SMTP pipelining) +RFC 3030 (CHUNKING without BINARYMIME) RFC 3207 (STARTTLS command) RFC 3461 (SMTP DSN extension) RFC 3463 (Enhanced status codes) @@ -71,7 +72,8 @@ RFC 7505 ("Null MX" No Service Resource Record) .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Depending on the setting of the \fBnotify_classes\fR parameter, the postmaster is notified of bounces, protocol problems, @@ -241,8 +243,9 @@ The mail filter protocol version and optional protocol extensions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. .IP "\fBmilter_default_action (tempfail)\fR" -The default action when a Milter (mail filter) application is -unavailable or mis\-configured. +The default action when a Milter (mail filter) response is +unavailable (for example, bad Postfix configuration or Milter +failure). .IP "\fBmilter_macro_daemon_name ($myhostname)\fR" The {daemon_name} macro value for Milter (mail filter) applications. .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR" @@ -286,6 +289,11 @@ Available in Postfix version 3.1 and later: Optional list of \fIname=value\fR pairs that specify default values for arbitrary macros that Postfix may send to Milter applications. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBsmtpd_milter_maps (empty)\fR" +Lookup tables with Milter settings per remote SMTP client IP +address. .SH "GENERAL CONTENT INSPECTION CONTROLS" .na .nf @@ -367,6 +375,10 @@ Available in Postfix version 2.11 and later: .IP "\fBsmtpd_sasl_service (smtp)\fR" The service name that is passed to the SASL plug\-in that is selected with \fBsmtpd_sasl_type\fR and \fBsmtpd_sasl_path\fR. +.PP +Available in Postfix version 3.4 and later: +.IP "\fBsmtpd_sasl_response_limit (12288)\fR" +The maximum length of a SASL client's response to a server challenge. .SH "STARTTLS SUPPORT CONTROLS" .na .nf @@ -504,6 +516,30 @@ The name of the \fBtlsmgr\fR(8) service entry in master.cf. Available in Postfix version 3.0 and later: .IP "\fBtls_session_ticket_cipher (Postfix >= 3.0: aes\-256\-cbc, Postfix < 3.0: aes\-128\-cbc)\fR" Algorithm used to encrypt RFC5077 TLS session tickets. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBtls_eecdh_auto_curves (see 'postconf -d' output)\fR" +The prioritized list of elliptic curves supported by the Postfix +SMTP client and server. +.PP +Available in Postfix version 3.4 and later: +.IP "\fBsmtpd_tls_chain_files (empty)\fR" +List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. +.IP "\fBtls_server_sni_maps (empty)\fR" +Optional lookup tables that map names received from remote SMTP +clients via the TLS Server Name Indication (SNI) extension to the +appropriate keys and certificate chains. +.PP +Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later: +.IP "\fBtls_fast_shutdown_enable (yes)\fR" +A workaround for implementations that hang Postfix while shutting +down a TLS session, until Postfix times out. +.PP +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.). .SH "OBSOLETE STARTTLS CONTROLS" .na .nf @@ -535,6 +571,12 @@ Enable stricter enforcement of the SMTPUTF8 protocol. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBenable_idna2003_compatibility (no)\fR" +Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF\-8 domain names to/from the ASCII form that is +used for DNS lookups. .SH "VERP SUPPORT CONTROLS" .na .nf @@ -623,6 +665,9 @@ envelopes. .IP "\fBrecipient_canonical_maps (empty)\fR" Optional address mapping lookup tables for envelope and header recipient addresses. +.IP "\fBsender_canonical_maps (empty)\fR" +Optional address mapping lookup tables for envelope and header +sender addresses. .PP Parameters concerning known/unknown local recipients: .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" @@ -1021,7 +1066,7 @@ The Postfix SMTP server's action when a reject\-type restriction fails due to a temporary error condition. .IP "\fBunknown_helo_hostname_tempfail_action ($reject_tempfail_action)\fR" The Postfix SMTP server's action when reject_unknown_helo_hostname -fails due to an temporary error condition. +fails due to a temporary error condition. .IP "\fBunknown_address_tempfail_action ($reject_tempfail_action)\fR" The Postfix SMTP server's action when reject_unknown_sender_domain or reject_unknown_recipient_domain fail due to a temporary error @@ -1081,8 +1126,8 @@ banner. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 2.2 and later: .IP "\fBsmtpd_forbidden_commands (CONNECT, GET, POST)\fR" @@ -1093,6 +1138,15 @@ Available in Postfix version 2.5 and later: .IP "\fBsmtpd_client_port_logging (no)\fR" Enable logging of the remote SMTP client port in addition to the hostname and IP address. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +Available in Postfix 3.4 and later: +.IP "\fBsmtpd_reject_footer_maps (empty)\fR" +Lookup tables, indexed by the complete Postfix SMTP server 4xx or +5xx response, with reject footer templates. .SH "SEE ALSO" .na .nf @@ -1104,6 +1158,7 @@ verify(8), address verification service postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na @@ -1115,7 +1170,8 @@ Use "\fBpostconf readme_directory\fR" or .na .nf ADDRESS_CLASS_README, blocking unknown hosted or relay recipients -ADDRESS_REWRITING_README Postfix address manipulation +ADDRESS_REWRITING_README, Postfix address manipulation +BDAT_README, Postfix CHUNKING support FILTER_README, external after\-queue content filter LOCAL_RECIPIENT_README, blocking unknown local recipients MILTER_README, before\-queue mail filter applications diff --git a/external/ibm-public/postfix/dist/man/man8/spawn.8 b/external/ibm-public/postfix/dist/man/man8/spawn.8 index 4e971b041bd..f80f2c9dfea 100644 --- a/external/ibm-public/postfix/dist/man/man8/spawn.8 +++ b/external/ibm-public/postfix/dist/man/man8/spawn.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: spawn.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: spawn.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH SPAWN 8 .ad @@ -57,7 +57,7 @@ replaced by a more structural solution. .ad .fi The \fBspawn\fR(8) daemon reports abnormal child exits. -Problems are logged to \fBsyslogd\fR(8). +Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8). .SH "SECURITY" .na .nf @@ -86,13 +86,10 @@ in the \fBmaster.cf\fR file. .nf .ad .fi -.IP "\fItransport\fB_time_limit ($command_time_limit)\fR" -The amount of time the command is allowed to run before it is -terminated. - -Postfix 2.4 and later support a suffix that specifies the -time unit: s (seconds), m (minutes), h (hours), d (days), -w (weeks). The default time unit is seconds. +.IP "\fBtransport_time_limit ($command_time_limit)\fR" +A transport\-specific override for the command_time_limit parameter +value, where \fItransport\fR is the master.cf name of the message +delivery transport. .SH "MISCELLANEOUS" .na .nf @@ -128,13 +125,18 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf postconf(5), configuration parameters master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "LICENSE" .na diff --git a/external/ibm-public/postfix/dist/man/man8/tlsmgr.8 b/external/ibm-public/postfix/dist/man/man8/tlsmgr.8 index 19b064df651..35830ea3584 100644 --- a/external/ibm-public/postfix/dist/man/man8/tlsmgr.8 +++ b/external/ibm-public/postfix/dist/man/man8/tlsmgr.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: tlsmgr.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: tlsmgr.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH TLSMGR 8 .ad @@ -61,7 +61,8 @@ is logged. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to the syslog daemon. +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -152,8 +153,12 @@ The process name of a Postfix command or daemon process. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf @@ -162,6 +167,7 @@ smtpd(8), Postfix SMTP server postconf(5), configuration parameters master(5), generic daemon options master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/tlsproxy.8 b/external/ibm-public/postfix/dist/man/man8/tlsproxy.8 index 2d09273dc4a..d94f43002ba 100644 --- a/external/ibm-public/postfix/dist/man/man8/tlsproxy.8 +++ b/external/ibm-public/postfix/dist/man/man8/tlsproxy.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: tlsproxy.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: tlsproxy.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH TLSPROXY 8 .ad @@ -14,11 +14,12 @@ Postfix TLS proxy .SH DESCRIPTION .ad .fi -The \fBtlsproxy\fR(8) server implements a server\-side TLS -proxy. It is used by \fBpostscreen\fR(8) to talk SMTP\-over\-TLS +The \fBtlsproxy\fR(8) server implements a two\-way TLS proxy. It +is used by the \fBpostscreen\fR(8) server to talk SMTP\-over\-TLS with remote SMTP clients that are not whitelisted (including -clients whose whitelist status has expired), -but it should also work for non\-SMTP protocols. +clients whose whitelist status has expired), and by the +\fBsmtp\fR(8) client to support TLS connection reuse, but it +should also work for non\-SMTP protocols. Although one \fBtlsproxy\fR(8) process can serve multiple sessions at the same time, it is a good idea to allow the @@ -58,7 +59,8 @@ can be run chrooted at fixed low privilege. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH "CONFIGURATION PARAMETERS" .na .nf @@ -71,11 +73,98 @@ reload\fR" to speed up a change. The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. -.SH "STARTTLS SUPPORT CONTROLS" +.SH "STARTTLS GLOBAL CONTROLS" .na .nf .ad .fi +The following settings are global and therefore cannot be +overruled by information specified in a \fBtlsproxy\fR(8) +client request. +.IP "\fBtls_append_default_CA (no)\fR" +Append the system\-supplied default Certification Authority +certificates to the ones specified with *_tls_CApath or *_tls_CAfile. +.IP "\fBtls_daemon_random_bytes (32)\fR" +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 +internal pseudo random number generator (PRNG). +.IP "\fBtls_high_cipherlist (see 'postconf -d' output)\fR" +The OpenSSL cipherlist for "high" grade ciphers. +.IP "\fBtls_medium_cipherlist (see 'postconf -d' output)\fR" +The OpenSSL cipherlist for "medium" or higher grade ciphers. +.IP "\fBtls_low_cipherlist (see 'postconf -d' output)\fR" +The OpenSSL cipherlist for "low" or higher grade ciphers. +.IP "\fBtls_export_cipherlist (see 'postconf -d' output)\fR" +The OpenSSL cipherlist for "export" or higher grade ciphers. +.IP "\fBtls_null_cipherlist (eNULL:!aNULL)\fR" +The OpenSSL cipherlist for "NULL" grade ciphers that provide +authentication without encryption. +.IP "\fBtls_eecdh_strong_curve (prime256v1)\fR" +The elliptic curve used by the Postfix SMTP server for sensibly +strong +ephemeral ECDH key exchange. +.IP "\fBtls_eecdh_ultra_curve (secp384r1)\fR" +The elliptic curve used by the Postfix SMTP server for maximally +strong +ephemeral ECDH key exchange. +.IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR" +List or bit\-mask of OpenSSL bug work\-arounds to disable. +.IP "\fBtls_preempt_cipherlist (no)\fR" +With SSLv3 and later, use the Postfix SMTP server's cipher +preference order instead of the remote client's cipher preference +order. +.PP +Available in Postfix version 2.9 and later: +.IP "\fBtls_legacy_public_key_fingerprints (no)\fR" +A temporary migration aid for sites that use certificate +\fIpublic\-key\fR fingerprints with Postfix 2.9.0..2.9.5, which use +an incorrect algorithm. +.PP +Available in Postfix version 2.11\-3.1: +.IP "\fBtls_dane_digest_agility (on)\fR" +Configure RFC7671 DANE TLSA digest algorithm agility. +.IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR" +Enable support for RFC 6698 (DANE TLSA) DNS records that contain +digests of trust\-anchors with certificate usage "2". +.PP +Available in Postfix version 2.11 and later: +.IP "\fBtlsmgr_service_name (tlsmgr)\fR" +The name of the \fBtlsmgr\fR(8) service entry in master.cf. +.PP +Available in Postfix version 3.0 and later: +.IP "\fBtls_session_ticket_cipher (Postfix >= 3.0: aes\-256\-cbc, Postfix < 3.0: aes\-128\-cbc)\fR" +Algorithm used to encrypt RFC5077 TLS session tickets. +.IP "\fBopenssl_path (openssl)\fR" +The location of the OpenSSL command line program \fBopenssl\fR(1). +.PP +Available in Postfix version 3.2 and later: +.IP "\fBtls_eecdh_auto_curves (see 'postconf -d' output)\fR" +The prioritized list of elliptic curves supported by the Postfix +SMTP client and server. +.PP +Available in Postfix version 3.4 and later: +.IP "\fBtls_server_sni_maps (empty)\fR" +Optional lookup tables that map names received from remote SMTP +clients via the TLS Server Name Indication (SNI) extension to the +appropriate keys and certificate chains. +.PP +Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later: +.IP "\fBtls_fast_shutdown_enable (yes)\fR" +A workaround for implementations that hang Postfix while shutting +down a TLS session, until Postfix times out. +.SH "STARTTLS SERVER CONTROLS" +.na +.nf +.ad +.fi +These settings are clones of Postfix SMTP server settings. +They allow \fBtlsproxy\fR(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 \fBtlsproxy\fR(8) client +request, but that limitation may be removed in a future +version. .IP "\fBtlsproxy_tls_CAfile ($smtpd_tls_CAfile)\fR" A file containing (PEM format) CA certificates of root CAs trusted to sign either remote SMTP client certificates or intermediate @@ -110,11 +199,11 @@ should use with export\-grade EDH ciphers. File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM format. .IP "\fBtlsproxy_tls_eccert_file ($smtpd_tls_eccert_file)\fR" -File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in -PEM format. +File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in PEM +format. .IP "\fBtlsproxy_tls_eckey_file ($smtpd_tls_eckey_file)\fR" -File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in -PEM format. +File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in PEM +format. .IP "\fBtlsproxy_tls_eecdh_grade ($smtpd_tls_eecdh_grade)\fR" The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral elliptic\-curve Diffie\-Hellman (EECDH) key exchange. @@ -150,10 +239,76 @@ client certificate in order to allow TLS connections to proceed. The SMTP TLS security level for the Postfix \fBtlsproxy\fR(8) server; when a non\-empty value is specified, this overrides the obsolete 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. +.SH "STARTTLS CLIENT CONTROLS" +.na +.nf +.ad +.fi +These settings are clones of Postfix SMTP client settings. +They allow \fBtlsproxy\fR(8) to load the same certificate +and private key information as 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 \fBtlsproxy\fR(8) client request. .PP -Available in Postfix version 2.11 and later: -.IP "\fBtlsmgr_service_name (tlsmgr)\fR" -The name of the \fBtlsmgr\fR(8) service entry in master.cf. +Available in Postfix version 3.4 and later: +.IP "\fBtlsproxy_client_CAfile ($smtp_tls_CAfile)\fR" +A file containing CA certificates of root CAs trusted to sign +either remote TLS server certificates or intermediate CA certificates. +.IP "\fBtlsproxy_client_CApath ($smtp_tls_CApath)\fR" +Directory with PEM format Certification Authority certificates +that the Postfix \fBtlsproxy\fR(8) client uses to verify a remote TLS +server certificate. +.IP "\fBtlsproxy_client_chain_files ($smtp_tls_chain_files)\fR" +Files with the Postfix \fBtlsproxy\fR(8) client keys and certificate +chains in PEM format. +.IP "\fBtlsproxy_client_cert_file ($smtp_tls_cert_file)\fR" +File with the Postfix \fBtlsproxy\fR(8) client RSA certificate in PEM +format. +.IP "\fBtlsproxy_client_key_file ($smtp_tls_key_file)\fR" +File with the Postfix \fBtlsproxy\fR(8) client RSA private key in PEM +format. +.IP "\fBtlsproxy_client_dcert_file ($smtp_tls_dcert_file)\fR" +File with the Postfix \fBtlsproxy\fR(8) client DSA certificate in PEM +format. +.IP "\fBtlsproxy_client_dkey_file ($smtp_tls_dkey_file)\fR" +File with the Postfix \fBtlsproxy\fR(8) client DSA private key in PEM +format. +.IP "\fBtlsproxy_client_eccert_file ($smtp_tls_eccert_file)\fR" +File with the Postfix \fBtlsproxy\fR(8) client ECDSA certificate in PEM +format. +.IP "\fBtlsproxy_client_eckey_file ($smtp_tls_eckey_file)\fR" +File with the Postfix \fBtlsproxy\fR(8) client ECDSA private key in PEM +format. +.IP "\fBtlsproxy_client_fingerprint_digest ($smtp_tls_fingerprint_digest)\fR" +The message digest algorithm used to construct remote TLS server +certificate fingerprints. +.IP "\fBtlsproxy_client_loglevel ($smtp_tls_loglevel)\fR" +Enable additional Postfix \fBtlsproxy\fR(8) client logging of TLS +activity. +.IP "\fBtlsproxy_client_loglevel_parameter (smtp_tls_loglevel)\fR" +The name of the parameter that provides the tlsproxy_client_loglevel +value. +.IP "\fBtlsproxy_client_scert_verifydepth ($smtp_tls_scert_verifydepth)\fR" +The verification depth for remote TLS server certificates. +.IP "\fBtlsproxy_client_security_level ($smtp_tls_security_level)\fR" +The default TLS security level for the Postfix \fBtlsproxy\fR(8) +client. +.IP "\fBtlsproxy_client_policy_maps ($smtp_tls_policy_maps)\fR" +Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS +security policy by next\-hop destination. +.IP "\fBtlsproxy_client_use_tls ($smtp_use_tls)\fR" +Opportunistic mode: use TLS when a remote server announces TLS +support. +.IP "\fBtlsproxy_client_enforce_tls ($smtp_enforce_tls)\fR" +Enforcement mode: require that SMTP servers use TLS encryption. +.IP "\fBtlsproxy_client_per_site ($smtp_tls_per_site)\fR" +Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS +usage policy by next\-hop destination and by remote TLS server +hostname. .SH "OBSOLETE STARTTLS SUPPORT CONTROLS" .na .nf @@ -190,15 +345,20 @@ The process name of a Postfix command or daemon process. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf postscreen(8), Postfix zombie blocker smtpd(8), Postfix SMTP server postconf(5), configuration parameters -syslogd(5), system logging +postlogd(8), Postfix logging +syslogd(8), system logging .SH "LICENSE" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man8/trivial-rewrite.8 b/external/ibm-public/postfix/dist/man/man8/trivial-rewrite.8 index 74b96859205..e82a291b310 100644 --- a/external/ibm-public/postfix/dist/man/man8/trivial-rewrite.8 +++ b/external/ibm-public/postfix/dist/man/man8/trivial-rewrite.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: trivial-rewrite.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: trivial-rewrite.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH TRIVIAL-REWRITE 8 .ad @@ -83,7 +83,8 @@ It can run at a fixed low privilege in a chrooted environment. .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH "CONFIGURATION PARAMETERS" .na .nf @@ -276,13 +277,17 @@ responses. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 2.0 and later: .IP "\fBhelpful_warnings (yes)\fR" Log warnings about problematic configuration settings, and provide helpful suggestions. +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf @@ -290,6 +295,7 @@ postconf(5), configuration parameters transport(5), transport table format relocated(5), format of the "user has moved" table master(8), process manager +postlogd(8), Postfix logging syslogd(8), system logging .SH "README FILES" .na diff --git a/external/ibm-public/postfix/dist/man/man8/verify.8 b/external/ibm-public/postfix/dist/man/man8/verify.8 index d661e6a3fd1..26818755d54 100644 --- a/external/ibm-public/postfix/dist/man/man8/verify.8 +++ b/external/ibm-public/postfix/dist/man/man8/verify.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: verify.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: verify.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH VERIFY 8 .ad @@ -67,7 +67,8 @@ non\-Postfix directory is redirected to the Postfix\-owned .SH DIAGNOSTICS .ad .fi -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). .SH BUGS .ad .fi @@ -179,6 +180,12 @@ Preliminary SMTPUTF8 support is introduced with Postfix 3.0. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. +.PP +Available in Postfix version 3.2 and later: +.IP "\fBenable_idna2003_compatibility (no)\fR" +Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF\-8 domain names to/from the ASCII form that is +used for DNS lookups. .SH "MISCELLANEOUS CONTROLS" .na .nf @@ -202,15 +209,20 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". +.PP +Available in Postfix 3.3 and later: +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. .SH "SEE ALSO" .na .nf smtpd(8), Postfix SMTP server cleanup(8), enqueue Postfix message postconf(5), configuration parameters -syslogd(5), system logging +postlogd(8), Postfix logging +syslogd(8), system logging .SH "README FILES" .na .nf diff --git a/external/ibm-public/postfix/dist/man/man8/virtual.8 b/external/ibm-public/postfix/dist/man/man8/virtual.8 index 75a45fab64a..97a9af7b78a 100644 --- a/external/ibm-public/postfix/dist/man/man8/virtual.8 +++ b/external/ibm-public/postfix/dist/man/man8/virtual.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: virtual.8,v 1.2 2017/02/14 01:16:44 christos Exp $ +.\" $NetBSD: virtual.8,v 1.3 2020/03/18 19:05:14 christos Exp $ .\" .TH VIRTUAL 8 .ad @@ -159,7 +159,8 @@ Mail bounces when the recipient has no mailbox or when the recipient is over disk quota. In all other cases, mail for an existing recipient is deferred and a warning is logged. -Problems and transactions are logged to \fBsyslogd\fR(8). +Problems and transactions are logged to \fBsyslogd\fR(8) +or \fBpostlogd\fR(8). Corrupted message files are marked so that the queue manager can move them to the \fBcorrupt\fR queue afterwards. @@ -240,15 +241,17 @@ The time after which a stale exclusive mailbox lockfile is removed. .nf .ad .fi +.IP "\fBvirtual_mailbox_limit (51200000)\fR" +The maximal size in bytes of an individual \fBvirtual\fR(8) mailbox or +maildir file, or zero (no limit). +.PP +Implemented in the qmgr(8) daemon: .IP "\fBvirtual_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" The maximal number of parallel deliveries to the same destination via the virtual message delivery transport. .IP "\fBvirtual_destination_recipient_limit ($default_destination_recipient_limit)\fR" The maximal number of recipients per message for the virtual message delivery transport. -.IP "\fBvirtual_mailbox_limit (51200000)\fR" -The maximal size in bytes of an individual \fBvirtual\fR(8) mailbox or -maildir file, or zero (no limit). .SH "MISCELLANEOUS CONTROLS" .na .nf @@ -281,20 +284,34 @@ The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". .PP Available in Postfix version 3.0 and later: .IP "\fBvirtual_delivery_status_filter ($default_delivery_status_filter)\fR" Optional filter for the \fBvirtual\fR(8) delivery agent to change the delivery status code or explanatory text of successful or unsuccessful deliveries. +.PP +Available in Postfix version 3.3 and later: +.IP "\fBenable_original_recipient (yes)\fR" +Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). +.IP "\fBservice_name (read\-only)\fR" +The master.cf service name of a Postfix daemon process. +.PP +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.). .SH "SEE ALSO" .na .nf qmgr(8), queue manager bounce(8), delivery status reports postconf(5), configuration parameters +postlogd(8), Postfix logging syslogd(8), system logging .SH "README_FILES" .na diff --git a/external/ibm-public/postfix/dist/postfix-install b/external/ibm-public/postfix/dist/postfix-install index e3b2513f611..49f0fbe8f6e 100644 --- a/external/ibm-public/postfix/dist/postfix-install +++ b/external/ibm-public/postfix/dist/postfix-install @@ -40,6 +40,10 @@ # is installed from a pre-built package or from source code. # # Arguments +# .IP -keep-build-mtime +# When installing files preserve new file's mtime timestamps. +# Otherwise, mtimes will be set to the time that postfix-install +# is run. # .IP -non-interactive # Do not ask the user for parameter settings. Installation parameters # are specified via one of the non-interactive methods described @@ -210,6 +214,7 @@ if [ -n "$SHLIB_ENV_VAR" ]; then fi USAGE="Usage: $0 [name=value] [option] + -keep-build-mtime Preserve build-time file mtime timestamps. -non-interactive Do not ask for installation parameters. -package Build a ready-to-install package. name=value Specify an installation parameter". @@ -225,6 +230,8 @@ do *=*) IFS= eval $arg; IFS="$BACKUP_IFS";; -non-int*) non_interactive=1;; -package) need_install_root=install_root;; +-keep-build-mtime) + keep_build_mtime=1;; *) echo "$0: Error: $USAGE" 1>&2; exit 1;; esac shift @@ -304,7 +311,9 @@ compare_or_replace() { (cmp $src $dst >/dev/null 2>&1 && echo Skipping $dst...) || { echo Updating $dst... rm -f $tempdir/junk || exit 1 + # Not: "cp -p" which preserves ownership. cp $src $tempdir/junk || exit 1 + test -z "$keep_build_mtime" || touch -r $src $tempdir/junk || exit 1 mv -f $tempdir/junk $dst || exit 1 test -z "$owner" || chown $owner $dst || exit 1 test -z "$group" || chgrp $group $dst || exit 1 @@ -367,7 +376,7 @@ check_parent() { done } -# How to supress newlines in echo. +# How to suppress newlines in echo. case `echo -n` in "") n=-n; c=;; diff --git a/external/ibm-public/postfix/dist/proto/ADDRESS_VERIFICATION_README.html b/external/ibm-public/postfix/dist/proto/ADDRESS_VERIFICATION_README.html index 613eeb6fdf8..ef1f6a7830d 100644 --- a/external/ibm-public/postfix/dist/proto/ADDRESS_VERIFICATION_README.html +++ b/external/ibm-public/postfix/dist/proto/ADDRESS_VERIFICATION_README.html @@ -298,6 +298,12 @@ the same address repeatedly. </p> ... # Postfix 2.6 and later privacy feature. # unverified_recipient_reject_reason = Address lookup failed + + # Postfix 3.2 and earlier workaround. + # Do not set enable_original_recipient=no. This prevents Postfix + # from saving the recipient address verification result under + # the original address, when the address verification probe + # message goes through address aliasing or canonical mapping. </pre> </blockquote> @@ -348,6 +354,12 @@ in forged email. </p> # Note 1: Be sure to read the "<a href="#caching">Caching</a>" section below! # Note 2: Avoid hash files here. Use btree or lmdb instead. address_verify_map = btree:/var/lib/postfix/verify + + # Postfix 3.2 and earlier workaround. + # Do not set enable_original_recipient=no. This prevents Postfix + # from saving the sender address verification result under the + # original address, when the address verification probe message + # goes through address aliasing or canonical mapping. /etc/postfix/sender_access: # Don't do this when you handle lots of email. diff --git a/external/ibm-public/postfix/dist/proto/INSTALL.html b/external/ibm-public/postfix/dist/proto/INSTALL.html index 87ec14d8330..b0df887150c 100644 --- a/external/ibm-public/postfix/dist/proto/INSTALL.html +++ b/external/ibm-public/postfix/dist/proto/INSTALL.html @@ -566,7 +566,7 @@ configuration file postfix-files will automatically include files under the directory postfix-files.d. Thanks to this, you can install or deinstall a database plugin package without having to edit postfix-files or dynamicmaps.cf. Instead, you give that plugin its -own configuration files dynamicmaps.cf.d and postfix-files.d, and +own configuration files under dynamicmaps.cf.d and postfix-files.d, and you add or remove those configuration files along with the database plugin dynamically-linked object. </p> @@ -837,7 +837,9 @@ unreachable code. </td> </tr> <tr> <td> </td> <td> -DNO_IPV6 </td> <td> Do not build with IPv6 support. By default, IPv6 support is compiled in on platforms that are known to have IPv6 support. Note: this directive is for debugging -and testing only. It is not guaranteed to work on all platforms. +And testing only. It is not guaranteed to work on all platforms. +If you don't want IPv6 support, set "inet_protocols = ipv4" in +main.cf. </td> </tr> <tr> <td> </td> <td> -DNO_KQUEUE </td> <td> Do not build with FreeBSD @@ -866,6 +868,10 @@ these where they are known to be available. </td> </tr> By default, Postfix uses <tt>sigsetjmp()/siglongjmp()</tt> when they are known to be available. </td> </tr> +<tr> <td> </td> <td> -DNO_SNPRINTF </td> <td> Use <tt>sprintf()</tt> +instead of <tt>snprintf()</tt>. By default, Postfix uses +<tt>snprintf()</tt> except on ancient systems. </td> </tr> + <tr> <td colspan="2"> DEBUG=debug_level </td> <td> Specifies a non-default compiler debugging level. The default is "<tt>-g</tt>". Specify DEBUG= to turn off debugging. </td> </tr> @@ -874,6 +880,11 @@ Specify DEBUG= to turn off debugging. </td> </tr> a non-default optimization level. The default is "<tt>-O</tt>". Specify OPT= to turn off optimization. </td> </tr> +<tr> <td colspan="2"> POSTFIX_INSTALL_OPTS=-option... </td> <td> +Specifies options for the <tt>postfix-install</tt> command, separated +by whitespace. Currently, the only supported option is +"<tt>-keep-build-mtime</tt>". </td> </tr> + <tr> <td colspan="2"> SHLIB_CFLAGS=flags </td> <td> Specifies non-default compiler options for building Postfix dynamically-linked libraries and database plugins. The typical default is "-fPIC". diff --git a/external/ibm-public/postfix/dist/proto/TLS_README.html b/external/ibm-public/postfix/dist/proto/TLS_README.html index faa29309112..d8d2041b653 100644 --- a/external/ibm-public/postfix/dist/proto/TLS_README.html +++ b/external/ibm-public/postfix/dist/proto/TLS_README.html @@ -18,15 +18,6 @@ <hr> -<h2> WARNING </h2> - -<p> By turning on TLS support in Postfix, you not only get the -ability to encrypt mail and to authenticate remote SMTP clients or servers. -You also turn on thousands and thousands of lines of OpenSSL library -code. Assuming that OpenSSL is written as carefully as Wietse's -own code, every 1000 lines introduce one additional bug into -Postfix. </p> - <h2> What Postfix TLS support does for you </h2> <p> Transport Layer Security (TLS, formerly called SSL) provides @@ -34,13 +25,12 @@ certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. </p> -<blockquote> <p> <a name="client_tls_obs"></a> <a -name="client_tls_harden"></a> NOTE: This document describes a TLS -user interface that was introduced with Postfix version 2.3. Support -for an older user interface is documented in TLS_LEGACY_README, -which also describes the differences between Postfix and the -third-party patch on which Postfix version 2.2 TLS support was -based. </p> </blockquote> +<p> NOTE: By turning on TLS support in Postfix, you not only get +the ability to encrypt mail and to authenticate remote SMTP clients +or servers. You also turn on hundreds of thousands of lines of +OpenSSL library code. Assuming that OpenSSL is written as carefully +as Wietse's own code, every 1000 lines introduce one additional bug +into Postfix. </p> <p> Topics covered in this document: </p> @@ -135,6 +125,8 @@ align="center" bgcolor="#f0f0ff"> smtp<br> session<br> key cache <li><a href="#server_cert_key">Server-side certificate and private key configuration </a> +<li><a href="#server_pfs">Server-side forward-secrecy configuration </a> + <li><a href="#server_logging"> Server-side TLS activity logging </a> @@ -175,26 +167,32 @@ or similar software, it will only negotiate TLS ciphersuites that require a server certificate. </p> <p> For servers that are <b>not</b> public Internet MX hosts, Postfix -supports configurations with no certificates. This entails the -use of just the anonymous TLS ciphers, which are not supported by -typical SMTP clients. Since such clients will not, as a rule, fall -back to plain text after a TLS handshake failure, a certificate-less -Postfix SMTP server will -be unable to receive email from most TLS enabled clients. To avoid -accidental configurations with no certificates, Postfix enables -certificate-less operation only when the administrator explicitly sets -"smtpd_tls_cert_file = none". This ensures that new Postfix -SMTP server configurations will not accidentally run with no -certificates. </p> +supports configurations with no certificates. This entails the use of +just the anonymous TLS ciphers, which are not supported by typical SMTP +clients. Since some clients may not fall back to plain text after a TLS +handshake failure, a certificate-less Postfix SMTP server will be unable +to receive email from some TLS-enabled clients. To avoid accidental +configurations with no certificates, Postfix enables certificate-less +operation only when the administrator explicitly sets +"smtpd_tls_cert_file = none". This ensures that new Postfix SMTP server +configurations will not accidentally enable TLS without certificates. </p> + +<p> Note that server certificates are <b>not</b> optional in TLS 1.3. To +run without certificates you'd have to disable the TLS 1.3 protocol by +including '!TLSv1.3' in "smtpd_tls_protocols" and perhaps also +"smtpd_tls_mandatory_protocols". It is simpler instead to just +configure a certificate chain. Certificate-less operation is not +recommended. <p> <p> RSA, DSA and ECDSA (Postfix ≥ 2.6) certificates are supported. Most sites only have RSA certificates. You can configure all three at the same time, in which case the ciphersuite negotiated with the remote SMTP client determines which certificate is used. If your -DNS zone is signed, and you want to publish RFC 6698 TLSA records, -these must match any of the configured certificates. Since the -best practice is to publish "3 1 1" certificate associations, create -a separate TLSA record for each public-key certificate digest. </p> +DNS zone is signed, and you want to publish DANE TLSA (RFC 6698, +RFC 7671, RFC 7672) records, these must match all of the configured +certificate chains. Since the best practice is to publish "3 1 1" +certificate associations, create a separate TLSA record to match +each public-key certificate digest. </p> <h4> Creating the server certificate file </h4> @@ -226,11 +224,10 @@ size of the server TLS handshake. </p> </pre> </blockquote> -<li> <p> If you publish RFC 6698 TLSA "2 0 1" or "2 1 1" records to -specify root CA certificate digests, you must include the corresponding -root CA certificates in the "server.pem" certificate file. See the -documentation of the tls_dane_trust_anchor_digest_enable main.cf -parameter. </p> +<li> <p> If you publish DANE TLSA (RFC 6698, RFC 7671, RFC 7672) +"2 0 1" or "2 1 1" records to specify root CA certificate digests, +you must include the corresponding root CA certificates in the +"server.pem" certificate file. </p> <blockquote> <pre> @@ -247,11 +244,10 @@ applies to "2 0 2" and "2 1 2" TLSA records or any other digest of a CA certificate, but it is expected that SHA256 will be by far the most common digest for TLSA. </p> -<p> As a best practice, publish either "3 0 1" or "3 1 1" TLSA -associations that specify the SHA256 digest of the server certificate -public key with the alias-expanded hostname of each STARTTLS capable -SMTP server. These continue to work when a certificate is renewed -with the same public/private key pair. </p> +<p> As a best practice, publish "3 1 1" TLSA associations that specify +the SHA256 digest of the server's public key. These continue to work +unmodified when a certificate is renewed with the same public/private +key pair. </p> </ul> @@ -277,6 +273,58 @@ directory. </p> <h4> Configuring the server certificate and key files </h4> +<p> Example: Postfix ≥ 3.4 all-in-one chain file(s). One or more +chain files that start with a key that is immediately followed by the +corresponding certificate and any additional issuer certificates. A +single file can hold multiple <i>(key, cert, [chain])</i> sequences, one +per algorithm. It is typically simpler to keep the chain for each +algorithm in its own file. Most users are likely to deploy just a +single RSA chain, but with OpenSSL 1.1.1, it is possible to deploy up to +five chains, one each for RSA, ECDSA, ED25519, ED448 and even the +obsolete DSA. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. Preferred configuration interface. Each file + # starts with the private key, followed by the corresponding + # certificate, and any intermediate issuer certificates. The root CA + # cert may also be needed when published as a DANE trust anchor. + # + smtpd_tls_chain_files = + /etc/postfix/rsa.pem, + /etc/postfix/ecdsa.pem, + /etc/postfix/ed25519.pem, + /etc/postfix/ed448.pem +</pre> +</blockquote> + +<p> You can also store the keys separately from their certificates, again +provided each is listed before the corresponding certificate chain. Storing a +key and its associated certificate chain in separate files is not recommended, +because this is prone to race conditions during key rollover, as there is no +way to update multiple files atomically. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. + # Storing keys separately from the associated certificates is not + # recommended. + smtpd_tls_chain_files = + /etc/postfix/rsakey.pem, + /etc/postfix/rsacerts.pem, + /etc/postfix/ecdsakey.pem, + /etc/postfix/ecdsacerts.pem +</pre> +</blockquote> + +<p> The below examples show the legacy algorithm-specific configurations +for Postfix 3.3 and older. With Postfix ≤ 3.3, even if the key is +stored in the same file as the certificate, the file is read twice and a +(brief) race condition still exists during key rollover. While Postfix +≥ 3.4 avoids the race when the key and certificate are in the same +file, you should use the new "smtpd_tls_chain_files" interface shown +above. <p> + <p> RSA key and certificate examples: </p> <blockquote> @@ -302,8 +350,8 @@ directory. </p> <blockquote> <pre> /etc/postfix/main.cf: - # Most clients will not be ECDSA capable, so you will likely also need - # an RSA or DSA certificate and private key. + # Some clients will not be ECDSA capable, so you will likely still need + # an RSA certificate and private key. # smtpd_tls_eccert_file = /etc/postfix/server-ecdsa.pem smtpd_tls_eckey_file = $smtpd_tls_eccert_file @@ -316,6 +364,8 @@ anonymous-cipher capable clients: </p> <blockquote> <pre> /etc/postfix/main.cf: + # Not recommended: breaks TLS 1.3 and clients that don't support + # anonymous cipher suites. smtpd_tls_cert_file = none </pre> </blockquote> @@ -370,6 +420,18 @@ the TLS handshake when client certificates are requested. </p> </pre> </blockquote> +<h3><a name="server_pfs"> Server-side forward-secrecy configuration </a> </h3> + +<p> If you want to take maximal advantage of ciphers that offer <a +href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see +the <a href="FORWARD_SECRECY_README.html#quick-start">Getting +started</a> section of <a +href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The +full document conveniently presents all information about Postfix +forward secrecy support in one place: what forward secrecy is, how +to tweak settings, and what you can expect to see when Postfix uses +ciphers with forward secrecy. </p> + <h3><a name="server_logging"> Server-side TLS activity logging </a> </h3> <p> To get additional information about Postfix SMTP server TLS @@ -850,7 +912,11 @@ without corresponding changes to the Postfix source code. </p> supports configurations with no <a href="#server_cert_key">server certificates</a> that use <b>only</b> the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" -and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. </p> +and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. +Such configurations may not interoperate with some clients, and require +that TLSv1.3 be explicitly disabled. Therefore, they are not +recommended, it is better and simpler to just configure a suitable +certificate. </p> <p> Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3, with high grade ciphers: </p> @@ -870,15 +936,30 @@ with high grade ciphers: </p> </pre> </blockquote> +<p> With Postfix ≥ 3.4, specify instead a single file that holds the +key followed by the corresponding certificate and any associated issuing +certificates, leaving the "smtpd_tls_cert_file" and "smtpd_tls_key_file" +and related DSA and ECDSA parameters empty. </p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + smtpd_tls_chain_files = /etc/postfix/rsachain.pem + smtpd_tls_cert_file = + smtpd_tls_key_file = + ... +</pre> +</blockquote> + <p> If you want to take maximal advantage of ciphers that offer <a href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see the <a href="FORWARD_SECRECY_README.html#quick-start">Getting started</a> section of <a href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The full document conveniently presents all information about Postfix -"perfect" forward secrecy support in one place: what forward secrecy -is, how to tweak settings, and what you can expect to see when -Postfix uses ciphers with forward secrecy. </p> +forward secrecy support in one place: what forward secrecy is, how +to tweak settings, and what you can expect to see when Postfix uses +ciphers with forward secrecy. </p> <p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS servers to preempt the TLS client's cipher-suite preference list. @@ -919,12 +1000,13 @@ handshake procedures. </p> </blockquote> <p> With Postfix 2.8 and later, the tls_disable_workarounds parameter -specifies a list or bit-mask of OpenSSL bug work-arounds to disable. This -may be necessary if one of the work-arounds enabled by default in -OpenSSL proves to pose a security risk, or introduces an unexpected -interoperability issue. Some bug work-arounds known to be problematic -are disabled in the default value of the parameter when linked with -an OpenSSL library that could be vulnerable. </p> +specifies a list or bit-mask of default-enabled OpenSSL bug +work-arounds to disable. This may be necessary if one of the +work-arounds enabled by default in OpenSSL proves to pose a security +risk, or introduces an unexpected interoperability issue. The list +of enabled bug work-arounds is OpenSSL-release-specific. See the +tls_disable_workarounds parameter documentation for the list of +supported values.</p> <p> Example: </p> @@ -942,19 +1024,8 @@ more of the named options below, or a hexadecimal bitmask of options found in the ssl.h file corresponding to the run-time OpenSSL library. While it may be reasonable to turn off all bug workarounds (see above), it is not a good idea to attempt to turn on all features. -</p> - -<dl> - -<dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3).</dd> - -<dt><b>NO_TICKET</b></dt> <dd>See SSL_CTX_set_options(3).</dd> - -<dt><b>NO_COMPRESSION</b></dt> <dd>Disable SSL compression even if -supported by the OpenSSL library. Compression is CPU-intensive, -and compression before encryption does not always improve security. </dd> - -</dl> +See the tls_ssl_options parameter documentation for the list of +supported values. </p> <p> Example: </p> @@ -988,6 +1059,8 @@ solution. </p> <li><a href="#client_cert_key">Client-side certificate and private key configuration </a> +<li><a href="#client_tls_reuse">Client-side TLS connection reuse</a> + <li><a href="#client_tls_cache">Client-side TLS session cache</a> <li><a href="#client_tls_limits"> Client TLS limitations </a> @@ -1144,7 +1217,7 @@ parameters includes useful interoperability and security guidelines. <p> Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for -mail delivery to the public Internet. Most MX hosts do not support TLS at +mail delivery to the public Internet. Some MX hosts do not support TLS at all, and some of those that do have broken implementations. On a host that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level. </p> @@ -1208,16 +1281,17 @@ just in case the transport table entries are not specified consistently. </p> <h4><a name="client_tls_dane">DANE TLS authentication.</a> </h4> <p> The Postfix SMTP client supports two TLS security levels based -on RFC6698 DANE TLSA records. The opportunistic "dane" level and -the mandatory "dane-only" level. </p> +on DANE TLSA (RFC 6698, RFC 7671, RFC 7672) records. The opportunistic +"dane" level and the mandatory "dane-only" level. </p> <p> The "dane" level is a stronger form of <a href="#client_tls_may">opportunistic</a> TLS that is resistant to man in the middle and downgrade attacks when the destination domain uses DNSSEC to publish DANE TLSA records for its MX hosts. If a -remote SMTP server has "usable" (see RFC 6698) DANE TLSA records, -the server connection will be authenticated. When DANE authentication -fails, there is no fallback to unauthenticated or plaintext delivery. </p> +remote SMTP server has "usable" (see section 3 of RFC 7672) DANE +TLSA records, the server connection will be authenticated. When +DANE authentication fails, there is no fallback to unauthenticated +or plaintext delivery. </p> <p> If TLSA records are published for a given remote SMTP server (implying TLS support), but are all "unusable" due to unsupported @@ -1248,9 +1322,9 @@ to be in effect, the destination domain's containing DNS zone must be signed and the Postfix SMTP client's operating system must be configured to send its DNS queries to a recursive DNS nameserver that is able to validate the signed records. Each MX host's DNS -zone needs to also be signed, and needs to publish DANE TLSA (RFC 6698) -records that specify how that MX host's TLS certificate is to be -verified. </p> +zone needs to also be signed, and needs to publish DANE TLSA (see +section 3 of RFC 7672) records that specify how that MX host's TLS +certificate is to be verified. </p> <p> TLSA records do not preempt the normal SMTP MX host selection algorithm, if some MX hosts support TLSA and others do @@ -1258,35 +1332,17 @@ not, TLS security will vary from delivery to delivery. It is up to the domain owner to configure their MX hosts and their DNS sensibly. To configure the Postfix SMTP client for DNSSEC lookups see the documentation for the smtp_dns_support_level main.cf -parameter. The tls_dane_trust_anchor_digest_enable main.cf parameter -controls support for trust-anchor digest TLSA records. The -tls_dane_digests and tls_dane_digest_agility parameters control -the list of supported digests and digest downgrade attack resistance. -</p> +parameter. The tls_dane_digests parameter controls the list of +supported digests. </p> -<p> DANE for SMTP MTAs deviates in some details from the baseline -DANE protocol in RFC 6698. Most notably, it is not expected that -SMTP MTAs can reasonably include every public CA that a remote SMTP -server's administrator may believe to be well-known. Nor is there -an interactive user to "click OK" when authentication fails. </p> - -<p> Therefore, certificate usages "0" and "1" from RFC 6698 which -are intended to "constrain" existing PKI trust, are not supported. -TLSA records with usage "0" are treated as "unusable". TLSA records -with usage "1" are instead treated as "trust assertions" and mapped -to usage "3". Specifically, with certificate usage "1", Postfix -will not require the remote SMTP server's certificate to be trusted -with respect to any locally defined public CAs, it is the domain -owner's responsibility to ensure that the certificate associations -in their TLSA records are appropriate to authenticate their SMTP -servers. </p> +<p> As explained in section 3 of RFC 7672, certificate usages "0" +and "1", which are intended to "constrain" existing Web-PKI trust, +are not supported with MTA-to-MTA SMTP. Rather, TLSA records with +usages "0" and "1" are treated as "unusable". </p> <p> The Postfix SMTP client supports only certificate usages "2" -and "3" (with "1" treated as though it were "3"). See -tls_dane_trust_anchor_digest_enable for usage "2" usability -considerations. Support for certificate usage "1" is an experiment, -it may be withdrawn in the future. Server operators SHOULD NOT -publish TLSA records with usage "1". </p> +and "3". Experimental support for silently mapping certificate +usage "1" to "3" has been withdrawn starting with Postfix 3.2. </p> <p> When usable TLSA records are obtained for the remote SMTP server the Postfix SMTP client sends the SNI TLS extension in its SSL @@ -1299,7 +1355,7 @@ security level is treated like a "mandatory" TLS security level, and weak ciphers and protocols are disabled. Since DANE authenticates server certificates the "aNULL" cipher-suites are transparently excluded at this level, no need to configure this manually. RFC -6698 (DANE) TLS authentication is available with Postfix 2.11 and +7672 (DANE) TLS authentication is available with Postfix 2.11 and later. </p> <p> When a DANE TLSA record specifies a trust-anchor (TA) certificate @@ -1561,8 +1617,8 @@ parent certificates will be ignored. </p> <p> Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory certificate trust chain and subject name verification -is not viable as a default Internet mail delivery policy. Most MX hosts -do not support TLS at all, and a significant portion of TLS enabled +is not viable as a default Internet mail delivery policy. Some MX hosts +do not support TLS at all, and a significant portion of TLS-enabled MTAs use self-signed certificates, or certificates that are signed by a private Certification Authority. On a machine that delivers mail to the Internet, you should not configure mandatory server certificate @@ -1635,8 +1691,8 @@ parent certificates will be ignored. </p> <p> Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory secure server certificate verification is not -viable as a default Internet mail delivery policy. Most MX hosts -do not support TLS at all, and a significant portion of TLS enabled +viable as a default Internet mail delivery policy. Some MX hosts +do not support TLS at all, and a significant portion of TLS-enabled MTAs use self-signed certificates, or certificates that are signed by a private Certification Authority. On a machine that delivers mail to the Internet, you should not configure secure TLS verification @@ -1797,24 +1853,24 @@ well without them. The recommended setting is to let the defaults stand: </p> # Postfix ≥ 2.6 smtp_tls_eccert_file = smtp_tls_eckey_file = + # Postfix ≥ 3.4 + smtp_tls_chain_files = </pre> </blockquote> <p> The best way to use the default settings is to comment out the above parameters in main.cf if present. </p> -<p> During TLS startup negotiation the Postfix SMTP client may present -a certificate to the remote SMTP server. The Netscape client is -rather clever here and lets the user select between only those -certificates that match CA certificates offered by the remote SMTP -server. As the Postfix SMTP client uses the "SSL_connect()" function -from the OpenSSL package, this is not possible and we have to choose -just one certificate. So for now the default is to use _no_ -certificate and key unless one is explicitly specified here. </p> +<p> During TLS startup negotiation the Postfix SMTP client may present a +certificate to the remote SMTP server. Browsers typically let the user +select among the certificates that match the CA names indicated by the +remote SMTP server. The Postfix SMTP client does not yet have a mechanism +to select from multiple candidate certificates on the fly, and supports a +single set of certificates (at most one per public key algorithm). </p> <p> RSA, DSA and ECDSA (Postfix ≥ 2.6) certificates are supported. You can configure all three at the same time, in which case the -cipher used determines which certificate is presented. </p> +cipher used determines which certificate is presented. </p> <p> It is possible for the Postfix SMTP client to use the same key/certificate pair as the Postfix SMTP server. If a certificate @@ -1823,6 +1879,14 @@ must not be encrypted, meaning: it must be accessible without password. Both parts (certificate and private key) may be in the same file. </p> +<p> With OpenSSL 1.1.1 and Postfix ≥ 3.4 it is also possible to +configure Ed25519 and Ed448 certificates. Rather than add two more +pairs of key and certificate parameters, Postfix 3.4 introduces a new +"smtp_tls_chain_files" parameter which specifies all the configured +certificates at once, and handles files that hold both the key and the +associated certificates in one pass, thereby avoiding potential race +conditions during key rollover. </p> + <p> To enable remote SMTP servers to verify the Postfix SMTP client certificate, the issuing CA certificates must be made available to the server. You should include the required certificates in the client @@ -1831,11 +1895,12 @@ CA(s) (bottom-up order). </p> <p> Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". -Create the client.pem file with: </p> +As the "root" super-user create the client.pem file with: </p> <blockquote> <pre> -% <b>cat client_cert.pem intermediate_CA.pem > client.pem </b> +# <b>umask 077</b> +# <b>cat client_key.pem client_cert.pem intermediate_CA.pem > chain.pem </b> </pre> </blockquote> @@ -1845,13 +1910,64 @@ sslclient ..." test. </p> <p> A server that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA -certificate here. Leaving it out of the "client.pem" file reduces +certificate here. Leaving it out of the "chain.pem" file reduces the overhead of the TLS exchange. </p> <p> If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. </p> +<p> Example: Postfix ≥ 3.4 all-in-one chain file(s). One or more +chain files that start with a key that is immediately followed by the +corresponding certificate and any additional issuer certificates. A +single file can hold multiple <i>(key, cert, [chain])</i> sequences, one +per algorithm. It is typically simpler to keep the chain for each +algorithm in its own file. Most users are likely to deploy at most a +single RSA chain, but with OpenSSL 1.1.1, it is possible to deploy up +five chains, one each for RSA, ECDSA, ED25519, ED448 and even the +obsolete DSA. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. Preferred configuration interface. Each file + # starts with the private key, followed by the corresponding + # certificate, and any intermediate issuer certificates. + # + smtp_tls_chain_files = + /etc/postfix/rsa.pem, + /etc/postfix/ecdsa.pem, + /etc/postfix/ed25519.pem, + /etc/postfix/ed448.pem +</pre> +</blockquote> + +<p> You can also store the keys separately from their certificates, again +provided each is listed before the corresponding certificate chain. Storing a +key and its associated certificate chain in separate files is not recommended, +because this is prone to race conditions during key rollover, as there is no +way to update multiple files atomically. </p> + +<blockquote> +<pre> + # Postfix ≥ 3.4. + # Storing keys separately from the associated certificates is not + # recommended. + smtp_tls_chain_files = + /etc/postfix/rsakey.pem, + /etc/postfix/rsacerts.pem, + /etc/postfix/ecdsakey.pem, + /etc/postfix/ecdsacerts.pem +</pre> +</blockquote> + +<p> The below examples show the legacy algorithm-specific configurations +for Postfix 3.3 and older. With Postfix ≤ 3.3, even if the key is +stored in the same file as the certificate, the file is read twice and a +(brief) race condition still exists during key rollover. While Postfix +≥ 3.4 avoids the race when the key and certificate are in the same +file, you should use the new "smtp_tls_chain_files" interface shown +above. <p> + <p> RSA key and certificate examples: </p> <blockquote> @@ -1921,6 +2037,49 @@ when the certificate is needed. </p> </pre> </blockquote> +<h3><a name="client_tls_reuse">Client-side TLS connection reuse</a> </h3> + +<p> Historically, the Postfix SMTP client has supported multiple +deliveries per plaintext connection. Postfix 3.4 introduces support +for multiple deliveries per TLS-encrypted connection. Multiple +deliveries per connection improve mail delivery performance, +especially for destinations that throttle clients that don't combine +deliveries. </p> + +<p> To enable multiple deliveries per TLS connection, specify:</p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + smtp_tls_connection_reuse = yes +</pre> +</blockquote> + +<p> Alternatively, specify the attribute "connection_reuse=yes" in +an smtp_tls_policy_maps entry. </p> + +<p> The implementation of TLS connection reuse relies on the same +scache(8) service as used for delivering plaintext SMTP mail, the +same tlsproxy(8) daemon as used by the postscreen(8) service, and +relies on the same hints from the qmgr(8) daemon. + +See "<a href="CONNECTION_CACHE_README.html">Postfix Connection +Cache</a>" for a description of the underlying connection reuse +infrastructure. </p> + +<p> Initial SMTP handshake:</p> +<pre> smtp(8) -> remote SMTP server</pre> + +<p> Reused SMTP/TLS connection, or new SMTP/TLS connection: </p> +<pre> smtp(8) -> tlsproxy(8) -> remote SMTP server </pre> + +<p> Cached SMTP/TLS connection:</p> +<pre> scache(8) -> tlsproxy(8) -> remote SMTP server</pre> + +<p> As of Postfix 3.4, TLS connection reuse is disabled by default. +This may change once the impact on over-all performance is understood. +</p> + <h3><a name="client_tls_cache">Client-side TLS session cache</a> </h3> <p> The remote SMTP server and the Postfix SMTP client negotiate a @@ -2122,7 +2281,10 @@ additional attributes are supported at this level. </dd> 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. </dd> +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. </dd> <dt><b>encrypt</b></dt> <dd><a href="#client_tls_encrypt"> Mandatory encryption</a>. Mail is delivered only if the remote SMTP server offers STARTTLS @@ -2141,7 +2303,7 @@ found, but none are usable, the effective security level is <a href="#client_tls_encrypt">encrypt</a>. When usable TLSA records are obtained for the remote SMTP server, SSLv2+3 are automatically disabled (see smtp_tls_mandatory_protocols), and the server certificate -must match the TLSA records. RFC 6698 (DANE) TLS authentication +must match the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 and later. </dd> <dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>. @@ -2150,7 +2312,7 @@ 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 6698 (DANE) TLS authentication and +match the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 and later. </dd> <dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate @@ -2808,6 +2970,9 @@ DANE TLSA records. See the postfix-tls(1) documentation for details. <p> The following commands (credits: Viktor Dukhovni) generate and install a 2048-bit RSA private key and 10-year self-signed certificate for the local Postfix system. This requires super-user privileges. +(By using date-specific filenames for the certificate and key files, +and updating main.cf with new filenames, a potential race condition +in which the key and certificate might not match is avoided). </p> <blockquote> diff --git a/external/ibm-public/postfix/dist/proto/postconf.proto b/external/ibm-public/postfix/dist/proto/postconf.proto index 92f6c9dbe2b..979a41e62fd 100644 --- a/external/ibm-public/postfix/dist/proto/postconf.proto +++ b/external/ibm-public/postfix/dist/proto/postconf.proto @@ -989,7 +989,7 @@ is no maximum, it doesn't make much sense to use values above say <p> The only reason why the value of 2 is not the default is the way this parameter affects the delivery of mailing-list mail. In the -worst case, their delivery can take somewhere between (cost+1/cost) +worst case, delivery can take somewhere between (cost+1/cost) and (cost/cost-1) times more than if the preemptive scheduler was disabled. The default value of 5 turns out to provide reasonable message response times while making sure the mailing-list deliveries @@ -1123,7 +1123,9 @@ This feature is available in Postfix 2.0 and later. </p> <p> -The template is subject to exactly one level of $name substitution: +The template does not support Postfix configuration parameter $name +substitution. Instead, it supports exactly one level of $name +substitution for the following attributes: </p> <dl> @@ -1238,13 +1240,6 @@ non-address DSN status (e.g., 4.0.0). </p> </ul> -%PARAM smtpd_expansion_filter see "postconf -d" output - -<p> -The smtpd_expansion_filter configuration parameter controls what -characters may appear in $name expansions. -</p> - %PARAM default_recipient_limit 20000 <p> @@ -1315,7 +1310,9 @@ domain. Specify a string of the form <i>transport:nexthop</i>, where <i>transport</i> is the name of a mail delivery transport defined in master.cf. The <i>:nexthop</i> destination is optional; its syntax is documented -in the manual page of the corresponding delivery agent. +in the manual page of the corresponding delivery agent. In the case of +SMTP or LMTP, specify one or more destinations separated by comma or +whitespace (with Postfix 3.5 and later). </p> <p> @@ -1402,22 +1399,39 @@ for showq(8) queue displays. </p> %PARAM enable_original_recipient yes -<p> Enable support for the X-Original-To message header. This header -is needed for multi-recipient mailboxes. </p> +<p> Enable support for the original recipient address after an +address is rewritten to a different address (for example with +aliasing or with canonical mapping). </p> -<p> When this parameter is set to yes, the cleanup(8) daemon performs -duplicate elimination on distinct pairs of (original recipient, -rewritten recipient), and generates non-empty original recipient -queue file records. </p> +<p> The original recipient address is used as follows: </p> -<p> When this parameter is set to no, the cleanup(8) daemon performs -duplicate elimination on the rewritten recipient address only, and -generates empty original recipient queue file records. </p> +<dl> -<p> This feature is available in Postfix 2.1 and later. With Postfix -version 2.0, support for the X-Original-To message header is always turned -on. Postfix versions before 2.0 have no support for the X-Original-To -message header. </p> +<dt> Final delivery </dt> <dd> With "enable_original_recipient = +yes", the original recipient address is stored in the <b>X-Original-To</b> +message header. This header may be used to distinguish between +different recipients that share the same mailbox. </dd> + +<dt> Recipient deduplication </dt> <dd> With "enable_original_recipient += yes", the cleanup(8) daemon performs duplicate recipient elimination +based on the content of (original recipient, maybe-rewritten +recipient) pairs. Otherwise, the cleanup(8) daemon performs duplicate +recipient elimination based only on the maybe-rewritten recipient +address. </dd> + +</dl> + +<p> Note: with Postfix ≤ 3.2 the "setting enable_original_recipient += <b>no</b>" breaks address verification for addresses that are +aliased or otherwise rewritten (Postfix is unable to store the +address verification result under the original probe destination +address; instead, it can store the result only under the rewritten +address). </p> + +<p> This feature is available in Postfix 2.1 and later. Postfix +version 2.0 behaves as if this parameter is always set to <b>yes</b>. +Postfix versions before 2.0 have no support for the original recipient +address. </p> %PARAM export_environment see "postconf -d" output @@ -1430,7 +1444,8 @@ time keeping on System-V-ish systems. <p> Specify a list of names and/or name=value pairs, separated by whitespace or comma. Specify "{ name=value }" to protect whitespace -or comma in parameter values (whitespace after "{" and before "}" +or comma in parameter values (whitespace after the opening "{" and +before the closing "}" is ignored). The form name=value is supported with Postfix version 2.1 and later; the use of {} is supported with Postfix 3.0 and later. </p> @@ -1611,8 +1626,10 @@ outside the allowed set are replaced by underscores. </p> external command. Failure to change directory causes the delivery to be deferred. </p> -<p> The following $name expansions are done on command_execution_directory -before the directory is changed. Expansion happens in the context +<p> The command_execution_directory value is not subject to Postfix +configuration parameter $name expansion. Instead, the following +$name expansions are done on command_execution_directory before the +directory is used. Expansion happens in the context of the delivery request. The result of $name expansion is filtered with the character set that is specified with the execution_directory_expansion_filter parameter. </p> @@ -1675,8 +1692,10 @@ Instead of $name you can also specify ${name} or $(name). file with user-specified delivery methods. The first file that is found is used. </p> -<p> The following $name expansions are done on forward_path before -the search actually happens. The result of $name expansion is +<p> The forward_path value is not subject to Postfix configuration +parameter $name expansion. Instead, the following $name expansions +are done on forward_path before the search actually happens. +The result of $name expansion is filtered with the character set that is specified with the forward_expansion_filter parameter. </p> @@ -1872,17 +1891,18 @@ mis-delivery of mail. %PARAM import_environment see "postconf -d" output -<p> -The list of environment parameters that a Postfix process will -import from a non-Postfix parent process. Examples of relevant -parameters: -</p> +<p> The list of environment parameters that a privileged Postfix +process will import from a non-Postfix parent process, or name=value +environment overrides. Unprivileged utilities will enforce the +name=value overrides, but otherwise will not change their process +environment. Examples of relevant parameters: </p> <dl> <dt><b>TZ</b></dt> -<dd>Needed for sane time keeping on most System-V-ish systems. </dd> +<dd>May be needed for sane time keeping on most System-V-ish systems. +</dd> <dt><b>DISPLAY</b></dt> @@ -1900,7 +1920,8 @@ parameters: <p> Specify a list of names and/or name=value pairs, separated by whitespace or comma. Specify "{ name=value }" to protect whitespace -or comma in parameter values (whitespace after "{" and before "}" +or comma in parameter values (whitespace after the opening "{" and +before the closing "}" is ignored). The form name=value is supported with Postfix version 2.1 and later; the use of {} is supported with Postfix 3.0 and later. </p> @@ -2431,7 +2452,9 @@ as undeliverable. </p> <p> -The following $name expansions are done on luser_relay: +The luser_relay value is not subject to Postfix configuration +parameter $name expansion. Instead, the following $name expansions +are done: </p> <dl> @@ -2666,7 +2689,7 @@ it easier to specify shell syntax (see example below). <p> If you can, avoid shell meta characters because they will force Postfix to run an expensive shell process. If you're delivering -via Procmail then running a shell won't make a noticeable difference +via "procmail" then running a shell won't make a noticeable difference in the total cost. </p> @@ -2805,7 +2828,7 @@ masquerade_domains = $mydomain <p> Optional list of user names that are not subjected to address -masquerading, even when their address matches $masquerade_domains. +masquerading, even when their addresses match $masquerade_domains. </p> <p> @@ -3752,7 +3775,7 @@ This feature is available in Postfix 2.0 and later. %PARAM relayhost <p> -The next-hop destination of non-local mail; overrides non-local +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 @@ -3766,9 +3789,11 @@ gateway host instead. </p> <p> -In the case of SMTP, specify a domain name, hostname, hostname:port, -[hostname]:port, [hostaddress] or [hostaddress]:port. The form -[hostname] turns off MX lookups. +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. </p> <p> @@ -3783,7 +3808,7 @@ Examples: <pre> relayhost = $mydomain relayhost = [gateway.example.com] -relayhost = uucphost +relayhost = mail1.example:587, mail2.example:587 relayhost = [an.ip.add.ress] </pre> @@ -5078,15 +5103,28 @@ client network address information. <dt><b><a name="check_ccert_access">check_ccert_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt> -<dd> Use the remote SMTP client certificate fingerprint or the public key +<dd> By default use the remote SMTP client certificate fingerprint +or the public key fingerprint (Postfix 2.9 and later) as lookup key for the specified access(5) database; with Postfix version 2.2, also require that the remote SMTP client certificate is verified successfully. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard-coded as md5 prior to -Postfix version 2.5). This feature is available with Postfix version +Postfix version 2.5). This feature requires "smtpd_tls_ask_ccert += yes" and is available with Postfix version 2.2 and later. </dd> +<br> + +<dd> Alternatively, check_ccert_access accepts an explicit search +order (Postfix 3.5 and later). The default search order as described +above corresponds with: </dd> + +<dd> check_ccert_access { type:table, { search_order = cert_fingerprint, +pubkey_fingerprint } } </dd> + +<dd> The commas are optional. </dd> + <dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt> <dd>Search the specified access database for the client hostname, @@ -5186,7 +5224,8 @@ CA. Otherwise, clients with a third-party certificate would also be allowed to relay. Specify "tls_append_default_CA = no" when the trusted CA is specified with smtpd_tls_CAfile or smtpd_tls_CApath, to prevent Postfix from appending the system-supplied default CAs. -This feature is available with Postfix version 2.2.</dd> +This feature requires "smtpd_tls_ask_ccert = yes" and is available +with Postfix version 2.2 and later.</dd> <dt><b><a name="permit_tls_clientcerts">permit_tls_clientcerts</a></b></dt> @@ -5195,8 +5234,8 @@ fingerprint or public key fingerprint (Postfix 2.9 and later) is listed in $relay_clientcerts. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard-coded as md5 prior to -Postfix version 2.5). This feature is available with Postfix version -2.2. </dd> +Postfix version 2.5). This feature requires "smtpd_tls_ask_ccert += yes" and is available with Postfix version 2.2 and later.</dd> <dt><b><a name="reject_rbl_client">reject_rbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt> @@ -5274,7 +5313,7 @@ available in Postfix 2.8 and later. </dd> <dt><b><a name="reject_unknown_client_hostname">reject_unknown_client_hostname</a></b> (with Postfix < 2.3: reject_unknown_client)</dt> <dd>Reject the request when 1) the client IP address->name mapping -fails, 2) the name->address mapping fails, or 3) the name->address +fails, or 2) the name->address mapping fails, or 3) the name->address mapping does not match the client IP address. <br> This is a stronger restriction than the reject_unknown_reverse_client_hostname feature, which triggers only under condition 1) above. <br> The @@ -5604,7 +5643,8 @@ Use C like escapes to specify special characters such as whitespace. </p> <p> -This parameter is not subjected to $parameter expansion. +The smtpd_expansion_filter value is not subject to Postfix configuration +parameter $name expansion. </p> <p> @@ -6040,7 +6080,8 @@ lookup problem with Postfix prior to version 2.0. <dt><b><a name="reject_non_fqdn_recipient">reject_non_fqdn_recipient</a></b></dt> -<dd>Reject the request when the RCPT TO address is not in +<dd>Reject the request when the RCPT TO address specifies a +domain that is not in fully-qualified domain form, as required by the RFC. <br> The non_fqdn_reject_code parameter specifies the response code for rejected requests (default: 504). </dd> @@ -6119,8 +6160,9 @@ numerical response code when an address probe failed due to a temporary problem (default: 450). <br> The unverified_recipient_tempfail_action parameter specifies the action after address probe failure due to a temporary problem (default: -defer_if_permit). <br> This feature is available in Postfix 2.1 -and later. </dd> +defer_if_permit). <br> This feature breaks for aliased addresses +with "enable_original_recipient = no" (Postfix ≤ 3.2). <br> +This feature is available in Postfix 2.1 and later. </dd> </dl> @@ -6519,8 +6561,9 @@ feature is available in Postfix version 2.11 and later. </dd> <dt><b><a name="reject_non_fqdn_sender">reject_non_fqdn_sender</a></b></dt> -<dd>Reject the request when the MAIL FROM address is not in -fully-qualified domain form, as required by the RFC. <br> The +<dd>Reject the request when the MAIL FROM address specifies a +domain that is not in +fully-qualified domain form as required by the RFC. <br> The non_fqdn_reject_code parameter specifies the response code for rejected requests (default: 504). </dd> @@ -6587,8 +6630,10 @@ change into 550 when you are confident that it is safe to do so). code when an address probe failed due to a temporary problem (default: 450). <br> The unverified_sender_tempfail_action parameter specifies the action after address probe failure due to a temporary -problem (default: defer_if_permit). <br> This feature is available -in Postfix 2.1 and later. </dd> +problem (default: defer_if_permit). <br> This feature breaks for +aliased addresses with "enable_original_recipient = no" (Postfix +≤ 3.2). <br> This feature is available in Postfix 2.1 and later. +</dd> </dl> @@ -6746,8 +6791,8 @@ errors while accessing the Postfix main.cf configuration file. %PARAM syslog_name see "postconf -d" output <p> -The mail system name that is prepended to the process name in syslog -records, so that "smtpd" becomes, for example, "postfix/smtpd". +A prefix that is prepended to the process name in syslog +records, so that, for example, "smtpd" becomes "prefix/smtpd". </p> <p> @@ -7122,16 +7167,22 @@ probes, and generates probes on request by other Postfix processes. <p> A list of non-default Postfix configuration directories that may -be specified with "-c config_directory" on the command line, or -via the MAIL_CONFIG environment parameter. +be specified with "-c config_directory" on the command line (in the +case of sendmail(1), with the "-C" option), or via the MAIL_CONFIG +environment parameter. </p> <p> -This list must be specified in the default Postfix configuration -directory, and is used by set-gid Postfix commands such as postqueue(1) +This list must be specified in the default Postfix main.cf file, +and will be used by set-gid Postfix commands such as postqueue(1) and postdrop(1). </p> +<p> +Specify absolute pathnames, separated by comma or space. Note: $name +expansion is not supported. +</p> + %PARAM append_at_myorigin yes <p> @@ -7691,10 +7742,11 @@ This feature is available in Postfix 2.0 and later. %PARAM expand_owner_alias no <p> -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. Normally, Postfix sets the envelope -sender address to the name of the "owner-aliasname" alias. +When delivering to an alias "<i>aliasname</i>" that has an +"owner-<i>aliasname</i>" companion alias, set the envelope sender +address to the expansion of the "owner-<i>aliasname</i>" alias. +Normally, Postfix sets the envelope sender address to the name of +the "owner-<i>aliasname</i>" alias. </p> %PARAM fallback_transport @@ -7858,6 +7910,14 @@ lmtp_sasl_security_options = noplaintext <p> The default TCP port that the Postfix LMTP client connects to. +Specify a symbolic name (see services(5)) or a numeric port. +</p> + +%PARAM smtp_tcp_port smtp + +<p> +The default TCP port that the Postfix SMTP client connects to. +Specify a symbolic name (see services(5)) or a numeric port. </p> %PARAM mail_release_date see "postconf -d" output @@ -8030,10 +8090,10 @@ or reject_non_fqdn_recipient restriction. %PARAM owner_request_special yes <p> -Give special treatment to owner-listname and listname-request -address localparts: don't split such addresses when the -recipient_delimiter is set to "-". This feature is useful for -mailing lists. +Enable special treatment for owner-<i>listname</i> entries in the +aliases(5) file, and don't split owner-<i>listname</i> and +<i>listname</i>-request address localparts when the recipient_delimiter +is set to "-". This feature is useful for mailing lists. </p> %PARAM permit_mx_backup_networks @@ -8091,6 +8151,30 @@ prepend_delivered_header = forward The process name of a Postfix command or daemon process. </p> +%PARAM service_name read-only + +<p> The master.cf service name of a Postfix daemon process. This +can be used to distinguish the logging from different services that +use the same program name. </p> + +<p> Example master.cf entries: </p> + +<pre> +# Distinguish inbound MTA logging from submission and smtps logging. +smtp inet n - n - - smtpd +submission inet n - n - - smtpd + -o syslog_name=postfix/$service_name +smtps inet n - n - - smtpd + -o syslog_name=postfix/$service_name +</pre> + +<pre> +# Distinguish outbound MTA logging from inbound relay logging. +smtp unix - - n - - smtp +relay unix - - n - - smtp + -o syslog_name=postfix/$service_name +</pre> + %PARAM process_id read-only <p> @@ -8291,8 +8375,8 @@ earlier: "<b>/etc/postfix/post-install set-permissions</b>". <p> Display the name of the recipient table in the "User unknown" -responses. The extra detail makes trouble shooting easier but also -reveals information that is nobody elses business. +responses. The extra detail makes troubleshooting easier but also +reveals information that is nobody else's business. </p> <p> @@ -9243,7 +9327,9 @@ local_header_rewrite_clients = permit_mynetworks, %PARAM smtpd_tls_cert_file <p> File with the Postfix SMTP server RSA certificate in PEM format. -This file may also contain the Postfix SMTP server private RSA key. </p> +This file may also contain the Postfix SMTP server private RSA key. +With Postfix ≥ 3.4 the preferred way to configure server keys and +certificates is via the "smtpd_tls_chain_files" parameter. </p> <p> Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a @@ -9252,15 +9338,22 @@ able to authenticate the server, but unless it is running Postfix 2.3 or similar software, it will still insist on a server certificate. </p> <p> For servers that are <b>not</b> public Internet MX hosts, Postfix -2.3 supports configurations with no certificates. This entails the -use of just the anonymous TLS ciphers, which are not supported by -typical SMTP clients. Since such clients will not, as a rule, fall -back to plain text after a TLS handshake failure, the server will -be unable to receive email from TLS enabled clients. To avoid -accidental configurations with no certificates, Postfix 2.3 enables -certificate-less operation only when the administrator explicitly -sets "smtpd_tls_cert_file = none". This ensures that new Postfix -configurations will not accidentally run with no certificates. </p> +supports configurations with no certificates. This entails the use of +just the anonymous TLS ciphers, which are not supported by typical SMTP +clients. Since some clients may not fall back to plain text after a TLS +handshake failure, a certificate-less Postfix SMTP server will be unable +to receive email from some TLS-enabled clients. To avoid accidental +configurations with no certificates, Postfix enables certificate-less +operation only when the administrator explicitly sets +"smtpd_tls_cert_file = none". This ensures that new Postfix SMTP server +configurations will not accidentally enable TLS without certificates. </p> + +<p> Note that server certificates are not optional in TLS 1.3. To run +without certificates you'd have to disable the TLS 1.3 protocol by +including '!TLSv1.3' in "smtpd_tls_protocols" and perhaps also +"smtpd_tls_mandatory_protocols". It is simpler instead to just +configure a certificate chain. Certificate-less operation is not +recommended. <p> <p> Both RSA and DSA certificates are supported. When both types are present, the cipher used determines which certificate will be @@ -9280,8 +9373,8 @@ root_CA.pem > server.pem". </p> <p> If you also want to verify client certificates issued by these CAs, you can add the CA certificates to the smtpd_tls_CAfile, in which -case it is not necessary to have them in the smtpd_tls_cert_file or -smtpd_tls_dcert_file. </p> +case it is not necessary to have them in the smtpd_tls_cert_file, +smtpd_tls_dcert_file (obsolete) or smtpd_tls_eccert_file. </p> <p> A certificate supplied here must be usable as an SSL server certificate and hence pass the "openssl verify -purpose sslserver ..." test. </p> @@ -9298,7 +9391,9 @@ smtpd_tls_cert_file = /etc/postfix/server.pem <p> File with the Postfix SMTP server RSA private key in PEM format. This file may be combined with the Postfix SMTP server RSA certificate -file specified with $smtpd_tls_cert_file. </p> +file specified with $smtpd_tls_cert_file. With Postfix ≥ 3.4 the +preferred way to configure server keys and certificates is via the +"smtpd_tls_chain_files" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -9308,7 +9403,8 @@ to anyone else. </p> %PARAM smtpd_tls_dcert_file <p> File with the Postfix SMTP server DSA certificate in PEM format. -This file may also contain the Postfix SMTP server private DSA key. </p> +This file may also contain the Postfix SMTP server private DSA key. +The DSA algorithm is obsolete and should not be used. </p> <p> See the discussion under smtpd_tls_cert_file for more details. </p> @@ -9325,7 +9421,8 @@ smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem <p> File with the Postfix SMTP server DSA private key in PEM format. This file may be combined with the Postfix SMTP server DSA certificate -file specified with $smtpd_tls_dcert_file. </p> +file specified with $smtpd_tls_dcert_file. The DSA algorithm is obsolete +and should not be used. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -9716,9 +9813,10 @@ was fixed at 300s. </p> %PARAM smtp_tls_cert_file <p> File with the Postfix SMTP client RSA certificate in PEM format. -This file may also contain the Postfix SMTP client private RSA key, -and these may be the same as the Postfix SMTP server RSA certificate and key -file. </p> +This file may also contain the Postfix SMTP client private RSA key, and +these may be the same as the Postfix SMTP server RSA certificate and key +file. With Postfix ≥ 3.4 the preferred way to configure client keys +and certificates is via the "smtp_tls_chain_files" parameter. </p> <p> Do not configure client certificates unless you <b>must</b> present client TLS certificates to one or more servers. Client certificates are @@ -9729,10 +9827,13 @@ well without them. The recommended setting is to let the defaults stand: </p> <pre> smtp_tls_cert_file = smtp_tls_key_file = -smtp_tls_dcert_file = -smtp_tls_dkey_file = smtp_tls_eccert_file = smtp_tls_eckey_file = +# Obsolete DSA parameters +smtp_tls_dcert_file = +smtp_tls_dkey_file = +# Postfix ≥ 3.4 interface +smtp_tls_chain_files = </pre> </blockquote> @@ -9747,13 +9848,19 @@ CA(s) (bottom-up order). </p> <p> Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". -Create the client.pem file with "cat client_cert.pem intermediate_CA.pem -root_CA.pem > client.pem". </p> +As the "root" super-user create the client.pem file with: </p> + +<blockquote> +<pre> +# <b>umask 077</b> +# <b>cat client_key.pem client_cert.pem intermediate_CA.pem > chain.pem </b> +</pre> +</blockquote> <p> If you also want to verify remote SMTP server certificates issued by these CAs, you can add the CA certificates to the smtp_tls_CAfile, in which case it is not necessary to have them in the smtp_tls_cert_file, -smtp_tls_dcert_file or smtp_tls_eccert_file. </p> +smtp_tls_dcert_file (obsolete) or smtp_tls_eccert_file. </p> <p> A certificate supplied here must be usable as an SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. </p> @@ -9761,7 +9868,7 @@ and hence pass the "openssl verify -purpose sslclient ..." test. </p> <p> Example: </p> <pre> -smtp_tls_cert_file = /etc/postfix/client.pem +smtp_tls_cert_file = /etc/postfix/chain.pem </pre> <p> This feature is available in Postfix 2.2 and later. </p> @@ -9770,7 +9877,9 @@ smtp_tls_cert_file = /etc/postfix/client.pem <p> File with the Postfix SMTP client RSA private key in PEM format. This file may be combined with the Postfix SMTP client RSA certificate -file specified with $smtp_tls_cert_file. </p> +file specified with $smtp_tls_cert_file. With Postfix ≥ 3.4 the +preferred way to configure client keys and certificates is via the +"smtp_tls_chain_files" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -9795,7 +9904,7 @@ smtp_tls_CApath instead, but note that the latter directory must be present in the chroot jail if the smtp(8) client is chrooted. This file may also be used to augment the client certificate trust chain, but it is best to include all the required certificates directly in -$smtp_tls_cert_file. </p> +$smtp_tls_cert_file (or, Postfix ≥ 3.4 $smtp_tls_chain_files). </p> <p> Specify "smtp_tls_CAfile = /path/to/system_CA_file" to use ONLY the system-supplied default Certification Authority certificates. @@ -10104,7 +10213,8 @@ during TLS startup and shutdown handshake procedures. </p> <p> File with the Postfix SMTP client DSA private key in PEM format. This file may be combined with the Postfix SMTP client DSA certificate -file specified with $smtp_tls_dcert_file. </p> +file specified with $smtp_tls_dcert_file. The DSA algorithm is obsolete +and should not be used. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -10116,7 +10226,8 @@ to anyone else. </p> %PARAM smtp_tls_dcert_file <p> File with the Postfix SMTP client DSA certificate in PEM format. -This file may also contain the Postfix SMTP client private DSA key. </p> +This file may also contain the Postfix SMTP client private DSA key. +The DSA algorithm is obsolete and should not be used. </p> <p> See the discussion under smtp_tls_cert_file for more details. </p> @@ -10717,6 +10828,22 @@ selected with <b>smtpd_sasl_type</b> and <b>smtpd_sasl_path</b>. <p> This feature is available in Postfix 2.11 and later. Prior versions behave as if "<b>smtp</b>" is specified. </p> +%PARAM smtpd_sasl_response_limit 12288 + +<p> The maximum length of a SASL client's response to a server challenge. +When the client's "initial response" is longer than the normal limit for +SMTP commands, the client must omit its initial response, and wait for an +empty server challenge; it can then send what would have been its "initial +response" as a response to the empty server challenge. RFC4954 requires the +server to accept client responses up to at least 12288 octets of +base64-encoded text. The default value is therefore also the minimum value +accepted for this parameter.</p> + +<p> This feature is available in Postfix 3.4 and later. Prior versions use +"line_length_limit", which may need to be raised to accommodate larger client +responses, as may be needed with GSSAPI authentication of Windows AD users +who are members of many groups. </p> + %PARAM cyrus_sasl_config_path <p> Search path for Cyrus SASL application configuration files, @@ -10988,11 +11115,13 @@ security are: </p> <dt><b><a href="TLS_README.html#client_tls_may">may</a></b></dt> <dd>Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces -interoperability. The optional "ciphers", "exclude" and "protocols" +interoperability. 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. When opportunistic TLS -handshakes fail, Postfix retries the connection with TLS disabled. +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. When opportunistic +TLS handshakes fail, Postfix retries the connection with TLS disabled. This allows mail delivery to sites with non-interoperable TLS implementations.</dd> @@ -11000,9 +11129,11 @@ implementations.</dd> <dd>Mandatory TLS encryption. 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 +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. In the policy table, +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 protocols or excluded ciphers must be separated by colons, as attribute values may not contain whitespace or commas. </dd> @@ -11014,20 +11145,24 @@ href="TLS_README.html#client_tls_may">may</a>. If TLSA records are found, but none are usable, the effective security level is <a href="TLS_README.html#client_tls_encrypt">encrypt</a>. When usable TLSA records are obtained for the remote SMTP server, the -server certificate must match the TLSA records. RFC 6698 (DANE) +server certificate must match the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix -2.11 and later. </dd> +2.11 and later. The optional "connection_reuse" attribute (Postfix +≥ 3.4) overrides the main.cf smtp_tls_connection_reuse parameter. +</dd> <dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt> <dd>Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA records in DNSSEC. If no TLSA records are found, or none are usable, no connection is made to the server. When usable TLSA records are obtained for the remote SMTP server, the -server certificate must match the TLSA records. RFC 6698 (DANE) TLS +server certificate must match the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is available with Postfix 2.11 -and later. </dd> +and later. The optional "connection_reuse" attribute (Postfix ≥ +3.4) overrides the main.cf smtp_tls_connection_reuse parameter. +</dd> -<dt><b><a href="TLS_README.html#client_tls_fingerprint">fingerprint</a></b></dt> +<dt><b><a href="TLS_README.html#client_tls_fprint">fingerprint</a></b></dt> <dd>Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted Certification Authorities. The certificate @@ -11041,7 +11176,8 @@ algorithm used to calculate the fingerprint is selected by the be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) -digits. </dd> +digits. The optional "connection_reuse" attribute (Postfix ≥ 3.4) +overrides the main.cf smtp_tls_connection_reuse parameter. </dd> <dt><b><a href="TLS_README.html#client_tls_verify">verify</a></b></dt> <dd>Mandatory TLS verification. At this security @@ -11051,7 +11187,9 @@ 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. </dd> +"secure" policy, described below. The optional "connection_reuse" +attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. </dd> <dt><b><a href="TLS_README.html#client_tls_secure">secure</a></b></dt> <dd>Secure-channel TLS. At this security level, DNS @@ -11069,7 +11207,9 @@ routing 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. </dd> +verification of a new MX host fails. The optional "connection_reuse" +attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. </dd> </dl> @@ -11129,8 +11269,10 @@ matches the underlying OpenSSL interface semantics. <p> The range of protocols advertised by an SSL/TLS client must be contiguous. When a protocol version is enabled, disabling any -higher version implicitly disables all versions above that higher -version. Thus, for example: </p> +higher version implicitly disables all versions above that higher version. +Thus, for example (assuming the OpenSSL library supports both SSLv2 +and SSLv3): +</p> <blockquote> <pre> smtp_tls_mandatory_protocols = !SSLv2, !TLSv1 @@ -11147,6 +11289,10 @@ disabled except by also disabling "TLSv1" (typically leaving just versions of Postfix ≥ 2.10 can explicitly disable support for "TLSv1.1" or "TLSv1.2". </p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> At the <a href="TLS_README.html#client_tls_dane">dane</a> and <a href="TLS_README.html#client_tls_dane">dane-only</a> security levels, when usable TLSA records are obtained for the remote SMTP @@ -11344,6 +11490,10 @@ disabled. The latest patch levels of Postfix ≥ 2.6, and all versions of Postfix ≥ 2.10 can disable support for "TLSv1.1" or "TLSv1.2". </p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> Example: </p> <pre> @@ -11401,7 +11551,7 @@ in effect, the destination domain's containing DNS zone must be signed and the Postfix SMTP client's operating system must be configured to send its DNS queries to a recursive DNS nameserver that is able to validate the signed records. Each MX host's DNS -zone should also be signed, and should publish DANE TLSA (RFC 6698) +zone should also be signed, and should publish DANE TLSA (RFC 7672) records that specify how that MX host's TLS certificate is to be verified. TLSA records do not preempt the normal SMTP MX host selection algorithm, if some MX hosts support TLSA and others do @@ -11416,17 +11566,17 @@ purposes of protocol and cipher selection, the "dane" security level is treated like a "mandatory" TLS security level, and weak ciphers and protocols are disabled. Since DANE authenticates server certificates the "aNULL" cipher-suites are transparently excluded -at this level, no need to configure this manually. RFC 6698 (DANE) +at this level, no need to configure this manually. RFC 7672 (DANE) TLS authentication is available with Postfix 2.11 and later. </dd> <dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt> <dd>Mandatory DANE TLS. This is just like "dane" above, but DANE TLSA authentication is required. There is no fallback to "may" or -"encrypt" when TLSA records are missing or unusable. RFC 6698 +"encrypt" when TLSA records are missing or unusable. RFC 7672 (DANE) TLS authentication is available with Postfix 2.11 and later. </dd> -<dt><b><a href="TLS_README.html#client_tls_fingerprint">fingerprint</a></b></dt> +<dt><b><a href="TLS_README.html#client_tls_fprint">fingerprint</a></b></dt> <dd>Certificate fingerprint verification. At this security level, there are no trusted Certification Authorities. The certificate trust chain, expiration date, etc., are @@ -11577,8 +11727,9 @@ will not reply for each individual message header.</dd> %PARAM milter_default_action tempfail -<p> The default action when a Milter (mail filter) application is -unavailable or mis-configured. Specify one of the following: </p> +<p> The default action when a Milter (mail filter) response is +unavailable (for example, bad Postfix configuration or Milter +failure). Specify one of the following: </p> <dl compact> @@ -12485,11 +12636,13 @@ and "TLSv1". </p> <p> The range of protocols advertised by an SSL/TLS client must be contiguous. When a protocol version is enabled, disabling any -higher version implicitly disables all versions above that higher -version. Thus, for example: </p> +higher version implicitly disables all versions above that higher version. +Thus, for example (assuming the OpenSSL library supports both SSLv2 +and SSLv3): +</p> <blockquote> <pre> -smtp_tls_mandatory_protocols = !SSLv2, !TLSv1 +smtp_tls_protocols = !SSLv2, !TLSv1 </pre> </blockquote> <p> also disables any protocols version higher than TLSv1 leaving @@ -12500,6 +12653,10 @@ and "TLSv1.2". The latest patch levels of Postfix ≥ 2.6, and all versions of Postfix ≥ 2.10 can explicitly disable support for "TLSv1.1" or "TLSv1.2"</p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 for opportunistic TLS set "smtp_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set @@ -12532,6 +12689,10 @@ and "TLSv1.2". The latest patch levels of Postfix ≥ 2.6, and all versions of Postfix ≥ 2.10 can disable support for "TLSv1.1" or "TLSv1.2". </p> +<p> OpenSSL 1.1.1 introduces support for "TLSv1.3". With Postfix +≥ 3.4 (or patch releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2) +this can be disabled, if need be, via "!TLSv1.3". </p> + <p> To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 for opportunistic TLS set "smtpd_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set @@ -12596,6 +12757,29 @@ parameter. See there for details. </p> <p> This feature is available in Postfix 2.6 and later. </p> +%PARAM tls_eecdh_auto_curves see "postconf -d" output + +<p> The prioritized list of elliptic curves supported by the Postfix +SMTP client and server. These curves are used by the Postfix SMTP +server when "smtpd_tls_eecdh_grade = auto". The selected curves +must be implemented by OpenSSL and be standardized for use in TLS +(RFC 4492 or its imminent successor). It is unwise to list only +"bleeding-edge" curves supported by a small subset of clients. The +default list is suitable for most users. </p> + +<p> Postfix skips curve names that are unknown to OpenSSL, or that +are known but not yet implemented. This makes it possible to +"anticipate" support for curves that should be used once they become +available. In particular, in some OpenSSL versions, the new RFC +8031 curves "X25519" and "X448" may be known by name, but ECDH +support for either or both may be missing. These curves may appear +in the default value of this parameter, even though they'll only +be usable with later versions of OpenSSL. </p> + +<p> This feature is available in Postfix 3.2 and later, when it is +compiled and linked with OpenSSL 1.0.2 or later on platforms where +EC algorithms have not been disabled by the vendor. </p> + %PARAM tls_eecdh_strong_curve prime256v1 <p> The elliptic curve used by the Postfix SMTP server for sensibly @@ -12608,11 +12792,11 @@ reported by ecparam(1) with the "-list_curves" option) and be one of the curves listed in Section 5.1.1 of RFC 4492. You should not generally change this setting. Remote SMTP client implementations must support this curve for EECDH key exchange to take place. It -is unwise to choose an "exotic" curve supported by only a small subset -of clients. </p> +is unwise to choose an "bleeding-edge" curve supported by only a +small subset of clients. </p> <p> The default "strong" curve is rated in NSA <a -href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite +href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite B</a> for information classified up to SECRET. </p> <p> Note: elliptic curve names are poorly standardized; different @@ -12649,7 +12833,7 @@ curve must be implemented by OpenSSL (as reported by ecparam(1) with the of RFC 4492. You should not generally change this setting. </p> <p> This default "ultra" curve is rated in NSA <a -href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite +href="https://web.archive.org/web/20160330034144/https://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite B</a> for information classified up to TOP SECRET. </p> <p> If you want to take maximal advantage of ciphers that offer <a @@ -12691,6 +12875,11 @@ as 128 bit strength ECC. Barring significant progress in attacks on elliptic curve crypto-systems, the "strong" curve is sufficient for most users. </dd> +<dt><b>auto</b></dt> <dd> Use the most preferred curve that is +supported by both the client and the server. This setting requires +Postfix ≥ 3.2 compiled and linked with OpenSSL ≥ 1.0.2. This +is the default setting under the above conditions. </dd> + </dl> <p> If you want to take maximal advantage of ciphers that offer <a @@ -12710,7 +12899,9 @@ where EC algorithms have not been disabled by the vendor. </p> %PARAM smtpd_tls_eccert_file <p> File with the Postfix SMTP server ECDSA certificate in PEM format. -This file may also contain the Postfix SMTP server private ECDSA key. </p> +This file may also contain the Postfix SMTP server private ECDSA key. +With Postfix ≥ 3.4 the preferred way to configure server keys and +certificates is via the "smtpd_tls_chain_files" parameter. </p> <p> See the discussion under smtpd_tls_cert_file for more details. </p> @@ -12727,7 +12918,9 @@ compiled and linked with OpenSSL 1.0.0 or later. </p> <p> File with the Postfix SMTP server ECDSA private key in PEM format. This file may be combined with the Postfix SMTP server ECDSA certificate -file specified with $smtpd_tls_eccert_file. </p> +file specified with $smtpd_tls_eccert_file. With Postfix ≥ 3.4 the +preferred way to configure server keys and certificates is via the +"smtpd_tls_chain_files" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -12740,7 +12933,9 @@ compiled and linked with OpenSSL 1.0.0 or later. </p> %PARAM smtp_tls_eccert_file <p> File with the Postfix SMTP client ECDSA certificate in PEM format. -This file may also contain the Postfix SMTP client ECDSA private key. </p> +This file may also contain the Postfix SMTP client ECDSA private key. +With Postfix ≥ 3.4 the preferred way to configure client keys and +certificates is via the "smtp_tls_chain_files" parameter. </p> <p> See the discussion under smtp_tls_cert_file for more details. </p> @@ -12757,8 +12952,10 @@ compiled and linked with OpenSSL 1.0.0 or later. </p> %PARAM smtp_tls_eckey_file $smtp_tls_eccert_file <p> File with the Postfix SMTP client ECDSA private key in PEM format. -This file may be combined with the Postfix SMTP client ECDSA -certificate file specified with $smtp_tls_eccert_file. </p> +This file may be combined with the Postfix SMTP client ECDSA certificate +file specified with $smtp_tls_eccert_file. With Postfix ≥ 3.4 the +preferred way to configure client keys and certificates is via the +"smtp_tls_chain_files" parameter. </p> <p> The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only @@ -13166,9 +13363,10 @@ this case: "_recipient_refill_delay"). </p> %PARAM default_transport_rate_delay 0s <p> The default amount of delay that is inserted between individual -deliveries over the same message delivery transport, regardless of -destination. If non-zero, all deliveries over the same message -delivery transport will happen one at a time. </p> +message deliveries over the same message delivery transport, +regardless of destination. Specify a non-zero value to rate-limit +those message deliveries to at most one per $default_transport_rate_delay. +</p> <p>Use <i>transport</i>_transport_rate_delay to specify a transport-specific override, where the initial <i>transport</i> is @@ -13202,8 +13400,14 @@ name is the master.cf name of the message delivery transport. </p> %PARAM default_destination_rate_delay 0s <p> The default amount of delay that is inserted between individual -deliveries to the same destination; the resulting behavior depends -on the value of the corresponding per-destination recipient limit. +message deliveries to the same destination and over the same message +delivery transport. Specify a non-zero value to rate-limit those +message deliveries to at most one per $default_destination_rate_delay. +</p> + +<p> The resulting behavior depends on the value of the corresponding +per-destination recipient limit. + </p> <ul> @@ -13593,7 +13797,7 @@ defers the client request only if it would otherwise be accepted. %PARAM unknown_helo_hostname_tempfail_action $reject_tempfail_action <p> The Postfix SMTP server's action when reject_unknown_helo_hostname -fails due to an temporary error condition. Specify "defer" to defer +fails due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request @@ -13989,7 +14193,7 @@ to the configured before/after 220 greeting tests. </dd> <pre> /etc/postfix/main.cf: postscreen_access_list = permit_mynetworks, - cidr:/etc/postfix/postscreen_access.cidr + cidr:/etc/postfix/postscreen_access.cidr postscreen_blacklist_action = enforce </pre> @@ -14658,7 +14862,8 @@ Postfix releases, the behavior is as if this parameter is set to "yes". </p> <p> As documented in aliases(5), when an alias <i>name</i> has a -companion alias named owner-<i>name</i>, delivery errors will be +companion alias named owner-<i>name</i>, this will replace the +envelope sender address, so that delivery errors will be reported to the owner alias instead of the sender. This configuration is recommended for mailing lists. <p> @@ -14688,7 +14893,9 @@ to other mailing list members. </p> <p> Unfortunately, older Postfix releases reset the owner-alias attribute when delivering mail to a child alias that does not have -its own owner alias. The local(8) delivery agent then attempts to +its own owner alias. To be precise, this resets only the decision +to create a new queue file, not the decision to override the envelope +sender address. The local(8) delivery agent then attempts to deliver local addresses as soon as they come out of child alias expansion. If delivery to any address from child alias expansion fails with a temporary error condition, the entire mailing list may @@ -14784,44 +14991,46 @@ you can only disable one of these via the hexadecimal syntax above. </p> <dl> -<dt><b>MICROSOFT_SESS_ID_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>CRYPTOPRO_TLSEXT_BUG</b></dt> <dd>New with GOST support in +OpenSSL 1.0.0.</dd> -<dt><b>NETSCAPE_CHALLENGE_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>DONT_INSERT_EMPTY_FRAGMENTS</b></dt> <dd>See +SSL_CTX_set_options(3)</dd> <dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3)</dd> -<dt><b>NETSCAPE_REUSE_CIPHER_CHANGE_BUG</b></dt> <dd> also aliased -as <b>CVE-2010-4180</b>. Postfix 2.8 disables this work-around by -default with OpenSSL versions that may predate the fix. Fixed in -OpenSSL 0.9.8q and OpenSSL 1.0.0c.</dd> - -<dt><b>SSLREF2_REUSE_CERT_TYPE_BUG</b></dt> <dd>See -SSL_CTX_set_options(3)</dd> - <dt><b>MICROSOFT_BIG_SSLV3_BUFFER</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>MICROSOFT_SESS_ID_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> + <dt><b>MSIE_SSLV2_RSA_PADDING</b></dt> <dd> also aliased as <b>CVE-2005-2969</b>. Postfix 2.8 disables this work-around by default with OpenSSL versions that may predate the fix. Fixed in OpenSSL 0.9.7h and OpenSSL 0.9.8a.</dd> +<dt><b>NETSCAPE_CHALLENGE_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> + +<dt><b>NETSCAPE_REUSE_CIPHER_CHANGE_BUG</b></dt> <dd> also aliased +as <b>CVE-2010-4180</b>. Postfix 2.8 disables this work-around by +default with OpenSSL versions that may predate the fix. Fixed in +OpenSSL 0.9.8q and OpenSSL 1.0.0c.</dd> + <dt><b>SSLEAY_080_CLIENT_DH_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> -<dt><b>TLS_D5_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>SSLREF2_REUSE_CERT_TYPE_BUG</b></dt> <dd>See +SSL_CTX_set_options(3)</dd> <dt><b>TLS_BLOCK_PADDING_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> +<dt><b>TLS_D5_BUG</b></dt> <dd>See SSL_CTX_set_options(3)</dd> + <dt><b>TLS_ROLLBACK_BUG</b></dt> <dd>See SSL_CTX_set_options(3). This is disabled in OpenSSL 0.9.7 and later. Nobody should still be using 0.9.6! </dd> -<dt><b>DONT_INSERT_EMPTY_FRAGMENTS</b></dt> <dd>See -SSL_CTX_set_options(3)</dd> - -<dt><b>CRYPTOPRO_TLSEXT_BUG</b></dt> <dd>New with GOST support in -OpenSSL 1.0.0.</dd> +<dt><b>TLSEXT_PADDING</b></dt><dd>Postfix ≥ 3.4. See SSL_CTX_set_options(3).</dd> </dl> @@ -14855,7 +15064,7 @@ cannot be set under 10s. </p> one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). </p> -<p> This feature is available in Postfix 2.8. </p> +<p> This feature is available in Postfix 2.8 and later </p> %PARAM postscreen_discard_ehlo_keywords $smtpd_discard_ehlo_keywords @@ -14953,7 +15162,9 @@ file. See smtpd_tls_ccert_verifydepth for further details. </p> <p> File with the Postfix tlsproxy(8) server RSA certificate in PEM format. This file may also contain the Postfix tlsproxy(8) server -private RSA key. See smtpd_tls_cert_file for further details. </p> +private RSA key. See smtpd_tls_cert_file for further details. With +Postfix ≥ 3.4 the preferred way to configure tlsproxy server keys and +certificates is via the "tlsproxy_tls_chain_files" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -14969,8 +15180,8 @@ for further details. </p> <p> File with the Postfix tlsproxy(8) server DSA certificate in PEM format. This file may also contain the Postfix tlsproxy(8) server -private DSA key. See smtpd_tls_dcert_file for further details. -</p> +private DSA key. DSA is obsolete and should not be used. See +smtpd_tls_dcert_file for further details. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -14995,27 +15206,31 @@ result export-grade cipher suites are by default not used. </p> %PARAM tlsproxy_tls_dkey_file $smtpd_tls_dkey_file <p> File with the Postfix tlsproxy(8) server DSA private key in PEM -format. This file may be combined with the Postfix tlsproxy(8) -server DSA certificate file specified with $smtpd_tls_dcert_file. -See smtpd_tls_dkey_file for further details. </p> +format. This file may be combined with the Postfix tlsproxy(8) server +DSA certificate file specified with $smtpd_tls_dcert_file. DSA is +obsolete and should not be used. See smtpd_tls_dkey_file for further +details. </p> <p> This feature is available in Postfix 2.8 and later. </p> %PARAM tlsproxy_tls_eccert_file $smtpd_tls_eccert_file -<p> File with the Postfix tlsproxy(8) server ECDSA certificate in -PEM format. This file may also contain the Postfix tlsproxy(8) -server private ECDSA key. See smtpd_tls_eccert_file for further -details. </p> +<p> File with the Postfix tlsproxy(8) server ECDSA certificate in PEM +format. This file may also contain the Postfix tlsproxy(8) server +private ECDSA key. See smtpd_tls_eccert_file for further details. With +Postfix ≥ 3.4 the preferred way to configure tlsproxy server keys and +certificates is via the "tlsproxy_tls_chain_files" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> %PARAM tlsproxy_tls_eckey_file $smtpd_tls_eckey_file -<p> File with the Postfix tlsproxy(8) server ECDSA private key in -PEM format. This file may be combined with the Postfix tlsproxy(8) -server ECDSA certificate file specified with $smtpd_tls_eccert_file. -See smtpd_tls_eckey_file for further details. </p> +<p> File with the Postfix tlsproxy(8) server ECDSA private key in PEM +format. This file may be combined with the Postfix tlsproxy(8) server +ECDSA certificate file specified with $smtpd_tls_eccert_file. See +smtpd_tls_eckey_file for further details. With Postfix ≥ 3.4 the +preferred way to configure tlsproxy server keys and certificates is via +the "tlsproxy_tls_chain_files" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -15047,9 +15262,11 @@ fingerprints. See smtpd_tls_fingerprint_digest for further details. %PARAM tlsproxy_tls_key_file $smtpd_tls_key_file <p> File with the Postfix tlsproxy(8) server RSA private key in PEM -format. This file may be combined with the Postfix tlsproxy(8) -server RSA certificate file specified with $smtpd_tls_cert_file. -See smtpd_tls_key_file for further details. </p> +format. This file may be combined with the Postfix tlsproxy(8) server +RSA certificate file specified with $smtpd_tls_cert_file. See +smtpd_tls_key_file for further details. With Postfix ≥ 3.4 the +preferred way to configure tlsproxy server keys and certificates is via +the "tlsproxy_tls_chain_files" parameter. </p> <p> This feature is available in Postfix 2.8 and later. </p> @@ -15167,9 +15384,15 @@ be truncated before it is logged to the remote SMTP client's maillog file, or before it is returned to the sender in a delivery status notification. </p> -<p> This feature supports a limited number of $name attributes in -the footer text. These are replaced by their current value for the -SMTP session: </p> +<p> The template text is not subject to Postfix configuration +parameter $name expansion. Instead, this feature supports a limited +number of $name attributes in the footer text. These attributes are +replaced with their current value for the SMTP session. </p> + +<p> Note: specify $$name in footer text that is looked up from +regexp: or pcre:-based smtpd_reject_footer_maps, otherwise the +Postfix server will not use the footer text and will log a warning +instead. </p> <dl> @@ -15214,6 +15437,20 @@ text (Postfix 2.10 and later). </p> <p> This feature is available in Postfix 2.8 and later. </p> +%PARAM smtpd_reject_footer_maps + +<p> Lookup tables, indexed by the complete Postfix SMTP server 4xx or +5xx response, with reject footer templates. See smtpd_reject_footer +for details. </p> + +<p> +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. +</p> + +<p> This feature is available in Postfix 3.4 and later. </p> + %PARAM postscreen_expansion_filter see "postconf -d" output <p> List of characters that are permitted in postscreen_reject_footer @@ -15230,6 +15467,14 @@ response. See smtpd_reject_footer for further details. </p> <p> This feature is available in Postfix 2.8 and later. </p> +%PARAM postscreen_reject_footer_maps $smtpd_reject_footer_maps + +<p> Optional lookup table for information that is appended after a 4XX +or 5XX postscreen(8) server response. See smtpd_reject_footer_maps for +further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + %PARAM postscreen_command_filter $smtpd_command_filter <p> A mechanism to transform commands from remote SMTP clients. @@ -15351,7 +15596,7 @@ pattern. </p> proxy agent. When a proxy agent is used, this protocol conveys local and remote address and port information. Specify "postscreen_upstream_proxy_protocol = haproxy" to enable the haproxy -protocol. <p> +protocol; version 2 is supported with Postfix 3.5 and later. <p> <p> This feature is available in Postfix 2.10 and later. </p> @@ -15368,7 +15613,7 @@ postscreen_upstream_proxy_protocol parameter. </p> proxy agent. When a proxy agent is used, this protocol conveys local and remote address and port information. Specify "smtpd_upstream_proxy_protocol = haproxy" to enable the haproxy -protocol. </p> +protocol; version 2 is supported with Postfix 3.5 and later. </p> <p> NOTE: To use the nginx proxy with smtpd(8), enable the XCLIENT protocol with smtpd_authorized_xclient_hosts. This supports SASL @@ -15702,7 +15947,7 @@ itself is not configured to use DNSSEC. </p> <p> When using Postfix DANE support the "smtp_host_lookup" parameter should include "dns", as <a -href="https://tools.ietf.org/html/rfc6698">DANE</a> is not applicable +href="https://tools.ietf.org/html/rfc7672">DANE</a> is not applicable to hosts resolved via "native" lookups. </p> <p> As mentioned above, Postfix is not a validating <a @@ -15760,9 +16005,9 @@ trust-anchor files are used at all, they will be specified on a per-destination basis via the "tafile" attribute of the "verify" and "secure" levels in smtp_tls_policy_maps. </p> -<p> The underlying mechanism is in support of RFC 6698 (DANE TLSA), -which defines mechanisms for a client to securely determine server -TLS certificates via DNS. </p> +<p> The underlying mechanism is in support of RFC 7672 (DANE TLSA), +which defines mechanisms for an SMTP client MTA to securely determine +server TLS certificates via DNS. </p> <p> If you want your trust anchors to be public keys, with OpenSSL you can extract a single PEM public key from a PEM X.509 file @@ -15785,31 +16030,15 @@ configuration parameter. See there for details. </p> %PARAM tls_dane_trust_anchor_digest_enable yes -<p> RFC 6698 trust-anchor digest support in the Postfix TLS library. -Enable support for RFC 6698 (DANE TLSA) DNS records that contain -digests of trust-anchors with certificate usage "2". In this case -the certificate usage logically requires the server administrator -to configure the server to include the trust-anchor certificate in -the server's SSL certificate chain. If enough domains mess this -up, you can disable support for these TLSA records, but you'll no -longer have secure connections that get it right and only publish -trust anchor records. </p> - -<p> At the <a href="TLS_README.html#client_tls_dane">dane</a> -security level, when a TLSA RRset includes only unusable associations, -the Postfix SMTP client will automatically switch the connection -to the <a href="TLS_README.html#client_tls_encrypt">encrypt</a> -security level. At the <a -href="TLS_README.html#client_tls_dane">dane-only</a> security level, -the server in question is skipped and delivery is deferred if no -secure servers are found. </p> - -<p> The tls_dane_digests parameter controls the list of digest -algorithms that are supported in TLSA records. The tls_dane_digest_agility -parameter controls digest algorithm downgrade attack resistance. -</p> +<p> Enable support for RFC 6698 (DANE TLSA) DNS records that contain +digests of trust-anchors with certificate usage "2". Do not change +this setting from its default value. </p> -<p> This feature is available in Postfix 2.11 and later. </p> +<p> This feature is available in Postfix 2.11 through 3.1. It has +been withdrawn in Postfix 3.2, as trust-anchor TLSA records are now +widely used and have proved sufficiently reliable. Postfix 3.2 and +later ignore this configuration parameter and behaves as though it +were set to "yes". </p> %PARAM tls_wildcard_matches_multiple_labels yes @@ -15890,18 +16119,36 @@ in its value are enabled (see openssl/ssl.h and SSL_CTX_set_options(3)). You can only enable options not already controlled by other Postfix settings. For example, you cannot disable protocols or enable server cipher preference. Do not attempt to turn all features by -specifying 0xFFFFFFFF, this is unlikely to be a good idea. </p> +specifying 0xFFFFFFFF, this is unlikely to be a good idea. Some +bug work-arounds are also valid here, allowing them to be re-enabled +if/when they're no longer enabled by default. The supported values +include: </p> <dl> +<dt><b>ENABLE_MIDDLEBOX_COMPAT</b></dt> <dd>Postfix ≥ 3.4. See +SSL_CTX_set_options(3).</dd> + <dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3).</dd> -<dt><b>NO_TICKET</b></dt> <dd>See SSL_CTX_set_options(3).</dd> +<dt><b>NO_TICKET</b></dt> <dd>Enabled by default when needed in +fully-patched Postfix ≥ 2.7. Not needed at all for Postfix ≥ +2.11, unless for some reason you do not want to support TLS session +resumption. Best not set explicitly. See SSL_CTX_set_options(3).</dd> <dt><b>NO_COMPRESSION</b></dt> <dd>Disable SSL compression even if supported by the OpenSSL library. Compression is CPU-intensive, and compression before encryption does not always improve security. </dd> +<dt><b>NO_RENEGOTIATION</b></dt> <dd>Postfix ≥ 3.4. This can +reduce opportunities for a potential CPU exhaustion attack. See +SSL_CTX_set_options(3).</dd> + +<dt><b>NO_SESSION_RESUMPTION_ON_RENEGOTIATION</b></dt> <dd>Postfix +≥ 3.4. See SSL_CTX_set_options(3).</dd> + +<dt><b>PRIORITIZE_CHACHA</b></dt> <dd>Postfix ≥ 3.4. See SSL_CTX_set_options(3).</dd> + </dl> <p> This feature is available in Postfix 2.11 and later. </p> @@ -15958,70 +16205,22 @@ are not prepared to handle the new TLSA RRset. </p> %PARAM tls_dane_digest_agility on -<p> Configure DANE TLSA digest algorithm agility. When digest -algorithm agility is enabled, and the server and client support a -common strong digest algorithm, TLSA records with weaker digest -algorithms are ignored. </p> - -<p> Specify one of the following: </p> +<p> Configure RFC7671 DANE TLSA digest algorithm agility. +Do not change this setting from its default value. </p> -<dl> - -<dt><b>off</b></dt> -<dd> DANE verification examines each well-formed record in the TLSA -RRset whose matching type is either "0" (no hash used) or is one of -the digest algorithms listed in $tls_dane_digests. This setting -is not recommended. </dd> - -<dt><b>on</b></dt> -<dd> From each group of well-formed TLSA RRs a non-zero digest -matching type with the same certificate usage and selector, DANE -verification examines only those records whose matching type has -the highest precedence (appear earliest in $tls_dane_digests). -</dd> +<p> See Section 8 of RFC7671 for correct key rotation procedures. </p> -<dt><b>maybe</b></dt> -<dd> For compatibility with digest algorithm agility, each certificate -or public key whose digest is included in a DANE TLSA RRset, SHOULD -be published with the same set of digest matching type values as -any other with the same usage and selector. Therefore, compatible -TLSA RRsets will contain an identical count of well-formed RRs with -each non-zero digest matching type for any fixed combination of -usage and selector. When this constraint is violated, or any of -the digest records are malformed, digest algorithm agility will -disabled. Otherwise, digest algorithm agility is enabled. </dd> - -</dl> - -<p> Digest algorithm agility ensures that the strongest digest -supported by both the Postfix SMTP client and the remote server is -used, and weaker digests are ignored. This supports non-disruptive -deprecation of outdated digest algorithms. </p> - -<p> To ensure compatibility with digest algorithm agility during -key rotation, when a certificate or public key is being replaced -with another, and both are published during the transition, both -the old and the new certificate MUST be specified with the same set -of digests. One can change the list of digest algorithms later, -once old keys are retired. At any given time, change either the -list of digests without changing the list of certificates or public -keys or the list of certificates or public keys without changing -the list of digests. Full value matching type "0" records are not -subject to this constraint, but are discouraged due to the size of -the resulting DNS records. </p> - -<p> It is expected that this algorithm agility mechanism will be -published in a standards track RFC for SMTP with DANE, and also in -an eventual update to RFC 6698. </p> - -<p> This feature is available in Postfix 2.11 and later. </p> +<p> This feature is available in Postfix 2.11 through 3.1. Postfix +3.2 and later ignore this configuration parameter and behave as +though it were set to "on". </p> %PARAM tls_dane_digests sha512 sha256 -<p> RFC 6698 TLSA resource-record "matching type" digest algorithms -in descending preference order. All the specified algorithms must -be supported by the underlying OpenSSL library, otherwise the Postfix -SMTP client will not support DANE TLSA security. </p> +<p> DANE TLSA (RFC 6698, RFC 7671, RFC 7672) resource-record "matching +type" digest algorithms in descending preference order. All the +specified algorithms must be supported by the underlying OpenSSL +library, otherwise the Postfix SMTP client will not support DANE +TLSA security. </p> <p> Specify a list of digest names separated by commas and/or whitespace. Each digest name may be followed by an optional @@ -16046,16 +16245,6 @@ seriously compromised and servers have had ample time to update their TLSA records you should not omit any standard digests, just arrange them in order from strongest to weakest. </p> -<p> When for a particular combination of "certificate usage" and -"selector" the TLSA RRset contains records with more than one digest -matching type, the tls_dane_digest_agility parameter determines -whether all the RRs are used, or only those with the most preferred -digest matching type. </p> - -<p> The tls_dane_trust_anchor_digest_enable parameter controls -whether any digest TLSA records are acceptable in usage "2" (trust -anchor assertion) TLSA records. </p> - <p> This feature is available in Postfix 2.11 and later. </p> %PARAM tls_session_ticket_cipher Postfix ≥ 3.0: aes-256-cbc, Postfix < 3.0: aes-128-cbc @@ -16072,6 +16261,14 @@ support is via the tls_ssl_options parameter. </p> <p> This feature is available in Postfix 3.0 and later. </p> +%PARAM tls_fast_shutdown_enable yes + +<p> A workaround for implementations that hang Postfix while shutting +down a TLS session, until Postfix times out. With this enabled, +Postfix will not wait for the remote TLS peer to respond to a TLS +'close' notification. This behavior is recommended for TLSv1.0 and +later. </p> + %PARAM default_delivery_status_filter <p> Optional filter to replace the delivery status code or explanatory @@ -16079,6 +16276,12 @@ text of successful or unsuccessful deliveries. This does not allow the replacement of a successful status code (2.X.X) with an unsuccessful status code (4.X.X or 5.X.X) or vice versa. </p> +<p> Note: the (smtp|lmtp)_delivery_status_filter is applied only +once per recipient: when delivery is successful, when delivery is +rejected with 5XX, or when there are no more alternate MX or A +destinations. Use smtp_reply_filter or lmtp_reply_filter to inspect +responses for all delivery attempts. </p> + <p> The following parameters can be used to implement a filter for specific delivery agents: lmtp_delivery_status_filter, local_delivery_status_filter, pipe_delivery_status_filter, @@ -16557,6 +16760,25 @@ Postfix versions. </p> <p> This feature is available in Postfix 3.0 and later. </p> +%PARAM smtp_tls_connection_reuse no + +<p> Try to make multiple deliveries per TLS-encrypted connection. +This uses the tlsproxy(8) service to encrypt an SMTP connection, +uses the scache(8) service to save that connection, and relies on +hints from the qmgr(8) daemon. </p> + +<p> See "<a href="TLS_README.html#client_tls_reuse">Client-side +TLS connection reuse</a>" for background details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM lmtp_tls_connection_reuse no + +<p> The LMTP-specific version of the smtp_tls_connection_reuse configuration +parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + %PARAM virtual_alias_address_length_limit 1000 <p> @@ -16667,3 +16889,812 @@ the verify(8) daemon automatically refreshes an active address before it expires. </p> <p> This feature is available in Postfix 3.1 and later. </p> + +%PARAM smtpd_milter_maps + +<p> Lookup tables with Milter settings per remote SMTP client IP +address. The lookup result overrides the smtpd_milters setting, +and has the same syntax. </p> + +<p> Note: lookup tables cannot return empty responses. Specify a +lookup result of DISABLE (case does not matter) to indicate that +Milter support should be disabled. </p> + +<p> Example to disable Milters for local clients: </p> + +<pre> +/etc/postfix/main.cf: + smtpd_milter_maps = cidr:/etc/postfix/smtpd_milter_map + smtpd_milters = inet:host:port, { inet:host:port, ... }, ... +</pre> + +<pre> +/etc/postfix/smtpd_milter_map: + # Disable Milters for local clients. + 127.0.0.0/8 DISABLE + 192.168.0.0/16 DISABLE + ::/64 DISABLE + 2001:db8::/32 DISABLE +</pre> + +<p> This feature is available in Postfix 3.2 and later. </p> + +%PARAM enable_idna2003_compatibility no + +<p> Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +when converting UTF-8 domain names to/from the ASCII form that is +used for DNS lookups. Specify "yes" for compatibility with Postfix +≤ 3.1 (not recommended). This affects the conversion of domain +names that contain for example the German sz and the Greek zeta. +See http://unicode.org/cldr/utility/idna.jsp for more examples. +</p> + +<p> This feature is available in Postfix 3.2 and later. </p> + +%PARAM smtp_balance_inet_protocols yes + +<p> 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. </p> + +<p> This avoids an interoperability problem when a destination resolves +to primarily IPv6 addresses, the smtp_address_limit feature eliminates +most or all IPv4 addresses, and the destination is not reachable over +IPv6. </p> + +<p> This feature is available in Postfix 3.3 and later. </p> + +%PARAM lmtp_balance_inet_protocols yes + +<p> The LMTP-specific version of the smtp_balance_inet_protocols +configuration parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.3 and later. </p> + +%PARAM header_from_format standard + +<p> The format of the Postfix-generated <b>From:</b> header. This +setting affects the appearance of 'full name' information when a +local program such as /bin/mail submits a message without From: +header through the Postfix sendmail(1) command. </p> + +<p> Specify one of the following: </p> + +<dl> + +<dt><b>standard</b> (default)</dt> <dd> Produce a header formatted +as "<b>From:</b> <i>name</i><b> <</b><i>address</i><b>></b>". +This is the default as of Postfix 3.3.</dd> + +<dt><b>obsolete</b></dt> <dd>Produce a header formatted as "<b>From:</b> +<i>address</i> <b>(</b><i>name</i><b>)</b>". This is the behavior +prior to Postfix 3.3. </dd> + +</dl> + +<p> Notes: </p> + +<ul> + +<li> <p> Postfix generates the format "<b>From:</b> <i>address</i>" +when <i>name</i> information is unavailable or the envelope sender +address is empty. This is the same behavior as prior to Postfix +3.3. </p> + +<li> <p> In the <b>standard</b> form, the <i>name</i> will be quoted +if it contains <b>specials</b> as defined in RFC 5322, or the "!%" +address operators. </p> + +<li> <p> The Postfix sendmail(1) command gets <i>name</i> information +from the <b>-F</b> command-line option, from the <b>NAME</b> +environment variable, or from the UNIX password file. </p> + +</ul> + +<p> This feature is available in Postfix 3.3 and later. </p> + +%PARAM tlsproxy_client_CAfile $smtp_tls_CAfile + +<p> A file containing CA certificates of root CAs trusted to sign +either remote TLS server certificates or intermediate CA certificates. +See smtp_tls_CAfile for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_CApath $smtp_tls_CApath + +<p> Directory with PEM format Certification Authority certificates +that the Postfix tlsproxy(8) client uses to verify a remote TLS +server certificate. See smtp_tls_CApath for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_cert_file $smtp_tls_cert_file + +<p> File with the Postfix tlsproxy(8) client RSA certificate in PEM +format. See smtp_tls_cert_file for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_key_file $smtp_tls_key_file + +<p> File with the Postfix tlsproxy(8) client RSA private key in PEM +format. See smtp_tls_key_file for further details. The preferred way to +configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_dcert_file $smtp_tls_dcert_file + +<p> File with the Postfix tlsproxy(8) client DSA certificate in PEM +format. See smtp_tls_dcert_file for further details. DSA is obsolete and +should not be used. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_dkey_file $smtp_tls_dkey_file + +<p> File with the Postfix tlsproxy(8) client DSA private key in PEM +format. See smtp_tls_dkey_file for further details. DSA is obsolete and +should not be used. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_eccert_file $smtp_tls_eccert_file + +<p> File with the Postfix tlsproxy(8) client ECDSA certificate in PEM +format. See smtp_tls_eccert_file for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_eckey_file $smtp_tls_eckey_file + +<p> File with the Postfix tlsproxy(8) client ECDSA private key in PEM +format. See smtp_tls_eckey_file for further details. The preferred way +to configure tlsproxy client keys and certificates is via the +"tlsproxy_client_chain_files" parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_fingerprint_digest $smtp_tls_fingerprint_digest + +<p> The message digest algorithm used to construct remote TLS server +certificate fingerprints. See smtp_tls_fingerprint_digest for +further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_loglevel $smtp_tls_loglevel + +<p> Enable additional Postfix tlsproxy(8) client logging of TLS +activity. See smtp_tls_loglevel for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_loglevel_parameter smtp_tls_loglevel + +<p> The name of the parameter that provides the tlsproxy_client_loglevel +value. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_scert_verifydepth $smtp_tls_scert_verifydepth + +<p> The verification depth for remote TLS server certificates. +See smtp_tls_scert_verifydepth for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_security_level $smtp_tls_security_level + +<p> The default TLS security level for the Postfix tlsproxy(8) +client. See smtp_tls_security_level for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_per_site $smtp_tls_per_site + +<p> Optional lookup tables with the Postfix tlsproxy(8) client TLS +usage policy by next-hop destination and by remote TLS server +hostname. See smtp_tls_per_site for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_policy_maps $smtp_tls_policy_maps + +<p> Optional lookup tables with the Postfix tlsproxy(8) client TLS +security policy by next-hop destination. See smtp_tls_policy_maps +for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_use_tls $smtp_use_tls + +<p> Opportunistic mode: use TLS when a remote server announces TLS +support. See smtp_use_tls for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_enforce_tls $smtp_enforce_tls + +<p> Enforcement mode: require that SMTP servers use TLS encryption. +See smtp_enforce_tls for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM smtpd_tls_chain_files + +<p> List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. The file names +are separated by commas and/or whitespace. This parameter obsoletes the +legacy algorithm-specific key and certificate file settings. When this +parameter is non-empty, the legacy parameters are ignored, and a warning +is logged if any are also non-empty. </p> + +<p> With the proliferation of multiple private key algorithms—which, +as of OpenSSL 1.1.1, include DSA (obsolete), RSA, ECDSA, Ed25519 +and Ed448—it is increasingly impractical to use separate +parameters to configure the key and certificate chain for each +algorithm. Therefore, Postfix now supports storing multiple keys and +corresponding certificate chains in a single file or in a set of files. + +<p> Each key must appear <b>immediately before</b> the corresponding +certificate, optionally followed by additional issuer certificates that +complete the certificate chain for that key. When multiple files are +specified, they are equivalent to a single file that is concatenated +from those files in the given order. Thus, while a key must always +precede its certificate and issuer chain, it can be in a separate file, +so long as that file is listed immediately before the file that holds +the corresponding certificate chain. Once all the files are +concatenated, the sequence of PEM objects must be: <i>key1, cert1, +[chain1], key2, cert2, [chain2], ..., keyN, certN, [chainN].</i> </p> + +<p> Storing the private key in the same file as the corresponding +certificate is more reliable. With the key and certificate in separate +files, there is a chance that during key rollover a Postfix process +might load a private key and certificate from separate files that don't +match. Various operational errors may even result in a persistent +broken configuration in which the certificate does not match the private +key. </p> + +<p> The file or files must contain at most one key of each type. If, +for example, two or more RSA keys and corresponding chains are listed, +depending on the version of OpenSSL either only the last one will be +used or an configuration error may be detected. Note that while +"Ed25519" and "Ed448" are considered separate algorithms, the various +ECDSA curves (typically one of prime256v1, secp384r1 or secp521r1) are +considered as different parameters of a single "ECDSA" algorithm, so it +is not presently possible to configure keys for more than one ECDSA +curve. </p> + +<p> RSA is still the most widely supported algorithm. Presently (late +2018), ECDSA support is common, but not yet universal, and Ed25519 and +Ed448 support is mostly absent. Therefore, an RSA key should generally +be configured, along with any additional keys for the other algorithms +when desired. </p> + +<p> +Example (separate files for each key and corresponding certificate chain): +</p> +<blockquote> +<pre> +/etc/postfix/main.cf: + smtpd_tls_chain_files = + ${config_directory}/ed25519.pem, + ${config_directory}/ed448.pem, + ${config_directory}/rsa.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed25519.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed448.pem: + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/rsa.pem: + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> +Example (all keys and certificates in a single file): +</p> +<blockquote> +<pre> +/etc/postfix/main.cf: + smtpd_tls_chain_files = ${config_directory}/chains.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/chains.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM smtp_tls_chain_files + +<p> List of one or more PEM files, each holding one or more private keys +directly followed by a corresponding certificate chain. The file names +are separated by commas and/or whitespace. This parameter obsoletes the +legacy algorithm-specific key and certificate file settings. When this +parameter is non-empty, the legacy parameters are ignored, and a warning +is logged if any are also non-empty. </p> + +<p> With the proliferation of multiple private key algorithms—which, +as of OpenSSL 1.1.1, include DSA (obsolete), RSA, ECDSA, Ed25519 +and Ed448—it is increasingly impractical to use separate +parameters to configure the key and certificate chain for each +algorithm. Therefore, Postfix now supports storing multiple keys and +corresponding certificate chains in a single file or in a set of files. + +<p> Each key must appear <b>immediately before</b> the corresponding +certificate, optionally followed by additional issuer certificates that +complete the certificate chain for that key. When multiple files are +specified, they are equivalent to a single file that is concatenated +from those files in the given order. Thus, while a key must always +precede its certificate and issuer chain, it can be in a separate file, +so long as that file is listed immediately before the file that holds +the corresponding certificate chain. Once all the files are +concatenated, the sequence of PEM objects must be: <i>key1, cert1, +[chain1], key2, cert2, [chain2], ..., keyN, certN, [chainN].</i> </p> + +<p> Storing the private key in the same file as the corresponding +certificate is more reliable. With the key and certificate in separate +files, there is a chance that during key rollover a Postfix process +might load a private key and certificate from separate files that don't +match. Various operational errors may even result in a persistent +broken configuration in which the certificate does not match the private +key. </p> + +<p> The file or files must contain at most one key of each type. If, +for example, two or more RSA keys and corresponding chains are listed, +depending on the version of OpenSSL either only the last one will be +used or an configuration error may be detected. Note that while +"Ed25519" and "Ed448" are considered separate algorithms, the various +ECDSA curves (typically one of prime256v1, secp384r1 or secp521r1) are +considered as different parameters of a single "ECDSA" algorithm, so it +is not presently possible to configure keys for more than one ECDSA +curve. </p> + +<p> +Example (separate files for each key and corresponding certificate chain): +</p> +<blockquote> +<pre> +/etc/postfix/main.cf: + smtp_tls_chain_files = + ${config_directory}/ed25519.pem, + ${config_directory}/ed448.pem, + ${config_directory}/rsa.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed25519.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/ed448.pem: + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/rsa.pem: + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> +Example (all keys and certificates in a single file): +</p> +<blockquote> +<pre> +/etc/postfix/main.cf: + smtp_tls_chain_files = ${config_directory}/chains.pem +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/chains.pem: + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEJfbbO4BgBQGBg9NAbIJaDBqZb4bC4cOkjtAH+Efbz3 + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBKzCB3qADAgECAhQaw+rflRreYuUZBp0HuNn/e5rMZDAFBgMrZXAwFDESMBAG + ... + nC0egv51YPDWxEHom4QA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MEcCAQAwBQYDK2VxBDsEOQf+m0P+G0qi+NZ0RolyeiE5zdlPQR8h8y4jByBifpIe + LNler7nzHQJ1SLcOiXFHXlxp/84VZuh32A== + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIBdjCB96ADAgECAhQSv4oP972KypOZPNPF4fmsiQoRHzAFBgMrZXEwFDESMBAG + ... + pQcWsx+4J29e6YWH3Cy/CdUaexKP4RPCZDrPX7bk5C2BQ+eeYOxyThMA + -----END CERTIFICATE----- + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc4QusgkahH9rL + ... + ahQkZ3+krcaJvDSMgvu0tDc= + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIC+DCCAeCgAwIBAgIUIUkrbk1GAemPCT8i9wKsTGDH7HswDQYJKoZIhvcNAQEL + ... + Rirz15HGVNTK8wzFd+nulPzwUo6dH2IU8KazmyRi7OGvpyrMlm15TRE2oyE= + -----END CERTIFICATE----- +</pre> +</blockquote> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM lmtp_tls_chain_files + +<p> The LMTP-specific version of the smtp_tls_chain_files configuration +parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_client_chain_files $smtp_tls_chain_files + +<p> Files with the Postfix tlsproxy(8) client keys and certificate +chains in PEM format. See smtp_tls_chain_files for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tlsproxy_tls_chain_files $smtpd_tls_chain_files + +<p> Files with the Postfix tlsproxy(8) server keys and certificate +chains in PEM format. See smtpd_tls_chain_files for further details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM tls_server_sni_maps + +<p> Optional lookup tables that map names received from remote SMTP +clients via the TLS Server Name Indication (SNI) extension to the +appropriate keys and certificate chains. This parameter is implemented +in the Postfix TLS library, and applies to both smtpd(8) and the SMTP +server mode of tlsproxy(8). </p> + +<p> When this parameter is non-empty, the Postfix SMTP server enables +SNI extension processing, and logs SNI values that are invalid or +don't match an entry in the the specified tables. When an entry +does match, the SNI name is logged as part of the connection summary +at log levels 1 and higher. </p> + +<p> The lookup key is either the verbatim SNI domain name or an +ancestor domain prefixed with a leading dot. For internationalized +domains, the lookup key must be in IDNA 2008 A-label form (as +required in the TLS SNI extension). </p> + +<p> The syntax of the lookup value is the same as with the +smtp_tls_chain_files parameter (see there for additional details), +but here scoped to just TLS connections in which the client sends +a matching SNI domain name. </p> + +<p> Example: </p> +<blockquote> +<pre> +/etc/postfix/main.cf: + # + # The indexed SNI table must be created with "postmap -F" + # + indexed = ${default_database_type}:${config_directory}/ + tls_server_sni_maps = ${indexed}sni +</pre> +</blockquote> + +<blockquote> +<pre> +/etc/postfix/sni: + # + # The example.com domain has both an RSA and ECDSA certificate + # chain. The chain files MUST start with the private key, + # with the certificate chain next, starting with the leaf + # (server) certificate, and then the issuer certificates. + # + example.com /etc/postfix/sni-chains/rsa2048.example.com.pem, + /etc/postfix/sni-chains/ecdsa-p256.example.com.pem + # + # The example.net domain has a wildcard certificate, and two + # additional DNS names. So its certificate chain is also used + # with any subdomain, plus the additional names. + # + example.net /etc/postfix/sni-chains/example.net.pem + .example.net /etc/postfix/sni-chains/example.net.pem + example.info /etc/postfix/sni-chains/example.net.pem + example.org /etc/postfix/sni-chains/example.net.pem +</pre> +</blockquote> + +<p> Note that the SNI lookup tables should also have entries for +the domains that correspond to the Postfix SMTP server's default +certificate(s). This ensures that the remote SMTP client's TLS SNI +extension gets a positive response when it specifies one of the +Postfix SMTP server's default domains, and ensures that the Postfix +SMTP server will not log an SNI name mismatch for such a domain. +The Postfix SMTP server's default certificates are then only used +when the client sends no SNI or when it sends SNI with a domain +that the server knows no certificate(s) for. </p> + +<p> The mapping from an SNI domain name to a certificate chain is indirect. In +the input source files for "cdb", "hash", "btree" or other tables that are +converted to on-disk indexed files via postmap(1), the value specified for each +key is a list of filenames. When postmap(1) is used with the <b>-F</b> option, +the generated table stores for each lookup key the base64-encoded contents of +the associated files. When querying tables via <b>postmap -Fq</b>, the table +value is decoded from base64, yielding the original file content, plus a new +line. </p> + +<p> With "regexp", "pcre", "inline", "texthash", "static" and similar +tables that are interpreted at run-time, and don't have a separate +source format, the table value is again a list files, that are loaded +into memory when the table is opened. </p> + +<p> With tables whose content is managed outside of Postfix, such +as LDAP, MySQL, PostgreSQL, socketmap and tcp, the value must be a +concatenation of the desired PEM keys and certificate chains, that +is then further encoded to yield a single-line base64 string. +Creation of such tables and secure storage (the value includes +private key material) are outside the responsibility of Postfix. </p> + +<p> With "socketmap" and "tcp" the data will be transmitted in the clear, and +there is no query access control, so these are generally unsuitable for storing +SNI chains. With LDAP and SQL, you should restrict read access and use TLS to +protect the sensitive data in transit. </p> + +<p> Typically there is only one private key and its chain of certificates +starting with the "leaf" certificate corresponding to that key, and +continuing with the appropriate intermediate issuer CA certificates, +with each certificate ideally followed by its issuer. Servers +that have keys and certificates for more than one algorithm (e.g. +both an RSA key and an ECDSA key, or even RSA, ECDSA and Ed25519) +can use multiple chains concatenated together, with the key always +listed before the corresponding certificates. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM smtp_tls_servername + +<p> Optional name to send to the remote SMTP server in the TLS Server +Name Indication (SNI) extension. The SNI extension is always on when +DANE is used to authenticate the server, and in that case the SNI name +sent is the one required by RFC7672 and this parameter is ignored. </p> + +<p> Some SMTP servers use the received SNI name to select an appropriate +certificate chain to present to the client. While this may improve +interoperability with such servers, it may reduce interoperability with +other servers that choose to abort the connection when they don't have a +certificate chain configured for the requested name. Such servers +should select a default certificate chain and continue the handshake, +but some may not. Therefore, absent DANE, no SNI name is sent by +default. </p> + +<p> The SNI name must be either a valid DNS hostname, or else one of the +special values <b>hostname</b> or <b>nexthop</b>, which select either the +remote hostname or the nexthop domain respectively. DNS names for SNI must be +in A-label (punycode) form. Invalid DNS names log a configuration error +warning and mail delivery is deferred. </p> + +<p> Except when using a relayhost to forward all email, the only +sensible non-empty main.cf setting for this parameter is +<b>hostname</b>. Other non-empty values are only practical on a +per-destination basis via the <b>servername</b> attribute of the Postfix +TLS <a href="TLS_README.html#client_tls_policy">policy table</a>. When +in doubt, leave this parameter empty, and configure per-destination SNI +as needed. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM lmtp_tls_servername + +<p> The LMTP-specific version of the smtp_tls_servername configuration +parameter. See there for details. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM maillog_file + +<p> The name of an optional logfile that is written by the Postfix +postlogd(8) service. An empty value selects logging to syslogd(8). +Specify "/dev/stdout" to select logging to standard output. Stdout +logging requires that Postfix is started with "postfix start-fg". +</p> + +<p> Note 1: The maillog_file parameter value must contain a prefix +that is specified with the maillog_file_prefixes parameter. </p> + +<p> Note 2: Some Postfix non-daemon programs may still log information +to syslogd(8), before they have processed their configuration +parameters and command-line options. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM postlog_service_name postlog + +<p> The name of the postlogd(8) service entry in master.cf. +This service appends logfile records to the file specified +with the maillog_file parameter. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM postlogd_watchdog_timeout 10s + +<p> How much time a postlogd(8) process may take to process a request +before it is terminated by a built-in watchdog timer. This is a +safety mechanism that prevents postlogd(8) from becoming non-responsive +due to a bug in Postfix itself or in system software. This limit +cannot be set under 10s. </p> + +<p> Specify a non-zero time value (an integral value plus an optional +one-letter suffix that specifies the time unit). Time units: s +(seconds), m (minutes), h (hours), d (days), w (weeks). </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM maillog_file_prefixes /var, /dev/stdout + +<p> A list of allowed prefixes for a maillog_file value. This is a +safety feature to contain the damage from a single configuration +mistake. Specify one or more prefix strings, separated by comma or +whitespace. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM maillog_file_compressor gzip + +<p> The program to run after rotating $maillog_file with "postfix +logrotate". The command is run with the rotated logfile name as its +first argument. </p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM maillog_file_rotate_suffix %Y%M%d-%H%M%S + +<p> The format of the suffix to append to $maillog_file while rotating +the file with "postfix logrotate". See strftime(3) for syntax. The +default suffix, YYYYMMDD-HHMMSS, allows logs to be rotated frequently. +</p> + +<p> This feature is available in Postfix 3.4 and later. </p> + +%PARAM info_log_address_format external + +<p> The email address form that will be used in non-debug logging +(info, warning, etc.). As of Postfix 3.5 when an address localpart +contains spaces or other special characters, the localpart will be +quoted, for example: </p> + +<blockquote> +<pre> + from=<"name with spaces"@example.com> +</pre> +</blockquote> + +<p> Older Postfix versions would log the internal (unquoted) form: </p> + +<blockquote> +<pre> + from=<name with spaces@example.com> +</pre> +</blockquote> + +<p> The external and internal forms are identical for the vast +majority of email addresses that contain no spaces or other special +characters in the localpart. </p> + +<p> The logging in external form is consistent with the address +form that Postfix 3.2 and later prefer for most table lookups. This +is therefore the more useful form for non-debug logging. </p> + +<p> Specify "<b>info_log_address_format = internal</b>" for backwards +compatibility. </p> + +<p> Postfix uses the unquoted form internally, because an attacker +can specify an email address in different forms by playing games +with quotes and backslashes. An attacker should not be able to use +such games to circumvent Postfix access policies. </p> + +<p> This feature is available in Postfix 3.5 and later. </p> diff --git a/external/ibm-public/postfix/dist/src/anvil/anvil.c b/external/ibm-public/postfix/dist/src/anvil/anvil.c index 9c3783f4908..8236ce9c0a0 100644 --- a/external/ibm-public/postfix/dist/src/anvil/anvil.c +++ b/external/ibm-public/postfix/dist/src/anvil/anvil.c @@ -1,4 +1,4 @@ -/* $NetBSD: anvil.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: anvil.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -167,7 +167,8 @@ /* from many remote clients. To reduce memory usage, reduce /* the time unit over which state is kept. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* /* Upon exit, and every \fBanvil_status_update_time\fR /* seconds, the server logs the maximal count and rate values measured, @@ -231,8 +232,12 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* smtpd(8), Postfix SMTP server /* postconf(5), configuration parameters diff --git a/external/ibm-public/postfix/dist/src/bounce/bounce.c b/external/ibm-public/postfix/dist/src/bounce/bounce.c index 86e40307252..d09c09f4ddd 100644 --- a/external/ibm-public/postfix/dist/src/bounce/bounce.c +++ b/external/ibm-public/postfix/dist/src/bounce/bounce.c @@ -1,4 +1,4 @@ -/* $NetBSD: bounce.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: bounce.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -46,7 +46,8 @@ /* RFC 6532 (Internationalized Message Format) /* RFC 6533 (Internationalized Delivery Status Notifications) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -114,13 +115,17 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix 3.0 and later: /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* FILES /* /var/spool/postfix/bounce/* non-delivery records /* /var/spool/postfix/defer/* non-delivery records @@ -131,6 +136,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad diff --git a/external/ibm-public/postfix/dist/src/bounce/bounce_notify_util.c b/external/ibm-public/postfix/dist/src/bounce/bounce_notify_util.c index 0c6d745c4dc..91aa4db6f28 100644 --- a/external/ibm-public/postfix/dist/src/bounce/bounce_notify_util.c +++ b/external/ibm-public/postfix/dist/src/bounce/bounce_notify_util.c @@ -1,4 +1,4 @@ -/* $NetBSD: bounce_notify_util.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: bounce_notify_util.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -157,6 +157,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -639,7 +644,9 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) (bounce_info->smtputf8 & SMTPUTF8_FLAG_REQUESTED) ? "global-" : ""); /* Fix 20140709: addresses may be 8bit. */ - if (NOT_7BIT_MIME(bounce_info)) + if (NOT_7BIT_MIME(bounce_info) + /* BC Fix 20170610: prevent MIME downgrade of message/delivery-status. */ + && (bounce_info->smtputf8 & SMTPUTF8_FLAG_REQUESTED)) post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", bounce_info->mime_encoding); diff --git a/external/ibm-public/postfix/dist/src/bounce/bounce_template.c b/external/ibm-public/postfix/dist/src/bounce/bounce_template.c index 1080b99225a..3fe51d68ce7 100644 --- a/external/ibm-public/postfix/dist/src/bounce/bounce_template.c +++ b/external/ibm-public/postfix/dist/src/bounce/bounce_template.c @@ -1,4 +1,4 @@ -/* $NetBSD: bounce_template.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: bounce_template.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -308,7 +308,7 @@ static void bounce_template_parse_buffer(BOUNCE_TEMPLATE *tp) * Parse pseudo-header labels and values. * * XXX EAI: allow UTF8 in template headers when responding to SMTPUTF8 - * message. Sending SMTPUTF8 in reponse to non-SMTPUTF8 mail would make + * message. Sending SMTPUTF8 in response to non-SMTPUTF8 mail would make * no sense. */ #define GETLINE(line, buf) \ diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup.c index 46d149d7cf5..7746fd6c786 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup.c,v 1.6 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup.c,v 1.7 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -56,7 +56,8 @@ /* RFC 3464 (Delivery status notifications) /* RFC 5322 (Internet Message Format) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* Table-driven rewriting rules make it hard to express \fBif then /* else\fR and other logical relationships. @@ -262,7 +263,7 @@ /* off in email addresses. /* .IP "\fBmasquerade_exceptions (empty)\fR" /* Optional list of user names that are not subjected to address -/* masquerading, even when their address matches $masquerade_domains. +/* masquerading, even when their addresses match $masquerade_domains. /* .IP "\fBpropagate_unmatched_extensions (canonical, virtual)\fR" /* What address lookup tables copy an address extension from the lookup /* key to the lookup result. @@ -342,6 +343,12 @@ /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBenable_idna2003_compatibility (no)\fR" +/* Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +/* when converting UTF-8 domain names to/from the ASCII form that is +/* used for DNS lookups. /* MISCELLANEOUS CONTROLS /* .ad /* .fi @@ -383,12 +390,23 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 2.1 and later: /* .IP "\fBenable_original_recipient (yes)\fR" -/* Enable support for the X-Original-To message header. +/* Enable support for the original recipient address after an +/* address is rewritten to a different address (for example with +/* aliasing or with canonical mapping). +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* FILES /* /etc/postfix/canonical*, canonical mapping table /* /etc/postfix/virtual*, virtual mapping table @@ -402,6 +420,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup.h b/external/ibm-public/postfix/dist/src/cleanup/cleanup.h index b89e9e17185..6fb3859fd81 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup.h +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup.h @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup.h,v 1.8 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup.h,v 1.9 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -114,11 +114,14 @@ typedef struct CLEANUP_STATE { const char *client_addr; /* real or ersatz client */ int client_af; /* real or ersatz client */ const char *client_port; /* real or ersatz client */ + const char *server_addr; /* real or ersatz server */ + const char *server_port; /* real or ersatz server */ VSTRING *milter_ext_from; /* externalized sender */ VSTRING *milter_ext_rcpt; /* externalized recipient */ VSTRING *milter_err_text; /* milter call-back reply */ HBC_CHECKS *milter_hbc_checks; /* Milter header checks */ VSTRING *milter_hbc_reply; /* Milter header checks reply */ + VSTRING *milter_dsn_buf; /* Milter DSN parsing buffer */ /* * Support for Milter body replacement requests. @@ -348,6 +351,13 @@ extern int cleanup_body_edit_write(CLEANUP_STATE *, int, VSTRING *); extern int cleanup_body_edit_finish(CLEANUP_STATE *); extern void cleanup_body_edit_free(CLEANUP_STATE *); + /* + * From: header formatting. + */ +#define HFROM_FORMAT_CODE_STD 0 +#define HFROM_FORMAT_CODE_OBS 1 +extern int hfrom_format_code; + /* LICENSE /* .ad /* .fi @@ -357,4 +367,9 @@ extern void cleanup_body_edit_free(CLEANUP_STATE *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_addr.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_addr.c index 2ef14cbcf51..ca220b88655 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_addr.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_addr.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_addr.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -65,6 +65,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -167,8 +172,9 @@ off_t cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) if ((state->flags & CLEANUP_FLAG_BCC_OK) && *STR(clean_addr) && cleanup_send_bcc_maps) { - if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr), - IGNORE_EXTENSION)) != 0) { + if ((bcc = mail_addr_find_to_internal(cleanup_send_bcc_maps, + STR(clean_addr), + IGNORE_EXTENSION)) != 0) { cleanup_addr_bcc(state, bcc); } else if (cleanup_send_bcc_maps->error) { msg_warn("%s: %s map lookup problem -- " @@ -230,8 +236,9 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) if ((state->flags & CLEANUP_FLAG_BCC_OK) && *STR(clean_addr) && cleanup_rcpt_bcc_maps) { - if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr), - IGNORE_EXTENSION)) != 0) { + if ((bcc = mail_addr_find_to_internal(cleanup_rcpt_bcc_maps, + STR(clean_addr), + IGNORE_EXTENSION)) != 0) { cleanup_addr_bcc(state, bcc); } else if (cleanup_rcpt_bcc_maps->error) { msg_warn("%s: %s map lookup problem -- " diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_api.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_api.c index a9633d78fd0..a180f2bc60f 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_api.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_api.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_api.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_api.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -83,7 +83,8 @@ /* Autodetection: request SMTPUTF8 support if the message /* contains an UTF8 message header, sender, or recipient. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* SEE ALSO /* cleanup(8) cleanup service description. /* cleanup_init(8) cleanup callable interface, initialization @@ -96,6 +97,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_body_edit.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_body_edit.c index 8eda3f60afb..85b627e1ef6 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_body_edit.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_body_edit.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_body_edit.c,v 1.1.1.2 2020/03/18 18:59:32 christos Exp $ */ +/* $NetBSD: cleanup_body_edit.c,v 1.2 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_envelope.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_envelope.c index 76f69133e3a..7f8ba5e873f 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_envelope.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_envelope.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_envelope.c,v 1.4 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_envelope.c,v 1.5 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -39,6 +39,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -408,31 +413,21 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, return; } if (mapped_type == REC_TYPE_DSN_ENVID) { - /* Allow only one instance. */ - if (state->dsn_envid != 0) { - msg_warn("%s: message rejected: multiple DSN envelope ID records", - state->queue_id); - state->errs |= CLEANUP_STAT_BAD; - return; - } + /* Don't break "postsuper -r" after Milter overrides ENVID. */ if (!allprint(mapped_buf)) { msg_warn("%s: message rejected: bad DSN envelope ID record", state->queue_id); state->errs |= CLEANUP_STAT_BAD; return; } + if (state->dsn_envid != 0) + myfree(state->dsn_envid); state->dsn_envid = mystrdup(mapped_buf); cleanup_out(state, type, buf, len); return; } if (mapped_type == REC_TYPE_DSN_RET) { - /* Allow only one instance. */ - if (state->dsn_ret != 0) { - msg_warn("%s: message rejected: multiple DSN RET records", - state->queue_id); - state->errs |= CLEANUP_STAT_BAD; - return; - } + /* Don't break "postsuper -r" after Milter overrides RET. */ if (!alldig(mapped_buf) || (junk = atoi(mapped_buf)) == 0 || DSN_RET_OK(junk) == 0) { msg_warn("%s: message rejected: bad DSN RET record <%.200s>", diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_init.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_init.c index d305ea1794d..bb0afe52050 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_init.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_init.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_init.c,v 1.5 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_init.c,v 1.6 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -63,7 +63,8 @@ /* cleanup_sig() must be called in case of SIGTERM, in order /* to remove an incomplete queue file. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* SEE ALSO /* cleanup_api(3) cleanup callable interface, message processing /* LICENSE @@ -92,6 +93,7 @@ #include <msg.h> #include <iostuff.h> +#include <name_code.h> #include <name_mask.h> #include <stringops.h> @@ -137,7 +139,6 @@ char *var_mimehdr_checks; /* mime header checks */ char *var_nesthdr_checks; /* nested header checks */ char *var_body_checks; /* any body checks */ int var_dup_filter_limit; /* recipient dup filter */ -bool var_enable_orcpt; /* Include orcpt in dup filter? */ char *var_empty_addr; /* destination of bounced bounces */ int var_delay_warn_time; /* delay that triggers warning */ char *var_prop_extension; /* propagate unmatched extension */ @@ -176,6 +177,7 @@ char *var_milt_macro_deflts; /* default macro settings */ 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 */ const CONFIG_INT_TABLE cleanup_int_table[] = { VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0, @@ -189,7 +191,6 @@ const CONFIG_INT_TABLE cleanup_int_table[] = { }; const CONFIG_BOOL_TABLE cleanup_bool_table[] = { - VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt, 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, @@ -243,6 +244,7 @@ const CONFIG_STR_TABLE cleanup_str_table[] = { VAR_CLEANUP_MILTERS, DEF_CLEANUP_MILTERS, &var_cleanup_milters, 0, 0, VAR_MILT_HEAD_CHECKS, DEF_MILT_HEAD_CHECKS, &var_milt_head_checks, 0, 0, VAR_MILT_MACRO_DEFLTS, DEF_MILT_MACRO_DEFLTS, &var_milt_macro_deflts, 0, 0, + VAR_HFROM_FORMAT, DEF_HFROM_FORMAT, &var_hfrom_format, 1, 0, 0, }; @@ -282,6 +284,11 @@ int cleanup_ext_prop_mask; */ MILTERS *cleanup_milters; + /* + * From: header format. + */ +int hfrom_format_code; + /* cleanup_all - callback for the runtime error handler */ void cleanup_all(void) @@ -432,6 +439,11 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv) void cleanup_post_jail(char *unused_name, char **unused_argv) { + static const NAME_CODE hfrom_format_table[] = { + HFROM_FORMAT_NAME_STD, HFROM_FORMAT_CODE_STD, + HFROM_FORMAT_NAME_OBS, HFROM_FORMAT_CODE_OBS, + 0, -1, + }; /* * Optionally set the file size resource limit. XXX This limits the @@ -440,7 +452,7 @@ void cleanup_post_jail(char *unused_name, char **unused_argv) * really low limit, the difference is going to matter only when a queue * file has lots of recipients. */ - if (var_message_limit > 0) + if (ENFORCING_SIZE_LIMIT(var_message_limit)) set_file_limit((off_t) var_message_limit); /* @@ -461,4 +473,12 @@ void cleanup_post_jail(char *unused_name, char **unused_argv) cleanup_strip_chars = vstring_alloc(strlen(var_msg_strip_chars)); unescape(cleanup_strip_chars, var_msg_strip_chars); } + + /* + * From: header formatting. + */ + if ((hfrom_format_code = name_code(hfrom_format_table, + NAME_CODE_FLAG_NONE, var_hfrom_format)) < 0) + msg_fatal("invalid setting: %s = %s", + VAR_HFROM_FORMAT, var_hfrom_format); } diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_map11.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_map11.c index 94f0ba8bb55..95d5eaf1466 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_map11.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_map11.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_map11.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_map11.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -60,6 +60,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -106,7 +111,9 @@ int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr, * the place. */ for (count = 0; count < MAX_RECURSION; count++) { - if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) { + if ((new_addr = mail_addr_map_opt(maps, STR(addr), propagate, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + MA_FORM_EXTERNAL)) != 0) { if (new_addr->argc > 1) msg_warn("%s: multi-valued %s entry for %s", state->queue_id, maps->title, STR(addr)); diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_map1n.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_map1n.c index 188ed2da050..4063879628c 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_map1n.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_map1n.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_map1n.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_map1n.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -41,6 +41,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -134,8 +139,8 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, UNEXPAND(argv, addr); RETURN(argv); } - quote_822_local(state->temp1, argv->argv[arg]); - if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) { + if ((lookup = mail_addr_map_internal(maps, argv->argv[arg], + propagate)) != 0) { saved_lhs = mystrdup(argv->argv[arg]); for (i = 0; i < lookup->argc; i++) { if (strlen(lookup->argv[i]) > var_virt_addrlen_limit) { @@ -147,18 +152,17 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, UNEXPAND(argv, addr); RETURN(argv); } - unquote_822_local(state->temp1, lookup->argv[i]); if (i == 0) { - UPDATE(argv->argv[arg], STR(state->temp1)); + UPDATE(argv->argv[arg], lookup->argv[i]); } else { - argv_add(argv, STR(state->temp1), ARGV_END); + argv_add(argv, lookup->argv[i], ARGV_END); argv_terminate(argv); } /* * Allow an address to expand into itself once. */ - if (strcasecmp_utf8(saved_lhs, STR(state->temp1)) == 0) + if (strcasecmp_utf8(saved_lhs, lookup->argv[i]) == 0) been_here_fixed(been_here, saved_lhs); } myfree(saved_lhs); diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_message.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_message.c index 6cec3de4e2f..e613f28dbd2 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_message.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_message.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_message.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_message.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -41,6 +41,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -72,6 +77,7 @@ #include <rec_type.h> #include <cleanup_user.h> #include <tok822.h> +#include <lex_822.h> #include <header_opts.h> #include <quote_822_local.h> #include <mail_params.h> @@ -84,6 +90,7 @@ #include <lex_822.h> #include <dsn_util.h> #include <conv_time.h> +#include <info_log_addr_form.h> /* Application-specific. */ @@ -259,9 +266,11 @@ static void cleanup_act_log(CLEANUP_STATE *state, vstring_sprintf(state->temp1, "%s: %s: %s %.200s from %s;", state->queue_id, action, class, content, attr); if (state->sender) - vstring_sprintf_append(state->temp1, " from=<%s>", state->sender); + vstring_sprintf_append(state->temp1, " from=<%s>", + info_log_addr_form_sender(state->sender)); if (state->recip) - vstring_sprintf_append(state->temp1, " to=<%s>", state->recip); + vstring_sprintf_append(state->temp1, " to=<%s>", + info_log_addr_form_recipient(state->recip)); if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_PROTO_NAME)) != 0) vstring_sprintf_append(state->temp1, " proto=%s", attr); if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_HELO_NAME)) != 0) @@ -347,6 +356,11 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context, } return (buf); } + if (STREQUAL(value, "PASS", command_len)) { + cleanup_act_log(state, "pass", context, buf, optional_text); + state->flags &= ~CLEANUP_FLAG_FILTER_ALL; + return (buf); + } if (STREQUAL(value, "DISCARD", command_len)) { cleanup_act_log(state, "discard", context, buf, optional_text); state->flags |= CLEANUP_FLAG_DISCARD; @@ -403,7 +417,7 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context, cleanup_act_log(state, "prepend", context, buf, optional_text); temp = vstring_strcpy(vstring_alloc(strlen(optional_text)), - optional_text); + optional_text); cleanup_out_header(state, temp); vstring_free(temp); } @@ -455,6 +469,10 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context, } return (buf); } + if (STREQUAL(value, "STRIP", command_len)) { + cleanup_act_log(state, "strip", context, buf, optional_text); + return (CLEANUP_ACT_DROP); + } /* Allow and ignore optional text after the action. */ if (STREQUAL(value, "IGNORE", command_len)) @@ -648,6 +666,7 @@ static void cleanup_header_done_callback(void *context) char time_stamp[1024]; /* XXX locale dependent? */ struct tm *tp; TOK822 *token; + TOK822 *dummy_token; time_t tv; /* @@ -735,14 +754,60 @@ static void cleanup_header_done_callback(void *context) HDR_RESENT_FROM : HDR_FROM))) == 0) { quote_822_local(state->temp1, *state->sender ? state->sender : MAIL_ADDR_MAIL_DAEMON); - vstring_sprintf(state->temp2, "%sFrom: %s", - state->resent, vstring_str(state->temp1)); if (*state->sender && state->fullname && *state->fullname) { - vstring_sprintf(state->temp1, "(%s)", state->fullname); - token = tok822_parse(vstring_str(state->temp1)); - vstring_strcat(state->temp2, " "); - tok822_externalize(state->temp2, token, TOK822_STR_NONE); - tok822_free_tree(token); + char *cp; + + /* Enforce some sanity on full name content. */ + while ((cp = strchr(state->fullname, '\r')) != 0 + || (cp = strchr(state->fullname, '\n')) != 0) + *cp = ' '; + + switch (hfrom_format_code) { + + /* + * "From: phrase <route-addr>". Quote the phrase if it + * contains specials or the "%!" legacy address operators. + */ + case HFROM_FORMAT_CODE_STD: + vstring_sprintf(state->temp2, "%sFrom: ", state->resent); + if (state->fullname[strcspn(state->fullname, + "%!" LEX_822_SPECIALS)] == 0) { + /* Normalize whitespace. */ + token = tok822_scan_limit(state->fullname, &dummy_token, + var_token_limit); + } else { + token = tok822_alloc(TOK822_QSTRING, state->fullname); + } + tok822_externalize(state->temp2, token, TOK822_STR_NONE); + tok822_free(token); + vstring_sprintf_append(state->temp2, " <%s>", + vstring_str(state->temp1)); + break; + + /* + * "From: addr-spec (ctext)". This is the obsolete form. + */ + case HFROM_FORMAT_CODE_OBS: + vstring_sprintf(state->temp2, "%sFrom: %s ", + state->resent, vstring_str(state->temp1)); + vstring_sprintf(state->temp1, "(%s)", state->fullname); + token = tok822_parse(vstring_str(state->temp1)); + tok822_externalize(state->temp2, token, TOK822_STR_NONE); + tok822_free_tree(token); + break; + default: + msg_panic("%s: unknown header format %d", + myname, hfrom_format_code); + } + } + + /* + * "From: addr-spec". This is the form in the absence of full name + * information, also used for mail from mailer-daemon. + */ + else { + vstring_sprintf(state->temp2, "%sFrom: %s", + state->resent, vstring_str(state->temp1)); } CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2); } @@ -964,7 +1029,9 @@ static void cleanup_mime_error_callback(void *context, int err_code, #define TEXT_LEN (len < 100 ? (int) len : 100) msg_info("%s: reject: mime-error %s: %.*s from %s; from=<%s> to=<%s>", state->queue_id, mime_state_error(err_code), TEXT_LEN, text, - origin, state->sender, state->recip ? state->recip : "unknown"); + origin, info_log_addr_form_sender(state->sender), + info_log_addr_form_recipient(state->recip ? + state->recip : "unknown")); } } diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_milter.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_milter.c index 2b24c1a34fd..1ca1470c045 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_milter.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_milter.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_milter.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_milter.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -98,6 +98,7 @@ #include <vstream.h> #include <vstring.h> #include <stringops.h> +#include <inet_proto.h> /* Global library. */ @@ -114,6 +115,7 @@ #include <quote_821_local.h> #include <dsn_util.h> #include <xtext.h> +#include <info_log_addr_form.h> /* Application-specific. */ @@ -241,9 +243,11 @@ static void cleanup_milter_hbc_log(void *context, const char *action, state->queue_id, where, action, where, line, state->client_name, state->client_addr); if (state->sender) - vstring_sprintf_append(state->temp1, " from=<%s>", state->sender); + vstring_sprintf_append(state->temp1, " from=<%s>", + info_log_addr_form_sender(state->sender)); if (state->recip) - vstring_sprintf_append(state->temp1, " to=<%s>", state->recip); + vstring_sprintf_append(state->temp1, " to=<%s>", + info_log_addr_form_recipient(state->recip)); if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_PROTO_NAME)) != 0) vstring_sprintf_append(state->temp1, " proto=%s", attr); if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_HELO_NAME)) != 0) @@ -1331,22 +1335,61 @@ static const char *cleanup_chg_from(void *context, const char *ext_from, { const char *myname = "cleanup_chg_from"; CLEANUP_STATE *state = (CLEANUP_STATE *) context; + off_t new_offset; off_t new_sender_offset; off_t after_sender_offs; int addr_count; TOK822 *tree; TOK822 *tp; VSTRING *int_sender_buf; + int dsn_envid = 0; + int dsn_ret = 0; if (msg_verbose) msg_info("%s: \"%s\" \"%s\"", myname, ext_from, esmtp_args); - if (esmtp_args[0]) - msg_warn("%s: %s: ignoring ESMTP arguments \"%.100s\"", - state->queue_id, myname, esmtp_args); + /* + * ESMTP support is limited to RET and ENVID, i.e. things that are stored + * together with the sender queue file record. + */ + if (esmtp_args[0]) { + ARGV *esmtp_argv; + int i; + const char *arg; + + esmtp_argv = argv_split(esmtp_args, " "); + for (i = 0; i < esmtp_argv->argc; ++i) { + arg = esmtp_argv->argv[i]; + if (strncasecmp(arg, "RET=", 4) == 0) { + if ((dsn_ret = dsn_ret_code(arg + 4)) == 0) { + msg_warn("Ignoring bad ESMTP parameter \"%s\" in " + "SMFI_CHGFROM request", arg); + } else { + state->dsn_ret = dsn_ret; + } + } else if (strncasecmp(arg, "ENVID=", 6) == 0) { + if (state->milter_dsn_buf == 0) + state->milter_dsn_buf = vstring_alloc(20); + dsn_envid = (xtext_unquote(state->milter_dsn_buf, arg + 6) + && allprint(STR(state->milter_dsn_buf))); + if (!dsn_envid) { + msg_warn("Ignoring bad ESMTP parameter \"%s\" in " + "SMFI_CHGFROM request", arg); + } else { + if (state->dsn_envid) + myfree(state->dsn_envid); + state->dsn_envid = mystrdup(STR(state->milter_dsn_buf)); + } + } else { + msg_warn("Ignoring bad ESMTP parameter \"%s\" in " + "SMFI_CHGFROM request", arg); + } + } + argv_free(esmtp_argv); + } /* - * The cleanup server remembers the location of the the original sender + * The cleanup server remembers the file offset of the current sender * address record (offset in sender_pt_offset) and the file offset of the * record that follows the sender address (offset in sender_pt_target). * Short original sender records are padded, so that they can safely be @@ -1358,24 +1401,38 @@ static const char *cleanup_chg_from(void *context, const char *ext_from, msg_panic("%s: no post-sender record offset", myname); /* - * Allocate space after the end of the queue file, and write the new - * sender record, followed by a reverse pointer record that points to the - * record that follows the original sender address record. No padding is - * needed for a "new" short sender record, since the record is not meant - * to be overwritten. When the "new" sender is replaced, we allocate a - * new record at the end of the queue file. + * Allocate space after the end of the queue file, and write the new {DSN + * envid, DSN ret, sender address, sender BCC} records, followed by a + * reverse pointer record that points to the record that follows the + * original sender record. * * We update the queue file in a safe manner: save the new sender after the * end of the queue file, write the reverse pointer, and only then * overwrite the old sender record with the forward pointer to the new * sender. */ - if ((new_sender_offset = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) { + if ((new_offset = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) { msg_warn("%s: seek file %s: %m", myname, cleanup_path); return (cleanup_milter_error(state, errno)); } /* + * Sender DSN attribute records precede the sender record. + */ + if (dsn_envid) + rec_fprintf(state->dst, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_DSN_ENVID, STR(state->milter_dsn_buf)); + if (dsn_ret) + rec_fprintf(state->dst, REC_TYPE_ATTR, "%s=%d", + MAIL_ATTR_DSN_RET, dsn_ret); + if (dsn_envid == 0 && dsn_ret == 0) { + new_sender_offset = new_offset; + } else if ((new_sender_offset = vstream_ftell(state->dst)) < 0) { + msg_warn("%s: vstream_ftell file %s: %m", myname, cleanup_path); + return (cleanup_milter_error(state, errno)); + } + + /* * Transform the address from external form to internal form. This also * removes the enclosing <>, if present. * @@ -1403,15 +1460,20 @@ static const char *cleanup_chg_from(void *context, const char *ext_from, state->sender_pt_target = after_sender_offs; /* - * Overwrite the original sender record with the pointer to the new - * sender address record. + * Overwrite the current sender record with the pointer to the new {DSN + * envid, DSN ret, sender address, sender BCC} records. */ if (vstream_fseek(state->dst, state->sender_pt_offset, SEEK_SET) < 0) { msg_warn("%s: seek file %s: %m", myname, cleanup_path); return (cleanup_milter_error(state, errno)); } cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT, - (long) new_sender_offset); + (long) new_offset); + + /* + * Remember the location of the new current sender record. + */ + state->sender_pt_offset = new_sender_offset; /* * In case of error while doing record output. @@ -1823,6 +1885,7 @@ static const char *cleanup_milter_eval(const char *name, void *ptr) */ #ifndef CLIENT_ATTR_UNKNOWN #define CLIENT_ATTR_UNKNOWN "unknown" +#define SERVER_ATTR_UNKNOWN "unknown" #endif if (strcmp(name, S8_MAC__) == 0) { @@ -1844,6 +1907,13 @@ static const char *cleanup_milter_eval(const char *name, void *ptr) state->client_port : "0"); if (strcmp(name, S8_MAC_CLIENT_PTR) == 0) return (state->reverse_name); + /* XXX S8_MAC_CLIENT_RES needs SMTPD_PEER_CODE_XXX from smtpd. */ + if (strcmp(name, S8_MAC_DAEMON_ADDR) == 0) + return (state->server_addr); + if (strcmp(name, S8_MAC_DAEMON_PORT) == 0) + return (state->server_port + && strcmp(state->server_port, SERVER_ATTR_UNKNOWN) ? + state->server_port : "0"); /* * MAIL FROM macros. @@ -1889,7 +1959,7 @@ void cleanup_milter_receive(CLEANUP_STATE *state, int count) cleanup_repl_body, (void *) state); } -/* cleanup_milter_apply - apply Milter reponse, non-zero if rejecting */ +/* cleanup_milter_apply - apply Milter response, non-zero if rejecting */ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, const char *resp) @@ -1991,9 +2061,11 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, state->queue_id, action, event, state->client_name, state->client_addr, text); if (state->sender) - vstring_sprintf_append(state->temp1, " from=<%s>", state->sender); + vstring_sprintf_append(state->temp1, " from=<%s>", + info_log_addr_form_sender(state->sender)); if (state->recip) - vstring_sprintf_append(state->temp1, " to=<%s>", state->recip); + vstring_sprintf_append(state->temp1, " to=<%s>", + info_log_addr_form_recipient(state->recip)); if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_PROTO_NAME)) != 0) vstring_sprintf_append(state->temp1, " proto=%s", attr); if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_HELO_NAME)) != 0) @@ -2007,6 +2079,7 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, static void cleanup_milter_client_init(CLEANUP_STATE *state) { + static INET_PROTO_INFO *proto_info; const char *proto_attr; /* @@ -2021,19 +2094,34 @@ static void cleanup_milter_client_init(CLEANUP_STATE *state) state->client_addr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR); state->client_port = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_PORT); proto_attr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_AF); + state->server_addr = nvtable_find(state->attr, MAIL_ATTR_ACT_SERVER_ADDR); + state->server_port = nvtable_find(state->attr, MAIL_ATTR_ACT_SERVER_PORT); if (state->client_name == 0 || state->client_addr == 0 || proto_attr == 0 || !alldig(proto_attr)) { state->client_name = "localhost"; - state->client_addr = "127.0.0.1"; - state->client_af = AF_INET; +#ifdef AF_INET6 + if (proto_info == 0) + proto_info = inet_proto_info(); + if (proto_info->sa_family_list[0] == PF_INET6) { + state->client_addr = "::1"; + state->client_af = AF_INET6; + } else +#endif + { + state->client_addr = "127.0.0.1"; + state->client_af = AF_INET; + } + state->server_addr = state->client_addr; } else state->client_af = atoi(proto_attr); if (state->reverse_name == 0) state->reverse_name = state->client_name; /* Compatibility with pre-2.5 queue files. */ - if (state->client_port == 0) + if (state->client_port == 0) { state->client_port = NO_CLIENT_PORT; + state->server_port = state->client_port; + } } /* cleanup_milter_inspect - run message through mail filter */ @@ -2221,7 +2309,6 @@ int cleanup_send_canon_flags; MAPS *cleanup_send_canon_maps; int var_dup_filter_limit = DEF_DUP_FILTER_LIMIT; char *var_empty_addr = DEF_EMPTY_ADDR; -int var_enable_orcpt = DEF_ENABLE_ORCPT; MAPS *cleanup_virt_alias_maps; char *var_milt_daemon_name = "host.example.com"; char *var_milt_v = DEF_MILT_V; @@ -2405,6 +2492,7 @@ int main(int unused_argc, char **argv) char *bufp; int istty = isatty(vstream_fileno(VSTREAM_IN)); CLEANUP_STATE *state = cleanup_state_alloc((VSTREAM *) 0); + const char *parens = "{}"; state->queue_id = mystrdup("NOQUEUE"); state->sender = mystrdup("sender"); @@ -2416,6 +2504,8 @@ int main(int unused_argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); var_line_limit = DEF_LINE_LIMIT; var_header_limit = DEF_HEADER_LIMIT; + var_enable_orcpt = DEF_ENABLE_ORCPT; + var_info_log_addr_form = DEF_INFO_LOG_ADDR_FORM; for (;;) { ARGV *argv; @@ -2436,7 +2526,7 @@ int main(int unused_argc, char **argv) } if (*bufp == '#' || *bufp == 0 || allspace(bufp)) continue; - argv = argv_split(bufp, " "); + argv = argv_splitq(bufp, " ", parens); if (argv->argc == 0) { msg_warn("missing command"); } else if (strcmp(argv->argv[0], "?") == 0) { @@ -2516,7 +2606,15 @@ int main(int unused_argc, char **argv) if (argv->argc != 3) { msg_warn("bad chg_from argument count: %ld", (long) argv->argc); } else { - cleanup_chg_from(state, argv->argv[1], argv->argv[2]); + char *arg = argv->argv[2]; + const char *err; + + if (*arg == parens[0] + && (err = extpar(&arg, parens, EXTPAR_FLAG_NONE)) != 0) { + msg_warn("%s in \"%s\"", err, arg); + } else { + cleanup_chg_from(state, argv->argv[1], arg); + } } } else if (strcmp(argv->argv[0], "add_rcpt") == 0) { if (argv->argc != 2) { diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_out_recipient.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_out_recipient.c index 35888fdd69f..b0074a9a066 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_out_recipient.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_out_recipient.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_out_recipient.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_out_recipient.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -55,6 +55,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -135,8 +140,6 @@ void cleanup_out_recipient(CLEANUP_STATE *state, /* * XXX Not elegant, but eliminates complexity in the record reading loop. */ - if (!var_enable_orcpt) - orcpt = ""; if (dsn_orcpt == 0) dsn_orcpt = ""; diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_region.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_region.c index ff80a79db89..a7bb1639edd 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_region.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_region.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_region.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_region.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -40,7 +40,7 @@ /* queue file is complete. /* /* cleanup_region_open() opens an existing region or creates -/* a new region that can accomodate at least the specified +/* a new region that can accommodate at least the specified /* amount of space. A new region is an open-ended region at /* the end of the file; it must be closed (see next) before /* unrelated data can be appended to the same file. diff --git a/external/ibm-public/postfix/dist/src/cleanup/cleanup_state.c b/external/ibm-public/postfix/dist/src/cleanup/cleanup_state.c index 09774d3e7eb..33c39324fdd 100644 --- a/external/ibm-public/postfix/dist/src/cleanup/cleanup_state.c +++ b/external/ibm-public/postfix/dist/src/cleanup/cleanup_state.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanup_state.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: cleanup_state.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -30,6 +30,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -127,9 +132,12 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) state->client_addr = 0; state->client_af = 0; state->client_port = 0; + state->server_addr = 0; + state->server_port = 0; state->milter_ext_from = 0; state->milter_ext_rcpt = 0; state->milter_err_text = 0; + state->milter_dsn_buf = 0; state->free_regions = state->body_regions = state->curr_body_region = 0; state->smtputf8 = 0; return (state); @@ -189,6 +197,8 @@ void cleanup_state_free(CLEANUP_STATE *state) vstring_free(state->milter_ext_rcpt); if (state->milter_err_text) vstring_free(state->milter_err_text); + if (state->milter_dsn_buf) + vstring_free(state->milter_dsn_buf); cleanup_region_done(state); myfree((void *) state); } diff --git a/external/ibm-public/postfix/dist/src/discard/discard.c b/external/ibm-public/postfix/dist/src/discard/discard.c index c5769ad3fe8..ab6e8a6f300 100644 --- a/external/ibm-public/postfix/dist/src/discard/discard.c +++ b/external/ibm-public/postfix/dist/src/discard/discard.c @@ -1,4 +1,4 @@ -/* $NetBSD: discard.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: discard.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -33,7 +33,8 @@ /* STANDARDS /* RFC 3463 (Enhanced Status Codes) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* /* Depending on the setting of the \fBnotify_classes\fR parameter, /* the postmaster is notified of bounces and of other trouble. @@ -76,8 +77,12 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* qmgr(8), queue manager /* bounce(8), delivery status reports @@ -85,6 +90,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad diff --git a/external/ibm-public/postfix/dist/src/dns/dns.h b/external/ibm-public/postfix/dist/src/dns/dns.h index c89b42f04c6..e8369722fab 100644 --- a/external/ibm-public/postfix/dist/src/dns/dns.h +++ b/external/ibm-public/postfix/dist/src/dns/dns.h @@ -1,4 +1,4 @@ -/* $NetBSD: dns.h,v 1.2 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: dns.h,v 1.3 2020/03/18 19:05:15 christos Exp $ */ #ifndef _DNS_H_INCLUDED_ #define _DNS_H_INCLUDED_ @@ -302,6 +302,11 @@ extern int dns_rr_filter_execute(DNS_RR **); #endif + /* + * dns_str_resflags.c + */ +const char *dns_str_resflags(unsigned long); + /* LICENSE /* .ad /* .fi @@ -311,6 +316,11 @@ extern int dns_rr_filter_execute(DNS_RR **); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/dns/dns_lookup.c b/external/ibm-public/postfix/dist/src/dns/dns_lookup.c index ab424fa8cc1..58d7567af39 100644 --- a/external/ibm-public/postfix/dist/src/dns/dns_lookup.c +++ b/external/ibm-public/postfix/dist/src/dns/dns_lookup.c @@ -1,4 +1,4 @@ -/* $NetBSD: dns_lookup.c,v 1.4 2017/02/14 01:16:44 christos Exp $ */ +/* $NetBSD: dns_lookup.c,v 1.5 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -147,6 +147,8 @@ /* available. The per-record reply TTL specifies how long the /* DNS_NOTFOUND answer is valid. The caller should pass the /* record(s) to dns_rr_free(). +/* Logs a warning if the RES_DNSRCH or RES_DEFNAMES resolver +/* flags are set, and disables those flags. /* .RE /* .IP ltype /* The resource record types to be looked up. In the case of @@ -340,6 +342,7 @@ res_nmkquery(res_state statp, int op, const char *dname, int class, * information, but that will have to wait until it is safe to make * libunbound a mandatory dependency for Postfix. */ +#ifdef HAVE_RES_SEND /* dns_res_query - a res_query() clone that can return negative replies */ @@ -405,6 +408,8 @@ static int dns_res_query(res_state res, const char *name, int class, int type, } } +#endif + /* dns_res_search - res_search() that can return negative replies */ static int dns_res_search(res_state res, const char *name, int class, int type, @@ -488,6 +493,16 @@ static int dns_query(const char *name, int type, unsigned flags, flags |= RES_USE_EDNS0; /* + * Can't append domains: we need the right SOA TTL. + */ +#define APPEND_DOMAIN_FLAGS (RES_DNSRCH | RES_DEFNAMES) + + if (keep_notfound && (flags & APPEND_DOMAIN_FLAGS)) { + msg_warn("negative caching disables RES_DEFNAMES and RES_DNSRCH"); + flags &= ~APPEND_DOMAIN_FLAGS; + } + + /* * Save and restore resolver options that we overwrite, to avoid * surprising behavior in other code that also invokes the resolver. */ @@ -1121,8 +1136,8 @@ int dns_lookup_rl(const char *name, unsigned flags, DNS_RR **rrlist, for (type = va_arg(ap, unsigned); type != 0; type = next) { next = va_arg(ap, unsigned); if (msg_verbose) - msg_info("lookup %s type %s flags %d", - name, dns_strtype(type), flags); + msg_info("lookup %s type %s flags %s", + name, dns_strtype(type), dns_str_resflags(flags)); status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0, fqdn, why, rcode, lflags); if (rrlist && rr) @@ -1173,8 +1188,8 @@ int dns_lookup_rv(const char *name, unsigned flags, DNS_RR **rrlist, for (type = *types++; type != 0; type = next) { next = *types++; if (msg_verbose) - msg_info("lookup %s type %s flags %d", - name, dns_strtype(type), flags); + msg_info("lookup %s type %s flags %s", + name, dns_strtype(type), dns_str_resflags(flags)); status = dns_lookup_x(name, type, flags, rrlist ? &rr : (DNS_RR **) 0, fqdn, why, rcode, lflags); if (rrlist && rr) diff --git a/external/ibm-public/postfix/dist/src/dns/dns_str_resflags.c b/external/ibm-public/postfix/dist/src/dns/dns_str_resflags.c index dbb7dc7b18e..ba4ded2ff11 100644 --- a/external/ibm-public/postfix/dist/src/dns/dns_str_resflags.c +++ b/external/ibm-public/postfix/dist/src/dns/dns_str_resflags.c @@ -1,4 +1,4 @@ -/* $NetBSD: dns_str_resflags.c,v 1.1.1.1 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: dns_str_resflags.c,v 1.2 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/dnsblog/dnsblog.c b/external/ibm-public/postfix/dist/src/dnsblog/dnsblog.c index fb9064854d2..7bb2441bff8 100644 --- a/external/ibm-public/postfix/dist/src/dnsblog/dnsblog.c +++ b/external/ibm-public/postfix/dist/src/dnsblog/dnsblog.c @@ -1,4 +1,4 @@ -/* $NetBSD: dnsblog.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: dnsblog.c,v 1.3 2020/03/18 19:05:15 christos Exp $ */ /*++ /* NAME @@ -22,10 +22,12 @@ /* query arguments plus an address list with the resulting IP /* addresses, separated by whitespace, and the reply TTL. /* Otherwise it replies with the query arguments plus an empty -/* address list and the reply TTL (-1 if unavailable). Finally, -/* The \fBdnsblog\fR(8) server closes the connection. +/* address list and the reply TTL; the reply TTL is -1 if there +/* is no reply, or a negative reply that contains no SOA record. +/* Finally, the \fBdnsblog\fR(8) server closes the connection. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -57,12 +59,17 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* smtpd(8), Postfix SMTP server /* postconf(5), configuration parameters -/* syslogd(5), system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -309,5 +316,6 @@ int main(int argc, char **argv) CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_POST_INIT(post_jail_init), CA_MAIL_SERVER_UNLIMITED, + CA_MAIL_SERVER_RETIRE_ME, 0); } diff --git a/external/ibm-public/postfix/dist/src/error/error.c b/external/ibm-public/postfix/dist/src/error/error.c index 73035d2c05c..86c05e20bef 100644 --- a/external/ibm-public/postfix/dist/src/error/error.c +++ b/external/ibm-public/postfix/dist/src/error/error.c @@ -1,4 +1,4 @@ -/* $NetBSD: error.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: error.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -34,7 +34,8 @@ /* STANDARDS /* RFC 3463 (Enhanced Status Codes) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* /* Depending on the setting of the \fBnotify_classes\fR parameter, /* the postmaster is notified of bounces and of other trouble. @@ -86,8 +87,12 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* qmgr(8), queue manager /* bounce(8), delivery status reports @@ -95,6 +100,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad diff --git a/external/ibm-public/postfix/dist/src/flush/flush.c b/external/ibm-public/postfix/dist/src/flush/flush.c index 9bdafb61538..6eb289622d0 100644 --- a/external/ibm-public/postfix/dist/src/flush/flush.c +++ b/external/ibm-public/postfix/dist/src/flush/flush.c @@ -1,4 +1,4 @@ -/* $NetBSD: flush.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: flush.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -55,7 +55,8 @@ /* talk to the network, and it does not talk to local users. /* The fast flush server can run chrooted at fixed low privilege. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* Fast flush logfiles are truncated only after a "send" /* request, not when mail is actually delivered, and therefore can @@ -116,8 +117,12 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* FILES /* /var/spool/postfix/flush, "fast flush" logfiles. /* SEE ALSO @@ -126,6 +131,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/global/anvil_clnt.c b/external/ibm-public/postfix/dist/src/global/anvil_clnt.c index 9663a7f3cf8..538c65479ce 100644 --- a/external/ibm-public/postfix/dist/src/global/anvil_clnt.c +++ b/external/ibm-public/postfix/dist/src/global/anvil_clnt.c @@ -1,4 +1,4 @@ -/* $NetBSD: anvil_clnt.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: anvil_clnt.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -143,6 +143,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/global/anvil_clnt.h b/external/ibm-public/postfix/dist/src/global/anvil_clnt.h index d4af0ed60bf..b06c7243ce5 100644 --- a/external/ibm-public/postfix/dist/src/global/anvil_clnt.h +++ b/external/ibm-public/postfix/dist/src/global/anvil_clnt.h @@ -1,4 +1,4 @@ -/* $NetBSD: anvil_clnt.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: anvil_clnt.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _ANVIL_CLNT_H_INCLUDED_ #define _ANVIL_CLNT_H_INCLUDED_ @@ -75,6 +75,11 @@ extern void anvil_clnt_free(ANVIL_CLNT *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/been_here.c b/external/ibm-public/postfix/dist/src/global/been_here.c index dc5e1cbb952..9eefb08a4a4 100644 --- a/external/ibm-public/postfix/dist/src/global/been_here.c +++ b/external/ibm-public/postfix/dist/src/global/been_here.c @@ -1,4 +1,4 @@ -/* $NetBSD: been_here.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: been_here.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -53,7 +53,7 @@ /* Arguments: /* .IP size /* Upper bound on the table size; at most \fIsize\fR strings will -/* be remembered. Specify a value <= 0 to disable the upper bound. +/* be remembered. Specify BH_BOUND_NONE to disable the upper bound. /* .IP flags /* Requests for special processing. Specify the bitwise OR of zero /* or more flags: diff --git a/external/ibm-public/postfix/dist/src/global/been_here.h b/external/ibm-public/postfix/dist/src/global/been_here.h index f423e5ca3a6..f219eb5d69a 100644 --- a/external/ibm-public/postfix/dist/src/global/been_here.h +++ b/external/ibm-public/postfix/dist/src/global/been_here.h @@ -1,4 +1,4 @@ -/* $NetBSD: been_here.h,v 1.1.1.2 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: been_here.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _BEEN_HERE_H_INCLUDED_ #define _BEEN_HERE_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/bounce_log.c b/external/ibm-public/postfix/dist/src/global/bounce_log.c index 5b355fb000a..c3db20c7ad5 100644 --- a/external/ibm-public/postfix/dist/src/global/bounce_log.c +++ b/external/ibm-public/postfix/dist/src/global/bounce_log.c @@ -1,4 +1,4 @@ -/* $NetBSD: bounce_log.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: bounce_log.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -80,6 +80,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -266,7 +271,7 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf, recipient = cp + 1; if ((cp = strstr(recipient, ">: ")) == 0) { msg_warn("%s: malformed record: %.30s...", - VSTREAM_PATH(bp->fp), cp); + VSTREAM_PATH(bp->fp), recipient - 1); continue; } *cp = 0; diff --git a/external/ibm-public/postfix/dist/src/global/clnt_stream.c b/external/ibm-public/postfix/dist/src/global/clnt_stream.c index 6f225afd12b..110b3c5b8cf 100644 --- a/external/ibm-public/postfix/dist/src/global/clnt_stream.c +++ b/external/ibm-public/postfix/dist/src/global/clnt_stream.c @@ -1,4 +1,4 @@ -/* $NetBSD: clnt_stream.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: clnt_stream.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -129,7 +129,7 @@ static void clnt_stream_ttl_event(int event, void *context) * with the call-back routine, but there is too much code that would have * to be changed. * - * XXX Should we be concerned that an overly agressive optimizer will + * XXX Should we be concerned that an overly aggressive optimizer will * eliminate this function and replace calls to clnt_stream_ttl_event() * by direct calls to clnt_stream_event()? It should not, because there * exists code that takes the address of both functions. diff --git a/external/ibm-public/postfix/dist/src/global/deliver_request.h b/external/ibm-public/postfix/dist/src/global/deliver_request.h index d742913a906..7d01b99bc19 100644 --- a/external/ibm-public/postfix/dist/src/global/deliver_request.h +++ b/external/ibm-public/postfix/dist/src/global/deliver_request.h @@ -1,4 +1,4 @@ -/* $NetBSD: deliver_request.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: deliver_request.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _DELIVER_REQUEST_H_INCLUDED_ #define _DELIVER_REQUEST_H_INCLUDED_ @@ -14,6 +14,12 @@ /* .nf /* + * System library. + */ +#include <sys_defs.h> +#include <stdarg.h> + + /* * Utility library. */ #include <vstring.h> @@ -130,6 +136,9 @@ typedef struct VSTREAM _deliver_vstream_; extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *); extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int); +extern int PRINTFLIKE(4, 5) reject_deliver_request(const char *, + DELIVER_REQUEST *, const char *, const char *,...); + /* LICENSE /* .ad /* .fi @@ -139,6 +148,11 @@ extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/dict_ldap.c b/external/ibm-public/postfix/dist/src/global/dict_ldap.c index b04a8889f48..99d7883b2d7 100644 --- a/external/ibm-public/postfix/dist/src/global/dict_ldap.c +++ b/external/ibm-public/postfix/dist/src/global/dict_ldap.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_ldap.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: dict_ldap.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -156,6 +156,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* John Hensley /* john@sunislelodge.com /* @@ -1354,10 +1359,10 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { - if (dict->fold_buf == 0) - dict->fold_buf = vstring_alloc(10); - vstring_strcpy(dict->fold_buf, name); - name = lowercase(vstring_str(dict->fold_buf)); + if (dict->fold_buf == 0) + dict->fold_buf = vstring_alloc(10); + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); } /* @@ -1772,17 +1777,9 @@ DICT *dict_ldap_open(const char *ldapsource, int open_flags, int dict_flags) * set. */ dict_ldap->timeout = cfg_get_int(dict_ldap->parser, "timeout", 10, 0, 0); - -#if 0 /* No benefit from changing - * this to match the - * MySQL/PGSQL syntax */ - if ((dict_ldap->query = - cfg_get_str(dict_ldap->parser, "query", 0, 0, 0)) == 0) -#endif - dict_ldap->query = - cfg_get_str(dict_ldap->parser, "query_filter", - "(mailacceptinggeneralid=%s)", 0, 0); - + dict_ldap->query = + cfg_get_str(dict_ldap->parser, "query_filter", + "(mailacceptinggeneralid=%s)", 0, 0); if ((dict_ldap->result_format = cfg_get_str(dict_ldap->parser, "result_format", 0, 0, 0)) == 0) dict_ldap->result_format = diff --git a/external/ibm-public/postfix/dist/src/global/dict_mysql.c b/external/ibm-public/postfix/dist/src/global/dict_mysql.c index 1a7fa7aa697..cfca5cdb3bc 100644 --- a/external/ibm-public/postfix/dist/src/global/dict_mysql.c +++ b/external/ibm-public/postfix/dist/src/global/dict_mysql.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_mysql.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: dict_mysql.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -59,7 +59,7 @@ /* List of domains the queries should be restricted to. If /* specified, only FQDN addresses whose domain parts matching this /* list will be queried against the SQL database. Lookups for -/* partial addresses are also supressed. This can significantly +/* partial addresses are also suppressed. This can significantly /* reduce the query load on the server. /* .IP query /* Query template, before the query is actually issued, variable @@ -98,6 +98,8 @@ /* location. /* .IP option_group /* Read options from the given group. +/* .IP require_result_set +/* Require that every query produces a result set. /* .IP tls_cert_file /* File containing client's X509 certificate. /* .IP tls_key_file @@ -134,44 +136,25 @@ /* where_field = alias /* .br /* hosts = host1.some.domain host2.some.domain -/* .IP additional_conditions -/* Backward compatibility when \fIquery\fR is not set, additional -/* conditions to the WHERE clause. -/* .IP hosts -/* List of hosts to connect to. -/* .PP -/* For example, if you want the map to reference databases of -/* the name "your_db" and execute a query like this: select -/* forw_addr from aliases where alias like '<some username>' -/* against any database called "vmailer_info" located on hosts -/* host1.some.domain and host2.some.domain, logging in as user -/* "vmailer" and password "passwd" then the configuration file -/* should read: -/* .PP -/* user = vmailer -/* .br -/* password = passwd -/* .br -/* dbname = vmailer_info -/* .br -/* table = aliases -/* .br -/* select_field = forw_addr -/* .br -/* where_field = alias -/* .br -/* hosts = host1.some.domain host2.some.domain /* .PP /* SEE ALSO /* dict(3) generic dictionary manager /* AUTHOR(S) -/* Scott Cotton +/* Scott Cotton, Joshua Marcus /* IC Group, Inc. /* scott@icgroup.com /* -/* Joshua Marcus -/* IC Group, Inc. -/* josh@icgroup.com +/* Liviu Daia +/* Institute of Mathematics of the Romanian Academy +/* P.O. BOX 1-764 +/* RO-014700 Bucharest, ROMANIA +/* +/* John Fawcett +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -188,6 +171,8 @@ #include <syslog.h> #include <time.h> #include <mysql.h> +#include <limits.h> +#include <errno.h> #ifdef STRCASECMP_IN_STRINGS_H #include <strings.h> @@ -215,6 +200,14 @@ #include "dict_mysql.h" +/* MySQL 8.x API change */ + +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50023 +#define DICT_MYSQL_SSL_VERIFY_SERVER_CERT MYSQL_OPT_SSL_VERIFY_SERVER_CERT +#elif MYSQL_VERSION_ID >= 80000 +#define DICT_MYSQL_SSL_VERIFY_SERVER_CERT MYSQL_OPT_SSL_MODE +#endif + /* need some structs to help organize things */ typedef struct { MYSQL *db; @@ -254,10 +247,11 @@ typedef struct { char *tls_CAfile; char *tls_CApath; char *tls_ciphers; -#if MYSQL_VERSION_ID >= 50023 +#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT) int tls_verify_cert; #endif #endif + int require_result_set; } DICT_MYSQL; #define STATACTIVE (1<<0) @@ -273,7 +267,7 @@ typedef struct { /* internal function declarations */ static PLMYSQL *plmysql_init(ARGV *); -static MYSQL_RES *plmysql_query(DICT_MYSQL *, const char *, VSTRING *); +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 *); @@ -290,14 +284,16 @@ static void dict_mysql_quote(DICT *dict, const char *name, VSTRING *result) { DICT_MYSQL *dict_mysql = (DICT_MYSQL *) dict; int len = strlen(name); - int buflen = 2 * len + 1; + int buflen; /* * We won't get integer overflows in 2*len + 1, because Postfix input * keys have reasonable size limits, better safe than sorry. */ - if (buflen < len) - msg_panic("dict_mysql_quote: integer overflow in 2*%d+1", len); + if (len > (INT_MAX - VSTRING_LEN(result) - 1) / 2) + msg_panic("dict_mysql_quote: integer overflow in %lu+2*%d+1", + (unsigned long) VSTRING_LEN(result), len); + buflen = 2 * len + 1; VSTRING_SPACE(result, buflen); #if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 @@ -332,6 +328,19 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name) dict->error = 0; /* + * Don't frustrate future attempts to make Postfix UTF-8 transparent. + */ +#ifdef SNAPSHOT + if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 + && !valid_utf8_string(name, strlen(name))) { + if (msg_verbose) + msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", + myname, dict_mysql->parser->name, name); + return (0); + } +#endif + + /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { @@ -381,10 +390,12 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name) return (0); /* do the query - set dict->error & cleanup if there's an error */ - if ((query_res = plmysql_query(dict_mysql, name, query)) == 0) { + if (plmysql_query(dict_mysql, name, query, &query_res) == 0) { dict->error = DICT_ERR_RETRY; return (0); } + if (query_res == 0) + return (0); numrows = mysql_num_rows(query_res); if (msg_verbose) msg_info("%s: retrieved %d rows", myname, numrows); @@ -506,20 +517,34 @@ static void dict_mysql_event(int unused_event, void *context) } /* - * plmysql_query - process a MySQL query. Return MYSQL_RES* on success. + * plmysql_query - process a MySQL query. Return 'true' on success. * On failure, log failure and try other db instances. - * on failure of all db instances, return 0; + * on failure of all db instances, return 'false'; * close unnecessary active connections */ -static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql, - const char *name, - VSTRING *query) +static int plmysql_query(DICT_MYSQL *dict_mysql, + const char *name, + VSTRING *query, + MYSQL_RES **result) { HOST *host; - MYSQL_RES *res = 0; + MYSQL_RES *first_result = 0; + int query_error; + + /* + * Helper to avoid spamming the log with warnings. + */ +#define SET_ERROR_AND_WARN_ONCE(err, ...) \ + do { \ + if (err == 0) { \ + err = 1; \ + msg_warn(__VA_ARGS__); \ + } \ + } while (0) while ((host = dict_mysql_get_active(dict_mysql)) != NULL) { + #if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 /* @@ -534,23 +559,104 @@ static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql, dict_mysql->active_host = 0; #endif - if (!(mysql_query(host->db, vstring_str(query)))) { - if ((res = mysql_store_result(host->db)) == 0) { - msg_warn("mysql query failed: %s", mysql_error(host->db)); - plmysql_down_host(host); - } else { - if (msg_verbose) - msg_info("dict_mysql: successful query from host %s", host->hostname); - event_request_timer(dict_mysql_event, (void *) host, IDLE_CONN_INTV); - break; + query_error = 0; + errno = 0; + + /* + * The query must complete. + */ + if (mysql_query(host->db, vstring_str(query)) != 0) { + query_error = 1; + msg_warn("%s:%s: query failed: %s", + dict_mysql->dict.type, dict_mysql->dict.name, + mysql_error(host->db)); + } + + /* + * Collect all result sets to avoid synchronization errors. + */ + else { + int next_res_status; + + do { + MYSQL_RES *temp_result; + + /* + * Keep the first result set. Reject multiple result sets. + */ + if ((temp_result = mysql_store_result(host->db)) != 0) { + if (first_result == 0) { + first_result = temp_result; + } else { + SET_ERROR_AND_WARN_ONCE(query_error, + "%s:%s: query failed: multiple result sets " + "returning data are not supported", + dict_mysql->dict.type, + dict_mysql->dict.name); + mysql_free_result(temp_result); + } + } + + /* + * No result: the mysql_field_count() function must return 0 + * to indicate that mysql_store_result() completed normally. + */ + else if (mysql_field_count(host->db) != 0) { + SET_ERROR_AND_WARN_ONCE(query_error, + "%s:%s: query failed (mysql_store_result): %s", + dict_mysql->dict.type, + dict_mysql->dict.name, + mysql_error(host->db)); + } + + /* + * Are there more results? -1 = no, 0 = yes, > 0 = error. + */ + if ((next_res_status = mysql_next_result(host->db)) > 0) { + SET_ERROR_AND_WARN_ONCE(query_error, + "%s:%s: query failed (mysql_next_result): %s", + dict_mysql->dict.type, + dict_mysql->dict.name, + mysql_error(host->db)); + } + } while (next_res_status == 0); + + /* + * Enforce the require_result_set setting. + */ + if (first_result == 0 && dict_mysql->require_result_set) { + SET_ERROR_AND_WARN_ONCE(query_error, + "%s:%s: query failed: query returned no result set" + "(require_result_set = yes)", + dict_mysql->dict.type, + dict_mysql->dict.name); } - } else { - msg_warn("mysql query failed: %s", mysql_error(host->db)); + } + + /* + * See what we got. + */ + if (query_error) { plmysql_down_host(host); + if (errno == 0) + errno = ENOTSUP; + if (first_result) { + mysql_free_result(first_result); + first_result = 0; + } + } else { + if (msg_verbose) + msg_info("%s:%s: successful query result from host %s", + dict_mysql->dict.type, dict_mysql->dict.name, + host->hostname); + event_request_timer(dict_mysql_event, (void *) host, + IDLE_CONN_INTV); + break; } } - return res; + *result = first_result; + return (query_error == 0); } /* @@ -564,7 +670,7 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) msg_fatal("dict_mysql: insufficient memory"); if (dict_mysql->option_file) mysql_options(host->db, MYSQL_READ_DEFAULT_FILE, dict_mysql->option_file); - if (dict_mysql->option_group) + 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 || @@ -573,9 +679,9 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) dict_mysql->tls_key_file, dict_mysql->tls_cert_file, dict_mysql->tls_CAfile, dict_mysql->tls_CApath, dict_mysql->tls_ciphers); -#if MYSQL_VERSION_ID >= 50023 +#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT) if (dict_mysql->tls_verify_cert != -1) - mysql_options(host->db, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + mysql_options(host->db, DICT_MYSQL_SSL_VERIFY_SERVER_CERT, &dict_mysql->tls_verify_cert); #endif #endif @@ -586,7 +692,7 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) dict_mysql->dbname, host->port, (host->type == TYPEUNIX ? host->name : 0), - 0)) { + CLIENT_MULTI_RESULTS)) { if (msg_verbose) msg_info("dict_mysql: successful connection to host %s", host->hostname); @@ -633,17 +739,18 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf) dict_mysql->dbname = cfg_get_str(p, "dbname", "", 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", 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); dict_mysql->tls_CApath = cfg_get_str(p, "tls_CApath", NULL, 0, 0); dict_mysql->tls_ciphers = cfg_get_str(p, "tls_ciphers", NULL, 0, 0); -#if MYSQL_VERSION_ID >= 50023 +#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); /* * XXX: The default should be non-zero for safety, but that is not @@ -730,13 +837,13 @@ DICT *dict_mysql_open(const char *name, int open_flags, int dict_flags) #endif dict_mysql->pldb = plmysql_init(dict_mysql->hosts); if (dict_mysql->pldb == NULL) - msg_fatal("couldn't intialize pldb!\n"); + msg_fatal("couldn't initialize pldb!\n"); dict_mysql->dict.owner = cfg_get_owner(dict_mysql->parser); return (DICT_DEBUG (&dict_mysql->dict)); } /* - * plmysql_init - initalize a MYSQL database. + * plmysql_init - initialize a MYSQL database. * Return NULL on failure, or a PLMYSQL * on success. */ static PLMYSQL *plmysql_init(ARGV *hosts) diff --git a/external/ibm-public/postfix/dist/src/global/dict_pgsql.c b/external/ibm-public/postfix/dist/src/global/dict_pgsql.c index 6bfab486805..7af6c0cd033 100644 --- a/external/ibm-public/postfix/dist/src/global/dict_pgsql.c +++ b/external/ibm-public/postfix/dist/src/global/dict_pgsql.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_pgsql.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: dict_pgsql.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -66,7 +66,7 @@ /* List of domains the queries should be restricted to. If /* specified, only FQDN addresses whose domain parts matching this /* list will be queried against the SQL database. Lookups for -/* partial addresses are also supressed. This can significantly +/* partial addresses are also suppressed. This can significantly /* reduce the query load on the server. /* .IP result_format /* The format used to expand results from queries. Substitutions @@ -162,7 +162,6 @@ #include "argv.h" #include "vstring.h" #include "split_at.h" -#include "find_inet.h" #include "myrand.h" #include "events.h" #include "stringops.h" @@ -182,6 +181,7 @@ #define TYPEUNIX (1<<0) #define TYPEINET (1<<1) +#define TYPECONNSTRING (1<<2) #define RETRY_CONN_MAX 100 #define RETRY_CONN_INTV 60 /* 1 minute */ @@ -192,7 +192,7 @@ typedef struct { char *hostname; char *name; char *port; - unsigned type; /* TYPEUNIX | TYPEINET */ + unsigned type; /* TYPEUNIX | TYPEINET | TYPECONNSTRING */ unsigned stat; /* STATUNTRIED | STATFAIL | STATCUR */ time_t ts; /* used for attempting reconnection */ } HOST; @@ -243,7 +243,7 @@ static void dict_pgsql_quote(DICT *dict, const char *name, VSTRING *result) HOST *active_host = dict_pgsql->active_host; char *myname = "dict_pgsql_quote"; size_t len = strlen(name); - size_t buflen = 2 * len + 1; + size_t buflen; int err = 1; if (active_host == 0) @@ -253,9 +253,11 @@ static void dict_pgsql_quote(DICT *dict, const char *name, VSTRING *result) * We won't get arithmetic overflows in 2*len + 1, because Postfix input * keys have reasonable size limits, better safe than sorry. */ - if (buflen <= len) - msg_panic("%s: arithmetic overflow in 2*%lu+1", - myname, (unsigned long) len); + if (len > (SSIZE_T_MAX - VSTRING_LEN(result) - 1) / 2) + msg_panic("%s: arithmetic overflow in %lu+2*%lu+1", + myname, (unsigned long) VSTRING_LEN(result), + (unsigned long) len); + buflen = 2 * len + 1; /* * XXX Workaround: stop further processing when PQescapeStringConn() @@ -346,6 +348,19 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) dict->error = 0; /* + * Don't frustrate future attempts to make Postfix UTF-8 transparent. + */ +#ifdef SNAPSHOT + if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 + && !valid_utf8_string(name, strlen(name))) { + if (msg_verbose) + msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", + myname, dict_pgsql->parser->name, name); + return (0); + } +#endif + + /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { @@ -469,7 +484,8 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, /* 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, TYPEINET)) != NULL || + (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTRING)) != NULL) { if (msg_verbose) msg_info("%s: found active connection to host %s", myname, host->hostname); @@ -485,7 +501,9 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, ((host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL, TYPEUNIX)) != NULL || (host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL, - TYPEINET)) != NULL)) { + TYPEINET)) != NULL || + (host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL, + TYPECONNSTRING)) != NULL)) { if (msg_verbose) msg_info("%s: attempting to connect to host %s", myname, host->hostname); @@ -624,9 +642,13 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, */ static void plpgsql_connect_single(HOST *host, char *dbname, char *username, char *password) { - if ((host->db = PQsetdbLogin(host->name, host->port, NULL, NULL, - dbname, username, password)) == NULL - || PQstatus(host->db) != CONNECTION_OK) { + if (host->type == TYPECONNSTRING) { + host->db = PQconnectdb(host->name); + } else { + host->db = PQsetdbLogin(host->name, host->port, NULL, NULL, + dbname, username, 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); @@ -637,6 +659,18 @@ static void plpgsql_connect_single(HOST *host, char *dbname, char *username, cha host->hostname); /* + * The only legitimate encodings for Internet mail are ASCII and UTF-8. + */ +#ifdef SNAPSHOT + if (PQsetClientEncoding(host->db, "UTF8") != 0) { + msg_warn("dict_pgsql: cannot set the encoding to UTF8, skipping %s", + host->hostname); + plpgsql_down_host(host); + return; + } +#else + + /* * XXX Postfix does not send multi-byte characters. The following piece * of code is an explicit statement of this fact, and the database server * should not accept multi-byte information after this point. @@ -647,6 +681,7 @@ static void plpgsql_connect_single(HOST *host, char *dbname, char *username, cha plpgsql_down_host(host); return; } +#endif /* Success. */ host->stat = STATACTIVE; } @@ -778,12 +813,12 @@ DICT *dict_pgsql_open(const char *name, int open_flags, int dict_flags) dict_pgsql->active_host = 0; dict_pgsql->pldb = plpgsql_init(dict_pgsql->hosts); if (dict_pgsql->pldb == NULL) - msg_fatal("couldn't intialize pldb!\n"); + msg_fatal("couldn't initialize pldb!\n"); dict_pgsql->dict.owner = cfg_get_owner(dict_pgsql->parser); return (DICT_DEBUG (&dict_pgsql->dict)); } -/* plpgsql_init - initalize a PGSQL database */ +/* plpgsql_init - initialize a PGSQL database */ static PLPGSQL *plpgsql_init(ARGV *hosts) { @@ -814,24 +849,37 @@ static HOST *host_init(const char *hostname) host->ts = 0; /* - * Ad-hoc parsing code. Expect "unix:pathname" or "inet:host:port", where - * both "inet:" and ":port" are optional. + * Modern syntax: "postgresql://connection-info". */ - if (strncmp(d, "unix:", 5) == 0 || strncmp(d, "inet:", 5) == 0) - d += 5; - host->name = mystrdup(d); - host->port = split_at_right(host->name, ':'); - - /* This is how PgSQL distinguishes between UNIX and INET: */ - if (host->name[0] && host->name[0] != '/') - host->type = TYPEINET; - else - host->type = TYPEUNIX; + if (strncmp(d, "postgresql:", 11) == 0) { + host->type = TYPECONNSTRING; + host->name = mystrdup(d); + host->port = 0; + } + /* + * Historical syntax: "unix:/pathname" and "inet:host:port". Strip the + * "unix:" and "inet:" prefixes. Look at the first character, which is + * how PgSQL historically distinguishes between UNIX and INET. + */ + else { + if (strncmp(d, "unix:", 5) == 0 || strncmp(d, "inet:", 5) == 0) + d += 5; + host->name = mystrdup(d); + if (host->name[0] && host->name[0] != '/') { + host->type = TYPEINET; + host->port = split_at_right(host->name, ':'); + } else { + host->type = TYPEUNIX; + host->port = 0; + } + } if (msg_verbose > 1) msg_info("%s: host=%s, port=%s, type=%s", myname, host->name, host->port ? host->port : "", - host->type == TYPEUNIX ? "unix" : "inet"); + host->type == TYPEUNIX ? "unix" : + host->type == TYPEINET ? "inet" : + "uri"); return host; } diff --git a/external/ibm-public/postfix/dist/src/global/ehlo_mask.c b/external/ibm-public/postfix/dist/src/global/ehlo_mask.c index 92f1a1888b4..fbcd51f71a3 100644 --- a/external/ibm-public/postfix/dist/src/global/ehlo_mask.c +++ b/external/ibm-public/postfix/dist/src/global/ehlo_mask.c @@ -1,4 +1,4 @@ -/* $NetBSD: ehlo_mask.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: ehlo_mask.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -21,6 +21,7 @@ /* #define EHLO_MASK_ENHANCEDSTATUSCODES (1<<10) /* #define EHLO_MASK_DSN (1<<11) /* #define EHLO_MASK_SMTPUTF8 (1<<12) +/* #define EHLO_MASK_CHUNKING (1<<13) /* #define EHLO_MASK_SILENT (1<<15) /* /* int ehlo_mask(keyword_list) @@ -48,6 +49,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library.*/ @@ -79,6 +85,8 @@ static const NAME_MASK ehlo_mask_table[] = { "ENHANCEDSTATUSCODES", EHLO_MASK_ENHANCEDSTATUSCODES, "DSN", EHLO_MASK_DSN, "EHLO_MASK_SMTPUTF8", EHLO_MASK_SMTPUTF8, + "SMTPUTF8", EHLO_MASK_SMTPUTF8, + "CHUNKING", EHLO_MASK_CHUNKING, "SILENT-DISCARD", EHLO_MASK_SILENT, /* XXX In-band signaling */ 0, }; diff --git a/external/ibm-public/postfix/dist/src/global/ehlo_mask.h b/external/ibm-public/postfix/dist/src/global/ehlo_mask.h index 8c53c7c7fc9..d65150a8ee0 100644 --- a/external/ibm-public/postfix/dist/src/global/ehlo_mask.h +++ b/external/ibm-public/postfix/dist/src/global/ehlo_mask.h @@ -1,4 +1,4 @@ -/* $NetBSD: ehlo_mask.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: ehlo_mask.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _EHLO_MASK_H_INCLUDED_ #define _EHLO_MASK_H_INCLUDED_ @@ -30,6 +30,7 @@ #define EHLO_MASK_ENHANCEDSTATUSCODES (1<<10) #define EHLO_MASK_DSN (1<<11) #define EHLO_MASK_SMTPUTF8 (1<<12) +#define EHLO_MASK_CHUNKING (1<<13) #define EHLO_MASK_SILENT (1<<15) extern int ehlo_mask(const char *); @@ -44,6 +45,11 @@ extern const char *str_ehlo_mask(int); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/haproxy_srvr.c b/external/ibm-public/postfix/dist/src/global/haproxy_srvr.c index 96b6099e26b..c71ebb572d7 100644 --- a/external/ibm-public/postfix/dist/src/global/haproxy_srvr.c +++ b/external/ibm-public/postfix/dist/src/global/haproxy_srvr.c @@ -1,4 +1,4 @@ -/* $NetBSD: haproxy_srvr.c,v 1.1.1.2 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: haproxy_srvr.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/haproxy_srvr.h b/external/ibm-public/postfix/dist/src/global/haproxy_srvr.h index 91cb5a62297..ce79ae8b2e2 100644 --- a/external/ibm-public/postfix/dist/src/global/haproxy_srvr.h +++ b/external/ibm-public/postfix/dist/src/global/haproxy_srvr.h @@ -1,4 +1,4 @@ -/* $NetBSD: haproxy_srvr.h,v 1.1.1.2 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: haproxy_srvr.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _HAPROXY_SRVR_H_INCLUDED_ #define _HAPROXY_SRVR_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/header_body_checks.c b/external/ibm-public/postfix/dist/src/global/header_body_checks.c index 89572efe5a3..bf616608750 100644 --- a/external/ibm-public/postfix/dist/src/global/header_body_checks.c +++ b/external/ibm-public/postfix/dist/src/global/header_body_checks.c @@ -1,4 +1,4 @@ -/* $NetBSD: header_body_checks.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: header_body_checks.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -156,6 +156,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -283,12 +288,16 @@ static char *hbc_action(void *context, HBC_CALL_BACKS *cb, } return ((char *) line); } + if (STREQUAL(cmd, "STRIP", cmd_len)) { + cb->logger(context, "strip", where, line, cmd_args); + return (HBC_CHECKS_STAT_IGNORE); + } /* Allow and ignore optional text after the action. */ if (STREQUAL(cmd, "IGNORE", cmd_len)) /* XXX Not logged for compatibility with cleanup(8). */ return (HBC_CHECKS_STAT_IGNORE); - + if (STREQUAL(cmd, "DUNNO", cmd_len) /* preferred */ ||STREQUAL(cmd, "OK", cmd_len)) /* compatibility */ return ((char *) line); diff --git a/external/ibm-public/postfix/dist/src/global/info_log_addr_form.c b/external/ibm-public/postfix/dist/src/global/info_log_addr_form.c index f5b405dce58..7efbda07ddf 100644 --- a/external/ibm-public/postfix/dist/src/global/info_log_addr_form.c +++ b/external/ibm-public/postfix/dist/src/global/info_log_addr_form.c @@ -1,4 +1,4 @@ -/* $NetBSD: info_log_addr_form.c,v 1.1.1.1 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: info_log_addr_form.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/info_log_addr_form.h b/external/ibm-public/postfix/dist/src/global/info_log_addr_form.h index 757d7a36a59..98eeafd1f6f 100644 --- a/external/ibm-public/postfix/dist/src/global/info_log_addr_form.h +++ b/external/ibm-public/postfix/dist/src/global/info_log_addr_form.h @@ -1,4 +1,4 @@ -/* $NetBSD: info_log_addr_form.h,v 1.1.1.1 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: info_log_addr_form.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _INFO_LOG_ADDR_FORM_H_INCLUDED_ #define _INFO_LOG_ADDR_FORM_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/log_adhoc.c b/external/ibm-public/postfix/dist/src/global/log_adhoc.c index 5f7b375313e..9fa0ffe2aaf 100644 --- a/external/ibm-public/postfix/dist/src/global/log_adhoc.c +++ b/external/ibm-public/postfix/dist/src/global/log_adhoc.c @@ -1,4 +1,4 @@ -/* $NetBSD: log_adhoc.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: log_adhoc.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -29,9 +29,8 @@ /* Time stamps from different message delivery stages /* and session reuse count. /* .IP recipient -/* Recipient information. See recipient_list(3). -/* .IP sender -/* The sender envelope address. +/* Recipient information, see recipient_list(3). The address +/* is formatted by the info_log_addr_form(3) routines. /* .IP relay /* Host we could (not) talk to. /* .IP status @@ -50,6 +49,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -68,6 +72,7 @@ #include <log_adhoc.h> #include <mail_params.h> +#include <info_log_addr_form.h> /* * Don't use "struct timeval" for time differences; use explicit signed @@ -105,10 +110,12 @@ void log_adhoc(const char *id, MSG_STATS *stats, RECIPIENT *recipient, * First, critical information that identifies the nature of the * transaction. */ - vstring_sprintf(buf, "%s: to=<%s>", id, recipient->address); + vstring_sprintf(buf, "%s: to=<%s>", id, + info_log_addr_form_recipient(recipient->address)); if (recipient->orig_addr && *recipient->orig_addr && strcasecmp_utf8(recipient->address, recipient->orig_addr) != 0) - vstring_sprintf_append(buf, ", orig_to=<%s>", recipient->orig_addr); + vstring_sprintf_append(buf, ", orig_to=<%s>", + info_log_addr_form_recipient(recipient->orig_addr)); vstring_sprintf_append(buf, ", relay=%s", relay); if (stats->reuse_count > 0) vstring_sprintf_append(buf, ", conn_use=%d", stats->reuse_count + 1); diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.c b/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.c index 5854a187e88..beaaeeb2551 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.c +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_crunch.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_addr_crunch.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -8,22 +8,40 @@ /* SYNOPSIS /* #include <mail_addr_crunch.h> /* -/* ARGV *mail_addr_crunch(string, extension) +/* ARGV *mail_addr_crunch_ext_to_int(string, extension) /* const char *string; /* const char *extension; +/* +/* ARGV *mail_addr_crunch_opt(string, extension, in_form, out_form) +/* const char *string; +/* const char *extension; +/* int in_form; +/* int out_form; /* DESCRIPTION -/* mail_addr_crunch() parses a string with zero or more addresses, +/* mail_addr_crunch_*() parses a string with zero or more addresses, /* rewrites each address to canonical form, and optionally applies -/* an address extension to each resulting address. Input and result -/* are in external (quoted) format. The caller is expected to pass -/* the result to argv_free(). +/* an address extension to each resulting address. The caller is +/* expected to pass the result to argv_free(). +/* +/* With mail_addr_crunch_ext_to_int(), the string is in external +/* form, and the result is in internal form. This API minimizes +/* the number of conversions between internal and external forms. +/* +/* mail_addr_crunch_opt() gives more control, at the cost of +/* additional conversions between internal and external forms. /* /* Arguments: /* .IP string -/* A string with zero or more addresses in RFC 822 (external) format. +/* A string with zero or more addresses in external (quoted) +/* form, or in the form specified with the in_form argument. /* .IP extension /* A null pointer, or an address extension (including the recipient /* address delimiter) that is propagated to all result addresses. +/* This is in internal (unquoted) form. +/* .IP in_form +/* .IP out_form +/* Input and output address forms, either MA_FORM_INTERNAL +/* (unquoted form) or MA_FORM_EXTERNAL (quoted form). /* DIAGNOSTICS /* Fatal error: out of memory. /* SEE ALSO @@ -38,6 +56,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -55,12 +78,15 @@ #include <tok822.h> #include <canon_addr.h> +#include <quote_822_local.h> #include <mail_addr_crunch.h> /* mail_addr_crunch - break string into addresses, optionally add extension */ -ARGV *mail_addr_crunch(const char *string, const char *extension) +ARGV *mail_addr_crunch_opt(const char *string, const char *extension, + int in_form, int out_form) { + VSTRING *intern_addr = vstring_alloc(100); VSTRING *extern_addr = vstring_alloc(100); VSTRING *canon_addr = vstring_alloc(100); ARGV *argv = argv_alloc(1); @@ -76,6 +102,14 @@ ARGV *mail_addr_crunch(const char *string, const char *extension) #define STR(x) vstring_str(x) /* + * Optionally convert input from internal form. + */ + if (in_form == MA_FORM_INTERNAL) { + quote_822_local(extern_addr, string); + string = STR(extern_addr); + } + + /* * Parse the string, rewrite each address to canonical form, and convert * the result to external (quoted) form. Optionally apply the extension * to each address found. @@ -86,27 +120,37 @@ ARGV *mail_addr_crunch(const char *string, const char *extension) if (*string == 0 || strcmp(string, "<>") == 0) string = "\"\""; tree = tok822_parse(string); + /* string->extern_addr would be invalidated by tok822_externalize() */ + string = 0; addr_list = tok822_grep(tree, TOK822_ADDR); for (tpp = addr_list; *tpp; tpp++) { tok822_externalize(extern_addr, tpp[0]->head, TOK822_STR_DEFL); canon_addr_external(canon_addr, STR(extern_addr)); + unquote_822_local(intern_addr, STR(canon_addr)); if (extension) { - VSTRING_SPACE(canon_addr, extlen + 1); - if ((ratsign = strrchr(STR(canon_addr), '@')) == 0) { - vstring_strcat(canon_addr, extension); + VSTRING_SPACE(intern_addr, extlen + 1); + if ((ratsign = strrchr(STR(intern_addr), '@')) == 0) { + vstring_strcat(intern_addr, extension); } else { memmove(ratsign + extlen, ratsign, strlen(ratsign) + 1); memcpy(ratsign, extension, extlen); - VSTRING_SKIP(canon_addr); + VSTRING_SKIP(intern_addr); } } - argv_add(argv, STR(canon_addr), ARGV_END); + /* Optionally convert output to external form. */ + if (out_form == MA_FORM_EXTERNAL) { + quote_822_local(extern_addr, STR(intern_addr)); + argv_add(argv, STR(extern_addr), ARGV_END); + } else { + argv_add(argv, STR(intern_addr), ARGV_END); + } } argv_terminate(argv); myfree((void *) addr_list); tok822_free_tree(tree); vstring_free(canon_addr); vstring_free(extern_addr); + vstring_free(intern_addr); return (argv); } @@ -123,30 +167,66 @@ ARGV *mail_addr_crunch(const char *string, const char *extension) #include <mail_conf.h> #include <mail_params.h> +/* canon_addr_external - surrogate to avoid trivial-rewrite dependency */ + +VSTRING *canon_addr_external(VSTRING *result, const char *addr) +{ + return (vstring_strcpy(result, addr)); +} + +static int get_addr_form(const char *prompt, VSTRING *buf) +{ + int addr_form; + + if (prompt) { + vstream_printf("%s: ", prompt); + vstream_fflush(VSTREAM_OUT); + } + if (vstring_get_nonl(buf, VSTREAM_IN) == VSTREAM_EOF) + exit(0); + if ((addr_form = mail_addr_form_from_string(STR(buf))) < 0) + msg_fatal("bad address form: %s", STR(buf)); + return (addr_form); +} + int main(int unused_argc, char **unused_argv) { VSTRING *extension = vstring_alloc(1); VSTRING *buf = vstring_alloc(1); ARGV *argv; char **cpp; + int do_prompt = isatty(0); + int in_form; + int out_form; mail_conf_read(); if (chdir(var_queue_dir) < 0) msg_fatal("chdir %s: %m", var_queue_dir); - vstream_printf("extension: (CR for none): "); - vstream_fflush(VSTREAM_OUT); + in_form = get_addr_form(do_prompt ? "input form" : 0, buf); + out_form = get_addr_form(do_prompt ? "output form" : 0, buf); + if (do_prompt) { + vstream_printf("extension: (CR for none): "); + vstream_fflush(VSTREAM_OUT); + } if (vstring_get_nonl(extension, VSTREAM_IN) == VSTREAM_EOF) exit(0); - vstream_printf("print strings to be translated, one per line\n"); - vstream_fflush(VSTREAM_OUT); + if (do_prompt) { + vstream_printf("print strings to be translated, one per line\n"); + vstream_fflush(VSTREAM_OUT); + } while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { - argv = mail_addr_crunch(STR(buf), VSTRING_LEN(extension) ? STR(extension) : 0); + argv = mail_addr_crunch_opt(STR(buf), (VSTRING_LEN(extension) ? + STR(extension) : 0), + in_form, out_form); for (cpp = argv->argv; *cpp; cpp++) - vstream_printf(" %s\n", *cpp); + vstream_printf("|%s|\n", *cpp); vstream_fflush(VSTREAM_OUT); + argv_free(argv); } + vstring_free(extension); + vstring_free(buf); return (0); } diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.h b/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.h index 015d321c902..56b212c39ea 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.h +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_crunch.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_crunch.h,v 1.1.1.2 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_addr_crunch.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_ADDR_CRUNCH_H_INCLUDED_ #define _MAIL_ADDR_CRUNCH_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_find.c b/external/ibm-public/postfix/dist/src/global/mail_addr_find.c index a4a4fef62f7..83efa6568b5 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_find.c +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_find.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_find.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_addr_find.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -8,34 +8,75 @@ /* SYNOPSIS /* #include <mail_addr_find.h> /* +/* const char *mail_addr_find_int_to_ext(maps, address, extension) +/* MAPS *maps; +/* const char *address; +/* char **extension; +/* +/* const char *mail_addr_find_opt(maps, address, extension, in_form, +/* query_form, out_form, strategy) +/* MAPS *maps; +/* const char *address; +/* char **extension; +/* int in_form; +/* int in_form; +/* int out_form; +/* int strategy; +/* LEGACY SUPPORT /* const char *mail_addr_find(maps, address, extension) /* MAPS *maps; /* const char *address; /* char **extension; +/* +/* const char *mail_addr_find_to_internal(maps, address, extension) +/* MAPS *maps; +/* const char *address; +/* char **extension; +/* +/* const char *mail_addr_find_strategy(maps, address, extension) +/* MAPS *maps; +/* const char *address; +/* char **extension; +/* int strategy; /* DESCRIPTION -/* mail_addr_find() searches the specified maps for an entry with as +/* mail_addr_find*() searches the specified maps for an entry with as /* key the specified address, and derivations from that address. /* It is up to the caller to specify its case sensitivity /* preferences when it opens the maps. /* The result is overwritten upon each call. /* -/* An address that is in the form \fIuser\fR matches itself. +/* In the lookup table, the key is expected to be in external +/* form (as produced with the postmap command) and the value is +/* expected to be in external (quoted) form if it is an email +/* address. Override these assumptions with the query_form +/* and out_form arguments. +/* +/* With mail_addr_find_int_to_ext(), the specified address is in +/* internal (unquoted) form, the query is made in external (quoted) +/* form, and the result is in the form found in the table (it is +/* not necessarily an email address). This version minimizes +/* internal/external (unquoted/quoted) conversions of the input, +/* query, extension, or result. +/* +/* mail_addr_find_opt() gives more control, at the cost of +/* additional conversions between internal and external forms. +/* In particular, output conversion to internal form assumes +/* that the lookup result is an email address. +/* +/* mail_addr_find() is used by legacy code that historically searched +/* with internal-form queries. The input is in internal form. It +/* searches with external-form queries first, and falls back to +/* internal-form queries if no result was found and the external +/* and internal forms differ. The result is external form (i.e. no +/* conversion). +/* +/* mail_addr_find_to_internal() is like mail_addr_find() but assumes +/* that the lookup result is one external-form email address, +/* and converts it to internal form. +/* +/* mail_addr_find_strategy() is like mail_addr_find() but overrides +/* the default search strategy for full and partial addresses. /* -/* Given an address of the form \fIuser@domain\fR, the following -/* lookups are done in the given order until one returns a result: -/* .IP user@domain -/* Look up the entire address. -/* .IP user -/* Look up \fIuser\fR when \fIdomain\fR is equal to $myorigin, -/* when \fIdomain\fR matches $mydestination, or when it matches -/* $inet_interfaces or $proxy_interfaces. -/* .IP @domain -/* Look for an entry that matches the domain specified in \fIaddress\fR. -/* .PP -/* With address extension enabled, the table lookup order is: -/* \fIuser+extension\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR, -/* \fIuser+extension\fR, \fIuser\fR, and @\fIdomain\fR. -/* .PP /* Arguments: /* .IP maps /* Dictionary search path (see maps(3)). @@ -46,13 +87,59 @@ /* the address of a dynamic memory copy of the address extension /* that had to be chopped off in order to match the lookup tables. /* The copy includes the recipient address delimiter. +/* The copy is in internal (unquoted) form. /* The caller is expected to pass the copy to myfree(). +/* .IP query_form +/* The address form to use for database queries: one of +/* MA_FORM_INTERNAL (unquoted form), MA_FORM_EXTERNAL (quoted form), +/* MA_FORM_EXTERNAL_FIRST (external form, then internal form if the +/* external and internal forms differ), or MA_FORM_INTERNAL_FIRST +/* (internal form, then external form if the internal and external +/* forms differ). +/* .IP in_form .IP out_form +/* Input and output address forms, one of MA_FORM_INTERNAL (unquoted +/* form), or MA_FORM_EXTERNAL (quoted form). +/* .IP strategy +/* The lookup strategy for full and partial addresses, specified +/* as the binary OR of one or more of the following. These lookups +/* are implemented in the order as listed below. +/* .RS +/* .IP MA_FIND_DEFAULT +/* A convenience alias for (MA_FIND_FULL | +/* MA_FIND_NOEXT | MA_FIND_LOCALPART_IF_LOCAL | +/* MA_FIND_AT_DOMAIN). +/* .IP MA_FIND_FULL +/* Look up the full email address. +/* .IP MA_FIND_NOEXT +/* If no match was found, and the address has a localpart extension, +/* look up the address after removing the extension. +/* .IP MA_FIND_LOCALPART_IF_LOCAL +/* If no match was found, and the domain matches myorigin, +/* mydestination, or any inet_interfaces or proxy_interfaces IP +/* address, look up the localpart. If no match was found, and the +/* address has a localpart extension, repeat the same query after +/* removing the extension unless MA_FIND_NOEXT is specified. +/* .IP MA_FIND_LOCALPART_AT_IF_LOCAL +/* As above, but using the localpart@ instead. +/* .IP MA_FIND_AT_DOMAIN +/* If no match was found, look up the @domain without localpart. +/* .IP MA_FIND_DOMAIN +/* If no match was found, look up the domain without localpart. +/* .IP MA_FIND_PDMS +/* When used with MA_FIND_DOMAIN, the domain also matches subdomains. +/* .IP MA_FIND_PDDMDS +/* When used with MA_FIND_DOMAIN, dot-domain also matches +/* dot-subdomains. +/* .IP MA_FIND_LOCALPART_AT +/* If no match was found, look up the localpart@, regardless of +/* the domain content. +/* .RE /* DIAGNOSTICS -/* The maps->error value is non-zero when the lookup -/* should be tried again. +/* The maps->error value is non-zero when the lookup failed due to +/* a non-permanent error. /* SEE ALSO -/* maps(3), multi-dictionary search -/* resolve_local(3), recognize local system +/* maps(3), multi-dictionary search resolve_local(3), recognize +/* local system /* LICENSE /* .ad /* .fi @@ -62,6 +149,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -72,6 +164,7 @@ /* Utility library. */ #include <msg.h> +#include <name_mask.h> #include <dict.h> #include <stringops.h> #include <mymalloc.h> @@ -83,79 +176,291 @@ #include <strip_addr.h> #include <mail_addr_find.h> #include <resolve_local.h> +#include <quote_822_local.h> /* Application-specific. */ #define STR vstring_str -/* mail_addr_find - map a canonical address */ +#ifdef TEST + +static const NAME_MASK strategy_table[] = { + "full", MA_FIND_FULL, + "noext", MA_FIND_NOEXT, + "localpart_if_local", MA_FIND_LOCALPART_IF_LOCAL, + "localpart_at_if_local", MA_FIND_LOCALPART_AT_IF_LOCAL, + "at_domain", MA_FIND_AT_DOMAIN, + "domain", MA_FIND_DOMAIN, + "pdms", MA_FIND_PDMS, + "pddms", MA_FIND_PDDMDS, + "localpart_at", MA_FIND_LOCALPART_AT, + "default", MA_FIND_DEFAULT, + 0, -1, +}; + +/* strategy_from_string - symbolic strategy flags to internal form */ + +static int strategy_from_string(const char *strategy_string) +{ + return (name_mask_delim_opt("strategy_from_string", strategy_table, + strategy_string, "|", + NAME_MASK_WARN | NAME_MASK_ANY_CASE)); +} + +/* strategy_to_string - internal form to symbolic strategy flags */ + +static const char *strategy_to_string(VSTRING *res_buf, int strategy_mask) +{ + static VSTRING *my_buf; + + if (res_buf == 0 && (res_buf = my_buf) == 0) + res_buf = my_buf = vstring_alloc(20); + return (str_name_mask_opt(res_buf, "strategy_to_string", + strategy_table, strategy_mask, + NAME_MASK_WARN | NAME_MASK_PIPE)); +} + +#endif + + /* + * Specify what keys are partial or full, to avoid matching partial + * addresses with regular expressions. + */ +#define FULL 0 +#define PARTIAL DICT_FLAG_FIXED + +/* find_addr - helper to search maps with the right query form */ + +static const char *find_addr(MAPS *path, const char *address, int flags, + int with_domain, int query_form, VSTRING *ext_addr_buf) +{ + const char *result; + +#define SANS_DOMAIN 0 +#define WITH_DOMAIN 1 + + switch (query_form) { + + /* + * Query with external-form (quoted) address. The code looks a bit + * unusual to emphasize the symmetry with the other cases. + */ + case MA_FORM_EXTERNAL: + case MA_FORM_EXTERNAL_FIRST: + quote_822_local_flags(ext_addr_buf, address, + with_domain ? QUOTE_FLAG_DEFAULT : + QUOTE_FLAG_DEFAULT | QUOTE_FLAG_BARE_LOCALPART); + result = maps_find(path, STR(ext_addr_buf), flags); + if (result != 0 || path->error != 0 + || query_form != MA_FORM_EXTERNAL_FIRST + || strcmp(address, STR(ext_addr_buf)) == 0) + break; + result = maps_find(path, address, flags); + break; + + /* + * Query with internal-form (unquoted) address. The code looks a bit + * unusual to emphasize the symmetry with the other cases. + */ + case MA_FORM_INTERNAL: + case MA_FORM_INTERNAL_FIRST: + result = maps_find(path, address, flags); + if (result != 0 || path->error != 0 + || query_form != MA_FORM_INTERNAL_FIRST) + break; + quote_822_local_flags(ext_addr_buf, address, + with_domain ? QUOTE_FLAG_DEFAULT : + QUOTE_FLAG_DEFAULT | QUOTE_FLAG_BARE_LOCALPART); + if (strcmp(address, STR(ext_addr_buf)) == 0) + break; + result = maps_find(path, STR(ext_addr_buf), flags); + break; + + /* + * Can't happen. + */ + default: + msg_panic("mail_addr_find: bad query_form: %d", query_form); + } + return (result); +} + +/* find_local - search on localpart info */ + +static const char *find_local(MAPS *path, char *ratsign, int rats_offs, + char *int_full_key, char *int_bare_key, + int query_form, char **extp, char **saved_ext, + VSTRING *ext_addr_buf) +{ + const char *myname = "mail_addr_find"; + const char *result; + int with_domain; + int saved_ch; + + /* + * This code was ripped from the middle of a function so that it can be + * reused multiple times, that's why the interface makes little sense. + */ + with_domain = rats_offs ? WITH_DOMAIN : SANS_DOMAIN; + + saved_ch = *(unsigned char *) (ratsign + rats_offs); + *(ratsign + rats_offs) = 0; + result = find_addr(path, int_full_key, PARTIAL, with_domain, + query_form, ext_addr_buf); + *(ratsign + rats_offs) = saved_ch; + if (result == 0 && path->error == 0 && int_bare_key != 0) { + if ((ratsign = strrchr(int_bare_key, '@')) == 0) + msg_panic("%s: bare key botch", myname); + saved_ch = *(unsigned char *) (ratsign + rats_offs); + *(ratsign + rats_offs) = 0; + if ((result = find_addr(path, int_bare_key, PARTIAL, with_domain, + query_form, ext_addr_buf)) != 0 + && extp != 0) { + *extp = *saved_ext; + *saved_ext = 0; + } + *(ratsign + rats_offs) = saved_ch; + } + return result; +} + +/* mail_addr_find_opt - map a canonical address */ -const char *mail_addr_find(MAPS *path, const char *address, char **extp) +const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp, + int in_form, int query_form, + int out_form, int strategy) { const char *myname = "mail_addr_find"; + VSTRING *ext_addr_buf = 0; + VSTRING *int_addr_buf = 0; + const char *int_addr; + static VSTRING *int_result = 0; const char *result; char *ratsign = 0; - char *full_key; - char *bare_key; + char *int_full_key; + char *int_bare_key; char *saved_ext; int rc = 0; /* + * Optionally convert the address from external form. + */ + if (in_form == MA_FORM_EXTERNAL) { + int_addr_buf = vstring_alloc(100); + unquote_822_local(int_addr_buf, address); + int_addr = STR(int_addr_buf); + } else { + int_addr = address; + } + if (query_form == MA_FORM_EXTERNAL_FIRST + || query_form == MA_FORM_EXTERNAL) + ext_addr_buf = vstring_alloc(100); + + /* * Initialize. */ - full_key = mystrdup(address); - if (*var_rcpt_delim == 0) { - bare_key = saved_ext = 0; + int_full_key = mystrdup(int_addr); + if (*var_rcpt_delim == 0 || (strategy & MA_FIND_NOEXT) == 0) { + int_bare_key = saved_ext = 0; } else { - bare_key = strip_addr(full_key, &saved_ext, var_rcpt_delim); + /* XXX This could be done after user+foo@domain fails. */ + int_bare_key = + strip_addr_internal(int_full_key, &saved_ext, var_rcpt_delim); } /* * Try user+foo@domain and user@domain. - * - * Specify what keys are partial or full, to avoid matching partial - * addresses with regular expressions. */ -#define FULL 0 -#define PARTIAL DICT_FLAG_FIXED + if ((strategy & MA_FIND_FULL) != 0) { + result = find_addr(path, int_full_key, FULL, WITH_DOMAIN, + query_form, ext_addr_buf); + } else { + result = 0; + path->error = 0; + } - if ((result = maps_find(path, full_key, FULL)) == 0 && path->error == 0 - && bare_key != 0 && (result = maps_find(path, bare_key, PARTIAL)) != 0 + if (result == 0 && path->error == 0 && int_bare_key != 0 + && (result = find_addr(path, int_bare_key, PARTIAL, WITH_DOMAIN, + query_form, ext_addr_buf)) != 0 && extp != 0) { *extp = saved_ext; saved_ext = 0; } /* - * Try user+foo@$myorigin, user+foo@$mydestination or - * user+foo@[${proxy,inet}_interfaces]. Then try with +foo stripped off. + * Try user+foo if the domain matches user+foo@$myorigin, + * user+foo@$mydestination or user+foo@[${proxy,inet}_interfaces]. Then + * try with +foo stripped off. */ if (result == 0 && path->error == 0 - && (ratsign = strrchr(full_key, '@')) != 0 - && (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0 - || (rc = resolve_local(ratsign + 1)) > 0)) { - *ratsign = 0; - result = maps_find(path, full_key, PARTIAL); - if (result == 0 && path->error == 0 && bare_key != 0) { - if ((ratsign = strrchr(bare_key, '@')) == 0) - msg_panic("%s: bare key botch", myname); - *ratsign = 0; - if ((result = maps_find(path, bare_key, PARTIAL)) != 0 && extp != 0) { - *extp = saved_ext; - saved_ext = 0; - } - } - *ratsign = '@'; - } else if (rc < 0) - path->error = rc; + && (ratsign = strrchr(int_full_key, '@')) != 0 + && (strategy & (MA_FIND_LOCALPART_IF_LOCAL + | MA_FIND_LOCALPART_AT_IF_LOCAL)) != 0) { + if (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0 + || (rc = resolve_local(ratsign + 1)) > 0) { + if ((strategy & MA_FIND_LOCALPART_IF_LOCAL) != 0) + result = find_local(path, ratsign, 0, int_full_key, + int_bare_key, query_form, extp, &saved_ext, + ext_addr_buf); + if (result == 0 && path->error == 0 + && (strategy & MA_FIND_LOCALPART_AT_IF_LOCAL) != 0) + result = find_local(path, ratsign, 1, int_full_key, + int_bare_key, query_form, extp, &saved_ext, + ext_addr_buf); + } else if (rc < 0) + path->error = rc; + } /* * Try @domain. */ - if (result == 0 && path->error == 0 && ratsign) + if (result == 0 && path->error == 0 && ratsign != 0 + && (strategy & MA_FIND_AT_DOMAIN) != 0) result = maps_find(path, ratsign, PARTIAL); /* + * Try domain (optionally, subdomains). + */ + if (result == 0 && path->error == 0 && ratsign != 0 + && (strategy & MA_FIND_DOMAIN) != 0) { + const char *name; + const char *next; + + if ((strategy & MA_FIND_PDMS) && (strategy & MA_FIND_PDDMDS)) + msg_warn("mail_addr_find_opt: do not specify both " + "MA_FIND_PDMS and MA_FIND_PDDMDS"); + for (name = ratsign + 1; *name != 0; name = next) { + if ((result = maps_find(path, name, PARTIAL)) != 0 + || path->error != 0 + || (strategy & (MA_FIND_PDMS | MA_FIND_PDDMDS)) == 0 + || (next = strchr(name + 1, '.')) == 0) + break; + if ((strategy & MA_FIND_PDDMDS) == 0) + next++; + } + } + + /* + * Try localpart@ even if the domain is not local. + */ + 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); + + /* + * Optionally convert the result to internal form. The lookup result is + * supposed to be one external-form email address. + */ + if (result != 0 && out_form == MA_FORM_INTERNAL) { + if (int_result == 0) + int_result = vstring_alloc(100); + unquote_822_local(int_result, result); + result = STR(int_result); + } + + /* * Clean up. */ if (msg_verbose) @@ -163,59 +468,205 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp) result ? result : path->error ? "(try again)" : "(not found)"); - myfree(full_key); - if (bare_key) - myfree(bare_key); + myfree(int_full_key); + if (int_bare_key) + myfree(int_bare_key); if (saved_ext) myfree(saved_ext); - + if (int_addr_buf) + vstring_free(int_addr_buf); + if (ext_addr_buf) + vstring_free(ext_addr_buf); return (result); } #ifdef TEST /* - * Proof-of-concept test program. Read an address from stdin, and spit out - * the lookup result. + * Proof-of-concept test program. Read an address and expected results from + * stdin, and warn about any discrepancies. */ +#include <ctype.h> +#include <stdlib.h> + #include <vstream.h> #include <vstring_vstream.h> -#include <mail_conf.h> +#include <mail_params.h> + +static NORETURN usage(const char *progname) +{ + msg_fatal("usage: %s [-v]", progname); +} int main(int argc, char **argv) { VSTRING *buffer = vstring_alloc(100); - MAPS *path; + char *bp; + MAPS *path = 0; const char *result; char *extent; + char *cmd; + char *in_field; + char *query_field; + char *out_field; + char *strategy_field; + char *key_field; + char *expect_res; + char *expect_ext; + int in_form; + int query_form; + int out_form; + int strategy_flags; + int ch; + int errs = 0; /* * Parse JCL. */ - if (argc != 2) - msg_fatal("usage: %s database", argv[0]); - msg_verbose = 1; + while ((ch = GETOPT(argc, argv, "v")) > 0) { + switch (ch) { + case 'v': + msg_verbose++; + break; + default: + usage(argv[0]); + } + } + if (argc != optind) + usage(argv[0]); /* * Initialize. */ - mail_conf_read(); - path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX \ - |DICT_FLAG_UTF8_REQUEST); +#define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0) + + mail_params_init(); + + /* + * TODO: move these assignments into the read/eval loop. + */ + UPDATE(var_rcpt_delim, "+"); + UPDATE(var_mydomain, "localdomain"); + UPDATE(var_myorigin, "localdomain"); + UPDATE(var_mydest, "localhost.localdomain"); while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { - extent = 0; - result = mail_addr_find(path, STR(buffer), &extent); - vstream_printf("%s -> %s (%s)\n", STR(buffer), result ? result : - path->error ? "(try again)" : - "(not found)", extent ? extent : "null extension"); - vstream_fflush(VSTREAM_OUT); - if (extent) - myfree(extent); + bp = STR(buffer); + if (msg_verbose) + msg_info("> %s", bp); + if ((cmd = mystrtok(&bp, CHARS_SPACE)) == 0 || *cmd == '#') + continue; + while (ISSPACE(*bp)) + bp++; + + /* + * Visible comment. + */ + if (strcmp(cmd, "echo") == 0) { + vstream_printf("%s\n", bp); + } + + /* + * Open maps. + */ + else if (strcmp(cmd, "maps") == 0) { + if (path) + maps_free(path); + path = maps_create(argv[0], bp, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST); + vstream_printf("%s\n", bp); + continue; + } + + /* + * Lookup and verify. + */ + else if (path && strcmp(cmd, "test") == 0) { + + /* + * Parse the input and expectations. + */ + /* internal, external. */ + if ((in_field = mystrtok(&bp, ":")) == 0) + msg_fatal("no input form"); + if ((in_form = mail_addr_form_from_string(in_field)) < 0) + msg_fatal("bad input form: '%s'", in_field); + if ((query_field = mystrtok(&bp, ":")) == 0) + msg_fatal("no query form"); + /* internal, external, external-first. */ + if ((query_form = mail_addr_form_from_string(query_field)) < 0) + msg_fatal("bad query form: '%s'", query_field); + if ((out_field = mystrtok(&bp, ":")) == 0) + msg_fatal("no output form"); + /* internal, external. */ + if ((out_form = mail_addr_form_from_string(out_field)) < 0) + msg_fatal("bad output form: '%s'", out_field); + if ((strategy_field = mystrtok(&bp, ":")) == 0) + msg_fatal("no strategy field"); + if ((strategy_flags = strategy_from_string(strategy_field)) < 0) + msg_fatal("bad strategy field: '%s'", strategy_field); + if ((key_field = mystrtok(&bp, ":")) == 0) + msg_fatal("no search key"); + expect_res = mystrtok(&bp, ":"); + expect_ext = mystrtok(&bp, ":"); + if (mystrtok(&bp, ":") != 0) + msg_fatal("garbage after extension field"); + + /* + * Lookups. + */ + extent = 0; + result = mail_addr_find_opt(path, key_field, &extent, + in_form, query_form, out_form, + strategy_flags); + vstream_printf("%s:%s -%s-> %s:%s (%s)\n", + in_field, key_field, query_field, out_field, result ? result : + path->error ? "(try again)" : + "(not found)", extent ? extent : "null extension"); + vstream_fflush(VSTREAM_OUT); + + /* + * Enforce expectations. + */ + if (expect_res && result) { + if (strcmp(expect_res, result) != 0) { + msg_warn("expect result '%s' but got '%s'", expect_res, result); + errs = 1; + if (expect_ext && extent) { + if (strcmp(expect_ext, extent) != 0) + msg_warn("expect extension '%s' but got '%s'", + expect_ext, extent); + errs = 1; + } else if (expect_ext && !extent) { + msg_warn("expect extension '%s' but got none", expect_ext); + errs = 1; + } else if (!expect_ext && extent) { + msg_warn("expect no extension but got '%s'", extent); + errs = 1; + } + } + } else if (expect_res && !result) { + msg_warn("expect result '%s' but got none", expect_res); + errs = 1; + } else if (!expect_res && result) { + msg_warn("expected no result but got '%s'", result); + errs = 1; + } + vstream_fflush(VSTREAM_OUT); + if (extent) + myfree(extent); + } + + /* + * Unknown request. + */ + else { + msg_warn("bad request: %s", cmd); + } } vstring_free(buffer); maps_free(path); - return (0); + return (errs != 0); } #endif diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_find.h b/external/ibm-public/postfix/dist/src/global/mail_addr_find.h index 8518735fdd2..60768209d6c 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_find.h +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_find.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_find.h,v 1.1.1.2 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_addr_find.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_ADDR_FIND_H_INCLUDED_ #define _MAIL_ADDR_FIND_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_form.c b/external/ibm-public/postfix/dist/src/global/mail_addr_form.c index a562684d002..9f0b3feb33d 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_form.c +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_form.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_form.c,v 1.1.1.1 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_addr_form.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_form.h b/external/ibm-public/postfix/dist/src/global/mail_addr_form.h index 9382656c901..b4c4b1ec858 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_form.h +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_form.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_form.h,v 1.1.1.1 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_addr_form.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_ADDR_FORM_H_INCLUDED_ #define _MAIL_ADDR_FORM_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_map.c b/external/ibm-public/postfix/dist/src/global/mail_addr_map.c index 0cd9e331c96..a415bf05ce5 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_map.c +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_map.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_map.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_addr_map.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -8,21 +8,35 @@ /* SYNOPSIS /* #include <mail_addr_map.h> /* -/* ARGV *mail_addr_map(path, address, propagate) +/* ARGV *mail_addr_map_internal(path, address, propagate) /* MAPS *path; /* const char *address; /* int propagate; +/* +/* ARGV *mail_addr_map_opt(path, address, propagate, in_form, +/* query_form, out_form) +/* MAPS *path; +/* const char *address; +/* int propagate; +/* int in_form; +/* int query_form; +/* int out_form; /* DESCRIPTION -/* mail_addr_map() returns the translation for the named address, -/* or a null pointer if none is found. The result is in canonical -/* external (quoted) form. The search is case insensitive. +/* mail_addr_map_*() returns the translation for the named address, +/* or a null pointer if none is found. +/* +/* With mail_addr_map_internal(), the search address and results +/* are in internal (unquoted) form. +/* +/* mail_addr_map_opt() gives more control, at the cost of additional +/* conversions between internal and external forms. /* /* When the \fBpropagate\fR argument is non-zero, /* address extensions that aren't explicitly matched in the lookup /* table are propagated to the result addresses. The caller is -/* expected to pass the result to argv_free(). +/* expected to pass the lookup result to argv_free(). /* -/* Lookups are performed by mail_addr_find(). When the result has the +/* Lookups are performed by mail_addr_find_*(). When the result has the /* form \fI@otherdomain\fR, the result is the original user in /* \fIotherdomain\fR. /* @@ -30,12 +44,23 @@ /* .IP path /* Dictionary search path (see maps(3)). /* .IP address -/* The address to be looked up. +/* The address to be looked up in external (quoted) form, or +/* in the form specified with the in_form argument. +/* .IP query_form +/* Database query address forms, either MA_FORM_INTERNAL (unquoted +/* form), MA_FORM_EXTERNAL (quoted form), MA_FORM_EXTERNAL_FIRST +/* (external, then internal if the forms differ), or +/* MA_FORM_INTERNAL_FIRST (internal, then external if the forms +/* differ). +/* .IP in_form +/* .IP out_form +/* Input and output address forms, either MA_FORM_INTERNAL (unquoted +/* form) or MA_FORM_EXTERNAL (quoted form). /* DIAGNOSTICS /* Warnings: map lookup returns a non-address result. /* /* The path->error value is non-zero when the lookup -/* should be tried again. +/* failed with a non-permanent error. /* SEE ALSO /* mail_addr_find(3), mail address matching /* mail_addr_crunch(3), mail address parsing and rewriting @@ -48,6 +73,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -65,6 +95,7 @@ /* Global library. */ +#include <quote_822_local.h> #include <mail_addr_find.h> #include <mail_addr_crunch.h> #include <mail_addr_map.h> @@ -76,7 +107,8 @@ /* mail_addr_map - map a canonical address */ -ARGV *mail_addr_map(MAPS *path, const char *address, int propagate) +ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate, + int in_form, int query_form, int out_form) { VSTRING *buffer = 0; const char *myname = "mail_addr_map"; @@ -85,36 +117,61 @@ ARGV *mail_addr_map(MAPS *path, const char *address, int propagate) char *extension = 0; ARGV *argv = 0; int i; + VSTRING *int_address = 0; + VSTRING *ext_address = 0; + const char *int_addr; + + /* + * Optionally convert input from external form. We prefer internal-form + * input to avoid unnecessary input conversion in mail_addr_find_opt(). + */ + if (in_form == MA_FORM_EXTERNAL) { + int_address = vstring_alloc(100); + unquote_822_local(int_address, address); + int_addr = STR(int_address); + in_form = MA_FORM_INTERNAL; + } else { + int_addr = address; + } /* * Look up the full address; if no match is found, look up the address * with the extension stripped off, and remember the unmatched extension. */ - if ((string = mail_addr_find(path, address, &extension)) != 0) { + if ((string = mail_addr_find_opt(path, int_addr, &extension, + in_form, query_form, + MA_FORM_EXTERNAL, + MA_FIND_DEFAULT)) != 0) { /* * Prepend the original user to @otherdomain, but do not propagate - * the unmatched address extension. + * the unmatched address extension. Convert the address to external + * form just like the mail_addr_find_opt() output. */ if (*string == '@') { buffer = vstring_alloc(100); - if ((ratsign = strrchr(address, '@')) != 0) - vstring_strncpy(buffer, address, ratsign - address); + if ((ratsign = strrchr(int_addr, '@')) != 0) + vstring_strncpy(buffer, int_addr, ratsign - int_addr); else - vstring_strcpy(buffer, address); + vstring_strcpy(buffer, int_addr); if (extension) vstring_truncate(buffer, LEN(buffer) - strlen(extension)); vstring_strcat(buffer, string); - string = STR(buffer); + ext_address = vstring_alloc(2 * LEN(buffer)); + quote_822_local(ext_address, STR(buffer)); + string = STR(ext_address); } /* - * Canonicalize and externalize the result, and propagate the - * unmatched extension to each address found. + * Canonicalize the result, and propagate the unmatched extension to + * each address found. */ - argv = mail_addr_crunch(string, propagate ? extension : 0); + argv = mail_addr_crunch_opt(string, propagate ? extension : 0, + MA_FORM_EXTERNAL, out_form); if (buffer) vstring_free(buffer); + if (ext_address) + vstring_free(ext_address); if (msg_verbose) for (i = 0; i < argv->argc; i++) msg_info("%s: %s -> %d: %s", myname, address, i, argv->argv[i]); @@ -140,61 +197,333 @@ ARGV *mail_addr_map(MAPS *path, const char *address, int propagate) */ if (extension) myfree(extension); + if (int_address) + vstring_free(int_address); return (argv); } #ifdef TEST - /* - * Proof-of-concept test program. Read an address from stdin, and spit out - * the lookup result. - */ +/* + * SYNOPSIS + * mail_addr_map pass_tests | fail_tests + * DESCRIPTION + * mail_addr_map performs the specified set of built-in + * unit tests. With 'pass_tests', all tests must pass, and + * with 'fail_tests' all tests must fail. + * DIAGNOSTICS + * When a unit test fails, the program prints details of the + * failed test. + * + * The program terminates with a non-zero exit status when at + * least one test does not pass with 'pass_tests', or when at + * least one test does not fail with 'fail_tests'. + */ + +/* System library. */ + +#include <sys_defs.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> #include <unistd.h> -#include <mail_conf.h> -#include <vstream.h> -#include <vstring_vstream.h> + +/* Utility library. */ + +#include <argv.h> +#include <msg.h> +#include <mymalloc.h> +#include <vstring.h> + +/* Global library. */ + +#include <canon_addr.h> +#include <mail_addr_map.h> #include <mail_params.h> +/* Application-specific. */ + +#define STR vstring_str + +typedef struct { + const char *testname; + const char *database; + int propagate; + const char *delimiter; + int in_form; + int query_form; + int out_form; + const char *address; + const char *expect_argv[2]; + int expect_argc; +} MAIL_ADDR_MAP_TEST; + +#define DONT_PROPAGATE_UNMATCHED_EXTENSION 0 +#define DO_PROPAGATE_UNMATCHED_EXTENSION 1 +#define NO_RECIPIENT_DELIMITER "" +#define PLUS_RECIPIENT_DELIMITER "+" +#define DOT_RECIPIENT_DELIMITER "." + + /* + * All these tests must pass, so that we know that mail_addr_map_opt() works + * as intended. mail_addr_map() has always been used for maps that expect + * external-form queries, so there are no tests here for internal-form + * queries. + */ +static MAIL_ADDR_MAP_TEST pass_tests[] = { + { + "1 external -external-> external, no extension", + "inline:{ aa@example.com=bb@example.com }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "aa@example.com", + {"bb@example.com"}, 1, + }, + { + "2 external -external-> external, extension, propagation", + "inline:{ aa@example.com=bb@example.com }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "aa+ext@example.com", + {"bb+ext@example.com"}, 1, + }, + { + "3 external -external-> external, extension, no propagation, no match", + "inline:{ aa@example.com=bb@example.com }", + DONT_PROPAGATE_UNMATCHED_EXTENSION, NO_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "aa+ext@example.com", + {0}, 0, + }, + { + "4 external -external-> external, extension, full match", + "inline:{{cc+ext@example.com=dd@example.com,ee@example.com}}", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "cc+ext@example.com", + {"dd@example.com", "ee@example.com"}, 2, + }, + { + "5 external -external-> external, no extension, quoted", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "\"a a\"@example.com", + {"\"b b\"@example.com"}, 1, + }, + { + "6 external -external-> external, extension, propagation, quoted", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "\"a a+ext\"@example.com", + {"\"b b+ext\"@example.com"}, 1, + }, + { + "7 internal -external-> internal, no extension, propagation, embedded space", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_INTERNAL, MA_FORM_EXTERNAL, MA_FORM_INTERNAL, + "a a@example.com", + {"b b@example.com"}, 1, + }, + { + "8 internal -external-> internal, extension, propagation, embedded space", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_INTERNAL, MA_FORM_EXTERNAL, MA_FORM_INTERNAL, + "a a+ext@example.com", + {"b b+ext@example.com"}, 1, + }, + { + "9 internal -external-> internal, no extension, propagation, embedded space", + "inline:{ {a_a@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_INTERNAL, MA_FORM_EXTERNAL, MA_FORM_INTERNAL, + "a_a@example.com", + {"b b@example.com"}, 1, + }, + { + "10 internal -external-> internal, extension, propagation, embedded space", + "inline:{ {a_a@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_INTERNAL, MA_FORM_EXTERNAL, MA_FORM_INTERNAL, + "a_a+ext@example.com", + {"b b+ext@example.com"}, 1, + }, + { + "11 internal -external-> internal, no extension, @domain", + "inline:{ {@example.com=@example.net} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_INTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "a@a@example.com", + {"\"a@a\"@example.net"}, 1, + }, + { + "12 external -external-> external, extension, propagation", + "inline:{ aa@example.com=bb@example.com }", + DO_PROPAGATE_UNMATCHED_EXTENSION, DOT_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "aa.ext@example.com", + {"bb.ext@example.com"}, 1, + }, + 0, +}; + + /* + * All these tests must fail, so that we know that the tests work. + */ +static MAIL_ADDR_MAP_TEST fail_tests[] = { + { + "selftest 1 external -external-> external, no extension, quoted", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "\"a a\"@example.com", + {"\"bXb\"@example.com"}, 1, + }, + { + "selftest 2 external -external-> external, no extension, quoted", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "\"aXa\"@example.com", + {"\"b b\"@example.com"}, 1, + }, + { + "selftest 3 external -external-> external, no extension, quoted", + "inline:{ {\"a a\"@example.com=\"b b\"@example.com} }", + DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER, + MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, + "\"a a\"@example.com", + {0}, 0, + }, + 0, +}; + +/* canon_addr_external - surrogate to avoid trivial-rewrite dependency */ + +VSTRING *canon_addr_external(VSTRING *result, const char *addr) +{ + return (vstring_strcpy(result, addr)); +} + +static int compare(const char *testname, + const char **expect_argv, int expect_argc, + char **result_argv, int result_argc) +{ + int n; + int err = 0; + + if (expect_argc != 0 && result_argc != 0) { + for (n = 0; n < expect_argc && n < result_argc; n++) { + if (strcmp(expect_argv[n], result_argv[n]) != 0) { + msg_warn("fail test %s: expect[%d]='%s', result[%d]='%s'", + testname, n, expect_argv[n], n, result_argv[n]); + err = 1; + } + } + } + if (expect_argc != result_argc) { + msg_warn("fail test %s: expects %d results but there were %d", + testname, expect_argc, result_argc); + for (n = expect_argc; n < result_argc; n++) + msg_info("no expect to match result[%d]='%s'", n, result_argv[n]); + for (n = result_argc; n < expect_argc; n++) + msg_info("no result to match expect[%d]='%s'", n, expect_argv[n]); + err = 1; + } + return (err); +} + +static char *progname; + +static NORETURN usage(void) +{ + msg_fatal("usage: %s pass_test | fail_test", progname); +} + int main(int argc, char **argv) { - VSTRING *buffer = vstring_alloc(100); - MAPS *path; - ARGV *result; + MAIL_ADDR_MAP_TEST *test; + MAIL_ADDR_MAP_TEST *tests; + int errs = 0; + +#define UPDATE(dst, src) { if (dst) myfree(dst); dst = mystrdup(src); } /* * Parse JCL. */ - if (argc != 2) - msg_fatal("usage: %s database", argv[0]); + progname = argv[0]; + if (argc != 2) { + usage(); + } else if (strcmp(argv[1], "pass_tests") == 0) { + tests = pass_tests; + } else if (strcmp(argv[1], "fail_tests") == 0) { + tests = fail_tests; + } else { + usage(); + } /* * Initialize. */ -#define UPDATE(dst, src) { myfree(dst); dst = mystrdup(src); } - - mail_conf_read(); - msg_verbose = 1; - if (chdir(var_queue_dir) < 0) - msg_fatal("chdir %s: %m", var_queue_dir); - path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX \ - | DICT_FLAGS_UTF8_REQUEST); - while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { - msg_info("=== Address extension on, extension propagation on ==="); - UPDATE(var_rcpt_delim, "+"); - if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) - argv_free(result); - msg_info("=== Address extension on, extension propagation off ==="); - if ((result = mail_addr_map(path, STR(buffer), 0)) != 0) - argv_free(result); - msg_info("=== Address extension off ==="); - UPDATE(var_rcpt_delim, ""); - if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) + mail_params_init(); + + /* + * A read-eval-print loop, because specifying C strings with quotes and + * backslashes is painful. + */ + for (test = tests; test->testname; test++) { + ARGV *result; + int fail = 0; + + if (mail_addr_form_to_string(test->in_form) == 0) { + msg_warn("test %s: bad in_form field: %d", + test->testname, test->in_form); + fail = 1; + continue; + } + if (mail_addr_form_to_string(test->query_form) == 0) { + msg_warn("test %s: bad query_form field: %d", + test->testname, test->query_form); + fail = 1; + continue; + } + if (mail_addr_form_to_string(test->out_form) == 0) { + msg_warn("test %s: bad out_form field: %d", + test->testname, test->out_form); + fail = 1; + continue; + } + MAPS *maps = maps_create("test", test->database, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST); + + UPDATE(var_rcpt_delim, test->delimiter); + result = mail_addr_map_opt(maps, test->address, test->propagate, + test->in_form, test->query_form, test->out_form); + if (compare(test->testname, test->expect_argv, test->expect_argc, + result ? result->argv : 0, result ? result->argc : 0) != 0) { + msg_info("database = %s", test->database); + msg_info("propagate = %d", test->propagate); + msg_info("delimiter = '%s'", var_rcpt_delim); + msg_info("in_form = %s", mail_addr_form_to_string(test->in_form)); + msg_info("query_form = %s", mail_addr_form_to_string(test->query_form)); + msg_info("out_form = %s", mail_addr_form_to_string(test->out_form)); + msg_info("address = %s", test->address); + fail = 1; + } + maps_free(maps); + if (result) argv_free(result); + + /* + * It is an error if a test does not pass or fail as intended. + */ + errs += (tests == pass_tests ? fail : !fail); } - vstring_free(buffer); - maps_free(path); - return (0); + return (errs != 0); } #endif diff --git a/external/ibm-public/postfix/dist/src/global/mail_addr_map.h b/external/ibm-public/postfix/dist/src/global/mail_addr_map.h index 8ae955f6728..86719f4b003 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_addr_map.h +++ b/external/ibm-public/postfix/dist/src/global/mail_addr_map.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_addr_map.h,v 1.1.1.2 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_addr_map.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_ADDR_MAP_H_INCLUDED_ #define _MAIL_ADDR_MAP_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/mail_command_client.c b/external/ibm-public/postfix/dist/src/global/mail_command_client.c index 044c90ed46b..45aa9df5b1d 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_command_client.c +++ b/external/ibm-public/postfix/dist/src/global/mail_command_client.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_command_client.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_command_client.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -43,6 +43,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/global/mail_conf.c b/external/ibm-public/postfix/dist/src/global/mail_conf.c index a5a71415a82..779918702df 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_conf.c +++ b/external/ibm-public/postfix/dist/src/global/mail_conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_conf.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_conf.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -14,6 +14,9 @@ /* /* void mail_conf_flush() /* +/* void mail_conf_checkdir(config_dir) +/* const char *config_dir; +/* /* void mail_conf_update(name, value) /* const char *name; /* const char *value; @@ -30,8 +33,18 @@ /* const char *mail_conf_lookup_eval(name) /* const char *name; /* DESCRIPTION -/* mail_conf_suck() reads the global Postfix configuration file, and -/* stores its values into a global configuration dictionary. +/* mail_conf_suck() reads the global Postfix configuration +/* file, and stores its values into a global configuration +/* dictionary. When the configuration directory name is not +/* trusted, this function requires that the directory name is +/* authorized with the alternate_config_directories setting +/* in the default main.cf file. +/* +/* This function requires that all configuration directory +/* override mechanisms set the MAIL_CONFIG environment variable, +/* even if the override was specified via the command line. +/* This reduces the number of pathways that need to be checked +/* for possible security attacks. /* /* mail_conf_read() invokes mail_conf_suck() and assigns the values /* to global variables by calling mail_params_init(). @@ -40,6 +53,10 @@ /* This is needed in programs that read main.cf multiple times, to /* ensure that deleted parameter settings are handled properly. /* +/* mail_conf_checkdir() verifies that configuration directory +/* is authorized through settings in the default main.cf file, +/* and terminates the program if it is not. +/* /* The following routines are wrappers around the generic dictionary /* access routines. /* @@ -84,6 +101,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -111,7 +133,7 @@ /* mail_conf_checkdir - authorize non-default directory */ -static void mail_conf_checkdir(const char *config_dir) +void mail_conf_checkdir(const char *config_dir) { VSTRING *buf; VSTREAM *fp; @@ -145,9 +167,10 @@ static void mail_conf_checkdir(const char *config_dir) vstring_free(buf); if (found == 0) { - msg_error("untrusted configuration directory name: %s", config_dir); - msg_fatal("specify \"%s = %s\" in %s", - VAR_CONFIG_DIRS, config_dir, path); + msg_error("unauthorized configuration directory name: %s", config_dir); + msg_fatal("specify \"%s = %s\" or \"%s = %s\" in %s", + VAR_CONFIG_DIRS, config_dir, + VAR_MULTI_CONF_DIRS, config_dir, path); } myfree(path); } @@ -168,6 +191,16 @@ void mail_conf_suck(void) char *path; /* + * The code below requires that all configuration directory override + * mechanisms set the CONF_ENV_PATH environment variable, even if the + * override was specified via the command line. This reduces the number + * of pathways that need to be checked for possible security attacks. + * + * Note: this code necessarily runs before cleanenv() can enforce the + * import_environment scrubbing policy. + */ + + /* * Permit references to unknown configuration variable names. We rely on * a separate configuration checking tool to spot misspelled names and * other kinds of trouble. Enter the configuration directory into the @@ -181,12 +214,11 @@ void mail_conf_suck(void) set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir); /* - * If the configuration directory name comes from a different trust - * domain, require that it is listed in the default main.cf file. + * If the configuration directory name comes from an untrusted source, + * require that it is listed in the default main.cf file. */ if (strcmp(var_config_dir, DEF_CONFIG_DIR) != 0 /* non-default */ - && safe_getenv(CONF_ENV_PATH) == 0 /* non-default */ - && geteuid() != 0) /* untrusted */ + && unsafe()) /* untrusted env and cli */ mail_conf_checkdir(var_config_dir); path = concatenate(var_config_dir, "/", "main.cf", (char *) 0); if (dict_load_file_xt(CONFIG_DICT, path) == 0) diff --git a/external/ibm-public/postfix/dist/src/global/mail_conf.h b/external/ibm-public/postfix/dist/src/global/mail_conf.h index 333b7e4cae3..1fc112802b7 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_conf.h +++ b/external/ibm-public/postfix/dist/src/global/mail_conf.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_conf.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_conf.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_CONF_H_INCLUDED_ #define _MAIL_CONF_H_INCLUDED_ @@ -38,6 +38,7 @@ extern void mail_conf_read(void); extern void mail_conf_suck(void); extern void mail_conf_flush(void); +extern void mail_conf_checkdir(const char *); extern void mail_conf_update(const char *, const char *); extern const char *mail_conf_lookup(const char *); @@ -240,6 +241,11 @@ extern void get_mail_conf_nbool_fn_table(const CONFIG_NBOOL_FN_TABLE *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/mail_conf_int.c b/external/ibm-public/postfix/dist/src/global/mail_conf_int.c index db1597cd5e7..7cf54674b31 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_conf_int.c +++ b/external/ibm-public/postfix/dist/src/global/mail_conf_int.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_conf_int.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_conf_int.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -84,6 +84,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -179,9 +184,21 @@ int get_mail_conf_int_fn(const char *name, stupid_indent_int defval, void set_mail_conf_int(const char *name, int value) { + const char myname[] = "set_mail_conf_int"; char buf[BUFSIZ]; /* yeah! crappy code! */ +#ifndef NO_SNPRINTF + ssize_t ret; + + ret = snprintf(buf, sizeof(buf), "%d", value); + if (ret < 0) + msg_panic("%s: output error for %%d", myname); + if (ret >= sizeof(buf)) + msg_panic("%s: output for %%d exceeds space %ld", + myname, (long) sizeof(buf)); +#else sprintf(buf, "%d", value); /* yeah! more crappy code! */ +#endif mail_conf_update(name, buf); } diff --git a/external/ibm-public/postfix/dist/src/global/mail_conf_long.c b/external/ibm-public/postfix/dist/src/global/mail_conf_long.c index 077effda1d4..a0ba0f9edee 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_conf_long.c +++ b/external/ibm-public/postfix/dist/src/global/mail_conf_long.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_conf_long.c,v 1.1.1.3 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_conf_long.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mail_conf_nint.c b/external/ibm-public/postfix/dist/src/global/mail_conf_nint.c index 1348b5c5a8e..5200d3cffb9 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_conf_nint.c +++ b/external/ibm-public/postfix/dist/src/global/mail_conf_nint.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_conf_nint.c,v 1.1.1.3 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_conf_nint.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mail_conf_time.c b/external/ibm-public/postfix/dist/src/global/mail_conf_time.c index b3c2af32ee2..b4bcc0c92e4 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_conf_time.c +++ b/external/ibm-public/postfix/dist/src/global/mail_conf_time.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_conf_time.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_conf_time.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -195,9 +195,21 @@ void set_mail_conf_time(const char *name, const char *value) void set_mail_conf_time_int(const char *name, int value) { + const char myname[] = "set_mail_conf_time_int"; char buf[BUFSIZ]; /* yeah! crappy code! */ +#ifndef NO_SNPRINTF + ssize_t ret; + + ret = snprintf(buf, sizeof(buf), "%ds", value); + if (ret < 0) + msg_panic("%s: output error for %%ds", myname); + if (ret >= sizeof(buf)) + msg_panic("%s: output for %%ds exceeds space %ld", + myname, (long) sizeof(buf)); +#else sprintf(buf, "%ds", value); /* yeah! more crappy code! */ +#endif mail_conf_update(name, buf); } diff --git a/external/ibm-public/postfix/dist/src/global/mail_copy.c b/external/ibm-public/postfix/dist/src/global/mail_copy.c index bd5ba95d241..6261eab04ee 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_copy.c +++ b/external/ibm-public/postfix/dist/src/global/mail_copy.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_copy.c,v 1.1.1.4 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_copy.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mail_error.c b/external/ibm-public/postfix/dist/src/global/mail_error.c index 27354f4246e..ac447469acc 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_error.c +++ b/external/ibm-public/postfix/dist/src/global/mail_error.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_error.c,v 1.1.1.3 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: mail_error.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mail_params.c b/external/ibm-public/postfix/dist/src/global/mail_params.c index 1e24b7db37c..675892907a1 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_params.c +++ b/external/ibm-public/postfix/dist/src/global/mail_params.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_params.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_params.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -38,6 +38,7 @@ /* int var_event_drain; /* int var_bundle_rcpt; /* char *var_procname; +/* char *var_servname; /* int var_pid; /* int var_ipc_timeout; /* char *var_pid_dir; @@ -129,8 +130,11 @@ /* int var_smtputf8_enable /* int var_strict_smtputf8; /* char *var_smtputf8_autoclass; +/* int var_idna2003_compat; /* int var_compat_level; /* char *var_drop_hdrs; +/* char *var_info_log_addr_form; +/* bool var_enable_orcpt; /* /* void mail_params_init() /* @@ -139,10 +143,17 @@ /* int warn_compat_break_app_dot_mydomain; /* int warn_compat_break_smtputf8_enable; /* int warn_compat_break_chroot; +/* int warn_compat_break_relay_restrictions; /* /* int warn_compat_break_relay_domains; /* int warn_compat_break_flush_domains; /* int warn_compat_break_mynetworks_style; +/* +/* char *var_maillog_file; +/* char *var_maillog_file_pfxs; +/* char *var_maillog_file_comp; +/* char *var_maillog_file_stamp; +/* char *var_postlog_service; /* DESCRIPTION /* This module (actually the associated include file) defines /* the names and defaults of all mail configuration parameters. @@ -169,6 +180,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -198,6 +214,7 @@ #include <inet_proto.h> #include <vstring_vstream.h> #include <iostuff.h> +#include <midna_domain.h> /* Global library. */ @@ -242,6 +259,7 @@ int var_event_drain; int var_idle_limit; int var_bundle_rcpt; char *var_procname; +char *var_servname; int var_pid; int var_ipc_timeout; char *var_pid_dir; @@ -334,8 +352,17 @@ char *var_dsn_filter; int var_smtputf8_enable; int var_strict_smtputf8; char *var_smtputf8_autoclass; +int var_idna2003_compat; int var_compat_level; char *var_drop_hdrs; +char *var_info_log_addr_form; +bool var_enable_orcpt; + +char *var_maillog_file; +char *var_maillog_file_pfxs; +char *var_maillog_file_comp; +char *var_maillog_file_stamp; +char *var_postlog_service; const char null_format_string[1] = ""; @@ -352,6 +379,7 @@ int warn_compat_break_mynetworks_style; int warn_compat_break_app_dot_mydomain; int warn_compat_break_smtputf8_enable; int warn_compat_break_chroot; +int warn_compat_break_relay_restrictions; /* check_myhostname - lookup hostname and validate */ @@ -605,6 +633,10 @@ static void check_legacy_defaults(void) if (mail_conf_lookup(VAR_MYNETWORKS) == 0 && mail_conf_lookup(VAR_MYNETWORKS_STYLE) == 0) warn_compat_break_mynetworks_style = 1; + } else { /* for 'postfix reload' */ + warn_compat_break_relay_domains = 0; + warn_compat_break_flush_domains = 0; + warn_compat_break_mynetworks_style = 0; } /* @@ -623,6 +655,17 @@ static void check_legacy_defaults(void) if (mail_conf_lookup(VAR_SMTPUTF8_ENABLE) == 0) warn_compat_break_smtputf8_enable = 1; warn_compat_break_chroot = 1; + + /* + * Grandfathered in to help sites migrating from Postfix <2.10. + */ + if (mail_conf_lookup(VAR_RELAY_CHECKS) == 0) + warn_compat_break_relay_restrictions = 1; + } else { /* for 'postfix reload' */ + warn_compat_break_app_dot_mydomain = 0; + warn_compat_break_smtputf8_enable = 0; + warn_compat_break_chroot = 0; + warn_compat_break_relay_restrictions = 0; } } @@ -643,6 +686,11 @@ void mail_params_init() /* multi_instance_wrapper may have dependencies but not dependents. */ VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0, VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0, + VAR_MAILLOG_FILE, DEF_MAILLOG_FILE, &var_maillog_file, 0, 0, + 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_POSTLOG_SERVICE, DEF_POSTLOG_SERVICE, &var_postlog_service, 1, 0, 0, }; static const CONFIG_BOOL_TABLE first_bool_defaults[] = { @@ -654,6 +702,7 @@ void mail_params_init() static const CONFIG_NBOOL_TABLE first_nbool_defaults[] = { /* read and process the following before opening tables. */ VAR_SMTPUTF8_ENABLE, DEF_SMTPUTF8_ENABLE, &var_smtputf8_enable, + VAR_IDNA2003_COMPAT, DEF_IDNA2003_COMPAT, &var_idna2003_compat, 0, }; static const CONFIG_STR_FN_TABLE function_str_defaults[] = { @@ -714,6 +763,7 @@ void mail_params_init() VAR_DSN_FILTER, DEF_DSN_FILTER, &var_dsn_filter, 0, 0, VAR_SMTPUTF8_AUTOCLASS, DEF_SMTPUTF8_AUTOCLASS, &var_smtputf8_autoclass, 1, 0, VAR_DROP_HDRS, DEF_DROP_HDRS, &var_drop_hdrs, 0, 0, + VAR_INFO_LOG_ADDR_FORM, DEF_INFO_LOG_ADDR_FORM, &var_info_log_addr_form, 1, 0, 0, }; static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = { @@ -776,6 +826,7 @@ void mail_params_init() VAR_MULTI_ENABLE, DEF_MULTI_ENABLE, &var_multi_enable, VAR_LONG_QUEUE_IDS, DEF_LONG_QUEUE_IDS, &var_long_queue_ids, VAR_STRICT_SMTPUTF8, DEF_STRICT_SMTPUTF8, &var_strict_smtputf8, + VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt, 0, }; const char *cp; @@ -793,7 +844,7 @@ void mail_params_init() */ get_mail_conf_str_table(first_str_defaults); - if (!msg_syslog_facility(var_syslog_facility)) + if (!msg_syslog_set_facility(var_syslog_facility)) msg_fatal("file %s/%s: parameter %s: unrecognized value: %s", var_config_dir, MAIN_CONF_FILE, VAR_SYSLOG_FACILITY, var_syslog_facility); @@ -820,6 +871,8 @@ void mail_params_init() msg_warn("%s is true, but EAI support is not compiled in", VAR_SMTPUTF8_ENABLE); var_smtputf8_enable = 0; +#else + midna_domain_transitional = var_idna2003_compat; #endif util_utf8_enable = var_smtputf8_enable; @@ -923,10 +976,6 @@ void mail_params_init() msg_fatal("%s parameter setting must not contain multiple values: %s", VAR_MYORIGIN, var_myorigin); - if (var_relayhost[strcspn(var_relayhost, CHARS_COMMA_SP)]) - msg_fatal("%s parameter setting must not contain multiple values: %s", - VAR_RELAYHOST, var_relayhost); - /* * One more sanity check. */ diff --git a/external/ibm-public/postfix/dist/src/global/mail_params.h b/external/ibm-public/postfix/dist/src/global/mail_params.h index 8882703a9e1..6661a3829cb 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_params.h +++ b/external/ibm-public/postfix/dist/src/global/mail_params.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_params.h,v 1.15 2017/02/15 16:42:16 christos Exp $ */ +/* $NetBSD: mail_params.h,v 1.16 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_PARAMS_H_INCLUDED_ #define _MAIL_PARAMS_H_INCLUDED_ @@ -18,6 +18,14 @@ */ typedef int bool; +#ifdef USE_TLS +#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */ +#include <openssl/objects.h> /* SN_* and NID_* macros */ +#if OPENSSL_VERSION_NUMBER < 0x1000200fUL +#error "OpenSSL releases prior to 1.0.2 are no longer supported" +#endif +#endif + /* * Name used when this mail system announces itself. */ @@ -52,6 +60,7 @@ extern int var_compat_level; extern int warn_compat_break_app_dot_mydomain; extern int warn_compat_break_smtputf8_enable; extern int warn_compat_break_chroot; +extern int warn_compat_break_relay_restrictions; /* Postfix 2.10. */ extern int warn_compat_break_relay_domains; extern int warn_compat_break_flush_domains; @@ -388,6 +397,16 @@ extern bool var_always_add_hdrs; extern char *var_drop_hdrs; /* + * From: header format: we provide canned versions only, no Sendmail-style + * macro expansions. + */ +#define HFROM_FORMAT_NAME_STD "standard" /* From: name <address> */ +#define HFROM_FORMAT_NAME_OBS "obsolete" /* From: address (name) */ +#define VAR_HFROM_FORMAT "header_from_format" +#define DEF_HFROM_FORMAT HFROM_FORMAT_NAME_STD +extern char *var_hfrom_format; + + /* * Standards violation: allow/permit RFC 822-style addresses in SMTP * commands. */ @@ -396,7 +415,7 @@ extern char *var_drop_hdrs; extern bool var_strict_rfc821_env; /* - * Standards violation: send "250 AUTH=list" in order to accomodate clients + * Standards violation: send "250 AUTH=list" in order to accommodate clients * that implement an old version of the protocol. */ #define VAR_BROKEN_AUTH_CLNTS "broken_sasl_auth_clients" @@ -1278,6 +1297,10 @@ extern bool var_smtpd_tls_req_ccert; #define DEF_SMTPD_TLS_CCERT_VD 9 extern int var_smtpd_tls_ccert_vd; +#define VAR_SMTPD_TLS_CHAIN_FILES "smtpd_tls_chain_files" +#define DEF_SMTPD_TLS_CHAIN_FILES "" +extern char *var_smtpd_tls_chain_files; + #define VAR_SMTPD_TLS_CERT_FILE "smtpd_tls_cert_file" #define DEF_SMTPD_TLS_CERT_FILE "" extern char *var_smtpd_tls_cert_file; @@ -1347,7 +1370,7 @@ extern char *var_smtpd_tls_dh512_param_file; extern char *var_smtpd_tls_dh1024_param_file; #define VAR_SMTPD_TLS_EECDH "smtpd_tls_eecdh_grade" -#define DEF_SMTPD_TLS_EECDH "strong" +#define DEF_SMTPD_TLS_EECDH "auto" extern char *var_smtpd_tls_eecdh; #define VAR_SMTPD_TLS_LOGLEVEL "smtpd_tls_loglevel" @@ -1417,6 +1440,12 @@ extern char *var_smtp_tls_level; #define DEF_LMTP_TLS_SCERT_VD 9 extern int var_smtp_tls_scert_vd; +#define VAR_SMTP_TLS_CHAIN_FILES "smtp_tls_chain_files" +#define DEF_SMTP_TLS_CHAIN_FILES "" +#define VAR_LMTP_TLS_CHAIN_FILES "lmtp_tls_chain_files" +#define DEF_LMTP_TLS_CHAIN_FILES "" +extern char *var_smtp_tls_chain_files; + #define VAR_SMTP_TLS_CERT_FILE "smtp_tls_cert_file" #define DEF_SMTP_TLS_CERT_FILE "" #define VAR_LMTP_TLS_CERT_FILE "lmtp_tls_cert_file" @@ -1570,6 +1599,12 @@ extern char *var_smtp_tls_sec_cmatch; #define DEF_LMTP_TLS_FPT_CMATCH "" extern char *var_smtp_tls_fpt_cmatch; +#define VAR_SMTP_TLS_SNI "smtp_tls_servername" +#define DEF_SMTP_TLS_SNI "" +#define VAR_LMTP_TLS_SNI "lmtp_tls_servername" +#define DEF_LMTP_TLS_SNI "" +extern char *var_smtp_tls_sni; + #define VAR_SMTP_TLS_BLK_EARLY_MAIL_REPLY "smtp_tls_block_early_mail_reply" #define DEF_SMTP_TLS_BLK_EARLY_MAIL_REPLY 0 #define VAR_LMTP_TLS_BLK_EARLY_MAIL_REPLY "lmtp_tls_block_early_mail_reply" @@ -1647,6 +1682,19 @@ extern char *var_smtpd_snd_auth_maps; "reject_unauthenticated_sender_login_mismatch" /* + * https://tools.ietf.org/html/rfc4954#page-5 + * + * (At the time of writing of this document, 12288 octets is considered to be a + * sufficient line length limit for handling of deployed authentication + * mechanisms.) + * + * The default value is also the minimum permissible value for this parameter. + */ +#define VAR_SMTPD_SASL_RESP_LIMIT "smtpd_sasl_response_limit" +#define DEF_SMTPD_SASL_RESP_LIMIT 12288 +extern int var_smtpd_sasl_resp_limit; + + /* * SASL authentication support, SMTP client side. */ #define VAR_SMTP_SASL_ENABLE "smtp_sasl_auth_enable" @@ -1697,6 +1745,12 @@ extern char *var_smtp_sasl_tlsv_opts; #define DEF_SMTP_DUMMY_MAIL_AUTH 0 extern bool var_smtp_dummy_mail_auth; +#define VAR_LMTP_BALANCE_INET_PROTO "lmtp_balance_inet_protocols" +#define DEF_LMTP_BALANCE_INET_PROTO DEF_SMTP_BALANCE_INET_PROTO +#define VAR_SMTP_BALANCE_INET_PROTO "smtp_balance_inet_protocols" +#define DEF_SMTP_BALANCE_INET_PROTO 1 +extern bool var_smtp_balance_inet_proto; + /* * LMTP server. The soft error limit determines how many errors an LMTP * client may make before we start to slow down; the hard error limit @@ -1798,6 +1852,10 @@ extern char *var_smtp_sasl_auth_cache_name; #define DEF_LMTP_SASL_AUTH_CACHE_TIME "90d" extern int var_smtp_sasl_auth_cache_time; +#define VAR_SMTP_TCP_PORT "smtp_tcp_port" +#define DEF_SMTP_TCP_PORT "smtp" +extern char *var_smtp_tcp_port; + /* * LMTP client. Timeouts inspired by RFC 1123. The LMTP recipient limit * determines how many recipient addresses the LMTP client sends along with @@ -1901,8 +1959,11 @@ extern long var_message_limit; #define VAR_QUEUE_MINFREE "queue_minfree" #define DEF_QUEUE_MINFREE 0 -extern int var_queue_minfree; +extern long var_queue_minfree; + /* + * Light-weight content inspection. + */ #define VAR_HEADER_CHECKS "header_checks" #define DEF_HEADER_CHECKS "" extern char *var_header_checks; @@ -2055,11 +2116,20 @@ extern char *var_helo_checks; extern char *var_mail_checks; #define VAR_RELAY_CHECKS "smtpd_relay_restrictions" -#define DEF_RELAY_CHECKS PERMIT_MYNETWORKS ", " \ +#define DEF_RELAY_CHECKS "${{$compatibility_level} < {1} ? " \ + "{} : {" PERMIT_MYNETWORKS ", " \ PERMIT_SASL_AUTH ", " \ - DEFER_UNAUTH_DEST + DEFER_UNAUTH_DEST "}}" extern char *var_relay_checks; + /* + * For warn_compat_break_relay_domains check. Same as DEF_RELAY_CHECKS + * except that it evaluates to DUNNO instead of REJECT. + */ +#define FAKE_RELAY_CHECKS PERMIT_MYNETWORKS ", " \ + PERMIT_SASL_AUTH ", " \ + PERMIT_AUTH_DEST + #define VAR_RCPT_CHECKS "smtpd_recipient_restrictions" #define DEF_RCPT_CHECKS "" extern char *var_rcpt_checks; @@ -2352,7 +2422,29 @@ extern int var_local_rcpt_code; " $" VAR_HELO_CHECKS \ " $" VAR_MAIL_CHECKS \ " $" VAR_RELAY_CHECKS \ - " $" VAR_RCPT_CHECKS + " $" VAR_RCPT_CHECKS \ + " $" VAR_VRFY_SND_DEF_XPORT_MAPS \ + " $" VAR_VRFY_RELAY_MAPS \ + " $" VAR_VRFY_XPORT_MAPS \ + " $" VAR_FBCK_TRANSP_MAPS \ + " $" VAR_LMTP_EHLO_DIS_MAPS \ + " $" VAR_LMTP_PIX_BUG_MAPS \ + " $" VAR_LMTP_SASL_PASSWD \ + " $" VAR_LMTP_TLS_POLICY \ + " $" VAR_MAILBOX_CMD_MAPS \ + " $" VAR_MBOX_TRANSP_MAPS \ + " $" VAR_PSC_EHLO_DIS_MAPS \ + " $" VAR_RBL_REPLY_MAPS \ + " $" VAR_SND_DEF_XPORT_MAPS \ + " $" VAR_SND_RELAY_MAPS \ + " $" VAR_SMTP_EHLO_DIS_MAPS \ + " $" VAR_SMTP_PIX_BUG_MAPS \ + " $" VAR_SMTP_SASL_PASSWD \ + " $" VAR_SMTP_TLS_POLICY \ + " $" VAR_SMTPD_EHLO_DIS_MAPS \ + " $" VAR_SMTPD_MILTER_MAPS \ + " $" VAR_VIRT_GID_MAPS \ + " $" VAR_VIRT_UID_MAPS extern char *var_proxy_read_maps; #define VAR_PROXY_WRITE_MAPS "proxy_write_maps" @@ -2376,6 +2468,9 @@ extern char *var_proxy_write_acl; #define VAR_PROCNAME "process_name" extern char *var_procname; +#define VAR_SERVNAME "service_name" +extern char *var_servname; + #define VAR_PID "process_id" extern int var_pid; @@ -2442,7 +2537,9 @@ extern int var_fflush_refresh; * and what Postfix exports to the external world. */ #define VAR_IMPORT_ENVIRON "import_environment" -#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY LANG=C" +#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG " \ + "TZ XAUTHORITY DISPLAY LANG=C " \ + "POSTLOG_SERVICE POSTLOG_HOSTNAME" extern char *var_import_environ; #define VAR_EXPORT_ENVIRON "export_environment" @@ -2614,6 +2711,7 @@ extern int var_fault_inj_code; #ifndef DEF_OPENSSL_PATH #define DEF_OPENSSL_PATH "openssl" #endif +extern char *var_openssl_path; #define VAR_MANPAGE_DIR "manpage_directory" #ifndef DEF_MANPAGE_DIR @@ -3140,37 +3238,60 @@ extern bool var_smtp_cname_overr; /* * TLS cipherlists */ -#ifdef USE_TLS -#include <openssl/opensslv.h> -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL -#define PREFER_aNULL "aNULL:-aNULL:" -#else -#define PREFER_aNULL "" -#endif -#else -#define PREFER_aNULL "" -#endif - #define VAR_TLS_HIGH_CLIST "tls_high_cipherlist" -#define DEF_TLS_HIGH_CLIST PREFER_aNULL "HIGH:@STRENGTH" +#define DEF_TLS_HIGH_CLIST "aNULL:-aNULL:HIGH:@STRENGTH" extern char *var_tls_high_clist; #define VAR_TLS_MEDIUM_CLIST "tls_medium_cipherlist" -#define DEF_TLS_MEDIUM_CLIST PREFER_aNULL "HIGH:MEDIUM:+RC4:@STRENGTH" +#define DEF_TLS_MEDIUM_CLIST "aNULL:-aNULL:HIGH:MEDIUM:+RC4:@STRENGTH" extern char *var_tls_medium_clist; #define VAR_TLS_LOW_CLIST "tls_low_cipherlist" -#define DEF_TLS_LOW_CLIST PREFER_aNULL "HIGH:MEDIUM:LOW:+RC4:@STRENGTH" +#define DEF_TLS_LOW_CLIST "aNULL:-aNULL:HIGH:MEDIUM:LOW:+RC4:@STRENGTH" extern char *var_tls_low_clist; #define VAR_TLS_EXPORT_CLIST "tls_export_cipherlist" -#define DEF_TLS_EXPORT_CLIST PREFER_aNULL "HIGH:MEDIUM:LOW:EXPORT:+RC4:@STRENGTH" +#define DEF_TLS_EXPORT_CLIST "aNULL:-aNULL:HIGH:MEDIUM:LOW:EXPORT:+RC4:@STRENGTH" extern char *var_tls_export_clist; #define VAR_TLS_NULL_CLIST "tls_null_cipherlist" #define DEF_TLS_NULL_CLIST "eNULL:!aNULL" extern char *var_tls_null_clist; +#if defined(SN_X25519) && defined(NID_X25519) +#define DEF_TLS_EECDH_AUTO_1 SN_X25519 " " +#else +#define DEF_TLS_EECDH_AUTO_1 "" +#endif +#if defined(SN_X448) && defined(NID_X448) +#define DEF_TLS_EECDH_AUTO_2 SN_X448 " " +#else +#define DEF_TLS_EECDH_AUTO_2 "" +#endif +#if defined(SN_X9_62_prime256v1) && defined(NID_X9_62_prime256v1) +#define DEF_TLS_EECDH_AUTO_3 SN_X9_62_prime256v1 " " +#else +#define DEF_TLS_EECDH_AUTO_3 "" +#endif +#if defined(SN_secp521r1) && defined(NID_secp521r1) +#define DEF_TLS_EECDH_AUTO_4 SN_secp521r1 " " +#else +#define DEF_TLS_EECDH_AUTO_4 "" +#endif +#if defined(SN_secp384r1) && defined(NID_secp384r1) +#define DEF_TLS_EECDH_AUTO_5 SN_secp384r1 +#else +#define DEF_TLS_EECDH_AUTO_5 "" +#endif + +#define VAR_TLS_EECDH_AUTO "tls_eecdh_auto_curves" +#define DEF_TLS_EECDH_AUTO DEF_TLS_EECDH_AUTO_1 \ + DEF_TLS_EECDH_AUTO_2 \ + DEF_TLS_EECDH_AUTO_3 \ + DEF_TLS_EECDH_AUTO_4 \ + DEF_TLS_EECDH_AUTO_5 +extern char *var_tls_eecdh_auto; + #define VAR_TLS_EECDH_STRONG "tls_eecdh_strong_curve" #define DEF_TLS_EECDH_STRONG "prime256v1" extern char *var_tls_eecdh_strong; @@ -3187,20 +3308,8 @@ extern bool var_tls_preempt_clist; #define DEF_TLS_MULTI_WILDCARD 1 extern bool var_tls_multi_wildcard; - /* The tweak for CVE-2010-4180 is needed in some versions prior to 1.0.1 */ - /* The tweak for CVE-2005-2969 is needed in some versions prior to 1.0.0 */ -#if defined(USE_TLS) && (OPENSSL_VERSION_NUMBER < 0x1000100fL) -#if (OPENSSL_VERSION_NUMBER < 0x1000000fL) -#define TLS_BUG_TWEAKS "CVE-2005-2969 CVE-2010-4180" -#else -#define TLS_BUG_TWEAKS "CVE-2010-4180" -#endif -#else -#define TLS_BUG_TWEAKS "" -#endif - #define VAR_TLS_BUG_TWEAKS "tls_disable_workarounds" -#define DEF_TLS_BUG_TWEAKS TLS_BUG_TWEAKS +#define DEF_TLS_BUG_TWEAKS "" extern char *var_tls_bug_tweaks; #define VAR_TLS_SSL_OPTIONS "tls_ssl_options" @@ -3215,15 +3324,9 @@ extern char *var_tls_tkt_cipher; #define DEF_TLS_BC_PKEY_FPRINT 0 extern bool var_tls_bc_pkey_fprint; - /* - * Ordered list of DANE digest algorithms. - */ -#define TLS_DANE_AGILITY_OFF "off" -#define TLS_DANE_AGILITY_ON "on" -#define TLS_DANE_AGILITY_MAYBE "maybe" -#define VAR_TLS_DANE_AGILITY "tls_dane_digest_agility" -#define DEF_TLS_DANE_AGILITY TLS_DANE_AGILITY_ON -extern char *var_tls_dane_agility; +#define VAR_TLS_SERVER_SNI_MAPS "tls_server_sni_maps" +#define DEF_TLS_SERVER_SNI_MAPS "" +extern char *var_tls_server_sni_maps; /* * Ordered list of DANE digest algorithms. @@ -3233,13 +3336,11 @@ extern char *var_tls_dane_agility; extern char *var_tls_dane_digests; /* - * External interface for enabling trust-anchor digests, which are risky - * when the corresponding certificate is missing from the peer chain (this - * can't happen with the leaf certificate). + * The default is incompatible with pre-TLSv1.0 protocols. */ -#define VAR_TLS_DANE_TAA_DGST "tls_dane_trust_anchor_digest_enable" -#define DEF_TLS_DANE_TAA_DGST 1 -extern bool var_tls_dane_taa_dgst; +#define VAR_TLS_FAST_SHUTDOWN "tls_fast_shutdown_enable" +#define DEF_TLS_FAST_SHUTDOWN 1 +extern bool var_tls_fast_shutdown; /* * Sendmail-style mail filter support. @@ -3248,6 +3349,12 @@ extern bool var_tls_dane_taa_dgst; #define DEF_SMTPD_MILTERS "" extern char *var_smtpd_milters; +#define VAR_SMTPD_MILTER_MAPS "smtpd_milter_maps" +#define DEF_SMTPD_MILTER_MAPS "" +extern char *var_smtpd_milter_maps; + +#define SMTPD_MILTERS_DISABLE "DISABLE" + #define VAR_CLEANUP_MILTERS "non_smtpd_milters" #define DEF_CLEANUP_MILTERS "" extern char *var_cleanup_milters; @@ -3257,7 +3364,7 @@ extern char *var_cleanup_milters; extern char *var_milt_def_action; #define VAR_MILT_CONN_MACROS "milter_connect_macros" -#define DEF_MILT_CONN_MACROS "j {daemon_name} v" +#define DEF_MILT_CONN_MACROS "j {daemon_name} {daemon_addr} v _" extern char *var_milt_conn_macros; #define VAR_MILT_HELO_MACROS "milter_helo_macros" @@ -3447,7 +3554,7 @@ extern bool var_strict_mbox_owner; extern int var_inet_windowsize; /* - * Plug-in multi-instance support. Only the first two paramaters are used by + * Plug-in multi-instance support. Only the first two parameters are used by * Postfix itself; the other ones are reserved for the instance manager. */ #define VAR_MULTI_CONF_DIRS "multi_instance_directories" @@ -3614,7 +3721,7 @@ extern int var_psc_cmd_count; #define VAR_PSC_CMD_TIME "postscreen_command_time_limit" #define DEF_PSC_CMD_TIME DEF_SMTPD_TMOUT -extern char *var_psc_cmd_time; +extern int var_psc_cmd_time; #define VAR_PSC_WATCHDOG "postscreen_watchdog_timeout" #define DEF_PSC_WATCHDOG "10s" @@ -3660,6 +3767,10 @@ extern int var_psc_cconn_limit; #define DEF_PSC_REJ_FOOTER "$" VAR_SMTPD_REJ_FOOTER extern char *var_psc_rej_footer; +#define VAR_PSC_REJ_FTR_MAPS "postscreen_reject_footer_maps" +#define DEF_PSC_REJ_FTR_MAPS "$" VAR_SMTPD_REJ_FTR_MAPS +extern char *var_psc_rej_ftr_maps; + #define VAR_PSC_EXP_FILTER "postscreen_expansion_filter" #define DEF_PSC_EXP_FILTER "$" VAR_SMTPD_EXP_FILTER extern char *var_psc_exp_filter; @@ -3726,6 +3837,10 @@ extern bool var_tlsp_tls_req_ccert; #define DEF_TLSP_TLS_CCERT_VD "$" VAR_SMTPD_TLS_CCERT_VD extern int var_tlsp_tls_ccert_vd; +#define VAR_TLSP_TLS_CHAIN_FILES "tlsproxy_tls_chain_files" +#define DEF_TLSP_TLS_CHAIN_FILES "$" VAR_SMTPD_TLS_CHAIN_FILES +extern char *var_tlsp_tls_chain_files; + #define VAR_TLSP_TLS_CERT_FILE "tlsproxy_tls_cert_file" #define DEF_TLSP_TLS_CERT_FILE "$" VAR_SMTPD_TLS_CERT_FILE extern char *var_tlsp_tls_cert_file; @@ -3814,12 +3929,91 @@ extern bool var_tlsp_tls_received_header; extern bool var_tlsp_tls_set_sessid; /* + * Workaround for tlsproxy(8) pre-jail client certs/keys access. + */ +#define VAR_TLSP_CLNT_LOGLEVEL "tlsproxy_client_loglevel" +#define DEF_TLSP_CLNT_LOGLEVEL "$" VAR_SMTP_TLS_LOGLEVEL +extern char *var_tlsp_clnt_loglevel; + +#define VAR_TLSP_CLNT_LOGPARAM "tlsproxy_client_loglevel_parameter" +#define DEF_TLSP_CLNT_LOGPARAM VAR_SMTP_TLS_LOGLEVEL +extern char *var_tlsp_clnt_logparam; + +#define VAR_TLSP_CLNT_SCERT_VD "tlsproxy_client_scert_verifydepth" +#define DEF_TLSP_CLNT_SCERT_VD "$" VAR_SMTP_TLS_SCERT_VD +extern int var_tlsp_clnt_scert_vd; + +#define VAR_TLSP_CLNT_CHAIN_FILES "tlsproxy_client_chain_files" +#define DEF_TLSP_CLNT_CHAIN_FILES "$" VAR_SMTP_TLS_CHAIN_FILES +extern char *var_tlsp_clnt_chain_files; + +#define VAR_TLSP_CLNT_CERT_FILE "tlsproxy_client_cert_file" +#define DEF_TLSP_CLNT_CERT_FILE "$" VAR_SMTP_TLS_CERT_FILE +extern char *var_tlsp_clnt_cert_file; + +#define VAR_TLSP_CLNT_KEY_FILE "tlsproxy_client_key_file" +#define DEF_TLSP_CLNT_KEY_FILE "$" VAR_SMTP_TLS_KEY_FILE +extern char *var_tlsp_clnt_key_file; + +#define VAR_TLSP_CLNT_DCERT_FILE "tlsproxy_client_dcert_file" +#define DEF_TLSP_CLNT_DCERT_FILE "$" VAR_SMTP_TLS_DCERT_FILE +extern char *var_tlsp_clnt_dcert_file; + +#define VAR_TLSP_CLNT_DKEY_FILE "tlsproxy_client_dkey_file" +#define DEF_TLSP_CLNT_DKEY_FILE "$" VAR_SMTP_TLS_DKEY_FILE +extern char *var_tlsp_clnt_dkey_file; + +#define VAR_TLSP_CLNT_ECCERT_FILE "tlsproxy_client_eccert_file" +#define DEF_TLSP_CLNT_ECCERT_FILE "$" VAR_SMTP_TLS_ECCERT_FILE +extern char *var_tlsp_clnt_eccert_file; + +#define VAR_TLSP_CLNT_ECKEY_FILE "tlsproxy_client_eckey_file" +#define DEF_TLSP_CLNT_ECKEY_FILE "$" VAR_SMTP_TLS_ECKEY_FILE +extern char *var_tlsp_clnt_eckey_file; + +#define VAR_TLSP_CLNT_CAFILE "tlsproxy_client_CAfile" +#define DEF_TLSP_CLNT_CAFILE "$" VAR_SMTP_TLS_CA_FILE +extern char *var_tlsp_clnt_CAfile; + +#define VAR_TLSP_CLNT_CAPATH "tlsproxy_client_CApath" +#define DEF_TLSP_CLNT_CAPATH "$" VAR_SMTP_TLS_CA_PATH +extern char *var_tlsp_clnt_CApath; + +#define VAR_TLSP_CLNT_FPT_DGST "tlsproxy_client_fingerprint_digest" +#define DEF_TLSP_CLNT_FPT_DGST "$" VAR_SMTP_TLS_FPT_DGST +extern char *var_tlsp_clnt_fpt_dgst; + +#define VAR_TLSP_CLNT_USE_TLS "tlsproxy_client_use_tls" +#define DEF_TLSP_CLNT_USE_TLS "$" VAR_SMTP_USE_TLS +extern bool var_tlsp_clnt_use_tls; + +#define VAR_TLSP_CLNT_ENFORCE_TLS "tlsproxy_client_enforce_tls" +#define DEF_TLSP_CLNT_ENFORCE_TLS "$" VAR_SMTP_ENFORCE_TLS +extern bool var_tlsp_clnt_enforce_tls; + +#define VAR_TLSP_CLNT_LEVEL "tlsproxy_client_level" +#define DEF_TLSP_CLNT_LEVEL "$" VAR_SMTP_TLS_LEVEL +extern char *var_tlsp_clnt_level; + +#define VAR_TLSP_CLNT_PER_SITE "tlsproxy_client_per_site" +#define DEF_TLSP_CLNT_PER_SITE "$" VAR_SMTP_TLS_PER_SITE +extern char *var_tlsp_clnt_per_site; + +#define VAR_TLSP_CLNT_POLICY "tlsproxy_client_policy" +#define DEF_TLSP_CLNT_POLICY "$" VAR_SMTP_TLS_POLICY +extern char *var_tlsp_clnt_policy; + + /* * SMTPD "reject" contact info. */ #define VAR_SMTPD_REJ_FOOTER "smtpd_reject_footer" #define DEF_SMTPD_REJ_FOOTER "" extern char *var_smtpd_rej_footer; +#define VAR_SMTPD_REJ_FTR_MAPS "smtpd_reject_footer_maps" +#define DEF_SMTPD_REJ_FTR_MAPS "" +extern char *var_smtpd_rej_ftr_maps; + /* * Per-record time limit support. */ @@ -3908,6 +4102,15 @@ extern char *var_smtp_dns_re_filter; extern char *var_smtpd_dns_re_filter; /* + * Share TLS sessions through tlproxy(8). + */ +#define VAR_SMTP_TLS_CONN_REUSE "smtp_tls_connection_reuse" +#define DEF_SMTP_TLS_CONN_REUSE 0 +#define VAR_LMTP_TLS_CONN_REUSE "lmtp_tls_connection_reuse" +#define DEF_LMTP_TLS_CONN_REUSE 0 +extern bool var_smtp_tls_conn_reuse; + + /* * Location of shared-library files. * * If the files will be installed into a known directory, such as a directory @@ -3933,8 +4136,10 @@ extern char *var_meta_dir; * SMTPUTF8 support. */ #define VAR_SMTPUTF8_ENABLE "smtputf8_enable" +#ifndef DEF_SMTPUTF8_ENABLE #define DEF_SMTPUTF8_ENABLE "${{$compatibility_level} < {1} ? " \ "{no} : {yes}}" +#endif extern int var_smtputf8_enable; #define VAR_STRICT_SMTPUTF8 "strict_smtputf8" @@ -3946,6 +4151,10 @@ extern int var_strict_smtputf8; MAIL_SRC_NAME_VERIFY extern char *var_smtputf8_autoclass; +#define VAR_IDNA2003_COMPAT "enable_idna2003_compatibility" +#define DEF_IDNA2003_COMPAT "no" +extern int var_idna2003_compat; + /* * Workaround for future incompatibility. Our implementation of RFC 2308 * negative reply caching relies on the promise that res_query() and @@ -3958,6 +4167,43 @@ extern char *var_smtputf8_autoclass; #define DEF_DNS_NCACHE_TTL_FIX 0 extern bool var_dns_ncache_ttl_fix; + /* + * Logging. As systems evolve over time, logging becomes more challenging. + */ +#define VAR_MAILLOG_FILE "maillog_file" +#define DEF_MAILLOG_FILE "" +extern char *var_maillog_file; + +#define VAR_MAILLOG_FILE_PFXS "maillog_file_prefixes" +#define DEF_MAILLOG_FILE_PFXS "/var, /dev/stdout" +extern char *var_maillog_file_pfxs; + +#define VAR_MAILLOG_FILE_COMP "maillog_file_compressor" +#define DEF_MAILLOG_FILE_COMP "gzip" +extern char *var_maillog_file_comp; + +#define VAR_MAILLOG_FILE_STAMP "maillog_file_rotate_suffix" +#define DEF_MAILLOG_FILE_STAMP "%Y%M%d-%H%M%S" +extern char *var_maillog_file_stamp; + +#define VAR_POSTLOG_SERVICE "postlog_service_name" +#define DEF_POSTLOG_SERVICE MAIL_SERVICE_POSTLOG +extern char *var_postlog_service; + +#define VAR_POSTLOGD_WATCHDOG "postlogd_watchdog_timeout" +#define DEF_POSTLOGD_WATCHDOG "10s" +extern int var_postlogd_watchdog; + + /* + * Backwards compatibility for internal-form address logging. + */ +#define INFO_LOG_ADDR_FORM_NAME_EXTERNAL "external" +#define INFO_LOG_ADDR_FORM_NAME_INTERNAL "internal" + +#define VAR_INFO_LOG_ADDR_FORM "info_log_address_format" +#define DEF_INFO_LOG_ADDR_FORM INFO_LOG_ADDR_FORM_NAME_EXTERNAL +extern char *var_info_log_addr_form; + /* LICENSE /* .ad /* .fi @@ -3967,6 +4213,11 @@ extern bool var_dns_ncache_ttl_fix; /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/mail_parm_split.c b/external/ibm-public/postfix/dist/src/global/mail_parm_split.c index cbd315339ed..d699197571f 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_parm_split.c +++ b/external/ibm-public/postfix/dist/src/global/mail_parm_split.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_parm_split.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_parm_split.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -38,6 +38,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -58,14 +63,6 @@ #include <mail_params.h> #include <mail_parm_split.h> - /* - * While testing, do not terminate the program after a syntax error. - */ -#ifdef TEST -#undef msg_fatal -#define msg_fatal msg_warn -#endif - /* mail_parm_split - split list, extract {text}, errors are fatal */ ARGV *mail_parm_split(const char *name, const char *value) @@ -74,7 +71,7 @@ ARGV *mail_parm_split(const char *name, const char *value) char *saved_string = mystrdup(value); char *bp = saved_string; char *arg; - const char *err; + char *err; /* * The code that detects the error shall either signal or handle the @@ -83,8 +80,14 @@ ARGV *mail_parm_split(const char *name, const char *value) */ while ((arg = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { if (*arg == CHARS_BRACE[0] - && (err = extpar(&arg, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) + && (err = extpar(&arg, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) { +#ifndef TEST msg_fatal("%s: %s", name, err); +#else + msg_warn("%s: %s", name, err); + myfree(err); +#endif + } argv_add(argvp, arg, (char *) 0); } argv_terminate(argvp); diff --git a/external/ibm-public/postfix/dist/src/global/mail_proto.h b/external/ibm-public/postfix/dist/src/global/mail_proto.h index 41496747058..372f8f53b6f 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_proto.h +++ b/external/ibm-public/postfix/dist/src/global/mail_proto.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_proto.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_proto.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_PROTO_H_INCLUDED_ #define _MAIL_PROTO_H_INCLUDED_ @@ -62,6 +62,7 @@ #define MAIL_SERVICE_SCACHE "scache" #define MAIL_SERVICE_DNSBLOG "dnsblog" #define MAIL_SERVICE_TLSPROXY "tlsproxy" +#define MAIL_SERVICE_POSTLOG "postlog" /* * Mail source classes. Used to specify policy decisions for content @@ -164,6 +165,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_LOG_IDENT "log_ident" #define MAIL_ATTR_RWR_CONTEXT "rewrite_context" #define MAIL_ATTR_POL_CONTEXT "policy_context" +#define MAIL_ATTR_FORCED_EXPIRE "forced_expire" #define MAIL_ATTR_RWR_LOCAL "local" #define MAIL_ATTR_RWR_REMOTE "remote" @@ -244,6 +246,8 @@ extern char *mail_pathname(const char *, const char *); #define XCLIENT_PROTO "PROTO" /* client protocol */ #define XCLIENT_HELO "HELO" /* client helo */ #define XCLIENT_LOGIN "LOGIN" /* SASL login name */ +#define XCLIENT_DESTADDR "DESTADDR" /* server address */ +#define XCLIENT_DESTPORT "DESTPORT" /* server port */ #define XCLIENT_UNAVAILABLE "[UNAVAILABLE]" /* permanently unavailable */ #define XCLIENT_TEMPORARY "[TEMPUNAVAIL]" /* temporarily unavailable */ @@ -277,25 +281,6 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_SMTPUTF8 "smtputf8" /* RFC6531 support */ /* - * TLSPROXY support. - */ -#define MAIL_ATTR_REMOTE_ENDPT "remote_endpoint" /* name[addr]:port */ -#define MAIL_ATTR_ROLE "role" /* requested role */ -#define MAIL_ATTR_ROLE_SERVER "server" -#define MAIL_ATTR_ROLE_CLIENT "client" -#define MAIL_ATTR_TIMEOUT "timeout" -#define MAIL_ATTR_PEER_CN "peer_CN" -#define MAIL_ATTR_ISSUER_CN "issuer_CN" -#define MAIL_ATTR_PEER_CERT_FPT "peer_fingerprint" -#define MAIL_ATTR_PEER_PKEY_FPT "peer_pubkey_fingerprint" -#define MAIL_ATTR_PEER_STATUS "peer_status" -#define MAIL_ATTR_CIPHER_PROTOCOL "cipher_protocol" -#define MAIL_ATTR_CIPHER_NAME "cipher_name" -#define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits" -#define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits" -#define MAIL_ATTR_SERVER_ID "server_id" - - /* * SMTP reply footer support. */ #define MAIL_ATTR_SERVER_NAME "server_name" @@ -309,6 +294,11 @@ extern char *mail_pathname(const char *, const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/mail_queue.h b/external/ibm-public/postfix/dist/src/global/mail_queue.h index 175d292854d..c1935a0391f 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_queue.h +++ b/external/ibm-public/postfix/dist/src/global/mail_queue.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_queue.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_queue.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_QUEUE_H_INCLUDED_ #define _MAIL_QUEUE_H_INCLUDED_ @@ -51,6 +51,7 @@ #define MAIL_QUEUE_STAT_CORRUPT (S_IRUSR) #ifndef MAIL_QUEUE_STAT_UNTHROTTLE #define MAIL_QUEUE_STAT_UNTHROTTLE (S_IRGRP) +#define MAIL_QUEUE_STAT_EXPIRE (S_IXGRP) #endif extern struct VSTREAM *mail_queue_enter(const char *, mode_t, struct timeval *); @@ -94,7 +95,7 @@ extern int mail_queue_id_ok(const char *); * - the inode number (base 51 encoded so that it contains no 'z'). */ #define MQID_LG_SEC_BASE 52 /* seconds safe alphabet base */ -#define MQID_LG_SEC_PAD 6 /* seconds minumum field width */ +#define MQID_LG_SEC_PAD 6 /* seconds minimum field width */ #define MQID_LG_USEC_BASE 52 /* microseconds safe alphabet base */ #define MQID_LG_USEC_PAD 4 /* microseconds exact field width */ #define MQID_LG_TIME_PAD (MQID_LG_SEC_PAD + MQID_LG_USEC_PAD) @@ -184,6 +185,11 @@ extern int mail_queue_id_ok(const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif /* _MAIL_QUEUE_H_INCLUDED_ */ diff --git a/external/ibm-public/postfix/dist/src/global/mail_task.c b/external/ibm-public/postfix/dist/src/global/mail_task.c index c3e03fc01f4..a66f41a4ce3 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_task.c +++ b/external/ibm-public/postfix/dist/src/global/mail_task.c @@ -1,4 +1,4 @@ -/* $NetBSD: mail_task.c,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: mail_task.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mail_version.h b/external/ibm-public/postfix/dist/src/global/mail_version.h index d12df41a45b..7fc5a3440a9 100644 --- a/external/ibm-public/postfix/dist/src/global/mail_version.h +++ b/external/ibm-public/postfix/dist/src/global/mail_version.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_version.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_version.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAIL_VERSION_H_INCLUDED_ #define _MAIL_VERSION_H_INCLUDED_ @@ -18,12 +18,12 @@ * snapshots are called a.b-yyyymmdd, where a=major release number, b=minor * release number, c=patchlevel, and yyyymmdd is the release date: * yyyy=year, mm=month, dd=day. - * + * * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20170101" -#define MAIL_VERSION_NUMBER "3.1.4" +#define MAIL_RELEASE_DATE "20200316" +#define MAIL_VERSION_NUMBER "3.5.0" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE @@ -101,6 +101,11 @@ extern void check_mail_version(const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/maillog_client.c b/external/ibm-public/postfix/dist/src/global/maillog_client.c index 7418eda4405..00905aaa9cc 100644 --- a/external/ibm-public/postfix/dist/src/global/maillog_client.c +++ b/external/ibm-public/postfix/dist/src/global/maillog_client.c @@ -1,4 +1,4 @@ -/* $NetBSD: maillog_client.c,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: maillog_client.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/maillog_client.h b/external/ibm-public/postfix/dist/src/global/maillog_client.h index 44921292040..0b95cae016c 100644 --- a/external/ibm-public/postfix/dist/src/global/maillog_client.h +++ b/external/ibm-public/postfix/dist/src/global/maillog_client.h @@ -1,4 +1,4 @@ -/* $NetBSD: maillog_client.h,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: maillog_client.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAILLOG_CLIENT_H_INCLUDED_ #define _MAILLOG_CLIENT_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/map_search.c b/external/ibm-public/postfix/dist/src/global/map_search.c index 6d45c1570c2..24ffb517e9a 100644 --- a/external/ibm-public/postfix/dist/src/global/map_search.c +++ b/external/ibm-public/postfix/dist/src/global/map_search.c @@ -1,4 +1,4 @@ -/* $NetBSD: map_search.c,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: map_search.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/map_search.h b/external/ibm-public/postfix/dist/src/global/map_search.h index 7991bcb742c..d4ad1da42be 100644 --- a/external/ibm-public/postfix/dist/src/global/map_search.h +++ b/external/ibm-public/postfix/dist/src/global/map_search.h @@ -1,4 +1,4 @@ -/* $NetBSD: map_search.h,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: map_search.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/maps.c b/external/ibm-public/postfix/dist/src/global/maps.c index ee1a640b5e5..c4c015c4cda 100644 --- a/external/ibm-public/postfix/dist/src/global/maps.c +++ b/external/ibm-public/postfix/dist/src/global/maps.c @@ -1,4 +1,4 @@ -/* $NetBSD: maps.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: maps.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -18,6 +18,11 @@ /* const char *key; /* int flags; /* +/* const char *maps_file_find(maps, key, flags) +/* MAPS *maps; +/* const char *key; +/* int flags; +/* /* MAPS *maps_free(maps) /* MAPS *maps; /* DESCRIPTION @@ -41,6 +46,10 @@ /* for example, DICT_FLAG_FIXED | DICT_FLAG_PATTERN selects /* dictionaries that have fixed keys or pattern keys. /* +/* maps_file_find() implements maps_find() but also decodes +/* the base64 lookup result. This requires that the maps are +/* opened with DICT_FLAG_SRC_RHS_IS_FILE. +/* /* maps_free() releases storage claimed by maps_create() /* and conveniently returns a null pointer. /* @@ -191,15 +200,81 @@ const char *maps_find(MAPS *maps, const char *name, int flags) maps->title, name); msg_warn("%s should return NO RESULT in case of NOT FOUND", maps->title); - maps->error = DICT_ERR_RETRY; + maps->error = DICT_ERR_CONFIG; return (0); } if (msg_verbose) - msg_info("%s: %s: %s: %s = %s", myname, maps->title, - *map_name, name, expansion); + msg_info("%s: %s: %s: %s = %.100s%s", myname, maps->title, + *map_name, name, expansion, + strlen(expansion) > 100 ? "..." : ""); return (expansion); } else if ((maps->error = dict->error) != 0) { - msg_warn("%s:%s lookup error for \"%.100s\"", + msg_warn("%s:%s lookup error for \"%s\"", + dict->type, dict->name, name); + break; + } + } + if (msg_verbose) + msg_info("%s: %s: %s: %s", myname, maps->title, name, maps->error ? + "search aborted" : "not found"); + return (0); +} + +/* maps_file_find - search a list of dictionaries and base64 decode */ + +const char *maps_file_find(MAPS *maps, const char *name, int flags) +{ + const char *myname = "maps_file_find"; + char **map_name; + const char *expansion; + DICT *dict; + VSTRING *unb64; + char *err; + + /* + * In case of return without map lookup (empty name or no maps). + */ + maps->error = 0; + + /* + * Temp. workaround, for buggy callers that pass zero-length keys when + * given partial addresses. + */ + if (*name == 0) + return (0); + + 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 ((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) + continue; + if ((expansion = dict_get(dict, name)) != 0) { + if (*expansion == 0) { + msg_warn("%s lookup of %s returns an empty string result", + maps->title, name); + msg_warn("%s should return NO RESULT in case of NOT FOUND", + maps->title); + maps->error = DICT_ERR_CONFIG; + return (0); + } + if (msg_verbose) + msg_info("%s: %s: %s: %s = %.100s%s", myname, maps->title, + *map_name, name, expansion, + strlen(expansion) > 100 ? "..." : ""); + if ((unb64 = dict_file_from_b64(dict, expansion)) == 0) { + err = dict_file_get_error(dict); + msg_warn("table %s:%s: key %s: %s", + dict->type, dict->name, name, err); + myfree(err); + maps->error = DICT_ERR_CONFIG; + return (0); + } + return (vstring_str(unb64)); + } else if ((maps->error = dict->error) != 0) { + msg_warn("%s:%s lookup error for \"%s\"", dict->type, dict->name, name); break; } diff --git a/external/ibm-public/postfix/dist/src/global/maps.h b/external/ibm-public/postfix/dist/src/global/maps.h index e53b916f7c1..0c5447ab997 100644 --- a/external/ibm-public/postfix/dist/src/global/maps.h +++ b/external/ibm-public/postfix/dist/src/global/maps.h @@ -1,4 +1,4 @@ -/* $NetBSD: maps.h,v 1.1.1.3 2020/03/18 18:59:33 christos Exp $ */ +/* $NetBSD: maps.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _MAPS_H_INCLUDED_ #define _MAPS_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/memcache_proto.c b/external/ibm-public/postfix/dist/src/global/memcache_proto.c index 117d1f30061..1e352ed8823 100644 --- a/external/ibm-public/postfix/dist/src/global/memcache_proto.c +++ b/external/ibm-public/postfix/dist/src/global/memcache_proto.c @@ -1,4 +1,4 @@ -/* $NetBSD: memcache_proto.c,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: memcache_proto.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/mime_state.c b/external/ibm-public/postfix/dist/src/global/mime_state.c index ca43acf64c6..d89b086e3c7 100644 --- a/external/ibm-public/postfix/dist/src/global/mime_state.c +++ b/external/ibm-public/postfix/dist/src/global/mime_state.c @@ -1,4 +1,4 @@ -/* $NetBSD: mime_state.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mime_state.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -239,6 +239,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -509,6 +514,7 @@ MIME_STATE *mime_state_alloc(int flags, state->prev_rec_type = 0; state->stack = 0; state->token_buffer = vstring_alloc(1); + state->nesting_level = -1; /* BC Fix 20170512 */ /* Static members. */ state->static_flags = flags; @@ -942,7 +948,7 @@ int mime_state_update(MIME_STATE *state, int rec_type, /* * Find out if the next body starts with its own message headers. In - * agressive mode, examine headers of partial and external-body + * aggressive mode, examine headers of partial and external-body * messages. Otherwise, treat such headers as part of the "body". Set * the proper encoding information for the multipart prolog. * @@ -1045,7 +1051,7 @@ int mime_state_update(MIME_STATE *state, int rec_type, /* * Body text. Look for message boundaries, and recover from missing - * boundary strings. Missing boundaries can happen in agressive mode + * boundary strings. Missing boundaries can happen in aggressive mode * with text/rfc822-headers or with message/partial. Ignore non-space * cruft after --boundary or --boundary--, because some MUAs do, and * because only perverse software would take advantage of this to diff --git a/external/ibm-public/postfix/dist/src/global/mkmap_db.c b/external/ibm-public/postfix/dist/src/global/mkmap_db.c index 38cb8a9d206..5cba5b703ae 100644 --- a/external/ibm-public/postfix/dist/src/global/mkmap_db.c +++ b/external/ibm-public/postfix/dist/src/global/mkmap_db.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkmap_db.c,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: mkmap_db.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.c b/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.c index 8d918d6954f..e40f2fb24f1 100644 --- a/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.c +++ b/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: normalize_mailhost_addr.c,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: normalize_mailhost_addr.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.h b/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.h index 410770450a4..d4b0296f35d 100644 --- a/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.h +++ b/external/ibm-public/postfix/dist/src/global/normalize_mailhost_addr.h @@ -1,4 +1,4 @@ -/* $NetBSD: normalize_mailhost_addr.h,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: normalize_mailhost_addr.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _NORMALIZE_MAILHOST_ADDR_H_INCLUDED_ #define _NORMALIZE_MAILHOST_ADDR_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/off_cvt.c b/external/ibm-public/postfix/dist/src/global/off_cvt.c index cd8e1b068e8..3c629fb2057 100644 --- a/external/ibm-public/postfix/dist/src/global/off_cvt.c +++ b/external/ibm-public/postfix/dist/src/global/off_cvt.c @@ -1,4 +1,4 @@ -/* $NetBSD: off_cvt.c,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: off_cvt.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/opened.c b/external/ibm-public/postfix/dist/src/global/opened.c index 4cd5f2626f3..9180b308da5 100644 --- a/external/ibm-public/postfix/dist/src/global/opened.c +++ b/external/ibm-public/postfix/dist/src/global/opened.c @@ -1,4 +1,4 @@ -/* $NetBSD: opened.c,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: opened.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/post_mail.c b/external/ibm-public/postfix/dist/src/global/post_mail.c index 26b774d5d30..f0e0b99727c 100644 --- a/external/ibm-public/postfix/dist/src/global/post_mail.c +++ b/external/ibm-public/postfix/dist/src/global/post_mail.c @@ -1,4 +1,4 @@ -/* $NetBSD: post_mail.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: post_mail.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -82,7 +82,7 @@ /* open stream and the caller-specified context when the /* service responds, or with a null stream and the caller-specified /* context when the request could not be completed. It is the -/* responsability of the application to close an open stream. +/* responsibility of the application to close an open stream. /* /* post_mail_fprintf() formats message content (header or body) /* and sends it to the cleanup service. @@ -156,6 +156,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/global/post_mail.h b/external/ibm-public/postfix/dist/src/global/post_mail.h index c2cc3ff98cc..1c3e0efc4e0 100644 --- a/external/ibm-public/postfix/dist/src/global/post_mail.h +++ b/external/ibm-public/postfix/dist/src/global/post_mail.h @@ -1,4 +1,4 @@ -/* $NetBSD: post_mail.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: post_mail.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _POST_MAIL_H_INCLUDED_ #define _POST_MAIL_H_INCLUDED_ @@ -53,6 +53,11 @@ extern void post_mail_fclose_async(VSTREAM *, POST_MAIL_FCLOSE_NOTIFY, void *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/quote_822_local.c b/external/ibm-public/postfix/dist/src/global/quote_822_local.c index dd0c3b07e67..c89066c4db8 100644 --- a/external/ibm-public/postfix/dist/src/global/quote_822_local.c +++ b/external/ibm-public/postfix/dist/src/global/quote_822_local.c @@ -1,4 +1,4 @@ -/* $NetBSD: quote_822_local.c,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: quote_822_local.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/quote_822_local.h b/external/ibm-public/postfix/dist/src/global/quote_822_local.h index 8f0a16ad5f8..8dcc328dd62 100644 --- a/external/ibm-public/postfix/dist/src/global/quote_822_local.h +++ b/external/ibm-public/postfix/dist/src/global/quote_822_local.h @@ -1,4 +1,4 @@ -/* $NetBSD: quote_822_local.h,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: quote_822_local.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _QUOTE_822_H_INCLUDED_ #define _QUOTE_822_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/quote_flags.c b/external/ibm-public/postfix/dist/src/global/quote_flags.c index a074e7f1749..7a09496ad71 100644 --- a/external/ibm-public/postfix/dist/src/global/quote_flags.c +++ b/external/ibm-public/postfix/dist/src/global/quote_flags.c @@ -1,4 +1,4 @@ -/* $NetBSD: quote_flags.c,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: quote_flags.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/quote_flags.h b/external/ibm-public/postfix/dist/src/global/quote_flags.h index 9b5a5ba68be..03f78157205 100644 --- a/external/ibm-public/postfix/dist/src/global/quote_flags.h +++ b/external/ibm-public/postfix/dist/src/global/quote_flags.h @@ -1,4 +1,4 @@ -/* $NetBSD: quote_flags.h,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: quote_flags.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/rcpt_buf.c b/external/ibm-public/postfix/dist/src/global/rcpt_buf.c index 90e43fa50b2..7701deb48a1 100644 --- a/external/ibm-public/postfix/dist/src/global/rcpt_buf.c +++ b/external/ibm-public/postfix/dist/src/global/rcpt_buf.c @@ -1,4 +1,4 @@ -/* $NetBSD: rcpt_buf.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: rcpt_buf.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -60,7 +60,7 @@ /* Yorktown Heights, NY 10598, USA /*--*/ -/* Syste, library. */ +/* System library. */ #include <sys_defs.h> diff --git a/external/ibm-public/postfix/dist/src/global/rec_type.h b/external/ibm-public/postfix/dist/src/global/rec_type.h index 5e0101d58b9..d7a01db1a04 100644 --- a/external/ibm-public/postfix/dist/src/global/rec_type.h +++ b/external/ibm-public/postfix/dist/src/global/rec_type.h @@ -1,4 +1,4 @@ -/* $NetBSD: rec_type.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: rec_type.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _REC_TYPE_H_INCLUDED_ #define _REC_TYPE_H_INCLUDED_ @@ -137,7 +137,7 @@ /* * The warn record specifies when the next warning that the message was * deferred should be sent. It is updated in place by qmgr, so changing - * this value when there are deferred mesages in the queue is dangerous! + * this value when there are deferred messages in the queue is dangerous! */ #define REC_TYPE_WARN_FORMAT "%15ld" /* warning time format */ #define REC_TYPE_WARN_ARG(tv) ((long) (tv)) diff --git a/external/ibm-public/postfix/dist/src/global/record.c b/external/ibm-public/postfix/dist/src/global/record.c index f42701757c3..c48c172fe1d 100644 --- a/external/ibm-public/postfix/dist/src/global/record.c +++ b/external/ibm-public/postfix/dist/src/global/record.c @@ -1,4 +1,4 @@ -/* $NetBSD: record.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: record.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -139,6 +139,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -284,14 +289,11 @@ int rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags) * Reserve buffer space for the result, and read the record data into * the buffer. */ - VSTRING_RESET(buf); - VSTRING_SPACE(buf, len); - if (vstream_fread(stream, vstring_str(buf), len) != len) { + if (vstream_fread_buf(stream, buf, len) != len) { msg_warn("%s: unexpected EOF in data, record type %d length %ld", VSTREAM_PATH(stream), type, (long) len); return (REC_TYPE_ERROR); } - VSTRING_AT_OFFSET(buf, len); VSTRING_TERMINATE(buf); if (msg_verbose > 2) msg_info("%s: type %c len %ld data %.10s", myname, diff --git a/external/ibm-public/postfix/dist/src/global/reject_deliver_request.c b/external/ibm-public/postfix/dist/src/global/reject_deliver_request.c index 0497f0d38d2..a358f05d472 100644 --- a/external/ibm-public/postfix/dist/src/global/reject_deliver_request.c +++ b/external/ibm-public/postfix/dist/src/global/reject_deliver_request.c @@ -1,4 +1,4 @@ -/* $NetBSD: reject_deliver_request.c,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: reject_deliver_request.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/global/resolve_clnt.c b/external/ibm-public/postfix/dist/src/global/resolve_clnt.c index 3f500540dbb..f708651668e 100644 --- a/external/ibm-public/postfix/dist/src/global/resolve_clnt.c +++ b/external/ibm-public/postfix/dist/src/global/resolve_clnt.c @@ -1,4 +1,4 @@ -/* $NetBSD: resolve_clnt.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: resolve_clnt.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -20,19 +20,11 @@ /* void resolve_clnt_init(reply) /* RESOLVE_REPLY *reply; /* -/* void resolve_clnt_query(address, reply) -/* const char *address; -/* RESOLVE_REPLY *reply; -/* /* void resolve_clnt_query_from(sender, address, reply) /* const char *sender; /* const char *address; /* RESOLVE_REPLY *reply; /* -/* void resolve_clnt_verify(address, reply) -/* const char *address; -/* RESOLVE_REPLY *reply; -/* /* void resolve_clnt_verify_from(sender, address, reply) /* const char *sender; /* const char *address; @@ -47,19 +39,17 @@ /* by resolve_clnt_query(). The structure is destroyed by passing /* it to resolve_clnt_free(). /* -/* resolve_clnt_query() sends an internal-form recipient address +/* resolve_clnt_query_from() sends an internal-form recipient address /* (user@domain) to the resolver daemon and returns the resulting /* transport name, next_hop host name, and internal-form recipient /* address. In case of communication failure the program keeps trying -/* until the mail system goes down. +/* until the mail system goes down. The internal-form sender +/* information is used for sender-dependent relayhost lookup. +/* Specify RESOLVE_NULL_FROM when the sender is unavailable. /* -/* resolve_clnt_verify() implements an alternative version that can +/* resolve_clnt_verify_from() implements an alternative version that can /* be used for address verification. /* -/* resolve_clnt_query_from() and resolve_clnt_verify_from() -/* allow the caller to supply sender context that will be used -/* for sender-dependent relayhost lookup. -/* /* In the resolver reply, the flags member is the bit-wise OR of /* zero or more of the following: /* .IP RESOLVE_FLAG_FINAL @@ -111,6 +101,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/global/resolve_clnt.h b/external/ibm-public/postfix/dist/src/global/resolve_clnt.h index 9d4841d9e5e..8fbefeb7757 100644 --- a/external/ibm-public/postfix/dist/src/global/resolve_clnt.h +++ b/external/ibm-public/postfix/dist/src/global/resolve_clnt.h @@ -1,4 +1,4 @@ -/* $NetBSD: resolve_clnt.h,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: resolve_clnt.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _RESOLVE_CLNT_H_INCLUDED_ #define _RESOLVE_CLNT_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/scache.h b/external/ibm-public/postfix/dist/src/global/scache.h index 936e3a41c60..637e29354a0 100644 --- a/external/ibm-public/postfix/dist/src/global/scache.h +++ b/external/ibm-public/postfix/dist/src/global/scache.h @@ -1,4 +1,4 @@ -/* $NetBSD: scache.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: scache.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _SCACHE_H_INCLUDED_ #define _SCACHE_H_INCLUDED_ @@ -94,7 +94,7 @@ typedef int (*SCACHE_FIND_DEST_FN) (SCACHE *, const char *, VSTRING *, VSTRING * */ struct SCACHE_SIZE { int dest_count; /* Nr of destination names */ - int endp_count; /* Nr of endpoint adresses */ + int endp_count; /* Nr of endpoint addresses */ int sess_count; /* Nr of cached sessions */ }; @@ -157,6 +157,11 @@ extern SCACHE *scache_multi_create(void); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/global/sent.c b/external/ibm-public/postfix/dist/src/global/sent.c index 57b49976304..e09f25cb039 100644 --- a/external/ibm-public/postfix/dist/src/global/sent.c +++ b/external/ibm-public/postfix/dist/src/global/sent.c @@ -1,4 +1,4 @@ -/* $NetBSD: sent.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: sent.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -18,7 +18,7 @@ /* DESCRIPTION /* sent() logs that a message was successfully delivered, /* updates the address verification service, or updates a -/* message delivery record on request by the sender. The +/* sender-requested message delivery record. The /* flags argument determines the action. /* /* Arguments: @@ -34,10 +34,10 @@ /* The message is a user-requested address expansion probe. /* Update the message delivery record. /* .IP DEL_REQ_FLAG_RECORD -/* .IP DEL_REQ_FLAG_REC_SENT /* This is a normal message with logged delivery. Update the /* the message delivery record. -/* .RE .IP queue_id +/* .RE +/* .IP queue_id /* The message queue id. /* .IP stats /* Time stamps from different message delivery stages @@ -66,6 +66,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/global/smtp_reply_footer.c b/external/ibm-public/postfix/dist/src/global/smtp_reply_footer.c index fb526a1b1eb..e1edec7264c 100644 --- a/external/ibm-public/postfix/dist/src/global/smtp_reply_footer.c +++ b/external/ibm-public/postfix/dist/src/global/smtp_reply_footer.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_reply_footer.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: smtp_reply_footer.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -259,7 +259,7 @@ static const char *lookup(const char *name, int unused_mode, void *context) int main(int argc, char **argv) { - struct test_case *tp; + const struct test_case *tp; int status; VSTRING *buf = vstring_alloc(10); void *context = 0; diff --git a/external/ibm-public/postfix/dist/src/global/smtp_stream.c b/external/ibm-public/postfix/dist/src/global/smtp_stream.c index c118c0ddc32..14e719e0a7d 100644 --- a/external/ibm-public/postfix/dist/src/global/smtp_stream.c +++ b/external/ibm-public/postfix/dist/src/global/smtp_stream.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_stream.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: smtp_stream.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -39,6 +39,11 @@ /* ssize_t len; /* VSTREAM *stream; /* +/* void smtp_fread_buf(vp, len, stream) +/* VSTRING *vp; +/* ssize_t len; +/* VSTREAM *stream; +/* /* void smtp_fputc(ch, stream) /* int ch; /* VSTREAM *stream; @@ -47,6 +52,12 @@ /* VSTREAM *stream; /* char *format; /* va_list ap; +/* AUXILIARY API +/* int smtp_get_noexcept(vp, stream, maxlen, flags) +/* VSTRING *vp; +/* VSTREAM *stream; +/* ssize_t maxlen; +/* int flags; /* LEGACY API /* void smtp_timeout_setup(stream, timeout) /* VSTREAM *stream; @@ -84,10 +95,15 @@ /* and protects the program against running out of memory. /* Specify a zero bound to turn off bounds checking. /* The result is the last character read, or VSTREAM_EOF. -/* The \fIflags\fR argument is either SMTP_GET_FLAG_NONE (no -/* special processing) or SMTP_GET_FLAG_SKIP (skip over input -/* in excess of \fImaxlen\fR). Either way, a result value of -/* '\n' means that the input did not exceed \fImaxlen\fR. +/* The \fIflags\fR argument is zero or more of: +/* .RS +/* .IP SMTP_GET_FLAG_SKIP +/* Skip over input in excess of \fImaxlen\fR). Either way, a result +/* value of '\n' means that the input did not exceed \fImaxlen\fR. +/* .IP SMTP_GET_FLAG_APPEND +/* Append content to the buffer instead of overwriting it. +/* .RE +/* Specify SMTP_GET_FLAG_NONE for no special processing. /* /* smtp_fputs() writes its string argument to the named stream. /* Long strings are not broken. Each string is followed by a @@ -97,11 +113,22 @@ /* Long strings are not broken. No CR LF is appended. The stream /* is not flushed. /* +/* smtp_fread_buf() invokes vstream_fread_buf() to read the +/* specified number of unformatted bytes from the stream. The +/* result is not null-terminated. NOTE: do not skip calling +/* smtp_fread_buf() when len == 0. This function has side +/* effects including resetting the buffer write position, and +/* skipping the call would invalidate the buffer state. +/* /* smtp_fputc() writes one character to the named stream. /* The stream is not flushed. /* /* smtp_vprintf() is the machine underneath smtp_printf(). /* +/* smtp_get_noexcept() implements the subset of smtp_get() +/* without timeouts and without making long jumps. Instead, +/* query the stream status with vstream_feof() etc. +/* /* smtp_timeout_setup() is a backwards-compatibility interface /* for programs that don't require per-record deadline support. /* DIAGNOSTICS @@ -145,6 +172,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -307,6 +339,29 @@ int smtp_fgetc(VSTREAM *stream) int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags) { int last_char; + + /* + * Do the I/O, protected against timeout. + */ + smtp_timeout_reset(stream); + last_char = smtp_get_noexcept(vp, stream, bound, flags); + + /* + * EOF is bad, whether or not it happens in the middle of a record. Don't + * allow data that was truncated because of EOF. + */ + if (vstream_ftimeout(stream)) + smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_get"); + if (vstream_feof(stream) || vstream_ferror(stream)) + smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_get"); + return (last_char); +} + +/* smtp_get_noexcept - read one line from SMTP peer, without exceptions */ + +int smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags) +{ + int last_char; int next_char; /* @@ -318,9 +373,13 @@ int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags) * XXX 2821: Section 4.1.1.4 says that an SMTP server must not recognize * bare LF as record terminator. */ - smtp_timeout_reset(stream); - last_char = (bound == 0 ? vstring_get(vp, stream) : - vstring_get_bound(vp, stream, bound)); + last_char = (bound == 0 ? + vstring_get_flags(vp, stream, + (flags & SMTP_GET_FLAG_APPEND) ? + VSTRING_GET_FLAG_APPEND : 0) : + vstring_get_flags_bound(vp, stream, + (flags & SMTP_GET_FLAG_APPEND) ? + VSTRING_GET_FLAG_APPEND : 0, bound)); switch (last_char) { @@ -369,14 +428,6 @@ int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags) && next_char != '\n') /* void */ ; - /* - * EOF is bad, whether or not it happens in the middle of a record. Don't - * allow data that was truncated because of EOF. - */ - if (vstream_ftimeout(stream)) - smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_get"); - if (vstream_feof(stream) || vstream_ferror(stream)) - smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_get"); return (last_char); } @@ -384,7 +435,7 @@ int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags) void smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream) { - ssize_t err; + int err; if (todo < 0) msg_panic("smtp_fputs: negative todo %ld", (long) todo); @@ -409,7 +460,7 @@ void smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream) void smtp_fwrite(const char *cp, ssize_t todo, VSTREAM *stream) { - ssize_t err; + int err; if (todo < 0) msg_panic("smtp_fwrite: negative todo %ld", (long) todo); @@ -429,6 +480,35 @@ void smtp_fwrite(const char *cp, ssize_t todo, VSTREAM *stream) smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_fwrite"); } +/* smtp_fread_buf - read one buffer from SMTP peer */ + +void smtp_fread_buf(VSTRING *vp, ssize_t todo, VSTREAM *stream) +{ + int err; + + /* + * Do not return early if todo == 0. We still need the side effects from + * calling vstream_fread_buf() including resetting the buffer write + * position. Skipping the call would invalidate the buffer state. + */ + if (todo < 0) + msg_panic("smtp_fread_buf: negative todo %ld", (long) todo); + + /* + * Do the I/O, protected against timeout. + */ + smtp_timeout_reset(stream); + err = (vstream_fread_buf(stream, vp, todo) != todo); + + /* + * See if there was a problem. + */ + if (vstream_ftimeout(stream)) + smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_fread"); + if (err != 0) + smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_fread"); +} + /* smtp_fputc - write to SMTP peer */ void smtp_fputc(int ch, VSTREAM *stream) diff --git a/external/ibm-public/postfix/dist/src/global/smtp_stream.h b/external/ibm-public/postfix/dist/src/global/smtp_stream.h index 62e2d381f7a..593ddddb94c 100644 --- a/external/ibm-public/postfix/dist/src/global/smtp_stream.h +++ b/external/ibm-public/postfix/dist/src/global/smtp_stream.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_stream.h,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: smtp_stream.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _SMTP_STREAM_H_INCLUDED_ #define _SMTP_STREAM_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/smtputf8.h b/external/ibm-public/postfix/dist/src/global/smtputf8.h index 7188019dc11..c3a0784029b 100644 --- a/external/ibm-public/postfix/dist/src/global/smtputf8.h +++ b/external/ibm-public/postfix/dist/src/global/smtputf8.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtputf8.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: smtputf8.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ #ifndef _SMTPUTF8_H_INCLUDED_ #define _SMTPUTF8_H_INCLUDED_ @@ -18,7 +18,7 @@ * environments with pre-existing mail flows that contain UTF8. * * Prior to SMTPUTF8, mail flows that contain UTF8 worked because the vast - * majority of MTAs is perfectly capable of handling UTF8 in addres + * majority of MTAs is perfectly capable of handling UTF8 in address * localparts (and in headers), even if pre-SMTPUTF8 standards do not * support this practice. * @@ -27,7 +27,7 @@ * client does not request SMTPUTF8 support, and because 2) a down-stream * MTA does not announce SMTPUTF8 support. * - * While 1) is easy enough to avoid (keep accepting UTF8 in addres localparts + * While 1) is easy enough to avoid (keep accepting UTF8 in address localparts * just like Postfix has always done), 2) presents a thornier problem. The * root cause of that problem is the need for SMTPUTF8 autodetection. * diff --git a/external/ibm-public/postfix/dist/src/global/split_addr.c b/external/ibm-public/postfix/dist/src/global/split_addr.c index 8c4d3c02236..d315b88b278 100644 --- a/external/ibm-public/postfix/dist/src/global/split_addr.c +++ b/external/ibm-public/postfix/dist/src/global/split_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: split_addr.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: split_addr.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -8,14 +8,23 @@ /* SYNOPSIS /* #include <split_addr.h> /* +/* char *split_addr_internal(localpart, delimiter_set) +/* char *localpart; +/* const char *delimiter_set; +/* LEGACY SUPPORT /* char *split_addr(localpart, delimiter_set) /* char *localpart; /* const char *delimiter_set; /* DESCRIPTION -/* split_addr() null-terminates \fIlocalpart\fR at the first +/* split_addr*() null-terminates \fIlocalpart\fR at the first /* occurrence of the \fIdelimiter\fR character(s) found, and /* returns a pointer to the remainder. /* +/* With split_addr_internal(), the address must be in internal +/* (unquoted) form. +/* +/* split_addr() is a backwards-compatible form for legacy code. +/* /* Reserved addresses are not split: postmaster, mailer-daemon, /* double-bounce. Addresses that begin with owner-, or addresses /* that end in -request are not split when the owner_request_special @@ -29,6 +38,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -51,9 +65,9 @@ #include <mail_addr.h> #include <split_addr.h> -/* split_addr - split address with extreme prejudice */ +/* split_addr_internal - split address with extreme prejudice */ -char *split_addr(char *localpart, const char *delimiter_set) +char *split_addr_internal(char *localpart, const char *delimiter_set) { ssize_t len; diff --git a/external/ibm-public/postfix/dist/src/global/split_addr.h b/external/ibm-public/postfix/dist/src/global/split_addr.h index a70a1774f34..de7fa1ac473 100644 --- a/external/ibm-public/postfix/dist/src/global/split_addr.h +++ b/external/ibm-public/postfix/dist/src/global/split_addr.h @@ -1,4 +1,4 @@ -/* $NetBSD: split_addr.h,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: split_addr.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _SPLIT_ADDR_H_INCLUDED_ #define _SPLIT_ADDR_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/strip_addr.c b/external/ibm-public/postfix/dist/src/global/strip_addr.c index 4732e8529e2..3289cb69128 100644 --- a/external/ibm-public/postfix/dist/src/global/strip_addr.c +++ b/external/ibm-public/postfix/dist/src/global/strip_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: strip_addr.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: strip_addr.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -8,16 +8,26 @@ /* SYNOPSIS /* #include <strip_addr.h> /* +/* char *strip_addr_internal(address, extension, delimiter_set) +/* const char *address; +/* char **extension; +/* const char *delimiter_set; +/* LEGACY SUPPORT /* char *strip_addr(address, extension, delimiter_set) /* const char *address; /* char **extension; /* const char *delimiter_set; /* DESCRIPTION -/* strip_addr() takes an address and either returns a null +/* strip_addr*() takes an address and either returns a null /* pointer when the address contains no address extension, /* or returns a copy of the address without address extension. /* The caller is expected to pass the copy to myfree(). /* +/* With strip_addr_internal(), the input and result are in +/* internal form. +/* +/* strip_addr() is a backwards-compatible form for legacy code. +/* /* Arguments: /* .IP address /* Address localpart or user@domain form. @@ -40,6 +50,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -58,7 +73,8 @@ /* strip_addr - strip extension from address */ -char *strip_addr(const char *full, char **extension, const char *delimiter_set) +char *strip_addr_internal(const char *full, char **extension, + const char *delimiter_set) { char *ratsign; char *extent; @@ -115,64 +131,64 @@ int main(int unused_argc, char **unused_argv) * Incredible. This function takes only three arguments, and the tests * already take more lines of code than the code being tested. */ - stripped = strip_addr("foo", (char **) 0, NO_DELIM); + stripped = strip_addr_internal("foo", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 1"); - stripped = strip_addr("foo", &extension, NO_DELIM); + stripped = strip_addr_internal("foo", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 2"); if (extension != 0) msg_panic("strip_addr botch 3"); - stripped = strip_addr("foo", (char **) 0, delim); + stripped = strip_addr_internal("foo", (char **) 0, delim); if (stripped != 0) msg_panic("strip_addr botch 4"); - stripped = strip_addr("foo", &extension, delim); + stripped = strip_addr_internal("foo", &extension, delim); if (stripped != 0) msg_panic("strip_addr botch 5"); if (extension != 0) msg_panic("strip_addr botch 6"); - stripped = strip_addr("foo@bar", (char **) 0, NO_DELIM); + stripped = strip_addr_internal("foo@bar", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 7"); - stripped = strip_addr("foo@bar", &extension, NO_DELIM); + stripped = strip_addr_internal("foo@bar", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 8"); if (extension != 0) msg_panic("strip_addr botch 9"); - stripped = strip_addr("foo@bar", (char **) 0, delim); + stripped = strip_addr_internal("foo@bar", (char **) 0, delim); if (stripped != 0) msg_panic("strip_addr botch 10"); - stripped = strip_addr("foo@bar", &extension, delim); + stripped = strip_addr_internal("foo@bar", &extension, delim); if (stripped != 0) msg_panic("strip_addr botch 11"); if (extension != 0) msg_panic("strip_addr botch 12"); - stripped = strip_addr("foo-ext", (char **) 0, NO_DELIM); + stripped = strip_addr_internal("foo-ext", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 13"); - stripped = strip_addr("foo-ext", &extension, NO_DELIM); + stripped = strip_addr_internal("foo-ext", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 14"); if (extension != 0) msg_panic("strip_addr botch 15"); - stripped = strip_addr("foo-ext", (char **) 0, delim); + stripped = strip_addr_internal("foo-ext", (char **) 0, delim); if (stripped == 0) msg_panic("strip_addr botch 16"); msg_info("wanted: foo-ext -> %s", "foo"); msg_info("strip_addr foo-ext -> %s", stripped); myfree(stripped); - stripped = strip_addr("foo-ext", &extension, delim); + stripped = strip_addr_internal("foo-ext", &extension, delim); if (stripped == 0) msg_panic("strip_addr botch 17"); if (extension == 0) @@ -182,24 +198,24 @@ int main(int unused_argc, char **unused_argv) myfree(stripped); myfree(extension); - stripped = strip_addr("foo-ext@bar", (char **) 0, NO_DELIM); + stripped = strip_addr_internal("foo-ext@bar", (char **) 0, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 19"); - stripped = strip_addr("foo-ext@bar", &extension, NO_DELIM); + stripped = strip_addr_internal("foo-ext@bar", &extension, NO_DELIM); if (stripped != 0) msg_panic("strip_addr botch 20"); if (extension != 0) msg_panic("strip_addr botch 21"); - stripped = strip_addr("foo-ext@bar", (char **) 0, delim); + stripped = strip_addr_internal("foo-ext@bar", (char **) 0, delim); if (stripped == 0) msg_panic("strip_addr botch 22"); msg_info("wanted: foo-ext@bar -> %s", "foo@bar"); msg_info("strip_addr foo-ext@bar -> %s", stripped); myfree(stripped); - stripped = strip_addr("foo-ext@bar", &extension, delim); + stripped = strip_addr_internal("foo-ext@bar", &extension, delim); if (stripped == 0) msg_panic("strip_addr botch 23"); if (extension == 0) @@ -209,7 +225,7 @@ int main(int unused_argc, char **unused_argv) myfree(stripped); myfree(extension); - stripped = strip_addr("foo+ext@bar", &extension, delim); + stripped = strip_addr_internal("foo+ext@bar", &extension, delim); if (stripped == 0) msg_panic("strip_addr botch 25"); if (extension == 0) @@ -219,6 +235,16 @@ int main(int unused_argc, char **unused_argv) myfree(stripped); myfree(extension); + stripped = strip_addr_internal("foo bar+ext", &extension, delim); + if (stripped == 0) + msg_panic("strip_addr botch 27"); + if (extension == 0) + msg_panic("strip_addr botch 28"); + msg_info("wanted: foo bar+ext -> %s %s", "foo bar", "+ext"); + msg_info("strip_addr foo bar+ext -> %s %s", stripped, extension); + myfree(stripped); + myfree(extension); + return (0); } diff --git a/external/ibm-public/postfix/dist/src/global/strip_addr.h b/external/ibm-public/postfix/dist/src/global/strip_addr.h index 3f97f6261ad..26299c58891 100644 --- a/external/ibm-public/postfix/dist/src/global/strip_addr.h +++ b/external/ibm-public/postfix/dist/src/global/strip_addr.h @@ -1,4 +1,4 @@ -/* $NetBSD: strip_addr.h,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: strip_addr.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ #ifndef _STRIP_ADDR_H_INCLUDED_ #define _STRIP_ADDR_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/global/uxtext.c b/external/ibm-public/postfix/dist/src/global/uxtext.c index a25a39cd2d3..4794da741de 100644 --- a/external/ibm-public/postfix/dist/src/global/uxtext.c +++ b/external/ibm-public/postfix/dist/src/global/uxtext.c @@ -1,4 +1,4 @@ -/* $NetBSD: uxtext.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: uxtext.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -54,6 +54,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -232,9 +237,7 @@ static ssize_t read_buf(VSTREAM *fp, VSTRING *buf) { ssize_t len; - VSTRING_RESET(buf); - len = vstream_fread(fp, STR(buf), vstring_avail(buf)); - VSTRING_AT_OFFSET(buf, len); /* XXX */ + len = vstream_fread_buf(fp, buf, BUFLEN); VSTRING_TERMINATE(buf); return (len); } diff --git a/external/ibm-public/postfix/dist/src/global/verify.c b/external/ibm-public/postfix/dist/src/global/verify.c index 6034c077f31..94b8d261b75 100644 --- a/external/ibm-public/postfix/dist/src/global/verify.c +++ b/external/ibm-public/postfix/dist/src/global/verify.c @@ -1,4 +1,4 @@ -/* $NetBSD: verify.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: verify.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -63,6 +63,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -102,11 +107,12 @@ int verify_append(const char *queue_id, MSG_STATS *stats, * XXX vrfy_stat is competely redundant because of dsn. */ if (var_verify_neg_cache || vrfy_stat == DEL_RCPT_STAT_OK) { - req_stat = verify_clnt_update(recipient->orig_addr, vrfy_stat, - my_dsn.reason); + if (recipient->orig_addr[0]) + req_stat = verify_clnt_update(recipient->orig_addr, vrfy_stat, + my_dsn.reason); /* Two verify updates for one verify request! */ if (req_stat == VRFY_STAT_OK - && strcasecmp_utf8(recipient->address, recipient->orig_addr) != 0) + && strcmp(recipient->address, recipient->orig_addr) != 0) req_stat = verify_clnt_update(recipient->address, vrfy_stat, my_dsn.reason); } else { diff --git a/external/ibm-public/postfix/dist/src/global/verify_sender_addr.c b/external/ibm-public/postfix/dist/src/global/verify_sender_addr.c index c41f02f9e71..a796b2396b6 100644 --- a/external/ibm-public/postfix/dist/src/global/verify_sender_addr.c +++ b/external/ibm-public/postfix/dist/src/global/verify_sender_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: verify_sender_addr.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: verify_sender_addr.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -297,7 +297,7 @@ int main(int argc, char **argv) verify_time = time((time_t *) 0); /* - * Compute the current probe sender addres. + * Compute the current probe sender address. */ verify_sender = make_verify_sender_addr(); diff --git a/external/ibm-public/postfix/dist/src/global/xtext.c b/external/ibm-public/postfix/dist/src/global/xtext.c index 88fde120b23..5634192732b 100644 --- a/external/ibm-public/postfix/dist/src/global/xtext.c +++ b/external/ibm-public/postfix/dist/src/global/xtext.c @@ -1,4 +1,4 @@ -/* $NetBSD: xtext.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: xtext.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -51,6 +51,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -152,9 +157,7 @@ static ssize_t read_buf(VSTREAM *fp, VSTRING *buf) { ssize_t len; - VSTRING_RESET(buf); - len = vstream_fread(fp, STR(buf), vstring_avail(buf)); - VSTRING_AT_OFFSET(buf, len); /* XXX */ + len = vstream_fread_buf(fp, buf, BUFLEN); VSTRING_TERMINATE(buf); return (len); } diff --git a/external/ibm-public/postfix/dist/src/local/alias.c b/external/ibm-public/postfix/dist/src/local/alias.c index 799b7920ee7..62a08b90085 100644 --- a/external/ibm-public/postfix/dist/src/local/alias.c +++ b/external/ibm-public/postfix/dist/src/local/alias.c @@ -1,4 +1,4 @@ -/* $NetBSD: alias.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: alias.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -131,7 +131,7 @@ int deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr, * * We cannot do duplicate elimination here. Sendmail compatibility requires * that we allow multiple deliveries to the same alias, even recursively! - * For example, we must deliver to mailbox any messags that are addressed + * For example, we must deliver to mailbox any messages that are addressed * to the alias of a user that lists that same alias in her own .forward * file. Yuck! This is just an example of some really perverse semantics * that people will expect Postfix to implement just like sendmail. diff --git a/external/ibm-public/postfix/dist/src/local/forward.c b/external/ibm-public/postfix/dist/src/local/forward.c index cf111674697..9144cbda1bd 100644 --- a/external/ibm-public/postfix/dist/src/local/forward.c +++ b/external/ibm-public/postfix/dist/src/local/forward.c @@ -1,4 +1,4 @@ -/* $NetBSD: forward.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: forward.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -50,6 +50,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/local/local.c b/external/ibm-public/postfix/dist/src/local/local.c index 83960148bbd..c2fee52a16f 100644 --- a/external/ibm-public/postfix/dist/src/local/local.c +++ b/external/ibm-public/postfix/dist/src/local/local.c @@ -1,4 +1,4 @@ -/* $NetBSD: local.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: local.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -316,7 +316,8 @@ /* RFC 822 (ARPA Internet Text Messages) /* RFC 3463 (Enhanced status codes) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* Corrupted message files are marked so that the queue /* manager can move them to the \fBcorrupt\fR queue afterwards. /* @@ -363,13 +364,14 @@ /* .IP "\fBbiff (yes)\fR" /* Whether or not to use the local biff service. /* .IP "\fBexpand_owner_alias (no)\fR" -/* 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. +/* When delivering to an alias "\fIaliasname\fR" that has an +/* "owner-\fIaliasname\fR" companion alias, set the envelope sender +/* address to the expansion of the "owner-\fIaliasname\fR" alias. /* .IP "\fBowner_request_special (yes)\fR" -/* Give special treatment to owner-listname and listname-request -/* address localparts: don't split such addresses when the -/* recipient_delimiter is set to "-". +/* Enable special treatment for owner-\fIlistname\fR entries in the +/* \fBaliases\fR(5) file, and don't split owner-\fIlistname\fR and +/* \fIlistname\fR-request address localparts when the recipient_delimiter +/* is set to "-". /* .IP "\fBsun_mailtool_compatibility (no)\fR" /* Obsolete SUN mailtool compatibility feature. /* .PP @@ -462,6 +464,11 @@ /* The maximal number of addresses remembered by the address /* duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or /* for \fBshowq\fR(8) queue displays. +/* .IP "\fBmailbox_size_limit (51200000)\fR" +/* The maximal size of any \fBlocal\fR(8) individual mailbox or maildir +/* file, or zero (no limit). +/* .PP +/* Implemented in the qmgr(8) daemon: /* .IP "\fBlocal_destination_concurrency_limit (2)\fR" /* The maximal number of parallel deliveries via the local mail /* delivery transport to the same recipient (when @@ -471,9 +478,6 @@ /* .IP "\fBlocal_destination_recipient_limit (1)\fR" /* The maximal number of recipients per message delivery via the /* local mail delivery transport. -/* .IP "\fBmailbox_size_limit (51200000)\fR" -/* The maximal size of any \fBlocal\fR(8) individual mailbox or maildir -/* file, or zero (no limit). /* SECURITY CONTROLS /* .ad /* .fi @@ -548,8 +552,21 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix version 3.3 and later: +/* .IP "\fBenable_original_recipient (yes)\fR" +/* Enable support for the original recipient address after an +/* address is rewritten to a different address (for example with +/* aliasing or with canonical mapping). +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* FILES /* The following are examples; details differ between systems. /* $HOME/.forward, per-user aliasing @@ -563,6 +580,7 @@ /* aliases(5), format of alias database /* postconf(5), configuration parameters /* master(5), generic daemon options +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad @@ -864,9 +882,12 @@ static void pre_init(char *unused_name, char **unused_argv) * because that prohibits the delivery agent from updating the queue * file. */ - if (var_mailbox_limit) { - if (var_mailbox_limit < var_message_limit || var_message_limit == 0) - msg_fatal("main.cf configuration error: %s is smaller than %s", + if (ENFORCING_SIZE_LIMIT(var_mailbox_limit)) { + if (!ENFORCING_SIZE_LIMIT(var_message_limit)) + msg_fatal("configuration error: %s is limited but %s is " + "unlimited", VAR_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT); + if (var_mailbox_limit < var_message_limit) + msg_fatal("configuration error: %s is smaller than %s", VAR_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT); set_file_limit(var_mailbox_limit); } diff --git a/external/ibm-public/postfix/dist/src/local/mailbox.c b/external/ibm-public/postfix/dist/src/local/mailbox.c index 4eee7e8098a..4dac8613699 100644 --- a/external/ibm-public/postfix/dist/src/local/mailbox.c +++ b/external/ibm-public/postfix/dist/src/local/mailbox.c @@ -1,4 +1,4 @@ -/* $NetBSD: mailbox.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mailbox.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -43,6 +43,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -99,7 +104,7 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) int deliver_status; int copy_flags; VSTRING *biff; - long end; + off_t end; struct stat st; uid_t spool_uid; gid_t spool_gid; @@ -204,7 +209,8 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) msg_warn("specify \"%s = no\" to ignore mailbox ownership mismatch", VAR_STRICT_MBOX_OWNER); } else { - end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END); + if ((end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END)) < 0) + msg_fatal("seek mailbox file %s: %m", mailbox); mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp, copy_flags, "\n", why); } diff --git a/external/ibm-public/postfix/dist/src/local/unknown.c b/external/ibm-public/postfix/dist/src/local/unknown.c index 12d5585ac42..016675ca29d 100644 --- a/external/ibm-public/postfix/dist/src/local/unknown.c +++ b/external/ibm-public/postfix/dist/src/local/unknown.c @@ -1,4 +1,4 @@ -/* $NetBSD: unknown.c,v 1.6 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: unknown.c,v 1.7 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -47,6 +47,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -75,11 +80,14 @@ #include <sent.h> #include <deliver_pass.h> #include <defer.h> +#include <canon_addr.h> /* Application-specific. */ #include "local.h" +#define STREQ(x,y) (strcasecmp((x),(y)) == 0) + /* deliver_unknown - delivery for unknown recipients */ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) @@ -87,6 +95,7 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) const char *myname = "deliver_unknown"; int status; VSTRING *expand_luser; + VSTRING *canon_luser; static MAPS *transp_maps; const char *map_transport; @@ -141,8 +150,20 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) if (*var_luser_relay) { state.msg_attr.unmatched = 0; expand_luser = vstring_alloc(100); + canon_luser = vstring_alloc(100); local_expand(expand_luser, var_luser_relay, &state, &usr_attr, (void *) 0); - status = deliver_resolve_addr(state, usr_attr, STR(expand_luser)); + /* In case luser_relay specifies a domain-less address. */ + canon_addr_external(canon_luser, vstring_str(expand_luser)); + /* Assumes that the address resolver won't change the address. */ + if (STREQ(vstring_str(canon_luser), state.msg_attr.rcpt.address)) { + dsb_simple(state.msg_attr.why, "5.1.1", + "unknown user: \"%s\"", state.msg_attr.user); + status = bounce_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + } else { + status = deliver_resolve_addr(state, usr_attr, STR(expand_luser)); + } + vstring_free(canon_luser); vstring_free(expand_luser); return (status); } @@ -151,8 +172,6 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) * If no alias was found for a required reserved name, toss the message * into the bit bucket, and issue a warning instead. */ -#define STREQ(x,y) (strcasecmp(x,y) == 0) - if (STREQ(state.msg_attr.user, MAIL_ADDR_MAIL_DAEMON) || STREQ(state.msg_attr.user, MAIL_ADDR_POSTMASTER)) { msg_warn("required alias not found: %s", state.msg_attr.user); diff --git a/external/ibm-public/postfix/dist/src/master/dgram_server.c b/external/ibm-public/postfix/dist/src/master/dgram_server.c index be53b9f1fba..0a69904dfa2 100644 --- a/external/ibm-public/postfix/dist/src/master/dgram_server.c +++ b/external/ibm-public/postfix/dist/src/master/dgram_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: dgram_server.c,v 1.1.1.1 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: dgram_server.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/master/event_server.c b/external/ibm-public/postfix/dist/src/master/event_server.c index a0b600ff331..d9d401530a8 100644 --- a/external/ibm-public/postfix/dist/src/master/event_server.c +++ b/external/ibm-public/postfix/dist/src/master/event_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: event_server.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: event_server.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -19,7 +19,7 @@ /* /* void event_server_drain() /* DESCRIPTION -/* This module implements a skeleton for multi-threaded +/* This module implements a skeleton for event-driven /* mail subsystems: mail subsystem programs that service multiple /* clients at the same time. The resulting program expects to be run /* from the \fBmaster\fR process. @@ -143,6 +143,11 @@ /* .IP "CA_MAIL_SERVER_BOUNCE_INIT(const char *, const char **)" /* Initialize the DSN filter for the bounce/defer service /* clients with the specified map source and map names. +/* .IP "CA_MAIL_SERVER_RETIRE_ME" +/* Prevent a process from being reused indefinitely. After +/* (var_max_use * var_max_idle) seconds or some sane constant, +/* stop accepting new connections and terminate voluntarily +/* when the process becomes idle. /* .PP /* event_server_disconnect() should be called by the application /* to close a client connection. @@ -154,7 +159,7 @@ /* result means this call should be tried again later. /* /* The var_use_limit variable limits the number of clients -/* that a server can service before it commits suicide. This +/* that a server can service before it commits suicide. This /* value is taken from the global \fBmain.cf\fR configuration /* file. Setting \fBvar_use_limit\fR to zero disables the /* client limit. @@ -165,10 +170,12 @@ /* configuration file. Setting \fBvar_idle_limit\fR to zero /* disables the idle limit. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* SEE ALSO /* master(8), master process -/* syslogd(8) system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -178,6 +185,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -187,7 +199,6 @@ #include <sys/time.h> /* select() */ #include <unistd.h> #include <signal.h> -#include <syslog.h> #include <stdlib.h> #include <limits.h> #include <string.h> @@ -206,7 +217,6 @@ /* Utility library. */ #include <msg.h> -#include <msg_syslog.h> #include <msg_vstream.h> #include <chroot_uid.h> #include <listen.h> @@ -236,6 +246,7 @@ #include <mail_flow.h> #include <mail_version.h> #include <bounce.h> +#include <maillog_client.h> /* Process manager. */ @@ -275,12 +286,27 @@ static NORETURN event_server_exit(void) exit(0); } +/* event_server_retire - retire when idle */ + +static void event_server_retire(int unused_event, void *unused_context) +{ + if (msg_verbose) + msg_info("time to retire -- %s", event_server_slow_exit ? + "draining" : "exiting"); + event_disable_readwrite(MASTER_STATUS_FD); + if (event_server_slow_exit) + event_server_slow_exit(event_server_name, event_server_argv); + else + event_server_exit(); +} + /* event_server_abort - terminate after abnormal master exit */ static void event_server_abort(int unused_event, void *unused_context) { if (msg_verbose) - msg_info("master disconnect -- exiting"); + msg_info("master disconnect -- %s", event_server_slow_exit ? + "draining" : "exiting"); event_disable_readwrite(MASTER_STATUS_FD); if (event_server_slow_exit) event_server_slow_exit(event_server_name, event_server_argv); @@ -561,9 +587,10 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; + int retire_me_from_flags = 0; + int retire_me = 0; /* * Process environment options as early as we can. @@ -595,7 +622,7 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -621,7 +648,7 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) * stderr, because no-one is going to see them. */ opterr = 0; - while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:St:uvVz")) > 0) { + while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:r:s:St:uvVz")) > 0) { switch (c) { case 'c': root_dir = "setme"; @@ -649,10 +676,12 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; + case 'r': + if ((retire_me_from_flags = atoi(optarg)) <= 0) + msg_fatal("invalid retirement time: %s", optarg); + break; case 's': if ((socket_count = atoi(optarg)) <= 0) msg_fatal("invalid socket_count: %s", optarg); @@ -677,17 +706,18 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) zerolimit = 1; break; default: - msg_fatal("invalid option: %c", c); + msg_fatal("invalid option: %c", optopt); break; } } + set_mail_conf_str(VAR_SERVNAME, service_name); /* - * Initialize generic parameters. + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for @@ -780,6 +810,15 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) dsn_filter_maps = va_arg(ap, const char **); bounce_client_init(dsn_filter_title, *dsn_filter_maps); break; + case MAIL_SERVER_RETIRE_ME: + if (retire_me_from_flags > 0) + retire_me = retire_me_from_flags; + else if (var_idle_limit == 0 || var_use_limit == 0 + || var_idle_limit > 18000 / var_use_limit) + retire_me = 18000; + else + retire_me = var_idle_limit * var_use_limit; + break; default: msg_panic("%s: unknown argument type: %d", myname, key); } @@ -903,6 +942,8 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) */ if (var_idle_limit > 0) event_request_timer(event_server_timeout, (void *) 0, var_idle_limit); + if (retire_me) + event_request_timer(event_server_retire, (void *) 0, retire_me); for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) { event_enable_read(fd, event_server_accept, CAST_INT_TO_VOID_PTR(fd)); close_on_exec(fd, CLOSE_ON_EXEC); diff --git a/external/ibm-public/postfix/dist/src/master/mail_server.h b/external/ibm-public/postfix/dist/src/master/mail_server.h index 89277eaa252..e8c845cca6c 100644 --- a/external/ibm-public/postfix/dist/src/master/mail_server.h +++ b/external/ibm-public/postfix/dist/src/master/mail_server.h @@ -1,4 +1,4 @@ -/* $NetBSD: mail_server.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: mail_server.h,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -46,6 +46,7 @@ #define MAIL_SERVER_IN_FLOW_DELAY 20 #define MAIL_SERVER_SLOW_EXIT 21 #define MAIL_SERVER_BOUNCE_INIT 22 +#define MAIL_SERVER_RETIRE_ME 23 typedef void (*MAIL_SERVER_INIT_FN) (char *, char **); typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **); @@ -76,6 +77,7 @@ typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **); #define CA_MAIL_SERVER_IN_FLOW_DELAY MAIL_SERVER_IN_FLOW_DELAY #define CA_MAIL_SERVER_SLOW_EXIT(v) MAIL_SERVER_SLOW_EXIT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_SLOW_EXIT_FN, (v)) #define CA_MAIL_SERVER_BOUNCE_INIT(v, w) MAIL_SERVER_BOUNCE_INIT, CHECK_PTR(MAIL_SERVER, char, (v)), CHECK_PPTR(MAIL_SERVER, char, (w)) +#define CA_MAIL_SERVER_RETIRE_ME MAIL_SERVER_RETIRE_ME CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_SLOW_EXIT_FN); CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_LOOP_FN); @@ -125,6 +127,14 @@ extern NORETURN trigger_server_main(int, char **, TRIGGER_SERVER_FN,...); #define TRIGGER_BUF_SIZE 1024 + /* + * dgram_server.c + */ +typedef void (*DGRAM_SERVER_FN) (char *, ssize_t, char *, char **); +extern NORETURN dgram_server_main(int, char **, DGRAM_SERVER_FN,...); + +#define DGRAM_BUF_SIZE 4096 + /* LICENSE /* .ad /* .fi @@ -134,4 +144,9 @@ extern NORETURN trigger_server_main(int, char **, TRIGGER_SERVER_FN,...); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/master/master.c b/external/ibm-public/postfix/dist/src/master/master.c index 7d4bed92245..d754e8d9f80 100644 --- a/external/ibm-public/postfix/dist/src/master/master.c +++ b/external/ibm-public/postfix/dist/src/master/master.c @@ -1,4 +1,4 @@ -/* $NetBSD: master.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: master.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -6,7 +6,7 @@ /* SUMMARY /* Postfix master process /* SYNOPSIS -/* \fBmaster\fR [\fB-Ddtvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR] +/* \fBmaster\fR [\fB-Dditvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR] /* DESCRIPTION /* The \fBmaster\fR(8) daemon is the resident process that runs Postfix /* daemons on demand: daemons to send or receive messages via the @@ -39,6 +39,18 @@ /* .IP "\fB-e \fIexit_time\fR" /* Terminate the master process after \fIexit_time\fR seconds. Child /* processes terminate at their convenience. +/* .IP \fB-i\fR +/* Enable \fBinit\fR mode: do not become a session or process +/* group leader; and similar to \fB-s\fR, do not redirect stdout +/* to /dev/null, so that "maillog_file = /dev/stdout" works. +/* This mode is allowed only if the process ID equals 1. +/* .sp +/* This feature is available in Postfix 3.3 and later. +/* .IP \fB-s\fR +/* Do not redirect stdout to /dev/null, so that "maillog_file +/* = /dev/stdout" works. +/* .sp +/* This feature is available in Postfix 3.4 and later. /* .IP \fB-t\fR /* Test mode. Return a zero exit status when the \fBmaster.pid\fR lock /* file does not exist or when that file is not locked. This is evidence @@ -73,7 +85,8 @@ /* terminate only the master ("\fBpostfix stop\fR") and allow running /* processes to finish what they are doing. /* DIAGNOSTICS -/* Problems are reported to \fBsyslogd\fR(8). The exit status +/* Problems are reported to \fBsyslogd\fR(8) or \fBpostlogd\fR(8). +/* The exit status /* is non-zero in case of problems, including problems while /* initializing as a master daemon process in the background. /* ENVIRONMENT @@ -130,8 +143,9 @@ /* 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 Postfix process will -/* import from a non-Postfix parent process. +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBmail_owner (postfix)\fR" /* The UNIX system account that owns the Postfix queue and most Postfix /* daemon processes. @@ -144,8 +158,12 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* FILES /* .ad /* .fi @@ -163,6 +181,7 @@ /* verify(8), address verification /* master(5), master.cf configuration file syntax /* postconf(5), main.cf configuration file syntax +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad @@ -184,7 +203,6 @@ #include <sys_defs.h> #include <sys/stat.h> -#include <syslog.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> @@ -196,7 +214,6 @@ #include <events.h> #include <msg.h> -#include <msg_syslog.h> #include <vstring.h> #include <mymalloc.h> #include <iostuff.h> @@ -220,12 +237,14 @@ #include <open_lock.h> #include <inet_proto.h> #include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ #include "master.h" int master_detach = 1; +int init_mode = 0; /* master_exit_event - exit for memory leak testing purposes */ @@ -254,6 +273,7 @@ int main(int argc, char **argv) VSTRING *data_lock_path; off_t inherited_limit; int debug_me = 0; + int keep_stdout = 0; int ch; int fd; int n; @@ -311,7 +331,8 @@ int main(int argc, char **argv) /* * Initialize logging and exit handler. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. @@ -331,7 +352,7 @@ int main(int argc, char **argv) /* * Process JCL. */ - while ((ch = GETOPT(argc, argv, "c:Dde:tvw")) > 0) { + while ((ch = GETOPT(argc, argv, "c:Dde:istvw")) > 0) { switch (ch) { case 'c': if (setenv(CONF_ENV_PATH, optarg, 1) < 0) @@ -343,9 +364,18 @@ int main(int argc, char **argv) case 'e': event_request_timer(master_exit_event, (void *) 0, atoi(optarg)); break; + case 'i': + if (getpid() != 1) + msg_fatal("-i is allowed only for PID 1 process"); + init_mode = 1; + keep_stdout = 1; + break; case 'D': debug_me = 1; break; + case 's': + keep_stdout = 1; + break; case 't': test_lock = 1; break; @@ -372,6 +402,8 @@ int main(int argc, char **argv) */ if (test_lock && wait_flag) msg_fatal("the -t and -w options cannot be used together"); + if (init_mode && (debug_me || !master_detach || wait_flag)) + msg_fatal("the -i option cannot be used with -D, -d, or -w"); /* * Run a foreground monitor process that returns an exit status of 0 when @@ -387,9 +419,12 @@ int main(int argc, char **argv) /* * If started from a terminal, get rid of any tty association. This also * means that all errors and warnings must go to the syslog daemon. + * Some new world has no terminals and prefers logging to stdout. */ if (master_detach) for (fd = 0; fd < 3; fd++) { + if (fd == STDOUT_FILENO && keep_stdout) + continue; (void) close(fd); if (open("/dev/null", O_RDWR, 0) != fd) msg_fatal("open /dev/null: %m"); @@ -400,7 +435,8 @@ int main(int argc, char **argv) * all MTA processes cleanly. Give up if we can't separate from our * parent process. We're not supposed to blow away the parent. */ - if (debug_me == 0 && master_detach != 0 && setsid() == -1 && getsid(0) != getpid()) + if (init_mode == 0 && debug_me == 0 && master_detach != 0 + && setsid() == -1 && getsid(0) != getpid()) msg_fatal("unable to set session and process group ID: %m"); /* @@ -507,6 +543,8 @@ int main(int argc, char **argv) master_config(); master_sigsetup(); master_flow_init(); + maillog_client_init(mail_task(var_procname), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); msg_info("daemon started -- version %s, configuration %s", var_mail_version, var_config_dir); @@ -545,6 +583,8 @@ int main(int argc, char **argv) master_gotsighup = 0; /* this first */ master_vars_init(); /* then this */ master_refresh(); /* then this */ + maillog_client_init(mail_task(var_procname), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); } if (master_gotsigchld) { if (msg_verbose) diff --git a/external/ibm-public/postfix/dist/src/master/master.h b/external/ibm-public/postfix/dist/src/master/master.h index e3c10604c83..7f905399051 100644 --- a/external/ibm-public/postfix/dist/src/master/master.h +++ b/external/ibm-public/postfix/dist/src/master/master.h @@ -1,4 +1,4 @@ -/* $NetBSD: master.h,v 1.1.1.5 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: master.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/master/master_conf.c b/external/ibm-public/postfix/dist/src/master/master_conf.c index db4ad386d30..6365a913c71 100644 --- a/external/ibm-public/postfix/dist/src/master/master_conf.c +++ b/external/ibm-public/postfix/dist/src/master/master_conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: master_conf.c,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: master_conf.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/master/master_ent.c b/external/ibm-public/postfix/dist/src/master/master_ent.c index de476dc7a72..568104d87e9 100644 --- a/external/ibm-public/postfix/dist/src/master/master_ent.c +++ b/external/ibm-public/postfix/dist/src/master/master_ent.c @@ -1,4 +1,4 @@ -/* $NetBSD: master_ent.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: master_ent.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -59,6 +59,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System libraries. */ @@ -383,6 +388,10 @@ MASTER_SERV *get_master_ent() serv->type = MASTER_SERV_TYPE_UNIX; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; + } else if (STR_SAME(transport, MASTER_XPORT_NAME_UXDG)) { + serv->type = MASTER_SERV_TYPE_UXDG; + serv->listen_fd_count = 1; + serv->flags |= MASTER_FLAG_LOCAL_ONLY; } else if (STR_SAME(transport, MASTER_XPORT_NAME_FIFO)) { serv->type = MASTER_SERV_TYPE_FIFO; serv->listen_fd_count = 1; @@ -446,6 +455,9 @@ MASTER_SERV *get_master_ent() } else if (serv->type == MASTER_SERV_TYPE_UNIX) { serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE : MAIL_CLASS_PUBLIC, name); + } else if (serv->type == MASTER_SERV_TYPE_UXDG) { + serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE : + MAIL_CLASS_PUBLIC, name); } else if (serv->type == MASTER_SERV_TYPE_FIFO) { serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE : MAIL_CLASS_PUBLIC, name); @@ -595,6 +607,7 @@ void print_master_ent(MASTER_SERV *serv) #ifdef MASTER_SERV_TYPE_PASS serv->type == MASTER_SERV_TYPE_PASS ? MASTER_XPORT_NAME_PASS : #endif + serv->type == MASTER_SERV_TYPE_UXDG ? MASTER_XPORT_NAME_UXDG : "unknown transport type"); msg_info("listen_fd_count: %d", serv->listen_fd_count); msg_info("wakeup: %d", serv->wakeup_time); diff --git a/external/ibm-public/postfix/dist/src/master/master_listen.c b/external/ibm-public/postfix/dist/src/master/master_listen.c index b9c3d7e7548..0c6a17ab5a5 100644 --- a/external/ibm-public/postfix/dist/src/master/master_listen.c +++ b/external/ibm-public/postfix/dist/src/master/master_listen.c @@ -1,4 +1,4 @@ -/* $NetBSD: master_listen.c,v 1.1.1.3 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: master_listen.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/master/master_proto.h b/external/ibm-public/postfix/dist/src/master/master_proto.h index b4adef70cef..e5afc54b190 100644 --- a/external/ibm-public/postfix/dist/src/master/master_proto.h +++ b/external/ibm-public/postfix/dist/src/master/master_proto.h @@ -1,4 +1,4 @@ -/* $NetBSD: master_proto.h,v 1.1.1.2 2020/03/18 18:59:34 christos Exp $ */ +/* $NetBSD: master_proto.h,v 1.2 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/master/master_sig.c b/external/ibm-public/postfix/dist/src/master/master_sig.c index e5221bafc6e..d7a712891bf 100644 --- a/external/ibm-public/postfix/dist/src/master/master_sig.c +++ b/external/ibm-public/postfix/dist/src/master/master_sig.c @@ -1,4 +1,4 @@ -/* $NetBSD: master_sig.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: master_sig.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -35,6 +35,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System libraries. */ @@ -202,6 +207,15 @@ static void master_sigdeath(int sig) msg_info("terminating on signal %d", sig); /* + * Undocumented: when a process runs with PID 1, Linux won't deliver a + * signal unless the process specifies a handler (i.e. SIG_DFL is treated + * as SIG_IGN). + */ + if (init_mode) + /* Don't call exit() from a signal handler. */ + _exit(0); + + /* * Deliver the signal to ourselves and clean up. XXX We're running as a * signal handler and really should not be doing complicated things... */ diff --git a/external/ibm-public/postfix/dist/src/master/master_spawn.c b/external/ibm-public/postfix/dist/src/master/master_spawn.c index 66ac435f459..4a30f08da31 100644 --- a/external/ibm-public/postfix/dist/src/master/master_spawn.c +++ b/external/ibm-public/postfix/dist/src/master/master_spawn.c @@ -1,4 +1,4 @@ -/* $NetBSD: master_spawn.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: master_spawn.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -303,8 +303,11 @@ void master_reap_child(void) if (msg_verbose) msg_info("master_reap_child: pid %d", pid); if ((proc = (MASTER_PROC *) binhash_find(master_child_table, - (void *) &pid, sizeof(pid))) == 0) + (void *) &pid, sizeof(pid))) == 0) { + if (init_mode) + continue; /* non-Postfix process */ msg_panic("master_reap: unknown pid: %d", pid); + } serv = proc->serv; #define MASTER_KILL_SIGNAL SIGTERM diff --git a/external/ibm-public/postfix/dist/src/master/master_wakeup.c b/external/ibm-public/postfix/dist/src/master/master_wakeup.c index bb40d959e54..cedf18caa10 100644 --- a/external/ibm-public/postfix/dist/src/master/master_wakeup.c +++ b/external/ibm-public/postfix/dist/src/master/master_wakeup.c @@ -1,4 +1,4 @@ -/* $NetBSD: master_wakeup.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: master_wakeup.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -48,6 +48,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -55,6 +60,7 @@ #include <sys_defs.h> #include <unistd.h> #include <string.h> +#include <errno.h> /* Utility library. */ @@ -107,6 +113,10 @@ static void master_wakeup_timer_event(int unused_event, void *context) case MASTER_SERV_TYPE_UNIX: status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); break; + case MASTER_SERV_TYPE_UXDG: + status = -1; + errno = EOPNOTSUPP; + break; #ifdef MASTER_SERV_TYPE_PASS case MASTER_SERV_TYPE_PASS: status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); diff --git a/external/ibm-public/postfix/dist/src/master/multi_server.c b/external/ibm-public/postfix/dist/src/master/multi_server.c index da3ab70a9f2..ee288d00c95 100644 --- a/external/ibm-public/postfix/dist/src/master/multi_server.c +++ b/external/ibm-public/postfix/dist/src/master/multi_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: multi_server.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: multi_server.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -153,10 +153,12 @@ /* This value is taken from the global \fBmain.cf\fR configuration /* file. Setting \fBvar_idle_limit\fR to zero disables the idle limit. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* SEE ALSO /* master(8), master process -/* syslogd(8) system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -166,6 +168,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -175,7 +182,6 @@ #include <sys/time.h> /* select() */ #include <unistd.h> #include <signal.h> -#include <syslog.h> #include <stdlib.h> #include <limits.h> #include <string.h> @@ -194,7 +200,6 @@ /* Utility library. */ #include <msg.h> -#include <msg_syslog.h> #include <msg_vstream.h> #include <chroot_uid.h> #include <listen.h> @@ -224,6 +229,7 @@ #include <mail_flow.h> #include <mail_version.h> #include <bounce.h> +#include <maillog_client.h> /* Process manager. */ @@ -557,7 +563,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; @@ -591,7 +596,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -645,8 +650,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; case 's': @@ -673,17 +676,18 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) zerolimit = 1; break; default: - msg_fatal("invalid option: %c", c); + msg_fatal("invalid option: %c", optopt); break; } } + set_mail_conf_str(VAR_SERVNAME, service_name); /* - * Initialize generic parameters. + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for diff --git a/external/ibm-public/postfix/dist/src/master/single_server.c b/external/ibm-public/postfix/dist/src/master/single_server.c index 98656718fd2..2fef72a63c1 100644 --- a/external/ibm-public/postfix/dist/src/master/single_server.c +++ b/external/ibm-public/postfix/dist/src/master/single_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: single_server.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: single_server.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -123,22 +123,30 @@ /* .IP "CA_MAIL_SERVER_BOUNCE_INIT(const char *, const char **)" /* Initialize the DSN filter for the bounce/defer service /* clients with the specified map source and map names. +/* .IP "CA_MAIL_SERVER_RETIRE_ME" +/* Prevent a process from being reused indefinitely. After +/* (var_max_use * var_max_idle) seconds or some sane constant, +/* terminate voluntarily when the process becomes idle. /* .PP -/* The var_use_limit variable limits the number of clients that -/* a server can service before it commits suicide. -/* This value is taken from the global \fBmain.cf\fR configuration -/* file. Setting \fBvar_idle_limit\fR to zero disables the client limit. +/* The var_use_limit variable limits the number of clients +/* that a server can service before it commits suicide. This +/* value is taken from the global \fBmain.cf\fR configuration +/* file. Setting \fBvar_use_limit\fR to zero disables the +/* client limit. /* /* The var_idle_limit variable limits the time that a service /* receives no client connection requests before it commits suicide. +/* Do not change this setting before calling single_server_main(). /* This value is taken from the global \fBmain.cf\fR configuration -/* file. Setting \fBvar_use_limit\fR to zero disables the idle limit. +/* file. Setting \fBvar_idle_limit\fR to zero disables the idle limit. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* SEE ALSO /* master(8), master process -/* syslogd(8) system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -148,6 +156,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -156,7 +169,6 @@ #include <sys/socket.h> #include <unistd.h> #include <signal.h> -#include <syslog.h> #include <stdlib.h> #include <limits.h> #include <string.h> @@ -171,7 +183,6 @@ /* Utility library. */ #include <msg.h> -#include <msg_syslog.h> #include <msg_vstream.h> #include <chroot_uid.h> #include <vstring.h> @@ -200,6 +211,7 @@ #include <mail_flow.h> #include <mail_version.h> #include <bounce.h> +#include <maillog_client.h> /* Process manager. */ @@ -233,6 +245,15 @@ static NORETURN single_server_exit(void) exit(0); } +/* single_server_retire - retire when idle */ + +static NORETURN single_server_retire(int unused_event, void *unused_context) +{ + if (msg_verbose) + msg_info("time to retire -- exiting"); + single_server_exit(); +} + /* single_server_abort - terminate after abnormal master exit */ static void single_server_abort(int unused_event, void *unused_context) @@ -435,9 +456,10 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; + int retire_me_from_flags = 0; + int retire_me = 0; /* * Process environment options as early as we can. @@ -469,7 +491,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -495,7 +517,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) * stderr, because no-one is going to see them. */ opterr = 0; - while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:St:uvVz")) > 0) { + while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:r:s:St:uvVz")) > 0) { switch (c) { case 'c': root_dir = "setme"; @@ -523,10 +545,12 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; + case 'r': + if ((retire_me_from_flags = atoi(optarg)) <= 0) + msg_fatal("invalid retirement time: %s", optarg); + break; case 's': if ((socket_count = atoi(optarg)) <= 0) msg_fatal("invalid socket_count: %s", optarg); @@ -551,17 +575,17 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) zerolimit = 1; break; default: - msg_fatal("invalid option: %c", c); + msg_fatal("invalid option: %c", optopt); break; } } + set_mail_conf_str(VAR_SERVNAME, service_name); /* * Initialize generic parameters. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for @@ -645,6 +669,15 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) dsn_filter_maps = va_arg(ap, const char **); bounce_client_init(dsn_filter_title, *dsn_filter_maps); break; + case MAIL_SERVER_RETIRE_ME: + if (retire_me_from_flags > 0) + retire_me = retire_me_from_flags; + else if (var_idle_limit == 0 || var_use_limit == 0 + || var_idle_limit > 18000 / var_use_limit) + retire_me = 18000; + else + retire_me = var_idle_limit * var_use_limit; + break; default: msg_panic("%s: unknown argument type: %d", myname, key); } @@ -761,6 +794,8 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) */ if (var_idle_limit > 0) event_request_timer(single_server_timeout, (void *) 0, var_idle_limit); + if (retire_me) + event_request_timer(single_server_retire, (void *) 0, retire_me); for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) { event_enable_read(fd, single_server_accept, CAST_INT_TO_VOID_PTR(fd)); close_on_exec(fd, CLOSE_ON_EXEC); diff --git a/external/ibm-public/postfix/dist/src/master/trigger_server.c b/external/ibm-public/postfix/dist/src/master/trigger_server.c index 801a776b827..0720cbfc275 100644 --- a/external/ibm-public/postfix/dist/src/master/trigger_server.c +++ b/external/ibm-public/postfix/dist/src/master/trigger_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: trigger_server.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: trigger_server.c,v 1.3 2020/03/18 19:05:16 christos Exp $ */ /*++ /* NAME @@ -142,12 +142,14 @@ /* This value is taken from the global \fBmain.cf\fR configuration /* file. Setting \fBvar_use_limit\fR to zero disables the idle limit. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* Works with FIFO-based services only. /* SEE ALSO /* master(8), master process -/* syslogd(8) system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -157,6 +159,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -165,7 +172,6 @@ #include <sys/socket.h> #include <unistd.h> #include <signal.h> -#include <syslog.h> #include <stdlib.h> #include <limits.h> #include <string.h> @@ -180,7 +186,6 @@ /* Utility library. */ #include <msg.h> -#include <msg_syslog.h> #include <msg_vstream.h> #include <chroot_uid.h> #include <vstring.h> @@ -208,6 +213,7 @@ #include <mail_flow.h> #include <mail_version.h> #include <bounce.h> +#include <maillog_client.h> /* Process manager. */ @@ -438,7 +444,6 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; @@ -472,7 +477,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -526,8 +531,6 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; case 's': @@ -554,17 +557,18 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. zerolimit = 1; break; default: - msg_fatal("invalid option: %c", c); + msg_fatal("invalid option: %c", optopt); break; } } + set_mail_conf_str(VAR_SERVNAME, service_name); /* - * Initialize generic parameters. + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for diff --git a/external/ibm-public/postfix/dist/src/milter/milter.c b/external/ibm-public/postfix/dist/src/milter/milter.c index 48d64845816..b48d41cd773 100644 --- a/external/ibm-public/postfix/dist/src/milter/milter.c +++ b/external/ibm-public/postfix/dist/src/milter/milter.c @@ -1,4 +1,4 @@ -/* $NetBSD: milter.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: milter.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -335,18 +335,21 @@ static ARGV *milter_macro_lookup(MILTERS *milters, const char *macro_names) VSTRING *canon_buf = vstring_alloc(20); const char *value; const char *name; + const char *cname; while ((name = mystrtok(&cp, CHARS_COMMA_SP)) != 0) { if (msg_verbose) msg_info("%s: \"%s\"", myname, name); if (*name != '{') /* } */ - name = STR(vstring_sprintf(canon_buf, "{%s}", name)); - if ((value = milters->mac_lookup(name, milters->mac_context)) != 0) { + cname = STR(vstring_sprintf(canon_buf, "{%s}", name)); + else + cname = name; + if ((value = milters->mac_lookup(cname, milters->mac_context)) != 0) { if (msg_verbose) msg_info("%s: result \"%s\"", myname, value); argv_add(argv, name, value, (char *) 0); } else if (milters->macro_defaults != 0 - && (value = htable_find(milters->macro_defaults, name)) != 0) { + && (value = htable_find(milters->macro_defaults, cname)) != 0) { if (msg_verbose) msg_info("%s: using default \"%s\"", myname, value); argv_add(argv, name, value, (char *) 0); @@ -416,6 +419,8 @@ const char *milter_conn_event(MILTERS *milters, if (msg_verbose) msg_info("report connect to all milters"); for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) { + if (m->connect_on_demand != 0) + m->connect_on_demand(m); any_macros = MILTER_MACRO_EVAL(global_macros, m, milters, conn_macros); resp = m->conn_event(m, client_name, client_addr, client_port, addr_family, any_macros); diff --git a/external/ibm-public/postfix/dist/src/milter/milter.h b/external/ibm-public/postfix/dist/src/milter/milter.h index 010bfc06dc4..d46adc16582 100644 --- a/external/ibm-public/postfix/dist/src/milter/milter.h +++ b/external/ibm-public/postfix/dist/src/milter/milter.h @@ -1,4 +1,4 @@ -/* $NetBSD: milter.h,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: milter.h,v 1.3 2020/03/18 19:05:17 christos Exp $ */ #ifndef _MILTER_H_INCLUDED_ #define _MILTER_H_INCLUDED_ @@ -37,6 +37,7 @@ typedef struct MILTER { struct MILTER *next; /* linkage */ struct MILTERS *parent; /* parent information */ struct MILTER_MACROS *macros; /* private macros */ + void (*connect_on_demand) (struct MILTER *); const char *(*conn_event) (struct MILTER *, const char *, const char *, const char *, unsigned, ARGV *); const char *(*helo_event) (struct MILTER *, const char *, int, ARGV *); const char *(*mail_event) (struct MILTER *, const char **, ARGV *); @@ -166,7 +167,7 @@ extern void milter_free(MILTERS *); /* * Sendmail 8 macro names. We support forms with and without the {}. */ -#define S8_MAC__ "{_}" /* sender resolve */ +#define S8_MAC__ "{_}" /* sender host, see client_resolve */ #define S8_MAC_J "{j}" /* myhostname */ #define S8_MAC_V "{v}" /* mail_name + mail_version */ @@ -181,6 +182,9 @@ extern void milter_free(MILTERS *); #define S8_MAC_CLIENT_PTR "{client_ptr}" #define S8_MAC_CLIENT_RES "{client_resolve}" +#define S8_MAC_DAEMON_ADDR "{daemon_addr}" +#define S8_MAC_DAEMON_PORT "{daemon_port}" + #define S8_MAC_TLS_VERSION "{tls_version}" #define S8_MAC_CIPHER "{cipher}" #define S8_MAC_CIPHER_BITS "{cipher_bits}" diff --git a/external/ibm-public/postfix/dist/src/milter/milter8.c b/external/ibm-public/postfix/dist/src/milter/milter8.c index 1ce62218b61..d85f7001e6e 100644 --- a/external/ibm-public/postfix/dist/src/milter/milter8.c +++ b/external/ibm-public/postfix/dist/src/milter/milter8.c @@ -1,4 +1,4 @@ -/* $NetBSD: milter8.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: milter8.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -53,6 +53,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -665,14 +670,11 @@ static int vmilter8_read_data(MILTER8 *milter, ssize_t *data_len, va_list ap) return (milter8_comm_error(milter)); } buf = va_arg(ap, VSTRING *); - VSTRING_RESET(buf); - VSTRING_SPACE(buf, *data_len); - if (vstream_fread(milter->fp, (void *) STR(buf), *data_len) + if (vstream_fread_buf(milter->fp, buf, *data_len) != *data_len) { msg_warn("milter %s: EOF while reading data: %m", milter->m.name); return (milter8_comm_error(milter)); } - VSTRING_AT_OFFSET(buf, *data_len); *data_len = 0; break; @@ -1918,15 +1920,6 @@ static const char *milter8_conn_event(MILTER *m, #define STR_NE(x,y) (strcmp((x), (y)) != 0) /* - * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds - * out that the SMTP client has disconnected. Because of this, Postfix - * has to open a new MTA-to-filter socket for each SMTP client. - */ -#ifdef LIBMILTER_AUTO_DISCONNECT - milter8_connect(milter); -#endif - - /* * Report the event. */ switch (milter->state) { @@ -2835,6 +2828,10 @@ static MILTER8 *milter8_alloc(const char *name, int conn_timeout, /* * Fill in the structure. Note: all strings must be copied. + * + * XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds + * out that the SMTP client has disconnected. Because of this, Postfix + * has to open a new MTA-to-filter socket for each SMTP client. */ milter = (MILTER8 *) mymalloc(sizeof(*milter)); milter->m.name = mystrdup(name); @@ -2842,6 +2839,11 @@ static MILTER8 *milter8_alloc(const char *name, int conn_timeout, milter->m.next = 0; milter->m.parent = parent; milter->m.macros = 0; +#ifdef LIBMILTER_AUTO_DISCONNECT + milter->m.connect_on_demand = (void (*) (struct MILTER *)) milter8_connect; +#else + milter->m.connect_on_demand = 0; +#endif milter->m.conn_event = milter8_conn_event; milter->m.helo_event = milter8_helo_event; milter->m.mail_event = milter8_mail_event; diff --git a/external/ibm-public/postfix/dist/src/milter/test-milter.c b/external/ibm-public/postfix/dist/src/milter/test-milter.c index b336f0abe92..85d5ac0db2f 100644 --- a/external/ibm-public/postfix/dist/src/milter/test-milter.c +++ b/external/ibm-public/postfix/dist/src/milter/test-milter.c @@ -1,4 +1,4 @@ -/* $NetBSD: test-milter.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */ +/* $NetBSD: test-milter.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -20,7 +20,8 @@ /* Arguments (multiple alternatives are separated by "\fB|\fR"): /* .IP "\fB-a accept|tempfail|reject|discard|skip|\fIddd x.y.z text\fR" /* Specifies a non-default reply for the MTA command specified -/* with \fB-c\fR. The default is \fBtempfail\fR. +/* with \fB-c\fR. The default is \fBtempfail\fR. The \fItext\fR +/* is repeated once, to produce multi-line reply text. /* .IP "\fB-A address\fR" /* Add the specified recipient address (specify ESMTP parameters /* separated by space). Multiple -A options are supported. @@ -70,6 +71,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #include <sys/types.h> @@ -187,7 +193,9 @@ static const char *macro_names[] = { "{client_port}", "{client_ptr}", "{client_resolve}", + "{daemon_addr}", "{daemon_name}", + "{daemon_port}", "{if_addr}", "{if_name}", "{mail_addr}", @@ -213,7 +221,7 @@ static int test_reply(SMFICTX *ctx, int code) if (code == SMFIR_REPLYCODE) { if (smfi_setmlreply(ctx, reply_code, reply_dsn, reply_message, reply_message, (char *) 0) == MI_FAILURE) fprintf(stderr, "smfi_setmlreply failed\n"); - printf("test_reply %s\n", reply_code); + printf("test_reply %s\n\n", reply_code); return (reply_code[0] == '4' ? SMFIS_TEMPFAIL : SMFIS_REJECT); } else { printf("test_reply %d\n\n", code); diff --git a/external/ibm-public/postfix/dist/src/oqmgr/qmgr.c b/external/ibm-public/postfix/dist/src/oqmgr/qmgr.c index 9e1725d031e..2fbc1e6cf3b 100644 --- a/external/ibm-public/postfix/dist/src/oqmgr/qmgr.c +++ b/external/ibm-public/postfix/dist/src/oqmgr/qmgr.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: qmgr.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -129,7 +129,8 @@ /* does not talk to the outside world, and it can be run at fixed low /* privilege in a chrooted environment. /* DIAGNOSTICS -/* Problems and transactions are logged to the \fBsyslog\fR(8) daemon. +/* Problems and transactions are logged to the \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8) daemon. /* Corrupted message files are saved to the \fBcorrupt\fR queue /* for further inspection. /* @@ -190,31 +191,44 @@ /* .IP "\fBdefault_destination_concurrency_limit (20)\fR" /* The default maximal number of parallel deliveries to the same /* destination. -/* .IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .PP /* Available in Postfix version 2.5 and later: -/* .IP "\fItransport\fB_initial_destination_concurrency ($initial_destination_concurrency)\fR" -/* Initial concurrency for delivery via the named message -/* \fItransport\fR. +/* .IP "\fBtransport_initial_destination_concurrency ($initial_destination_concurrency)\fR" +/* A transport-specific override for the initial_destination_concurrency +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .IP "\fBdefault_destination_concurrency_failed_cohort_limit (1)\fR" /* How many pseudo-cohorts must suffer connection or handshake /* failure before a specific destination is considered unavailable /* (and further delivery is suspended). -/* .IP "\fItransport\fB_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_failed_cohort_limit parameter value, +/* where \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .IP "\fBdefault_destination_concurrency_negative_feedback (1)\fR" /* The per-destination amount of delivery concurrency negative /* feedback, after a delivery completes with a connection or handshake /* failure. -/* .IP "\fItransport\fB_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_negative_feedback parameter value, +/* where \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .IP "\fBdefault_destination_concurrency_positive_feedback (1)\fR" /* The per-destination amount of delivery concurrency positive /* feedback, after a delivery completes without connection or handshake /* failure. -/* .IP "\fItransport\fB_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_positive_feedback parameter value, +/* where \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .IP "\fBdestination_concurrency_feedback_debug (no)\fR" /* Make the queue manager's feedback algorithm verbose for performance /* analysis purposes. @@ -223,8 +237,11 @@ /* .fi /* .IP "\fBdefault_destination_recipient_limit (50)\fR" /* The default maximal number of recipients per message delivery. -/* .IP \fItransport\fB_destination_recipient_limit\fR -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +/* A transport-specific override for the +/* default_destination_recipient_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. /* OTHER RESOURCE AND RATE CONTROLS /* .ad /* .fi @@ -253,18 +270,22 @@ /* Available in Postfix version 2.5 and later: /* .IP "\fBdefault_destination_rate_delay (0s)\fR" /* The default amount of delay that is inserted between individual -/* deliveries to the same destination; the resulting behavior depends -/* on the value of the corresponding per-destination recipient limit. -/* .IP "\fItransport\fB_destination_rate_delay $default_destination_rate_delay\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* message deliveries to the same destination and over the same message +/* delivery transport. +/* .IP "\fBtransport_destination_rate_delay ($default_destination_rate_delay)\fR" +/* A transport-specific override for the default_destination_rate_delay +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .PP /* Available in Postfix version 3.1 and later: /* .IP "\fBdefault_transport_rate_delay (0s)\fR" /* The default amount of delay that is inserted between individual -/* deliveries over the same message delivery transport, regardless of -/* destination. -/* .IP "\fItransport\fB_transport_rate_delay $default_transport_rate_delay\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* message deliveries over the same message delivery transport, +/* regardless of destination. +/* .IP "\fBtransport_transport_rate_delay ($default_transport_rate_delay)\fR" +/* A transport-specific override for the default_transport_rate_delay +/* parameter value, where the initial \fItransport\fR in the parameter +/* name is the master.cf name of the message delivery transport. /* SAFETY CONTROLS /* .ad /* .fi @@ -303,13 +324,22 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 3.0 and later: /* .IP "\fBconfirm_delay_cleared (no)\fR" /* After sending a "your message is delayed" notification, inform /* the sender when the delay clears up. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* FILES /* /var/spool/postfix/incoming, incoming queue /* /var/spool/postfix/active, active queue @@ -323,6 +353,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/oqmgr/qmgr.h b/external/ibm-public/postfix/dist/src/oqmgr/qmgr.h index 7a34b121a87..2021f148b18 100644 --- a/external/ibm-public/postfix/dist/src/oqmgr/qmgr.h +++ b/external/ibm-public/postfix/dist/src/oqmgr/qmgr.h @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr.h,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: qmgr.h,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -401,6 +401,7 @@ struct QMGR_SCAN { #define QMGR_FLUSH_ONCE (1<<2) /* unthrottle once */ #define QMGR_FLUSH_DFXP (1<<3) /* override defer_transports */ #define QMGR_FLUSH_EACH (1<<4) /* unthrottle per message */ +#define QMGR_FORCE_EXPIRE (1<<5) /* force-defer and force-expire */ /* * qmgr_scan.c @@ -425,4 +426,9 @@ extern char *qmgr_error_nexthop(DSN *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/oqmgr/qmgr_active.c b/external/ibm-public/postfix/dist/src/oqmgr/qmgr_active.c index 2510dc83505..f48d4d6e501 100644 --- a/external/ibm-public/postfix/dist/src/oqmgr/qmgr_active.c +++ b/external/ibm-public/postfix/dist/src/oqmgr/qmgr_active.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr_active.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: qmgr_active.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -72,6 +72,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -109,6 +114,7 @@ #include <abounce.h> #include <rec_type.h> #include <qmgr_user.h> +#include <info_log_addr_form.h> /* Application-specific. */ @@ -230,14 +236,19 @@ int qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id) * a minimal amount of time. */ #define QMGR_FLUSH_AFTER (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP) +#define MAYBE_FLUSH_AFTER(mode) \ + (((mode) & MAIL_QUEUE_STAT_UNTHROTTLE) ? QMGR_FLUSH_AFTER : 0) +#define MAYBE_FORCE_EXPIRE(mode) \ + (((mode) & MAIL_QUEUE_STAT_EXPIRE) ? QMGR_FORCE_EXPIRE : 0) +#define MAYBE_UPDATE_MODE(mode) \ + (((mode) & MAIL_QUEUE_STAT_UNTHROTTLE) ? \ + (mode) & ~MAIL_QUEUE_STAT_UNTHROTTLE : 0) if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id, - (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ? - scan_info->flags | QMGR_FLUSH_AFTER : - scan_info->flags, - (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ? - st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE : - 0)) == 0) { + scan_info->flags + | MAYBE_FLUSH_AFTER(st.st_mode) + | MAYBE_FORCE_EXPIRE(st.st_mode), + MAYBE_UPDATE_MODE(st.st_mode))) == 0) { qmgr_active_corrupt(queue_id); return (0); } else if (message == QMGR_MESSAGE_LOCKED) { @@ -429,6 +440,7 @@ static void qmgr_active_done_25_trace_flush(int status, void *context) static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) { const char *myname = "qmgr_active_done_25_generic"; + const char *expire_status = 0; /* * If we get to this point we have tried all recipients for this message. @@ -438,10 +450,18 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) * daemon waits for the qmgr to accept the "new mail" trigger. */ if (message->flags) { - if (event_time() >= message->create_time + - (*message->sender ? var_max_queue_time : var_dsn_queue_time)) { - msg_info("%s: from=<%s>, status=expired, returned to sender", - message->queue_id, message->sender); + if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) { + expire_status = "force-expired"; + } else if (event_time() >= message->create_time + + (*message->sender ? var_max_queue_time : var_dsn_queue_time)) { + expire_status = "expired"; + } else { + expire_status = 0; + } + if (expire_status != 0) { + msg_info("%s: from=<%s>, status=%s, returned to sender", + message->queue_id, info_log_addr_form_sender(message->sender), + expire_status); if (message->verp_delims == 0 || var_verp_bounce_off) adefer_flush(BOUNCE_FLAG_KEEP, message->queue_name, diff --git a/external/ibm-public/postfix/dist/src/oqmgr/qmgr_error.c b/external/ibm-public/postfix/dist/src/oqmgr/qmgr_error.c index bdc03f465ee..500b9eb731b 100644 --- a/external/ibm-public/postfix/dist/src/oqmgr/qmgr_error.c +++ b/external/ibm-public/postfix/dist/src/oqmgr/qmgr_error.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr_error.c,v 1.1.1.2 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: qmgr_error.c,v 1.2 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/oqmgr/qmgr_message.c b/external/ibm-public/postfix/dist/src/oqmgr/qmgr_message.c index 9f8e166bb67..a70c9eac330 100644 --- a/external/ibm-public/postfix/dist/src/oqmgr/qmgr_message.c +++ b/external/ibm-public/postfix/dist/src/oqmgr/qmgr_message.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr_message.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: qmgr_message.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -91,6 +91,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -602,17 +607,18 @@ static int qmgr_message_read(QMGR_MESSAGE *message) continue; } if (rec_type == REC_TYPE_DSN_ENVID) { - if (message->dsn_envid == 0) - message->dsn_envid = mystrdup(start); + /* Allow Milter override. */ + if (message->dsn_envid != 0) + myfree(message->dsn_envid); + message->dsn_envid = mystrdup(start); } if (rec_type == REC_TYPE_DSN_RET) { - if (message->dsn_ret == 0) { - if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n)) - msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s", - message->queue_id, start); - else - message->dsn_ret = n; - } + /* Allow Milter override. */ + if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n)) + msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s", + message->queue_id, start); + else + message->dsn_ret = n; } if (rec_type == REC_TYPE_ATTR) { /* Allow extra segment to override envelope segment info. */ @@ -1074,6 +1080,21 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) } /* + * Redirect a forced-to-expire message without defer log to the retry + * service, so that its defer log will contain an appropriate reason. + * Do not redirect such a message to the error service, because if + * that request fails, a defer log would be created with reason + * "bounce or trace service failure" which would make no sense. Note + * that if the bounce service fails to create a defer log, the + * message will be returned as undeliverable anyway, because it is + * expired. + */ + if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) { + QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY, + "4.7.0 message is administratively expired"); + } + + /* * Discard mail to the local double bounce address here, so this * system can run without a local delivery agent. They'd still have * to configure something for mail directed to the local postmaster, @@ -1345,6 +1366,7 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id, { const char *myname = "qmgr_message_alloc"; QMGR_MESSAGE *message; + struct stat st; if (msg_verbose) msg_info("%s: %s %s", myname, queue_name, queue_id); @@ -1384,6 +1406,25 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id, msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp)); /* + * If this message is forced to expire, use the existing defer + * logfile records and do not assign any deliveries, leaving the + * refcount at zero. If this message is forced to expire, but no + * defer logfile records are available, assign deliveries to the + * retry transport so that the sender will still find out what + * recipients are affected and why. Either way, do not assign normal + * deliveries because that would be undesirable especially with mail + * that was expired in the 'hold' queue. + */ + if ((message->qflags & QMGR_FORCE_EXPIRE) != 0 + && stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_DEFER, + queue_id), &st) == 0 && st.st_size > 0) { + /* Use this defer log; don't assign deliveries (refcount == 0). */ + message->flags = 1; /* simplify downstream code */ + qmgr_message_close(message); + return (message); + } + + /* * Reset the defer log. This code should not be here, but we must * reset the defer log *after* acquiring the exclusive lock on the * queue file and *before* resolving new recipients. Since all those diff --git a/external/ibm-public/postfix/dist/src/pickup/pickup.c b/external/ibm-public/postfix/dist/src/pickup/pickup.c index 12b75a1f53c..013da9532fe 100644 --- a/external/ibm-public/postfix/dist/src/pickup/pickup.c +++ b/external/ibm-public/postfix/dist/src/pickup/pickup.c @@ -1,4 +1,4 @@ -/* $NetBSD: pickup.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: pickup.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -29,7 +29,8 @@ /* what files it opens for reading, and does not actually touch any data /* that is sent to its public service endpoint. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* The \fBpickup\fR(8) daemon copies mail from file to the \fBcleanup\fR(8) /* daemon. It could avoid message copying overhead by sending a file @@ -80,8 +81,17 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* SEE ALSO /* cleanup(8), message canonicalization /* sendmail(1), Sendmail-compatible interface @@ -89,6 +99,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad @@ -147,6 +158,7 @@ #include <rec_attr_map.h> #include <mail_version.h> #include <smtputf8.h> +#include <info_log_addr_form.h> /* Single-threaded server skeleton. */ @@ -360,12 +372,12 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, if (MAIL_IS_REQUEUED(info)) { msg_info("%s: uid=%d from=<%s> orig_id=%s", info->id, - (int) info->st.st_uid, info->sender, + (int) info->st.st_uid, info_log_addr_form_sender(info->sender), ((name = strrchr(info->path, '/')) != 0 ? name + 1 : info->path)); } else { msg_info("%s: uid=%d from=<%s>", info->id, - (int) info->st.st_uid, info->sender); + (int) info->st.st_uid, info_log_addr_form_sender(info->sender)); } /* diff --git a/external/ibm-public/postfix/dist/src/pipe/pipe.c b/external/ibm-public/postfix/dist/src/pipe/pipe.c index 25e6ac4e7d0..426c01c5be2 100644 --- a/external/ibm-public/postfix/dist/src/pipe/pipe.c +++ b/external/ibm-public/postfix/dist/src/pipe/pipe.c @@ -1,4 +1,4 @@ -/* $NetBSD: pipe.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: pipe.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -193,7 +193,7 @@ /* .sp /* Specify "{" and "}" around command arguments that contain /* whitespace (Postfix 3.0 and later). Whitespace -/* after "{" and before "}" is ignored. +/* after the opening "{" and before the closing "}" is ignored. /* .sp /* In the command argument vector, the following macros are recognized /* and replaced with corresponding information from the Postfix queue @@ -333,7 +333,8 @@ /* This command output is not examined for the presence of an /* enhanced status code. /* -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* Corrupted message files are marked so that the queue manager /* can move them to the \fBcorrupt\fR queue for further inspection. /* SECURITY @@ -356,22 +357,22 @@ /* .fi /* In the text below, \fItransport\fR is the first field in a /* \fBmaster.cf\fR entry. -/* .IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -/* Limit the number of parallel deliveries to the same destination, -/* for delivery via the named \fItransport\fR. -/* The limit is enforced by the Postfix queue manager. -/* .IP "\fItransport\fB_destination_recipient_limit ($default_destination_recipient_limit)\fR" -/* Limit the number of recipients per message delivery, for delivery -/* via the named \fItransport\fR. -/* The limit is enforced by the Postfix queue manager. -/* .IP "\fItransport\fB_time_limit ($command_time_limit)\fR" -/* Limit the time for delivery to external command, for delivery via -/* the named \fItransport\fR. -/* The limit is enforced by the pipe delivery agent. -/* -/* Postfix 2.4 and later support a suffix that specifies the -/* time unit: s (seconds), m (minutes), h (hours), d (days), -/* w (weeks). The default time unit is seconds. +/* .IP "\fBtransport_time_limit ($command_time_limit)\fR" +/* A transport-specific override for the command_time_limit parameter +/* value, where \fItransport\fR is the master.cf name of the message +/* delivery transport. +/* .PP +/* Implemented in the qmgr(8) daemon: +/* .IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. +/* .IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +/* A transport-specific override for the +/* default_destination_recipient_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. /* MISCELLANEOUS CONTROLS /* .ad /* .fi @@ -412,20 +413,34 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 3.0 and later: /* .IP "\fBpipe_delivery_status_filter ($default_delivery_status_filter)\fR" /* Optional filter for the \fBpipe\fR(8) delivery agent to change the /* delivery status code or explanatory text of successful or unsuccessful /* deliveries. +/* .PP +/* Available in Postfix version 3.3 and later: +/* .IP "\fBenable_original_recipient (yes)\fR" +/* Enable support for the original recipient address after an +/* address is rewritten to a different address (for example with +/* aliasing or with canonical mapping). +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* SEE ALSO /* qmgr(8), queue manager /* bounce(8), delivery status reports /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad diff --git a/external/ibm-public/postfix/dist/src/postalias/postalias.c b/external/ibm-public/postfix/dist/src/postalias/postalias.c index 123394c0d15..517e10ba621 100644 --- a/external/ibm-public/postfix/dist/src/postalias/postalias.c +++ b/external/ibm-public/postfix/dist/src/postalias/postalias.c @@ -1,4 +1,4 @@ -/* $NetBSD: postalias.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postalias.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -81,6 +81,10 @@ /* found to the standard output stream. The exit status is zero /* when the requested information was found. /* +/* Note: this performs a single query with the key as specified, +/* and does not make iterative queries with substrings of the +/* key as described in the aliases(5) manual page. +/* /* If a key value of \fB-\fR is specified, the program reads key /* values from the standard input stream and writes one line of /* \fIkey: value\fR output for each key that was found. The exit @@ -145,7 +149,7 @@ /* The name of the alias database source file when creating a database. /* DIAGNOSTICS /* Problems are logged to the standard error stream and to -/* \fBsyslogd\fR(8). No output means that +/* \fBsyslogd\fR(8) or \fBpostlogd\fR(8). No output means that /* no problems were detected. Duplicate entries are skipped and are /* flagged with a warning. /* @@ -182,14 +186,18 @@ /* .IP "\fBdefault_database_type (see 'postconf -d' output)\fR" /* The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1) /* and \fBpostmap\fR(1) commands. +/* .IP "\fBimport_environment (see 'postconf -d' output)\fR" +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBsmtputf8_enable (yes)\fR" /* Enable preliminary SMTPUTF8 support for the protocols described /* in RFC 6531..6533. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* STANDARDS /* RFC 822 (ARPA Internet Text Messages) /* SEE ALSO @@ -199,6 +207,7 @@ /* postconf(5), configuration parameters /* postmap(1), create/update/query lookup tables /* newaliases(1), Sendmail compatibility interface. +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad @@ -241,13 +250,13 @@ #include <vstring.h> #include <vstream.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <readlline.h> #include <stringops.h> #include <split_at.h> #include <vstring_vstream.h> #include <set_eugid.h> #include <warn_stat.h> +#include <clean_env.h> /* Global library. */ @@ -259,6 +268,8 @@ #include <mkmap.h> #include <mail_task.h> #include <dict_proxy.h> +#include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ @@ -501,8 +512,8 @@ static int postalias_queries(VSTREAM *in, char **maps, const int map_count, dicts[n] = 0; /* - * Perform all queries. Open maps on the fly, to avoid opening unecessary - * maps. + * Perform all queries. Open maps on the fly, to avoid opening + * unnecessary maps. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { for (n = 0; n < map_count; n++) { @@ -702,6 +713,7 @@ int main(int argc, char **argv) char *delkey = 0; int sequence = 0; int found; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -731,13 +743,13 @@ int main(int argc, char **argv) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); /* * Check the Postfix library version as soon as we enable logging. @@ -808,8 +820,12 @@ int main(int argc, char **argv) } } mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); mail_dict_init(); /* diff --git a/external/ibm-public/postfix/dist/src/postcat/postcat.c b/external/ibm-public/postfix/dist/src/postcat/postcat.c index b9bfd16b1fe..885ead65990 100644 --- a/external/ibm-public/postfix/dist/src/postcat/postcat.c +++ b/external/ibm-public/postfix/dist/src/postcat/postcat.c @@ -1,4 +1,4 @@ -/* $NetBSD: postcat.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postcat.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -69,6 +69,10 @@ /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" /* 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 +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* FILES @@ -112,6 +116,7 @@ #include <vstring_vstream.h> #include <stringops.h> #include <warn_stat.h> +#include <clean_env.h> /* Global library. */ @@ -124,6 +129,7 @@ #include <mail_proto.h> #include <is_header.h> #include <lex_822.h> +#include <mail_parm_split.h> /* Application-specific. */ @@ -426,6 +432,7 @@ int main(int argc, char **argv) }; char **cpp; int tries; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -488,6 +495,9 @@ int main(int argc, char **argv) * Further initialization... */ mail_conf_read(); + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); /* * Initialize. diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf.c b/external/ibm-public/postfix/dist/src/postconf/postconf.c index 7b1cc27ecde..9604f52d3d2 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf.c +++ b/external/ibm-public/postfix/dist/src/postconf/postconf.c @@ -1,4 +1,4 @@ -/* $NetBSD: postconf.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -81,14 +81,14 @@ /* By default, the \fBpostconf\fR(1) command displays the /* values of \fBmain.cf\fR configuration parameters, and warns /* about possible mis-typed parameter names (Postfix 2.9 and later). -/* It can also change \fBmain.cf\fR configuration +/* The command can also change \fBmain.cf\fR configuration /* parameter values, or display other configuration information /* about the Postfix mail system. /* /* Options: /* .IP \fB-a\fR -/* List the available SASL server plug-in types. The SASL -/* plug-in type is selected with the \fBsmtpd_sasl_type\fR +/* List the available SASL plug-in types for the Postfix SMTP +/* server. The plug-in type is selected with the \fBsmtpd_sasl_type\fR /* configuration parameter by specifying one of the names /* listed below. /* .RS @@ -103,9 +103,9 @@ /* .IP /* This feature is available with Postfix 2.3 and later. /* .IP \fB-A\fR -/* List the available SASL client plug-in types. The SASL -/* plug-in type is selected with the \fBsmtp_sasl_type\fR or -/* \fBlmtp_sasl_type\fR configuration parameters by specifying +/* List the available SASL plug-in types for the Postfix SMTP +/* client. The plug-in type is selected with the \fBsmtp_sasl_type\fR +/* or \fBlmtp_sasl_type\fR configuration parameters by specifying /* one of the names listed below. /* .RS /* .IP \fBcyrus\fR @@ -116,18 +116,14 @@ /* This feature is available with Postfix 2.3 and later. /* .IP "\fB-b\fR [\fItemplate_file\fR]" /* Display the message text that appears at the beginning of -/* delivery status notification (DSN) messages, replacing +/* delivery status notification (DSN) messages, expanding /* $\fBname\fR expressions with actual values as described in /* \fBbounce\fR(5). /* -/* To override the built-in templates, specify a template file -/* name at the end of the \fBpostconf\fR(1) command line, or -/* specify a file name in \fBmain.cf\fR with the -/* \fBbounce_template_file\fR parameter. -/* -/* To force selection of the built-in templates, specify an -/* empty template file name on the \fBpostconf\fR(1) command -/* line (in shell language: ""). +/* To override the \fBbounce_template_file\fR parameter setting, +/* specify a template file name at the end of the "\fBpostconf +/* -b\fR" 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. /* .IP "\fB-c \fIconfig_dir\fR" @@ -169,7 +165,7 @@ /* /* With \fB-F\fR, edit the \fBmaster.cf\fR configuration file, /* and replace one or more service fields with new values as -/* specied with "\fIservice/type/field=value\fR" on the +/* specified with "\fIservice/type/field=value\fR" on the /* \fBpostconf\fR(1) command line. Currently, the "command" /* field contains the command name and command arguments. this /* may change in the near future, so that the "command" field @@ -178,7 +174,7 @@ /* /* With \fB-P\fR, edit the \fBmaster.cf\fR configuration file, /* and add or update one or more service parameter settings -/* (-o parameter=value settings) with new values as specied +/* (-o parameter=value settings) with new values as specified /* with "\fIservice/type/parameter=value\fR" on the \fBpostconf\fR(1) /* command line. /* @@ -247,20 +243,26 @@ /* .IP \fBcdb\fR /* A read-optimized structure with no support for incremental /* updates. Available on systems with support for CDB databases. +/* +/* This feature is available with Postfix 2.2 and later. /* .IP \fBcidr\fR /* A table that associates values with Classless Inter-Domain /* Routing (CIDR) patterns. This is described in \fBcidr_table\fR(5). +/* +/* This feature is available with Postfix 2.2 and later. /* .IP \fBdbm\fR /* An indexed file type based on hashing. Available on systems /* with support for DBM databases. /* .IP \fBenviron\fR /* The UNIX process environment array. The lookup key is the -/* variable name. Originally implemented for testing, someone -/* may find this useful someday. +/* environment variable name; the table name is ignored. Originally +/* implemented for testing, someone may find this useful someday. /* .IP \fBfail\fR /* A table that reliably fails all requests. The lookup table /* name is used for logging. This table exists to simplify /* Postfix error tests. +/* +/* This feature is available with Postfix 2.9 and later. /* .IP \fBhash\fR /* An indexed file type based on hashing. Available on systems /* with support for Berkeley DB databases. @@ -268,10 +270,14 @@ /* A non-shared, in-memory lookup table. Example: "\fBinline:{ /* \fIkey\fB=\fIvalue\fB, { \fIkey\fB = \fItext with whitespace /* or comma\fB }}\fR". Key-value pairs are separated by -/* whitespace or comma; whitespace after "\fB{\fR" and before "\fB}\fR" -/* is ignored. Inline tables eliminate the need to create a +/* whitespace or comma; with a key-value pair inside "\fB{}\fR", +/* whitespace is ignored after the opening "\fB{\fR", around +/* the "\fB=\fR" between key and value, and before the closing +/* "\fB}\fR". Inline tables eliminate the need to create a /* database file for just a few fixed elements. See also the /* \fIstatic:\fR map type. +/* +/* This feature is available with Postfix 3.0 and later. /* .IP \fBinternal\fR /* A non-shared, in-memory hash table. Its content are lost /* when a process terminates. @@ -279,11 +285,15 @@ /* OpenLDAP LMDB database (a memory-mapped, persistent file). /* Available on systems with support for LMDB databases. This /* is described in \fBlmdb_table\fR(5). +/* +/* This feature is available with Postfix 2.11 and later. /* .IP "\fBldap\fR (read-only)" /* LDAP database client. This is described in \fBldap_table\fR(5). /* .IP "\fBmemcache\fR" /* Memcache database client. This is described in /* \fBmemcache_table\fR(5). +/* +/* This feature is available with Postfix 2.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). @@ -293,6 +303,8 @@ /* .IP "\fBpgsql\fR (read-only)" /* PostgreSQL database client. This is described in /* \fBpgsql_table\fR(5). +/* +/* This feature is available with Postfix 2.1 and later. /* .IP "\fBpipemap\fR (read-only)" /* A lookup table that constructs a pipeline of tables. Example: /* "\fBpipemap:{\fItype_1:name_1, ..., type_n:name_n\fB}\fR". @@ -304,9 +316,13 @@ /* "pipemap:" table name must be "\fB{\fR" and "\fB}\fR". /* Within these, individual maps are separated with comma or /* whitespace. +/* +/* This feature is available with Postfix 3.0 and later. /* .IP "\fBproxy\fR" /* Postfix \fBproxymap\fR(8) client for shared access to Postfix /* databases. The table name syntax is \fItype\fB:\fIname\fR. +/* +/* This feature is available with Postfix 2.0 and later. /* .IP "\fBrandmap\fR (read-only)" /* An in-memory table that performs random selection. Example: /* "\fBrandmap:{\fIresult_1, ..., result_n\fB}\fR". Each table query @@ -315,26 +331,38 @@ /* "\fB{\fR" and "\fB}\fR". 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. /* .IP "\fBregexp\fR (read-only)" /* A lookup table based on regular expressions. The file format /* is described in \fBregexp_table\fR(5). /* .IP \fBsdbm\fR /* An indexed file type based on hashing. Available on systems /* with support for SDBM databases. +/* +/* This feature is available with Postfix 2.2 and later. /* .IP "\fBsocketmap\fR (read-only)" /* Sendmail-style socketmap client. The table name is /* \fBinet\fR:\fIhost\fR:\fIport\fR:\fIname\fR for a TCP/IP /* server, or \fBunix\fR:\fIpathname\fR:\fIname\fR for a /* UNIX-domain server. This is described in \fBsocketmap_table\fR(5). +/* +/* This feature is available with Postfix 2.10 and later. /* .IP "\fBsqlite\fR (read-only)" /* SQLite database. This is described in \fBsqlite_table\fR(5). +/* +/* This feature is available with Postfix 2.8 and later. /* .IP "\fBstatic\fR (read-only)" /* A table that always returns its name as lookup result. For /* example, \fBstatic:foobar\fR always returns the string /* \fBfoobar\fR as lookup result. Specify "\fBstatic:{ \fItext /* with whitespace\fB }\fR" when the result contains whitespace; -/* this form ignores whitespace after "\fB{\fR" and before +/* this form ignores whitespace after the opening "\fB{\fR" +/* and before the closing /* "\fB}\fR". See also the \fIinline:\fR map. +/* +/* The form "\fBstatic:{\fItext\fB}\fR is available with Postfix +/* 3.0 and later. /* .IP "\fBtcp\fR (read-only)" /* TCP/IP client. The protocol is described in \fBtcp_table\fR(5). /* .IP "\fBtexthash\fR (read-only)" @@ -342,10 +370,14 @@ /* don't need to run the \fBpostmap\fR(1) command before you /* can use the file, and that it does not detect changes after /* the file is read. +/* +/* This feature is available with Postfix 2.8 and later. /* .IP "\fBunionmap\fR (read-only)" /* 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 \fBpipemap\fR. +/* +/* This feature is available with Postfix 3.0 and later. /* .IP "\fBunix\fR (read-only)" /* A limited view of the UNIX authentication database. The /* following tables are implemented: @@ -388,7 +420,13 @@ /* Show only configuration parameters that have explicit /* \fIname=value\fR settings in \fBmain.cf\fR. Specify \fB-nf\fR /* to fold long lines for human readability (Postfix 2.9 and -/* later). +/* later). To show settings that differ from built-in defaults +/* only, use the following bash syntax: +/* .nf +/* comm -23 <(postconf -n) <(postconf -d) +/* .fi +/* Replace "-23" with "-12" to show settings that duplicate +/* built-in defaults. /* .IP "\fB-o \fIname=value\fR" /* Override \fBmain.cf\fR parameter settings. /* @@ -415,14 +453,10 @@ /* of delivery status notification (DSN) messages, without /* expanding $\fBname\fR expressions. /* -/* To override the built-in templates, specify a template file -/* name at the end of the \fBpostconf\fR(1) command line, or -/* specify a file name in \fBmain.cf\fR with the -/* \fBbounce_template_file\fR parameter. -/* -/* To force selection of the built-in templates, specify an -/* empty template file name on the \fBpostconf\fR(1) command -/* line (in shell language: ""). +/* To override the \fBbounce_template_file\fR parameter setting, +/* specify a template file name at the end of the "\fBpostconf +/* -t\fR" 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. /* .IP "\fB-T \fImode\fR" @@ -464,7 +498,7 @@ /* /* With \fB-P\fR, edit the \fBmaster.cf\fR configuration file, /* and remove one or more service parameter settings (-o -/* parameter=value settings) as specied with +/* parameter=value settings) as specified with /* "\fIservice/type/parameter\fR" on the \fBpostconf\fR(1) /* command line. /* @@ -897,6 +931,20 @@ int main(int argc, char **argv) } /* + * We don't enforce import_environment consistency in this program. + * + * We don't extract import_environment from main.cf, because the postconf + * command must be able to extract parameter settings from main.cf before + * all installation parameters such as mail_owner or setgid_group have a + * legitimate value. + * + * We would need the functionality of mail_params_init() including all the + * side effects of populating the CONFIG_DICT with default values so that + * $name expansion works correctly, but excluding all the parameter value + * sanity checks so that it would not abort at installation time. + */ + + /* * Make all options explicit, before checking their compatibility. */ #define PCF_MAIN_OR_MASTER \ @@ -975,6 +1023,7 @@ 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(); } /* diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf.h b/external/ibm-public/postfix/dist/src/postconf/postconf.h index 198d28652bb..4669d268fc1 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf.h +++ b/external/ibm-public/postfix/dist/src/postconf/postconf.h @@ -1,4 +1,4 @@ -/* $NetBSD: postconf.h,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf.h,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -77,6 +77,9 @@ typedef struct { ((node)->flags = (((node)->flags & ~PCF_PARAM_MASK_CLASS) | (class))) #define PCF_RAW_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_RAW) +#define PCF_BUILTIN_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_BUILTIN) +#define PCF_SERVICE_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_SERVICE) +#define PCF_USER_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_USER) #define PCF_LEGACY_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_LEGACY) #define PCF_READONLY_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_READONLY) #define PCF_DBMS_PARAMETER(node) ((node)->flags & PCF_PARAM_FLAG_DBMS) @@ -120,6 +123,7 @@ typedef struct { char *name_space; /* service/type, parameter name space */ ARGV *argv; /* null, or master.cf fields */ DICT *all_params; /* null, or all name=value entries */ + DICT *ro_params; /* read-only name=value entries */ HTABLE *valid_names; /* null, or "valid" parameter names */ } PCF_MASTER_ENT; @@ -150,7 +154,7 @@ typedef struct { * Lookup table for master.cf entries. The table is terminated with an entry * that has a null argv member. */ -PCF_MASTER_ENT *pcf_master_table; +extern PCF_MASTER_ENT *pcf_master_table; /* * Line-wrapping support. diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf_builtin.c b/external/ibm-public/postfix/dist/src/postconf/postconf_builtin.c index 899fdb3794d..ea69c79e0e4 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf_builtin.c +++ b/external/ibm-public/postfix/dist/src/postconf/postconf_builtin.c @@ -1,4 +1,4 @@ -/* $NetBSD: postconf_builtin.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf_builtin.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -175,6 +175,7 @@ static const CONFIG_STR_FN_TABLE pcf_str_fn_table[] = { * effects, then those side effects must happen only once. */ static CONFIG_STR_TABLE pcf_adhoc_procname = {VAR_PROCNAME}; +static CONFIG_STR_TABLE pcf_adhoc_servname = {VAR_SERVNAME}; static CONFIG_INT_TABLE pcf_adhoc_pid = {VAR_PID}; #define STR(x) vstring_str(x) @@ -447,6 +448,10 @@ void pcf_register_builtin_parameters(const char *procname, pid_t pid) PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_procname.name, PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY, (void *) &pcf_adhoc_procname, pcf_conv_str_parameter); + pcf_adhoc_servname.defval = mystrdup(""); + PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_servname.name, + PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY, + (void *) &pcf_adhoc_servname, pcf_conv_str_parameter); pcf_adhoc_pid.defval = pid; PCF_PARAM_TABLE_ENTER(pcf_param_table, pcf_adhoc_pid.name, PCF_PARAM_FLAG_BUILTIN | PCF_PARAM_FLAG_READONLY, diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf_dbms.c b/external/ibm-public/postfix/dist/src/postconf/postconf_dbms.c index f16ff7f6c63..de89119dddf 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf_dbms.c +++ b/external/ibm-public/postfix/dist/src/postconf/postconf_dbms.c @@ -1,4 +1,4 @@ -/* $NetBSD: postconf_dbms.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf_dbms.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -24,7 +24,9 @@ /* When a database type is found that supports legacy-style /* configuration, the table name is combined with each of the /* database-defined suffixes to generate candidate parameter -/* names for that database type. +/* names for that database type; if the table name specifies +/* a client configuration file, that file is scanned for unused +/* parameter settings. /* .IP flag_parameter /* A function that takes as arguments a candidate parameter /* name, parameter flags, and a PCF_MASTER_ENT pointer. The @@ -43,11 +45,18 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ #include <sys_defs.h> +#include <sys/stat.h> +#include <errno.h> #include <string.h> /* Utility library. */ @@ -63,6 +72,7 @@ #include <mail_conf.h> #include <mail_params.h> +#include <dict_ht.h> #include <dict_proxy.h> #include <dict_ldap.h> #include <dict_mysql.h> @@ -89,45 +99,36 @@ /* See ldap_table(5). */ static const char *pcf_ldap_suffixes[] = { - "bind", "bind_dn", "bind_pw", "cache", "cache_expiry", "cache_size", - "chase_referrals", "debuglevel", "dereference", "domain", - "expansion_limit", "leaf_result_attribute", "query_filter", - "recursion_limit", "result_attribute", "result_format", "scope", - "search_base", "server_host", "server_port", "size_limit", - "special_result_attribute", "terminal_result_attribute", - "timeout", "version", 0, +#include "pcf_ldap_suffixes.h" + 0, }; /* See mysql_table(5). */ static const char *pcf_mysql_suffixes[] = { - "additional_conditions", "dbname", "domain", "expansion_limit", - "hosts", "password", "query", "result_format", "select_field", - "table", "user", "where_field", 0, +#include "pcf_mysql_suffixes.h" + 0, }; /* See pgsql_table(5). */ static const char *pcf_pgsql_suffixes[] = { - "additional_conditions", "dbname", "domain", "expansion_limit", - "hosts", "password", "query", "result_format", "select_field", - "select_function", "table", "user", "where_field", 0, +#include "pcf_pgsql_suffixes.h" + 0, }; /* See sqlite_table(5). */ static const char *pcf_sqlite_suffixes[] = { - "additional_conditions", "dbpath", "domain", "expansion_limit", - "query", "result_format", "select_field", "table", "where_field", +#include "pcf_sqlite_suffixes.h" 0, }; /* See memcache_table(5). */ static const char *pcf_memcache_suffixes[] = { - "backup", "data_size_limit", "domain", "flags", "key_format", - "line_size_limit", "max_try", "memcache", "retry_pause", - "timeout", "ttl", 0, +#include "pcf_memcache_suffixes.h" + 0, }; /* @@ -147,6 +148,72 @@ static const PCF_DBMS_INFO pcf_dbms_info[] = { 0, }; +/* 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) +{ + DICT *dict; + VSTREAM *fp; + const char **cpp; + const char *name; + const char *value; + char *dict_spec; + int dir; + + /* + * We read each database client configuration file into its own + * dictionary, and nag only the first time that a file is visited. + */ + dict_spec = concatenate(dp->db_type, ":", cf_file, (char *) 0); + if ((dict = dict_handle(dict_spec)) == 0) { + struct stat st; + + /* + * Populate the dictionary with settings in this database client + * configuration file. Don't die if a file can't be opened - some + * files may contain passwords and should not be world-readable. + * Note: dict_load_fp() nags about duplicate pameter settings. + */ + dict = dict_ht_open(dict_spec, O_CREAT | O_RDWR, 0); + dict_register(dict_spec, dict); + if ((fp = vstream_fopen(cf_file, O_RDONLY, 0)) == 0) { + if (errno != EACCES) + msg_warn("open \"%s\" configuration \"%s\": %m", + dp->db_type, cf_file); + myfree(dict_spec); + return; + } + if (fstat(vstream_fileno(fp), &st) == 0 && !S_ISREG(st.st_mode)) { + msg_warn("open \"%s\" configuration \"%s\": not a regular file", + dp->db_type, cf_file); + myfree(dict_spec); + (void) vstream_fclose(fp); + return; + } + dict_load_fp(dict_spec, fp); + if (vstream_fclose(fp)) { + msg_warn("read \"%s\" configuration \"%s\": %m", + dp->db_type, cf_file); + myfree(dict_spec); + return; + } + + /* + * Remove all known database client parameters from this dictionary, + * then report the remaining ones as "unused". We use ad-hoc logging + * 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); + } + myfree(dict_spec); +} + /* pcf_register_dbms_helper - parse one possible database type:name */ static void pcf_register_dbms_helper(char *str_value, @@ -165,6 +232,19 @@ static void pcf_register_dbms_helper(char *str_value, * database or some other text. */ while ((db_type = mystrtokq(&str_value, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { + if (*db_type == CHARS_BRACE[0]) { + if ((err = extpar(&db_type, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) { + /* XXX Encapsulate this in pcf_warn() function. */ + if (local_scope) + msg_warn("%s:%s: %s", + MASTER_CONF_FILE, local_scope->name_space, err); + else + msg_warn("%s: %s", MAIN_CONF_FILE, err); + myfree(err); + } + pcf_register_dbms_helper(db_type, flag_parameter, local_scope); + continue; + } /* * Skip over "proxy:" maptypes, to emulate the proxymap(8) server's @@ -174,6 +254,28 @@ static void pcf_register_dbms_helper(char *str_value, && strcmp(db_type, DICT_TYPE_PROXY) == 0) db_type = prefix; + if (prefix == 0) + continue; + + /* + * Look for database:prefix where the prefix is an absolute pathname. + * Then, report unknown database client configuration parameters. + * + * XXX What about a pathname beginning with '.'? This supposedly is + * relative to the queue directory, which is the default directory + * for all Postfix daemon processes. This would also have to handle + * the case that the queue is not yet created. + */ + if (*prefix == '/') { + for (dp = pcf_dbms_info; dp->db_type != 0; dp++) { + if (strcmp(db_type, dp->db_type) == 0) { + pcf_check_dbms_client(dp, prefix); + break; + } + } + continue; + } + /* * Look for database:prefix where the prefix is not a pathname and * the database is a known type. Synthesize candidate parameter names @@ -181,7 +283,7 @@ static void pcf_register_dbms_helper(char *str_value, * list, and see if those parameters have a "name=value" entry in the * local or global namespace. */ - if (prefix != 0 && *prefix != '/' && *prefix != '.') { + if (*prefix != '.') { if (*prefix == CHARS_BRACE[0]) { if ((err = extpar(&prefix, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) { /* XXX Encapsulate this in pcf_warn() function. */ @@ -193,8 +295,8 @@ static void pcf_register_dbms_helper(char *str_value, msg_warn("%s: %s", MAIN_CONF_FILE, err); myfree(err); } - pcf_register_dbms_helper(prefix, flag_parameter, - local_scope); + pcf_register_dbms_helper(prefix, flag_parameter, local_scope); + continue; } else { for (dp = pcf_dbms_info; dp->db_type != 0; dp++) { if (strcmp(db_type, dp->db_type) == 0) { diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf_lookup.c b/external/ibm-public/postfix/dist/src/postconf/postconf_lookup.c index a26e84feb2b..50abb3f202b 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf_lookup.c +++ b/external/ibm-public/postfix/dist/src/postconf/postconf_lookup.c @@ -1,4 +1,4 @@ -/* $NetBSD: postconf_lookup.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf_lookup.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -75,6 +75,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -109,14 +114,17 @@ const char *pcf_lookup_parameter_value(int mode, const char *name, { const char *value = 0; +#define LOOKUP(dict, name) ((dict) ? dict_get((dict), (name)) : 0) + /* * Local name=value entries in master.cf take precedence over global * name=value entries in main.cf. Built-in defaults have the lowest * precedence. */ if ((mode & PCF_SHOW_DEFS) != 0 - || ((local_scope == 0 || local_scope->all_params == 0 - || (value = dict_get(local_scope->all_params, name)) == 0) + || ((local_scope == 0 + || ((value = LOOKUP(local_scope->ro_params, name)) == 0 + && (value = LOOKUP(local_scope->all_params, name)) == 0)) && (value = dict_lookup(CONFIG_DICT, name)) == 0 && (mode & PCF_SHOW_NONDEF) == 0)) { if (node != 0 || (node = PCF_PARAM_TABLE_FIND(pcf_param_table, name)) != 0) diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf_master.c b/external/ibm-public/postfix/dist/src/postconf/postconf_master.c index 586421cb396..899e8cdfe42 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf_master.c +++ b/external/ibm-public/postfix/dist/src/postconf/postconf_master.c @@ -1,4 +1,4 @@ -/* $NetBSD: postconf_master.c,v 1.5 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf_master.c,v 1.6 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -192,6 +192,7 @@ static const char *pcf_valid_master_types[] = { MASTER_XPORT_NAME_FIFO, MASTER_XPORT_NAME_INET, MASTER_XPORT_NAME_PASS, + MASTER_XPORT_NAME_UXDG, 0, }; @@ -355,8 +356,10 @@ void pcf_free_master_entry(PCF_MASTER_ENT *masterp) argv_free(masterp->argv); if (masterp->valid_names) htable_free(masterp->valid_names, myfree); + if (masterp->ro_params) + dict_close(masterp->ro_params); if (masterp->all_params) - dict_free(masterp->all_params); + dict_close(masterp->all_params); myfree((void *) masterp); } @@ -365,6 +368,8 @@ void pcf_free_master_entry(PCF_MASTER_ENT *masterp) const char *pcf_parse_master_entry(PCF_MASTER_ENT *masterp, const char *buf) { ARGV *argv; + char *ro_name_space; + char *process_name; /* * We can't use the master daemon's master_ent routines in their current @@ -386,8 +391,17 @@ const char *pcf_parse_master_entry(PCF_MASTER_ENT *masterp, const char *buf) pcf_normalize_daemon_args(argv); masterp->name_space = concatenate(argv->argv[0], PCF_NAMESP_SEP_STR, argv->argv[1], (char *) 0); + ro_name_space = + concatenate("ro", PCF_NAMESP_SEP_STR, masterp->name_space, (char *) 0); masterp->argv = argv; masterp->valid_names = 0; + process_name = basename(argv->argv[PCF_MASTER_FLD_CMD]); + dict_update(ro_name_space, VAR_PROCNAME, process_name); + dict_update(ro_name_space, VAR_SERVNAME, + strcmp(process_name, argv->argv[0]) != 0 ? + argv->argv[0] : process_name); + masterp->ro_params = dict_handle(ro_name_space); + myfree(ro_name_space); masterp->all_params = 0; return (0); } diff --git a/external/ibm-public/postfix/dist/src/postconf/postconf_user.c b/external/ibm-public/postfix/dist/src/postconf/postconf_user.c index 1972b098275..70ff87dbc29 100644 --- a/external/ibm-public/postfix/dist/src/postconf/postconf_user.c +++ b/external/ibm-public/postfix/dist/src/postconf/postconf_user.c @@ -1,4 +1,4 @@ -/* $NetBSD: postconf_user.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postconf_user.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -37,6 +37,11 @@ /* name spaces for user-defined parameters and flags parameters /* as "valid" in the global name space (pcf_param_table) or /* in the per-service name space (valid_params). +/* +/* This function also invokes pcf_register_dbms_parameters() to +/* 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. /* DIAGNOSTICS /* Problems are reported to the standard error stream. /* LICENSE @@ -48,6 +53,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -292,8 +302,16 @@ static void pcf_scan_user_parameter_namespace(const char *dict_name, } SCAN_USER_PARAMETER_VALUE(cparam_value, PCF_PARAM_FLAG_USER, local_scope); #ifdef LEGACY_DBMS_SUPPORT - pcf_register_dbms_parameters(cparam_value, pcf_flag_user_parameter, - local_scope); + + /* + * Scan global or local parameters that are built-in or per-service + * (when node == 0, the parameter doesn't exist in the global + * namespace and therefore it can't be built-in or per-service). + */ + if (node != 0 + && (PCF_BUILTIN_PARAMETER(node) || PCF_SERVICE_PARAMETER(node))) + pcf_register_dbms_parameters(cparam_value, pcf_flag_user_parameter, + local_scope); #endif } } diff --git a/external/ibm-public/postfix/dist/src/postdrop/postdrop.c b/external/ibm-public/postfix/dist/src/postdrop/postdrop.c index 0aba1590e57..9328c2cafcb 100644 --- a/external/ibm-public/postfix/dist/src/postdrop/postdrop.c +++ b/external/ibm-public/postfix/dist/src/postdrop/postdrop.c @@ -1,4 +1,4 @@ -/* $NetBSD: postdrop.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postdrop.c,v 1.3 2020/03/18 19:05:17 christos Exp $ */ /*++ /* NAME @@ -32,7 +32,8 @@ /* it can connect to Postfix daemon processes. /* DIAGNOSTICS /* Fatal errors: malformed input, I/O error, out of memory. Problems -/* are logged to \fBsyslogd\fR(8) and to the standard error stream. +/* are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8) and to +/* the standard error stream. /* When the input is incomplete, or when the process receives a HUP, /* INT, QUIT or TERM signal, the queue file is deleted. /* ENVIRONMENT @@ -58,21 +59,23 @@ /* \fBpostconf\fR(5) for more details including examples. /* .IP "\fBalternate_config_directories (empty)\fR" /* A list of non-default Postfix configuration directories that may -/* be specified with "-c config_directory" on the command line, or -/* via the MAIL_CONFIG environment parameter. +/* be specified with "-c config_directory" on the command line (in the +/* case of \fBsendmail\fR(1), with the "-C" option), or via the MAIL_CONFIG +/* environment parameter. /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" /* 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 Postfix process will -/* import from a non-Postfix parent process. +/* The list of environment parameters 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" /* The location of the Postfix top-level queue directory. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .IP "\fBtrigger_timeout (10s)\fR" /* The time limit for sending a trigger to a Postfix daemon (for /* example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon). @@ -86,6 +89,7 @@ /* SEE ALSO /* sendmail(1), compatibility interface /* postconf(5), configuration parameters +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad @@ -113,7 +117,6 @@ #include <string.h> #include <stdlib.h> #include <signal.h> -#include <syslog.h> #include <errno.h> #include <warn_stat.h> @@ -124,7 +127,6 @@ #include <vstream.h> #include <vstring.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <argv.h> #include <iostuff.h> #include <stringops.h> @@ -146,6 +148,7 @@ #include <user_acl.h> #include <rec_attr_map.h> #include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ @@ -186,9 +189,11 @@ static void postdrop_sig(int sig) /* * This is the fatal error handler. Don't try to do anything fancy. * - * msg_vstream does not allocate memory, but msg_syslog may indirectly in - * syslog(), so it should not be called from a user-triggered signal - * handler. + * To avoid privilege escalation in a set-gid program, Postfix logging + * functions must not be called from a user-triggered signal handler, + * because Postfix logging functions may allocate memory on the fly (as + * does the syslog() library function), and the memory allocator is not + * reentrant. * * Assume atomic signal() updates, even when emulated with sigaction(). We * use the in-kernel SIGINT handler address as an atomic variable to @@ -272,7 +277,7 @@ int main(int argc, char **argv) */ argv[0] = "postdrop"; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postdrop"), MAILLOG_CLIENT_FLAG_NONE); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -305,16 +310,11 @@ int main(int argc, char **argv) /* * Read the global configuration file and extract configuration - * information. Some claim that the user should supply the working - * directory instead. That might be OK, given that this command needs - * write permission in a subdirectory called "maildrop". However we still - * need to reliably detect incomplete input, and so we must perform - * record-level I/O. With that, we should also take the opportunity to - * perform some sanity checks on the input. + * information. */ mail_conf_read(); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postdrop"), MAILLOG_CLIENT_FLAG_NONE); get_mail_conf_str_table(str_table); /* @@ -331,7 +331,8 @@ int main(int argc, char **argv) * Stop run-away process accidents by limiting the queue file size. This * is not a defense against DOS attack. */ - if (var_message_limit > 0 && get_file_limit() > var_message_limit) + if (ENFORCING_SIZE_LIMIT(var_message_limit) + && get_file_limit() > var_message_limit) set_file_limit((off_t) var_message_limit); /* diff --git a/external/ibm-public/postfix/dist/src/postfix/postfix.c b/external/ibm-public/postfix/dist/src/postfix/postfix.c index d046c4809e7..e0ce1ed7e81 100644 --- a/external/ibm-public/postfix/dist/src/postfix/postfix.c +++ b/external/ibm-public/postfix/dist/src/postfix/postfix.c @@ -1,4 +1,4 @@ -/* $NetBSD: postfix.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postfix.c,v 1.3 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME @@ -33,6 +33,17 @@ /* .IP \fBstart\fR /* Start the Postfix mail system. This also runs the configuration /* check described above. +/* .IP \fBstart-fg\fR +/* Like \fBstart\fR, but keep the \fBmaster\fR(8) daemon running +/* in the foreground, and enable \fBmaster\fR(8) "init" mode +/* when running as PID 1. +/* This command requires that multi-instance support is +/* disabled (i.e. the multi_instance_directories parameter +/* value must be empty). When running Postfix inside a container, +/* mount the container host's /dev/log socket inside the +/* container (example: "docker run -v /dev/log:/dev/log ...") +/* and specify a distinct Postfix "syslog_name" prefix that +/* identifies logging from the Postfix instance. /* .IP \fBstop\fR /* Stop the Postfix mail system in an orderly fashion. If /* possible, running processes are allowed to terminate at @@ -68,6 +79,14 @@ /* This feature is available in Postfix 2.1 and later. With /* Postfix 2.0 and earlier, use "\fB$config_directory/post-install /* set-permissions\fR". +/* .IP "\fBlogrotate\fR" +/* Rotate the logfile specified with $maillog_file, by appending +/* a time-stamp suffix that is formatted according to +/* $maillog_file_rotate_suffix, and by compressing the file +/* with the command specified with $maillog_file_compressor. +/* This will not rotate /dev/* files. +/* .sp +/* This feature is available in Postfix 3.4 and later. /* .IP "\fBtls\fR \fIsubcommand\fR" /* Enable opportunistic TLS in the Postfix SMTP client or /* server, and manage Postfix SMTP server TLS private keys and @@ -119,6 +138,15 @@ /* This is set when the -v command-line option is present. /* .IP \fBMAIL_DEBUG\fR /* This is set when the -D command-line option is present. +/* .PP +/* When the internal logging service is enabled (by setting a +/* non-empty maillog_file parameter value) the postfix(1) +/* command exports settings that are used by child processes +/* before they have processed main.cf or command-line settings. +/* .IP \fBPOSTLOG_SERVICE +/* The name of the public postlog service endpoint. +/* .IP \fBPOSTLOG_HOSTNAME +/* The hostname to prepend to internal logging. /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -179,13 +207,14 @@ /* .PP /* Other configuration parameters: /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a Postfix process will -/* import from a non-Postfix parent process. +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 2.6 and later: /* .IP "\fBmulti_instance_directories (empty)\fR" @@ -205,6 +234,21 @@ /* .IP "\fBmulti_instance_enable (no)\fR" /* Allow this Postfix instance to be started, stopped, etc., by a /* multi-instance manager. +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBmaillog_file (empty)\fR" +/* The name of an optional logfile that is written by the Postfix +/* \fBpostlogd\fR(8) service. +/* .IP "\fBmaillog_file_compressor (gzip)\fR" +/* The program to run after rotating $maillog_file with "postfix +/* logrotate". +/* .IP "\fBmaillog_file_prefixes (/var, /dev/stdout)\fR" +/* A list of allowed prefixes for a maillog_file value. +/* .IP "\fBmaillog_file_rotate_suffix (%Y%M%d-%H%M%S)\fR" +/* The format of the suffix to append to $maillog_file while rotating +/* the file with "postfix logrotate". +/* .IP "\fBpostlog_service_name (postlog)\fR" +/* The name of the \fBpostlogd\fR(8) service entry in master.cf. /* FILES /* .ad /* .fi @@ -286,6 +330,7 @@ /* oqmgr(8), old Postfix queue manager /* pickup(8), Postfix local mail pickup /* pipe(8), deliver mail to non-Postfix command +/* postlogd(8), Postfix internal logging service /* postscreen(8), Postfix zombie blocker /* proxymap(8), Postfix lookup table proxy server /* qmgr(8), Postfix queue manager @@ -370,7 +415,6 @@ #include <unistd.h> #include <string.h> #include <fcntl.h> -#include <syslog.h> #ifdef USE_PATHS_H #include <paths.h> #endif @@ -379,7 +423,6 @@ #include <msg.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <stringops.h> #include <clean_env.h> #include <argv.h> @@ -392,6 +435,7 @@ #include <mail_params.h> #include <mail_version.h> #include <mail_parm_split.h> +#include <maillog_client.h> /* Additional installation parameters. */ @@ -466,7 +510,7 @@ int main(int argc, char **argv) argv[0] = slash + 1; if (isatty(STDERR_FILENO)) msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY); + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. @@ -516,6 +560,22 @@ int main(int argc, char **argv) get_mail_conf_str_table(str_table); /* + * Environment import filter, to enforce consistent behavior whether this + * command is started by hand, or at system boot time. This is necessary + * because some shell scripts use environment settings to override + * main.cf settings. + */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + clean_env(import_env->argv); + argv_free(import_env); + + /* + * This is after calling clean_env(), to ensure that POSTLOG_XXX exports + * will work, even if import_environment would remove them. + */ + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + + /* * Alert the sysadmin that the backwards-compatible settings are still in * effect. */ @@ -528,17 +588,6 @@ int main(int argc, char **argv) VAR_COMPAT_LEVEL "=%d\" and \"postfix reload\"", CUR_COMPAT_LEVEL); } - - /* - * Environment import filter, to enforce consistent behavior whether this - * command is started by hand, or at system boot time. This is necessary - * because some shell scripts use environment settings to override - * main.cf settings. - */ - import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); - clean_env(import_env->argv); - argv_free(import_env); - check_setenv("PATH", ROOT_PATH); /* sys_defs.h */ check_setenv(CONF_ENV_PATH, var_config_dir);/* mail_conf.h */ diff --git a/external/ibm-public/postfix/dist/src/postkick/postkick.c b/external/ibm-public/postfix/dist/src/postkick/postkick.c index ccd0ae1bb82..bb10a5267df 100644 --- a/external/ibm-public/postfix/dist/src/postkick/postkick.c +++ b/external/ibm-public/postfix/dist/src/postkick/postkick.c @@ -1,4 +1,4 @@ -/* $NetBSD: postkick.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postkick.c,v 1.3 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME @@ -55,6 +55,10 @@ /* .IP "\fBapplication_event_drain_time (100s)\fR" /* 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 +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* FILES @@ -86,7 +90,6 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> -#include <syslog.h> #include <string.h> #include <stdlib.h> @@ -99,6 +102,7 @@ #include <safe.h> #include <events.h> #include <warn_stat.h> +#include <clean_env.h> /* Global library. */ @@ -106,6 +110,7 @@ #include <mail_params.h> #include <mail_version.h> #include <mail_conf.h> +#include <mail_parm_split.h> static NORETURN usage(char *myname) { @@ -123,6 +128,7 @@ int main(int argc, char **argv) struct stat st; char *slash; int c; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -146,8 +152,8 @@ int main(int argc, char **argv) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; @@ -180,6 +186,10 @@ int main(int argc, char **argv) * Finish initializations. */ mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); if (chdir(var_queue_dir)) msg_fatal("chdir %s: %m", var_queue_dir); diff --git a/external/ibm-public/postfix/dist/src/postlock/postlock.c b/external/ibm-public/postfix/dist/src/postlock/postlock.c index 7d33420b648..dbe96b8c058 100644 --- a/external/ibm-public/postfix/dist/src/postlock/postlock.c +++ b/external/ibm-public/postfix/dist/src/postlock/postlock.c @@ -1,4 +1,4 @@ -/* $NetBSD: postlock.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postlock.c,v 1.3 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME @@ -80,6 +80,10 @@ /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" /* 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 +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* SEE ALSO /* postconf(5), configuration parameters /* LICENSE @@ -116,6 +120,7 @@ #include <msg_vstream.h> #include <iostuff.h> #include <warn_stat.h> +#include <clean_env.h> /* Global library. */ @@ -128,6 +133,7 @@ #include <mbox_conf.h> #include <mbox_open.h> #include <dsn_util.h> +#include <mail_parm_split.h> /* Application-specific. */ @@ -163,6 +169,7 @@ int main(int argc, char **argv) int lock_mask; char *lock_style = 0; MBOX *mp; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -228,6 +235,10 @@ int main(int argc, char **argv) * configured lock style. */ mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); lock_mask = mbox_lock_mask(lock_style ? lock_style : get_mail_conf_str(VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, 1, 0)); diff --git a/external/ibm-public/postfix/dist/src/postlog/postlog.c b/external/ibm-public/postfix/dist/src/postlog/postlog.c index 16f65105856..5fa0d270389 100644 --- a/external/ibm-public/postfix/dist/src/postlog/postlog.c +++ b/external/ibm-public/postfix/dist/src/postlog/postlog.c @@ -1,4 +1,4 @@ -/* $NetBSD: postlog.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ +/* $NetBSD: postlog.c,v 1.3 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME @@ -19,15 +19,18 @@ /* line, \fBpostlog\fR(1) reads from standard input and logs each input /* line as one record. /* -/* Logging is sent to \fBsyslogd\fR(8); when the standard error stream -/* is connected to a terminal, logging is sent there as well. +/* By default, logging is sent to \fBsyslogd\fR(8) or +/* \fBpostlogd\fR(8); when the +/* standard error stream is connected to a terminal, logging +/* is sent there as well. /* /* The following options are implemented: /* .IP "\fB-c \fIconfig_dir\fR" /* Read the \fBmain.cf\fR configuration file in the named directory /* instead of the default configuration directory. -/* .IP \fB-i\fR -/* Include the process ID in the logging tag. +/* .IP "\fB-i\fR (obsolete)" +/* Include the process ID in the logging tag. This flag is ignored as +/* of Postfix 3.4, where the PID is always included. /* .IP "\fB-p \fIpriority\fR (default: \fBinfo\fR)" /* Specifies the logging severity: \fBinfo\fR, \fBwarn\fR, /* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1 @@ -57,14 +60,26 @@ /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" /* 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 +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.4 and later: +/* .IP "\fBmaillog_file (empty)\fR" +/* 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. /* SEE ALSO /* postconf(5), configuration parameters -/* syslogd(8), syslog daemon +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -86,7 +101,6 @@ #include <sys_defs.h> #include <sys/stat.h> #include <string.h> -#include <syslog.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> @@ -103,8 +117,8 @@ #include <vstring_vstream.h> #include <msg_output.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <warn_stat.h> +#include <clean_env.h> /* Global library. */ @@ -112,6 +126,8 @@ #include <mail_version.h> #include <mail_conf.h> #include <mail_task.h> +#include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ @@ -158,7 +174,7 @@ static void log_argv(int level, char **argv) if (*argv) vstring_strcat(buf, " "); } - msg_text(level, vstring_str(buf)); + msg_printf(level, "%s", vstring_str(buf)); vstring_free(buf); } @@ -169,7 +185,7 @@ static void log_stream(int level, VSTREAM *fp) VSTRING *buf = vstring_alloc(100); while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) - msg_text(level, vstring_str(buf)); + msg_printf(level, "%s", vstring_str(buf)); vstring_free(buf); } @@ -183,8 +199,8 @@ int main(int argc, char **argv) int fd; int ch; const char *tag; - int log_flags = 0; int level = MSG_INFO; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -212,7 +228,7 @@ int main(int argc, char **argv) tag = mail_task(argv[0]); if (isatty(STDERR_FILENO)) msg_vstream_init(tag, VSTREAM_ERR); - msg_syslog_init(tag, LOG_PID, LOG_FACILITY); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. @@ -233,7 +249,6 @@ int main(int argc, char **argv) msg_fatal("out of memory"); break; case 'i': - log_flags |= LOG_PID; break; case 'p': level = level_map(optarg); @@ -252,6 +267,10 @@ int main(int argc, char **argv) * may require that mail_task() be re-evaluated. */ mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); if (tag == 0) tag = mail_task(argv[0]); @@ -261,7 +280,7 @@ int main(int argc, char **argv) */ if (isatty(STDERR_FILENO)) msg_vstream_init(tag, VSTREAM_ERR); - msg_syslog_init(tag, LOG_PID, LOG_FACILITY); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Log the command line or log lines from standard input. diff --git a/external/ibm-public/postfix/dist/src/postlogd/postlogd.c b/external/ibm-public/postfix/dist/src/postlogd/postlogd.c index 2597dc461a3..4f7005720dc 100644 --- a/external/ibm-public/postfix/dist/src/postlogd/postlogd.c +++ b/external/ibm-public/postfix/dist/src/postlogd/postlogd.c @@ -1,4 +1,4 @@ -/* $NetBSD: postlogd.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: postlogd.c,v 1.2 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/postmap/postmap.c b/external/ibm-public/postfix/dist/src/postmap/postmap.c index 3ea94048158..0b7970b95c5 100644 --- a/external/ibm-public/postfix/dist/src/postmap/postmap.c +++ b/external/ibm-public/postfix/dist/src/postmap/postmap.c @@ -1,4 +1,4 @@ -/* $NetBSD: postmap.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postmap.c,v 1.3 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME @@ -7,17 +7,12 @@ /* Postfix lookup table management /* SYNOPSIS /* .fi -/* \fBpostmap\fR [\fB-NbfhimnoprsuUvw\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostmap\fR [\fB-bfFhimnNoprsuUvw\fR] [\fB-c \fIconfig_dir\fR] /* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR] /* [\fIfile_type\fR:]\fIfile_name\fR ... /* DESCRIPTION /* The \fBpostmap\fR(1) command creates or queries one or more Postfix -/* lookup tables, or updates an existing one. The input and output -/* file formats are expected to be compatible with: -/* -/* .nf -/* \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR -/* .fi +/* lookup tables, or updates an existing one. /* /* If the result files do not exist they will be created with the /* same group and other read permissions as their source file. @@ -44,9 +39,20 @@ /* starts with whitespace continues a logical line. /* .PP /* The \fIkey\fR and \fIvalue\fR are processed as is, except that -/* surrounding white space is stripped off. Unlike with Postfix alias -/* databases, quotes cannot be used to protect lookup keys that contain -/* special characters such as `#' or whitespace. +/* surrounding white space is stripped off. Whitespace in lookup +/* keys is supported as of Postfix 3.2. +/* +/* When the \fB-F\fR option is given, the \fIvalue\fR must +/* specify one or more filenames separated by comma and/or +/* whitespace; \fBpostmap\fR(1) will concatenate the file +/* content (with a newline character inserted between files) +/* and will store the base64-encoded result instead of the +/* \fIvalue\fR. +/* +/* When the \fIkey\fR specifies email address information, the +/* localpart should be enclosed with double quotes if required +/* by RFC 5322. For example, an address localpart that contains +/* ";", or a localpart that starts or ends with ".". /* /* By default the lookup key is mapped to lowercase to make /* the lookups case insensitive; as of Postfix 2.3 this case @@ -62,7 +68,7 @@ /* .IP \fB-b\fR /* Enable message body query mode. When reading lookup keys /* from standard input with "\fB-q -\fR", process the input -/* as if it is an email message in RFC 2822 format. Each line +/* as if it is an email message in RFC 5322 format. Each line /* of body content becomes one lookup key. /* .sp /* By default, the \fB-b\fR option starts generating lookup @@ -96,10 +102,16 @@ /* With Postfix version 2.3 and later, this option has no /* effect for regular expression tables. There, case folding /* is controlled by appending a flag to a pattern. +/* .IP \fB-F\fR +/* When querying a map, or listing a map, base64-decode each +/* value. When creating a map from source file, process each +/* value as a list of filenames, concatenate the content of +/* those files, and store the base64-encoded result instead +/* of the value (see INPUT FORMAT for details). /* .IP \fB-h\fR /* Enable message header query mode. When reading lookup keys /* from standard input with "\fB-q -\fR", process the input -/* as if it is an email message in RFC 2822 format. Each +/* as if it is an email message in RFC 5322 format. Each /* logical header line becomes one lookup key. A multi-line /* header becomes one lookup key with one or more embedded /* newline characters. @@ -148,6 +160,11 @@ /* found to the standard output stream. The exit status is zero /* when the requested information was found. /* +/* Note: this performs a single query with the key as specified, +/* and does not make iterative queries with substrings of the +/* key as described for access(5), canonical(5), transport(5), +/* virtual(5) and other Postfix table-driven features. +/* /* If a key value of \fB-\fR is specified, the program reads key /* values from the standard input stream and writes one line of /* \fIkey value\fR output for each key that was found. The exit @@ -215,7 +232,7 @@ /* The name of the lookup table source file when rebuilding a database. /* DIAGNOSTICS /* Problems are logged to the standard error stream and to -/* \fBsyslogd\fR(8). +/* \fBsyslogd\fR(8) or \fBpostlogd\fR(8). /* No output means that no problems were detected. Duplicate entries are /* skipped and are flagged with a warning. /* @@ -248,18 +265,23 @@ /* .IP "\fBdefault_database_type (see 'postconf -d' output)\fR" /* The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1) /* and \fBpostmap\fR(1) commands. +/* .IP "\fBimport_environment (see 'postconf -d' output)\fR" +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBsmtputf8_enable (yes)\fR" /* Enable preliminary SMTPUTF8 support for the protocols described /* in RFC 6531..6533. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* SEE ALSO /* postalias(1), create/update/query alias database /* postconf(1), supported database types /* postconf(5), configuration parameters +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad @@ -302,13 +324,13 @@ #include <vstring.h> #include <vstream.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <readlline.h> #include <stringops.h> #include <split_at.h> #include <vstring_vstream.h> #include <set_eugid.h> #include <warn_stat.h> +#include <clean_env.h> /* Global library. */ @@ -321,6 +343,8 @@ #include <dict_proxy.h> #include <mime_state.h> #include <rec_type.h> +#include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ @@ -423,10 +447,12 @@ static void postmap(char *map_type, char *path_name, int postmap_flags, msg_fatal("seek %s: %m", VSTREAM_PATH(source_fp)); /* - * Add records to the database. + * Add records to the database. XXX This duplicates the parser in + * dict_thash.c. */ last_line = 0; while (readllines(line_buffer, source_fp, &last_line, &lineno)) { + int in_quotes = 0; /* * First some UTF-8 checks sans casefolding. @@ -441,19 +467,41 @@ static void postmap(char *map_type, char *path_name, int postmap_flags, } /* - * Split on the first whitespace character, then trim leading and - * trailing whitespace from key and value. + * Terminate the key on the first unquoted whitespace character, + * then trim leading and trailing whitespace from the value. */ - key = STR(line_buffer); - value = key + strcspn(key, CHARS_SPACE); + for (value = STR(line_buffer); *value; value++) { + if (*value == '\\') { + if (*++value == 0) + break; + } else if (ISSPACE(*value)) { + if (!in_quotes) + break; + } else if (*value == '"') { + in_quotes = !in_quotes; + } + } + if (in_quotes) { + msg_warn("%s, line %d: unbalanced '\"' in '%s'" + " -- ignoring this line", + VSTREAM_PATH(source_fp), lineno, STR(line_buffer)); + continue; + } if (*value) *value++ = 0; while (ISSPACE(*value)) value++; - trimblanks(key, 0)[0] = 0; trimblanks(value, 0)[0] = 0; /* + * Leave the key in quoted form, because 1) postmap cannot assume + * that a string without @ contains an email address localpart, + * and 2) an address localpart may require quoting even when the + * quoted form contains no backslash or ". + */ + key = STR(line_buffer); + + /* * Enforce the "key whitespace value" format. Disallow missing * keys or missing values. */ @@ -467,7 +515,26 @@ static void postmap(char *map_type, char *path_name, int postmap_flags, VSTREAM_PATH(source_fp), lineno); /* - * Store the value under a case-insensitive key. + * Optionally treat the vale 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; + char *err; + + if ((base64_buf = dict_file_to_b64(mkmap->dict, value)) == 0) { + err = dict_file_get_error(mkmap->dict); + msg_warn("%s, line %d: %s: skipping this entry", + VSTREAM_PATH(source_fp), lineno, err); + myfree(err); + continue; + } + value = vstring_str(base64_buf); + } + + /* + * Store the value under a (possibly case-insensitive) key, as + * specified with open_flags. */ mkmap_append(mkmap, key, value); if (mkmap->dict->error) @@ -591,7 +658,10 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count, dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); - if ((value = dict_get(dicts[n], STR(keybuf))) != 0) { + value = ((dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ? + dict_file_lookup : dicts[n]->lookup) + (dicts[n], STR(keybuf)); + if (value != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", dicts[n]->type, dicts[n]->name, STR(keybuf)); @@ -602,9 +672,16 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count, found = 1; break; } - if (dicts[n]->error) + switch (dicts[n]->error) { + case 0: + break; + case DICT_ERR_CONFIG: + msg_fatal("table %s:%s: query error", + dicts[n]->type, dicts[n]->name); + default: msg_fatal("table %s:%s: query error: %m", dicts[n]->type, dicts[n]->name); + } } } } else { @@ -653,6 +730,7 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count, mime_state_free(mime_state); found = key_state.found; } + if (found) vstream_fflush(VSTREAM_OUT); @@ -677,7 +755,9 @@ static int postmap_query(const char *map_type, const char *map_name, const char *value; dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); - if ((value = dict_get(dict, key)) != 0) { + value = ((dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ? + dict_file_lookup : dict->lookup) (dict, key); + if (value != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", map_type, map_name, key); @@ -686,8 +766,16 @@ static int postmap_query(const char *map_type, const char *map_name, } vstream_printf("%s\n", value); } - if (dict->error) - msg_fatal("table %s:%s: query error: %m", dict->type, dict->name); + switch (dict->error) { + case 0: + break; + case DICT_ERR_CONFIG: + msg_fatal("table %s:%s: query error", + dict->type, dict->name); + default: + msg_fatal("table %s:%s: query error: %m", + dict->type, dict->name); + } vstream_fflush(VSTREAM_OUT); dict_close(dict); return (value != 0); @@ -796,6 +884,20 @@ static void postmap_seq(const char *map_type, const char *map_name, msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND", map_type, map_name); } + if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) { + VSTRING *unb64; + char *err; + + if ((unb64 = dict_file_from_b64(dict, value)) == 0) { + err = dict_file_get_error(dict); + msg_warn("table %s:%s: key %s: %s", + dict->type, dict->name, key, err); + myfree(err); + /* dict->error = DICT_ERR_CONFIG; */ + continue; + } + value = STR(unb64); + } vstream_printf("%s %s\n", key, value); } if (dict->error) @@ -808,7 +910,7 @@ static void postmap_seq(const char *map_type, const char *map_name, static NORETURN usage(char *myname) { - msg_fatal("usage: %s [-NfinoprsuUvw] [-c config_dir] [-d key] [-q key] [map_type:]file...", + msg_fatal("usage: %s [-bfFhimnNoprsuUvw] [-c config_dir] [-d key] [-q key] [map_type:]file...", myname); } @@ -830,6 +932,7 @@ int main(int argc, char **argv) int sequence = 0; int found; int force_utf8 = 0; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -859,13 +962,13 @@ int main(int argc, char **argv) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); /* * Check the Postfix library version as soon as we enable logging. @@ -875,7 +978,7 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "Nbc:d:fhimnopq:rsuUvw")) > 0) { + while ((ch = GETOPT(argc, argv, "bc:d:fFhimnNopq:rsuUvw")) > 0) { switch (ch) { default: usage(argv[0]); @@ -899,6 +1002,9 @@ int main(int argc, char **argv) case 'f': dict_flags &= ~DICT_FLAG_FOLD_FIX; break; + case 'F': + dict_flags |= DICT_FLAG_SRC_RHS_IS_FILE; + break; case 'h': postmap_flags |= POSTMAP_FLAG_HEADER_KEY; break; @@ -948,8 +1054,12 @@ int main(int argc, char **argv) } } mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); mail_dict_init(); if ((query == 0 || strcmp(query, "-") != 0) && (postmap_flags & POSTMAP_FLAG_ANY_KEY)) diff --git a/external/ibm-public/postfix/dist/src/postmulti/postmulti.c b/external/ibm-public/postfix/dist/src/postmulti/postmulti.c index 0390ba0d3af..67590a954ad 100644 --- a/external/ibm-public/postfix/dist/src/postmulti/postmulti.c +++ b/external/ibm-public/postfix/dist/src/postmulti/postmulti.c @@ -1,4 +1,4 @@ -/* $NetBSD: postmulti.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postmulti.c,v 1.3 2020/03/18 19:05:18 christos Exp $ */ /*++ /* NAME @@ -19,10 +19,10 @@ /* [\fB-i \fIname\fR] /* /* \fBpostmulti\fR \fB-p\fR [\fB-av\fR] [\fB-g \fIgroup\fR] -/* [\fB-i \fIname\fR] \fIcommand...\fR +/* [\fB-i \fIname\fR] \fIpostfix-command...\fR /* /* \fBpostmulti\fR \fB-x\fR [\fB-aRv\fR] [\fB-g \fIgroup\fR] -/* [\fB-i \fIname\fR] \fIcommand...\fR +/* [\fB-i \fIname\fR] \fIunix-command...\fR /* /* .ti -4 /* \fBLife-cycle management:\fR @@ -107,8 +107,8 @@ /* List Postfix instances with their instance name, instance /* group name, enable/disable status and configuration directory. /* .SH "Postfix-wrapper mode" -/* .IP \fB-p\fR -/* Invoke \fBpostfix(1)\fR to execute the specified \fIcommand\fR. +/* .IP "\fB-p \fIpostfix-command\fR" +/* Invoke \fBpostfix(1)\fR to execute \fIpostfix-command\fR. /* This option implements the \fBpostfix-wrapper\fR(5) interface. /* .RS /* .IP \(bu @@ -138,8 +138,8 @@ /* # postmulti -g msa -p start /* .RE /* .SH "Command mode" -/* .IP \fB-x\fR -/* Execute the specified \fIcommand\fR for all Postfix instances. +/* .IP "\fB-x \fIunix-command\fR" +/* Execute the specified \fIunix-command\fR for all Postfix instances. /* The command runs with appropriate environment settings for /* MAIL_CONFIG, command_directory, daemon_directory, /* config_directory, queue_directory, data_directory, @@ -328,8 +328,9 @@ /* .IP "\fBdaemon_directory (see 'postconf -d' output)\fR" /* The directory with Postfix support programs and daemon programs. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a Postfix process will -/* import from a non-Postfix parent process. +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBmulti_instance_directories (empty)\fR" /* An optional list of non-default Postfix configuration directories; /* these directories belong to additional Postfix instances that share @@ -355,8 +356,8 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix 3.0 and later: /* .IP "\fBmeta_directory (see 'postconf -d' output)\fR" @@ -400,6 +401,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -412,7 +418,6 @@ #include <unistd.h> #include <string.h> #include <fcntl.h> -#include <syslog.h> #include <errno.h> #include <ctype.h> #ifdef USE_PATHS_H @@ -424,7 +429,6 @@ #include <msg.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <vstream.h> #include <vstring_vstream.h> #include <stringops.h> @@ -443,6 +447,7 @@ #include <mail_params.h> #include <mail_conf.h> #include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ @@ -765,7 +770,7 @@ static INSTANCE *create_primary_instance(void) INSTANCE *ip = alloc_instance(var_config_dir); /* - * There is no need to load primary instance paramater settings from + * There is no need to load primary instance parameter settings from * file. We already have the main.cf parameters of interest in memory. */ #define SAVE_INSTANCE_NAME(val) (*(val) ? mystrdup(val) : 0) @@ -1688,20 +1693,30 @@ int main(int argc, char **argv) argv[0] = slash + 1; if (isatty(STDERR_FILENO)) msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY); + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. */ MAIL_VERSION_CHECK; + /* + * Process main.cf parameters. This is done before the GETOPT() loop to + * improve logging. This assumes that no command-line option can affect + * parameter processing. + */ + mail_conf_read(); + get_mail_conf_str_table(str_table); + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + if ((config_dir = getenv(CONF_ENV_PATH)) != 0 && strcmp(config_dir, DEF_CONFIG_DIR) != 0) msg_fatal("Non-default configuration directory: %s=%s", CONF_ENV_PATH, config_dir); /* - * Parse switches. + * Parse switches. Move the above mail_conf_read() block after this loop, + * if any command-line option can affect parameter processing. */ while ((ch = GETOPT(argc, argv, "ae:g:i:G:I:lpRvx")) > 0) { switch (ch) { @@ -1816,12 +1831,6 @@ int main(int argc, char **argv) } /* - * Proces main.cf parameters. - */ - mail_conf_read(); - get_mail_conf_str_table(str_table); - - /* * Sanity checks. */ check_shared_dir_status(); diff --git a/external/ibm-public/postfix/dist/src/postqueue/postqueue.c b/external/ibm-public/postfix/dist/src/postqueue/postqueue.c index 2bb7c9f5444..f4026a14ea4 100644 --- a/external/ibm-public/postfix/dist/src/postqueue/postqueue.c +++ b/external/ibm-public/postfix/dist/src/postqueue/postqueue.c @@ -1,4 +1,4 @@ -/* $NetBSD: postqueue.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postqueue.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -75,6 +75,11 @@ /* .IP \fB!\fR /* The message is in the \fBhold\fR queue, i.e. no further delivery /* attempt will be made until the mail is taken off hold. +/* .IP \fB#\fR +/* The message is forced to expire. See the \fBpostsuper\fR(1) +/* options \fB-e\fR or \fB-f\fR. +/* .sp +/* This feature is available in Postfix 3.5 and later. /* .RE /* .IP "\fB-s \fIsite\fR" /* Schedule immediate delivery of all mail that is queued for the named @@ -118,6 +123,11 @@ /* number does not include message envelope information. It /* is approximately equal to the number of bytes that would /* be transmitted via SMTP including the <CR><LF> line endings. +/* .IP \fBforced_expire\fR +/* The message is forced to expire (\fBtrue\fR or \fBfalse\fR). +/* See the \fBpostsuper\fR(1) options \fB-e\fR or \fB-f\fR. +/* .sp +/* This feature is available in Postfix 3.5 and later. /* .IP \fBsender\fR /* The envelope sender address. /* .IP \fBrecipients\fR @@ -139,8 +149,8 @@ /* STANDARDS /* RFC 7159 (JSON notation) /* DIAGNOSTICS -/* Problems are logged to \fBsyslogd\fR(8) and to the standard error -/* stream. +/* Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8), +/* and to the standard error stream. /* ENVIRONMENT /* .ad /* .fi @@ -164,8 +174,9 @@ /* \fBpostconf\fR(5) for more details including examples. /* .IP "\fBalternate_config_directories (empty)\fR" /* A list of non-default Postfix configuration directories that may -/* be specified with "-c config_directory" on the command line, or -/* via the MAIL_CONFIG environment parameter. +/* be specified with "-c config_directory" on the command line (in the +/* case of \fBsendmail\fR(1), with the "-C" option), or via the MAIL_CONFIG +/* environment parameter. /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" /* The default location of the Postfix main.cf and master.cf /* configuration files. @@ -175,15 +186,16 @@ /* Optional list of destinations that are eligible for per-destination /* logfiles with mail that is queued to those destinations. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a Postfix process will -/* import from a non-Postfix parent process. +/* The list of environment parameters 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" /* The location of the Postfix top-level queue directory. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .IP "\fBtrigger_timeout (10s)\fR" /* The time limit for sending a trigger to a Postfix daemon (for /* example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon). @@ -201,6 +213,8 @@ /* flush(8), fast flush service /* sendmail(1), Sendmail-compatible user interface /* postsuper(1), privileged queue operations +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* README FILES /* .ad /* .fi @@ -247,7 +261,6 @@ #include <clean_env.h> #include <vstream.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <argv.h> #include <safe.h> #include <connect.h> @@ -272,6 +285,7 @@ #include <valid_mailhost_addr.h> #include <mail_dict.h> #include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ @@ -537,7 +551,6 @@ MAIL_VERSION_STAMP_DECLARE; int main(int argc, char **argv) { struct stat st; - char *slash; int c; int fd; int mode = PQ_MODE_DEFAULT; @@ -567,15 +580,14 @@ int main(int argc, char **argv) msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m"); /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. Set up signal handlers so that we - * can clean up incomplete output. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. Censor the process name: it is + * provided by the user. */ - if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) - argv[0] = slash + 1; + argv[0] = "postqueue"; msg_vstream_init(argv[0], VSTREAM_ERR); msg_cleanup(unavailable); - msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -638,22 +650,19 @@ int main(int argc, char **argv) */ mail_conf_read(); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE); mail_dict_init(); /* proxy, sql, ldap */ get_mail_conf_str_table(str_table); /* * This program is designed to be set-gid, which makes it a potential - * target for attack. If not running as root, strip the environment so we - * don't have to trust the C library. If running as root, don't strip the - * environment so that showq can receive non-default configuration - * directory info when the mail system is down. + * target for attack. Strip and optionally override the process + * environment so that we don't have to trust the C library. */ - if (geteuid() != 0) { - import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); - clean_env(import_env->argv); - argv_free(import_env); - } + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + clean_env(import_env->argv); + argv_free(import_env); + if (chdir(var_queue_dir)) msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir); diff --git a/external/ibm-public/postfix/dist/src/postqueue/showq_compat.c b/external/ibm-public/postfix/dist/src/postqueue/showq_compat.c index 552b0c22c08..8f79b38a390 100644 --- a/external/ibm-public/postfix/dist/src/postqueue/showq_compat.c +++ b/external/ibm-public/postfix/dist/src/postqueue/showq_compat.c @@ -1,4 +1,4 @@ -/* $NetBSD: showq_compat.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: showq_compat.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -38,6 +38,7 @@ #include <time.h> #include <string.h> #include <sysexits.h> +#include <errno.h> /* Utility library. */ @@ -89,12 +90,12 @@ static unsigned long showq_message(VSTREAM *showq_stream) static VSTRING *why = 0; long arrival_time; long message_size; - int message_status; char *saved_reason = mystrdup(""); const char *show_reason; int padding; int showq_status; time_t time_t_arrival_time; + int forced_expire; /* * One-time initialization. @@ -115,8 +116,9 @@ static unsigned long showq_message(VSTREAM *showq_stream) RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), RECV_ATTR_LONG(MAIL_ATTR_TIME, &arrival_time), RECV_ATTR_LONG(MAIL_ATTR_SIZE, &message_size), + RECV_ATTR_INT(MAIL_ATTR_FORCED_EXPIRE, &forced_expire), RECV_ATTR_STR(MAIL_ATTR_SENDER, addr), - ATTR_TYPE_END) != 5) + ATTR_TYPE_END) != 6) msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); /* @@ -124,9 +126,13 @@ static unsigned long showq_message(VSTREAM *showq_stream) * left-aligned, followed by other status info and the sender address * which is already in externalized RFC 5321 form. */ - message_status = (strcmp(STR(queue_name), MAIL_QUEUE_ACTIVE) == 0 ? '*' : - strcmp(STR(queue_name), MAIL_QUEUE_HOLD) == 0 ? '!' : ' '); - vstring_sprintf(id_status, "%s%c", STR(queue_id), message_status); + vstring_strcpy(id_status, STR(queue_id)); + if (strcmp(STR(queue_name), MAIL_QUEUE_ACTIVE) == 0) + vstring_strcat(id_status, "*"); + else if (strcmp(STR(queue_name), MAIL_QUEUE_HOLD) == 0) + vstring_strcat(id_status, "!"); + if (forced_expire) + vstring_strcat(id_status, "#"); time_t_arrival_time = arrival_time; vstream_printf(var_long_queue_ids ? L_SENDER_FORMAT : S_SENDER_FORMAT, STR(id_status), @@ -156,7 +162,7 @@ static unsigned long showq_message(VSTREAM *showq_stream) myfree(saved_reason); saved_reason = mystrdup(STR(why)); show_reason = *saved_reason ? saved_reason : "reason unavailable"; - if ((padding = 76 - strlen(show_reason)) < 0) + if ((padding = 76 - (int) strlen(show_reason)) < 0) padding = 0; vstream_printf("%*s(%s)\n", padding, "", show_reason); } @@ -192,7 +198,11 @@ void showq_compat(VSTREAM *showq_stream) } queue_size += showq_message(showq_stream); file_count++; - vstream_fflush(VSTREAM_OUT); + if (vstream_fflush(VSTREAM_OUT)) { + if (errno != EPIPE) + msg_fatal_status(EX_IOERR, "output write error: %m"); + return; + } } if (showq_status < 0) msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); @@ -207,5 +217,6 @@ void showq_compat(VSTREAM *showq_stream) queue_size / 1024, file_count, file_count == 1 ? "" : "s"); } - vstream_fflush(VSTREAM_OUT); + if (vstream_fflush(VSTREAM_OUT) && errno != EPIPE) + msg_fatal_status(EX_IOERR, "output write error: %m"); } diff --git a/external/ibm-public/postfix/dist/src/postqueue/showq_json.c b/external/ibm-public/postfix/dist/src/postqueue/showq_json.c index 90120ec9ff4..e69bc4dd317 100644 --- a/external/ibm-public/postfix/dist/src/postqueue/showq_json.c +++ b/external/ibm-public/postfix/dist/src/postqueue/showq_json.c @@ -1,4 +1,4 @@ -/* $NetBSD: showq_json.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: showq_json.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -36,6 +36,7 @@ #include <string.h> #include <sysexits.h> #include <ctype.h> +#include <errno.h> /* Utility library. */ @@ -135,6 +136,7 @@ static void format_json(VSTREAM *showq_stream) long message_size; int showq_status; int rcpt_count = 0; + int forced_expire; /* * One-time initialization. @@ -155,8 +157,9 @@ static void format_json(VSTREAM *showq_stream) RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), RECV_ATTR_LONG(MAIL_ATTR_TIME, &arrival_time), RECV_ATTR_LONG(MAIL_ATTR_SIZE, &message_size), + RECV_ATTR_INT(MAIL_ATTR_FORCED_EXPIRE, &forced_expire), RECV_ATTR_STR(MAIL_ATTR_SENDER, addr), - ATTR_TYPE_END) != 5) + ATTR_TYPE_END) != 6) msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); vstream_printf("{"); vstream_printf("\"queue_name\": \"%s\", ", @@ -165,11 +168,12 @@ static void format_json(VSTREAM *showq_stream) json_quote(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))); /* - Read zero or more (recipient, reason) pair(s) until attr_scan_more() + * Read zero or more (recipient, reason) pair(s) until attr_scan_more() * consumes a terminator. If the showq daemon messes up, don't try to * resynchronize. */ @@ -194,7 +198,8 @@ static void format_json(VSTREAM *showq_stream) if (showq_status < 0) msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); vstream_printf("}\n"); - vstream_fflush(VSTREAM_OUT); + if (vstream_fflush(VSTREAM_OUT) && errno != EPIPE) + msg_fatal_status(EX_IOERR, "output write error: %m"); } /* showq_json - streaming JSON-format output adapter */ @@ -204,10 +209,11 @@ void showq_json(VSTREAM *showq_stream) int showq_status; /* - * Emit zero or more queue file objects until attr_scan_more() - * consumes a terminator. + * Emit zero or more queue file objects until attr_scan_more() consumes a + * terminator. */ - while ((showq_status = attr_scan_more(showq_stream)) > 0) { + while ((showq_status = attr_scan_more(showq_stream)) > 0 + && vstream_ferror(VSTREAM_OUT) == 0) { format_json(showq_stream); } if (showq_status < 0) diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen.c index bd889034d75..0fe42d918c0 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -18,9 +18,9 @@ /* /* This program should not be used on SMTP ports that receive /* mail from end-user clients (MUAs). In a typical deployment, -/* \fBpostscreen\fR(8) handles the MX service on TCP port 25, -/* while MUA clients submit mail via the \fBsubmission\fR -/* service on TCP port 587 which requires client authentication. +/* \fBpostscreen\fR(8) handles the MX service on TCP port 25, and +/* \fBsmtpd\fR(8) receives mail from MUAs on the \fBsubmission\fR +/* service (TCP port 587) which requires client authentication. /* Alternatively, a site could set up a dedicated, non-postscreen, /* "port 25" server that provides \fBsubmission\fR service and /* client authentication, but no MX service. @@ -63,34 +63,28 @@ /* RFC 2034 (SMTP Enhanced Status Codes) /* RFC 2821 (SMTP protocol) /* Not: RFC 2920 (SMTP Pipelining) +/* RFC 3030 (CHUNKING without BINARYMIME) /* RFC 3207 (STARTTLS command) /* RFC 3461 (SMTP DSN Extension) /* RFC 3463 (Enhanced Status Codes) /* RFC 5321 (SMTP protocol, including multi-line 220 banners) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* The \fBpostscreen\fR(8) built-in SMTP protocol engine /* currently does not announce support for AUTH, XCLIENT or /* XFORWARD. /* If you need to make these services available /* on port 25, then do not enable the optional "after 220 -/* server greeting" tests, and do not use DNSBLs that reject -/* traffic from dial-up and residential networks. +/* server greeting" tests. /* -/* The optional "after 220 server greeting" tests involve -/* \fBpostscreen\fR(8)'s built-in SMTP protocol engine. When -/* these tests succeed, \fBpostscreen\fR(8) adds the client -/* to the temporary whitelist, but it cannot hand off the -/* "live" connection to a Postfix SMTP server process in the -/* middle of a session. Instead, \fBpostscreen\fR(8) defers -/* attempts to deliver mail with a 4XX status, and waits for -/* the client to disconnect. When the client connects again, -/* \fBpostscreen\fR(8) will allow the client to talk to a -/* Postfix SMTP server process (provided that the whitelist -/* status has not expired). \fBpostscreen\fR(8) mitigates -/* the impact of this limitation by giving the "after 220 -/* server greeting" tests a long expiration time. +/* The optional "after 220 server greeting" tests may result in +/* unexpected delivery delays from senders that retry email delivery +/* from a different IP address. Reason: after passing these tests a +/* new client must disconnect, and reconnect from the same IP +/* address before it can deliver mail. See POSTSCREEN_README, section +/* "Tests after the 220 SMTP server greeting", for a discussion. /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -127,6 +121,11 @@ /* Available in Postfix version 3.1 and later: /* .IP "\fBdns_ncache_ttl_fix_enable (no)\fR" /* Enable a workaround for future libc incompatibility. +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBpostscreen_reject_footer_maps ($smtpd_reject_footer_maps)\fR" +/* Optional lookup table for information that is appended after a 4XX +/* or 5XX \fBpostscreen\fR(8) server response. /* TROUBLE SHOOTING CONTROLS /* .ad /* .fi @@ -367,12 +366,22 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* SEE ALSO /* smtpd(8), Postfix SMTP server /* tlsproxy(8), Postfix TLS proxy server /* dnsblog(8), DNS black/whitelist logger +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad @@ -509,13 +518,14 @@ char *var_psc_barlf_action; int var_psc_barlf_ttl; int var_psc_cmd_count; -char *var_psc_cmd_time; +int var_psc_cmd_time; char *var_dnsblog_service; char *var_tlsproxy_service; char *var_smtpd_rej_footer; char *var_psc_rej_footer; +char *var_psc_rej_ftr_maps; int var_smtpd_cconn_limit; int var_psc_cconn_limit; @@ -602,6 +612,9 @@ static void psc_drain(char *unused_service, char **unused_argv) * * XXX Some Berkeley DB versions break with close-after-fork. Every new * version is an improvement over its predecessor. + * + * XXX Don't assume that it is OK to share the same LMDB lockfile descriptor + * between different processes. */ if (psc_cache_map != 0 /* XXX && psc_cache_map requires locking */ ) { @@ -698,7 +711,7 @@ static void psc_endpt_lookup_done(int endpt_status, * Reply with 421 when the client has too many open connections. */ if (var_psc_cconn_limit > 0 - && state->client_concurrency > var_psc_cconn_limit) { + && state->client_info->concurrency > var_psc_cconn_limit) { msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections", state->smtp_client_addr, state->smtp_client_port); PSC_DROP_SESSION_STATE(state, @@ -847,7 +860,7 @@ static int psc_cache_validator(const char *client_addr, const char *stamp_str, void *unused_context) { - PSC_STATE dummy; + PSC_STATE dummy_state; PSC_CLIENT_INFO dummy_client_info; /* @@ -858,9 +871,9 @@ static int psc_cache_validator(const char *client_addr, * silly logging we remove the cache entry only after all tests have * expired longer ago than the cache retention time. */ - dummy.client_info = &dummy_client_info; - psc_parse_tests(&dummy, stamp_str, event_time() - var_psc_cache_ret); - return ((dummy.flags & PSC_STATE_MASK_ANY_TODO) == 0); + dummy_state.client_info = &dummy_client_info; + psc_parse_tests(&dummy_state, stamp_str, event_time() - var_psc_cache_ret); + return ((dummy_state.flags & PSC_STATE_MASK_ANY_TODO) == 0); } /* pre_jail_init - pre-jail initialization */ @@ -1126,6 +1139,7 @@ int main(int argc, char **argv) VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0, VAR_PSC_WLIST_IF, DEF_PSC_WLIST_IF, &var_psc_wlist_if, 0, 0, VAR_PSC_UPROXY_PROTO, DEF_PSC_UPROXY_PROTO, &var_psc_uproxy_proto, 0, 0, + VAR_PSC_REJ_FTR_MAPS, DEF_PSC_REJ_FTR_MAPS, &var_psc_rej_ftr_maps, 0, 0, 0, }; static const CONFIG_INT_TABLE int_table[] = { @@ -1142,6 +1156,7 @@ int main(int argc, char **argv) 0, }; static const CONFIG_TIME_TABLE time_table[] = { + VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0, VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, &var_psc_greet_wait, 1, 0, VAR_PSC_PREGR_TTL, DEF_PSC_PREGR_TTL, &var_psc_pregr_ttl, 1, 0, VAR_PSC_DNSBL_MIN_TTL, DEF_PSC_DNSBL_MIN_TTL, &var_psc_dnsbl_min_ttl, 1, 0, @@ -1168,7 +1183,6 @@ int main(int argc, char **argv) 0, }; static const CONFIG_RAW_TABLE raw_table[] = { - VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0, VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0, VAR_PSC_REJ_FOOTER, DEF_PSC_REJ_FOOTER, &var_psc_rej_footer, 0, 0, VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0, diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen.h b/external/ibm-public/postfix/dist/src/postscreen/postscreen.h index 023b1513958..c98181847de 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen.h +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen.h @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen.h,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen.h,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -102,19 +102,6 @@ typedef struct { } PSC_STATE; /* - * Emulate legacy ad-hoc variables on top of indexable time stamps. This - * avoids massive scar tissue during initial feature development. - */ -#define pregr_stamp client_info->expire_time[PSC_TINDX_PREGR] -#define dnsbl_stamp client_info->expire_time[PSC_TINDX_DNSBL] -#define pipel_stamp client_info->expire_time[PSC_TINDX_PIPEL] -#define nsmtp_stamp client_info->expire_time[PSC_TINDX_NSMTP] -#define barlf_stamp client_info->expire_time[PSC_TINDX_BARLF] - - /* Minize the patch size for stable releases. */ -#define client_concurrency client_info->concurrency - - /* * Special expiration time values. */ #define PSC_TIME_STAMP_NEW (0) /* test was never passed */ @@ -471,6 +458,11 @@ extern HTABLE *psc_client_concurrency; /* per-client concurrency */ (state)->smtp_server_fd = (fd); \ psc_post_queue_length++; \ } while (0) +#define PSC_DEL_SERVER_STATE(state) do { \ + close((state)->smtp_server_fd); \ + (state)->smtp_server_fd = (-1); \ + psc_post_queue_length--; \ + } while (0) #define PSC_DEL_CLIENT_STATE(state) do { \ event_server_disconnect((state)->smtp_client_stream); \ (state)->smtp_client_stream = 0; \ @@ -555,6 +547,7 @@ extern void psc_hangup_event(PSC_STATE *); * postscreen_send.c */ #define PSC_SEND_REPLY psc_send_reply /* legacy macro */ +extern void pcs_send_pre_jail_init(void); extern int psc_send_reply(PSC_STATE *, const char *); extern void psc_send_socket(PSC_STATE *); @@ -577,6 +570,7 @@ typedef void (*PSC_ENDPT_LOOKUP_FN) (int, VSTREAM *, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *); extern void psc_endpt_lookup(VSTREAM *, PSC_ENDPT_LOOKUP_FN); +extern void psc_endpt_local_lookup(VSTREAM *, PSC_ENDPT_LOOKUP_FN); /* * postscreen_access emulation. diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_dnsbl.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_dnsbl.c index cb17a017b22..925a60db0c6 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_dnsbl.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_dnsbl.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_dnsbl.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_dnsbl.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -216,7 +216,7 @@ typedef struct { */ static VSTRING *reply_client; /* client address in DNSBLOG reply */ static VSTRING *reply_dnsbl; /* domain in DNSBLOG reply */ -static VSTRING *reply_addr; /* adress list in DNSBLOG reply */ +static VSTRING *reply_addr; /* address list in DNSBLOG reply */ /* psc_dnsbl_add_site - add DNSBL site information */ diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_early.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_early.c index ce928b787c5..7bda7f6a658 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_early.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_early.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_early.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_early.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -106,6 +106,7 @@ static void psc_early_event(int event, void *context) { const char *myname = "psc_early_event"; PSC_STATE *state = (PSC_STATE *) context; + time_t *expire_time = state->client_info->expire_time; char read_buf[PSC_READ_BUF_SIZE]; int read_count; DELTA_TIME elapsed; @@ -144,7 +145,7 @@ static void psc_early_event(int event, void *context) */ if ((state->flags & PSC_STATE_FLAG_PREGR_TODO) != 0 && (state->flags & PSC_STATE_MASK_PREGR_FAIL_DONE) == 0) { - state->pregr_stamp = event_time() + var_psc_pregr_ttl; + expire_time[PSC_TINDX_PREGR] = event_time() + var_psc_pregr_ttl; PSC_PASS_SESSION_STATE(state, "pregreet test", PSC_STATE_FLAG_PREGR_PASS); } @@ -177,7 +178,7 @@ static void psc_early_event(int event, void *context) psc_whitelist_non_dnsbl(state); } if (state->dnsbl_score < var_psc_dnsbl_thresh) { - state->dnsbl_stamp = event_time() + state->dnsbl_ttl; + expire_time[PSC_TINDX_DNSBL] = event_time() + state->dnsbl_ttl; PSC_PASS_SESSION_STATE(state, "dnsbl test", PSC_STATE_FLAG_DNSBL_PASS); } else { diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_endpt.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_endpt.c index 330430c4946..d1bab225c0d 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_endpt.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_endpt.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_endpt.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_endpt.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -18,6 +18,17 @@ /* MAI_SERVPORT_STR *smtp_client_port; /* MAI_HOSTADDR_STR *smtp_server_addr; /* MAI_SERVPORT_STR *smtp_server_port; +/* AUXILIARY METHODS +/* void psc_endpt_local_lookup(smtp_client_stream, lookup_done) +/* VSTREAM *smtp_client_stream; +/* void (*lookup_done)(status, smtp_client_stream, +/* smtp_client_addr, smtp_client_port, +/* smtp_server_addr, smtp_server_port) +/* int status; +/* MAI_HOSTADDR_STR *smtp_client_addr; +/* MAI_SERVPORT_STR *smtp_client_port; +/* MAI_HOSTADDR_STR *smtp_server_addr; +/* MAI_SERVPORT_STR *smtp_server_port; /* DESCRIPTION /* psc_endpt_lookup() looks up remote and local connection /* endpoint information, either through local system calls, @@ -28,6 +39,10 @@ /* .IP \(bu /* Accept the same arguments as psc_endpt_lookup(). /* .IP \(bu +/* Call psc_endpt_local_lookup() to look up connection info +/* when the upstream proxy indicates that the connection is +/* not proxied (e.g., health check probe). +/* .IP \(bu /* Validate protocol, address and port syntax. Permit only /* protocols that are configured with the main.cf:inet_protocols /* setting. @@ -43,10 +58,16 @@ /* Arguments: /* .IP client_stream /* A brand-new stream that is connected to the remote client. +/* This argument MUST be passed to psc_endpt_local_lookup() +/* if the up-stream proxy indicates that a connection is not +/* proxied. /* .IP lookup /* Call-back routine that reports the result status, address /* and port information. The result status is -1 in case of -/* error, 0 in case of success. +/* error, 0 in case of success. This MUST NOT be called directly +/* if the up-stream proxy indicates that a connection is not +/* proxied; instead this MUST be called indirectly by +/* psc_endpt_local_lookup(). /* LICENSE /* .ad /* .fi @@ -56,6 +77,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -107,8 +133,8 @@ static int psc_sockaddr_to_hostaddr(struct sockaddr *addr_storage, /* psc_endpt_local_lookup - look up local system connection information */ -static void psc_endpt_local_lookup(VSTREAM *smtp_client_stream, - PSC_ENDPT_LOOKUP_FN lookup_done) +void psc_endpt_local_lookup(VSTREAM *smtp_client_stream, + PSC_ENDPT_LOOKUP_FN lookup_done) { struct sockaddr_storage addr_storage; SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage); diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.c index 48b191050ac..6daa118be5e 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_haproxy.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_haproxy.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -20,8 +20,10 @@ /* MAI_SERVPORT_STR *smtp_server_port; /* DESCRIPTION /* psc_endpt_haproxy_lookup() looks up connection endpoint -/* information via the haproxy protocol. Arguments and results -/* conform to the postscreen_endpt(3) API. +/* information via the haproxy protocol, or looks up local +/* information if the haproxy handshake indicates that a +/* connection is not proxied. Arguments and results conform +/* to the postscreen_endpt(3) API. /* LICENSE /* .ad /* .fi @@ -31,6 +33,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -66,7 +73,6 @@ typedef struct { VSTREAM *stream; PSC_ENDPT_LOOKUP_FN notify; - VSTRING *buffer; } PSC_HAPROXY_STATE; /* psc_endpt_haproxy_event - read or time event */ @@ -80,94 +86,32 @@ static void psc_endpt_haproxy_event(int event, void *context) MAI_SERVPORT_STR smtp_client_port; MAI_HOSTADDR_STR smtp_server_addr; MAI_SERVPORT_STR smtp_server_port; - int last_char = 0; - const char *err; - VSTRING *escape_buf; - char read_buf[HAPROXY_MAX_LEN]; - ssize_t read_len; - char *cp; + int non_proxy = 0; - /* - * We must not read(2) past the <CR><LF> that terminates the haproxy - * line. For efficiency reasons we read the entire haproxy line in one - * read(2) call when we know that the line is unfragmented. In the rare - * case that the line is fragmented, we fall back and read(2) it one - * character at a time. - */ switch (event) { case EVENT_TIME: msg_warn("haproxy read: time limit exceeded"); status = -1; break; case EVENT_READ: - /* Determine the initial VSTREAM read(2) buffer size. */ - if (VSTRING_LEN(state->buffer) == 0) { - if ((read_len = recv(vstream_fileno(state->stream), - read_buf, sizeof(read_buf) - 1, MSG_PEEK)) > 0 - && ((cp = memchr(read_buf, '\n', read_len)) != 0)) { - read_len = cp - read_buf + 1; - } else { - read_len = 1; - } - vstream_control(state->stream, CA_VSTREAM_CTL_BUFSIZE(read_len), - CA_VSTREAM_CTL_END); - } - /* Drain the VSTREAM buffer, otherwise this pseudo-thread will hang. */ - do { - if ((last_char = VSTREAM_GETC(state->stream)) == VSTREAM_EOF) { - if (vstream_ferror(state->stream)) - msg_warn("haproxy read: %m"); - else - msg_warn("haproxy read: lost connection"); - status = -1; - break; - } - if (VSTRING_LEN(state->buffer) >= HAPROXY_MAX_LEN) { - msg_warn("haproxy read: line too long"); - status = -1; - break; - } - VSTRING_ADDCH(state->buffer, last_char); - } while (vstream_peek(state->stream) > 0); - break; - } - - /* - * Parse the haproxy line. Note: the haproxy_srvr_parse() routine - * performs address protocol checks, address and port syntax checks, and - * converts IPv4-in-IPv6 address string syntax (:ffff::1.2.3.4) to IPv4 - * syntax where permitted by the main.cf:inet_protocols setting. - */ - if (status == 0 && last_char == '\n') { - VSTRING_TERMINATE(state->buffer); - if ((err = haproxy_srvr_parse(vstring_str(state->buffer), + status = haproxy_srvr_receive(vstream_fileno(state->stream), &non_proxy, &smtp_client_addr, &smtp_client_port, - &smtp_server_addr, &smtp_server_port)) != 0) { - escape_buf = vstring_alloc(HAPROXY_MAX_LEN + 2); - escape(escape_buf, vstring_str(state->buffer), - VSTRING_LEN(state->buffer)); - msg_warn("haproxy read: %s: %s", err, vstring_str(escape_buf)); - status = -1; - vstring_free(escape_buf); - } + &smtp_server_addr, &smtp_server_port); } /* - * Are we done yet? + * Terminate this pseudo thread, and notify the caller. */ - if (status < 0 || last_char == '\n') { - PSC_CLEAR_EVENT_REQUEST(vstream_fileno(state->stream), - psc_endpt_haproxy_event, context); - vstream_control(state->stream, - CA_VSTREAM_CTL_BUFSIZE(VSTREAM_BUFSIZE), - CA_VSTREAM_CTL_END); + PSC_CLEAR_EVENT_REQUEST(vstream_fileno(state->stream), + psc_endpt_haproxy_event, context); + if (status == 0 && non_proxy) + psc_endpt_local_lookup(state->stream, state->notify); + else state->notify(status, state->stream, &smtp_client_addr, &smtp_client_port, &smtp_server_addr, &smtp_server_port); - /* Note: the stream may be closed at this point. */ - vstring_free(state->buffer); - myfree((void *) state); - } + /* Note: the stream may be closed at this point. */ + myfree((void *) state); } /* psc_endpt_haproxy_lookup - event-driven haproxy client */ @@ -186,7 +130,6 @@ void psc_endpt_haproxy_lookup(VSTREAM *stream, state = (PSC_HAPROXY_STATE *) mymalloc(sizeof(*state)); state->stream = stream; state->notify = notify; - state->buffer = vstring_alloc(100); /* * Read the haproxy line. diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.h b/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.h index bf6d9d38ee4..32e2a3331c1 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.h +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_haproxy.h @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_haproxy.h,v 1.1.1.2 2020/03/18 18:59:36 christos Exp $ */ +/* $NetBSD: postscreen_haproxy.h,v 1.2 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_misc.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_misc.c index 6e2978b329f..fefa2bf59ce 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_misc.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_misc.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_misc.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -45,6 +45,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_send.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_send.c index 1173c49a7be..c34d3ad95fc 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_send.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_send.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_send.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_send.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -8,6 +8,8 @@ /* SYNOPSIS /* #include <postscreen.h> /* +/* void pcs_send_pre_jail_init(void) +/* /* int psc_send_reply(state, text) /* PSC_STATE *state; /* const char *text; @@ -19,6 +21,8 @@ /* void psc_send_socket(state) /* PSC_STATE *state; /* DESCRIPTION +/* pcs_send_pre_jail_init() performs one-time initialization. +/* /* psc_send_reply() sends the specified text to the specified /* remote SMTP client. In case of an immediate error, it logs /* a warning (except EPIPE) with the client address and port, @@ -50,6 +54,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -71,11 +80,14 @@ #include <mail_params.h> #include <smtp_reply_footer.h> #include <mail_proto.h> +#include <maps.h> /* Application-specific. */ #include <postscreen.h> +static MAPS *psc_rej_ftr_maps; + /* * This program screens all inbound SMTP connections, so it better not waste * time. @@ -83,16 +95,49 @@ #define PSC_SEND_SOCK_CONNECT_TIMEOUT 1 #define PSC_SEND_SOCK_NOTIFY_TIMEOUT 100 +/* pcs_send_pre_jail_init - initialize */ + +void pcs_send_pre_jail_init(void) +{ + static int init_count = 0; + + if (init_count++ != 0) + msg_panic("pcs_send_pre_jail_init: multiple calls"); + + /* + * SMTP server reject footer. + */ + if (*var_psc_rej_ftr_maps) + psc_rej_ftr_maps = maps_create(VAR_SMTPD_REJ_FTR_MAPS, + var_psc_rej_ftr_maps, + DICT_FLAG_LOCK); +} + +/* psc_get_footer - find that footer */ + +static const char *psc_get_footer(const char *text, ssize_t text_len) +{ + static VSTRING *footer_buf = 0; + + if (footer_buf == 0) + footer_buf = vstring_alloc(100); + /* Strip the \r\n for consistency with smtpd. */ + vstring_strncpy(footer_buf, text, text_len); + return (psc_maps_find(psc_rej_ftr_maps, STR(footer_buf), 0)); +} + /* psc_send_reply - send reply to remote SMTP client */ int psc_send_reply(PSC_STATE *state, const char *text) { ssize_t start; int ret; + const char *footer; + ssize_t text_len = strlen(text) - 2; if (msg_verbose) msg_info("> [%s]:%s: %.*s", state->smtp_client_addr, - state->smtp_client_port, (int) strlen(text) - 2, text); + state->smtp_client_port, (int) text_len, text); /* * Append the new text to earlier text that could not be sent because the @@ -116,8 +161,11 @@ int psc_send_reply(PSC_STATE *state, const char *text) /* * Append the optional reply footer. */ - if (*var_psc_rej_footer && (*text == '4' || *text == '5')) - smtp_reply_footer(state->send_buf, start, var_psc_rej_footer, + if ((*text == '4' || *text == '5') + && ((psc_rej_ftr_maps != 0 + && (footer = psc_get_footer(text, text_len)) != 0) + || *(footer = var_psc_rej_footer) != 0)) + smtp_reply_footer(state->send_buf, start, footer, STR(psc_expand_filter), psc_expand_lookup, (void *) state); diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_smtpd.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_smtpd.c index 48a5b523c70..74b69bc4d2e 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_smtpd.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_smtpd.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_smtpd.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_smtpd.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -132,6 +132,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -161,6 +166,7 @@ #include <maps.h> #include <ehlo_mask.h> #include <lex_822.h> +#include <info_log_addr_form.h> /* TLS library. */ @@ -264,13 +270,13 @@ static DICT *psc_cmd_filter; PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \ (event), (void *) (state)); \ PSC_DROP_SESSION_STATE((state), (reply)); \ - } while (0); + } while (0) #define PSC_CLEAR_EVENT_HANGUP(state, event) do { \ PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \ (event), (void *) (state)); \ psc_hangup_event(state); \ - } while (0); + } while (0) /* psc_helo_cmd - record HELO and respond */ @@ -313,7 +319,7 @@ static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask vstring_sprintf(psc_temp, "250-%s\r\n", var_myhostname); if ((discard_mask & EHLO_MASK_SIZE) == 0) { - if (var_message_limit) + if (ENFORCING_SIZE_LIMIT(var_message_limit)) PSC_EHLO_APPEND1(saved_len, psc_temp, "250-SIZE %lu\r\n", (unsigned long) var_message_limit); else @@ -342,6 +348,8 @@ static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask /* Fix 20140708: announce SMTPUTF8. */ if (var_smtputf8_enable && (discard_mask & EHLO_MASK_SMTPUTF8) == 0) PSC_EHLO_APPEND(saved_len, psc_temp, "250-SMTPUTF8\r\n"); + if ((discard_mask & EHLO_MASK_CHUNKING) == 0) + PSC_EHLO_APPEND(saved_len, psc_temp, "250-CHUNKING\r\n"); STR(psc_temp)[saved_len + 3] = ' '; } @@ -569,7 +577,8 @@ static int psc_rcpt_cmd(PSC_STATE *state, char *args) (int) strlen(state->rcpt_reply) - 2, var_soft_bounce == 0 ? state->rcpt_reply : psc_soften_reply(state->rcpt_reply), - state->sender, addr, state->protocol, + info_log_addr_form_sender(state->sender), + info_log_addr_form_recipient(addr), state->protocol, state->helo_name ? state->helo_name : ""); return (PSC_SEND_REPLY(state, state->rcpt_reply)); } @@ -578,27 +587,65 @@ static int psc_rcpt_cmd(PSC_STATE *state, char *args) static int psc_data_cmd(PSC_STATE *state, char *args) { + const char myname[] = "psc_data_cmd"; /* - * smtpd(8) incompatibility: we reject all requests. + * smtpd(8) incompatibility: postscreen(8) drops the connection, instead + * of waiting for the next command. Justification: postscreen(8) should + * never see DATA from a legitimate client, because 1) the server rejects + * every recipient, and 2) the server does not announce PIPELINING. */ + msg_info("DATA without valid RCPT from [%s]:%s", + PSC_CLIENT_ADDR_PORT(state)); if (PSC_SMTPD_NEXT_TOKEN(args) != 0) - return (PSC_SEND_REPLY(state, - "501 5.5.4 Syntax: DATA\r\n")); - if (state->sender == 0) - return (PSC_SEND_REPLY(state, - "503 5.5.1 Error: need RCPT command\r\n")); + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "501 5.5.4 Syntax: DATA\r\n"); + else if (state->sender == 0) + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "503 5.5.1 Error: need RCPT command\r\n"); + else + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "554 5.5.1 Error: no valid recipients\r\n"); + /* Caution: state is now a dangling pointer. */ + return (0); +} + +/* psc_bdat_cmd - respond to BDAT and disconnect */ + +static int psc_bdat_cmd(PSC_STATE *state, char *args) +{ + const char *myname = "psc_bdat_cmd"; /* - * We really would like to hang up the connection as early as possible, - * so that we dont't have to deal with broken zombies that fall silent at - * the first reject response. For now we rely on stress-dependent command - * read timeouts. - * - * If we proceed into the data phase, enforce over-all DATA time limit. + * smtpd(8) incompatibility: postscreen(8) drops the connection, instead + * of reading the entire BDAT chunk and staying in sync with the client. + * Justification: postscreen(8) should never see BDAT from a legitimate + * client, because 1) the server rejects every recipient, and 2) the + * server does not announce PIPELINING. */ - return (PSC_SEND_REPLY(state, - "554 5.5.1 Error: no valid recipients\r\n")); + msg_info("BDAT without valid RCPT from [%s]:%s", + PSC_CLIENT_ADDR_PORT(state)); + if (state->ehlo_discard_mask & EHLO_MASK_CHUNKING) + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "502 5.5.1 Error: command not implemented\r\n"); + else if (PSC_SMTPD_NEXT_TOKEN(args) == 0) + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "501 5.5.4 Syntax: BDAT count [LAST]\r\n"); + else if (state->sender == 0) + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "554 5.5.1 Error: need RCPT command\r\n"); + else + PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, + psc_smtpd_time_event, + "554 5.5.1 Error: no valid recipients\r\n"); + /* Caution: state is now a dangling pointer. */ + return (0); } /* psc_rset_cmd - reset, send 250 OK */ @@ -698,6 +745,7 @@ typedef struct { #define PSC_SMTPD_CMD_FLAG_DESTROY (1<<1) /* dangling pointer alert */ #define PSC_SMTPD_CMD_FLAG_PRE_TLS (1<<2) /* allowed with mandatory TLS */ #define PSC_SMTPD_CMD_FLAG_SUSPEND (1<<3) /* suspend command engine */ +#define PSC_SMTPD_CMD_FLAG_HAS_PAYLOAD (1<<4) /* command has payload */ static const PSC_SMTPD_COMMAND command_table[] = { "HELO", psc_helo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS, @@ -708,8 +756,9 @@ static const PSC_SMTPD_COMMAND command_table[] = { "AUTH", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE, "MAIL", psc_mail_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, "RCPT", psc_rcpt_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, - "DATA", psc_data_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, + "DATA", psc_data_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_DESTROY, /* ".", psc_dot_cmd, PSC_SMTPD_CMD_FLAG_NONE, */ + "BDAT", psc_bdat_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_DESTROY | PSC_SMTPD_CMD_FLAG_HAS_PAYLOAD, "RSET", psc_rset_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, "NOOP", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS, "VRFY", psc_vrfy_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, @@ -724,6 +773,7 @@ static void psc_smtpd_read_event(int event, void *context) { const char *myname = "psc_smtpd_read_event"; PSC_STATE *state = (PSC_STATE *) context; + time_t *expire_time = state->client_info->expire_time; int ch; struct cmd_trans { int state; @@ -837,7 +887,7 @@ static void psc_smtpd_read_event(int event, void *context) PSC_CLIENT_ADDR_PORT(state), STR(psc_temp)); PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_FAIL); PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_PASS); - state->barlf_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */ + expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_DISABLED; /* XXX */ /* Skip this test for the remainder of this session. */ PSC_SKIP_SESSION_STATE(state, "bare newline test", PSC_STATE_FLAG_BARLF_SKIP); @@ -857,7 +907,7 @@ static void psc_smtpd_read_event(int event, void *context) /* Temporarily whitelist until something expires. */ PSC_PASS_SESSION_STATE(state, "bare newline test", PSC_STATE_FLAG_BARLF_PASS); - state->barlf_stamp = event_time() + psc_min_ttl; + expire_time[PSC_TINDX_BARLF] = event_time() + psc_min_ttl; break; default: msg_panic("%s: unknown bare_newline action value %d", @@ -897,7 +947,8 @@ static void psc_smtpd_read_event(int event, void *context) vstring_strcpy(state->cmd_buffer, cp); } else if (psc_cmd_filter->error != 0) { msg_fatal("%s:%s lookup error for \"%.100s\"", - psc_cmd_filter->type, psc_cmd_filter->name, cp); + psc_cmd_filter->type, psc_cmd_filter->name, + STR(state->cmd_buffer)); } } @@ -962,7 +1013,7 @@ static void psc_smtpd_read_event(int event, void *context) command, STR(psc_temp)); PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_FAIL); PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_PASS); - state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */ + expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_DISABLED; /* XXX */ /* Skip this test for the remainder of this SMTP session. */ PSC_SKIP_SESSION_STATE(state, "non-smtp test", PSC_STATE_FLAG_NSMTP_SKIP); @@ -982,7 +1033,7 @@ static void psc_smtpd_read_event(int event, void *context) /* Temporarily whitelist until something else expires. */ PSC_PASS_SESSION_STATE(state, "non-smtp test", PSC_STATE_FLAG_NSMTP_PASS); - state->nsmtp_stamp = event_time() + psc_min_ttl; + expire_time[PSC_TINDX_NSMTP] = event_time() + psc_min_ttl; break; default: msg_panic("%s: unknown non_smtp_command action value %d", @@ -990,7 +1041,8 @@ static void psc_smtpd_read_event(int event, void *context) } } /* Command PIPELINING test. */ - if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_SKIP) + if ((cmdp->flags & PSC_SMTPD_CMD_FLAG_HAS_PAYLOAD) == 0 + && (state->flags & PSC_STATE_MASK_PIPEL_TODO_SKIP) == PSC_STATE_FLAG_PIPEL_TODO && !PSC_SMTPD_BUFFER_EMPTY(state)) { printable(command, '?'); PSC_SMTPD_ESCAPE_TEXT(psc_temp, PSC_SMTPD_PEEK_DATA(state), @@ -999,7 +1051,7 @@ static void psc_smtpd_read_event(int event, void *context) PSC_CLIENT_ADDR_PORT(state), command, STR(psc_temp)); PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_FAIL); PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_PASS); - state->pipel_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */ + expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_DISABLED; /* XXX */ /* Skip this test for the remainder of this SMTP session. */ PSC_SKIP_SESSION_STATE(state, "pipelining test", PSC_STATE_FLAG_PIPEL_SKIP); @@ -1019,7 +1071,7 @@ static void psc_smtpd_read_event(int event, void *context) /* Temporarily whitelist until something else expires. */ PSC_PASS_SESSION_STATE(state, "pipelining test", PSC_STATE_FLAG_PIPEL_PASS); - state->pipel_stamp = event_time() + psc_min_ttl; + expire_time[PSC_TINDX_PIPEL] = event_time() + psc_min_ttl; break; default: msg_panic("%s: unknown pipelining action value %d", @@ -1038,21 +1090,21 @@ static void psc_smtpd_read_event(int event, void *context) PSC_PASS_SESSION_STATE(state, "bare newline test", PSC_STATE_FLAG_BARLF_PASS); /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */ - state->barlf_stamp = event_time() + var_psc_barlf_ttl; + expire_time[PSC_TINDX_BARLF] = event_time() + var_psc_barlf_ttl; } if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL) == PSC_STATE_FLAG_NSMTP_TODO) { PSC_PASS_SESSION_STATE(state, "non-smtp test", PSC_STATE_FLAG_NSMTP_PASS); /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */ - state->nsmtp_stamp = event_time() + var_psc_nsmtp_ttl; + expire_time[PSC_TINDX_NSMTP] = event_time() + var_psc_nsmtp_ttl; } if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL) == PSC_STATE_FLAG_PIPEL_TODO) { PSC_PASS_SESSION_STATE(state, "pipelining test", PSC_STATE_FLAG_PIPEL_PASS); /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */ - state->pipel_stamp = event_time() + var_psc_pipel_ttl; + expire_time[PSC_TINDX_PIPEL] = event_time() + var_psc_pipel_ttl; } } /* Command COUNT limit test. */ @@ -1128,16 +1180,18 @@ void psc_smtpd_tests(PSC_STATE *state) state->read_state = PSC_SMTPD_CMD_ST_ANY; /* - * Opportunistically make postscreen more useful by turning on the - * pipelining and non-SMTP command tests when a pre-handshake test - * failed, or when some deep test is configured as enabled. + * Disable all after-220 tests when we need to reply with 421 and hang up + * after reading the next SMTP client command. + * + * Opportunistically make postscreen more useful, by turning on all + * after-220 tests when a bad client failed a before-220 test. * - * XXX Make "opportunistically" configurable for each test. + * Otherwise, only apply the explicitly-configured after-220 tests. */ - if ((state->flags & PSC_STATE_FLAG_SMTPD_X21) == 0) { - state->flags |= PSC_STATE_MASK_SMTPD_TODO; - } else { + if (state->flags & PSC_STATE_FLAG_SMTPD_X21) { state->flags &= ~PSC_STATE_MASK_SMTPD_TODO; + } else if (state->flags & PSC_STATE_MASK_ANY_FAIL) { + state->flags |= PSC_STATE_MASK_SMTPD_TODO; } /* @@ -1242,7 +1296,7 @@ void psc_smtpd_init(void) /* * Initialize the reply footer. */ - if (*var_psc_rej_footer) + if (*var_psc_rej_footer || *var_psc_rej_ftr_maps) psc_expand_init(); } @@ -1270,4 +1324,10 @@ void psc_smtpd_pre_jail_init(void) if (*var_psc_cmd_filter) psc_cmd_filter = dict_open(var_psc_cmd_filter, O_RDONLY, DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); + + /* + * SMTP server reply footer. + */ + if (*var_psc_rej_ftr_maps) + pcs_send_pre_jail_init(); } diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_starttls.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_starttls.c index f861c155bfc..613b9e48989 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_starttls.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_starttls.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_starttls.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_starttls.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -39,6 +39,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -228,10 +233,11 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event) vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr, smtp_state->smtp_client_port); attr_print(tlsproxy_stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REMOTE_ENDPT, STR(remote_endpt)), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER), - SEND_ATTR_INT(MAIL_ATTR_TIMEOUT, psc_normal_cmd_time_limit), - SEND_ATTR_STR(MAIL_ATTR_SERVER_ID, MAIL_SERVICE_SMTPD), /* XXX */ + SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)), + SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER), + SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit), + SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit), + SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */ ATTR_TYPE_END); if (vstream_fflush(tlsproxy_stream) != 0) { msg_warn("error sending request to %s service: %m", psc_tlsp_service); diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_state.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_state.c index 4f4d5f9bb24..17b0237affa 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_state.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_state.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_state.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_state.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -27,6 +27,9 @@ /* PSC_STATE *state; /* int server_fd; /* +/* void PSC_DEL_SERVER_STATE(state) +/* PSC_STATE *state; +/* /* void PSC_DEL_CLIENT_STATE(state) /* PSC_STATE *state; /* @@ -90,6 +93,10 @@ /* increments the global psc_post_queue_length file descriptor /* counter. /* +/* PSC_DEL_SERVER_STATE() closes the specified session state +/* object's server file descriptor, and decrements the global +/* psc_post_queue_length file descriptor counter. +/* /* PSC_DEL_CLIENT_STATE() updates the specified session state /* object, closes the client stream, and decrements the global /* psc_check_queue_length file descriptor counter. @@ -118,6 +125,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -224,12 +236,10 @@ void psc_free_session_state(PSC_STATE *state) htable_delete(psc_client_concurrency, state->smtp_client_addr, myfree); if (state->smtp_client_stream != 0) { - event_server_disconnect(state->smtp_client_stream); - psc_check_queue_length--; + PSC_DEL_CLIENT_STATE(state); } if (state->smtp_server_fd >= 0) { - close(state->smtp_server_fd); - psc_post_queue_length--; + PSC_DEL_SERVER_STATE(state); } if (state->send_buf != 0) state->send_buf = vstring_free(state->send_buf); diff --git a/external/ibm-public/postfix/dist/src/postscreen/postscreen_tests.c b/external/ibm-public/postfix/dist/src/postscreen/postscreen_tests.c index c52f27d04b8..3c1ab214c6e 100644 --- a/external/ibm-public/postfix/dist/src/postscreen/postscreen_tests.c +++ b/external/ibm-public/postfix/dist/src/postscreen/postscreen_tests.c @@ -1,4 +1,4 @@ -/* $NetBSD: postscreen_tests.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postscreen_tests.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -81,6 +81,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -135,6 +140,7 @@ void psc_new_tests(PSC_STATE *state) { + time_t *expire_time = state->client_info->expire_time; /* * Give all tests a PSC_TIME_STAMP_NEW time stamp, so that we can later @@ -142,11 +148,11 @@ void psc_new_tests(PSC_STATE *state) * write a cache entry to the database, any new-but-disabled tests will * get a PSC_TIME_STAMP_DISABLED time stamp. */ - state->pregr_stamp = PSC_TIME_STAMP_NEW; - state->dnsbl_stamp = PSC_TIME_STAMP_NEW; - state->pipel_stamp = PSC_TIME_STAMP_NEW; - state->nsmtp_stamp = PSC_TIME_STAMP_NEW; - state->barlf_stamp = PSC_TIME_STAMP_NEW; + expire_time[PSC_TINDX_PREGR] = PSC_TIME_STAMP_NEW; + expire_time[PSC_TINDX_DNSBL] = PSC_TIME_STAMP_NEW; + expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_NEW; + expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_NEW; + expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_NEW; /* * Determine what tests need to be completed. @@ -192,7 +198,7 @@ void psc_parse_tests(PSC_STATE *state, void psc_todo_tests(PSC_STATE *state, time_t time_value) { - time_t *time_stamps = state->client_info->expire_time; + time_t *expire_time = state->client_info->expire_time; time_t *sp; /* @@ -205,7 +211,7 @@ void psc_todo_tests(PSC_STATE *state, time_t time_value) * enabled tests, but the remote SMTP client has not yet passed all those * tests. */ - for (sp = time_stamps; sp < time_stamps + PSC_TINDX_COUNT; sp++) { + for (sp = expire_time; sp < expire_time + PSC_TINDX_COUNT; sp++) { if (*sp == PSC_TIME_STAMP_NEW) state->flags |= PSC_STATE_FLAG_NEW; } @@ -214,15 +220,15 @@ void psc_todo_tests(PSC_STATE *state, time_t time_value) * Don't flag disabled tests as "todo", because there would be no way to * make those bits go away. */ - if (PSC_PREGR_TEST_ENABLE() && time_value > state->pregr_stamp) + if (PSC_PREGR_TEST_ENABLE() && time_value > expire_time[PSC_TINDX_PREGR]) state->flags |= PSC_STATE_FLAG_PREGR_TODO; - if (PSC_DNSBL_TEST_ENABLE() && time_value > state->dnsbl_stamp) + if (PSC_DNSBL_TEST_ENABLE() && time_value > expire_time[PSC_TINDX_DNSBL]) state->flags |= PSC_STATE_FLAG_DNSBL_TODO; - if (var_psc_pipel_enable && time_value > state->pipel_stamp) + if (var_psc_pipel_enable && time_value > expire_time[PSC_TINDX_PIPEL]) state->flags |= PSC_STATE_FLAG_PIPEL_TODO; - if (var_psc_nsmtp_enable && time_value > state->nsmtp_stamp) + if (var_psc_nsmtp_enable && time_value > expire_time[PSC_TINDX_NSMTP]) state->flags |= PSC_STATE_FLAG_NSMTP_TODO; - if (var_psc_barlf_enable && time_value > state->barlf_stamp) + if (var_psc_barlf_enable && time_value > expire_time[PSC_TINDX_BARLF]) state->flags |= PSC_STATE_FLAG_BARLF_TODO; /* @@ -237,15 +243,15 @@ void psc_todo_tests(PSC_STATE *state, time_t time_value) && var_psc_refresh_time > 0) { time_t refresh_time = time_value + var_psc_refresh_time; - if (PSC_PREGR_TEST_ENABLE() && refresh_time > state->pregr_stamp) + if (PSC_PREGR_TEST_ENABLE() && refresh_time > expire_time[PSC_TINDX_PREGR]) state->flags |= PSC_STATE_FLAG_PREGR_TODO; - if (PSC_DNSBL_TEST_ENABLE() && refresh_time > state->dnsbl_stamp) + if (PSC_DNSBL_TEST_ENABLE() && refresh_time > expire_time[PSC_TINDX_DNSBL]) state->flags |= PSC_STATE_FLAG_DNSBL_TODO; - if (var_psc_pipel_enable && refresh_time > state->pipel_stamp) + if (var_psc_pipel_enable && refresh_time > expire_time[PSC_TINDX_PIPEL]) state->flags |= PSC_STATE_FLAG_PIPEL_TODO; - if (var_psc_nsmtp_enable && refresh_time > state->nsmtp_stamp) + if (var_psc_nsmtp_enable && refresh_time > expire_time[PSC_TINDX_NSMTP]) state->flags |= PSC_STATE_FLAG_NSMTP_TODO; - if (var_psc_barlf_enable && refresh_time > state->barlf_stamp) + if (var_psc_barlf_enable && refresh_time > expire_time[PSC_TINDX_BARLF]) state->flags |= PSC_STATE_FLAG_BARLF_TODO; } #endif @@ -273,6 +279,7 @@ void psc_todo_tests(PSC_STATE *state, time_t time_value) char *psc_print_tests(VSTRING *buf, PSC_STATE *state) { const char *myname = "psc_print_tests"; + time_t *expire_time = state->client_info->expire_time; /* * Sanity check. @@ -285,23 +292,23 @@ char *psc_print_tests(VSTRING *buf, PSC_STATE *state) * with "pass new" when some disabled test becomes enabled at some later * time. */ - if (PSC_PREGR_TEST_ENABLE() == 0 && state->pregr_stamp == PSC_TIME_STAMP_NEW) - state->pregr_stamp = PSC_TIME_STAMP_DISABLED; - if (PSC_DNSBL_TEST_ENABLE() == 0 && state->dnsbl_stamp == PSC_TIME_STAMP_NEW) - state->dnsbl_stamp = PSC_TIME_STAMP_DISABLED; - if (var_psc_pipel_enable == 0 && state->pipel_stamp == PSC_TIME_STAMP_NEW) - state->pipel_stamp = PSC_TIME_STAMP_DISABLED; - if (var_psc_nsmtp_enable == 0 && state->nsmtp_stamp == PSC_TIME_STAMP_NEW) - state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED; - if (var_psc_barlf_enable == 0 && state->barlf_stamp == PSC_TIME_STAMP_NEW) - state->barlf_stamp = PSC_TIME_STAMP_DISABLED; + if (PSC_PREGR_TEST_ENABLE() == 0 && expire_time[PSC_TINDX_PREGR] == PSC_TIME_STAMP_NEW) + expire_time[PSC_TINDX_PREGR] = PSC_TIME_STAMP_DISABLED; + if (PSC_DNSBL_TEST_ENABLE() == 0 && expire_time[PSC_TINDX_DNSBL] == PSC_TIME_STAMP_NEW) + expire_time[PSC_TINDX_DNSBL] = PSC_TIME_STAMP_DISABLED; + if (var_psc_pipel_enable == 0 && expire_time[PSC_TINDX_PIPEL] == PSC_TIME_STAMP_NEW) + expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_DISABLED; + if (var_psc_nsmtp_enable == 0 && expire_time[PSC_TINDX_NSMTP] == PSC_TIME_STAMP_NEW) + expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_DISABLED; + if (var_psc_barlf_enable == 0 && expire_time[PSC_TINDX_BARLF] == PSC_TIME_STAMP_NEW) + expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_DISABLED; vstring_sprintf(buf, "%lu;%lu;%lu;%lu;%lu", - (unsigned long) state->pregr_stamp, - (unsigned long) state->dnsbl_stamp, - (unsigned long) state->pipel_stamp, - (unsigned long) state->nsmtp_stamp, - (unsigned long) state->barlf_stamp); + (unsigned long) expire_time[PSC_TINDX_PREGR], + (unsigned long) expire_time[PSC_TINDX_DNSBL], + (unsigned long) expire_time[PSC_TINDX_PIPEL], + (unsigned long) expire_time[PSC_TINDX_NSMTP], + (unsigned long) expire_time[PSC_TINDX_BARLF]); return (STR(buf)); } diff --git a/external/ibm-public/postfix/dist/src/postsuper/postsuper.c b/external/ibm-public/postfix/dist/src/postsuper/postsuper.c index b651b0f395d..96c7e12a84f 100644 --- a/external/ibm-public/postfix/dist/src/postsuper/postsuper.c +++ b/external/ibm-public/postfix/dist/src/postsuper/postsuper.c @@ -1,4 +1,4 @@ -/* $NetBSD: postsuper.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: postsuper.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -8,7 +8,8 @@ /* SYNOPSIS /* .fi /* \fBpostsuper\fR [\fB-psSv\fR] -/* [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR] +/* [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR] +/* [\fB-e \fIqueue_id\fR] [\fB-f \fIqueue_id\fR] /* [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR] /* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR] /* DESCRIPTION @@ -20,8 +21,9 @@ /* By default, \fBpostsuper\fR(1) performs the operations /* requested with the /* \fB-s\fR and \fB-p\fR command-line options on all Postfix queue -/* directories - this includes the \fBincoming\fR, \fBactive\fR and -/* \fBdeferred\fR directories with mail files and the \fBbounce\fR, +/* directories - this includes the \fBincoming\fR, \fBactive\fR, +/* \fBdeferred\fR, and \fBhold\fR directories with message +/* files and the \fBbounce\fR, /* \fBdefer\fR, \fBtrace\fR and \fBflush\fR directories with log files. /* /* Options: @@ -34,16 +36,17 @@ /* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and /* \fBdeferred\fR). /* -/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads -/* queue IDs from standard input. For example, to delete all mail +/* To delete multiple files, specify the \fB-d\fR option multiple +/* times, or specify a \fIqueue_id\fR of \fB-\fR to read queue IDs +/* from standard input. For example, to delete all mail /* with exactly one recipient \fBuser@example.com\fR: /* .sp /* .nf -/* mailq | tail +2 | grep -v '^ *(' | awk \'BEGIN { RS = "" } +/* mailq | tail -n +2 | grep -v '^ *(' | awk 'BEGIN { RS = "" } /* # $7=sender, $8=recipient1, $9=recipient2 /* { if ($8 == "user@example.com" && $9 == "") /* print $1 } -/* \' | tr -d '*!' | postsuper -d - +/* ' | tr -d '*!' | postsuper -d - /* .fi /* .sp /* Specify "\fB-d ALL\fR" to remove all messages; for example, specify @@ -73,14 +76,49 @@ /* \fBpostsuper\fR(1) deletes the new message, instead of the old /* message that it should have deleted. /* .RE +/* .IP "\fB-e \fIqueue_id\fR" +/* .IP "\fB-f \fIqueue_id\fR" +/* Request forced expiration for one message with the named +/* queue ID in the named mail queue(s) (default: \fBhold\fR, +/* \fBincoming\fR, \fBactive\fR and \fBdeferred\fR). +/* .RS +/* .IP \(bu +/* The message will be returned to the sender when the queue +/* manager attempts to deliver that message (note that Postfix +/* will never deliver messages in the \fBhold\fR queue). +/* .IP \(bu +/* The \fB-e\fR and \fB-f\fR options both request forced +/* expiration. The difference is that \fB-f\fR will also release +/* a message if it is in the \fBhold\fR queue. With \fB-e\fR, such +/* a message would not be returned to the sender until it is +/* released with \fB-f\fR or \fB-H\fR. +/* .IP \(bu +/* When a deferred message is force-expired, the return message +/* will state the reason for the delay. Otherwise, the reason +/* will be "message is administratively expired". +/* .RE +/* .IP +/* To expire multiple files, specify the \fB-e\fR or \fB-f\fR +/* option multiple times, or specify a \fIqueue_id\fR of \fB-\fR +/* to read queue IDs from standard input (see the \fB-d\fR option +/* above for an example, but be sure to replace \fB-d\fR in +/* the example). +/* .sp +/* Specify "\fB-e ALL\fR" or "\fB-f ALL\fR" to expire all +/* messages; for example, specify "\fB-e ALL deferred\fR" to +/* expire all mail in the \fBdeferred\fR queue. As a safety +/* measure, the word \fBALL\fR must be specified in upper case. +/* .sp +/* These features are available in Postfix 3.5 and later. /* .IP "\fB-h \fIqueue_id\fR" /* Put mail "on hold" so that no attempt is made to deliver it. /* Move one message with the named queue ID from the named /* mail queue(s) (default: \fBincoming\fR, \fBactive\fR and /* \fBdeferred\fR) to the \fBhold\fR queue. /* -/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads -/* queue IDs from standard input. +/* To hold multiple files, specify the \fB-h\fR option multiple +/* times, or specify a \fIqueue_id\fR of \fB-\fR to read queue IDs +/* from standard input. /* .sp /* Specify "\fB-h ALL\fR" to hold all messages; for example, specify /* "\fB-h ALL deferred\fR" to hold all mail in the \fBdeferred\fR queue. @@ -98,8 +136,9 @@ /* Move one message with the named queue ID from the named /* mail queue(s) (default: \fBhold\fR) to the \fBdeferred\fR queue. /* -/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads -/* queue IDs from standard input. +/* To release multiple files, specify the \fB-H\fR option multiple +/* times, or specify a \fIqueue_id\fR of \fB-\fR to read queue IDs +/* from standard input. /* .sp /* Note: specify "\fBpostsuper -r\fR" to release mail that was kept on /* hold for a significant fraction of \fB$maximal_queue_lifetime\fR @@ -113,15 +152,16 @@ /* .IP \fB-p\fR /* Purge old temporary files that are left over after system or /* software crashes. +/* The \fB-p\fR, \fB-s\fR, and \fB-S\fR operations are done +/* before other operations. /* .IP "\fB-r \fIqueue_id\fR" /* Requeue the message with the named queue ID from the named /* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and /* \fBdeferred\fR). -/* To requeue multiple messages, specify multiple \fB-r\fR -/* command-line options. /* -/* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, -/* the program reads queue IDs from standard input. +/* To requeue multiple files, specify the \fB-r\fR option multiple +/* times, or specify a \fIqueue_id\fR of \fB-\fR to read queue IDs +/* from standard input. /* .sp /* Specify "\fB-r ALL\fR" to requeue all messages. As a safety /* measure, the word \fBALL\fR must be specified in upper case. @@ -161,6 +201,8 @@ /* .IP \fB-s\fR /* Structure check and structure repair. This should be done once /* before Postfix startup. +/* The \fB-p\fR, \fB-s\fR, and \fB-S\fR operations are done +/* before other operations. /* .RS /* .IP \(bu /* Rename files whose name does not match the message file inode @@ -195,17 +237,23 @@ /* file names also match the message file inode number. This /* option exists for testing purposes, and is available with /* Postfix 2.9 and later. +/* The \fB-p\fR, \fB-s\fR, and \fB-S\fR operations are done +/* before other operations. /* .IP \fB-v\fR /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR /* options make the software increasingly verbose. /* DIAGNOSTICS /* Problems are reported to the standard error stream and to -/* \fBsyslogd\fR(8). +/* \fBsyslogd\fR(8) or \fBpostlogd\fR(8). /* -/* \fBpostsuper\fR(1) reports the number of messages deleted with \fB-d\fR, -/* the number of messages requeued with \fB-r\fR, and the number of -/* messages whose queue file name was fixed with \fB-s\fR. The report -/* is written to the standard error stream and to \fBsyslogd\fR(8). +/* \fBpostsuper\fR(1) reports the number of messages deleted +/* with \fB-d\fR, the number of messages expired with \fB-e\fR, +/* the number of messages expired or released with \fB-f\fR, +/* the number of messages held or released with \fB-h\fR or +/* \fB-H\fR, the number of messages requeued with \fB-r\fR, +/* and the number of messages whose queue file name was fixed +/* with \fB-s\fR. The report is written to the standard error +/* stream and to \fBsyslogd\fR(8) or \fBpostlogd\fR(8). /* ENVIRONMENT /* .ad /* .fi @@ -230,13 +278,17 @@ /* .IP "\fBhash_queue_names (deferred, defer)\fR" /* 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 +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 2.9 and later: /* .IP "\fBenable_long_queue_ids (no)\fR" @@ -244,6 +296,8 @@ /* SEE ALSO /* sendmail(1), Sendmail-compatible user interface /* postqueue(1), unprivileged queue operations +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -276,7 +330,6 @@ #include <mymalloc.h> #include <msg.h> -#include <msg_syslog.h> #include <vstream.h> #include <msg_vstream.h> #include <scan_dir.h> @@ -288,6 +341,9 @@ #include <sane_fsops.h> #include <myrand.h> #include <warn_stat.h> +#include <clean_env.h> +#include <safe_open.h> +#include <name_mask.h> /* Global library. */ @@ -299,10 +355,12 @@ #include <mail_queue.h> #include <mail_open_ok.h> #include <file_id.h> +#include <mail_parm_split.h> +#include <maillog_client.h> /* Application-specific. */ -#define MAX_TEMP_AGE (60 * 60 * 24) /* temp file maximal age */ +#define MAX_TEMP_AGE (7 * 60 * 60 * 24) /* temp file maximal age */ #define STR vstring_str /* silly little macro */ #define ACTION_STRUCT (1<<0) /* fix file organization */ @@ -316,22 +374,35 @@ #define ACTION_RELEASE_ONE (1<<8) /* release named queue file(s) */ #define ACTION_RELEASE_ALL (1<<9) /* release all "on hold" mail */ #define ACTION_STRUCT_RED (1<<10) /* fix long queue ID inode fields */ +#define ACTION_EXPIRE_ONE (1<<11) /* expire named queue file(s) */ +#define ACTION_EXPIRE_ALL (1<<12) /* expire all queue file(s) */ +#define ACTION_EXP_REL_ONE (1<<13) /* expire+release named queue file(s) */ +#define ACTION_EXP_REL_ALL (1<<14) /* expire+release all queue file(s) */ #define ACTION_DEFAULT (ACTION_STRUCT | ACTION_PURGE) /* * Actions that operate on individually named queue files. These must never - * be done when queue file names are changed to match their inode number. + * be done after fixing queue file names to match their inode number because + * the target file may have been replaced. Actions that move files are safe + * only when queue file names match their inode number, otherwise mail can + * be lost due to filename collisions. */ #define ACTIONS_BY_QUEUE_ID (ACTION_DELETE_ONE | ACTION_REQUEUE_ONE \ - | ACTION_HOLD_ONE | ACTION_RELEASE_ONE) + | ACTION_HOLD_ONE | ACTION_RELEASE_ONE \ + | ACTION_EXPIRE_ONE | ACTION_EXP_REL_ONE) /* - * Mass rename operations that are postponed to a second pass after queue - * file names are changed to match their inode number. + * Mass actions. Actions that move files are safe only when queue file names + * match their inode number, otherwise mail can be lost due to filename + * collisions. */ -#define ACTIONS_AFTER_INUM_FIX (ACTION_REQUEUE_ALL | ACTION_HOLD_ALL \ - | ACTION_RELEASE_ALL) +#define ACTIONS_BY_WILDCARD (ACTION_DELETE_ALL | ACTION_REQUEUE_ALL \ + | ACTION_HOLD_ALL | ACTION_RELEASE_ALL \ + | ACTION_EXPIRE_ALL | ACTION_EXP_REL_ALL) + +#define ACTIONS_FOR_REPAIR (ACTION_PURGE | ACTION_STRUCT \ + | ACTION_STRUCT_RED) /* * Information about queue directories and what we expect to do there. If a @@ -389,6 +460,7 @@ static int message_requeued = 0; /* requeued messages */ static int message_held = 0; /* messages put on hold */ static int message_released = 0; /* messages released from hold */ static int message_deleted = 0; /* deleted messages */ +static int message_expired = 0; /* expired messages */ static int inode_fixed = 0; /* queue id matched to inode number */ static int inode_mismatch = 0; /* queue id inode mismatch */ static int position_mismatch = 0; /* file position mismatch */ @@ -428,6 +500,47 @@ static int postremove(const char *path) return (ret); } +/* postexpire - expire file, setting the group execute permission */ + +static int postexpire(const char *path) +{ + static VSTRING *why = 0; + VSTREAM *fp; + struct stat st; + + /* + * Initialize. + */ + if (why == 0) + why = vstring_alloc(100); + + /* + * We don't actually verify the file content, therefore safe_open() the + * queue file so that we won't add group execute permission to some file + * outside of the mail queue. + */ + if ((fp = safe_open(path, O_RDWR, 0, &st, -1, -1, why)) == 0) { + if (errno != ENOENT) + msg_warn("expire file %s: %s", path, vstring_str(why)); + return (-1); + } +#define POSTEXPIRE_RETURN(x) do { \ + (void) vstream_fclose(fp); \ + return (x); \ + } while (0) + + if (!READY_MESSAGE(st)) + POSTEXPIRE_RETURN(-1); /* must not expire */ + if ((st.st_mode & MAIL_QUEUE_STAT_EXPIRE) != 0) + POSTEXPIRE_RETURN(-1); /* already expired */ + if (fchmod(vstream_fileno(fp), + (st.st_mode | MAIL_QUEUE_STAT_EXPIRE) & ~S_IFMT) < 0) { + msg_warn("expire file %s: cannot set permission: %m", path); + POSTEXPIRE_RETURN(-1); + } + POSTEXPIRE_RETURN(0); +} + /* postrename - rename file with extreme prejudice */ static int postrename(const char *old, const char *new) @@ -465,7 +578,7 @@ static int postrmdir(const char *path) /* delete_one - delete one message instance and all its associated files */ -static int delete_one(const char **queue_names, const char *queue_id) +static void delete_one(const char **queue_names, const char *queue_id) { struct stat st; const char **msg_qpp; @@ -480,7 +593,7 @@ static int delete_one(const char **queue_names, const char *queue_id) */ if (!mail_queue_id_ok(queue_id)) { msg_warn("invalid mail queue id: %s", queue_id); - return (0); + return; } log_path_buf = vstring_alloc(100); @@ -506,12 +619,12 @@ static int delete_one(const char **queue_names, const char *queue_id) } } vstring_free(log_path_buf); - return (found); + message_deleted += found; } /* requeue_one - requeue one message instance and delete its logfiles */ -static int requeue_one(const char **queue_names, const char *queue_id) +static void requeue_one(const char **queue_names, const char *queue_id) { struct stat st; const char **msg_qpp; @@ -526,7 +639,7 @@ static int requeue_one(const char **queue_names, const char *queue_id) */ if (!mail_queue_id_ok(queue_id)) { msg_warn("invalid mail queue id: %s", queue_id); - return (0); + return; } new_path_buf = vstring_alloc(100); @@ -556,12 +669,12 @@ static int requeue_one(const char **queue_names, const char *queue_id) } } vstring_free(new_path_buf); - return (found); + message_requeued += found; } /* hold_one - put "on hold" one message instance */ -static int hold_one(const char **queue_names, const char *queue_id) +static void hold_one(const char **queue_names, const char *queue_id) { struct stat st; const char **msg_qpp; @@ -575,7 +688,7 @@ static int hold_one(const char **queue_names, const char *queue_id) */ if (!mail_queue_id_ok(queue_id)) { msg_warn("invalid mail queue id: %s", queue_id); - return (0); + return; } new_path_buf = vstring_alloc(100); @@ -607,12 +720,12 @@ static int hold_one(const char **queue_names, const char *queue_id) } } vstring_free(new_path_buf); - return (found); + message_held += found; } /* release_one - release one message instance that was placed "on hold" */ -static int release_one(const char **queue_names, const char *queue_id) +static void release_one(const char **queue_names, const char *queue_id) { struct stat st; const char **msg_qpp; @@ -625,7 +738,7 @@ static int release_one(const char **queue_names, const char *queue_id) */ if (!mail_queue_id_ok(queue_id)) { msg_warn("invalid mail queue id: %s", queue_id); - return (0); + return; } new_path_buf = vstring_alloc(100); @@ -647,23 +760,68 @@ static int release_one(const char **queue_names, const char *queue_id) } } vstring_free(new_path_buf); - return (found); + message_released += found; +} + +/* expire_one - expire one message instance */ + +static void expire_one(const char **queue_names, const char *queue_id) +{ + struct stat st; + const char **msg_qpp; + const char *msg_path; + int found; + int tries; + + /* + * Sanity check. No early returns beyond this point. + */ + if (!mail_queue_id_ok(queue_id)) { + msg_warn("invalid mail queue id: %s", queue_id); + return; + } + + /* + * Skip meta file directories. + */ + for (found = 0, tries = 0; found == 0 && tries < 2; tries++) { + for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) { + if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp))) + continue; + if (strcmp(*msg_qpp, MAIL_QUEUE_MAILDROP) == 0) + continue; + if (mail_open_ok(*msg_qpp, queue_id, &st, &msg_path) != MAIL_OPEN_YES) + continue; + if (postexpire(msg_path) == 0) { + found = 1; + msg_info("%s: expired", queue_id); + break; + } /* else: maybe lost a race */ + } + } + message_expired += found; +} + +/* exp_rel_one - expire or release one message instance */ + +static void exp_rel_one(const char **queue_names, const char *queue_id) +{ + expire_one(queue_names, queue_id); + release_one(queue_names, queue_id); } /* operate_stream - operate on queue IDs given on stream */ -static int operate_stream(VSTREAM *fp, - int (*operator) (const char **, const char *), - const char **queues) +static void operate_stream(VSTREAM *fp, + void (*operator) (const char **, const char *), + const char **queues) { VSTRING *buf = vstring_alloc(20); - int found = 0; while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) - found += operator(queues, STR(buf)); + operator(queues, STR(buf)); vstring_free(buf); - return (found); } /* fix_queue_id - make message queue ID match inode number */ @@ -749,6 +907,15 @@ static void super(const char **queues, int action) int error; /* + * This routine was originally written to do multiple mass operations in + * one pass. However this hard-coded the order of operations which became + * difficult to explain. As of Postfix 3.5 this routine is called for one + * mass operation at a time, in the user-specified order. The exception + * is that repair operations (purging stale files, queue hashing, and + * file-inode match) are combined and done before other mass operations. + */ + + /* * Make sure every file is in the right place, clean out stale files, and * remove non-file/non-directory objects. */ @@ -819,7 +986,7 @@ static void super(const char **queues, int action) * otherwise we can hit the wrong files. */ vstring_sprintf(actual_path, "%s/%s", scan_dir_path(info), path); - if (stat(STR(actual_path), &st) < 0) + if (lstat(STR(actual_path), &st) < 0) continue; /* @@ -943,7 +1110,7 @@ static void super(const char **queues, int action) || (inum != (unsigned long) st.st_ino && (long_name == 0 || (action & ACTION_STRUCT_RED)))) { inode_mismatch++; /* before we fix */ - action &= ~ACTIONS_AFTER_INUM_FIX; + action &= ~ACTIONS_BY_WILDCARD; fix_queue_id(STR(actual_path), queue_name, path, &st); /* At this point, path and actual_path are invalidated. */ continue; @@ -969,6 +1136,24 @@ static void super(const char **queues, int action) } /* + * Many of the following actions may move queue files. To avoid + * loss of email due to file name collisions. we should do such + * actions only when the queue file names are known to match + * their inode number. Even with non-repeating queue IDs a name + * collision may happen when different queues are merged. + */ + + /* + * Mass expiration. We count the expiration of mail that this + * system has taken responsibility for. + */ + if ((action & (ACTION_EXPIRE_ALL | ACTION_EXP_REL_ALL)) + && MESSAGE_QUEUE(qp) && READY_MESSAGE(st) + && strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0 + && postexpire(STR(actual_path)) == 0) + message_expired++; + + /* * Mass renaming to the "on hold" queue. XXX This option does not * use mail_queue_rename(), so that it can avoid having to first * move queue files to the "right" subdirectory level. Like the @@ -994,7 +1179,7 @@ static void super(const char **queues, int action) * first move queue files to the "right" subdirectory level. Like * the release_one() routine, this code must not touch logfiles. */ - if ((action & ACTION_RELEASE_ALL) + if ((action & (ACTION_RELEASE_ALL | ACTION_EXP_REL_ALL)) && strcmp(queue_name, MAIL_QUEUE_HOLD) == 0) { (void) mail_queue_path(wanted_path, MAIL_QUEUE_DEFERRED, path); if (postrename(STR(actual_path), STR(wanted_path)) == 0) @@ -1075,11 +1260,8 @@ int main(int argc, char **argv) int action = 0; const char **queues; int c; - ARGV *requeue_names = 0; - ARGV *delete_names = 0; - ARGV *hold_names = 0; - ARGV *release_names = 0; - char **cpp; + ARGV *import_env; + int saved_optind; /* * Defaults. The structural checks must fix the directory levels of "log @@ -1099,16 +1281,6 @@ int main(int argc, char **argv) MAIL_QUEUE_FLUSH, 0, }; - static char *default_hold_queues[] = { - MAIL_QUEUE_INCOMING, - MAIL_QUEUE_ACTIVE, - MAIL_QUEUE_DEFERRED, - 0, - }; - static char *default_release_queues[] = { - MAIL_QUEUE_HOLD, - 0, - }; /* * Fingerprint executables and core dumps. @@ -1142,7 +1314,8 @@ int main(int argc, char **argv) if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -1164,13 +1337,21 @@ int main(int argc, char **argv) /* * Parse JCL. + * + * First, find out what kind of actions are requested, without executing + * them. Later, we execute actions in mostly user-specified order. */ - while ((c = GETOPT(argc, argv, "c:d:h:H:pr:sSv")) > 0) { +#define GETOPT_LIST "c:d:e:f:h:H:pr:sSv" + + saved_optind = optind; + while ((c = GETOPT(argc, argv, GETOPT_LIST)) > 0) { switch (c) { default: msg_fatal("usage: %s " "[-c config_dir] " "[-d queue_id (delete)] " + "[-e queue_id (expire)] " + "[-f queue_id (expire and/or un-hold)] " "[-h queue_id (hold)] [-H queue_id (un-hold)] " "[-p (purge temporary files)] [-r queue_id (requeue)] " "[-s (structure fix)] [-S (redundant structure fix)]" @@ -1182,23 +1363,22 @@ int main(int argc, char **argv) msg_fatal("setenv: %m"); break; case 'd': - if (delete_names == 0) - delete_names = argv_alloc(1); - argv_add(delete_names, optarg, (char *) 0); action |= (strcmp(optarg, "ALL") == 0 ? ACTION_DELETE_ALL : ACTION_DELETE_ONE); break; + case 'e': + action |= (strcmp(optarg, "ALL") == 0 ? + ACTION_EXPIRE_ALL : ACTION_EXPIRE_ONE); + break; + case 'f': + action |= (strcmp(optarg, "ALL") == 0 ? + ACTION_EXP_REL_ALL : ACTION_EXP_REL_ONE); + break; case 'h': - if (hold_names == 0) - hold_names = argv_alloc(1); - argv_add(hold_names, optarg, (char *) 0); action |= (strcmp(optarg, "ALL") == 0 ? ACTION_HOLD_ALL : ACTION_HOLD_ONE); break; case 'H': - if (release_names == 0) - release_names = argv_alloc(1); - argv_add(release_names, optarg, (char *) 0); action |= (strcmp(optarg, "ALL") == 0 ? ACTION_RELEASE_ALL : ACTION_RELEASE_ONE); break; @@ -1206,9 +1386,6 @@ int main(int argc, char **argv) action |= ACTION_PURGE; break; case 'r': - if (requeue_names == 0) - requeue_names = argv_alloc(1); - argv_add(requeue_names, optarg, (char *) 0); action |= (strcmp(optarg, "ALL") == 0 ? ACTION_REQUEUE_ALL : ACTION_REQUEUE_ONE); break; @@ -1230,8 +1407,13 @@ int main(int argc, char **argv) * configuration directory location. */ mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); if (chdir(var_queue_dir)) msg_fatal("chdir %s: %m", var_queue_dir); @@ -1272,26 +1454,6 @@ int main(int argc, char **argv) msg_cleanup(fatal_warning); /* - * Sanity checks. - */ - if ((action & ACTION_DELETE_ALL) && (action & ACTION_DELETE_ONE)) { - msg_warn("option \"-d ALL\" will ignore other command line queue IDs"); - action &= ~ACTION_DELETE_ONE; - } - if ((action & ACTION_REQUEUE_ALL) && (action & ACTION_REQUEUE_ONE)) { - msg_warn("option \"-r ALL\" will ignore other command line queue IDs"); - action &= ~ACTION_REQUEUE_ONE; - } - if ((action & ACTION_HOLD_ALL) && (action & ACTION_HOLD_ONE)) { - msg_warn("option \"-h ALL\" will ignore other command line queue IDs"); - action &= ~ACTION_HOLD_ONE; - } - if ((action & ACTION_RELEASE_ALL) && (action & ACTION_RELEASE_ONE)) { - msg_warn("option \"-H ALL\" will ignore other command line queue IDs"); - action &= ~ACTION_RELEASE_ONE; - } - - /* * Execute the explicitly specified (or default) action, on the * explicitly specified (or default) queues. * @@ -1305,20 +1467,16 @@ int main(int argc, char **argv) action = ACTION_DEFAULT; if (argv[optind] != 0) queues = (const char **) argv + optind; - else if (action == ACTION_HOLD_ALL) - queues = (const char **) default_hold_queues; - else if (action == ACTION_RELEASE_ALL) - queues = (const char **) default_release_queues; else queues = (const char **) default_queues; /* - * Basic queue maintenance, as well as mass deletion, mass requeuing, and - * mass name-to-inode fixing. This ensures that queue files are in the - * right place before the file-by-name operations are done. + * Basic queue maintenance, including mass name-to-inode fixing. This + * ensures that queue files are in the right place before any other + * operations are done. */ - if (action & ~ACTIONS_BY_QUEUE_ID) - super(queues, action); + if (action & ACTIONS_FOR_REPAIR) + super(queues, action & ACTIONS_FOR_REPAIR); /* * If any file names needed changing to match the message file inode @@ -1327,7 +1485,7 @@ int main(int argc, char **argv) * operations that had to be skipped in the first pass. */ if (inode_mismatch > 0) - super(queues, action); + super(queues, action & ACTIONS_FOR_REPAIR); /* * Don't do actions by queue file name if any queue files changed name @@ -1341,117 +1499,97 @@ int main(int argc, char **argv) } /* - * Delete queue files by name. This must not be done when queue file - * names have changed names as a result of inode number mismatches, - * because we could be deleting the wrong message. + * Execute actions by queue ID and by wildcard in the user-specified + * order. */ - if (action & ACTION_DELETE_ONE) { - argv_terminate(delete_names); - queues = (const char **) - (argv[optind] ? argv + optind : default_queues); - for (cpp = delete_names->argv; *cpp; cpp++) { - if (strcmp(*cpp, "ALL") == 0) - continue; - if (strcmp(*cpp, "-") == 0) - message_deleted += - operate_stream(VSTREAM_IN, delete_one, queues); + optind = saved_optind; + while ((c = GETOPT(argc, argv, GETOPT_LIST)) > 0) { + switch (c) { + default: + msg_panic("%s: unexpected option: %c", argv[0], c); + case 'c': + case 'p': + case 'S': + case 's': + case 'v': + /* Already handled. */ + break; + case 'd': + if (strcmp(optarg, "ALL") == 0) + super(queues, ACTION_DELETE_ALL); + else if (strcmp(optarg, "-") == 0) + operate_stream(VSTREAM_IN, delete_one, queues); else - message_deleted += delete_one(queues, *cpp); - } - } - - /* - * Requeue queue files by name. This must not be done when queue file - * names have changed names as a result of inode number mismatches, - * because we could be requeuing the wrong message. - */ - if (action & ACTION_REQUEUE_ONE) { - argv_terminate(requeue_names); - queues = (const char **) - (argv[optind] ? argv + optind : default_queues); - for (cpp = requeue_names->argv; *cpp; cpp++) { - if (strcmp(*cpp, "ALL") == 0) - continue; - if (strcmp(*cpp, "-") == 0) - message_requeued += - operate_stream(VSTREAM_IN, requeue_one, queues); + delete_one(queues, optarg); + break; + case 'e': + if (strcmp(optarg, "ALL") == 0) + super(queues, ACTION_EXPIRE_ALL); + else if (strcmp(optarg, "-") == 0) + operate_stream(VSTREAM_IN, expire_one, queues); else - message_requeued += requeue_one(queues, *cpp); - } - } - - /* - * Put on hold queue files by name. This must not be done when queue file - * names have changed names as a result of inode number mismatches, - * because we could put on hold the wrong message. - */ - if (action & ACTION_HOLD_ONE) { - argv_terminate(hold_names); - queues = (const char **) - (argv[optind] ? argv + optind : default_hold_queues); - for (cpp = hold_names->argv; *cpp; cpp++) { - if (strcmp(*cpp, "ALL") == 0) - continue; - if (strcmp(*cpp, "-") == 0) - message_held += - operate_stream(VSTREAM_IN, hold_one, queues); + expire_one(queues, optarg); + break; + case 'f': + if (strcmp(optarg, "ALL") == 0) + super(queues, ACTION_EXP_REL_ALL); + else if (strcmp(optarg, "-") == 0) + operate_stream(VSTREAM_IN, exp_rel_one, queues); else - message_held += hold_one(queues, *cpp); - } - } - - /* - * Take "off hold" queue files by name. This must not be done when queue - * file names have changed names as a result of inode number mismatches, - * because we could take off hold the wrong message. - */ - if (action & ACTION_RELEASE_ONE) { - argv_terminate(release_names); - queues = (const char **) - (argv[optind] ? argv + optind : default_release_queues); - for (cpp = release_names->argv; *cpp; cpp++) { - if (strcmp(*cpp, "ALL") == 0) - continue; - if (strcmp(*cpp, "-") == 0) - message_released += - operate_stream(VSTREAM_IN, release_one, queues); + exp_rel_one(queues, optarg); + break; + case 'h': + if (strcmp(optarg, "ALL") == 0) + super(queues, ACTION_HOLD_ALL); + else if (strcmp(optarg, "-") == 0) + operate_stream(VSTREAM_IN, hold_one, queues); + else + hold_one(queues, optarg); + break; + case 'H': + if (strcmp(optarg, "ALL") == 0) + super(queues, ACTION_RELEASE_ALL); + else if (strcmp(optarg, "-") == 0) + operate_stream(VSTREAM_IN, release_one, queues); else - message_released += release_one(queues, *cpp); + release_one(queues, optarg); + break; + case 'r': + if (strcmp(optarg, "ALL") == 0) + super(queues, ACTION_REQUEUE_ALL); + else if (strcmp(optarg, "-") == 0) + operate_stream(VSTREAM_IN, requeue_one, queues); + else + requeue_one(queues, optarg); + break; } } /* * Report. */ - if (message_requeued > 0) + if (action & (ACTION_REQUEUE_ONE | ACTION_REQUEUE_ALL)) msg_info("Requeued: %d message%s", message_requeued, - message_requeued > 1 ? "s" : ""); - if (message_deleted > 0) + message_requeued != 1 ? "s" : ""); + if (action & (ACTION_DELETE_ONE | ACTION_DELETE_ALL)) msg_info("Deleted: %d message%s", message_deleted, - message_deleted > 1 ? "s" : ""); - if (message_held > 0) + message_deleted != 1 ? "s" : ""); + if (action & (ACTION_EXPIRE_ONE | ACTION_EXPIRE_ALL + | ACTION_EXP_REL_ONE | ACTION_EXP_REL_ALL)) + msg_info("Force-expired: %d message%s", message_expired, + message_expired != 1 ? "s" : ""); + if (action & (ACTION_HOLD_ONE | ACTION_HOLD_ALL)) msg_info("Placed on hold: %d message%s", - message_held, message_held > 1 ? "s" : ""); - if (message_released > 0) + message_held, message_held != 1 ? "s" : ""); + if (action & (ACTION_RELEASE_ONE | ACTION_RELEASE_ALL + | ACTION_EXP_REL_ONE | ACTION_EXP_REL_ALL)) msg_info("Released from hold: %d message%s", - message_released, message_released > 1 ? "s" : ""); + message_released, message_released != 1 ? "s" : ""); if (inode_fixed > 0) msg_info("Renamed to match inode number: %d message%s", inode_fixed, - inode_fixed > 1 ? "s" : ""); + inode_fixed != 1 ? "s" : ""); if (inode_mismatch > 0 || inode_fixed > 0) msg_warn("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS"); - /* - * Clean up. - */ - if (requeue_names) - argv_free(requeue_names); - if (delete_names) - argv_free(delete_names); - if (hold_names) - argv_free(hold_names); - if (release_names) - argv_free(release_names); - exit(0); } diff --git a/external/ibm-public/postfix/dist/src/posttls-finger/posttls-finger.c b/external/ibm-public/postfix/dist/src/posttls-finger/posttls-finger.c index d6b804c4458..0797daf692b 100644 --- a/external/ibm-public/postfix/dist/src/posttls-finger/posttls-finger.c +++ b/external/ibm-public/postfix/dist/src/posttls-finger/posttls-finger.c @@ -1,4 +1,4 @@ -/* $NetBSD: posttls-finger.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: posttls-finger.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -117,6 +117,16 @@ /* .IP "\fB-h \fIhost_lookup\fR (default: \fBdns\fR)" /* The hostname lookup methods used for the connection. See the /* documentation of smtp_host_lookup for syntax and semantics. +/* .IP "\fB-H \fIchainfiles\fR (default: \fInone\fR)\fR" +/* List of files with a sequence PEM-encoded TLS client certificate +/* chains. The list can be built-up incrementally, by specifying +/* the option multiple times, or all at once via a comma or +/* whitespace separated list of filenames. Each chain starts with +/* a private key, which is followed immediately by the +/* corresponding certificate, and optionally by additional issuer +/* certificates. Each new key begins a new chain for the +/* corresponding algorithm. This option is mutually exclusive with +/* the below \fB-k\fR and \fB-K\fR options. /* .IP "\fB-k \fIcertfile\fR (default: \fIkeyfile\fR)\fR" /* File with PEM-encoded TLS client certificate chain. This /* defaults to \fIkeyfile\fR if one is specified. @@ -228,6 +238,12 @@ /* is encountered, up to 5 times or as specified with the \fB-m\fR option. /* By default reconnection is disabled, specify a positive delay to /* enable this behavior. +/* .IP "\fB-s \fIservername\fR" +/* The server name to send with the TLS Server Name Indication (SNI) +/* extension. When the server has DANE TLSA records, this parameter +/* is ignored and the TLSA base domain is used instead. Otherwise, SNI is +/* not used by default, but can be enabled by specifying the desired value +/* with this option. /* .IP "\fB-S\fR" /* Disable SMTP; that is, connect to an LMTP server. The default port for /* LMTP over TCP is 24. Alternative ports can specified by appending @@ -247,6 +263,9 @@ /* SMTP in SSL protocol, rather than the standard STARTTLS protocol. /* The destination \fIdomain\fR:\fIport\fR should of course provide such /* a service. +/* .IP "\fB-X\fR" +/* Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode, +/* for program development only. /* .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]" /* Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default /* port is \fBsmtp\fR (or 24 with LMTP). With SMTP an MX lookup is @@ -301,6 +320,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Viktor Dukhovni /*--*/ @@ -347,6 +371,7 @@ #include <myaddrinfo.h> #include <sock_addr.h> #include <midna_domain.h> +#include <clean_env.h> #define STR(x) vstring_str(x) @@ -357,6 +382,8 @@ #include <mail_conf.h> #include <smtp_stream.h> #include <dsn_buf.h> +#include <mail_parm_split.h> +#include <mail_proto.h> /* DNS library. */ @@ -374,6 +401,7 @@ #include <tls.h> #ifdef USE_TLS +#include <tls_proxy.h> #include <openssl/engine.h> #endif @@ -431,6 +459,7 @@ typedef struct STATE { int force_tlsa; /* -f option */ unsigned port; /* TCP port */ char *dest; /* Full destination spec */ + char *paddr; /* XXX printable addr for proxy */ char *addrport; /* [addr]:port */ char *namaddrport; /* name[addr]:port */ char *nexthop; /* Nexthop domain for verification */ @@ -449,8 +478,10 @@ typedef struct STATE { char *mdalg; /* fingerprint digest algorithm */ char *CAfile; /* Trusted public CAs */ char *CApath; /* Trusted public CAs */ + char *chains; /* TLS client certificate chain files */ char *certfile; /* TLS client certificate file */ char *keyfile; /* TLS client key file */ + char *sni; /* Server SNI name */ ARGV *match; /* match arguments */ int print_trust; /* -C option */ BIO *tls_bio; /* BIO wrapper for stdout */ @@ -461,6 +492,7 @@ typedef struct STATE { char *grade; /* Minimum cipher grade */ char *protocols; /* Protocol inclusion/exclusion */ int mxinsec_level; /* DANE for insecure MX RRs? */ + int tlsproxy_mode; #endif OPTIONS options; /* JCL */ } STATE; @@ -519,14 +551,13 @@ static RESPONSE *response(STATE *state, int verbose) char *cp; /* - * Initialize the response data buffer. Defend against a denial of - * service attack by limiting the amount of multi-line text that we are + * Initialize the response data buffer. smtp_get() defends against a + * denial of service attack by limiting the amount of single-line text, + * and the loop below limits the amount of multi-line text that we are * willing to store. */ - if (rdata.buf == 0) { + if (rdata.buf == 0) rdata.buf = vstring_alloc(100); - vstring_ctl(rdata.buf, CA_VSTRING_CTL_MAXLEN(var_line_limit), 0); - } /* * Censor out non-printable characters in server responses. Concatenate @@ -550,10 +581,12 @@ static RESPONSE *response(STATE *state, int verbose) cp++; while (ISSPACE(*cp)) cp++; - vstring_strcat(rdata.buf, cp); + if (VSTRING_LEN(rdata.buf) < var_line_limit) + vstring_strcat(rdata.buf, cp); if (more == 0) break; - VSTRING_ADDCH(rdata.buf, '\n'); + if (VSTRING_LEN(rdata.buf) < var_line_limit) + VSTRING_ADDCH(rdata.buf, '\n'); } VSTRING_TERMINATE(rdata.buf); rdata.str = vstring_str(rdata.buf); @@ -699,7 +732,11 @@ static int starttls(STATE *state) int except; RESPONSE *resp; VSTREAM *stream = state->stream; - TLS_CLIENT_START_PROPS tls_props; + TLS_CLIENT_START_PROPS start_props; + TLS_CLIENT_INIT_PROPS init_props; + VSTREAM *tlsproxy; + VSTRING *port_buf; + int cwd_fd; if (state->wrapper_mode == 0) { /* SMTP stream with deadline timeouts */ @@ -743,24 +780,137 @@ static int starttls(STATE *state) else ADD_EXCLUDE(cipher_exclusions, "eNULL"); - state->tls_context = - TLS_CLIENT_START(&tls_props, - ctx = state->tls_ctx, - stream = stream, - timeout = smtp_tmout, - tls_level = state->level, - nexthop = state->nexthop, - host = state->hostname, - namaddr = state->namaddrport, - serverid = state->addrport, - helo = state->helo ? state->helo : "", - protocols = state->protocols, - cipher_grade = state->grade, - cipher_exclusions - = vstring_str(cipher_exclusions), - matchargv = state->match, - mdalg = state->mdalg, - dane = state->ddane ? state->ddane : state->dane); + if (state->tlsproxy_mode) { + TLS_CLIENT_PARAMS tls_params; + + /* + * Send all our wishes in one big request. + */ + TLS_PROXY_CLIENT_INIT_PROPS(&init_props, + log_param = "-L option", + log_level = state->options.logopts, + verifydepth = DEF_SMTP_TLS_SCERT_VD, + cache_type = TLS_MGR_SCACHE_SMTP, + chain_files = state->chains, + cert_file = state->certfile, + key_file = state->keyfile, + dcert_file = "", + dkey_file = "", + eccert_file = "", + eckey_file = "", + CAfile = state->CAfile, + CApath = state->CApath, + mdalg = state->mdalg); + TLS_PROXY_CLIENT_START_PROPS(&start_props, + timeout = smtp_tmout, + tls_level = state->level, + nexthop = state->nexthop, + host = state->hostname, + namaddr = state->namaddrport, + sni = state->sni, + serverid = state->addrport, + helo = state->helo ? state->helo : "", + protocols = state->protocols, + cipher_grade = state->grade, + cipher_exclusions + = vstring_str(cipher_exclusions), + matchargv = state->match, + mdalg = state->mdalg, + dane = state->ddane ? + state->ddane : state->dane); + +#define PROXY_OPEN_FLAGS \ + (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT) +#define var_tlsproxy_service + + if ((cwd_fd = open(".", O_RDONLY)) < 0) + msg_fatal("open(\".\", O_RDONLY): %m"); + if (chdir(var_queue_dir) < 0) + msg_fatal("chdir(%s): %m", var_queue_dir); + port_buf = vstring_alloc(100); + vstring_sprintf(port_buf, "%d", ntohs(state->port)); + tlsproxy = + tls_proxy_open(DEF_TLSPROXY_SERVICE /* TODO */ , PROXY_OPEN_FLAGS, + state->stream, state->paddr, STR(port_buf), + smtp_tmout, smtp_tmout, state->addrport, + tls_proxy_client_param_from_config(&tls_params), + &init_props, &start_props); + vstring_free(port_buf); + if (fchdir(cwd_fd) < 0) + msg_fatal("fchdir: %m"); + (void) close(cwd_fd); + + /* + * To insert tlsproxy(8) between this process and the remote SMTP + * server, we swap the file descriptors between the tlsproxy and + * session->stream VSTREAMS, so that we don't lose all the + * user-configurable session->stream attributes (such as longjump + * buffers or timeouts). + * + * TODO: the tlsproxy RPCs should return more error detail than a "NO" + * result. + */ + if (tlsproxy == 0) { + state->tls_context = 0; + } else { + vstream_control(tlsproxy, + CA_VSTREAM_CTL_DOUBLE, + CA_VSTREAM_CTL_END); + vstream_control(state->stream, + CA_VSTREAM_CTL_SWAP_FD(tlsproxy), + CA_VSTREAM_CTL_END); + (void) vstream_fclose(tlsproxy); /* direct-to-server stream! */ + + /* + * There must not be any pending data in the stream buffers + * before we read the TLS context attributes. + */ + vstream_fpurge(state->stream, VSTREAM_PURGE_BOTH); + + /* + * After plumbing the plaintext stream, receive the TLS context + * object. For this we use the same VSTREAM buffer that we also + * use to receive subsequent SMTP commands, therefore we must be + * prepared for the possibility that the remote SMTP server + * starts talking immediately. The tlsproxy implementation sends + * the TLS context before remote content. The attribute protocol + * is robust enough that an adversary cannot insert their own TLS + * context attributes. + */ + state->tls_context = tls_proxy_context_receive(state->stream); + 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_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW, + state->tls_context); + } + } else { /* tls_proxy_mode */ + state->tls_context = + TLS_CLIENT_START(&start_props, + ctx = state->tls_ctx, + stream = stream, + fd = -1, + timeout = smtp_tmout, + tls_level = state->level, + nexthop = state->nexthop, + host = state->hostname, + namaddr = state->namaddrport, + sni = state->sni, + serverid = state->addrport, + helo = state->helo ? state->helo : "", + protocols = state->protocols, + cipher_grade = state->grade, + cipher_exclusions + = vstring_str(cipher_exclusions), + matchargv = state->match, + mdalg = state->mdalg, + dane = state->ddane ? state->ddane : state->dane); + } /* tlsproxy_mode */ vstring_free(cipher_exclusions); if (state->helo) { myfree(state->helo); @@ -780,12 +930,14 @@ static int starttls(STATE *state) ehlo(state); if (!TLS_CERT_IS_PRESENT(state->tls_context)) msg_info("Server is anonymous"); - else if (state->print_trust) - print_trust_info(state); - state->log_mask &= ~(TLS_LOG_CERTMATCH | TLS_LOG_PEERCERT | - TLS_LOG_VERBOSE | TLS_LOG_UNTRUSTED); - state->log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY; - tls_update_app_logmask(state->tls_ctx, state->log_mask); + else if (state->tlsproxy_mode == 0) { + if (state->print_trust) + print_trust_info(state); + state->log_mask &= ~(TLS_LOG_CERTMATCH | TLS_LOG_PEERCERT | + TLS_LOG_VERBOSE | TLS_LOG_UNTRUSTED); + state->log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY; + tls_update_app_logmask(state->tls_ctx, state->log_mask); + } } return (0); } @@ -879,6 +1031,8 @@ static VSTREAM *connect_sock(int sock, struct sockaddr *sa, int salen, vstring_sprintf(vstring_alloc(10), "[%s]:%u", addr, ntohs(state->port))); + state->paddr = mystrdup(addr); /* XXX for tlsproxy */ + /* * Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */ @@ -1409,7 +1563,7 @@ static int connect_dest(STATE *state) */ if (state->smtp == 0) { if (strncmp(dest, "unix:", 5) == 0) { - connect_unix(state, dest + 5); + state->stream = connect_unix(state, dest + 5); if (!state->stream) msg_info("Failed to establish session to %s: %s", dest, vstring_str(state->why->reason)); @@ -1426,9 +1580,14 @@ static int connect_dest(STATE *state) static void disconnect_dest(STATE *state) { #ifdef USE_TLS - if (state->tls_context) - tls_client_stop(state->tls_ctx, state->stream, - smtp_tmout, 0, state->tls_context); + if (state->tls_context) { + if (state->tlsproxy_mode) { + tls_proxy_context_free(state->tls_context); + } else { + tls_client_stop(state->tls_ctx, state->stream, + smtp_tmout, 0, state->tls_context); + } + } state->tls_context = 0; if (state->ddane) tls_dane_free(state->ddane); @@ -1447,6 +1606,10 @@ static void disconnect_dest(STATE *state) myfree(state->addrport); state->addrport = 0; + if (state->paddr) + myfree(state->paddr); + state->paddr = 0; + /* Reused on reconnect */ if (state->reconnect <= 0) { if (state->addr) @@ -1473,11 +1636,10 @@ static int finger(STATE *state) int err; /* - * Make sure the SMTP server cannot run us out of memory by sending - * never-ending lines of text. + * smtp_get() makes sure the SMTP server cannot run us out of memory by + * sending never-ending lines of text. */ state->buffer = vstring_alloc(100); - vstring_ctl(state->buffer, CA_VSTRING_CTL_MAXLEN(var_line_limit), 0); state->why = dsb_create(); if (!(err = connect_dest(state))) { @@ -1491,7 +1653,7 @@ static int finger(STATE *state) return (1); #ifdef USE_TLS - if (state->reconnect > 0) { + if (state->tlsproxy_mode == 0 && state->reconnect > 0) { int cache_enabled; int cache_count; int cache_hits; @@ -1519,11 +1681,7 @@ static int finger(STATE *state) static void ssl_cleanup(void) { -#if OPENSSL_VERSION_NUMBER >= 0x10000000L ERR_remove_thread_state(0); /* Thread-id is now a pointer */ -#else - ERR_remove_state(0); /* Deprecated with OpenSSL 1.0.0 */ -#endif ENGINE_cleanup(); CONF_modules_unload(1); ERR_free_strings(); @@ -1568,6 +1726,7 @@ static void cleanup(STATE *state) myfree(state->CAfile); myfree(state->certfile); myfree(state->keyfile); + myfree(state->sni); if (state->options.level) myfree(state->options.level); myfree(state->options.logopts); @@ -1596,13 +1755,13 @@ static void cleanup(STATE *state) static void usage(void) { #ifdef USE_TLS - fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s" + 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]", "[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]", - "[-A tafile] [-F CAfile.pem] [-P CApath/] " - "[-k certfile [-K keyfile]] [-m count] [-r delay]", - "[-o name=value]"); + "[-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); @@ -1620,12 +1779,14 @@ static void tls_init(STATE *state) if (state->level <= TLS_LEV_NONE) return; + /* Needed for tls_dane_avail() and other DANE-related processing. */ state->tls_ctx = TLS_CLIENT_INIT(&props, log_param = "-L option", log_level = state->options.logopts, verifydepth = DEF_SMTP_TLS_SCERT_VD, cache_type = "memory", + chain_files = state->chains, cert_file = state->certfile, key_file = state->keyfile, dcert_file = "", @@ -1672,17 +1833,20 @@ static void parse_options(STATE *state, int argc, char *argv[]) #define OPTS "a:ch:o:St:T:v" #ifdef USE_TLS -#define TLSOPTS "A:Cd:fF:g:k:K:l:L:m:M:p:P:r:w" +#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wX" state->mdalg = mystrdup("sha1"); state->CApath = mystrdup(""); state->CAfile = mystrdup(""); + state->chains = mystrdup(""); state->certfile = mystrdup(""); state->keyfile = mystrdup(""); + state->sni = mystrdup(""); state->options.tas = argv_alloc(1); state->options.logopts = 0; state->level = TLS_LEV_DANE; state->mxinsec_level = TLS_LEV_DANE; + state->tlsproxy_mode = 0; #else #define TLSOPTS "" state->level = TLS_LEV_NONE; @@ -1740,6 +1904,18 @@ static void parse_options(STATE *state, int argc, char *argv[]) myfree(state->grade); state->grade = mystrdup(optarg); break; + case 'H': + { + char *tmp; + + if (*state->chains) + tmp = concatenate(state->chains, ", ", optarg, (char *) 0); + else + tmp = mystrdup(optarg); + myfree(state->chains); + state->chains = tmp; + } + break; case 'k': myfree(state->certfile); state->certfile = mystrdup(optarg); @@ -1790,9 +1966,16 @@ static void parse_options(STATE *state, int argc, char *argv[]) case 'r': state->reconnect = atoi(optarg); break; + case 's': + myfree(state->sni); + state->sni = mystrdup(optarg); + break; case 'w': state->wrapper_mode = 1; break; + case 'X': + state->tlsproxy_mode = 1; + break; #endif } } @@ -1806,6 +1989,11 @@ static void parse_options(STATE *state, int argc, char *argv[]) if (state->addr_pref < 0) msg_fatal("bad '-a' option value: %s", state->options.addr_pref); +#ifdef USE_TLS + if (state->tlsproxy_mode && state->reconnect) + msg_fatal("The -X and -r options are mutually exclusive"); +#endif + /* * Select hostname lookup mechanisms. */ @@ -1815,6 +2003,10 @@ static void parse_options(STATE *state, int argc, char *argv[]) #ifdef USE_TLS + if (*state->chains && *state->certfile) + msg_fatal("When the '-H' option is used, neither the '-k'," + " nor the '-K' options may be used"); + if (state->reconnect < 0) tlsmgrmem_disable(); @@ -1921,6 +2113,7 @@ int main(int argc, char *argv[]) static STATE state; char *loopenv = getenv("VALGRINDLOOP"); int loop = loopenv ? atoi(loopenv) : 1; + ARGV *import_env; /* Don't die when a peer goes away unexpectedly. */ signal(SIGPIPE, SIG_IGN); @@ -1939,6 +2132,11 @@ int main(int argc, char *argv[]) mail_params_init(); parse_tas(&state); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); + argc -= optind; argv += optind; diff --git a/external/ibm-public/postfix/dist/src/proxymap/proxymap.c b/external/ibm-public/postfix/dist/src/proxymap/proxymap.c index 6c96b1afe11..631f72a9d44 100644 --- a/external/ibm-public/postfix/dist/src/proxymap/proxymap.c +++ b/external/ibm-public/postfix/dist/src/proxymap/proxymap.c @@ -1,4 +1,4 @@ -/* $NetBSD: proxymap.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: proxymap.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -126,7 +126,8 @@ /* type of security hole where ownership of a file or directory /* does not match the provider of its content. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* The \fBproxymap\fR(8) server provides service to multiple clients, /* and must therefore not be used for tables that have high-latency @@ -183,6 +184,10 @@ /* .IP "\fBproxy_write_maps (see 'postconf -d' output)\fR" /* The lookup tables that the \fBproxymap\fR(8) server is allowed to /* access for the read-write service. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* postconf(5), configuration parameters /* master(5), generic daemon options @@ -310,6 +315,8 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags, * deny the request. */ #define PROXY_MAP_FIND_ERROR_RETURN(x) { *statp = (x); return (0); } +#define PROXY_MAP_PARAM_NAME(proxy_writer) \ + ((proxy_writer) == 0 ? VAR_PROXY_READ_MAPS : VAR_PROXY_WRITE_MAPS) while (strncmp(map_type_name, PROXY_COLON, PROXY_COLON_LEN) == 0) map_type_name += PROXY_COLON_LEN; @@ -321,8 +328,7 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags, msg_warn("to approve this table for %s access, list %s:%s in %s:%s", proxy_writer == 0 ? "read-only" : "read-write", DICT_TYPE_PROXY, map_type_name, MAIN_CONF_FILE, - proxy_writer == 0 ? VAR_PROXY_READ_MAPS : - VAR_PROXY_WRITE_MAPS); + PROXY_MAP_PARAM_NAME(proxy_writer)); PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_DENY); } @@ -692,14 +698,33 @@ static void post_jail_init(char *service_name, char **unused_argv) var_proxy_read_maps); proxy_auth_maps = htable_create(13); while ((type_name = mystrtokq(&bp, sep, parens)) != 0) { + /* Maybe { maptype:mapname attr=value... } */ + if (*type_name == parens[0]) { + char *err; + + /* Warn about blatant syntax error. */ + if ((err = extpar(&type_name, parens, EXTPAR_FLAG_NONE)) != 0) { + msg_warn("bad %s parameter value: %s", + PROXY_MAP_PARAM_NAME(proxy_writer), err); + myfree(err); + continue; + } + /* Don't try to second-guess the semantics of { }. */ + if ((type_name = mystrtokq(&type_name, sep, parens)) == 0) + continue; + } if (strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN)) continue; do { type_name += PROXY_COLON_LEN; } while (!strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN)); if (strchr(type_name, ':') != 0 - && htable_locate(proxy_auth_maps, type_name) == 0) + && htable_locate(proxy_auth_maps, type_name) == 0) { (void) htable_enter(proxy_auth_maps, type_name, (void *) 0); + if (msg_verbose) + msg_info("whitelisting %s from %s", type_name, + PROXY_MAP_PARAM_NAME(proxy_writer)); + } } myfree(saved_filter); diff --git a/external/ibm-public/postfix/dist/src/qmgr/qmgr.c b/external/ibm-public/postfix/dist/src/qmgr/qmgr.c index 79c75cd6324..1f4974da770 100644 --- a/external/ibm-public/postfix/dist/src/qmgr/qmgr.c +++ b/external/ibm-public/postfix/dist/src/qmgr/qmgr.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: qmgr.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -133,7 +133,8 @@ /* does not talk to the outside world, and it can be run at fixed low /* privilege in a chrooted environment. /* DIAGNOSTICS -/* Problems and transactions are logged to the syslog daemon. +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* Corrupted message files are saved to the \fBcorrupt\fR queue /* for further inspection. /* @@ -186,24 +187,32 @@ /* .IP "\fBdefault_recipient_limit (20000)\fR" /* The default per-transport upper limit on the number of in-memory /* recipients. -/* .IP "\fItransport\fB_recipient_limit ($default_recipient_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_recipient_limit ($default_recipient_limit)\fR" +/* A transport-specific override for the default_recipient_limit +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .IP "\fBdefault_extra_recipient_limit (1000)\fR" /* The default value for the extra per-transport limit imposed on the /* number of in-memory recipients. -/* .IP "\fItransport\fB_extra_recipient_limit ($default_extra_recipient_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_extra_recipient_limit ($default_extra_recipient_limit)\fR" +/* A transport-specific override for the default_extra_recipient_limit +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .PP /* Available in Postfix version 2.4 and later: /* .IP "\fBdefault_recipient_refill_limit (100)\fR" /* The default per-transport limit on the number of recipients refilled at /* once. -/* .IP "\fItransport\fB_recipient_refill_limit ($default_recipient_refill_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_recipient_refill_limit ($default_recipient_refill_limit)\fR" +/* 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. -/* .IP "\fItransport\fB_recipient_refill_delay ($default_recipient_refill_delay)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .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 +/* the message delivery transport. /* DELIVERY CONCURRENCY CONTROLS /* .ad /* .fi @@ -213,31 +222,44 @@ /* .IP "\fBdefault_destination_concurrency_limit (20)\fR" /* The default maximal number of parallel deliveries to the same /* destination. -/* .IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .PP /* Available in Postfix version 2.5 and later: -/* .IP "\fItransport\fB_initial_destination_concurrency ($initial_destination_concurrency)\fR" -/* Initial concurrency for delivery via the named message -/* \fItransport\fR. +/* .IP "\fBtransport_initial_destination_concurrency ($initial_destination_concurrency)\fR" +/* A transport-specific override for the initial_destination_concurrency +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .IP "\fBdefault_destination_concurrency_failed_cohort_limit (1)\fR" /* How many pseudo-cohorts must suffer connection or handshake /* failure before a specific destination is considered unavailable /* (and further delivery is suspended). -/* .IP "\fItransport\fB_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_failed_cohort_limit ($default_destination_concurrency_failed_cohort_limit)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_failed_cohort_limit parameter value, +/* where \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .IP "\fBdefault_destination_concurrency_negative_feedback (1)\fR" /* The per-destination amount of delivery concurrency negative /* feedback, after a delivery completes with a connection or handshake /* failure. -/* .IP "\fItransport\fB_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_negative_feedback ($default_destination_concurrency_negative_feedback)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_negative_feedback parameter value, +/* where \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .IP "\fBdefault_destination_concurrency_positive_feedback (1)\fR" /* The per-destination amount of delivery concurrency positive /* feedback, after a delivery completes without connection or handshake /* failure. -/* .IP "\fItransport\fB_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_concurrency_positive_feedback ($default_destination_concurrency_positive_feedback)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_positive_feedback parameter value, +/* where \fItransport\fR is the master.cf name of the message delivery +/* transport. /* .IP "\fBdestination_concurrency_feedback_debug (no)\fR" /* Make the queue manager's feedback algorithm verbose for performance /* analysis purposes. @@ -246,31 +268,42 @@ /* .fi /* .IP "\fBdefault_destination_recipient_limit (50)\fR" /* The default maximal number of recipients per message delivery. -/* .IP "\fItransport\fB_destination_recipient_limit ($default_destination_recipient_limit)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +/* A transport-specific override for the +/* default_destination_recipient_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. /* MESSAGE SCHEDULING CONTROLS /* .ad /* .fi /* .IP "\fBdefault_delivery_slot_cost (5)\fR" /* How often the Postfix queue manager's scheduler is allowed to /* preempt delivery of one message with another. -/* .IP "\fItransport\fB_delivery_slot_cost ($default_delivery_slot_cost)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_delivery_slot_cost ($default_delivery_slot_cost)\fR" +/* A transport-specific override for the default_delivery_slot_cost +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .IP "\fBdefault_minimum_delivery_slots (3)\fR" /* How many recipients a message must have in order to invoke the /* Postfix queue manager's scheduling algorithm at all. -/* .IP "\fItransport\fB_minimum_delivery_slots ($default_minimum_delivery_slots)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_minimum_delivery_slots ($default_minimum_delivery_slots)\fR" +/* A transport-specific override for the default_minimum_delivery_slots +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .IP "\fBdefault_delivery_slot_discount (50)\fR" /* The default value for transport-specific _delivery_slot_discount /* settings. -/* .IP "\fItransport\fB_delivery_slot_discount ($default_delivery_slot_discount)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_delivery_slot_discount ($default_delivery_slot_discount)\fR" +/* A transport-specific override for the default_delivery_slot_discount +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .IP "\fBdefault_delivery_slot_loan (3)\fR" /* The default value for transport-specific _delivery_slot_loan /* settings. -/* .IP "\fItransport\fB_delivery_slot_loan ($default_delivery_slot_loan)\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* .IP "\fBtransport_delivery_slot_loan ($default_delivery_slot_loan)\fR" +/* A transport-specific override for the default_delivery_slot_loan +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* OTHER RESOURCE AND RATE CONTROLS /* .ad /* .fi @@ -299,18 +332,22 @@ /* Available in Postfix version 2.5 and later: /* .IP "\fBdefault_destination_rate_delay (0s)\fR" /* The default amount of delay that is inserted between individual -/* deliveries to the same destination; the resulting behavior depends -/* on the value of the corresponding per-destination recipient limit. -/* .IP "\fItransport\fB_destination_rate_delay $default_destination_rate_delay\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* message deliveries to the same destination and over the same message +/* delivery transport. +/* .IP "\fBtransport_destination_rate_delay ($default_destination_rate_delay)\fR" +/* A transport-specific override for the default_destination_rate_delay +/* parameter value, where \fItransport\fR is the master.cf name of +/* the message delivery transport. /* .PP /* Available in Postfix version 3.1 and later: /* .IP "\fBdefault_transport_rate_delay (0s)\fR" /* The default amount of delay that is inserted between individual -/* deliveries over the same message delivery transport, regardless of -/* destination. -/* .IP "\fItransport\fB_transport_rate_delay $default_transport_rate_delay\fR" -/* Idem, for delivery via the named message \fItransport\fR. +/* message deliveries over the same message delivery transport, +/* regardless of destination. +/* .IP "\fBtransport_transport_rate_delay ($default_transport_rate_delay)\fR" +/* A transport-specific override for the default_transport_rate_delay +/* parameter value, where the initial \fItransport\fR in the parameter +/* name is the master.cf name of the message delivery transport. /* SAFETY CONTROLS /* .ad /* .fi @@ -349,13 +386,22 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 3.0 and later: /* .IP "\fBconfirm_delay_cleared (no)\fR" /* After sending a "your message is delayed" notification, inform /* the sender when the delay clears up. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* FILES /* /var/spool/postfix/incoming, incoming queue /* /var/spool/postfix/active, active queue @@ -369,6 +415,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/qmgr/qmgr.h b/external/ibm-public/postfix/dist/src/qmgr/qmgr.h index 203cb072125..b03fe48390d 100644 --- a/external/ibm-public/postfix/dist/src/qmgr/qmgr.h +++ b/external/ibm-public/postfix/dist/src/qmgr/qmgr.h @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr.h,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: qmgr.h,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -510,6 +510,7 @@ struct QMGR_SCAN { #define QMGR_FLUSH_ONCE (1<<2) /* unthrottle once */ #define QMGR_FLUSH_DFXP (1<<3) /* override defer_transports */ #define QMGR_FLUSH_EACH (1<<4) /* unthrottle per message */ +#define QMGR_FORCE_EXPIRE (1<<5) /* force-defer and force-expire */ /* * qmgr_scan.c @@ -535,6 +536,11 @@ extern char *qmgr_error_nexthop(DSN *); /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Preemptive scheduler enhancements: /* Patrik Rak /* Modra 6 diff --git a/external/ibm-public/postfix/dist/src/qmgr/qmgr_active.c b/external/ibm-public/postfix/dist/src/qmgr/qmgr_active.c index e266ea7f463..de9cf3a87c9 100644 --- a/external/ibm-public/postfix/dist/src/qmgr/qmgr_active.c +++ b/external/ibm-public/postfix/dist/src/qmgr/qmgr_active.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr_active.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: qmgr_active.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -72,6 +72,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -109,6 +114,7 @@ #include <abounce.h> #include <rec_type.h> #include <qmgr_user.h> +#include <info_log_addr_form.h> /* Application-specific. */ @@ -230,14 +236,19 @@ int qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id) * a minimal amount of time. */ #define QMGR_FLUSH_AFTER (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP) +#define MAYBE_FLUSH_AFTER(mode) \ + (((mode) & MAIL_QUEUE_STAT_UNTHROTTLE) ? QMGR_FLUSH_AFTER : 0) +#define MAYBE_FORCE_EXPIRE(mode) \ + (((mode) & MAIL_QUEUE_STAT_EXPIRE) ? QMGR_FORCE_EXPIRE : 0) +#define MAYBE_UPDATE_MODE(mode) \ + (((mode) & MAIL_QUEUE_STAT_UNTHROTTLE) ? \ + (mode) & ~MAIL_QUEUE_STAT_UNTHROTTLE : 0) if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id, - (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ? - scan_info->flags | QMGR_FLUSH_AFTER : - scan_info->flags, - (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ? - st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE : - 0)) == 0) { + scan_info->flags + | MAYBE_FLUSH_AFTER(st.st_mode) + | MAYBE_FORCE_EXPIRE(st.st_mode), + MAYBE_UPDATE_MODE(st.st_mode))) == 0) { qmgr_active_corrupt(queue_id); return (0); } else if (message == QMGR_MESSAGE_LOCKED) { @@ -429,6 +440,7 @@ static void qmgr_active_done_25_trace_flush(int status, void *context) static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) { const char *myname = "qmgr_active_done_25_generic"; + const char *expire_status = 0; /* * If we get to this point we have tried all recipients for this message. @@ -438,10 +450,18 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) * daemon waits for the qmgr to accept the "new mail" trigger. */ if (message->flags) { - if (event_time() >= message->create_time + - (*message->sender ? var_max_queue_time : var_dsn_queue_time)) { - msg_info("%s: from=<%s>, status=expired, returned to sender", - message->queue_id, message->sender); + if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) { + expire_status = "force-expired"; + } else if (event_time() >= message->create_time + + (*message->sender ? var_max_queue_time : var_dsn_queue_time)) { + expire_status = "expired"; + } else { + expire_status = 0; + } + if (expire_status != 0) { + msg_info("%s: from=<%s>, status=%s, returned to sender", + message->queue_id, info_log_addr_form_sender(message->sender), + expire_status); if (message->verp_delims == 0 || var_verp_bounce_off) adefer_flush(BOUNCE_FLAG_KEEP, message->queue_name, diff --git a/external/ibm-public/postfix/dist/src/qmgr/qmgr_error.c b/external/ibm-public/postfix/dist/src/qmgr/qmgr_error.c index 5b1cca6b564..12ee72d8f2d 100644 --- a/external/ibm-public/postfix/dist/src/qmgr/qmgr_error.c +++ b/external/ibm-public/postfix/dist/src/qmgr/qmgr_error.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr_error.c,v 1.1.1.2 2020/03/18 18:59:36 christos Exp $ */ +/* $NetBSD: qmgr_error.c,v 1.2 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/qmgr/qmgr_message.c b/external/ibm-public/postfix/dist/src/qmgr/qmgr_message.c index 61f03eadcf9..06a702ffd96 100644 --- a/external/ibm-public/postfix/dist/src/qmgr/qmgr_message.c +++ b/external/ibm-public/postfix/dist/src/qmgr/qmgr_message.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmgr_message.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: qmgr_message.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -95,6 +95,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Preemptive scheduler enhancements: /* Patrik Rak /* Modra 6 @@ -643,17 +648,18 @@ static int qmgr_message_read(QMGR_MESSAGE *message) continue; } if (rec_type == REC_TYPE_DSN_ENVID) { - if (message->dsn_envid == 0) - message->dsn_envid = mystrdup(start); + /* Allow Milter override. */ + if (message->dsn_envid != 0) + myfree(message->dsn_envid); + message->dsn_envid = mystrdup(start); } if (rec_type == REC_TYPE_DSN_RET) { - if (message->dsn_ret == 0) { - if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n)) - msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s", - message->queue_id, start); - else - message->dsn_ret = n; - } + /* Allow Milter override. */ + if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n)) + msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s", + message->queue_id, start); + else + message->dsn_ret = n; } if (rec_type == REC_TYPE_ATTR) { /* Allow extra segment to override envelope segment info. */ @@ -1133,6 +1139,21 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) } /* + * Redirect a forced-to-expire message without defer log to the retry + * service, so that its defer log will contain an appropriate reason. + * Do not redirect such a message to the error service, because if + * that request fails, a defer log would be created with reason + * "bounce or trace service failure" which would make no sense. Note + * that if the bounce service fails to create a defer log, the + * message will be returned as undeliverable anyway, because it is + * expired. + */ + if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) { + QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY, + "4.7.0 message is administratively expired"); + } + + /* * Discard mail to the local double bounce address here, so this * system can run without a local delivery agent. They'd still have * to configure something for mail directed to the local postmaster, @@ -1466,6 +1487,7 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id, { const char *myname = "qmgr_message_alloc"; QMGR_MESSAGE *message; + struct stat st; if (msg_verbose) msg_info("%s: %s %s", myname, queue_name, queue_id); @@ -1505,6 +1527,25 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id, msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp)); /* + * If this message is forced to expire, use the existing defer + * logfile records and do not assign any deliveries, leaving the + * refcount at zero. If this message is forced to expire, but no + * defer logfile records are available, assign deliveries to the + * retry transport so that the sender will still find out what + * recipients are affected and why. Either way, do not assign normal + * deliveries because that would be undesirable especially with mail + * that was expired in the 'hold' queue. + */ + if ((message->qflags & QMGR_FORCE_EXPIRE) != 0 + && stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_DEFER, + queue_id), &st) == 0 && st.st_size > 0) { + /* Use this defer log; don't assign deliveries (refcount == 0). */ + message->flags = 1; /* simplify downstream code */ + qmgr_message_close(message); + return (message); + } + + /* * Reset the defer log. This code should not be here, but we must * reset the defer log *after* acquiring the exclusive lock on the * queue file and *before* resolving new recipients. Since all those diff --git a/external/ibm-public/postfix/dist/src/qmqpd/qmqpd.c b/external/ibm-public/postfix/dist/src/qmqpd/qmqpd.c index 6cca6d14f25..0682381ba7e 100644 --- a/external/ibm-public/postfix/dist/src/qmqpd/qmqpd.c +++ b/external/ibm-public/postfix/dist/src/qmqpd/qmqpd.c @@ -1,4 +1,4 @@ -/* $NetBSD: qmqpd.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: qmqpd.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -23,7 +23,8 @@ /* clients and to DNS servers on the network. The QMQP server can be /* run chrooted at fixed low privilege. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* The QMQP protocol provides only one server reply per message /* delivery. It is therefore not possible to reject individual @@ -62,6 +63,12 @@ /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBenable_idna2003_compatibility (no)\fR" +/* Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +/* when converting UTF-8 domain names to/from the ASCII form that is +/* used for DNS lookups. /* RESOURCE AND RATE CONTROLS /* .ad /* .fi @@ -124,8 +131,8 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .IP "\fBverp_delimiter_filter (-=+)\fR" /* The characters Postfix accepts as VERP delimiter characters on the /* Postfix \fBsendmail\fR(1) command line and in SMTP commands. @@ -134,10 +141,15 @@ /* .IP "\fBqmqpd_client_port_logging (no)\fR" /* Enable logging of the remote QMQP client port in addition to /* the hostname and IP address. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* http://cr.yp.to/proto/qmqp.html, QMQP protocol /* cleanup(8), message canonicalization /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/scache/scache.c b/external/ibm-public/postfix/dist/src/scache/scache.c index 02ca418ac79..0999baa9c54 100644 --- a/external/ibm-public/postfix/dist/src/scache/scache.c +++ b/external/ibm-public/postfix/dist/src/scache/scache.c @@ -1,4 +1,4 @@ -/* $NetBSD: scache.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: scache.c,v 1.3 2020/03/18 19:05:19 christos Exp $ */ /*++ /* NAME @@ -65,7 +65,8 @@ /* The \fBscache\fR(8) server is not a trusted process. It must /* not be used to store information that is security sensitive. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* The session cache cannot be shared among multiple machines. /* @@ -113,12 +114,17 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* smtp(8), SMTP client /* postconf(5), configuration parameters /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/sendmail/sendmail.c b/external/ibm-public/postfix/dist/src/sendmail/sendmail.c index c97a61d4831..6c547350616 100644 --- a/external/ibm-public/postfix/dist/src/sendmail/sendmail.c +++ b/external/ibm-public/postfix/dist/src/sendmail/sendmail.c @@ -1,4 +1,4 @@ -/* $NetBSD: sendmail.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ +/* $NetBSD: sendmail.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -109,6 +109,11 @@ /* parent directory. This information is ignored with Postfix /* versions before 2.3. /* +/* With Postfix version 3.2 and later, a non-default directory +/* must be authorized in the default \fBmain.cf\fR file, through +/* the alternate_config_directories or multi_instance_directories +/* parameters. +/* /* With all Postfix versions, you can specify a directory pathname /* with the MAIL_CONFIG environment variable to override the /* location of configuration files. @@ -252,8 +257,8 @@ /* Thus, the usual precautions need to be taken against malicious /* inputs. /* DIAGNOSTICS -/* Problems are logged to \fBsyslogd\fR(8) and to the standard error -/* stream. +/* Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8), +/* and to the standard error stream. /* ENVIRONMENT /* .ad /* .fi @@ -285,7 +290,7 @@ /* TROUBLE SHOOTING CONTROLS /* .ad /* .fi -/* The DEBUG_README file gives examples of how to trouble shoot a +/* The DEBUG_README file gives examples of how to troubleshoot a /* Postfix system. /* .IP "\fBdebugger_command (empty)\fR" /* The external command to execute when a Postfix daemon program is @@ -362,6 +367,10 @@ /* .IP "\fBdelay_warning_time (0h)\fR" /* The time after which the sender receives a copy of the message /* headers of mail that is still queued. +/* .IP "\fBimport_environment (see 'postconf -d' output)\fR" +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBmail_owner (postfix)\fR" /* The UNIX system account that owns the Postfix queue and most Postfix /* daemon processes. @@ -374,8 +383,21 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Postfix 3.2 and later: +/* .IP "\fBalternate_config_directories (empty)\fR" +/* A list of non-default Postfix configuration directories that may +/* be specified with "-c config_directory" on the command line (in the +/* case of \fBsendmail\fR(1), with the "-C" option), or via the MAIL_CONFIG +/* environment parameter. +/* .IP "\fBmulti_instance_directories (empty)\fR" +/* An optional list of non-default Postfix configuration directories; +/* these directories belong to additional Postfix instances that share +/* the Postfix executable files and documentation with the default +/* Postfix instance, and that are started, stopped, etc., together +/* with the default Postfix instance. /* FILES /* /var/spool/postfix, mail queue /* /etc/postfix, configuration files @@ -389,6 +411,7 @@ /* postdrop(1), mail posting utility /* postfix(1), mail system control /* postqueue(1), mail queue control +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README_FILES /* .ad @@ -426,7 +449,6 @@ #include <stdlib.h> #include <signal.h> #include <fcntl.h> -#include <syslog.h> #include <time.h> #include <errno.h> #include <ctype.h> @@ -439,7 +461,6 @@ #include <mymalloc.h> #include <vstream.h> #include <msg_vstream.h> -#include <msg_syslog.h> #include <vstring_vstream.h> #include <username.h> #include <fullname.h> @@ -452,6 +473,8 @@ #include <split_at.h> #include <name_code.h> #include <warn_stat.h> +#include <clean_env.h> +#include <maillog_client.h> /* Global library. */ @@ -474,8 +497,10 @@ #include <deliver_request.h> #include <mime_state.h> #include <header_opts.h> +#include <mail_dict.h> #include <user_acl.h> #include <dsn_mask.h> +#include <mail_parm_split.h> /* Application-specific. */ @@ -667,7 +692,8 @@ static void enqueue(const int flags, const char *encoding, * Stop run-away process accidents by limiting the queue file size. This * is not a defense against DOS attack. */ - if (var_message_limit > 0 && get_file_limit() > var_message_limit) + if (ENFORCING_SIZE_LIMIT(var_message_limit) + && get_file_limit() > var_message_limit) set_file_limit((off_t) var_message_limit); /* @@ -985,6 +1011,7 @@ int main(int argc, char **argv) int dsn_ret = 0; const char *dsn_envid = 0; int saved_optind; + ARGV *import_env; /* * Fingerprint executables and core dumps. @@ -1025,15 +1052,15 @@ int main(int argc, char **argv) debug_me = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. Set up signal handlers so that we - * can clean up incomplete output. + * Initialize. Set up logging. Read the global configuration file after + * command-line processing. Set up signal handlers so that we can clean + * up incomplete output. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); msg_cleanup(tempfail); - msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("sendmail"), MAILLOG_CLIENT_FLAG_NONE); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -1070,20 +1097,29 @@ int main(int argc, char **argv) break; if (c == 'C') { VSTRING *buf = vstring_alloc(1); + char *dir; - if (setenv(CONF_ENV_PATH, - strcmp(sane_basename(buf, optarg), MAIN_CONF_FILE) == 0 ? - sane_dirname(buf, optarg) : optarg, 1) < 0) + dir = strcmp(sane_basename(buf, optarg), MAIN_CONF_FILE) == 0 ? + sane_dirname(buf, optarg) : optarg; + if (strcmp(dir, DEF_CONFIG_DIR) != 0 && geteuid() != 0) + mail_conf_checkdir(dir); + if (setenv(CONF_ENV_PATH, dir, 1) < 0) msg_fatal_status(EX_UNAVAILABLE, "out of memory"); vstring_free(buf); } } optind = saved_optind; mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("sendmail"), MAILLOG_CLIENT_FLAG_NONE); get_mail_conf_str_table(str_table); + mail_dict_init(); + if (chdir(var_queue_dir)) msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir); diff --git a/external/ibm-public/postfix/dist/src/showq/showq.c b/external/ibm-public/postfix/dist/src/showq/showq.c index 2ad39cc89bc..c3ad21d572e 100644 --- a/external/ibm-public/postfix/dist/src/showq/showq.c +++ b/external/ibm-public/postfix/dist/src/showq/showq.c @@ -1,4 +1,4 @@ -/* $NetBSD: showq.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: showq.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -28,7 +28,8 @@ /* None. The \fBshowq\fR(8) daemon does not interact with the /* outside world. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -68,12 +69,16 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 2.9 and later: /* .IP "\fBenable_long_queue_ids (no)\fR" /* Enable long, non-repeating, queue IDs (queue file names). +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* FILES /* /var/spool/postfix, queue directories /* SEE ALSO @@ -82,6 +87,7 @@ /* qmgr(8), queue manager /* postconf(5), configuration parameters /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad @@ -156,7 +162,8 @@ static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *, /* showq_report - report status of sender and recipients */ static void showq_report(VSTREAM *client, char *queue, char *id, - VSTREAM *qfile, long size, time_t mtime) + VSTREAM *qfile, long size, time_t mtime, + mode_t mode) { VSTRING *buf = vstring_alloc(100); VSTRING *printable_quoted_addr = vstring_alloc(100); @@ -236,6 +243,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id, SEND_ATTR_LONG(MAIL_ATTR_TIME, arrival_time > 0 ? arrival_time : mtime), SEND_ATTR_LONG(MAIL_ATTR_SIZE, msg_size), + SEND_ATTR_INT(MAIL_ATTR_FORCED_EXPIRE, + (mode & MAIL_QUEUE_STAT_EXPIRE) != 0), SEND_ATTR_STR(MAIL_ATTR_SENDER, STR(printable_quoted_addr)), ATTR_TYPE_END); @@ -381,7 +390,7 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv) if (status == MAIL_OPEN_YES) { if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) { showq_report(client, qp->name, id, qfile, (long) st.st_size, - st.st_mtime); + st.st_mtime, st.st_mode); if (vstream_fclose(qfile)) msg_warn("close file %s %s: %m", qp->name, id); } else if (errno != ENOENT) { diff --git a/external/ibm-public/postfix/dist/src/smtp/lmtp_params.c b/external/ibm-public/postfix/dist/src/smtp/lmtp_params.c index 15fe9f7ab84..fd5e8e0325a 100644 --- a/external/ibm-public/postfix/dist/src/smtp/lmtp_params.c +++ b/external/ibm-public/postfix/dist/src/smtp/lmtp_params.c @@ -1,4 +1,4 @@ -/* $NetBSD: lmtp_params.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: lmtp_params.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ static const CONFIG_STR_TABLE lmtp_str_table[] = { VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, @@ -11,6 +11,7 @@ #ifdef USE_TLS VAR_LMTP_SASL_TLS_OPTS, DEF_LMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0, VAR_LMTP_SASL_TLSV_OPTS, DEF_LMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tlsv_opts, 0, 0, + VAR_LMTP_TLS_CHAIN_FILES, DEF_LMTP_TLS_CHAIN_FILES, &var_smtp_tls_chain_files, 0, 0, VAR_LMTP_TLS_CERT_FILE, DEF_LMTP_TLS_CERT_FILE, &var_smtp_tls_cert_file, 0, 0, VAR_LMTP_TLS_KEY_FILE, DEF_LMTP_TLS_KEY_FILE, &var_smtp_tls_key_file, 0, 0, VAR_LMTP_TLS_DCERT_FILE, DEF_LMTP_TLS_DCERT_FILE, &var_smtp_tls_dcert_file, 0, 0, @@ -31,6 +32,7 @@ VAR_LMTP_TLS_ECCERT_FILE, DEF_LMTP_TLS_ECCERT_FILE, &var_smtp_tls_eccert_file, 0, 0, VAR_LMTP_TLS_ECKEY_FILE, DEF_LMTP_TLS_ECKEY_FILE, &var_smtp_tls_eckey_file, 0, 0, VAR_LMTP_TLS_LOGLEVEL, DEF_LMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0, + VAR_LMTP_TLS_SNI, DEF_LMTP_TLS_SNI, &var_smtp_tls_sni, 0, 0, #endif VAR_LMTP_SASL_MECHS, DEF_LMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0, VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, @@ -49,7 +51,7 @@ VAR_LMTP_TLS_POLICY, DEF_LMTP_TLS_POLICY, &var_smtp_tls_policy, 0, 0, VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0, VAR_LMTP_GENERIC_MAPS, DEF_LMTP_GENERIC_MAPS, &var_smtp_generic_maps, 0, 0, - VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_lmtp_tcp_port, 0, 0, + VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_smtp_tcp_port, 0, 0, VAR_LMTP_PIX_BUG_WORDS, DEF_LMTP_PIX_BUG_WORDS, &var_smtp_pix_bug_words, 0, 0, VAR_LMTP_PIX_BUG_MAPS, DEF_LMTP_PIX_BUG_MAPS, &var_smtp_pix_bug_maps, 0, 0, VAR_LMTP_SASL_AUTH_CACHE_NAME, DEF_LMTP_SASL_AUTH_CACHE_NAME, &var_smtp_sasl_auth_cache_name, 0, 0, @@ -63,6 +65,7 @@ VAR_LMTP_DNS_RES_OPT, DEF_LMTP_DNS_RES_OPT, &var_smtp_dns_res_opt, 0, 0, VAR_LMTP_DSN_FILTER, DEF_LMTP_DSN_FILTER, &var_smtp_dsn_filter, 0, 0, VAR_LMTP_DNS_RE_FILTER, DEF_LMTP_DNS_RE_FILTER, &var_smtp_dns_re_filter, 0, 0, + VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0, 0, }; static const CONFIG_TIME_TABLE lmtp_time_table[] = { @@ -110,6 +113,7 @@ VAR_LMTP_CACHE_DEMAND, DEF_LMTP_CACHE_DEMAND, &var_smtp_cache_demand, VAR_LMTP_USE_TLS, DEF_LMTP_USE_TLS, &var_smtp_use_tls, VAR_LMTP_ENFORCE_TLS, DEF_LMTP_ENFORCE_TLS, &var_smtp_enforce_tls, + VAR_LMTP_TLS_CONN_REUSE, DEF_LMTP_TLS_CONN_REUSE, &var_smtp_tls_conn_reuse, #ifdef USE_TLS VAR_LMTP_TLS_ENFORCE_PN, DEF_LMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername, VAR_LMTP_TLS_NOTEOFFER, DEF_LMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer, @@ -123,5 +127,6 @@ VAR_LMTP_ASSUME_FINAL, DEF_LMTP_ASSUME_FINAL, &var_lmtp_assume_final, VAR_LMTP_REC_DEADLINE, DEF_LMTP_REC_DEADLINE, &var_smtp_rec_deadline, VAR_LMTP_DUMMY_MAIL_AUTH, DEF_LMTP_DUMMY_MAIL_AUTH, &var_smtp_dummy_mail_auth, + VAR_LMTP_BALANCE_INET_PROTO, DEF_LMTP_BALANCE_INET_PROTO, &var_smtp_balance_inet_proto, 0, }; diff --git a/external/ibm-public/postfix/dist/src/smtp/map11_map b/external/ibm-public/postfix/dist/src/smtp/map11_map deleted file mode 100644 index 5b35f1e5494..00000000000 --- a/external/ibm-public/postfix/dist/src/smtp/map11_map +++ /dev/null @@ -1,3 +0,0 @@ -foo@example.com bar@com.example -bar@example.com bar -baz@example.com @com.example diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp.c b/external/ibm-public/postfix/dist/src/smtp/smtp.c index e3ff3daf32b..3137e816cb3 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp.c,v 1.10 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp.c,v 1.11 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -6,7 +6,7 @@ /* SUMMARY /* Postfix SMTP+LMTP client /* SYNOPSIS -/* \fBsmtp\fR [generic Postfix daemon options] +/* \fBsmtp\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 @@ -40,6 +40,8 @@ /* SMTP DESTINATION SYNTAX /* .ad /* .fi +/* The Postfix SMTP+LMTP client supports multiple destinations +/* separated by comma or whitespace (Postfix 3.5 and later). /* SMTP destinations have the following form: /* .IP \fIdomainname\fR /* .IP \fIdomainname\fR:\fIport\fR @@ -57,6 +59,8 @@ /* LMTP DESTINATION SYNTAX /* .ad /* .fi +/* The Postfix SMTP+LMTP client supports multiple destinations +/* separated by comma or whitespace (Postfix 3.5 and later). /* LMTP destinations have the following form: /* .IP \fBunix\fR:\fIpathname\fR /* Connect to the local UNIX-domain server that is bound to the specified @@ -72,10 +76,62 @@ /* If no such service is found, the \fBlmtp_tcp_port\fR configuration /* parameter (default value of 24) will be used. /* An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. -/* .PP -/* SECURITY +/* SINGLE-RECIPIENT DELIVERY /* .ad /* .fi +/* By default, the Postfix SMTP+LMTP client delivers mail to +/* multiple recipients per delivery request. This is undesirable +/* when prepending a \fBDelivered-to:\fR or \fBX-Original-To:\fR +/* message header. To prevent Postfix from sending multiple +/* recipients per delivery request, specify +/* .sp +/* .nf +/* \fItransport\fB_destination_recipient_limit = 1\fR +/* .fi +/* +/* in the Postfix \fBmain.cf\fR file, where \fItransport\fR +/* is the name in the first column of the Postfix \fBmaster.cf\fR +/* entry for this mail delivery service. +/* COMMAND ATTRIBUTE SYNTAX +/* .ad +/* .fi +/* .IP "\fBflags=DORX\fR (optional)" +/* Optional message processing flags. +/* .RS +/* .IP \fBD\fR +/* Prepend a "\fBDelivered-To: \fIrecipient\fR" message header +/* with the envelope recipient address. Note: for this to work, +/* the \fItransport\fB_destination_recipient_limit\fR must be +/* 1 (see SINGLE-RECIPIENT DELIVERY above for details). +/* .sp +/* The \fBD\fR flag also enforces loop detection: if a message +/* already contains a \fBDelivered-To:\fR header with the same +/* recipient address, then the message is returned as +/* undeliverable. The address comparison is case insensitive. +/* .sp +/* This feature is available as of Postfix 3.5. +/* .IP \fBO\fR +/* Prepend an "\fBX-Original-To: \fIrecipient\fR" message +/* header with the recipient address as given to Postfix. Note: +/* for this to work, the +/* \fItransport\fB_destination_recipient_limit\fR must be 1 +/* (see SINGLE-RECIPIENT DELIVERY above for details). +/* .sp +/* This feature is available as of Postfix 3.5. +/* .IP \fBR\fR +/* Prepend a "\fBReturn-Path: <\fIsender\fB>\fR" message header +/* with the envelope sender address. +/* .sp +/* This feature is available as of Postfix 3.5. +/* .IP \fBX\fR +/* Indicates that the delivery is final. This flag affects +/* the status reported in "success" DSN (delivery status +/* notification) messages, and changes it from "relayed" into +/* "delivered". +/* .sp +/* This feature is available as of Postfix 3.5. +/* .RE +/* 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 @@ -102,7 +158,8 @@ /* RFC 6533 (Internationalized Delivery Status Notifications) /* RFC 7672 (SMTP security via opportunistic DANE TLS) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* Corrupted message files are marked so that the queue manager can /* move them to the \fBcorrupt\fR queue for further inspection. /* @@ -110,11 +167,10 @@ /* the postmaster is notified of bounces, protocol problems, and of /* other trouble. /* BUGS -/* SMTP and LMTP connection caching does not work with TLS. The necessary -/* support for TLS object passivation and re-activation does not -/* exist without closing the session, which defeats the purpose. +/* SMTP and LMTP connection reuse for TLS (without closing the +/* SMTP or LMTP connection) is not supported before Postfix 3.4. /* -/* SMTP and LMTP connection caching assumes that SASL credentials +/* SMTP and LMTP connection reuse assumes that SASL credentials /* are valid for all destinations that map onto the same IP /* address and TCP port. /* CONFIGURATION PARAMETERS @@ -265,6 +321,17 @@ /* deliveries. /* .IP "\fBsmtp_dns_reply_filter (empty)\fR" /* Optional filter for Postfix SMTP client DNS lookup results. +/* .PP +/* Available in Postfix version 3.3 and later: +/* .IP "\fBsmtp_balance_inet_protocols (yes)\fR" +/* 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. +/* .PP +/* 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.). /* MIME PROCESSING CONTROLS /* .ad /* .fi @@ -454,6 +521,13 @@ /* .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR" /* List or bit-mask of OpenSSL bug work-arounds to disable. /* .PP +/* Available in Postfix version 2.11-3.1: +/* .IP "\fBtls_dane_digest_agility (on)\fR" +/* Configure RFC7671 DANE TLSA digest algorithm agility. +/* .IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR" +/* Enable support for RFC 6698 (DANE TLSA) DNS records that contain +/* digests of trust-anchors with certificate usage "2". +/* .PP /* Available in Postfix version 2.11 and later: /* .IP "\fBsmtp_tls_trust_anchor_file (empty)\fR" /* Zero or more PEM-format files with trust-anchor certificates @@ -461,8 +535,6 @@ /* .IP "\fBsmtp_tls_force_insecure_host_tlsa_lookup (no)\fR" /* Lookup the associated DANE TLSA RRset even when a hostname is /* not an alias and its address records lie in an unsigned zone. -/* .IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR" -/* RFC 6698 trust-anchor digest support in the Postfix TLS library. /* .IP "\fBtlsmgr_service_name (tlsmgr)\fR" /* The name of the \fBtlsmgr\fR(8) service entry in master.cf. /* .PP @@ -476,6 +548,21 @@ /* The TLS policy for MX hosts with "secure" TLSA records when the /* nexthop destination security level is \fBdane\fR, but the MX /* record was found via an "insecure" MX lookup. +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBsmtp_tls_connection_reuse (no)\fR" +/* Try to make multiple deliveries per TLS-encrypted connection. +/* .IP "\fBsmtp_tls_chain_files (empty)\fR" +/* List of one or more PEM files, each holding one or more private keys +/* directly followed by a corresponding certificate chain. +/* .IP "\fBsmtp_tls_servername (empty)\fR" +/* Optional name to send to the remote SMTP server in the TLS Server +/* Name Indication (SNI) extension. +/* .PP +/* Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later: +/* .IP "\fBtls_fast_shutdown_enable (yes)\fR" +/* A workaround for implementations that hang Postfix while shutting +/* down a TLS session, until Postfix times out. /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -501,12 +588,6 @@ /* RESOURCE AND RATE CONTROLS /* .ad /* .fi -/* .IP "\fBsmtp_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" -/* The maximal number of parallel deliveries to the same destination -/* via the smtp message delivery transport. -/* .IP "\fBsmtp_destination_recipient_limit ($default_destination_recipient_limit)\fR" -/* The maximal number of recipients per message for the smtp -/* message delivery transport. /* .IP "\fBsmtp_connect_timeout (30s)\fR" /* The Postfix SMTP client time limit for completing a TCP connection, or /* zero (use the operating system built-in time limit). @@ -587,6 +668,22 @@ /* When SMTP connection caching is enabled, the number of times /* that an SMTP session may be reused before it is closed, or zero (no /* limit). +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBsmtp_tls_connection_reuse (no)\fR" +/* Try to make multiple deliveries per TLS-encrypted connection. +/* .PP +/* Implemented in the qmgr(8) daemon: +/* .IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" +/* A transport-specific override for the +/* default_destination_concurrency_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. +/* .IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR" +/* A transport-specific override for the +/* default_destination_recipient_limit parameter value, where +/* \fItransport\fR is the master.cf name of the message delivery +/* transport. /* SMTPUTF8 CONTROLS /* .ad /* .fi @@ -597,6 +694,12 @@ /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBenable_idna2003_compatibility (no)\fR" +/* Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +/* when converting UTF-8 domain names to/from the ASCII form that is +/* used for DNS lookups. /* TROUBLE SHOOTING CONTROLS /* .ad /* .fi @@ -685,8 +788,8 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available with Postfix 2.2 and earlier: /* .IP "\fBfallback_relay (empty)\fR" @@ -707,6 +810,14 @@ /* .IP "\fBlmtp_fallback_relay (empty)\fR" /* Optional list of relay hosts for LMTP destinations that can't be /* found or that are unreachable. +/* .PP +/* Available with Postfix 3.2 and later: +/* .IP "\fBsmtp_tcp_port (smtp)\fR" +/* The default TCP port that the Postfix SMTP client connects to. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* generic(5), output address rewriting /* header_checks(5), message header content inspection @@ -718,6 +829,7 @@ /* master(5), generic daemon options /* master(8), process manager /* tlsmgr(8), TLS session and PRNG management +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad @@ -784,10 +896,13 @@ #include <mymalloc.h> #include <name_mask.h> #include <name_code.h> +#include <byte_mask.h> /* Global library. */ #include <deliver_request.h> +#include <delivered_hdr.h> +#include <mail_proto.h> #include <mail_params.h> #include <mail_version.h> #include <mail_conf.h> @@ -873,6 +988,8 @@ bool var_smtp_enforce_tls; char *var_smtp_tls_per_site; char *var_smtp_tls_policy; bool var_smtp_tls_wrappermode; +bool var_smtp_tls_conn_reuse; +char *var_tlsproxy_service; #ifdef USE_TLS char *var_smtp_sasl_tls_opts; @@ -880,6 +997,7 @@ char *var_smtp_sasl_tlsv_opts; int var_smtp_starttls_tmout; char *var_smtp_tls_CAfile; char *var_smtp_tls_CApath; +char *var_smtp_tls_chain_files; char *var_smtp_tls_cert_file; char *var_smtp_tls_mand_ciph; char *var_smtp_tls_excl_ciph; @@ -901,6 +1019,7 @@ char *var_smtp_tls_proto; char *var_smtp_tls_ciph; char *var_smtp_tls_eccert_file; char *var_smtp_tls_eckey_file; +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; @@ -910,7 +1029,7 @@ char *var_smtp_tls_insecure_mx_policy; char *var_smtp_generic_maps; char *var_prop_extension; bool var_smtp_sender_auth; -char *var_lmtp_tcp_port; +char *var_smtp_tcp_port; int var_scache_proto_tmout; bool var_smtp_cname_overr; char *var_smtp_pix_bug_words; @@ -928,6 +1047,7 @@ bool var_smtp_rec_deadline; bool var_smtp_dummy_mail_auth; char *var_smtp_dsn_filter; char *var_smtp_dns_re_filter; +bool var_smtp_balance_inet_proto; /* Special handling of 535 AUTH errors. */ char *var_smtp_sasl_auth_cache_name; @@ -949,6 +1069,7 @@ unsigned smtp_dns_res_opt; MAPS *smtp_pix_bug_maps; HBC_CHECKS *smtp_header_checks; /* limited header checks */ HBC_CHECKS *smtp_body_checks; /* limited body checks */ +SMTP_CLI_ATTR smtp_cli_attr; /* parsed command-line */ #ifdef USE_TLS @@ -965,6 +1086,59 @@ int smtp_tls_insecure_mx_policy; */ static int smtp_addr_pref; +/* get_cli_attr - get command-line attributes */ + +static void get_cli_attr(SMTP_CLI_ATTR *attr, char **argv) +{ + const char myname[] = "get_cli_attr"; + const char *last_flags = "flags="; /* i.e. empty */ + static const BYTE_MASK flags_map[] = { + 'D', SMTP_CLI_FLAG_DELIVERED_TO, + 'O', SMTP_CLI_FLAG_ORIG_RCPT, + 'R', SMTP_CLI_FLAG_RETURN_PATH, + 'X', SMTP_CLI_FLAG_FINAL_DELIVERY, + 0, + }; + + /* + * Initialize. + */ + attr->flags = 0; + + /* + * Iterate over the command-line attribute list. Errors are fatal. + */ + for ( /* void */ ; *argv != 0; argv++) { + + /* + * flags=stuff. Errors are fatal. + */ + if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) { + last_flags = *argv; + if (msg_verbose) + msg_info("%s: %s", myname, last_flags); + attr->flags = byte_mask(*argv, flags_map, + *argv + sizeof("flags=") - 1); + } + + /* + * Bad. + */ + else + msg_fatal("unknown attribute name: %s", *argv); + } + + /* + * Backwards compatibility, redundancy, and obsolescence. + */ + if (!smtp_mode && var_lmtp_assume_final + && (attr->flags & SMTP_CLI_FLAG_FINAL_DELIVERY) == 0) { + attr->flags |= SMTP_CLI_FLAG_FINAL_DELIVERY; + msg_warn("%s is obsolete; instead, specify \"%sX\" in %s", + VAR_LMTP_ASSUME_FINAL, last_flags, MASTER_CONF_FILE); + } +} + /* deliver_message - deliver message with extreme prejudice */ static int deliver_message(const char *service, DELIVER_REQUEST *request) @@ -986,6 +1160,55 @@ static int deliver_message(const char *service, DELIVER_REQUEST *request) msg_fatal("recipient count: %d", request->rcpt_list.len); /* + * D flag checks. + */ + if (smtp_cli_attr.flags & SMTP_CLI_FLAG_DELIVERED_TO) { + + /* + * The D flag cannot be specified for multi-recipient deliveries. + */ + if (request->rcpt_list.len > 1) { + msg_warn("flag `D' requires %s_destination_recipient_limit = 1", + service); + return (reject_deliver_request(service, request, "4.3.5", + "mail system configuration error")); + } + + /* + * The recipient cannot appear in a Delivered-To: header. + */ + else { + DELIVERED_HDR_INFO *delivered_info = delivered_hdr_init( + request->fp, request->data_offset, FOLD_ADDR_ALL); + VSTRING *generic_rcpt = vstring_alloc(100); + int have_delivered_loop; + + smtp_rewrite_generic_internal(generic_rcpt, + request->rcpt_list.info->address); + have_delivered_loop = delivered_hdr_find( + delivered_info, STR(generic_rcpt)); + vstring_free(generic_rcpt); + delivered_hdr_free(delivered_info); + if (have_delivered_loop) { + return (reject_deliver_request(service, request, "5.4.6", + "mail forwarding loop for %s", + request->rcpt_list.info->address)); + } + } + } + + /* + * The O flag cannot be specified for multi-recipient deliveries. + */ + if ((smtp_cli_attr.flags & SMTP_CLI_FLAG_ORIG_RCPT) + && request->rcpt_list.len > 1) { + msg_warn("flag `O' requires %s_destination_recipient_limit = 1", + service); + return (reject_deliver_request(service, request, "4.3.5", + "mail system configuration error")); + } + + /* * Initialize. Bundle all information about the delivery request, so that * we can produce understandable diagnostics when something goes wrong * many levels below. The alternative would be to make everything global. @@ -1015,18 +1238,13 @@ static int deliver_message(const char *service, DELIVER_REQUEST *request) /* smtp_service - perform service for client */ -static void smtp_service(VSTREAM *client_stream, char *service, char **argv) +static void smtp_service(VSTREAM *client_stream, char *service, + char **unused_argv) { DELIVER_REQUEST *request; int status; /* - * Sanity check. This service takes no command-line arguments. - */ - if (argv[0]) - msg_fatal("unexpected command-line argument: %s", argv[0]); - - /* * This routine runs whenever a client connects to the UNIX-domain socket * dedicated to remote SMTP delivery service. What we see below is a * little protocol to (1) tell the queue manager that we are ready, (2) @@ -1042,7 +1260,7 @@ static void smtp_service(VSTREAM *client_stream, char *service, char **argv) /* post_init - post-jail initialization */ -static void post_init(char *unused_name, char **unused_argv) +static void post_init(char *unused_name, char **argv) { static const NAME_MASK lookup_masks[] = { SMTP_HOST_LOOKUP_DNS, SMTP_HOST_FLAG_DNS, @@ -1129,6 +1347,12 @@ static void post_init(char *unused_name, char **unused_argv) * Address verification. */ smtp_vrfy_init(); + + /* + * Look up service command-line attributes; these do not change during + * the process lifetime. + */ + get_cli_attr(&smtp_cli_attr, argv); } /* pre_init - pre-jail initialization */ @@ -1192,12 +1416,17 @@ static void pre_init(char *unused_name, char **unused_argv) #ifdef USE_TLS TLS_CLIENT_INIT_PROPS props; + tls_pre_jail_init(TLS_ROLE_CLIENT); + /* * We get stronger type safety and a cleaner interface by combining * the various parameters into a single tls_client_props structure. * * Large parameter lists are error-prone, so we emulate a language * feature that C does not have natively: named parameter lists. + * + * With tlsproxy(8) turned on, this is still needed for DANE-related + * initializations. */ smtp_tls_ctx = TLS_CLIENT_INIT(&props, @@ -1205,6 +1434,7 @@ static void pre_init(char *unused_name, char **unused_argv) log_level = var_smtp_tls_loglevel, verifydepth = var_smtp_tls_scert_vd, cache_type = LMTP_SMTP_SUFFIX(TLS_MGR_SCACHE), + chain_files = var_smtp_tls_chain_files, cert_file = var_smtp_tls_cert_file, key_file = var_smtp_tls_key_file, dcert_file = var_smtp_tls_dcert_file, @@ -1341,6 +1571,7 @@ int main(int argc, char **argv) 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); diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp.h b/external/ibm-public/postfix/dist/src/smtp/smtp.h index df3a8f06499..62eef6549f7 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp.h +++ b/external/ibm-public/postfix/dist/src/smtp/smtp.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtp.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp.h,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -41,6 +41,11 @@ #include <tls.h> /* + * tlsproxy client. + */ +#include <tls_proxy.h> + + /* * Global iterator support. This is updated by the connection-management * loop, and contains dynamic context that appears in lookup keys for SASL * passwords, TLS policy, cached SMTP connections, and cached TLS session @@ -51,7 +56,7 @@ */ typedef struct SMTP_ITERATOR { /* Public members. */ - VSTRING *request_nexthop; /* request nexhop or empty */ + VSTRING *request_nexthop; /* delivery request nexhop or empty */ VSTRING *dest; /* current nexthop */ VSTRING *host; /* hostname or empty */ VSTRING *addr; /* printable address or empty */ @@ -73,12 +78,6 @@ typedef struct SMTP_ITERATOR { (iter)->parent = (state); \ } while (0) -#define SMTP_ITER_CLOBBER(iter, _dest, _host, _addr) do { \ - vstring_strcpy((iter)->dest, (_dest)); \ - vstring_strcpy((iter)->host, (_host)); \ - vstring_strcpy((iter)->addr, (_addr)); \ - } while (0) - #define SMTP_ITER_SAVE_DEST(iter) do { \ vstring_strcpy((iter)->saved_dest, STR((iter)->dest)); \ } while (0) @@ -100,6 +99,8 @@ typedef struct SMTP_TLS_POLICY { ARGV *matchargv; /* Cert match patterns */ DSN_BUF *why; /* Lookup error status */ TLS_DANE *dane; /* DANE TLSA digests */ + char *sni; /* Optional SNI name when not DANE */ + int conn_reuse; /* enable connection reuse */ } SMTP_TLS_POLICY; /* @@ -133,6 +134,8 @@ extern void smtp_tls_policy_cache_flush(void); _tls_policy_init_tmp->matchargv = 0; \ _tls_policy_init_tmp->why = (w); \ _tls_policy_init_tmp->dane = 0; \ + _tls_policy_init_tmp->sni = 0; \ + _tls_policy_init_tmp->conn_reuse = 0; \ } while (0) #endif @@ -187,17 +190,26 @@ typedef struct SMTP_STATE { } SMTP_STATE; /* - * TODO: use the new SMTP_ITER name space. - */ -#define SET_NEXTHOP_STATE(state, nexthop) { \ + * Primitives to enable/disable/test connection caching and reuse based on + * the delivery request next-hop destination (i.e. not smtp_fallback_relay). + * + * Connection cache lookup by the delivery request next-hop destination allows + * a reuse request to skip over bad hosts, and may result in a connection to + * a fall-back relay. Once we have found a 'good' host for a delivery + * request next-hop, clear the delivery request next-hop destination, to + * avoid caching less-preferred connections under that same delivery request + * next-hop. + */ +#define SET_SCACHE_REQUEST_NEXTHOP(state, nexthop) do { \ vstring_strcpy((state)->iterator->request_nexthop, nexthop); \ - } + } while (0) -#define FREE_NEXTHOP_STATE(state) { \ +#define CLEAR_SCACHE_REQUEST_NEXTHOP(state) do { \ STR((state)->iterator->request_nexthop)[0] = 0; \ - } + } while (0) -#define HAVE_NEXTHOP_STATE(state) (STR((state)->iterator->request_nexthop)[0] != 0) +#define HAVE_SCACHE_REQUEST_NEXTHOP(state) \ + (STR((state)->iterator->request_nexthop)[0] != 0) /* @@ -224,6 +236,7 @@ typedef struct SMTP_STATE { #define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */ #define SMTP_FEATURE_XFORWARD_IDENT (1<<20) #define SMTP_FEATURE_SMTPUTF8 (1<<21) /* RFC 6531 */ +#define SMTP_FEATURE_FROM_PROXY (1<<22) /* proxied connection */ /* * Features that passivate under the endpoint. @@ -397,7 +410,7 @@ extern HBC_CALL_BACKS smtp_hbc_callbacks[]; * at completely different times. * * We "freeze" the choice in the sender loop, just before we generate "." or - * "RSET". The reader loop leaves the connection cachable even if the timer + * "RSET". The reader loop leaves the connection cacheable even if the timer * expires by the time the response arrives. The connection cleanup code * will call smtp_quit() for connections with an expired cache expiration * timer. @@ -611,17 +624,18 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); #define SMTP_KEY_FLAG_SERVICE (1<<0) /* service name */ #define SMTP_KEY_FLAG_SENDER (1<<1) /* sender address */ -#define SMTP_KEY_FLAG_REQ_NEXTHOP (1<<2) /* request nexthop */ -#define SMTP_KEY_FLAG_NEXTHOP (1<<3) /* current nexthop */ +#define SMTP_KEY_FLAG_REQ_NEXTHOP (1<<2) /* delivery request nexthop */ +#define SMTP_KEY_FLAG_CUR_NEXTHOP (1<<3) /* current nexthop */ #define SMTP_KEY_FLAG_HOSTNAME (1<<4) /* remote host name */ #define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */ #define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */ +#define SMTP_KEY_FLAG_TLS_LEVEL (1<<7) /* requested TLS level */ #define SMTP_KEY_MASK_ALL \ (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \ SMTP_KEY_FLAG_REQ_NEXTHOP | \ - SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \ - SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT) + SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \ + SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL) /* * Conditional lookup-key flags for cached connections that may be @@ -634,17 +648,28 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); ((var_smtp_sender_auth && *var_smtp_sasl_passwd) ? \ SMTP_KEY_FLAG_SENDER : 0) -#define COND_SASL_SMTP_KEY_FLAG_NEXTHOP \ - (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_NEXTHOP : 0) +#define COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \ + (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0) + +#ifdef USE_TLS +#define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \ + (TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0) +#else +#define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \ + (0) +#endif #define COND_SASL_SMTP_KEY_FLAG_HOSTNAME \ (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_HOSTNAME : 0) /* - * Connection-cache destination lookup key. The SENDER attribute is a proxy - * for sender-dependent SASL credentials (or absence thereof), and prevents - * false connection sharing when different SASL credentials may be required - * for different deliveries to the same domain and port. The SERVICE + * Connection-cache destination lookup key, based on the delivery request + * nexthop. The SENDER attribute is a proxy for sender-dependent SASL + * credentials (or absence thereof), and prevents false connection sharing + * when different SASL credentials may be required for different deliveries + * to the same domain and port. Likewise, the delivery request nexthop + * (REQ_NEXTHOP) prevents false sharing of TLS identities (the destination + * key links only to appropriate endpoint lookup keys). The SERVICE * attribute is a proxy for all request-independent configuration details. */ #define SMTP_KEY_MASK_SCACHE_DEST_LABEL \ @@ -652,15 +677,19 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); | SMTP_KEY_FLAG_REQ_NEXTHOP) /* - * Connection-cache endpoint lookup key. The SENDER, NEXTHOP, and HOSTNAME - * attributes are proxies for SASL credentials (or absence thereof), and - * prevent false connection sharing when different SASL credentials may be - * required for different deliveries to the same IP address and port. + * Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME, + * PORT and TLS_LEVEL attributes are proxies for SASL credentials and TLS + * authentication (or absence thereof), and prevent false connection sharing + * when different SASL credentials or TLS identities may be required for + * different deliveries to the same IP address and port. The SERVICE + * attribute is a proxy for all request-independent configuration details. */ #define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \ (SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \ - | COND_SASL_SMTP_KEY_FLAG_NEXTHOP | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \ - | SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT) + | COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \ + | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \ + | COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_ADDR | \ + SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL) /* * Silly little macros. @@ -673,6 +702,31 @@ extern int smtp_mode; #define VAR_LMTP_SMTP(x) (smtp_mode ? VAR_SMTP_##x : VAR_LMTP_##x) #define LMTP_SMTP_SUFFIX(x) (smtp_mode ? x##_SMTP : x##_LMTP) + /* + * Parsed command-line attributes. These do not change during the process + * lifetime. + */ +typedef struct { + int flags; /* from flags=, see below */ +} SMTP_CLI_ATTR; + +#define SMTP_CLI_FLAG_DELIVERED_TO (1<<0) /* prepend Delivered-To: */ +#define SMTP_CLI_FLAG_ORIG_RCPT (1<<1) /* prepend X-Original-To: */ +#define SMTP_CLI_FLAG_RETURN_PATH (1<<2) /* prepend Return-Path: */ +#define SMTP_CLI_FLAG_FINAL_DELIVERY (1<<3) /* final, not relay */ + +#define SMTP_CLI_MASK_ADD_HEADERS (SMTP_CLI_FLAG_DELIVERED_TO | \ + SMTP_CLI_FLAG_ORIG_RCPT | SMTP_CLI_FLAG_RETURN_PATH) + +extern SMTP_CLI_ATTR smtp_cli_attr; + + /* + * smtp_misc.c. + */ +extern void smtp_rewrite_generic_internal(VSTRING *, const char *); +extern void smtp_quote_822_address_flags(VSTRING *, const char *, int); +extern void smtp_quote_821_address(VSTRING *, const char *); + /* LICENSE /* .ad /* .fi @@ -683,6 +737,11 @@ extern int smtp_mode; /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* TLS support originally by: /* Lutz Jaenicke /* BTU Cottbus diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_addr.c b/external/ibm-public/postfix/dist/src/smtp/smtp_addr.c index c9477811e30..6518608186d 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_addr.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_addr.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_addr.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -63,6 +63,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -356,6 +361,122 @@ static DNS_RR *smtp_truncate_self(DNS_RR *addr_list, unsigned pref) return (addr_list); } +/* smtp_balance_inet_proto - balance IPv4/6 protocols within address limit */ + +static DNS_RR *smtp_balance_inet_proto(DNS_RR *addr_list, int misc_flags, + int addr_limit) +{ + const char myname[] = "smtp_balance_inet_proto"; + DNS_RR *rr; + DNS_RR *stripped_list; + DNS_RR *next; + int v6_count; + int v4_count; + int v6_target, + v4_target; + int *p; + + /* + * Precondition: the input is sorted by MX preference (not necessarily IP + * address family preference), and addresses with the same or worse + * preference than 'myself' have been eliminated. Postcondition: the + * relative list order is unchanged, but some elements are removed. + */ + + /* + * Count the number of IPv6 and IPv4 addresses. + */ + for (v4_count = v6_count = 0, rr = addr_list; rr != 0; rr = rr->next) { + if (rr->type == T_A) { + v4_count++; + } else if (rr->type == T_AAAA) { + v6_count++; + } else { + msg_panic("%s: unexpected record type: %s", + myname, dns_strtype(rr->type)); + } + } + + /* + * Ensure that one address type will not out-crowd the other, while + * enforcing the address count limit. This works around a current problem + * where some destination announces primarily IPv6 MX addresses, the + * smtp_address_limit eliminates most or all IPv4 addresses, and the + * destination is not reachable over IPv6. + * + * Maybe: do all smtp_mx_address_limit enforcement here, and remove + * pre-existing enforcement elsewhere. That would obsolete the + * smtp_balance_inet_protocols configuration parameter. + */ + if (v4_count > 0 && v6_count > 0 && v4_count + v6_count > addr_limit) { + + /*- + * Decide how many IPv6 and IPv4 addresses to keep. The code below + * has three branches, corresponding to the regions R1, R2 and R3 + * in the figure. + * + * L = addr_limit + * X = excluded by condition (v4_count + v6_count > addr_limit) + * + * v4_count + * ^ + * | + * L \ R1 + * |X\ | + * |XXX\ | + * |XXXXX\ | R2 + * L/2 +-------\------- + * |XXXXXXX|X\ + * |XXXXXXX|XXX\ R3 + * |XXXXXXX|XXXXX\ + * 0 +-------+-------\--> v6_count + * 0 L/2 L + */ + if (v6_count <= addr_limit / 2) { /* Region R1 */ + v6_target = v6_count; + v4_target = addr_limit - v6_target; + } else if (v4_count <= addr_limit / 2) {/* Region R3 */ + v4_target = v4_count; + v6_target = addr_limit - v4_target; + } else { /* Region R2 */ + /* v4_count > addr_limit / 2 && v6_count > addr_limit / 2 */ + v4_target = (addr_limit + (addr_list->type == T_A)) / 2; + v6_target = addr_limit - v4_target; + } + if (msg_verbose) + msg_info("v6_target=%d, v4_target=%d", v6_target, v4_target); + + /* Enforce the address count targets. */ + stripped_list = 0; + for (rr = addr_list; rr != 0; rr = next) { + next = rr->next; + rr->next = 0; + if (rr->type == T_A) { + p = &v4_target; + } else if (rr->type == T_AAAA) { + p = &v6_target; + } else { + msg_panic("%s: unexpected record type: %s", + myname, dns_strtype(rr->type)); + } + if (*p > 0) { + stripped_list = dns_rr_append(stripped_list, rr); + *p -= 1; + } else { + dns_rr_free(rr); + } + } + if (v4_target > 0 || v6_target > 0) + msg_panic("%s: bad target count: v4_target=%d, v6_target=%d", + myname, v4_target, v6_target); + if (msg_verbose) + smtp_print_addr("smtp_balance_inet_proto result", stripped_list); + return (stripped_list); + } else { + return (addr_list); + } +} + /* smtp_domain_addr - mail exchanger address lookup */ DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags, @@ -500,9 +621,13 @@ DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags, ((flags) & SMTP_MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \ dns_rr_compare_pref_any) - if (addr_list && addr_list->next && var_smtp_rand_addr) { - addr_list = dns_rr_shuffle(addr_list); + if (addr_list && addr_list->next) { + if (var_smtp_rand_addr) + addr_list = dns_rr_shuffle(addr_list); addr_list = dns_rr_sort(addr_list, SMTP_COMPARE_ADDR(misc_flags)); + if (var_smtp_mxaddr_limit > 0 && var_smtp_balance_inet_proto) + addr_list = smtp_balance_inet_proto(addr_list, misc_flags, + var_smtp_mxaddr_limit); } break; case DNS_NOTFOUND: @@ -560,6 +685,9 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why) /* The following changes the order of equal-preference hosts. */ if (inet_proto_info()->ai_family_list[1] != 0) addr_list = dns_rr_sort(addr_list, SMTP_COMPARE_ADDR(misc_flags)); + if (var_smtp_mxaddr_limit > 0 && var_smtp_balance_inet_proto) + addr_list = smtp_balance_inet_proto(addr_list, misc_flags, + var_smtp_mxaddr_limit); } if (msg_verbose) smtp_print_addr(host, addr_list); diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_chat.c b/external/ibm-public/postfix/dist/src/smtp/smtp_chat.c index 7aff0617764..0af647f5c7d 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_chat.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_chat.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_chat.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_chat.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -104,6 +104,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -356,8 +361,13 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session) * loss of mail is not acceptable then they can turn off pipelining * for specific sites, or they can turn off pipelining globally when * they find that there are just too many broken sites. + * + * Fix 20190621: don't cache an SMTP session after an SMTP protocol + * error. The protocol may be in a bad state. Disable caching here so + * that the protocol engine will send QUIT. */ session->error_mask |= MAIL_ERROR_PROTOCOL; + DONT_CACHE_THIS_SESSION; if (session->features & SMTP_FEATURE_PIPELINING) { msg_warn("%s: non-%s response from %s: %.100s", session->state->request->queue_id, diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_connect.c b/external/ibm-public/postfix/dist/src/smtp/smtp_connect.c index 38f7191849d..bbed4383a59 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_connect.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_connect.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_connect.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_connect.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -49,6 +49,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Connection caching in cooperation with: /* Victor Duchovni /* Morgan Stanley @@ -414,13 +419,13 @@ static void smtp_cleanup_session(SMTP_STATE *state) state->session = 0; /* - * If this session was good, reset the logical next-hop state, so that we - * won't cache connections to alternate servers under the logical - * next-hop destination. Otherwise we could end up skipping over the - * available and more preferred servers. + * If this session was good, reset the scache next-hop destination, so + * that we won't cache connections to less-preferred servers under the + * same next-hop destination. Otherwise we could end up skipping over the + * available and more-preferred servers. */ - if (HAVE_NEXTHOP_STATE(state) && !throttled) - FREE_NEXTHOP_STATE(state); + if (HAVE_SCACHE_REQUEST_NEXTHOP(state) && !throttled) + CLEAR_SCACHE_REQUEST_NEXTHOP(state); /* * Clean up the lists with todo and dropped recipients. @@ -489,6 +494,8 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path) * the "unix:" prefix. */ smtp_cache_policy(state, path); + if (state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE_MASK) + SET_SCACHE_REQUEST_NEXTHOP(state, path); /* * Here we ensure that the iter->addr member refers to a copy of the @@ -564,6 +571,12 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path) msg_panic("%s: unix-domain destination not final!", myname); smtp_cleanup_session(state); } + + /* + * Cleanup. + */ + if (HAVE_SCACHE_REQUEST_NEXTHOP(state)) + CLEAR_SCACHE_REQUEST_NEXTHOP(state); } /* smtp_scrub_address_list - delete all cached addresses from list */ @@ -654,27 +667,30 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list, DSN_BUF *why = state->why; /* - * First, search the cache by request nexthop. We truncate the server - * address list when all the sessions for this destination are used up, - * to reduce the number of variables that need to be checked later. + * First, search the cache by delivery request nexthop. We truncate the + * server address list when all the sessions for this destination are + * used up, to reduce the number of variables that need to be checked + * later. * - * Note: lookup by logical destination restores the "best MX" bit. + * Note: connection reuse by delivery request nexthop restores the "best MX" + * bit. * * smtp_reuse_nexthop() clobbers the iterators's "dest" attribute. We save * and restore it here, so that subsequent connections will use the * proper nexthop information. * - * We request a dummy "TLS disabled" policy for connection-cache lookup by - * request nexthop only. If we find a saved connection, then we know that - * plaintext was permitted, because we never save a connection after - * turning on TLS. + * We don't use TLS level info for nexthop-based connection cache storage + * keys. The combination of (service, nexthop, etc.) should be stable + * over the time range of interest, and the policy is still enforced on + * an individual connection to an MX host, before that connection is + * stored under a nexthop- or host-based storage key. */ #ifdef USE_TLS smtp_tls_policy_dummy(state->tls); #endif SMTP_ITER_SAVE_DEST(state->iterator); if (*addr_list && SMTP_RCPT_LEFT(state) > 0 - && HAVE_NEXTHOP_STATE(state) + && HAVE_SCACHE_REQUEST_NEXTHOP(state) && (session = smtp_reuse_nexthop(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL)) != 0) { session_count = 1; smtp_update_addr_list(addr_list, STR(iter->addr), session_count); @@ -770,11 +786,10 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, } /* - * Future proofing: do a null destination sanity check in case we allow - * the primary destination to be a list (it could be just separators). + * Do a null destination sanity check in case the primary destination is + * a list that consists of only separators. */ - sites = argv_alloc(1); - argv_add(sites, nexthop, (char *) 0); + sites = argv_split(nexthop, CHARS_COMMA_SP); if (sites->argc == 0) msg_panic("null destination: \"%s\"", nexthop); non_fallback_sites = sites->argc; @@ -876,10 +891,10 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, domain_best_pref = addr_list->pref; /* - * When session caching is enabled, store the first good session for - * this delivery request under the next-hop destination name. All - * good sessions will be stored under their specific server IP - * address. + * When connection caching is enabled, store the first good + * connection for this delivery request under the delivery request + * next-hop name. Good connections will also be stored under their + * specific server IP address. * * XXX smtp_session_cache_destinations specifies domain names without * :port, because : is already used for maptype:mapname. Because of @@ -895,7 +910,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_FIRST_NEXTHOP)) { smtp_cache_policy(state, domain); if (state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE_MASK) - SET_NEXTHOP_STATE(state, dest); + SET_SCACHE_REQUEST_NEXTHOP(state, dest); } /* @@ -1120,8 +1135,8 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, /* * Cleanup. */ - if (HAVE_NEXTHOP_STATE(state)) - FREE_NEXTHOP_STATE(state); + if (HAVE_SCACHE_REQUEST_NEXTHOP(state)) + CLEAR_SCACHE_REQUEST_NEXTHOP(state); argv_free(sites); } @@ -1142,8 +1157,6 @@ int smtp_connect(SMTP_STATE *state) * destination to address list, and whether to stop before we reach the * end of that list. */ -#define DEF_LMTP_SERVICE var_lmtp_tcp_port -#define DEF_SMTP_SERVICE "smtp" /* * With LMTP we have direct-to-host delivery only. The destination may @@ -1155,7 +1168,7 @@ int smtp_connect(SMTP_STATE *state) } else { if (strncmp(destination, "inet:", 5) == 0) destination += 5; - smtp_connect_inet(state, destination, DEF_LMTP_SERVICE); + smtp_connect_inet(state, destination, var_smtp_tcp_port); } } @@ -1165,7 +1178,7 @@ int smtp_connect(SMTP_STATE *state) * Postfix configurations that have a host with such a name. */ else { - smtp_connect_inet(state, destination, DEF_SMTP_SERVICE); + smtp_connect_inet(state, destination, var_smtp_tcp_port); } /* diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_key.c b/external/ibm-public/postfix/dist/src/smtp/smtp_key.c index 940e08cbe1a..4d045db9093 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_key.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_key.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_key.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_key.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -53,13 +53,14 @@ /* The envelope sender address. This is a proxy for sender-dependent /* context, such as per-sender SASL authentication. /* .IP SMTP_KEY_FLAG_REQ_NEXTHOP -/* The request nexthop destination. This is a proxy for +/* The delivery request nexthop destination, including optional +/* [] and :port (the same form that users specify in a SASL +/* password or TLS policy lookup table). This is a proxy for /* destination-dependent, but host-independent context. -/* .IP SMTP_KEY_FLAG_NEXTHOP -/* The current iterator's nexthop destination (request nexthop -/* or fallback nexthop, including optional [] and :port). This -/* is the form that users specify in a SASL or TLS lookup -/* tables. +/* .IP SMTP_KEY_FLAG_CUR_NEXTHOP +/* The current iterator's nexthop destination (delivery request +/* nexthop or fallback nexthop, including optional [] and +/* :port). /* .IP SMTP_KEY_FLAG_HOSTNAME /* The current iterator's remote hostname. /* .IP SMTP_KEY_FLAG_ADDR @@ -78,6 +79,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -180,7 +186,7 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na, */ if (flags & SMTP_KEY_FLAG_REQ_NEXTHOP) smtp_key_append_str(buffer, STR(iter->request_nexthop), delim_na); - if (flags & SMTP_KEY_FLAG_NEXTHOP) + if (flags & SMTP_KEY_FLAG_CUR_NEXTHOP) smtp_key_append_str(buffer, STR(iter->dest), delim_na); /* @@ -193,7 +199,17 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na, if (flags & SMTP_KEY_FLAG_PORT) smtp_key_append_uint(buffer, ntohs(iter->port), delim_na); - /* Similarly, provide unique TLS fingerprint when applicable. */ + /* + * Requested TLS level, if applicable. TODO(tlsproxy) should the lookup + * engine also try the requested TLS level and 'stronger', in case a + * server hosts multiple domains with different TLS requirements? + */ + if (flags & SMTP_KEY_FLAG_TLS_LEVEL) +#ifdef USE_TLS + smtp_key_append_uint(buffer, state->tls->level, delim_na); +#else + smtp_key_append_na(buffer, delim_na); +#endif VSTRING_TERMINATE(buffer); diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_map11.c b/external/ibm-public/postfix/dist/src/smtp/smtp_map11.c index d31b5e10da1..62eb7d5a1f7 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_map11.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_map11.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_map11.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_map11.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -8,12 +8,12 @@ /* SYNOPSIS /* #include <smtp.h> /* -/* int smtp_map11_external(addr, maps, propagate) +/* int smtp_map11_internal(addr, maps, propagate) /* VSTRING *addr; /* MAPS *maps; /* int propagate; /* -/* int smtp_map11_internal(addr, maps, propagate) +/* int smtp_map11_external(addr, maps, propagate) /* VSTRING *addr; /* MAPS *maps; /* int propagate; @@ -27,16 +27,17 @@ /* An unmatched address extension is propagated when /* \fIpropagate\fR is non-zero. /* -/* smtp_map11_external() looks up the RFC 822 external (quoted) string -/* form of an address in the maps specified via the \fImaps\fR argument. +/* smtp_map11_internal() looks up the RFC 822 internal (unquoted) +/* string form of an address in the maps specified via the +/* \fImaps\fR argument. /* -/* smtp_map11_internal() is a wrapper around the -/* smtp_map11_external() routine that transforms from -/* internal (quoted) string form to external form and back. +/* smtp_map11_external() is a wrapper around the smtp_map11_internal() +/* routine that transforms from external (quoted) string form +/* to internal form and back. /* -/* smtp_map11_tree() is a wrapper around the -/* smtp_map11_external() routine that transforms from -/* internal parse tree form to external form and back. +/* smtp_map11_tree() is a wrapper around the smtp_map11_internal() +/* routine that transforms from internal parse tree form to +/* internal form and back. /* DIAGNOSTICS /* Table lookup errors are fatal. /* SEE ALSO @@ -50,6 +51,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -74,15 +80,15 @@ #include <smtp.h> -/* smtp_map11_external - one-to-one table lookups */ +/* smtp_map11_internal - one-to-one table lookups */ -int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate) +int smtp_map11_internal(VSTRING *addr, MAPS *maps, int propagate) { - const char *myname = "smtp_map11_external"; + const char *myname = "smtp_map11_internal"; ARGV *new_addr; const char *result; - if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) { + if ((new_addr = mail_addr_map_internal(maps, STR(addr), propagate)) != 0) { if (new_addr->argc > 1) msg_warn("multi-valued %s result for %s", maps->title, STR(addr)); result = new_addr->argv[0]; @@ -104,63 +110,218 @@ int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate) int smtp_map11_tree(TOK822 *tree, MAPS *maps, int propagate) { - VSTRING *temp = vstring_alloc(100); + VSTRING *int_buf = vstring_alloc(100); + VSTRING *ext_buf = vstring_alloc(100); int ret; - tok822_externalize(temp, tree->head, TOK822_STR_DEFL); - ret = smtp_map11_external(temp, maps, propagate); + tok822_internalize(int_buf, tree->head, TOK822_STR_DEFL); + ret = smtp_map11_internal(int_buf, maps, propagate); tok822_free_tree(tree->head); - tree->head = tok822_scan(STR(temp), &tree->tail); - vstring_free(temp); + quote_822_local(ext_buf, STR(int_buf)); + tree->head = tok822_scan(STR(ext_buf), &tree->tail); + vstring_free(int_buf); + vstring_free(ext_buf); return (ret); } -/* smtp_map11_internal - rewrite address internal form */ +/* smtp_map11_external - rewrite address external form */ -int smtp_map11_internal(VSTRING *addr, MAPS *maps, int propagate) +int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate) { VSTRING *temp = vstring_alloc(100); int ret; - quote_822_local(temp, STR(addr)); - ret = smtp_map11_external(temp, maps, propagate); - unquote_822_local(addr, STR(temp)); + unquote_822_local(temp, STR(addr)); + ret = smtp_map11_internal(temp, maps, propagate); + quote_822_local(addr, STR(temp)); vstring_free(temp); return (ret); } #ifdef TEST +#include <ctype.h> #include <msg_vstream.h> +#include <readlline.h> #include <stringops.h> +#include <vstring_vstream.h> + +#include <canon_addr.h> #include <mail_params.h> +/* canon_addr_external - surrogate to avoid trivial-rewrite dependency */ + +VSTRING *canon_addr_external(VSTRING *result, const char *addr) +{ + char *at; + + vstring_strcpy(result, addr); + if ((at = strrchr(addr, '@')) == 0 + || (at + 1)[strcspn(at + 1, "\"\\")] != 0) + vstring_sprintf_append(result, "@%s", var_myorigin); + return (result); +} + +static NORETURN usage(const char *progname) +{ + msg_fatal("usage: %s [-v]", progname); +} + int main(int argc, char **argv) { - VSTRING *buf = vstring_alloc(100); - MAPS *maps; + VSTRING *read_buf = vstring_alloc(100); + MAPS *maps = 0; + int lineno; + int first_line; + char *bp; + char *cmd; + VSTRING *addr_buf = vstring_alloc(100); + char *addr_field; + char *res_field; + int ch; + int errs = 0; + /* + * Initialize. + */ msg_vstream_init(basename(argv[0]), VSTREAM_ERR); - if (argc < 3) - msg_fatal("usage: %s maptype:mapname address...", argv[0]); + + /* + * Parse JCL. + */ + while ((ch = GETOPT(argc, argv, "v")) > 0) { + switch (ch) { + case 'v': + msg_verbose++; + break; + default: + usage(argv[0]); + } + } + if (argc != optind) + usage(argv[0]); util_utf8_enable = 1; - maps = maps_create(argv[1], argv[1], DICT_FLAG_FOLD_FIX - | DICT_FLAG_UTF8_REQUEST); mail_params_init(); - if (chdir(var_queue_dir) < 0) - msg_fatal("chdir(%s): %m", var_queue_dir); - argv += 1; - - msg_verbose = 1; - while (--argc && *++argv) { - msg_info("-- start %s --", *argv); - smtp_map11_external(vstring_strcpy(buf, *argv), maps, 1); - msg_info("-- end %s --", *argv); + + /* + * TODO: Data-driven parameter settings. + */ +#define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0) + + UPDATE(var_myhostname, "localhost.localdomain"); + UPDATE(var_mydomain, "localdomain"); + UPDATE(var_myorigin, "localdomain"); + UPDATE(var_mydest, "localhost.localdomain"); + UPDATE(var_rcpt_delim, "+"); + + /* + * The read-eval-print loop. + */ + while (readllines(read_buf, VSTREAM_IN, &lineno, &first_line)) { + bp = STR(read_buf); + if (msg_verbose) + msg_info("> %s", bp); + if ((cmd = mystrtok(&bp, CHARS_SPACE)) == 0 || *cmd == '#') + continue; + while (ISSPACE(*bp)) + bp++; + if (*bp == 0) + msg_fatal("missing parameter for command %s", cmd); + + /* + * Open maps. + */ + if (strcmp(cmd, "maps") == 0) { + if (maps) + maps_free(maps); + maps = maps_create(bp, bp, DICT_FLAG_FOLD_FIX + | DICT_FLAG_UTF8_REQUEST); + vstream_printf("%s\n", bp); + continue; + } + + /* + * Lookup and verify. + */ + else if (maps != 0 && (strcmp(cmd, "external") == 0 + || strcmp(cmd, "internal") == 0 + || strcmp(cmd, "tree") == 0)) { + int have_result = 0; + + + /* + * Parse the input and expectations. + */ + if ((addr_field = mystrtok(&bp, ":")) == 0) + msg_fatal("missing address field"); + res_field = mystrtok(&bp, ":"); + if (mystrtok(&bp, ":") != 0) + msg_fatal("garbage after result field"); + + /* + * Perform the mapping. + */ + if (strcmp(cmd, "external") == 0) { + vstring_strcpy(addr_buf, addr_field); + have_result = smtp_map11_external(addr_buf, maps, 1); + } else if (maps && strcmp(cmd, "internal") == 0) { + vstring_strcpy(addr_buf, addr_field); + have_result = smtp_map11_internal(addr_buf, maps, 1); + } else if (maps && strcmp(cmd, "tree") == 0) { + TOK822 *tree; + TOK822 **addr_list; + TOK822 **tpp; + + tree = tok822_parse(addr_field); + addr_list = tok822_grep(tree, TOK822_ADDR); + for (tpp = addr_list; *tpp; tpp++) + have_result |= smtp_map11_tree(tpp[0], maps, 1); + myfree((void *) addr_list); + if (have_result) + tok822_externalize(addr_buf, tree, TOK822_STR_DEFL); + tok822_free_tree(tree); + } + + /* + * Summarize. + */ + vstream_printf("%s:%s -> %s\n", + cmd, addr_field, have_result ? + STR(addr_buf) : maps->error ? + "(error)" : "(no match)"); + vstream_fflush(VSTREAM_OUT); + + /* + * Enforce expectations. + */ + if (res_field && have_result) { + if (strcmp(res_field, STR(addr_buf)) != 0) { + msg_warn("expect result '%s' but got '%s'", + res_field, STR(addr_buf)); + errs = 1; + } + } else if (res_field && !have_result) { + msg_warn("expect result '%s' but got none", res_field); + errs = 1; + } else if (!res_field && have_result) { + msg_warn("expected no result but got '%s'", STR(addr_buf)); + errs = 1; + } + vstream_fflush(VSTREAM_OUT); + } + + /* + * Unknown request. + */ + else { + msg_fatal("bad request: %s", cmd); + } } - vstring_free(buf); + vstring_free(addr_buf); + vstring_free(read_buf); maps_free(maps); - return (0); + return (errs != 0); } #endif diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_misc.c b/external/ibm-public/postfix/dist/src/smtp/smtp_misc.c index 9b8a8e2db6d..fcf3528cfc1 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_misc.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_misc.c,v 1.1.1.1 2020/03/18 18:59:36 christos Exp $ */ +/* $NetBSD: smtp_misc.c,v 1.2 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_params.c b/external/ibm-public/postfix/dist/src/smtp/smtp_params.c index 01f15a26d9b..881390d68c8 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_params.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_params.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_params.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_params.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ static const CONFIG_STR_TABLE smtp_str_table[] = { VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, @@ -11,6 +11,7 @@ #ifdef USE_TLS VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0, VAR_SMTP_SASL_TLSV_OPTS, DEF_SMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tlsv_opts, 0, 0, + VAR_SMTP_TLS_CHAIN_FILES, DEF_SMTP_TLS_CHAIN_FILES, &var_smtp_tls_chain_files, 0, 0, VAR_SMTP_TLS_CERT_FILE, DEF_SMTP_TLS_CERT_FILE, &var_smtp_tls_cert_file, 0, 0, VAR_SMTP_TLS_KEY_FILE, DEF_SMTP_TLS_KEY_FILE, &var_smtp_tls_key_file, 0, 0, VAR_SMTP_TLS_DCERT_FILE, DEF_SMTP_TLS_DCERT_FILE, &var_smtp_tls_dcert_file, 0, 0, @@ -31,6 +32,7 @@ VAR_SMTP_TLS_ECCERT_FILE, DEF_SMTP_TLS_ECCERT_FILE, &var_smtp_tls_eccert_file, 0, 0, VAR_SMTP_TLS_ECKEY_FILE, DEF_SMTP_TLS_ECKEY_FILE, &var_smtp_tls_eckey_file, 0, 0, VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0, + VAR_SMTP_TLS_SNI, DEF_SMTP_TLS_SNI, &var_smtp_tls_sni, 0, 0, VAR_SMTP_TLS_INSECURE_MX_POLICY, DEF_SMTP_TLS_INSECURE_MX_POLICY, &var_smtp_tls_insecure_mx_policy, 0, 0, #endif VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0, @@ -50,7 +52,7 @@ VAR_SMTP_TLS_POLICY, DEF_SMTP_TLS_POLICY, &var_smtp_tls_policy, 0, 0, VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0, VAR_SMTP_GENERIC_MAPS, DEF_SMTP_GENERIC_MAPS, &var_smtp_generic_maps, 0, 0, - VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_lmtp_tcp_port, 0, 0, + VAR_SMTP_TCP_PORT, DEF_SMTP_TCP_PORT, &var_smtp_tcp_port, 0, 0, VAR_SMTP_PIX_BUG_WORDS, DEF_SMTP_PIX_BUG_WORDS, &var_smtp_pix_bug_words, 0, 0, VAR_SMTP_PIX_BUG_MAPS, DEF_SMTP_PIX_BUG_MAPS, &var_smtp_pix_bug_maps, 0, 0, VAR_SMTP_SASL_AUTH_CACHE_NAME, DEF_SMTP_SASL_AUTH_CACHE_NAME, &var_smtp_sasl_auth_cache_name, 0, 0, @@ -64,6 +66,7 @@ VAR_SMTP_DNS_RES_OPT, DEF_SMTP_DNS_RES_OPT, &var_smtp_dns_res_opt, 0, 0, VAR_SMTP_DSN_FILTER, DEF_SMTP_DSN_FILTER, &var_smtp_dsn_filter, 0, 0, VAR_SMTP_DNS_RE_FILTER, DEF_SMTP_DNS_RE_FILTER, &var_smtp_dns_re_filter, 0, 0, + VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0, 0, }; static const CONFIG_TIME_TABLE smtp_time_table[] = { @@ -114,6 +117,7 @@ VAR_SMTP_CACHE_DEMAND, DEF_SMTP_CACHE_DEMAND, &var_smtp_cache_demand, VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls, VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_tls, + VAR_SMTP_TLS_CONN_REUSE, DEF_SMTP_TLS_CONN_REUSE, &var_smtp_tls_conn_reuse, #ifdef USE_TLS VAR_SMTP_TLS_ENFORCE_PN, DEF_SMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername, VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer, @@ -127,5 +131,6 @@ VAR_LMTP_ASSUME_FINAL, DEF_LMTP_ASSUME_FINAL, &var_lmtp_assume_final, VAR_SMTP_REC_DEADLINE, DEF_SMTP_REC_DEADLINE, &var_smtp_rec_deadline, VAR_SMTP_DUMMY_MAIL_AUTH, DEF_SMTP_DUMMY_MAIL_AUTH, &var_smtp_dummy_mail_auth, + VAR_SMTP_BALANCE_INET_PROTO, DEF_SMTP_BALANCE_INET_PROTO, &var_smtp_balance_inet_proto, 0, }; diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_proto.c b/external/ibm-public/postfix/dist/src/smtp/smtp_proto.c index 7428659b187..966000bc3e6 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_proto.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_proto.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_proto.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_proto.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -75,6 +75,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Pipelining code in cooperation with: /* Jon Ribbens /* Oaktree Internet Solutions Ltd., @@ -137,7 +142,6 @@ #include <rec_type.h> #include <off_cvt.h> #include <mark_corrupt.h> -#include <quote_821_local.h> #include <quote_822_local.h> #include <mail_proto.h> #include <mime_state.h> @@ -334,6 +338,8 @@ int smtp_helo(SMTP_STATE *state) && (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0) { /* XXX Mix-up of per-session and per-request flags. */ state->misc_flags |= SMTP_MISC_FLAG_IN_STARTTLS; + smtp_stream_setup(state->session->stream, var_smtp_starttls_tmout, + var_smtp_rec_deadline); tls_helo_status = smtp_start_tls(state); state->misc_flags &= ~SMTP_MISC_FLAG_IN_STARTTLS; return (tls_helo_status); @@ -405,6 +411,10 @@ int smtp_helo(SMTP_STATE *state) pix_bug_mask = name_mask_opt(pix_bug_source, pix_bug_table, pix_bug_words, NAME_MASK_ANY_CASE | NAME_MASK_IGNORE); + if ((pix_bug_mask & SMTP_FEATURE_PIX_DELAY_DOTCRLF) + && request->msg_stats.incoming_arrival.tv_sec + > vstream_ftime(state->session->stream) - var_smtp_pix_thresh) + pix_bug_mask &= ~SMTP_FEATURE_PIX_DELAY_DOTCRLF; msg_info("%s: enabling PIX workarounds: %s for %s", request->queue_id, str_name_mask("pix workaround bitmask", @@ -841,20 +851,29 @@ static int smtp_start_tls(SMTP_STATE *state) { SMTP_SESSION *session = state->session; SMTP_ITERATOR *iter = state->iterator; - TLS_CLIENT_START_PROPS tls_props; + TLS_CLIENT_START_PROPS start_props; VSTRING *serverid; SMTP_RESP fake; + TLS_CLIENT_INIT_PROPS init_props; + VSTREAM *tlsproxy; + VSTRING *port_buf; /* - * Turn off SMTP connection caching. When the TLS handshake succeeds, we - * can't reuse the SMTP connection. Reason: we can't turn off TLS in one - * process, save the connection to the cache which is shared with all - * SMTP clients, migrate the connection to another SMTP client, and - * resume TLS there. When the TLS handshake fails, we can't reuse the - * SMTP connection either, because the conversation is in an unknown - * state. + * When the TLS handshake succeeds, we can reuse a connection only if TLS + * remains turned on for the lifetime of that connection. This requires + * that the TLS library state is maintained in some proxy process, for + * example, in tlsproxy(8). We then store the proxy file handle in the + * connection cache, and reuse that file handle. + * + * Otherwise, we must turn off connection caching. We can't turn off TLS in + * one SMTP client process, save the open connection to a cache which is + * shared with all SMTP clients, migrate the connection to another SMTP + * client, and resume TLS there. When the TLS handshake fails, we can't + * reuse the SMTP connection either, because the conversation is in an + * unknown state. */ - DONT_CACHE_THIS_SESSION; + if (state->tls->conn_reuse == 0) + DONT_CACHE_THIS_SESSION; /* * The following assumes sites that use TLS in a perverse configuration: @@ -883,41 +902,178 @@ static int smtp_start_tls(SMTP_STATE *state) */ serverid = vstring_alloc(10); smtp_key_prefix(serverid, "&", state->iterator, SMTP_KEY_FLAG_SERVICE - | SMTP_KEY_FLAG_NEXTHOP /* With port */ + | SMTP_KEY_FLAG_CUR_NEXTHOP /* With port */ | SMTP_KEY_FLAG_HOSTNAME | SMTP_KEY_FLAG_ADDR); - /* - * As of Postfix 2.5, tls_client_start() tries hard to always complete - * the TLS handshake. It records the verification and match status in the - * resulting TLScontext. It is now up to the application to abort the TLS - * connection if it chooses. - * - * XXX When tls_client_start() fails then we don't know what state the SMTP - * connection is in, so we give up on this connection even if we are not - * required to use TLS. - * - * Large parameter lists are error-prone, so we emulate a language feature - * that C does not have natively: named parameter lists. - */ - session->tls_context = - TLS_CLIENT_START(&tls_props, - ctx = smtp_tls_ctx, - stream = session->stream, - timeout = var_smtp_starttls_tmout, - tls_level = state->tls->level, - nexthop = session->tls_nexthop, - host = STR(iter->host), - namaddr = session->namaddrport, - serverid = vstring_str(serverid), - helo = session->helo, - protocols = state->tls->protocols, - cipher_grade = state->tls->grade, - cipher_exclusions - = vstring_str(state->tls->exclusions), - matchargv = state->tls->matchargv, - mdalg = var_smtp_tls_fpt_dgst, - dane = state->tls->dane); + if (state->tls->conn_reuse) { + TLS_CLIENT_PARAMS tls_params; + + /* + * Send all our wishes in one big request. + */ + TLS_PROXY_CLIENT_INIT_PROPS(&init_props, + log_param = VAR_LMTP_SMTP(TLS_LOGLEVEL), + log_level = var_smtp_tls_loglevel, + verifydepth = var_smtp_tls_scert_vd, + cache_type + = LMTP_SMTP_SUFFIX(TLS_MGR_SCACHE), + chain_files = var_smtp_tls_chain_files, + cert_file = var_smtp_tls_cert_file, + key_file = var_smtp_tls_key_file, + dcert_file = var_smtp_tls_dcert_file, + dkey_file = var_smtp_tls_dkey_file, + eccert_file = var_smtp_tls_eccert_file, + eckey_file = var_smtp_tls_eckey_file, + CAfile = var_smtp_tls_CAfile, + CApath = var_smtp_tls_CApath, + mdalg = var_smtp_tls_fpt_dgst); + TLS_PROXY_CLIENT_START_PROPS(&start_props, + timeout = var_smtp_starttls_tmout, + tls_level = state->tls->level, + nexthop = session->tls_nexthop, + host = STR(iter->host), + namaddr = session->namaddrport, + sni = state->tls->sni, + serverid = vstring_str(serverid), + helo = session->helo, + protocols = state->tls->protocols, + cipher_grade = state->tls->grade, + cipher_exclusions + = vstring_str(state->tls->exclusions), + matchargv = state->tls->matchargv, + mdalg = var_smtp_tls_fpt_dgst, + dane = state->tls->dane); + + /* + * The tlsproxy(8) server enforces timeouts that are larger than + * those specified by the tlsproxy(8) client. These timeouts are a + * safety net for the case that the tlsproxy(8) client fails to + * enforce time limits. Normally, the tlsproxy(8) client would time + * out and trigger a plaintext event in the tlsproxy(8) server, and + * cause it to tear down the session. + * + * However, the tlsproxy(8) server has no insight into the SMTP + * protocol, and therefore it cannot by itself support different + * timeouts at different SMTP protocol stages. Instead, we specify + * the largest timeout (end-of-data) and rely on the SMTP client to + * time out first, which normally results in a plaintext event in the + * tlsproxy(8) server. Unfortunately, we cannot permit plaintext + * events during the TLS handshake, so we specify a separate timeout + * for that stage (the end-of-data timeout would be unreasonably + * large anyway). + */ +#define PROXY_OPEN_FLAGS \ + (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT) + + port_buf = vstring_alloc(100); /* minimize fragmentation */ + vstring_sprintf(port_buf, "%d", ntohs(iter->port)); + tlsproxy = + tls_proxy_open(var_tlsproxy_service, PROXY_OPEN_FLAGS, + session->stream, STR(iter->addr), + STR(port_buf), var_smtp_starttls_tmout, + var_smtp_data2_tmout, state->service, + tls_proxy_client_param_from_config(&tls_params), + &init_props, &start_props); + vstring_free(port_buf); + + /* + * To insert tlsproxy(8) between this process and the remote SMTP + * server, we swap the file descriptors between the tlsproxy and + * session->stream VSTREAMS, so that we don't lose all the + * user-configurable session->stream attributes (such as longjump + * buffers or timeouts). + * + * TODO: the tlsproxy RPCs should return more error detail than a "NO" + * result. OTOH, the in-process TLS engine does not return such info + * either. + * + * If the tlsproxy request fails we do not fall back to the in-process + * TLS stack. Reason: the admin enabled connection reuse to respect + * receiver policy; silently violating such policy would not be + * useful. + * + * We also don't fall back to the in-process TLS stack under low-traffic + * conditions, to avoid frustrating attempts to debug a problem with + * using the tlsproxy(8) service. + */ + if (tlsproxy == 0) { + session->tls_context = 0; + } else { + vstream_control(tlsproxy, + CA_VSTREAM_CTL_DOUBLE, + CA_VSTREAM_CTL_END); + vstream_control(session->stream, + CA_VSTREAM_CTL_SWAP_FD(tlsproxy), + CA_VSTREAM_CTL_END); + (void) vstream_fclose(tlsproxy); /* direct-to-server stream! */ + + /* + * There must not be any pending data in the stream buffers + * before we read the TLS context attributes. + */ + vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH); + + /* + * After plumbing the plaintext stream, receive the TLS context + * object. For this we use the same VSTREAM buffer that we also + * use to receive subsequent SMTP commands, therefore we must be + * prepared for the possibility that the remote SMTP server + * starts talking immediately. The tlsproxy implementation sends + * the TLS context before remote content. The attribute protocol + * is robust enough that an adversary cannot insert their own TLS + * context attributes. + */ + session->tls_context = tls_proxy_context_receive(session->stream); + if (session->tls_context) { + session->features |= SMTP_FEATURE_FROM_PROXY; + tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW, + session->tls_context); + } + } + } else { /* state->tls->conn_reuse */ + + /* + * As of Postfix 2.5, tls_client_start() tries hard to always + * complete the TLS handshake. It records the verification and match + * status in the resulting TLScontext. It is now up to the + * application to abort the TLS connection if it chooses. + * + * XXX When tls_client_start() fails then we don't know what state the + * SMTP connection is in, so we give up on this connection even if we + * are not required to use TLS. + * + * Large parameter lists are error-prone, so we emulate a language + * feature that C does not have natively: named parameter lists. + */ + session->tls_context = + TLS_CLIENT_START(&start_props, + ctx = smtp_tls_ctx, + stream = session->stream, + fd = -1, + timeout = var_smtp_starttls_tmout, + tls_level = state->tls->level, + nexthop = session->tls_nexthop, + host = STR(iter->host), + namaddr = session->namaddrport, + sni = state->tls->sni, + serverid = vstring_str(serverid), + helo = session->helo, + protocols = state->tls->protocols, + cipher_grade = state->tls->grade, + cipher_exclusions + = vstring_str(state->tls->exclusions), + matchargv = state->tls->matchargv, + mdalg = var_smtp_tls_fpt_dgst, + dane = state->tls->dane); + + /* + * At this point there must not be any pending data in the stream + * buffers. + */ + vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH); + } /* state->tls->conn_reuse */ + vstring_free(serverid); if (session->tls_context == 0) { @@ -925,7 +1081,6 @@ static int smtp_start_tls(SMTP_STATE *state) /* * We must avoid further I/O, the peer is in an undefined state. */ - (void) vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH); DONT_USE_FORBIDDEN_SESSION; /* @@ -976,9 +1131,6 @@ static int smtp_start_tls(SMTP_STATE *state) SMTP_RESP_FAKE(&fake, "4.7.5"), "Server certificate not verified")); - /* At this point there must not be any pending plaintext. */ - vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH); - /* * At this point we have to re-negotiate the "EHLO" to reget the * feature-list. @@ -1237,6 +1389,64 @@ static void smtp_mime_fail(SMTP_STATE *state, int mime_errs) "%s", detail->text); } +/* smtp_out_raw_or_mime - output buffer, raw output or MIME-aware */ + +static int smtp_out_raw_or_mime(SMTP_STATE *state, VSTRING *buf) +{ + SMTP_SESSION *session = state->session; + int mime_errs; + + if (session->mime_state == 0) { + smtp_text_out((void *) state, REC_TYPE_NORM, vstring_str(buf), + VSTRING_LEN(buf), (off_t) 0); + } else { + mime_errs = + mime_state_update(session->mime_state, REC_TYPE_NORM, + vstring_str(buf), VSTRING_LEN(buf)); + if (mime_errs) { + smtp_mime_fail(state, mime_errs); + return (-1); + } + } + return (0); +} + +/* smtp_out_add_header - format address header, uses session->scratch* */ + +static int smtp_out_add_header(SMTP_STATE *state, const char *label, + const char *lt, const char *addr, + const char *gt) +{ + SMTP_SESSION *session = state->session; + + smtp_rewrite_generic_internal(session->scratch2, addr); + vstring_sprintf(session->scratch, "%s: %s", label, lt); + smtp_quote_822_address_flags(session->scratch, + vstring_str(session->scratch2), + QUOTE_FLAG_DEFAULT | QUOTE_FLAG_APPEND); + vstring_strcat(session->scratch, gt); + return (smtp_out_raw_or_mime(state, session->scratch)); +} + +/* smtp_out_add_headers - output additional headers, uses session->scratch* */ + +static int smtp_out_add_headers(SMTP_STATE *state) +{ + if (smtp_cli_attr.flags & SMTP_CLI_FLAG_DELIVERED_TO) + if (smtp_out_add_header(state, "Delivered-To", "", + state->request->rcpt_list.info->address, "") < 0) + return (-1); + if (smtp_cli_attr.flags & SMTP_CLI_FLAG_ORIG_RCPT) + if (smtp_out_add_header(state, "X-Original-To", "", + state->request->rcpt_list.info->orig_addr, "") < 0) + return (-1); + if (smtp_cli_attr.flags & SMTP_CLI_FLAG_RETURN_PATH) + if (smtp_out_add_header(state, "Return-Path", "<", + state->request->sender, ">") < 0) + return (-1); + return (0); +} + /* smtp_loop - exercise the SMTP protocol engine */ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, @@ -1265,24 +1475,6 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, SMTP_RESP fake; int fail_status; - /* - * Macros for readability. - */ -#define REWRITE_ADDRESS(dst, src) do { \ - vstring_strcpy(dst, src); \ - if (*(src) && smtp_generic_maps) \ - smtp_map11_internal(dst, smtp_generic_maps, \ - smtp_ext_prop_mask & EXT_PROP_GENERIC); \ - } while (0) - -#define QUOTE_ADDRESS(dst, src) do { \ - if (*(src) && var_smtp_quote_821_env) { \ - quote_821_local(dst, src); \ - } else { \ - vstring_strcpy(dst, src); \ - } \ - } while (0) - /* Caution: changes to RETURN() also affect code outside the main loop. */ #define RETURN(x) do { \ @@ -1457,8 +1649,9 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, case SMTP_STATE_MAIL: request->msg_stats.reuse_count = session->reuse_count; GETTIMEOFDAY(&request->msg_stats.conn_setup_done); - REWRITE_ADDRESS(session->scratch2, request->sender); - QUOTE_ADDRESS(session->scratch, vstring_str(session->scratch2)); + smtp_rewrite_generic_internal(session->scratch2, request->sender); + smtp_quote_821_address(session->scratch, + vstring_str(session->scratch2)); vstring_sprintf(next_command, "MAIL FROM:<%s>", vstring_str(session->scratch)); /* XXX Don't announce SIZE if we're going to MIME downgrade. */ @@ -1546,8 +1739,9 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, */ case SMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; - REWRITE_ADDRESS(session->scratch2, rcpt->address); - QUOTE_ADDRESS(session->scratch, vstring_str(session->scratch2)); + smtp_rewrite_generic_internal(session->scratch2, rcpt->address); + smtp_quote_821_address(session->scratch, + vstring_str(session->scratch2)); vstring_sprintf(next_command, "RCPT TO:<%s>", vstring_str(session->scratch)); if (session->features & SMTP_FEATURE_DSN) { @@ -2108,24 +2302,15 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, (void *) state); state->space_left = var_smtp_line_limit; + if ((smtp_cli_attr.flags & SMTP_CLI_MASK_ADD_HEADERS) != 0 + && smtp_out_add_headers(state) < 0) + RETURN(0); + while ((rec_type = rec_get(state->src, session->scratch, 0)) > 0) { if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT) break; - if (session->mime_state == 0) { - smtp_text_out((void *) state, rec_type, - vstring_str(session->scratch), - VSTRING_LEN(session->scratch), - (off_t) 0); - } else { - mime_errs = - mime_state_update(session->mime_state, rec_type, - vstring_str(session->scratch), - VSTRING_LEN(session->scratch)); - if (mime_errs) { - smtp_mime_fail(state, mime_errs); - RETURN(0); - } - } + if (smtp_out_raw_or_mime(state, session->scratch) < 0) + RETURN(0); prev_type = rec_type; } @@ -2149,9 +2334,7 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, } } else if (prev_type == REC_TYPE_CONT) /* missing newline */ smtp_fputs("", 0, session->stream); - if ((session->features & SMTP_FEATURE_PIX_DELAY_DOTCRLF) != 0 - && request->msg_stats.incoming_arrival.tv_sec - <= vstream_ftime(session->stream) - var_smtp_pix_thresh) { + if (session->features & SMTP_FEATURE_PIX_DELAY_DOTCRLF) { smtp_flush(session->stream);/* hurts performance */ sleep(var_smtp_pix_delay); /* not to mention this */ } diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_rcpt.c b/external/ibm-public/postfix/dist/src/smtp/smtp_rcpt.c index 8031d2d8468..f91f19c06a0 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_rcpt.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_rcpt.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_rcpt.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_rcpt.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -108,6 +108,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -162,7 +167,7 @@ void smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt) */ if ((session->features & SMTP_FEATURE_DSN) == 0 && !smtp_mode - && var_lmtp_assume_final != 0) + && (smtp_cli_attr.flags & SMTP_CLI_FLAG_FINAL_DELIVERY) != 0) dsn_action = "delivered"; /* diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_reuse.c b/external/ibm-public/postfix/dist/src/smtp/smtp_reuse.c index f4c8e03c5b1..2687b829957 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_reuse.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_reuse.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_reuse.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_reuse.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -25,25 +25,26 @@ /* This module implements the SMTP client specific interface to /* the generic session cache infrastructure. /* -/* A cached connection is closed when the TLS policy requires -/* that TLS is enabled. +/* The caller needs to include additional state in _key_flags +/* to avoid false sharing of SASL-authenticated or TLS-authenticated +/* sessions. /* /* smtp_save_session() stores the current session under the -/* next-hop logical destination (if available) and under the -/* remote server address. The SMTP_SESSION object is destroyed. +/* delivery request next-hop logical destination (if applicable) +/* and under the remote server address. The SMTP_SESSION object +/* is destroyed. /* -/* smtp_reuse_nexthop() looks up a cached session by its logical -/* destination, and verifies that the session is still alive. -/* The restored session information includes the "best MX" bit -/* and overrides the iterator dest, host and addr fields. -/* The result is null in case of failure. +/* smtp_reuse_nexthop() looks up a cached session by its +/* delivery request next-hop destination, and verifies that +/* the session is still alive. The restored session information +/* includes the "best MX" bit and overrides the iterator dest, +/* host and addr fields. The result is null in case of failure. /* /* smtp_reuse_addr() looks up a cached session by its server /* address, and verifies that the session is still alive. /* The restored session information does not include the "best /* MX" bit, and does not override the iterator dest, host and -/* addr fields. -/* The result is null in case of failure. +/* addr fields. The result is null in case of failure. /* /* Arguments: /* .IP state @@ -66,6 +67,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -111,10 +117,16 @@ void smtp_save_session(SMTP_STATE *state, int name_key_flags, int fd; /* - * Encode the next-hop logical destination, if available. Reuse storage - * that is also used for cache lookup queries. + * Encode the delivery request next-hop destination, if applicable. Reuse + * storage that is also used for cache lookup queries. + * + * HAVE_SCACHE_REQUEST_NEXTHOP() controls whether or not to reuse or cache a + * connection by its delivery request next-hop destination. The idea is + * 1) to allow a reuse request to skip over bad hosts, and 2) to avoid + * caching a less-preferred connection when a more-preferred connection + * was possible. */ - if (HAVE_NEXTHOP_STATE(state)) + if (HAVE_SCACHE_REQUEST_NEXTHOP(state)) smtp_key_prefix(state->dest_label, SMTP_REUSE_KEY_DELIM_NA, state->iterator, name_key_flags); @@ -133,16 +145,18 @@ void smtp_save_session(SMTP_STATE *state, int name_key_flags, state->session = 0; /* - * Save the session under the next-hop name, if available. + * Save the session under the delivery request next-hop name, if + * applicable. * * XXX The logical to physical binding can be kept for as long as the DNS * allows us to (but that could result in the caching of lots of unused * bindings). The session should be idle for no more than 30 seconds or * so. */ - if (HAVE_NEXTHOP_STATE(state)) - scache_save_dest(smtp_scache, var_smtp_cache_conn, STR(state->dest_label), - STR(state->dest_prop), STR(state->endp_label)); + if (HAVE_SCACHE_REQUEST_NEXTHOP(state)) + scache_save_dest(smtp_scache, var_smtp_cache_conn, + STR(state->dest_label), STR(state->dest_prop), + STR(state->endp_label)); /* * Save every good session under its physical endpoint address. @@ -161,16 +175,6 @@ static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd, SMTP_SESSION *session; /* - * Can't happen. Both smtp_reuse_nexthop() and smtp_reuse_addr() decline - * the request when the TLS policy is not TLS_LEV_NONE. - */ -#ifdef USE_TLS - if (state->tls->level > TLS_LEV_NONE) - msg_panic("%s: unexpected plain-text cached session to %s", - myname, label); -#endif - - /* * Re-activate the SMTP_SESSION object. */ session = smtp_session_activate(fd, state->iterator, state->dest_prop, @@ -213,15 +217,6 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags) int fd; /* - * Don't look up an existing plaintext connection when a new connection - * would (try to) use TLS. - */ -#ifdef USE_TLS - if (state->tls->level > TLS_LEV_NONE) - return (0); -#endif - - /* * Look up the session by its logical name. */ smtp_key_prefix(state->dest_label, SMTP_REUSE_KEY_DELIM_NA, @@ -246,13 +241,13 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags) int fd; /* - * Don't look up an existing plaintext connection when a new connection - * would (try to) use TLS. + * Address-based reuse is safe for security levels that require TLS + * certificate checks, as long as the current nexhop is included in the + * cache lookup key (COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP). This is + * sufficient to prevent the reuse of a TLS-authenticated connection to + * the same MX hostname, IP address, and port, but for a different + * current nexthop destination with a different TLS policy. */ -#ifdef USE_TLS - if (state->tls->level > TLS_LEV_NONE) - return (0); -#endif /* * Look up the session by its IP address. This means that we have no diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_auth_cache.c b/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_auth_cache.c index 69d3d5e87fc..e3f77b938bc 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_auth_cache.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_auth_cache.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_sasl_auth_cache.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_sasl_auth_cache.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -130,7 +130,7 @@ SMTP_SASL_AUTH_CACHE *smtp_sasl_auth_cache_init(const char *map, int ttl) * XXX To avoid multiple writers the map needs to be maintained by the * proxywrite service. We would like to have a DICT_FLAG_REQ_PROXY flag * so that the library can enforce this, but that requires moving the - * dict_proxy module one level down in the build dependency hierachy. + * dict_proxy module one level down in the build dependency hierarchy. */ #define CACHE_DICT_OPEN_FLAGS \ (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | DICT_FLAG_UTF8_REQUEST) diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_glue.c b/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_glue.c index 6fe42d1437f..8dceaab5682 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_glue.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_sasl_glue.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_sasl_glue.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_sasl_glue.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -91,6 +91,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -360,22 +365,36 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) session->namaddr, STR(session->sasl_reply)); return (-1); } - - /* + /*- * Send the AUTH command and the optional initial client response. - * sasl_encode64() produces four bytes for each complete or incomplete - * triple of input bytes. Allocate an extra byte for string termination. + * + * https://tools.ietf.org/html/rfc4954#page-4 + * Note that the AUTH command is still subject to the line length + * limitations defined in [SMTP]. If use of the initial response argument + * would cause the AUTH command to exceed this length, the client MUST NOT + * use the initial response parameter... + * + * https://tools.ietf.org/html/rfc5321#section-4.5.3.1.4 + * The maximum total length of a command line including the command word + * and the <CRLF> is 512 octets. + * + * Defer the initial response if the resulting command exceeds the limit. */ - if (LEN(session->sasl_reply) > 0) { + if (LEN(session->sasl_reply) > 0 + && strlen(mechanism) + LEN(session->sasl_reply) + 8 <= 512) { smtp_chat_cmd(session, "AUTH %s %s", mechanism, STR(session->sasl_reply)); + VSTRING_RESET(session->sasl_reply); /* no deferred initial reply */ } else { smtp_chat_cmd(session, "AUTH %s", mechanism); } /* * Step through the authentication protocol until the server tells us - * that we are done. + * that we are done. If session->sasl_reply is non-empty we have a + * deferred initial reply and expect an empty initial challenge from the + * server. If the server's initial challenge is non-empty we have a SASL + * protocol violation with both sides wanting to go first. */ while ((resp = smtp_chat_resp(session))->code / 100 == 3) { @@ -394,21 +413,39 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why) */ line = resp->str; (void) mystrtok(&line, "- \t\n"); /* skip over result code */ - result = xsasl_client_next(session->sasl_client, line, - session->sasl_reply); - if (result != XSASL_AUTH_OK) { - dsb_update(why, "4.7.0", DSB_DEF_ACTION, /* Fix 200512 */ + + if (LEN(session->sasl_reply) > 0) { + + /* + * Deferred initial response, the server challenge must be empty. + * Cleared after actual transmission to the server. + */ + if (*line) { + dsb_update(why, "4.7.0", DSB_DEF_ACTION, + DSB_SKIP_RMTA, DSB_DTYPE_SASL, "protocol error", + "SASL authentication failed; non-empty initial " + "%s challenge from server %s: %s", mechanism, + session->namaddr, STR(session->sasl_reply)); + return (-1); + } + } else { + result = xsasl_client_next(session->sasl_client, line, + session->sasl_reply); + if (result != XSASL_AUTH_OK) { + dsb_update(why, "4.7.0", DSB_DEF_ACTION, /* Fix 200512 */ DSB_SKIP_RMTA, DSB_DTYPE_SASL, STR(session->sasl_reply), - "SASL authentication failed; " - "cannot authenticate to server %s: %s", - session->namaddr, STR(session->sasl_reply)); - return (-1); /* Fix 200512 */ + "SASL authentication failed; " + "cannot authenticate to server %s: %s", + session->namaddr, STR(session->sasl_reply)); + return (-1); /* Fix 200512 */ + } } /* * Send a client response. */ smtp_chat_cmd(session, "%s", STR(session->sasl_reply)); + VSTRING_RESET(session->sasl_reply); /* clear initial reply */ } /* diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_session.c b/external/ibm-public/postfix/dist/src/smtp/smtp_session.c index 60264ec04da..9cd7beacf18 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_session.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_session.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_session.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_session.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -38,8 +38,9 @@ /* case of a null stream and will assume it was given a different /* purpose. /* -/* smtp_session_passivate() flattens an SMTP session so that -/* it can be cached. The SMTP_SESSION structure is destroyed. +/* smtp_session_passivate() flattens an SMTP session (including +/* TLS context) so that it can be cached. The SMTP_SESSION +/* structure is destroyed. /* /* smtp_session_activate() inflates a flattened SMTP session /* so that it can be used. The input property arguments are @@ -86,6 +87,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Viktor Dukhovni /*--*/ @@ -110,11 +116,28 @@ #include <debug_peer.h> #include <mail_params.h> +/* TLS Library. */ + +#include <tls_proxy.h> + /* Application-specific. */ #include "smtp.h" #include "smtp_sasl.h" + /* + * Local, because these are meaningful only for code in this file. + */ +#define SESS_ATTR_DEST "destination" +#define SESS_ATTR_HOST "host_name" +#define SESS_ATTR_ADDR "host_addr" +#define SESS_ATTR_DEST_FEATURES "destination_features" + +#define SESS_ATTR_TLS_LEVEL "tls_level" +#define SESS_ATTR_REUSE_COUNT "reuse_count" +#define SESS_ATTR_ENDP_FEATURES "endpoint_features" +#define SESS_ATTR_EXPIRE_TIME "expire_time" + /* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, SMTP_ITERATOR *iter, @@ -178,7 +201,12 @@ void smtp_session_free(SMTP_SESSION *session) #ifdef USE_TLS if (session->stream) { vstream_fflush(session->stream); - if (session->tls_context) + } + if (session->tls_context) { + if (session->features & + (SMTP_FEATURE_FROM_CACHE | SMTP_FEATURE_FROM_PROXY)) + tls_proxy_context_free(session->tls_context); + else tls_client_stop(smtp_tls_ctx, session->stream, var_smtp_starttls_tmout, 0, session->tls_context); } @@ -213,54 +241,72 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop, VSTRING *endp_prop) { SMTP_ITERATOR *iter = session->iterator; + VSTREAM *mp; int fd; /* - * Encode the local-to-physical binding properties: whether or not this - * server is best MX host for the next-hop or fall-back logical - * destination (this information is needed for loop handling in - * smtp_proto()). - * - * XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can - * serialize the properties with attr_print() instead of using ad-hoc, - * non-reusable, code and hard-coded format strings. + * Encode the delivery request next-hop to endpoint binding properties: + * whether or not this server is best MX host for the delivery request + * next-hop or fall-back logical destination (this information is needed + * for loop handling in smtp_proto()). * * TODO: save SASL username and password information so that we can * correctly save a reused authenticated connection. * + * These memory writes should never fail. */ - vstring_sprintf(dest_prop, "%s\n%s\n%s\n%u", - STR(iter->dest), STR(iter->host), STR(iter->addr), - session->features & SMTP_FEATURE_DESTINATION_MASK); + if ((mp = vstream_memopen(dest_prop, O_WRONLY)) == 0 + || attr_print_plain(mp, ATTR_FLAG_NONE, + SEND_ATTR_STR(SESS_ATTR_DEST, STR(iter->dest)), + SEND_ATTR_STR(SESS_ATTR_HOST, STR(iter->host)), + SEND_ATTR_STR(SESS_ATTR_ADDR, STR(iter->addr)), + SEND_ATTR_INT(SESS_ATTR_DEST_FEATURES, + session->features & SMTP_FEATURE_DESTINATION_MASK), + ATTR_TYPE_END) != 0 + || vstream_fclose(mp) != 0) + msg_fatal("smtp_session_passivate: can't save dest properties: %m"); /* * Encode the physical endpoint properties: all the session properties - * except for "session from cache", "best MX", or "RSET failure". + * except for "session from cache", "best MX", or "RSET failure". Plus + * the TLS level, reuse count, and connection expiration time. * - * XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can - * serialize the properties with attr_print() instead of using obscure - * hard-coded format strings. + * XXX Should also record how many non-delivering mail transactions there + * were during this session, and perhaps other statistics, so that we + * don't reuse a session too much. * - * XXX Should also record an absolute time when a session must be closed, - * how many non-delivering mail transactions there were during this - * session, and perhaps other statistics, so that we don't reuse a - * session too much. + * TODO: passivate SASL username and password information so that we can + * correctly save a reused authenticated connection. * - * XXX Be sure to use unsigned types in the format string. Sign characters - * would be rejected by the alldig() test on the reading end. + * These memory writes should never fail. */ - vstring_sprintf(endp_prop, "%u\n%u\n%lu", - session->reuse_count, - session->features & SMTP_FEATURE_ENDPOINT_MASK, - (long) session->expire_time); + if ((mp = vstream_memopen(endp_prop, O_WRONLY)) == 0 + || attr_print_plain(mp, ATTR_FLAG_NONE, +#ifdef USE_TLS + SEND_ATTR_INT(SESS_ATTR_TLS_LEVEL, + session->state->tls->level), +#endif + SEND_ATTR_INT(SESS_ATTR_REUSE_COUNT, + session->reuse_count), + SEND_ATTR_INT(SESS_ATTR_ENDP_FEATURES, + session->features & SMTP_FEATURE_ENDPOINT_MASK), + SEND_ATTR_LONG(SESS_ATTR_EXPIRE_TIME, + (long) session->expire_time), + ATTR_TYPE_END) != 0 /* - * Append the passivated SASL attributes. + * Append the passivated TLS context. These memory writes should never + * fail. */ -#ifdef notdef - if (smtp_sasl_enable) - smtp_sasl_passivate(endp_prop, session); +#ifdef USE_TLS + || (session->tls_context + && attr_print_plain(mp, ATTR_FLAG_NONE, + SEND_ATTR_FUNC(tls_proxy_context_print, + (void *) session->tls_context), + ATTR_TYPE_END) != 0) #endif + || vstream_fclose(mp) != 0) + msg_fatal("smtp_session_passivate: cannot save TLS context: %m"); /* * Salvage the underlying file descriptor, and destroy the session @@ -281,52 +327,66 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter, VSTRING *endp_prop) { const char *myname = "smtp_session_activate"; + VSTREAM *mp; SMTP_SESSION *session; - char *dest_props; - char *endp_props; - const char *prop; - const char *dest; - const char *host; - const char *addr; - unsigned features; /* server features */ - time_t expire_time; /* session re-use expiration time */ - unsigned reuse_count; /* # times reused */ + int endp_features; /* server features */ + int dest_features; /* server features */ + long expire_time; /* session re-use expiration time */ + int reuse_count; /* # times reused */ + +#ifdef USE_TLS + TLS_SESS_STATE *tls_context = 0; + SMTP_TLS_POLICY *tls = iter->parent->tls; + +#define TLS_PROXY_CONTEXT_FREE() do { \ + if (tls_context) \ + tls_proxy_context_free(tls_context); \ + } while (0) +#else +#define TLS_PROXY_CONTEXT_FREE() /* nothing */ +#endif + +#define SMTP_SESSION_ACTIVATE_ERR_RETURN() do { \ + TLS_PROXY_CONTEXT_FREE(); \ + return (0); \ + } while (0) /* - * XXX it would be nice to have a VSTRING to VSTREAM adapter so that we - * can de-serialize the properties with attr_scan(), instead of using - * ad-hoc, non-reusable code. - * - * XXX As a preliminary solution we use mystrtok(), but that function is not - * suitable for zero-length fields. + * Sanity check: if TLS is required, the cached properties must contain a + * TLS context. */ - endp_props = STR(endp_prop); - if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { - msg_warn("%s: bad cached session reuse count property", myname); - return (0); - } - reuse_count = atoi(prop); - if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { - msg_warn("%s: bad cached session features property", myname); - return (0); - } - features = atoi(prop); - if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { - msg_warn("%s: bad cached session expiration time property", myname); - return (0); - } -#ifdef MISSING_STRTOUL - expire_time = strtol(prop, 0, 10); -#else - expire_time = strtoul(prop, 0, 10); + if ((mp = vstream_memopen(endp_prop, O_RDONLY)) == 0 + || attr_scan_plain(mp, ATTR_FLAG_NONE, +#ifdef USE_TLS + RECV_ATTR_INT(SESS_ATTR_TLS_LEVEL, + &tls->level), #endif + RECV_ATTR_INT(SESS_ATTR_REUSE_COUNT, + &reuse_count), + RECV_ATTR_INT(SESS_ATTR_ENDP_FEATURES, + &endp_features), + RECV_ATTR_LONG(SESS_ATTR_EXPIRE_TIME, + &expire_time), + ATTR_TYPE_END) != 4 +#ifdef USE_TLS + || ((tls->level > TLS_LEV_MAY + || (tls->level == TLS_LEV_MAY && vstream_peek(mp) > 0)) + && attr_scan_plain(mp, ATTR_FLAG_NONE, + RECV_ATTR_FUNC(tls_proxy_context_scan, + (void *) &tls_context), + ATTR_TYPE_END) != 1) +#endif + || vstream_fclose(mp) != 0) { + msg_warn("smtp_session_activate: bad cached endp properties"); + SMTP_SESSION_ACTIVATE_ERR_RETURN(); + } /* * Clobber the iterator's current nexthop, host and address fields with * cached-connection information. This is done when a session is looked - * up by request nexthop instead of address and port. It is the caller's - * responsibility to save and restore the request nexthop with - * SMTP_ITER_SAVE_DEST() and SMTP_ITER_RESTORE_DEST(). + * up by delivery request nexthop instead of address and port. It is the + * caller's responsibility to save and restore the delivery request + * nexthop with SMTP_ITER_SAVE_DEST() and SMTP_ITER_RESTORE_DEST(). * * TODO: Eliminate the duplication between SMTP_ITERATOR and SMTP_SESSION. * @@ -334,26 +394,25 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter, * correctly save a reused authenticated connection. */ if (dest_prop && VSTRING_LEN(dest_prop)) { - dest_props = STR(dest_prop); - if ((dest = mystrtok(&dest_props, "\n")) == 0) { - msg_warn("%s: missing cached session destination property", myname); - return (0); - } - if ((host = mystrtok(&dest_props, "\n")) == 0) { - msg_warn("%s: missing cached session hostname property", myname); - return (0); - } - if ((addr = mystrtok(&dest_props, "\n")) == 0) { - msg_warn("%s: missing cached session address property", myname); - return (0); + if ((mp = vstream_memopen(dest_prop, O_RDONLY)) == 0 + || attr_scan_plain(mp, ATTR_FLAG_NONE, + RECV_ATTR_STR(SESS_ATTR_DEST, iter->dest), + RECV_ATTR_STR(SESS_ATTR_HOST, iter->host), + RECV_ATTR_STR(SESS_ATTR_ADDR, iter->addr), + RECV_ATTR_INT(SESS_ATTR_DEST_FEATURES, + &dest_features), + ATTR_TYPE_END) != 4 + || vstream_fclose(mp) != 0) { + msg_warn("smtp_session_passivate: bad cached dest properties"); + SMTP_SESSION_ACTIVATE_ERR_RETURN(); } - if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) { - msg_warn("%s: bad cached destination features property", myname); - return (0); - } - features |= atoi(prop); - SMTP_ITER_CLOBBER(iter, dest, host, addr); + } else { + dest_features = 0; } +#ifdef USE_TLS + if (msg_verbose) + msg_info("%s: tls_level=%d", myname, tls->level); +#endif /* * Allright, bundle up what we have sofar. @@ -362,7 +421,11 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter, session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), iter, (time_t) 0, NO_FLAGS); - session->features = (features | SMTP_FEATURE_FROM_CACHE); + session->features = + (endp_features | dest_features | SMTP_FEATURE_FROM_CACHE); +#ifdef USE_TLS + session->tls_context = tls_context; +#endif CACHE_THIS_SESSION_UNTIL(expire_time); session->reuse_count = ++reuse_count; @@ -370,20 +433,15 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter, msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, " "ttl=%ld, reuse=%d", myname, STR(iter->dest), STR(iter->host), - STR(iter->addr), ntohs(iter->port), features, + STR(iter->addr), ntohs(iter->port), + endp_features | dest_features, (long) (expire_time - time((time_t *) 0)), reuse_count); - /* - * Re-activate the SASL attributes. - */ -#ifdef notdef - if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) { - vstream_fdclose(session->stream); - session->stream = 0; - smtp_session_free(session); - return (0); - } +#if USE_TLS + if (tls_context) + tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_USED, + session->tls_context); #endif return (session); diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_tls_policy.c b/external/ibm-public/postfix/dist/src/smtp/smtp_tls_policy.c index aaaf787005a..5b6c9dec0bf 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_tls_policy.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_tls_policy.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_tls_policy.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_tls_policy.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -76,6 +76,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Viktor Dukhovni /*--*/ @@ -100,6 +105,7 @@ #include <mymalloc.h> #include <vstring.h> #include <stringops.h> +#include <valid_hostname.h> #include <valid_utf8_hostname.h> #include <ctable.h> @@ -301,6 +307,22 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, tls->protocols = mystrdup(val); continue; } + /* Only one instance per policy. */ + if (!strcasecmp(name, "servername")) { + if (tls->sni) { + msg_warn("%s: attribute \"%s\" is specified multiple times", + WHERE, name); + INVALID_RETURN(tls->why, site_level); + } + if (valid_hostname(val, DONT_GRIPE)) + tls->sni = mystrdup(val); + else { + msg_warn("%s: \"%s=%s\" specifies an invalid hostname", + WHERE, name, val); + INVALID_RETURN(tls->why, site_level); + } + continue; + } /* Multiple instances per policy. */ if (!strcasecmp(name, "match")) { if (*val == 0) { @@ -358,6 +380,18 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, } continue; } + /* Last one wins. */ + if (!strcasecmp(name, "connection_reuse")) { + if (strcasecmp(val, "yes") == 0) { + tls->conn_reuse = 1; + } else if (strcasecmp(val, "no") == 0) { + tls->conn_reuse = 0; + } else { + msg_warn("%s: attribute \"%s\" has bad value: \"%s\"", + WHERE, name, val); + INVALID_RETURN(tls->why, site_level); + } + } msg_warn("%s: invalid attribute name: \"%s\"", WHERE, name); INVALID_RETURN(tls->why, site_level); } @@ -485,6 +519,7 @@ static void *policy_create(const char *unused_key, void *context) SMTP_TLS_POLICY *tls = (SMTP_TLS_POLICY *) mymalloc(sizeof(*tls)); smtp_tls_policy_init(tls, dsb_create()); + tls->conn_reuse = var_smtp_tls_conn_reuse; /* * Compute the per-site TLS enforcement level. For compatibility with the @@ -544,12 +579,23 @@ static void *policy_create(const char *unused_key, void *context) return ((void *) tls); /* - * Use main.cf protocols setting if not set in per-destination table. + * Use main.cf protocols and SNI settings if not set in per-destination + * table. */ if (tls->level > TLS_LEV_NONE && tls->protocols == 0) tls->protocols = mystrdup((tls->level == TLS_LEV_MAY) ? var_smtp_tls_proto : var_smtp_tls_mand_proto); + if (tls->level > TLS_LEV_NONE && tls->sni == 0) { + if (!*var_smtp_tls_sni || valid_hostname(var_smtp_tls_sni, DONT_GRIPE)) + tls->sni = mystrdup(var_smtp_tls_sni); + else { + msg_warn("\"%s = %s\" specifies an invalid hostname", + VAR_LMTP_SMTP(TLS_SNI), var_smtp_tls_sni); + MARK_INVALID(tls->why, &tls->level); + return ((void *) tls); + } + } /* * Compute cipher grade (if set in per-destination table, else @@ -620,6 +666,8 @@ static void policy_delete(void *item, void *unused_context) if (tls->protocols) myfree(tls->protocols); + if (tls->sni) + myfree(tls->sni); if (tls->grade) myfree(tls->grade); if (tls->exclusions) @@ -652,7 +700,7 @@ int smtp_tls_policy_cache_query(DSN_BUF *why, SMTP_TLS_POLICY *tls, * values that also appear in other cache and table search keys. */ key = vstring_alloc(100); - smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_NEXTHOP + smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | SMTP_KEY_FLAG_PORT); ctable_newcontext(policy_cache, (void *) iter); diff --git a/external/ibm-public/postfix/dist/src/smtp/smtp_trouble.c b/external/ibm-public/postfix/dist/src/smtp/smtp_trouble.c index b87838f885e..064b784ef52 100644 --- a/external/ibm-public/postfix/dist/src/smtp/smtp_trouble.c +++ b/external/ibm-public/postfix/dist/src/smtp/smtp_trouble.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp_trouble.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp_trouble.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -146,6 +146,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -192,11 +197,17 @@ static void smtp_check_code(SMTP_SESSION *session, int code) * remote servers screw up, protocol wise. This is becoming a common * problem now that response codes are configured manually as part of * anti-UCE systems, by people who aren't aware of RFC details. + * + * Fix 20190621: don't cache an SMTP session after an SMTP protocol error. + * The protocol may be in a bad state. Disable caching here so that the + * protocol engine will send QUIT. */ if (code < 400 || code > 599 || code == 555 /* RFC 1869, section 6.1. */ - || (code >= 500 && code < 510)) + || (code >= 500 && code < 510)) { session->error_mask |= MAIL_ERROR_PROTOCOL; + DONT_CACHE_THIS_SESSION; + } } /* smtp_bulk_fail - skip, defer or bounce recipients, maybe throttle queue */ @@ -311,9 +322,17 @@ static void vsmtp_fill_dsn(SMTP_STATE *state, const char *mta_name, * when informal text needs to be formatted. So we maintain consistency * with other error reporting in the SMTP client even if we waste a few * cycles. + * + * Fix 20190621: don't cache an SMTP session after an SMTP protocol error. + * The protocol may be in a bad state. Disable caching here so that the + * protocol engine will send QUIT. */ VSTRING_RESET(why->reason); if (mta_name && status && status[0] != '4' && status[0] != '5') { + SMTP_SESSION *session = state->session; + + session->error_mask |= MAIL_ERROR_PROTOCOL; + DONT_CACHE_THIS_SESSION; vstring_strcpy(why->reason, "Protocol error: "); status = "5.5.0"; } @@ -325,8 +344,8 @@ static void vsmtp_fill_dsn(SMTP_STATE *state, const char *mta_name, /* smtp_misc_fail - maybe throttle queue; skip/defer/bounce all recipients */ -int smtp_misc_fail(SMTP_STATE *state, int throttle, const char *mta_name, - SMTP_RESP *resp, const char *format,...) +int smtp_misc_fail(SMTP_STATE *state, int throttle, const char *mta_name, + SMTP_RESP *resp, const char *format,...) { va_list ap; diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd.c index c7c2c9ac26b..be02b63b34d 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd.c,v 1.16 2018/02/01 03:32:00 christos Exp $ */ +/* $NetBSD: smtpd.c,v 1.17 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -48,6 +48,7 @@ /* RFC 2554 (AUTH command) /* RFC 2821 (SMTP protocol) /* RFC 2920 (SMTP pipelining) +/* RFC 3030 (CHUNKING without BINARYMIME) /* RFC 3207 (STARTTLS command) /* RFC 3461 (SMTP DSN extension) /* RFC 3463 (Enhanced status codes) @@ -59,7 +60,8 @@ /* RFC 6533 (Internationalized Delivery Status Notifications) /* RFC 7505 ("Null MX" No Service Resource Record) /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* /* Depending on the setting of the \fBnotify_classes\fR parameter, /* the postmaster is notified of bounces, protocol problems, @@ -215,8 +217,9 @@ /* for communication with a Milter application; prior to Postfix 2.6 /* the default protocol is 2. /* .IP "\fBmilter_default_action (tempfail)\fR" -/* The default action when a Milter (mail filter) application is -/* unavailable or mis-configured. +/* The default action when a Milter (mail filter) response is +/* unavailable (for example, bad Postfix configuration or Milter +/* failure). /* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR" /* The {daemon_name} macro value for Milter (mail filter) applications. /* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR" @@ -260,6 +263,11 @@ /* Optional list of \fIname=value\fR pairs that specify default /* values for arbitrary macros that Postfix may send to Milter /* applications. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBsmtpd_milter_maps (empty)\fR" +/* Lookup tables with Milter settings per remote SMTP client IP +/* address. /* GENERAL CONTENT INSPECTION CONTROLS /* .ad /* .fi @@ -335,6 +343,10 @@ /* .IP "\fBsmtpd_sasl_service (smtp)\fR" /* The service name that is passed to the SASL plug-in that is /* selected with \fBsmtpd_sasl_type\fR and \fBsmtpd_sasl_path\fR. +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBsmtpd_sasl_response_limit (12288)\fR" +/* The maximum length of a SASL client's response to a server challenge. /* STARTTLS SUPPORT CONTROLS /* .ad /* .fi @@ -470,6 +482,30 @@ /* Available in Postfix version 3.0 and later: /* .IP "\fBtls_session_ticket_cipher (Postfix >= 3.0: aes-256-cbc, Postfix < 3.0: aes-128-cbc)\fR" /* Algorithm used to encrypt RFC5077 TLS session tickets. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBtls_eecdh_auto_curves (see 'postconf -d' output)\fR" +/* The prioritized list of elliptic curves supported by the Postfix +/* SMTP client and server. +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBsmtpd_tls_chain_files (empty)\fR" +/* List of one or more PEM files, each holding one or more private keys +/* directly followed by a corresponding certificate chain. +/* .IP "\fBtls_server_sni_maps (empty)\fR" +/* Optional lookup tables that map names received from remote SMTP +/* clients via the TLS Server Name Indication (SNI) extension to the +/* appropriate keys and certificate chains. +/* .PP +/* Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later: +/* .IP "\fBtls_fast_shutdown_enable (yes)\fR" +/* A workaround for implementations that hang Postfix while shutting +/* down a TLS session, until Postfix times out. +/* .PP +/* 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.). /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -497,6 +533,12 @@ /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBenable_idna2003_compatibility (no)\fR" +/* Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +/* when converting UTF-8 domain names to/from the ASCII form that is +/* used for DNS lookups. /* VERP SUPPORT CONTROLS /* .ad /* .fi @@ -579,6 +621,9 @@ /* .IP "\fBrecipient_canonical_maps (empty)\fR" /* Optional address mapping lookup tables for envelope and header /* recipient addresses. +/* .IP "\fBsender_canonical_maps (empty)\fR" +/* Optional address mapping lookup tables for envelope and header +/* sender addresses. /* .PP /* Parameters concerning known/unknown local recipients: /* .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" @@ -965,7 +1010,7 @@ /* fails due to a temporary error condition. /* .IP "\fBunknown_helo_hostname_tempfail_action ($reject_tempfail_action)\fR" /* The Postfix SMTP server's action when reject_unknown_helo_hostname -/* fails due to an temporary error condition. +/* fails due to a temporary error condition. /* .IP "\fBunknown_address_tempfail_action ($reject_tempfail_action)\fR" /* The Postfix SMTP server's action when reject_unknown_sender_domain /* or reject_unknown_recipient_domain fail due to a temporary error @@ -1023,8 +1068,8 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 2.2 and later: /* .IP "\fBsmtpd_forbidden_commands (CONNECT, GET, POST)\fR" @@ -1035,6 +1080,15 @@ /* .IP "\fBsmtpd_client_port_logging (no)\fR" /* Enable logging of the remote SMTP client port in addition to /* the hostname and IP address. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* Available in Postfix 3.4 and later: +/* .IP "\fBsmtpd_reject_footer_maps (empty)\fR" +/* Lookup tables, indexed by the complete Postfix SMTP server 4xx or +/* 5xx response, with reject footer templates. /* SEE ALSO /* anvil(8), connection/rate limiting /* cleanup(8), message canonicalization @@ -1044,6 +1098,7 @@ /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad @@ -1053,7 +1108,8 @@ /* .na /* .nf /* ADDRESS_CLASS_README, blocking unknown hosted or relay recipients -/* ADDRESS_REWRITING_README Postfix address manipulation +/* ADDRESS_REWRITING_README, Postfix address manipulation +/* BDAT_README, Postfix CHUNKING support /* FILTER_README, external after-queue content filter /* LOCAL_RECIPIENT_README, blocking unknown local recipients /* MILTER_README, before-queue mail filter applications @@ -1172,6 +1228,8 @@ #include <verify_sender_addr.h> #include <smtputf8.h> #include <match_parent_style.h> +#include <normalize_mailhost_addr.h> +#include <info_log_addr_form.h> /* Single-threaded server skeleton. */ @@ -1211,7 +1269,7 @@ int var_smtpd_rcpt_limit; int var_smtpd_tmout; int var_smtpd_soft_erlim; int var_smtpd_hard_erlim; -int var_queue_minfree; /* XXX use off_t */ +long var_queue_minfree; /* XXX use off_t */ char *var_smtpd_banner; char *var_notify_classes; char *var_client_checks; @@ -1259,6 +1317,7 @@ char *var_smtpd_sasl_path; char *var_smtpd_sasl_service; char *var_cyrus_conf_path; char *var_smtpd_sasl_realm; +int var_smtpd_sasl_resp_limit; char *var_smtpd_sasl_exceptions_networks; char *var_smtpd_sasl_type; char *var_filter_xport; @@ -1322,6 +1381,7 @@ bool var_smtpd_tls_wrappermode; bool var_smtpd_tls_auth_only; char *var_smtpd_cmd_filter; char *var_smtpd_rej_footer; +char *var_smtpd_rej_ftr_maps; char *var_smtpd_acl_perm_log; char *var_smtpd_dns_re_filter; @@ -1353,6 +1413,7 @@ char *var_smtpd_tls_proto; char *var_smtpd_tls_eecdh; char *var_smtpd_tls_eccert_file; char *var_smtpd_tls_eckey_file; +char *var_smtpd_tls_chain_files; #endif @@ -1360,6 +1421,7 @@ bool var_smtpd_peername_lookup; int var_plaintext_code; bool var_smtpd_delay_open; char *var_smtpd_milters; +char *var_smtpd_milter_maps; int var_milt_conn_time; int var_milt_cmd_time; int var_milt_msg_time; @@ -1408,6 +1470,13 @@ int var_smtpd_uproxy_tmout; static MAPS *ehlo_discard_maps; /* + * Per-client Milter support. + */ +static MAPS *smtpd_milter_maps; +static void setup_milters(SMTPD_STATE *); +static void teardown_milters(SMTPD_STATE *); + + /* * VERP command name. */ #define VERP_CMD "XVERP" @@ -1464,19 +1533,16 @@ static void tls_reset(SMTPD_STATE *); #define REASON_LOST_CONNECTION "lost connection" #define REASON_ERROR_LIMIT "too many errors" - /* - * Mail filter initialization status. - */ -MILTERS *smtpd_milters; - #ifdef USE_TLS /* * TLS initialization status. */ +#ifndef USE_TLSPROXY static TLS_APPL_STATE *smtpd_tls_ctx; static int ask_client_cert; +#endif /* USE_TLSPROXY */ #endif /* @@ -1529,13 +1595,20 @@ static const char *smtpd_whatsup(SMTPD_STATE *state) else VSTRING_RESET(buf); if (state->sender) - vstring_sprintf_append(buf, " from=<%s>", state->sender); + vstring_sprintf_append(buf, " from=<%s>", + info_log_addr_form_sender(state->sender)); if (state->recipient) - vstring_sprintf_append(buf, " to=<%s>", state->recipient); + vstring_sprintf_append(buf, " to=<%s>", + info_log_addr_form_recipient(state->recipient)); if (state->protocol) vstring_sprintf_append(buf, " proto=%s", state->protocol); if (state->helo_name) vstring_sprintf_append(buf, " helo=<%s>", state->helo_name); +#ifdef USE_SASL_AUTH + if (state->sasl_username) + vstring_sprintf_append(buf, " sasl_username=<%s>", + state->sasl_username); +#endif return (STR(buf)); } @@ -1640,10 +1713,9 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) #define PUSH_STRING(old, curr, new) { char *old = (curr); (curr) = (new); #define POP_STRING(old, curr) (curr) = old; } - if (smtpd_milters != 0 - && SMTPD_STAND_ALONE(state) == 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0 - && (err = milter_helo_event(smtpd_milters, argv[1].strval, 0)) != 0) { + && (err = milter_helo_event(state->milters, argv[1].strval, 0)) != 0) { /* Log reject etc. with correct HELO information. */ PUSH_STRING(saved_helo, state->helo_name, argv[1].strval); err = check_milter_reply(state, err); @@ -1726,10 +1798,9 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) * other commands such as AUTH, STARTTLS, and VRFY. */ err = 0; - if (smtpd_milters != 0 - && SMTPD_STAND_ALONE(state) == 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0 - && (err = milter_helo_event(smtpd_milters, argv[1].strval, 1)) != 0) { + && (err = milter_helo_event(state->milters, argv[1].strval, 1)) != 0) { /* Log reject etc. with correct HELO information. */ PUSH_STRING(saved_helo, state->helo_name, argv[1].strval); err = check_milter_reply(state, err); @@ -1810,7 +1881,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) if ((discard_mask & EHLO_MASK_PIPELINING) == 0) EHLO_APPEND(state, "PIPELINING"); if ((discard_mask & EHLO_MASK_SIZE) == 0) { - if (var_message_limit) + if (ENFORCING_SIZE_LIMIT(var_message_limit)) EHLO_APPEND1(state, "SIZE %lu", (unsigned long) var_message_limit); /* XXX */ else @@ -1855,7 +1926,9 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) " " XCLIENT_NAME " " XCLIENT_ADDR " " XCLIENT_PROTO " " XCLIENT_HELO " " XCLIENT_REVERSE_NAME " " XCLIENT_PORT - XCLIENT_LOGIN_KLUDGE); + XCLIENT_LOGIN_KLUDGE + " " XCLIENT_DESTADDR + " " XCLIENT_DESTPORT); else if (xclient_hosts && xclient_hosts->error) cant_announce_feature(state, XCLIENT_CMD); } @@ -1877,6 +1950,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) EHLO_APPEND(state, "DSN"); if (var_smtputf8_enable && (discard_mask & EHLO_MASK_SMTPUTF8) == 0) EHLO_APPEND(state, "SMTPUTF8"); + if ((discard_mask & EHLO_MASK_CHUNKING) == 0) + EHLO_APPEND(state, "CHUNKING"); /* * Send the reply. @@ -1902,8 +1977,8 @@ static void helo_reset(SMTPD_STATE *state) if (state->helo_name) { myfree(state->helo_name); state->helo_name = 0; - if (SMTPD_STAND_ALONE(state) == 0 && smtpd_milters != 0) - milter_abort(smtpd_milters); + if (state->milters != 0) + milter_abort(state->milters); } if (state->ehlo_argv) { argv_free(state->ehlo_argv); @@ -2034,10 +2109,10 @@ static int mail_open_stream(SMTPD_STATE *state) state->cleanup = state->dest->stream; state->queue_id = mystrdup(state->dest->id); if (SMTPD_STAND_ALONE(state) == 0) { - if (smtpd_milters != 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0) /* Send place-holder smtpd_milters list. */ - (void) milter_dummy(smtpd_milters, state->cleanup); + (void) milter_dummy(state->milters, state->cleanup); rec_fprintf(state->cleanup, REC_TYPE_TIME, REC_TYPE_TIME_FORMAT, REC_TYPE_TIME_ARG(state->arrival_time)); if (*var_filter_xport) @@ -2136,6 +2211,10 @@ static int mail_open_stream(SMTPD_STATE *state) MAIL_ATTR_ACT_CLIENT_ADDR, state->addr); rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_CLIENT_PORT, state->port); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ACT_SERVER_ADDR, state->dest_addr); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ACT_SERVER_PORT, state->dest_port); if (state->helo_name) rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ACT_HELO_NAME, state->helo_name); @@ -2360,6 +2439,12 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "503 5.5.1 Error: nested MAIL command"); return (-1); } + /* Don't accept MAIL after out-of-order BDAT. */ + if (SMTPD_PROCESSING_BDAT(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 5.5.1 Error: MAIL after BDAT"); + return (-1); + } if (argc < 3 || strcasecmp(argv[1].strval, "from:") != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; @@ -2496,7 +2581,11 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) return (-1); } } - if ((err = smtpd_check_size(state, state->msg_size)) != 0) { + /* Fix 20161205: show the envelope sender in reject logging. */ + PUSH_STRING(saved_sender, state->sender, STR(state->addr_buf)); + err = smtpd_check_size(state, state->msg_size); + POP_STRING(saved_sender, state->sender); + if (err != 0) { smtpd_chat_reply(state, "%s", err); return (-1); } @@ -2528,11 +2617,11 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "%s", err); return (-1); } - if (smtpd_milters != 0 - && SMTPD_STAND_ALONE(state) == 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0) { + state->flags |= SMTPD_FLAG_NEED_MILTER_ABORT; PUSH_STRING(saved_sender, state->sender, STR(state->addr_buf)); - err = milter_mail_event(smtpd_milters, + err = milter_mail_event(state->milters, milter_argv(state, argc - 2, argv + 2)); if (err != 0) { /* Log reject etc. with correct sender information. */ @@ -2559,7 +2648,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) /* * Historically, Postfix does not forbid 8-bit envelope localparts. * Changing this would be a compatibility break. That can't happen in the - * forseeable future. + * foreseeable future. */ if ((var_strict_smtputf8 || warn_compat_break_smtputf8_enable) && (state->flags & SMTPD_FLAG_SMTPUTF8) == 0 @@ -2646,11 +2735,14 @@ static void mail_reset(SMTPD_STATE *state) state->queue_id = 0; } if (state->sender) { - if (SMTPD_STAND_ALONE(state) == 0 && smtpd_milters != 0) - milter_abort(smtpd_milters); myfree(state->sender); state->sender = 0; } + /* WeiYu Wu: need to undo milter_mail_event() state change. */ + if (state->flags & SMTPD_FLAG_NEED_MILTER_ABORT) { + milter_abort(state->milters); + state->flags &= ~SMTPD_FLAG_NEED_MILTER_ABORT; + } if (state->verp_delims) { myfree(state->verp_delims); state->verp_delims = 0; @@ -2668,7 +2760,7 @@ static void mail_reset(SMTPD_STATE *state) state->saved_redirect = 0; } if (state->saved_bcc) { - myfree(state->saved_bcc); + argv_free(state->saved_bcc); state->saved_bcc = 0; } state->saved_flags = 0; @@ -2698,6 +2790,17 @@ static void mail_reset(SMTPD_STATE *state) state->milter_argv = 0; state->milter_argc = 0; } + + /* + * BDAT. + */ + state->bdat_state = SMTPD_BDAT_STAT_NONE; + if (state->bdat_get_stream) { + (void) vstream_fclose(state->bdat_get_stream); + state->bdat_get_stream = 0; + } + if (state->bdat_get_buffer) + VSTRING_RESET(state->bdat_get_buffer); } /* rcpt_cmd - process RCPT TO command */ @@ -2730,6 +2833,12 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "503 5.5.1 Error: need MAIL command"); return (-1); } + /* Don't accept RCPT after BDAT. */ + if (SMTPD_PROCESSING_BDAT(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 5.5.1 Error: RCPT after BDAT"); + return (-1); + } if (argc < 3 || strcasecmp(argv[1].strval, "to:") != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; @@ -2821,7 +2930,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) /* * Historically, Postfix does not forbid 8-bit envelope localparts. * Changing this would be a compatibility break. That can't happen in the - * forseeable future. + * foreseeable future. */ if ((var_strict_smtputf8 || warn_compat_break_smtputf8_enable) && (state->flags & SMTPD_FLAG_SMTPUTF8) == 0 @@ -2861,11 +2970,11 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) } else { err = smtpd_check_rcpt(state, STR(state->addr_buf)); } - if (smtpd_milters != 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0) { PUSH_STRING(saved_rcpt, state->recipient, STR(state->addr_buf)); state->milter_reject_text = err; - milter_err = milter_rcpt_event(smtpd_milters, + milter_err = milter_rcpt_event(state->milters, err == 0 ? MILTER_FLAG_NONE : MILTER_FLAG_WANT_RCPT_REJ, milter_argv(state, argc - 2, argv + 2)); @@ -3079,45 +3188,37 @@ static void comment_sanitize(VSTRING *comment_string) VSTRING_TERMINATE(comment_string); } +static void common_pre_message_handling(SMTPD_STATE *state, + int (*out_record) (VSTREAM *, int, const char *, ssize_t), + int (*out_fprintf) (VSTREAM *, int, const char *,...), + VSTREAM *out_stream, int out_error); +static void receive_data_message(SMTPD_STATE *state, + int (*out_record) (VSTREAM *, int, const char *, ssize_t), + int (*out_fprintf) (VSTREAM *, int, const char *,...), + VSTREAM *out_stream, int out_error); +static int common_post_message_handling(SMTPD_STATE *state); + /* data_cmd - process DATA command */ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) { SMTPD_PROXY *proxy; const char *err; - char *start; - int len; - int curr_rec_type; - int prev_rec_type; - int first = 1; - VSTRING *why = 0; - int saved_err; int (*out_record) (VSTREAM *, int, const char *, ssize_t); int (*out_fprintf) (VSTREAM *, int, const char *,...); VSTREAM *out_stream; int out_error; - char **cpp; - const CLEANUP_STAT_DETAIL *detail; - const char *rfc3848_sess; - const char *rfc3848_auth; - const char *with_protocol = (state->flags & SMTPD_FLAG_SMTPUTF8) ? - "UTF8SMTP" : state->protocol; - -#ifdef USE_TLS - VSTRING *peer_CN; - VSTRING *issuer_CN; - -#endif -#ifdef USE_SASL_AUTH - VSTRING *username; - -#endif /* * Sanity checks. With ESMTP command pipelining the client can send DATA * before all recipients are rejected, so don't report that as a protocol * error. */ + if (SMTPD_PROCESSING_BDAT(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 5.5.1 Error: DATA after BDAT"); + return (-1); + } if (state->rcpt_count == 0) { if (!SMTPD_IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; @@ -3136,10 +3237,9 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) smtpd_chat_reply(state, "%s", err); return (-1); } - if (smtpd_milters != 0 - && SMTPD_STAND_ALONE(state) == 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0 - && (err = milter_data_event(smtpd_milters)) != 0 + && (err = milter_data_event(state->milters)) != 0 && (err = check_milter_reply(state, err)) != 0) { smtpd_chat_reply(state, "%s", err); return (-1); @@ -3167,6 +3267,38 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) out_fprintf = rec_fprintf; out_error = CLEANUP_STAT_WRITE; } + common_pre_message_handling(state, out_record, out_fprintf, + out_stream, out_error); + smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>"); + state->where = SMTPD_AFTER_DATA; + receive_data_message(state, out_record, out_fprintf, out_stream, out_error); + return common_post_message_handling(state); +} + +/* common_pre_message_handling - finish envelope and open message segment */ + +static void common_pre_message_handling(SMTPD_STATE *state, + int (*out_record) (VSTREAM *, int, const char *, ssize_t), + int (*out_fprintf) (VSTREAM *, int, const char *,...), + VSTREAM *out_stream, + int out_error) +{ + SMTPD_PROXY *proxy = state->proxy; + char **cpp; + const char *rfc3848_sess; + const char *rfc3848_auth; + const char *with_protocol = (state->flags & SMTPD_FLAG_SMTPUTF8) ? + "UTF8SMTP" : state->protocol; + +#ifdef USE_TLS + VSTRING *peer_CN; + VSTRING *issuer_CN; + +#endif +#ifdef USE_SASL_AUTH + VSTRING *username; + +#endif /* * Flush out a first batch of access table actions that are delegated to @@ -3179,10 +3311,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) */ if (state->cleanup) { if (SMTPD_STAND_ALONE(state) == 0) { - if (smtpd_milters != 0 + if (state->milters != 0 && (state->saved_flags & MILTER_SKIP_FLAGS) == 0) /* Send actual smtpd_milters list. */ - (void) milter_send(smtpd_milters, state->cleanup); + (void) milter_send(state->milters, state->cleanup); if (state->saved_flags) rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", state->saved_flags); @@ -3211,12 +3343,70 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) #ifdef USE_TLS if (var_smtpd_tls_received_header && state->tls_context) { - out_fprintf(out_stream, REC_TYPE_NORM, - "\t(using %s with cipher %s (%d/%d bits))", - state->tls_context->protocol, - state->tls_context->cipher_name, - state->tls_context->cipher_usebits, - state->tls_context->cipher_algbits); + int cont = 0; + + vstring_sprintf(state->buffer, + "\t(using %s with cipher %s (%d/%d bits)", + state->tls_context->protocol, + state->tls_context->cipher_name, + state->tls_context->cipher_usebits, + state->tls_context->cipher_algbits); + if (state->tls_context->kex_name && *state->tls_context->kex_name) { + out_record(out_stream, REC_TYPE_NORM, STR(state->buffer), + LEN(state->buffer)); + vstring_sprintf(state->buffer, "\t key-exchange %s", + state->tls_context->kex_name); + if (state->tls_context->kex_curve + && *state->tls_context->kex_curve) + vstring_sprintf_append(state->buffer, " (%s)", + state->tls_context->kex_curve); + else if (state->tls_context->kex_bits > 0) + vstring_sprintf_append(state->buffer, " (%d bits)", + state->tls_context->kex_bits); + cont = 1; + } + if (state->tls_context->srvr_sig_name + && *state->tls_context->srvr_sig_name) { + if (cont) { + vstring_sprintf_append(state->buffer, " server-signature %s", + state->tls_context->srvr_sig_name); + } else { + out_record(out_stream, REC_TYPE_NORM, STR(state->buffer), + LEN(state->buffer)); + vstring_sprintf(state->buffer, "\t server-signature %s", + state->tls_context->srvr_sig_name); + } + 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); + else if (state->tls_context->srvr_sig_bits > 0) + vstring_sprintf_append(state->buffer, " (%d bits)", + state->tls_context->srvr_sig_bits); + if (state->tls_context->srvr_sig_dgst + && *state->tls_context->srvr_sig_dgst) + vstring_sprintf_append(state->buffer, " server-digest %s", + state->tls_context->srvr_sig_dgst); + } + if (state->tls_context->clnt_sig_name + && *state->tls_context->clnt_sig_name) { + out_record(out_stream, REC_TYPE_NORM, STR(state->buffer), + LEN(state->buffer)); + vstring_sprintf(state->buffer, "\t client-signature %s", + 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); + else if (state->tls_context->clnt_sig_bits > 0) + vstring_sprintf_append(state->buffer, " (%d bits)", + state->tls_context->clnt_sig_bits); + if (state->tls_context->clnt_sig_dgst + && *state->tls_context->clnt_sig_dgst) + vstring_sprintf_append(state->buffer, " client-digest %s", + state->tls_context->clnt_sig_dgst); + } + out_fprintf(out_stream, REC_TYPE_NORM, "%s)", STR(state->buffer)); if (TLS_CERT_IS_PRESENT(state->tls_context)) { peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN); comment_sanitize(peer_CN); @@ -3286,8 +3476,22 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) "\t(envelope-from %s)", STR(state->buffer)); #endif } - smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>"); - state->where = SMTPD_AFTER_DATA; +} + +/* receive_data_message - finish envelope and open message segment */ + +static void receive_data_message(SMTPD_STATE *state, + int (*out_record) (VSTREAM *, int, const char *, ssize_t), + int (*out_fprintf) (VSTREAM *, int, const char *,...), + VSTREAM *out_stream, + int out_error) +{ + SMTPD_PROXY *proxy = state->proxy; + char *start; + int len; + int curr_rec_type; + int prev_rec_type; + int first = 1; /* * Copy the message content. If the cleanup process has a problem, keep @@ -3323,7 +3527,8 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) && (proxy == 0 ? (++start, --len) == 0 : len == 1)) break; if (state->err == CLEANUP_STAT_OK) { - if (var_message_limit > 0 && var_message_limit - state->act_size < len + 2) { + if (ENFORCING_SIZE_LIMIT(var_message_limit) + && var_message_limit - state->act_size < len + 2) { state->err = CLEANUP_STAT_SIZE; msg_warn("%s: queue file size limit exceeded", state->queue_id ? state->queue_id : "NOQUEUE"); @@ -3334,7 +3539,24 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) } } } - state->where = SMTPD_AFTER_DOT; + state->where = SMTPD_AFTER_EOM; +} + +/* common_post_message_handling - commit message or report error */ + +static int common_post_message_handling(SMTPD_STATE *state) +{ + SMTPD_PROXY *proxy = state->proxy; + const char *err; + VSTRING *why = 0; + int saved_err; + const CLEANUP_STAT_DETAIL *detail; + +#define IS_SMTP_REJECT(s) \ + (((s)[0] == '4' || (s)[0] == '5') \ + && ISDIGIT((s)[1]) && ISDIGIT((s)[2]) \ + && ((s)[3] == '\0' || (s)[3] == ' ' || (s)[3] == '-')) + if (state->err == CLEANUP_STAT_OK && SMTPD_STAND_ALONE(state) == 0 && (err = smtpd_check_eod(state)) != 0) { @@ -3378,10 +3600,14 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) rec_fprintf(state->cleanup, REC_TYPE_RDR, "%s", state->saved_redirect); if (state->saved_bcc) { - rec_fprintf(state->cleanup, REC_TYPE_RCPT, "%s", - state->saved_bcc); - rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%d", - MAIL_ATTR_DSN_NOTIFY, DSN_NOTIFY_NEVER); + char **cpp; + + for (cpp = state->saved_bcc->argv; *cpp; cpp++) { + rec_fprintf(state->cleanup, REC_TYPE_RCPT, "%s", + *cpp); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%d", + MAIL_ATTR_DSN_NOTIFY, DSN_NOTIFY_NEVER); + } } if (state->saved_flags) rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", @@ -3401,7 +3627,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) if (state->err == 0) { why = vstring_alloc(10); state->err = mail_stream_finish(state->dest, why); - printable(STR(why), ' '); + if (IS_SMTP_REJECT(STR(why))) + printable_except(STR(why), ' ', "\r\n"); + else + printable(STR(why), ' '); } else mail_stream_cleanup(state->dest); state->dest = 0; @@ -3426,7 +3655,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) * XXX See exception below in code that overrides state->access_denied for * compliance with RFC 2821 Sec 3.1. */ - if (smtpd_milters != 0 && (state->err & CLEANUP_STAT_WRITE) != 0) + if (state->milters != 0 && (state->err & CLEANUP_STAT_WRITE) != 0) state->access_denied = mystrdup("421 4.3.0 Mail system error"); /* @@ -3436,17 +3665,16 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) * * See also: qmqpd.c */ -#define IS_SMTP_REJECT(s) \ - (((s)[0] == '4' || (s)[0] == '5') \ - && ISDIGIT((s)[1]) && ISDIGIT((s)[2]) \ - && ((s)[3] == '\0' || (s)[3] == ' ' || (s)[3] == '-')) - if (state->err == CLEANUP_STAT_OK) { state->error_count = 0; state->error_mask = 0; state->junk_cmds = 0; if (proxy) smtpd_chat_reply(state, "%s", STR(proxy->reply)); + else if (SMTPD_PROCESSING_BDAT(state)) + smtpd_chat_reply(state, + "250 2.0.0 Ok: %ld bytes queued as %s", + (long) state->act_size, state->queue_id); else smtpd_chat_reply(state, "250 2.0.0 Ok: queued as %s", state->queue_id); @@ -3525,6 +3753,306 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) return (saved_err); } +/* skip_bdat - skip content and respond to BDAT error */ + +static int skip_bdat(SMTPD_STATE *state, off_t chunk_size, + bool final_chunk, const char *format,...) +{ + va_list ap; + off_t done; + off_t len; + + /* + * Read and discard content from the remote SMTP client. TODO: drop the + * connection in case of overload. + */ + for (done = 0; done < chunk_size; done += len) { + if ((len = chunk_size - done) > VSTREAM_BUFSIZE) + len = VSTREAM_BUFSIZE; + smtp_fread_buf(state->buffer, len, state->client); + } + + /* + * Send the response to the remote SMTP client. + */ + va_start(ap, format); + vsmtpd_chat_reply(state, format, ap); + va_end(ap); + + /* + * Reset state, or drop subsequent BDAT payloads until BDAT LAST or RSET. + */ + if (final_chunk) + mail_reset(state); + else + state->bdat_state = SMTPD_BDAT_STAT_ERROR; + return (-1); +} + +/* bdat_cmd - process BDAT command */ + +static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + SMTPD_PROXY *proxy; + const char *err; + off_t chunk_size; + bool final_chunk; + off_t done; + off_t read_len; + char *start; + int len; + int curr_rec_type; + int (*out_record) (VSTREAM *, int, const char *, ssize_t); + int (*out_fprintf) (VSTREAM *, int, const char *,...); + VSTREAM *out_stream; + int out_error; + + /* + * Hang up if the BDAT command is disabled. The next input would be raw + * message content and that would trigger lots of command errors. + */ + if (state->ehlo_discard_mask & EHLO_MASK_CHUNKING) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "521 5.5.1 Error: command not implemented"); + return (-1); + } + + /* + * Hang up if the BDAT command is malformed. The next input would be raw + * message content and that would trigger lots of command errors. + */ + if (argc < 2 || argc > 3 || !alldig(argv[1].strval) + || (chunk_size = off_cvt_string(argv[1].strval)) < 0 + || ((final_chunk = (argc == 3)) + && strcasecmp(argv[2].strval, "LAST") != 0)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + msg_warn("%s: malformed BDAT command syntax from %s: %.100s", + state->queue_id ? state->queue_id : "NOQUEUE", + state->namaddr, printable(vstring_str(state->buffer), '?')); + smtpd_chat_reply(state, "521 5.5.4 Syntax: BDAT count [LAST]"); + return (-1); + } + + /* + * Block abuse involving empty chunks (alternatively, we could count + * "BDAT 0" as a "NOOP", but then we would have to refactor the code that + * enforces the junk command limit). Clients that send a message as a + * sequence of "BDAT 1" should not be a problem: the Postfix BDAT + * implementation should be efficient enough to handle that. + */ + if (chunk_size == 0 && !final_chunk) { + msg_warn("%s: null BDAT request from %s", + state->queue_id ? state->queue_id : "NOQUEUE", + state->namaddr); + return skip_bdat(state, chunk_size, final_chunk, + "551 5.7.1 Null BDAT request"); + } + + /* + * BDAT commands may be pipelined within a MAIL transaction. After a BDAT + * request fails, keep accepting BDAT requests and skipping BDAT payloads + * to maintain synchronization with the remote SMTP client, until the + * client sends BDAT LAST or RSET. + */ + if (state->bdat_state == SMTPD_BDAT_STAT_ERROR) + return skip_bdat(state, chunk_size, final_chunk, + "551 5.0.0 Discarded %ld bytes after earlier error", + (long) chunk_size); + + /* + * Special handling for the first BDAT command in a MAIL transaction, + * treating it as a kind of "DATA" command for the purpose of policy + * evaluation. + */ + if (!SMTPD_PROCESSING_BDAT(state)) { + + /* + * With ESMTP command pipelining a client may send BDAT before the + * server has replied to all RCPT commands. For this reason we cannot + * treat BDAT without valid recipients as a protocol error. Worse, + * RFC 3030 does not discuss the role of BDAT commands in RFC 2920 + * command groups (batches of commands that may be sent without + * waiting for a response to each individual command). Therefore we + * have to allow for clients that pipeline the entire SMTP session + * after EHLO, including multiple MAIL transactions. + */ + if (state->rcpt_count == 0) { + if (!SMTPD_IN_MAIL_TRANSACTION(state)) { + /* TODO: maybe remove this from the DATA and BDAT handlers. */ + state->error_mask |= MAIL_ERROR_PROTOCOL; + return skip_bdat(state, chunk_size, final_chunk, + "503 5.5.1 Error: need RCPT command"); + } else { + return skip_bdat(state, chunk_size, final_chunk, + "554 5.5.1 Error: no valid recipients"); + } + } + if (SMTPD_STAND_ALONE(state) == 0 + && (err = smtpd_check_data(state)) != 0) { + return skip_bdat(state, chunk_size, final_chunk, "%s", err); + } + if (state->milters != 0 + && (state->saved_flags & MILTER_SKIP_FLAGS) == 0 + && (err = milter_data_event(state->milters)) != 0 + && (err = check_milter_reply(state, err)) != 0) { + return skip_bdat(state, chunk_size, final_chunk, "%s", err); + } + proxy = state->proxy; + if (proxy != 0 && proxy->cmd(state, SMTPD_PROX_WANT_MORE, + SMTPD_CMD_DATA) != 0) { + return skip_bdat(state, chunk_size, final_chunk, + "%s", STR(proxy->reply)); + } + } + /* Block too large chunks. */ + if (ENFORCING_SIZE_LIMIT(var_message_limit) + && state->act_size > var_message_limit - chunk_size) { + state->error_mask |= MAIL_ERROR_POLICY; + msg_warn("%s: BDAT request from %s exceeds message size limit", + state->queue_id ? state->queue_id : "NOQUEUE", + state->namaddr); + return skip_bdat(state, chunk_size, final_chunk, + "552 5.3.4 Chunk exceeds message size limit"); + } + + /* + * One level of indirection to choose between normal or proxied + * operation. We want to avoid massive code duplication within tons of + * if-else clauses. TODO: store this in its own data structure, or in + * SMTPD_STATE. + */ + proxy = state->proxy; + if (proxy) { + out_stream = proxy->stream; + out_record = proxy->rec_put; + out_fprintf = proxy->rec_fprintf; + out_error = CLEANUP_STAT_PROXY; + } else { + out_stream = state->cleanup; + out_record = rec_put; + out_fprintf = rec_fprintf; + out_error = CLEANUP_STAT_WRITE; + } + if (!SMTPD_PROCESSING_BDAT(state)) { + common_pre_message_handling(state, out_record, out_fprintf, + out_stream, out_error); + if (state->bdat_get_buffer == 0) + state->bdat_get_buffer = vstring_alloc(VSTREAM_BUFSIZE); + else + VSTRING_RESET(state->bdat_get_buffer); + state->bdat_prev_rec_type = 0; + } + state->bdat_state = SMTPD_BDAT_STAT_OK; + state->where = SMTPD_AFTER_BDAT; + + /* + * Copy the message content. If the cleanup process has a problem, keep + * reading until the remote stops sending, then complain. Produce typed + * records from the SMTP stream so we can handle data that spans buffers. + */ + + /* + * Instead of reading the entire BDAT chunk into memory, read the chunk + * one fragment at a time. The loops below always make one iteration, to + * avoid code duplication for the "BDAT 0 LAST" case (empty chunk). + */ + done = 0; + do { + + /* + * Do not skip the smtp_fread_buf() call if read_len == 0. We still + * need the side effects which include resetting the buffer write + * position. Skipping the call would invalidate the buffer state. + * + * Caution: smtp_fread_buf() will long jump after EOF or timeout. + */ + if ((read_len = chunk_size - done) > VSTREAM_BUFSIZE) + read_len = VSTREAM_BUFSIZE; + smtp_fread_buf(state->buffer, read_len, state->client); + state->bdat_get_stream = vstream_memreopen( + state->bdat_get_stream, state->buffer, O_RDONLY); + + /* + * Read lines from the fragment. The last line may continue in the + * next fragment, or in the next chunk. + */ + do { + if (smtp_get_noexcept(state->bdat_get_buffer, + state->bdat_get_stream, + var_line_limit, + SMTP_GET_FLAG_APPEND) == '\n') { + /* Stopped at end-of-line. */ + curr_rec_type = REC_TYPE_NORM; + } else if (!vstream_feof(state->bdat_get_stream)) { + /* Stopped at var_line_limit. */ + curr_rec_type = REC_TYPE_CONT; + } else if (VSTRING_LEN(state->bdat_get_buffer) > 0 + && final_chunk && read_len == chunk_size - done) { + /* Stopped at final chunk end; handle missing end-of-line. */ + curr_rec_type = REC_TYPE_NORM; + } else { + /* Stopped at fragment end; empty buffer or not at chunk end. */ + /* Skip the out_record() and VSTRING_RESET() calls below. */ + break; + } + start = vstring_str(state->bdat_get_buffer); + len = VSTRING_LEN(state->bdat_get_buffer); + if (state->err == CLEANUP_STAT_OK) { + if (ENFORCING_SIZE_LIMIT(var_message_limit) + && var_message_limit - state->act_size < len + 2) { + state->err = CLEANUP_STAT_SIZE; + msg_warn("%s: queue file size limit exceeded", + state->queue_id ? state->queue_id : "NOQUEUE"); + } else { + state->act_size += len + 2; + if (*start == '.' && proxy != 0 + && state->bdat_prev_rec_type != REC_TYPE_CONT) + if (out_record(out_stream, REC_TYPE_CONT, ".", 1) < 0) + state->err = out_error; + if (state->err == CLEANUP_STAT_OK + && out_record(out_stream, curr_rec_type, + vstring_str(state->bdat_get_buffer), + VSTRING_LEN(state->bdat_get_buffer)) < 0) + state->err = out_error; + } + } + VSTRING_RESET(state->bdat_get_buffer); + state->bdat_prev_rec_type = curr_rec_type; + } while (!vstream_feof(state->bdat_get_stream)); + done += read_len; + } while (done < chunk_size); + + /* + * Special handling for BDAT LAST (successful or unsuccessful). + */ + if (final_chunk) { + state->where = SMTPD_AFTER_EOM; + return common_post_message_handling(state); + } + + /* + * Unsuccessful non-final BDAT command. common_post_message_handling() + * resets all MAIL transaction state including BDAT state. To avoid + * useless error messages due to pipelined BDAT commands, enter the + * SMTPD_BDAT_STAT_ERROR state to accept BDAT commands and skip BDAT + * payloads. + */ + else if (state->err != CLEANUP_STAT_OK) { + /* NOT: state->where = SMTPD_AFTER_EOM; */ + (void) common_post_message_handling(state); + state->bdat_state = SMTPD_BDAT_STAT_ERROR; + return (-1); + } + + /* + * Successful non-final BDAT command. + */ + else { + smtpd_chat_reply(state, "250 2.0.0 Ok: %ld bytes", (long) chunk_size); + return (0); + } +} + /* rset_cmd - process RSET */ static int rset_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) @@ -3588,7 +4116,7 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) /* * The SMTP standard (RFC 821) disallows unquoted special characters in * the VRFY argument. Common practice violates the standard, however. - * Postfix accomodates common practice where it violates the standard. + * Postfix accommodates common practice where it violates the standard. * * XXX Impedance mismatch! The SMTP command tokenizer preserves quoting, * whereas the recipient restrictions checks expect unquoted (internal) @@ -3648,7 +4176,7 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) state->addr); return (-1); } - if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0 + if (state->milters != 0 && (err = milter_other_event(state->milters)) != 0 && (err[0] == '5' || err[0] == '4')) { state->error_mask |= MAIL_ERROR_POLICY; smtpd_chat_reply(state, "%s", err); @@ -3710,7 +4238,7 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "503 Error: send HELO/EHLO first"); return (-1); } - if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0 + if (state->milters != 0 && (err = milter_other_event(state->milters)) != 0 && (err[0] == '5' || err[0] == '4')) { state->error_mask |= MAIL_ERROR_POLICY; smtpd_chat_reply(state, "%s", err); @@ -3810,7 +4338,6 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) SMTPD_TOKEN *argp; char *raw_value; char *attr_value; - const char *bare_value; char *attr_name; int update_namaddr = 0; int name_status; @@ -3858,11 +4385,6 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) return (-1); } #define STREQ(x,y) (strcasecmp((x), (y)) == 0) -#define UPDATE_STR(s, v) do { \ - const char *_v = (v); \ - if (s) myfree(s); \ - s = (_v) ? mystrdup(_v) : 0; \ - } while(0) /* * Initialize. @@ -3900,6 +4422,12 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) */ printable(attr_value, '?'); +#define UPDATE_STR(s, v) do { \ + const char *_v = (v); \ + if (s) myfree(s); \ + (s) = (_v) ? mystrdup(_v) : 0; \ + } while(0) + /* * NAME=substitute SMTP client hostname (and reverse/forward name, in * case of success). Also updates the client hostname lookup status @@ -3954,24 +4482,19 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) else if (STREQ(attr_name, XCLIENT_ADDR)) { if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) { attr_value = CLIENT_ADDR_UNKNOWN; - bare_value = attr_value; + UPDATE_STR(state->addr, attr_value); + UPDATE_STR(state->rfc_addr, attr_value); } else { - if ((bare_value = valid_mailhost_addr(attr_value, DONT_GRIPE)) == 0) { + neuter(attr_value, NEUTER_CHARACTERS, '?'); + if (normalize_mailhost_addr(attr_value, &state->rfc_addr, + &state->addr, + &state->addr_family) < 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s", XCLIENT_ADDR, attr_value); return (-1); } } - UPDATE_STR(state->addr, bare_value); - UPDATE_STR(state->rfc_addr, attr_value); -#ifdef HAS_IPV6 - if (strncasecmp(attr_value, INET_PROTO_NAME_IPV6 ":", - sizeof(INET_PROTO_NAME_IPV6 ":") - 1) == 0) - state->addr_family = AF_INET6; - else -#endif - state->addr_family = AF_INET; update_namaddr = 1; } @@ -4043,6 +4566,47 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) #endif /* + * DESTADDR=substitute SMTP server network address. + */ + else if (STREQ(attr_name, XCLIENT_DESTADDR)) { + if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) { + attr_value = SERVER_ADDR_UNKNOWN; + UPDATE_STR(state->dest_addr, attr_value); + } else { +#define NO_NORM_RFC_ADDR ((char **) 0) +#define NO_NORM_ADDR_FAMILY ((int *) 0) + neuter(attr_value, NEUTER_CHARACTERS, '?'); + if (normalize_mailhost_addr(attr_value, NO_NORM_RFC_ADDR, + &state->dest_addr, + NO_NORM_ADDR_FAMILY) < 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s", + XCLIENT_DESTADDR, attr_value); + return (-1); + } + } + /* XXX Require same address family as client address. */ + } + + /* + * DESTPORT=substitute SMTP server port number. + */ + else if (STREQ(attr_name, XCLIENT_DESTPORT)) { + if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) { + attr_value = SERVER_PORT_UNKNOWN; + } else { + if (!alldig(attr_value) + || strlen(attr_value) > sizeof("65535") - 1) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s", + XCLIENT_DESTPORT, attr_value); + return (-1); + } + } + UPDATE_STR(state->dest_port, attr_value); + } + + /* * Unknown attribute name. Complain. */ else { @@ -4114,8 +4678,11 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) chat_reset(state, 0); mail_reset(state); rcpt_reset(state); - if (smtpd_milters) - milter_disc_event(smtpd_milters); + if (state->milters) + milter_disc_event(state->milters); + /* Following duplicates the top-level connect/disconnect handler. */ + teardown_milters(state); + setup_milters(state); vstream_longjmp(state->client, SMTP_ERR_NONE); return (0); } @@ -4127,7 +4694,6 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) SMTPD_TOKEN *argp; char *raw_value; char *attr_value; - const char *bare_value; char *attr_name; int updated = 0; static const NAME_CODE xforward_flags[] = { @@ -4243,18 +4809,19 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) case SMTPD_STATE_XFORWARD_ADDR: if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) { attr_value = CLIENT_ADDR_UNKNOWN; - bare_value = attr_value; + UPDATE_STR(state->xforward.addr, attr_value); } else { neuter(attr_value, NEUTER_CHARACTERS, '?'); - if ((bare_value = valid_mailhost_addr(attr_value, DONT_GRIPE)) == 0) { + if (normalize_mailhost_addr(attr_value, + &state->xforward.rfc_addr, + &state->xforward.addr, + NO_NORM_ADDR_FAMILY) < 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s", XFORWARD_ADDR, attr_value); return (-1); } } - UPDATE_STR(state->xforward.addr, bare_value); - UPDATE_STR(state->xforward.rfc_addr, attr_value); break; /* @@ -4356,7 +4923,8 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) * Update the combined name and address when either has changed. Use only * the name when no address is available. */ - if (updated & (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR)) { + if (updated & (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR + | SMTPD_STATE_XFORWARD_PORT)) { if (state->xforward.namaddr) myfree(state->xforward.namaddr); state->xforward.namaddr = @@ -4594,7 +5162,7 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) smtpd_chat_reply(state, "501 5.5.4 Syntax: STARTTLS"); return (-1); } - if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0) { + if (state->milters != 0 && (err = milter_other_event(state->milters)) != 0) { if (err[0] == '5') { state->error_mask |= MAIL_ERROR_POLICY; smtpd_chat_reply(state, "%s", err); @@ -4627,9 +5195,11 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) #define PROXY_OPEN_FLAGS \ (TLS_PROXY_FLAG_ROLE_SERVER | TLS_PROXY_FLAG_SEND_CONTEXT) - state->tlsproxy = tls_proxy_open(var_tlsproxy_service, PROXY_OPEN_FLAGS, - state->client, state->addr, - state->port, var_smtpd_tmout); + state->tlsproxy = + tls_proxy_legacy_open(var_tlsproxy_service, PROXY_OPEN_FLAGS, + state->client, state->addr, + state->port, var_smtpd_tmout, + state->service); if (state->tlsproxy == 0) { state->error_mask |= MAIL_ERROR_SOFTWARE; /* RFC 3207 Section 4. */ @@ -4755,6 +5325,13 @@ typedef struct SMTPD_CMD { int total_count; } SMTPD_CMD; + /* + * Per RFC 2920: "In particular, the commands RSET, MAIL FROM, SEND FROM, + * SOML FROM, SAML FROM, and RCPT TO can all appear anywhere in a pipelined + * command group. The EHLO, DATA, VRFY, EXPN, TURN, QUIT, and NOOP commands + * can only appear as the last command in a group". RFC 3030 allows BDAT + * commands to be pipelined as well. + */ #define SMTPD_CMD_FLAG_LIMIT (1<<0) /* limit usage */ #define SMTPD_CMD_FLAG_PRE_TLS (1<<1) /* allow before STARTTLS */ #define SMTPD_CMD_FLAG_LAST (1<<2) /* last in PIPELINING command group */ @@ -4762,7 +5339,7 @@ typedef struct SMTPD_CMD { 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,}, - {SMTPD_CMD_XCLIENT, xclient_cmd,}, + {SMTPD_CMD_XCLIENT, xclient_cmd, SMTPD_CMD_FLAG_PRE_TLS}, {SMTPD_CMD_XFORWARD, xforward_cmd,}, #ifdef USE_TLS {SMTPD_CMD_STARTTLS, starttls_cmd, SMTPD_CMD_FLAG_PRE_TLS,}, @@ -4777,6 +5354,7 @@ static SMTPD_CMD smtpd_cmd_table[] = { {SMTPD_CMD_MAIL, mail_cmd,}, {SMTPD_CMD_RCPT, rcpt_cmd,}, {SMTPD_CMD_DATA, data_cmd, SMTPD_CMD_FLAG_LAST,}, + {SMTPD_CMD_BDAT, bdat_cmd,}, {SMTPD_CMD_RSET, rset_cmd, SMTPD_CMD_FLAG_LIMIT,}, {SMTPD_CMD_NOOP, noop_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS | SMTPD_CMD_FLAG_LAST,}, {SMTPD_CMD_VRFY, vrfy_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_LAST,}, @@ -4862,12 +5440,13 @@ static void smtpd_proto(SMTPD_STATE *state) case 0: /* - * Reset the per-command counters. + * Don't bother doing anything if some pre-SMTP handshake (haproxy) + * did not work out. */ - for (cmdp = smtpd_cmd_table; /* see below */ ; cmdp++) { - cmdp->success_count = cmdp->total_count = 0; - if (cmdp->name == 0) - break; + if (state->flags & SMTPD_FLAG_HANGUP) { + smtpd_chat_reply(state, "421 4.3.0 %s Server local error", + var_myhostname); + break; } /* @@ -4886,10 +5465,12 @@ static void smtpd_proto(SMTPD_STATE *state) if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode) { #ifdef USE_TLSPROXY /* We garbage-collect the VSTREAM in smtpd_state_reset() */ - state->tlsproxy = tls_proxy_open(var_tlsproxy_service, - PROXY_OPEN_FLAGS, - state->client, state->addr, - state->port, var_smtpd_tmout); + state->tlsproxy = + tls_proxy_legacy_open(var_tlsproxy_service, + PROXY_OPEN_FLAGS, + state->client, state->addr, + state->port, var_smtpd_tmout, + state->service); if (state->tlsproxy == 0) { msg_warn("Wrapper-mode request dropped from %s for service %s." " TLS context initialization failed. For details see" @@ -4995,10 +5576,10 @@ static void smtpd_proto(SMTPD_STATE *state) */ else { err = 0; - if (smtpd_milters != 0 && SMTPD_STAND_ALONE(state) == 0) { - milter_macro_callback(smtpd_milters, smtpd_milter_eval, + if (state->milters != 0) { + milter_macro_callback(state->milters, smtpd_milter_eval, (void *) state); - if ((err = milter_conn_event(smtpd_milters, state->name, + if ((err = milter_conn_event(state->milters, state->name, state->addr, strcmp(state->port, CLIENT_PORT_UNKNOWN) ? state->port : "0", @@ -5124,9 +5705,8 @@ static void smtpd_proto(SMTPD_STATE *state) } /* state->access_denied == 0 || cmdp->action == quit_cmd */ if (cmdp->name == 0) { - if (smtpd_milters != 0 - && SMTPD_STAND_ALONE(state) == 0 - && (err = milter_unknown_event(smtpd_milters, + if (state->milters != 0 + && (err = milter_unknown_event(state->milters, argv[0].strval)) != 0 && (err = check_milter_reply(state, err)) != 0) { smtpd_chat_reply(state, "%s", err); @@ -5205,7 +5785,13 @@ static void smtpd_proto(SMTPD_STATE *state) state->reason, SMTPD_CMD_DATA, /* 2.5 compat */ (long) (state->act_size + vstream_peek(state->client)), state->namaddr); - } else if (strcmp(state->where, SMTPD_AFTER_DOT) + } else if (strcmp(state->where, SMTPD_AFTER_BDAT) == 0) { + msg_info("%s after %s (%lu bytes) from %s", + state->reason, SMTPD_CMD_BDAT, + (long) (state->act_size + VSTRING_LEN(state->buffer) + + VSTRING_LEN(state->bdat_get_buffer)), + state->namaddr); + } else if (strcmp(state->where, SMTPD_AFTER_EOM) || strcmp(state->reason, REASON_LOST_CONNECTION)) { msg_info("%s after %s from %s", state->reason, state->where, state->namaddr); @@ -5231,8 +5817,8 @@ static void smtpd_proto(SMTPD_STATE *state) chat_reset(state, 0); mail_reset(state); rcpt_reset(state); - if (smtpd_milters) - milter_disc_event(smtpd_milters); + if (state->milters) + milter_disc_event(state->milters); } /* smtpd_format_cmd_stats - format per-command statistics */ @@ -5263,6 +5849,20 @@ static char *smtpd_format_cmd_stats(VSTRING *buf) } /* + * Reset the per-command counters. + * + * Fix 20190621: the command counter resetting code was moved from the SMTP + * protocol handler to this place, because the protocol handler was never + * called after HaProxy handshake error, causing stale numbers to be + * logged. + */ + for (cmdp = smtpd_cmd_table; /* see below */ ; cmdp++) { + cmdp->success_count = cmdp->total_count = 0; + if (cmdp->name == 0) + break; + } + + /* * Log total numbers, so that logfile analyzers will see something even * if the above loop produced no output. When no commands were received * log "0/0" to simplify the identification of abnormal sessions: any @@ -5274,6 +5874,61 @@ static char *smtpd_format_cmd_stats(VSTRING *buf) return (lowercase(STR(buf))); } +/* setup_milters - set up Milters after a connection is established */ + +static void setup_milters(SMTPD_STATE *state) +{ + const char *milter_string; + + /* + * Postcondition: either state->milters is set, or the + * INPUT_TRANSP_MILTER flag is passed down-stream. + */ + if (SMTPD_STAND_ALONE(state) == 0 + && (smtpd_input_transp_mask & INPUT_TRANSP_MILTER) == 0 + && ((smtpd_milter_maps + && (milter_string = + maps_find(smtpd_milter_maps, state->addr, 0)) != 0) + || *(milter_string = var_smtpd_milters) != 0) + && strcasecmp(milter_string, SMTPD_MILTERS_DISABLE) != 0) { + state->milters = milter_create(milter_string, + var_milt_conn_time, + var_milt_cmd_time, + var_milt_msg_time, + var_milt_protocol, + var_milt_def_action, + var_milt_conn_macros, + var_milt_helo_macros, + var_milt_mail_macros, + var_milt_rcpt_macros, + var_milt_data_macros, + var_milt_eoh_macros, + var_milt_eod_macros, + var_milt_unk_macros, + var_milt_macro_deflts); + } + + /* + * Safety: disable non_smtpd_milters when not sending our own mail filter + * list. Otherwise the next stage could handle this message as a local + * submission. + */ + if (state->milters == 0) + smtpd_input_transp_mask |= INPUT_TRANSP_MILTER; +} + +/* teardown_milters - release resources */ + +static void teardown_milters(SMTPD_STATE *state) +{ + if (state->milters) { + milter_free(state->milters); + state->milters = 0; + } + smtpd_input_transp_mask = + input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); +} + /* smtpd_service - service one client */ @@ -5336,10 +5991,14 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv) debug_peer_check(state.name, state.addr); /* + * Set up Milters, or disable Milters down-stream. + */ + setup_milters(&state); /* duplicates xclient_cmd */ + + /* * Provide the SMTP service. */ - if ((state.flags & SMTPD_FLAG_HANGUP) == 0) - smtpd_proto(&state); + smtpd_proto(&state); /* * After the client has gone away, clean up whatever we have set up at @@ -5347,6 +6006,7 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv) */ msg_info("disconnect from %s%s", state.namaddr, smtpd_format_cmd_stats(state.buffer)); + teardown_milters(&state); /* duplicates xclient_cmd */ smtpd_state_reset(&state); debug_peer_restore(); } @@ -5496,16 +6156,33 @@ 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 || *var_smtpd_tls_dcert_file || *var_smtpd_tls_eccert_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; + + if (*var_smtpd_tls_chain_files != 0) { + if (!have_server_cert) + have_server_cert = 1; + else + msg_warn("Both %s and one or more of the legacy " + " %s, %s or %s are non-empty; the legacy " + " parameters will be ignored", + VAR_SMTPD_TLS_CHAIN_FILES, + VAR_SMTPD_TLS_CERT_FILE, + VAR_SMTPD_TLS_ECCERT_FILE, + VAR_SMTPD_TLS_DCERT_FILE); + } /* Some TLS configuration errors are not show stoppers. */ if (!have_server_cert && require_server_cert) msg_warn("Need a server cert to request client certs"); if (!var_smtpd_enforce_tls && var_smtpd_tls_req_ccert) msg_warn("Can't require client certs unless TLS is required"); /* After a show-stopper error, reply with 454 to STARTTLS. */ - if (have_server_cert || (no_server_cert_ok && !require_server_cert)) + if (have_server_cert + || (no_server_cert_ok && !require_server_cert)) { + + tls_pre_jail_init(TLS_ROLE_SERVER); /* * Large parameter lists are error-prone, so we emulate a @@ -5519,6 +6196,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv) verifydepth = var_smtpd_tls_ccert_vd, cache_type = TLS_MGR_SCACHE_SMTPD, set_sessid = var_smtpd_tls_set_sessid, + chain_files = var_smtpd_tls_chain_files, cert_file = cert_file, key_file = var_smtpd_tls_key_file, dcert_file = var_smtpd_tls_dcert_file, @@ -5537,8 +6215,9 @@ static void pre_jail_init(char *unused_name, char **unused_argv) var_smtpd_tls_proto, ask_ccert = ask_client_cert, mdalg = var_smtpd_tls_fpt_dgst); - else + } else { msg_warn("No server certs available. TLS won't be enabled"); + } #endif /* USE_TLSPROXY */ #else msg_warn("TLS has been selected, but TLS support is not compiled in"); @@ -5560,11 +6239,25 @@ static void pre_jail_init(char *unused_name, char **unused_argv) DICT_FLAG_LOCK); /* + * Per-client Milter support. + */ + if (*var_smtpd_milter_maps) + smtpd_milter_maps = maps_create(VAR_SMTPD_MILTER_MAPS, + var_smtpd_milter_maps, + DICT_FLAG_LOCK); + + /* * DNS reply filter. */ if (*var_smtpd_dns_re_filter) dns_rr_filter_compile(VAR_SMTPD_DNS_RE_FILTER, var_smtpd_dns_re_filter); + + /* + * Reject footer. + */ + if (*var_smtpd_rej_ftr_maps) + smtpd_chat_pre_jail_init(); } /* post_jail_init - post-jail initialization */ @@ -5589,42 +6282,13 @@ static void post_jail_init(char *unused_name, char **unused_argv) smtpd_proxy_parse_opts(VAR_SMTPD_PROXY_OPTS, var_smtpd_proxy_opts); /* - * Sendmail mail filters. - * - * XXX Should not do this when running in stand-alone mode. But that test - * looks at VSTREAM_IN which is not available at this point. - * - * XXX Disable non_smtpd_milters when not sending our own mail filter list. - */ - if ((smtpd_input_transp_mask & INPUT_TRANSP_MILTER) == 0) { - if (*var_smtpd_milters) - smtpd_milters = milter_create(var_smtpd_milters, - var_milt_conn_time, - var_milt_cmd_time, - var_milt_msg_time, - var_milt_protocol, - var_milt_def_action, - var_milt_conn_macros, - var_milt_helo_macros, - var_milt_mail_macros, - var_milt_rcpt_macros, - var_milt_data_macros, - var_milt_eoh_macros, - var_milt_eod_macros, - var_milt_unk_macros, - var_milt_macro_deflts); - else - smtpd_input_transp_mask |= INPUT_TRANSP_MILTER; - } - - /* * Sanity checks. The queue_minfree value should be at least as large as * (process_limit * message_size_limit) but that is unpractical, so we * arbitrarily pick a small multiple of the per-message size limit. This * helps to avoid many unneeded (re)transmissions. */ - if (var_queue_minfree > 0 - && var_message_limit > 0 + if (ENFORCING_SIZE_LIMIT(var_queue_minfree) + && ENFORCING_SIZE_LIMIT(var_message_limit) && var_queue_minfree / 1.5 < var_message_limit) msg_warn("%s(%lu) should be at least 1.5*%s(%lu)", VAR_QUEUE_MINFREE, (unsigned long) var_queue_minfree, @@ -5654,7 +6318,6 @@ int main(int argc, char **argv) }; static const CONFIG_INT_TABLE int_table[] = { VAR_SMTPD_RCPT_LIMIT, DEF_SMTPD_RCPT_LIMIT, &var_smtpd_rcpt_limit, 1, 0, - VAR_QUEUE_MINFREE, DEF_QUEUE_MINFREE, &var_queue_minfree, 0, 0, VAR_UNK_CLIENT_CODE, DEF_UNK_CLIENT_CODE, &var_unk_client_code, 0, 0, VAR_BAD_NAME_CODE, DEF_BAD_NAME_CODE, &var_bad_name_code, 0, 0, VAR_UNK_NAME_CODE, DEF_UNK_NAME_CODE, &var_unk_name_code, 0, 0, @@ -5687,10 +6350,15 @@ int main(int argc, char **argv) #ifdef USE_TLS VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0, #endif + VAR_SMTPD_SASL_RESP_LIMIT, DEF_SMTPD_SASL_RESP_LIMIT, &var_smtpd_sasl_resp_limit, DEF_SMTPD_SASL_RESP_LIMIT, 0, VAR_SMTPD_POLICY_REQ_LIMIT, DEF_SMTPD_POLICY_REQ_LIMIT, &var_smtpd_policy_req_limit, 0, 0, VAR_SMTPD_POLICY_TRY_LIMIT, DEF_SMTPD_POLICY_TRY_LIMIT, &var_smtpd_policy_try_limit, 1, 0, 0, }; + static const CONFIG_LONG_TABLE long_table[] = { + VAR_QUEUE_MINFREE, DEF_QUEUE_MINFREE, &var_queue_minfree, 0, 0, + 0, + }; static const CONFIG_TIME_TABLE time_table[] = { VAR_SMTPD_TMOUT, DEF_SMTPD_TMOUT, &var_smtpd_tmout, 1, 0, VAR_SMTPD_ERR_SLEEP, DEF_SMTPD_ERR_SLEEP, &var_smtpd_err_sleep, 0, 0, @@ -5791,6 +6459,7 @@ int main(int argc, char **argv) #ifdef USE_TLS VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 0, 0, VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0, + VAR_SMTPD_TLS_CHAIN_FILES, DEF_SMTPD_TLS_CHAIN_FILES, &var_smtpd_tls_chain_files, 0, 0, VAR_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CERT_FILE, &var_smtpd_tls_cert_file, 0, 0, VAR_SMTPD_TLS_KEY_FILE, DEF_SMTPD_TLS_KEY_FILE, &var_smtpd_tls_key_file, 0, 0, VAR_SMTPD_TLS_DCERT_FILE, DEF_SMTPD_TLS_DCERT_FILE, &var_smtpd_tls_dcert_file, 0, 0, @@ -5827,6 +6496,7 @@ int main(int argc, char **argv) VAR_MILT_DAEMON_NAME, DEF_MILT_DAEMON_NAME, &var_milt_daemon_name, 1, 0, VAR_MILT_V, DEF_MILT_V, &var_milt_v, 1, 0, VAR_MILT_MACRO_DEFLTS, DEF_MILT_MACRO_DEFLTS, &var_milt_macro_deflts, 0, 0, + VAR_SMTPD_MILTER_MAPS, DEF_SMTPD_MILTER_MAPS, &var_smtpd_milter_maps, 0, 0, VAR_STRESS, DEF_STRESS, &var_stress, 0, 0, VAR_UNV_FROM_WHY, DEF_UNV_FROM_WHY, &var_unv_from_why, 0, 0, VAR_UNV_RCPT_WHY, DEF_UNV_RCPT_WHY, &var_unv_rcpt_why, 0, 0, @@ -5844,6 +6514,7 @@ int main(int argc, char **argv) VAR_SMTPD_POLICY_DEF_ACTION, DEF_SMTPD_POLICY_DEF_ACTION, &var_smtpd_policy_def_action, 1, 0, VAR_SMTPD_POLICY_CONTEXT, DEF_SMTPD_POLICY_CONTEXT, &var_smtpd_policy_context, 0, 0, VAR_SMTPD_DNS_RE_FILTER, DEF_SMTPD_DNS_RE_FILTER, &var_smtpd_dns_re_filter, 0, 0, + VAR_SMTPD_REJ_FTR_MAPS, DEF_SMTPD_REJ_FTR_MAPS, &var_smtpd_rej_ftr_maps, 0, 0, 0, }; static const CONFIG_RAW_TABLE raw_table[] = { @@ -5864,6 +6535,7 @@ int main(int argc, char **argv) single_server_main(argc, argv, smtpd_service, CA_MAIL_SERVER_NINT_TABLE(nint_table), CA_MAIL_SERVER_INT_TABLE(int_table), + CA_MAIL_SERVER_LONG_TABLE(long_table), CA_MAIL_SERVER_STR_TABLE(str_table), CA_MAIL_SERVER_RAW_TABLE(raw_table), CA_MAIL_SERVER_BOOL_TABLE(bool_table), diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd.h b/external/ibm-public/postfix/dist/src/smtpd/smtpd.h index 5e49fa97015..2ab622a6c7d 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd.h +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd.h,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -81,9 +81,12 @@ typedef struct { char *namaddr; /* name[address]:port */ char *rfc_addr; /* address for RFC 2821 */ int addr_family; /* address family */ - char *dest_addr; /* for Dovecot AUTH */ + char *dest_addr; /* Dovecot AUTH, Milter {daemon_addr} */ + char *dest_port; /* Milter {daemon_port} */ struct sockaddr_storage sockaddr; /* binary client endpoint */ SOCKADDR_SIZE sockaddr_len; /* binary client endpoint */ + struct sockaddr_storage dest_sockaddr; /* binary local endpoint */ + SOCKADDR_SIZE dest_sockaddr_len; /* binary local endpoint */ int name_status; /* 2=ok 4=soft 5=hard 6=forged */ int reverse_name_status; /* 2=ok 4=soft 5=hard */ int conn_count; /* connections from this client */ @@ -139,7 +142,7 @@ typedef struct { int discard; /* discard message */ char *saved_filter; /* postponed filter action */ char *saved_redirect; /* postponed redirect action */ - char *saved_bcc; /* postponed bcc action */ + ARGV *saved_bcc; /* postponed bcc action */ int saved_flags; /* postponed hold/discard */ #ifdef DELAY_ACTION int saved_delay; /* postponed deferred delay */ @@ -181,22 +184,35 @@ typedef struct { const char **milter_argv; /* SMTP command vector */ ssize_t milter_argc; /* SMTP command vector */ const char *milter_reject_text; /* input to call-back from Milter */ + MILTERS *milters; /* Milter initialization status. */ /* * EHLO temporary space. */ VSTRING *ehlo_buf; ARGV *ehlo_argv; + + /* + * BDAT processing state. + */ +#define SMTPD_BDAT_STAT_NONE 0 /* not processing BDAT */ +#define SMTPD_BDAT_STAT_OK 1 /* accepting BDAT chunks */ +#define SMTPD_BDAT_STAT_ERROR 2 /* skipping BDAT chunks */ + int bdat_state; /* see above */ + VSTREAM *bdat_get_stream; /* memory stream from BDAT chunk */ + VSTRING *bdat_get_buffer; /* read from memory stream */ + int bdat_prev_rec_type; } SMTPD_STATE; #define SMTPD_FLAG_HANGUP (1<<0) /* 421/521 disconnect */ #define SMTPD_FLAG_ILL_PIPELINING (1<<1) /* inappropriate pipelining */ #define SMTPD_FLAG_AUTH_USED (1<<2) /* don't reuse SASL state */ #define SMTPD_FLAG_SMTPUTF8 (1<<3) /* RFC 6531/2 transaction */ +#define SMTPD_FLAG_NEED_MILTER_ABORT (1<<4) /* undo milter_mail_event() */ /* Security: don't reset SMTPD_FLAG_AUTH_USED. */ #define SMTPD_MASK_MAIL_KEEP \ - ~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */ + ~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */ #define SMTPD_STATE_XFORWARD_INIT (1<<0) /* xforward preset done */ #define SMTPD_STATE_XFORWARD_NAME (1<<1) /* client name received */ @@ -221,7 +237,8 @@ extern void smtpd_state_reset(SMTPD_STATE *); */ #define SMTPD_AFTER_CONNECT "CONNECT" #define SMTPD_AFTER_DATA "DATA content" -#define SMTPD_AFTER_DOT "END-OF-MESSAGE" +#define SMTPD_AFTER_BDAT "BDAT content" +#define SMTPD_AFTER_EOM "END-OF-MESSAGE" /* * Other stages. These are sometimes used to change the way information is @@ -234,7 +251,8 @@ extern void smtpd_state_reset(SMTPD_STATE *); #define SMTPD_CMD_MAIL "MAIL" #define SMTPD_CMD_RCPT "RCPT" #define SMTPD_CMD_DATA "DATA" -#define SMTPD_CMD_EOD SMTPD_AFTER_DOT /* XXX Was: END-OF-DATA */ +#define SMTPD_CMD_BDAT "BDAT" +#define SMTPD_CMD_EOD SMTPD_AFTER_EOM /* XXX Was: END-OF-DATA */ #define SMTPD_CMD_RSET "RSET" #define SMTPD_CMD_NOOP "NOOP" #define SMTPD_CMD_VRFY "VRFY" @@ -281,6 +299,11 @@ extern void smtpd_state_reset(SMTPD_STATE *); #define CLIENT_DOMAIN_UNKNOWN 0 #define CLIENT_LOGIN_UNKNOWN 0 +#define SERVER_ATTR_UNKNOWN "unknown" + +#define SERVER_ADDR_UNKNOWN SERVER_ATTR_UNKNOWN +#define SERVER_PORT_UNKNOWN SERVER_ATTR_UNKNOWN + #define IS_AVAIL_CLIENT_ATTR(v) ((v) && strcmp((v), CLIENT_ATTR_UNKNOWN)) #define IS_AVAIL_CLIENT_NAME(v) IS_AVAIL_CLIENT_ATTR(v) @@ -315,11 +338,18 @@ extern void smtpd_state_reset(SMTPD_STATE *); #define SMTPD_IN_MAIL_TRANSACTION(state) ((state)->sender != 0) /* + * Are we processing BDAT requests? + */ +#define SMTPD_PROCESSING_BDAT(state) \ + ((state)->bdat_state != SMTPD_BDAT_STAT_NONE) + + /* * SMTPD peer information lookup. */ extern void smtpd_peer_init(SMTPD_STATE *state); extern void smtpd_peer_reset(SMTPD_STATE *state); -extern int smtpd_peer_from_haproxy(SMTPD_STATE *state); +extern void smtpd_peer_from_default(SMTPD_STATE *); +extern int smtpd_peer_from_haproxy(SMTPD_STATE *); #define SMTPD_PEER_CODE_OK 2 #define SMTPD_PEER_CODE_TEMP 4 @@ -399,6 +429,11 @@ extern double smtpd_space_multf; /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* TLS support originally by: /* Lutz Jaenicke /* BTU Cottbus diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.c index 5a4db7ecf65..715605ff253 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_chat.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_chat.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -9,6 +9,12 @@ /* #include <smtpd.h> /* #include <smtpd_chat.h> /* +/* void smtpd_chat_pre_jail_init(void) +/* +/* int smtpd_chat_query_limit(state, limit) +/* SMTPD_STATE *state; +/* int limit; +/* /* void smtpd_chat_query(state) /* SMTPD_STATE *state; /* @@ -25,12 +31,19 @@ /* This module implements SMTP server support for request/reply /* conversations, and maintains a limited SMTP transaction log. /* +/* smtpd_chat_pre_jail_init() performs one-time initialization. +/* +/* smtpd_chat_query_limit() reads a line from the client that is +/* at most "limit" bytes long. A copy is appended to the SMTP +/* transaction log. The return value is non-zero for a complete +/* line or else zero if the length limit was exceeded. +/* /* smtpd_chat_query() receives a client request and appends a copy /* to the SMTP transaction log. /* /* smtpd_chat_reply() formats a server reply, sends it to the /* client, and appends a copy to the SMTP transaction log. -/* When soft_bounce is enabled, all 5xx (reject) reponses are +/* When soft_bounce is enabled, all 5xx (reject) responses are /* replaced by 4xx (try again). In case of a 421 reply the /* SMTPD_FLAG_HANGUP flag is set for orderly disconnect. /* @@ -54,6 +67,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -83,6 +101,7 @@ #include <mail_proto.h> #include <mail_params.h> #include <mail_addr.h> +#include <maps.h> #include <post_mail.h> #include <mail_error.h> #include <smtp_reply_footer.h> @@ -93,9 +112,32 @@ #include "smtpd_expand.h" #include "smtpd_chat.h" + /* + * Reject footer. + */ +static MAPS *smtpd_rej_ftr_maps; + #define STR vstring_str #define LEN VSTRING_LEN +/* smtpd_chat_pre_jail_init - initialize */ + +void smtpd_chat_pre_jail_init(void) +{ + static int init_count = 0; + + if (init_count++ != 0) + msg_panic("smtpd_chat_pre_jail_init: multiple calls"); + + /* + * SMTP server reject footer. + */ + if (*var_smtpd_rej_ftr_maps) + smtpd_rej_ftr_maps = maps_create(VAR_SMTPD_REJ_FTR_MAPS, + var_smtpd_rej_ftr_maps, + DICT_FLAG_LOCK); +} + /* smtp_chat_reset - reset SMTP transaction log */ void smtpd_chat_reset(SMTPD_STATE *state) @@ -125,7 +167,7 @@ static void smtp_chat_append(SMTPD_STATE *state, char *direction, /* smtpd_chat_query - receive and record an SMTP request */ -void smtpd_chat_query(SMTPD_STATE *state) +int smtpd_chat_query_limit(SMTPD_STATE *state, int limit) { int last_char; @@ -133,16 +175,17 @@ void smtpd_chat_query(SMTPD_STATE *state) * We can't parse or store input that exceeds var_line_limit, so we skip * over it to avoid loss of synchronization. */ - last_char = smtp_get(state->buffer, state->client, var_line_limit, + last_char = smtp_get(state->buffer, state->client, limit, SMTP_GET_FLAG_SKIP); smtp_chat_append(state, "In: ", STR(state->buffer)); if (last_char != '\n') msg_warn("%s: request longer than %d: %.30s...", - state->namaddr, var_line_limit, + state->namaddr, limit, printable(STR(state->buffer), '?')); if (msg_verbose) msg_info("< %s: %s", state->namaddr, STR(state->buffer)); + return (last_char == '\n'); } /* smtpd_chat_reply - format, send and record an SMTP response */ @@ -150,10 +193,21 @@ void smtpd_chat_query(SMTPD_STATE *state) void smtpd_chat_reply(SMTPD_STATE *state, const char *format,...) { va_list ap; + + va_start(ap, format); + vsmtpd_chat_reply(state, format, ap); + va_end(ap); +} + +/* vsmtpd_chat_reply - format, send and record an SMTP response */ + +void vsmtpd_chat_reply(SMTPD_STATE *state, const char *format, va_list ap) +{ int delay = 0; char *cp; char *next; char *end; + const char *footer; /* * Slow down clients that make errors. Sleep-on-anything slows down @@ -162,15 +216,14 @@ void smtpd_chat_reply(SMTPD_STATE *state, const char *format,...) if (state->error_count >= var_smtpd_soft_erlim) sleep(delay = var_smtpd_err_sleep); - va_start(ap, format); vstring_vsprintf(state->buffer, format, ap); - va_end(ap); - if (*var_smtpd_rej_footer - && (*(cp = STR(state->buffer)) == '4' || *cp == '5')) - smtp_reply_footer(state->buffer, 0, var_smtpd_rej_footer, - STR(smtpd_expand_filter), smtpd_expand_lookup, - (void *) state); + if ((*(cp = STR(state->buffer)) == '4' || *cp == '5') + && ((smtpd_rej_ftr_maps != 0 + && (footer = maps_find(smtpd_rej_ftr_maps, cp, 0)) != 0) + || *(footer = var_smtpd_rej_footer) != 0)) + smtp_reply_footer(state->buffer, 0, footer, STR(smtpd_expand_filter), + smtpd_expand_lookup, (void *) state); /* All 5xx replies must have a 5.xx.xx detail code. */ for (cp = STR(state->buffer), end = cp + strlen(STR(state->buffer));;) { diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.h b/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.h index 9bb30774e0a..ad677648f90 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.h +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_chat.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_chat.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_chat.h,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -12,13 +12,24 @@ /* .nf /* + * Global library. + */ +#include <mail_params.h> + + /* * External interface. */ +extern void smtpd_chat_pre_jail_init(void); extern void smtpd_chat_reset(SMTPD_STATE *); +extern int smtpd_chat_query_limit(SMTPD_STATE *, int); extern void smtpd_chat_query(SMTPD_STATE *); extern void PRINTFLIKE(2, 3) smtpd_chat_reply(SMTPD_STATE *, const char *,...); +extern void vsmtpd_chat_reply(SMTPD_STATE *, const char *, va_list); extern void smtpd_chat_notify(SMTPD_STATE *); +#define smtpd_chat_query(state) \ + ((void) smtpd_chat_query_limit((state), var_line_limit)) + /* LICENSE /* .ad /* .fi @@ -28,4 +39,9 @@ extern void smtpd_chat_notify(SMTPD_STATE *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.c index 480375e2a0a..74553750f90 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_check.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_check.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -165,6 +165,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* TLS support originally by: /* Lutz Jaenicke /* BTU Cottbus @@ -213,6 +218,7 @@ #include <valid_utf8_hostname.h> #include <midna_domain.h> #include <mynetworks.h> +#include <name_code.h> /* DNS library. */ @@ -247,6 +253,8 @@ #include <xtext.h> #include <smtp_stream.h> #include <attr_override.h> +#include <map_search.h> +#include <info_log_addr_form.h> /* Application-specific. */ @@ -332,6 +340,7 @@ static ARGV *client_restrctions; static ARGV *helo_restrctions; static ARGV *mail_restrctions; static ARGV *relay_restrctions; +static ARGV *fake_relay_restrctions; static ARGV *rcpt_restrctions; static ARGV *etrn_restrctions; static ARGV *data_restrctions; @@ -339,6 +348,7 @@ static ARGV *eod_restrictions; static HTABLE *smtpd_rest_classes; static HTABLE *policy_clnt_table; +static HTABLE *map_command_table; static ARGV *local_rewrite_clients; @@ -509,6 +519,35 @@ static ATTR_OVER_STR str_table[] = { #define smtpd_policy_def_action_offset 0 #define smtpd_policy_context_offset 1 + /* + * Search order names must be distinct, non-empty, and non-null. + */ +#define SMTPD_ACL_SEARCH_NAME_CERT_FPRINT "cert_fingerprint" +#define SMTPD_ACL_SEARCH_NAME_PKEY_FPRINT "pubkey_fingerprint" +#define SMTPD_ACL_SEARCH_NAME_CERT_ISSUER_CN "issuer_cn" +#define SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT_CN "subject_cn" + + /* + * Search order tokens must be distinct, and 1..126 inclusive, so that they + * can be stored in a character string without concerns about signed versus + * unsigned. Code 127 is reserved by map_search(3). + */ +#define SMTPD_ACL_SEARCH_CODE_CERT_FPRINT 1 +#define SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT 2 +#define SMTPD_ACL_SEARCH_CODE_CERT_ISSUER_CN 3 +#define SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT_CN 4 + + /* + * Mapping from search-list names and to search-list codes. + */ +static const NAME_CODE search_actions[] = { + SMTPD_ACL_SEARCH_NAME_CERT_FPRINT, SMTPD_ACL_SEARCH_CODE_CERT_FPRINT, + SMTPD_ACL_SEARCH_NAME_PKEY_FPRINT, SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT, + SMTPD_ACL_SEARCH_NAME_CERT_ISSUER_CN, SMTPD_ACL_SEARCH_CODE_CERT_ISSUER_CN, + SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT_CN, SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT_CN, + 0, MAP_SEARCH_CODE_UNKNOWN, +}; + /* policy_client_register - register policy service endpoint */ static void policy_client_register(const char *name) @@ -594,6 +633,23 @@ static void policy_client_register(const char *name) } } +/* command_map_register - register access table for maps lookup */ + +static void command_map_register(const char *name) +{ + MAPS *maps; + + if (map_command_table == 0) + map_command_table = htable_create(1); + + if (htable_find(map_command_table, name) == 0) { + maps = maps_create(name, name, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX + | DICT_FLAG_UTF8_REQUEST); + (void) htable_enter(map_command_table, name, (void *) maps); + } +} + /* smtpd_check_parse - pre-parse restrictions */ static ARGV *smtpd_check_parse(int flags, const char *checks) @@ -603,6 +659,7 @@ static ARGV *smtpd_check_parse(int flags, const char *checks) char *bp = saved_checks; char *name; char *last = 0; + const MAP_SEARCH *map_search; /* * Pre-parse the restriction list, and open any dictionaries that we @@ -616,13 +673,12 @@ static ARGV *smtpd_check_parse(int flags, const char *checks) while ((name = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { argv_add(argv, name, (char *) 0); if ((flags & SMTPD_CHECK_PARSE_POLICY) - && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0) + && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0) { policy_client_register(name); - else if ((flags & SMTPD_CHECK_PARSE_MAPS) - && strchr(name, ':') && dict_handle(name) == 0) { - dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK - | DICT_FLAG_FOLD_FIX - | DICT_FLAG_UTF8_REQUEST)); + } else if ((flags & SMTPD_CHECK_PARSE_MAPS) + && (*name == *CHARS_BRACE || strchr(name, ':') != 0)) { + if ((map_search = map_search_create(name)) != 0) + command_map_register(map_search->map_type_name); } last = name; } @@ -635,6 +691,8 @@ static ARGV *smtpd_check_parse(int flags, const char *checks) return (argv); } +#ifndef TEST + /* has_required - make sure required restriction is present */ static int has_required(ARGV *restrictions, const char **required) @@ -693,6 +751,8 @@ static void fail_required(const char *name, const char **required) name, STR(example)); } +#endif + /* smtpd_check_init - initialize once during process lifetime */ void smtpd_check_init(void) @@ -701,6 +761,8 @@ void smtpd_check_init(void) const char *name; const char *value; char *cp; + +#ifndef TEST static const char *rcpt_required[] = { REJECT_UNAUTH_DEST, DEFER_UNAUTH_DEST, @@ -710,6 +772,8 @@ void smtpd_check_init(void) CHECK_RELAY_DOMAINS, 0, }; + +#endif static NAME_CODE tempfail_actions[] = { DEFER_ALL, DEFER_ALL_ACT, DEFER_IF_PERMIT, DEFER_IF_PERMIT_ACT, @@ -808,6 +872,12 @@ void smtpd_check_init(void) rbl_byte_pageout, (void *) 0); /* + * Initialize access map search list support before parsing restriction + * lists. + */ + map_search_init(search_actions); + + /* * Pre-parse the restriction lists. At the same time, pre-open tables * before going to jail. */ @@ -819,6 +889,9 @@ void smtpd_check_init(void) var_mail_checks); relay_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, var_relay_checks); + if (warn_compat_break_relay_restrictions) + fake_relay_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, + FAKE_RELAY_CHECKS); rcpt_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, var_rcpt_checks); etrn_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, @@ -925,9 +998,11 @@ static void log_whatsup(SMTPD_STATE *state, const char *whatsup, state->queue_id ? state->queue_id : "NOQUEUE", whatsup, state->where, state->namaddr, text); if (state->sender) - vstring_sprintf_append(buf, " from=<%s>", state->sender); + vstring_sprintf_append(buf, " from=<%s>", + info_log_addr_form_sender(state->sender)); if (state->recipient) - vstring_sprintf_append(buf, " to=<%s>", state->recipient); + vstring_sprintf_append(buf, " to=<%s>", + info_log_addr_form_recipient(state->recipient)); if (state->protocol) vstring_sprintf_append(buf, " proto=%s", state->protocol); if (state->helo_name) @@ -999,10 +1074,11 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class, /* * Do not reject mail if we were asked to warn only. However, - * configuration errors cannot be converted into warnings. + * configuration/software/data errors cannot be converted into warnings. */ if (state->warn_if_reject && error_class != MAIL_ERROR_SOFTWARE - && error_class != MAIL_ERROR_RESOURCE) { + && error_class != MAIL_ERROR_RESOURCE + && error_class != MAIL_ERROR_DATA) { warn_if_reject = 1; whatsup = "reject_warning"; } else { @@ -1553,6 +1629,10 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) if (msg_verbose) msg_info("relay_clientcerts: No match for fingerprint '%s', " "pkey fingerprint %s", prints[0], prints[1]); + } else if (!var_smtpd_tls_ask_ccert) { + msg_warn("%s is requested, but \"%s = no\"", permit_all_certs ? + PERMIT_TLS_ALL_CLIENTCERTS : PERMIT_TLS_CLIENTCERTS, + VAR_SMTPD_TLS_ACERT); } #endif return (SMTPD_CHECK_DUNNO); @@ -2521,7 +2601,9 @@ static int check_table_result(SMTPD_STATE *state, const char *table, reply_name, reply_class, cmd_text); log_whatsup(state, "bcc", STR(error_text)); #ifndef TEST - UPDATE_STRING(state->saved_bcc, cmd_text); + if (state->saved_bcc == 0) + state->saved_bcc = argv_alloc(1); + argv_add(state->saved_bcc, cmd_text, (char *) 0); #endif return (SMTPD_CHECK_DUNNO); } @@ -2565,7 +2647,7 @@ static int check_table_result(SMTPD_STATE *state, const char *table, if (not_in_client_helo(state, table, "PREPEND", reply_class) == 0) return (SMTPD_CHECK_DUNNO); #endif - if (strcmp(state->where, SMTPD_AFTER_DOT) == 0) { + if (strcmp(state->where, SMTPD_AFTER_EOM) == 0) { msg_warn("access table %s: action PREPEND must be used before %s", table, VAR_EOD_CHECKS); return (SMTPD_CHECK_DUNNO); @@ -2684,7 +2766,7 @@ static int check_access(SMTPD_STATE *state, const char *table, const char *name, { const char *myname = "check_access"; const char *value; - DICT *dict; + MAPS *maps; #define CHK_ACCESS_RETURN(x,y) \ { *found = y; return(x); } @@ -2696,25 +2778,23 @@ static int check_access(SMTPD_STATE *state, const char *table, const char *name, if (msg_verbose) msg_info("%s: %s", myname, name); - if ((dict = dict_handle(table)) == 0) { + if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) { msg_warn("%s: unexpected dictionary: %s", myname, table); value = "451 4.3.5 Server configuration error"; CHK_ACCESS_RETURN(check_table_result(state, table, value, name, reply_name, reply_class, def_acl), FOUND); } - if (flags == 0 || (flags & dict->flags) != 0) { - if ((value = dict_get(dict, name)) != 0) - CHK_ACCESS_RETURN(check_table_result(state, table, value, name, - reply_name, reply_class, - def_acl), FOUND); - if (dict->error != 0) { - msg_warn("%s: table lookup problem", table); - value = "451 4.3.5 Server configuration error"; - CHK_ACCESS_RETURN(check_table_result(state, table, value, name, - reply_name, reply_class, - def_acl), FOUND); - } + if ((value = maps_find(maps, name, flags)) != 0) + CHK_ACCESS_RETURN(check_table_result(state, table, value, name, + reply_name, reply_class, + def_acl), FOUND); + if (maps->error != 0) { + /* Warning is already logged. */ + value = "451 4.3.5 Server configuration error"; + CHK_ACCESS_RETURN(check_table_result(state, table, value, name, + reply_name, reply_class, + def_acl), FOUND); } CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO, MISSED); } @@ -2731,7 +2811,7 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, const char *name; const char *next; const char *value; - DICT *dict; + MAPS *maps; int maybe_numerical = 1; if (msg_verbose) @@ -2743,10 +2823,12 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, * Helo names can end in ".". The test below avoids lookups of the empty * key, because Berkeley DB cannot deal with it. [Victor Duchovni, Morgan * Stanley]. + * + * TODO(wietse) move to mail_domain_find library module. */ #define CHK_DOMAIN_RETURN(x,y) { *found = y; return(x); } - if ((dict = dict_handle(table)) == 0) { + if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) { msg_warn("%s: unexpected dictionary: %s", myname, table); value = "451 4.3.5 Server configuration error"; CHK_DOMAIN_RETURN(check_table_result(state, table, value, @@ -2754,18 +2836,16 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, def_acl), FOUND); } for (name = domain; *name != 0; name = next) { - if (flags == 0 || (flags & dict->flags) != 0) { - if ((value = dict_get(dict, name)) != 0) - CHK_DOMAIN_RETURN(check_table_result(state, table, value, + if ((value = maps_find(maps, name, flags)) != 0) + CHK_DOMAIN_RETURN(check_table_result(state, table, value, domain, reply_name, reply_class, - def_acl), FOUND); - if (dict->error != 0) { - msg_warn("%s: table lookup problem", table); - value = "451 4.3.5 Server configuration error"; - CHK_DOMAIN_RETURN(check_table_result(state, table, value, + def_acl), FOUND); + if (maps->error != 0) { + /* Warning is already logged. */ + value = "451 4.3.5 Server configuration error"; + CHK_DOMAIN_RETURN(check_table_result(state, table, value, domain, reply_name, reply_class, - def_acl), FOUND); - } + def_acl), FOUND); } /* Don't apply subdomain magic to numerical hostnames. */ if (maybe_numerical @@ -2791,7 +2871,7 @@ static int check_addr_access(SMTPD_STATE *state, const char *table, const char *myname = "check_addr_access"; char *addr; const char *value; - DICT *dict; + MAPS *maps; int delim; if (msg_verbose) @@ -2799,6 +2879,8 @@ static int check_addr_access(SMTPD_STATE *state, const char *table, /* * Try the address and its parent networks. + * + * TODO(wietse) move to mail_ipaddr_find library module. */ #define CHK_ADDR_RETURN(x,y) { *found = y; return(x); } @@ -2810,7 +2892,7 @@ static int check_addr_access(SMTPD_STATE *state, const char *table, #endif delim = '.'; - if ((dict = dict_handle(table)) == 0) { + if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) { msg_warn("%s: unexpected dictionary: %s", myname, table); value = "451 4.3.5 Server configuration error"; CHK_ADDR_RETURN(check_table_result(state, table, value, address, @@ -2818,18 +2900,16 @@ static int check_addr_access(SMTPD_STATE *state, const char *table, def_acl), FOUND); } do { - if (flags == 0 || (flags & dict->flags) != 0) { - if ((value = dict_get(dict, addr)) != 0) - CHK_ADDR_RETURN(check_table_result(state, table, value, address, - reply_name, reply_class, - def_acl), FOUND); - if (dict->error != 0) { - msg_warn("%s: table lookup problem", table); - value = "451 4.3.5 Server configuration error"; - CHK_ADDR_RETURN(check_table_result(state, table, value, address, - reply_name, reply_class, - def_acl), FOUND); - } + if ((value = maps_find(maps, addr, flags)) != 0) + CHK_ADDR_RETURN(check_table_result(state, table, value, address, + reply_name, reply_class, + def_acl), FOUND); + if (maps->error != 0) { + /* Warning is already logged. */ + value = "451 4.3.5 Server configuration error"; + CHK_ADDR_RETURN(check_table_result(state, table, value, address, + reply_name, reply_class, + def_acl), FOUND); } flags = PARTIAL; } while (split_at_right(addr, delim)); @@ -2930,7 +3010,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table, const char *bare_addr; ssize_t len; - if (type != T_MX) + if (type != T_A && type != T_MX) return (SMTPD_CHECK_DUNNO); len = strlen(domain); if (domain[len - 1] != ']') @@ -2995,7 +3075,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table, domain += 1; dns_status = dns_lookup(domain, type, 0, &server_list, (VSTRING *) 0, (VSTRING *) 0); - if (dns_status != DNS_NOTFOUND /* || h_errno != NO_DATA */) + if (dns_status != DNS_NOTFOUND /* || h_errno != NO_DATA */ ) break; } } @@ -3069,8 +3149,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table, /* check_ccert_access - access for TLS clients by certificate fingerprint */ - -static int check_ccert_access(SMTPD_STATE *state, const char *table, +static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, const char *def_acl) { int result = SMTPD_CHECK_DUNNO; @@ -3078,39 +3157,82 @@ static int check_ccert_access(SMTPD_STATE *state, const char *table, #ifdef USE_TLS const char *myname = "check_ccert_access"; int found; + const MAP_SEARCH *acl; + const char default_search[] = { + SMTPD_ACL_SEARCH_CODE_CERT_FPRINT, + SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT, + 0, + }; + const char *search_order; + + /* + * Look up the acl search list. If there is no ACL then we don't have a + * table to check. + */ + if ((acl = map_search_lookup(acl_spec)) == 0) { + msg_warn("See earlier parsing error messages for '%s", acl_spec); + return (smtpd_check_reject(state, MAIL_ERROR_SOFTWARE, 451, "4.3.5", + "Server configuration error")); + } + if ((search_order = acl->search_order) == 0) + search_order = default_search; + if (msg_verbose) + msg_info("%s: search_order length=%ld", + myname, (long) strlen(search_order)); /* * When directly checking the fingerprint, it is OK if the issuing CA is * not trusted. */ if (TLS_CERT_IS_PRESENT(state->tls_context)) { - int i; - char *prints[2]; - - prints[0] = state->tls_context->peer_cert_fprint; - prints[1] = state->tls_context->peer_pkey_fprint; - - for (i = 0; i < 2; ++i) { + const char *action; + const char *match_this; + const char *known_action; + + for (action = search_order; *action; action++) { + switch (*action) { + case SMTPD_ACL_SEARCH_CODE_CERT_FPRINT: + match_this = state->tls_context->peer_cert_fprint; + break; + case SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT: + match_this = state->tls_context->peer_pkey_fprint; + break; + default: + known_action = str_name_code(search_actions, *action); + if (known_action == 0) + msg_panic("%s: unknown action #%d in '%s'", + myname, *action, acl_spec); + msg_warn("%s: unexpected action '%s' in '%s'", + myname, known_action, acl_spec); + return (smtpd_check_reject(state, MAIL_ERROR_SOFTWARE, + 451, "4.3.5", + "Server configuration error")); + } if (msg_verbose) - msg_info("%s: %s", myname, prints[i]); + msg_info("%s: look up %s %s", + myname, str_name_code(search_actions, *action), + match_this); /* - * Regexp tables don't make sense for certificate fingerprints. - * That may be so, but we can't ignore the entire - * check_ccert_access request without logging a warning. - * * Log the peer CommonName when access is denied. Non-printable * characters will be neutered by smtpd_check_reject(). The SMTP * client name and address are always syslogged as part of a - * "reject" event. + * "reject" event. XXX Should log the thing that is rejected + * (fingerprint etc.) or would that give away too much? */ - result = check_access(state, table, prints[i], + result = 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) break; } + } else if (!var_smtpd_tls_ask_ccert) { + msg_warn("%s is requested, but \"%s = no\"", + CHECK_CCERT_ACL, VAR_SMTPD_TLS_ACERT); + } else { + if (msg_verbose) + msg_info("%s: no client certificate", myname); } #endif return (result); @@ -3146,11 +3268,10 @@ static int check_mail_access(SMTPD_STATE *state, const char *table, { const char *myname = "check_mail_access"; const RESOLVE_REPLY *reply; - const char *domain; + const char *value; + int lookup_strategy; int status; - char *local_at; - char *bare_addr; - char *bare_at; + MAPS *maps; if (msg_verbose) msg_info("%s: %s", myname, addr); @@ -3167,24 +3288,11 @@ static int check_mail_access(SMTPD_STATE *state, const char *table, * Garbage in, garbage out. Every address from rewrite_clnt_internal() * and from resolve_clnt_query() must be fully qualified. */ - if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) { + if (strrchr(CONST_STR(reply->recipient), '@') == 0) { msg_warn("%s: no @domain in address: %s", myname, CONST_STR(reply->recipient)); return (0); } - domain += 1; - - /* - * In case of address extensions. - */ - if (*var_rcpt_delim == 0) { - bare_addr = 0; - } else { - bare_addr = strip_addr(addr, (char **) 0, var_rcpt_delim); - } - -#define CHECK_MAIL_ACCESS_RETURN(x) \ - { if (bare_addr) myfree(bare_addr); return(x); } /* * Source-routed (non-local or virtual) recipient addresses are too @@ -3201,68 +3309,40 @@ static int check_mail_access(SMTPD_STATE *state, const char *table, * Look up user+foo@domain if the address has an extension, user@domain * otherwise. */ - if ((status = check_access(state, table, CONST_STR(reply->recipient), FULL, - found, reply_name, reply_class, def_acl)) != 0 - || *found) - CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK - && SUSPICIOUS(reply, reply_class) ? - SMTPD_CHECK_DUNNO : status); - - /* - * Try user@domain if the address has an extension. - */ - if (bare_addr) - if ((status = check_access(state, table, bare_addr, PARTIAL, - found, reply_name, reply_class, def_acl)) != 0 - || *found) - CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK - && SUSPICIOUS(reply, reply_class) ? - SMTPD_CHECK_DUNNO : status); - - /* - * Look up the domain name, or parent domains thereof. - */ - if ((status = check_domain_access(state, table, domain, PARTIAL, - found, reply_name, reply_class, def_acl)) != 0 - || *found) - CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK - && SUSPICIOUS(reply, reply_class) ? - SMTPD_CHECK_DUNNO : status); - - /* - * Look up user+foo@ if the address has an extension, user@ otherwise. - * XXX This leaks a little memory if map lookup is aborted. - */ - local_at = mystrndup(CONST_STR(reply->recipient), - domain - CONST_STR(reply->recipient)); - status = check_access(state, table, local_at, PARTIAL, found, - reply_name, reply_class, def_acl); - myfree(local_at); - if (status != 0 || *found) - CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK - && SUSPICIOUS(reply, reply_class) ? - SMTPD_CHECK_DUNNO : status); - - /* - * Look up user@ if the address has an extension. XXX Same problem here. - */ - if (bare_addr) { - bare_at = strrchr(bare_addr, '@'); - local_at = (bare_at ? mystrndup(bare_addr, bare_at + 1 - bare_addr) : - mystrdup(bare_addr)); - status = check_access(state, table, local_at, PARTIAL, found, - reply_name, reply_class, def_acl); - myfree(local_at); - if (status != 0 || *found) - CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK - && SUSPICIOUS(reply, reply_class) ? - SMTPD_CHECK_DUNNO : status); + lookup_strategy = MA_FIND_FULL | MA_FIND_NOEXT | MA_FIND_DOMAIN + | MA_FIND_LOCALPART_AT + | (access_parent_style == MATCH_FLAG_PARENT ? + MA_FIND_PDMS : MA_FIND_PDDMDS); + + if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) { + msg_warn("%s: unexpected dictionary: %s", myname, table); + value = "451 4.3.5 Server configuration error"; + return (check_table_result(state, table, value, + CONST_STR(reply->recipient), + reply_name, reply_class, + def_acl)); + } + if ((value = mail_addr_find_strategy(maps, CONST_STR(reply->recipient), + (char **) 0, lookup_strategy)) != 0) { + *found = 1; + status = check_table_result(state, table, value, + CONST_STR(reply->recipient), + reply_name, reply_class, def_acl); + return (status == SMTPD_CHECK_OK && SUSPICIOUS(reply, reply_class) ? + SMTPD_CHECK_DUNNO : status); + } else if (maps->error != 0) { + /* Warning is already logged. */ + value = "451 4.3.5 Server configuration error"; + return (check_table_result(state, table, value, + CONST_STR(reply->recipient), + reply_name, reply_class, + def_acl)); } /* * Undecided when no match found. */ - CHECK_MAIL_ACCESS_RETURN(SMTPD_CHECK_DUNNO); + return (SMTPD_CHECK_DUNNO); } /* Support for different DNSXL lookup results. */ @@ -3921,13 +4001,19 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, if (attr_clnt_request(policy_clnt->client, ATTR_FLAG_NONE, /* Query attributes. */ SEND_ATTR_STR(MAIL_ATTR_REQ, "smtpd_access_policy"), - SEND_ATTR_STR(MAIL_ATTR_PROTO_STATE, state->where), + SEND_ATTR_STR(MAIL_ATTR_PROTO_STATE, + STREQ(state->where, SMTPD_CMD_BDAT) ? + SMTPD_CMD_DATA : state->where), SEND_ATTR_STR(MAIL_ATTR_ACT_PROTO_NAME, state->protocol), SEND_ATTR_STR(MAIL_ATTR_ACT_CLIENT_ADDR, state->addr), SEND_ATTR_STR(MAIL_ATTR_ACT_CLIENT_NAME, state->name), SEND_ATTR_STR(MAIL_ATTR_ACT_CLIENT_PORT, state->port), SEND_ATTR_STR(MAIL_ATTR_ACT_REVERSE_CLIENT_NAME, state->reverse_name), + SEND_ATTR_STR(MAIL_ATTR_ACT_SERVER_ADDR, + state->dest_addr), + SEND_ATTR_STR(MAIL_ATTR_ACT_SERVER_PORT, + state->dest_port), SEND_ATTR_STR(MAIL_ATTR_ACT_HELO_NAME, state->helo_name ? state->helo_name : ""), SEND_ATTR_STR(MAIL_ATTR_SENDER, @@ -3936,7 +4022,8 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, state->recipient ? state->recipient : ""), SEND_ATTR_INT(MAIL_ATTR_RCPT_COUNT, ((strcasecmp(state->where, SMTPD_CMD_DATA) == 0) || - (strcasecmp(state->where, SMTPD_AFTER_DOT) == 0)) ? + (strcasecmp(state->where, SMTPD_CMD_BDAT) == 0) || + (strcasecmp(state->where, SMTPD_AFTER_EOM) == 0)) ? state->rcpt_count : 0), SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id ? state->queue_id : ""), @@ -4055,7 +4142,7 @@ static int is_map_command(SMTPD_STATE *state, const char *name, static void forbid_whitelist(SMTPD_STATE *state, const char *name, int status, const char *target) { - if (status == SMTPD_CHECK_OK) { + if (state->discard == 0 && status == SMTPD_CHECK_OK) { msg_warn("restriction %s returns OK for %s", name, target); msg_warn("this is not allowed for security reasons"); msg_warn("use DUNNO instead of OK if you want to make an exception"); @@ -4587,7 +4674,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, status = check_recipient_rcpt_maps(state, state->recipient); } else if (strcasecmp(name, REJECT_MUL_RCPT_BOUNCE) == 0) { if (state->sender && *state->sender == 0 && state->rcpt_count - > (strcmp(state->where, SMTPD_CMD_DATA) ? 0 : 1)) + > (strcmp(state->where, SMTPD_CMD_RCPT) != 0)) status = smtpd_check_reject(state, MAIL_ERROR_POLICY, var_mul_rcpt_code, "5.5.3", "<%s>: %s rejected: Multi-recipient bounce", @@ -4699,7 +4786,7 @@ char *smtpd_check_rewrite(SMTPD_STATE *state) const char *myname = "smtpd_check_rewrite"; int status; char **cpp; - DICT *dict; + MAPS *maps; char *name; /* @@ -4719,13 +4806,13 @@ char *smtpd_check_rewrite(SMTPD_STATE *state) } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) { status = permit_mynetworks(state); } else if (is_map_command(state, name, CHECK_ADDR_MAP, &cpp)) { - if ((dict = dict_handle(*cpp)) == 0) + if ((maps = (MAPS *) htable_find(map_command_table, *cpp)) == 0) msg_panic("%s: dictionary not found: %s", myname, *cpp); - if (dict_get(dict, state->addr) != 0) + if (maps_find(maps, state->addr, 0) != 0) status = SMTPD_CHECK_OK; - else if (dict->error != 0) { - msg_warn("%s: %s: lookup error", VAR_LOC_RWR_CLIENTS, *cpp); - status = dict->error; + else if (maps->error != 0) { + /* Warning is already logged. */ + status = maps->error; } } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) { #ifdef USE_SASL_AUTH @@ -4969,15 +5056,31 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) * Apply restrictions in the order as specified. We allow relay * restrictions to be empty, for sites that require backwards * compatibility. + * + * If compatibility_level < 1 and smtpd_relay_restrictions is left at its + * default value, find out if the new smtpd_relay_restrictions default + * value would block the request, without logging REJECT messages. + * Approach: evaluate fake relay restrictions (permit_mynetworks, + * permit_sasl_authenticated, permit_auth_destination) and log a warning + * if the result is DUNNO instead of OK, i.e. a reject_unauth_destinatin + * at the end would have blocked the request. */ SMTPD_CHECK_RESET(); - restrctions[0] = relay_restrctions; - restrctions[1] = rcpt_restrctions; + restrctions[0] = rcpt_restrctions; + restrctions[1] = warn_compat_break_relay_restrictions ? + fake_relay_restrctions : relay_restrctions; for (n = 0; n < 2; n++) { status = setjmp(smtpd_check_buf); if (status == 0 && restrctions[n]->argc) status = generic_checks(state, restrctions[n], recipient, SMTPD_NAME_RECIPIENT, CHECK_RECIP_ACL); + if (n == 1 && warn_compat_break_relay_restrictions + && status == SMTPD_CHECK_DUNNO) { + msg_info("using backwards-compatible default setting \"" + VAR_RELAY_CHECKS " = (empty)\" to avoid \"Relay " + "access denied\" error for recipient \"%s\" from " + "client \"%s\"", state->recipient, state->namaddr); + } if (status == SMTPD_CHECK_REJECT) break; } @@ -5283,7 +5386,7 @@ char *smtpd_check_size(SMTPD_STATE *state, off_t size) /* * Check against file size limit. */ - if (var_message_limit > 0 && size > var_message_limit) { + if (ENFORCING_SIZE_LIMIT(var_message_limit) && size > var_message_limit) { (void) smtpd_check_reject(state, MAIL_ERROR_POLICY, 552, "5.3.4", "Message size exceeds fixed limit"); @@ -5522,6 +5625,7 @@ char *var_unk_addr_tf_act; char *var_unv_rcpt_tf_act; char *var_unv_from_tf_act; char *var_smtpd_acl_perm_log; +char *var_info_log_addr_form; typedef struct { char *name; @@ -5577,6 +5681,7 @@ static const STRING_TABLE string_table[] = { /* XXX Can't use ``$name'' type default values above. */ VAR_SMTPD_ACL_PERM_LOG, DEF_SMTPD_ACL_PERM_LOG, &var_smtpd_acl_perm_log, VAR_SMTPD_DNS_RE_FILTER, DEF_SMTPD_DNS_RE_FILTER, &var_smtpd_dns_re_filter, + VAR_INFO_LOG_ADDR_FORM, DEF_INFO_LOG_ADDR_FORM, &var_info_log_addr_form, 0, }; @@ -5609,7 +5714,7 @@ static int string_update(char **argv) /* * Integer parameters. */ -int var_queue_minfree; /* XXX use off_t */ +long var_queue_minfree; /* XXX use off_t */ typedef struct { char *name; int defval; @@ -5653,6 +5758,7 @@ int var_plaintext_code; bool var_smtpd_peername_lookup; bool var_smtpd_client_port_log; char *var_smtpd_dns_re_filter; +bool var_smtpd_tls_ask_ccert; #define int_table test_int_table @@ -5687,6 +5793,7 @@ static const INT_TABLE int_table[] = { VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup, VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log, + VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert, 0, }; @@ -5914,7 +6021,6 @@ int main(int argc, char **argv) char *bp; char *resp; char *addr; - INET_PROTO_INFO *proto_info; /* * Initialization. Use dummies for client information. @@ -5926,7 +6032,7 @@ int main(int argc, char **argv) int_init(); smtpd_check_init(); smtpd_expand_init(); - proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_IPV4); + (void) inet_proto_init(argv[0], INET_PROTO_NAME_IPV4); smtpd_state_init(&state, VSTREAM_IN, "smtpd"); state.queue_id = "<queue id>"; @@ -5952,7 +6058,7 @@ int main(int argc, char **argv) vstream_printf("exit %d\n", system(bp + 1)); continue; } - args = argv_split(bp, CHARS_SPACE); + args = argv_splitq(bp, CHARS_SPACE, CHARS_BRACE); /* * Recognize the command. diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.h b/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.h index 7147da31f94..d22434497ea 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.h +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_check.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_check.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_check.h,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -37,4 +37,9 @@ extern char *smtpd_check_policy(SMTPD_STATE *, char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_expand.h b/external/ibm-public/postfix/dist/src/smtpd/smtpd_expand.h index 12ac586cedc..e172cbf6158 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_expand.h +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_expand.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_expand.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_expand.h,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -20,7 +20,7 @@ /* * External interface. */ -VSTRING *smtpd_expand_filter; +extern VSTRING *smtpd_expand_filter; void smtpd_expand_init(void); const char *smtpd_expand_lookup(const char *, int, void *); int smtpd_expand(SMTPD_STATE *, VSTRING *, const char *, int); @@ -34,4 +34,9 @@ int smtpd_expand(SMTPD_STATE *, VSTRING *, const char *, int); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_haproxy.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_haproxy.c index db21e6b6ff3..ac8e49221ce 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_haproxy.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_haproxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_haproxy.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_haproxy.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -17,6 +17,11 @@ /* The following summarizes what the Postfix SMTP server expects /* from an up-stream proxy adapter. /* .IP \(bu +/* Call smtpd_peer_from_default() if the up-stream proxy +/* indicates that the connection is not proxied. In that case, +/* a proxy adapter MUST NOT update any STATE fields: the +/* smtpd_peer_from_default() function will do that instead. +/* .IP \(bu /* Validate protocol, address and port syntax. Permit only /* protocols that are configured with the main.cf:inet_protocols /* setting. @@ -25,8 +30,8 @@ /* both IPv6 and IPv4 support are enabled with main.cf:inet_protocols. /* .IP \(bu /* Update the following session context fields: addr, port, -/* rfc_addr, addr_family, dest_addr. The addr_family field -/* applies to the client address. +/* rfc_addr, addr_family, dest_addr, dest_port. The addr_family +/* field applies to the client address. /* .IP \(bu /* Dynamically allocate storage for string information with /* mystrdup(). In case of error, leave unassigned string fields @@ -54,6 +59,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -67,6 +77,7 @@ #include <myaddrinfo.h> #include <mymalloc.h> #include <stringops.h> +#include <iostuff.h> /* Global library. */ @@ -88,77 +99,39 @@ int smtpd_peer_from_haproxy(SMTPD_STATE *state) { - const char *myname = "smtpd_peer_from_haproxy"; MAI_HOSTADDR_STR smtp_client_addr; MAI_SERVPORT_STR smtp_client_port; MAI_HOSTADDR_STR smtp_server_addr; MAI_SERVPORT_STR smtp_server_port; - const char *proxy_err; - int io_err; - VSTRING *escape_buf; - - /* - * While reading HAProxy handshake information, don't buffer input beyond - * the end-of-line. That would break the TLS wrappermode handshake. - */ - vstream_control(state->client, - VSTREAM_CTL_BUFSIZE, 1, - VSTREAM_CTL_END); + int non_proxy = 0; - /* - * Note: the haproxy_srvr_parse() routine performs address protocol - * checks, address and port syntax checks, and converts IPv4-in-IPv6 - * address string syntax (:ffff::1.2.3.4) to IPv4 syntax where permitted - * by the main.cf:inet_protocols setting, but logs no warnings. - */ -#define ENABLE_DEADLINE 1 - - smtp_stream_setup(state->client, var_smtpd_uproxy_tmout, ENABLE_DEADLINE); - switch (io_err = vstream_setjmp(state->client)) { - default: - msg_panic("%s: unhandled I/O error %d", myname, io_err); - case SMTP_ERR_EOF: - msg_warn("haproxy read: unexpected EOF"); - return (-1); - case SMTP_ERR_TIME: + if (read_wait(vstream_fileno(state->client), var_smtpd_uproxy_tmout) < 0) { msg_warn("haproxy read: timeout error"); return (-1); - case 0: - if (smtp_get(state->buffer, state->client, HAPROXY_MAX_LEN, - SMTP_GET_FLAG_NONE) != '\n') { - msg_warn("haproxy read: line > %d characters", HAPROXY_MAX_LEN); - return (-1); - } - if ((proxy_err = haproxy_srvr_parse(STR(state->buffer), - &smtp_client_addr, &smtp_client_port, - &smtp_server_addr, &smtp_server_port)) != 0) { - escape_buf = vstring_alloc(HAPROXY_MAX_LEN + 2); - escape(escape_buf, STR(state->buffer), LEN(state->buffer)); - msg_warn("haproxy read: %s: %s", proxy_err, STR(escape_buf)); - vstring_free(escape_buf); - return (-1); - } - state->addr = mystrdup(smtp_client_addr.buf); - if (strrchr(state->addr, ':') != 0) { - state->rfc_addr = concatenate(IPV6_COL, state->addr, (char *) 0); - state->addr_family = AF_INET6; - } else { - state->rfc_addr = mystrdup(state->addr); - state->addr_family = AF_INET; - } - state->port = mystrdup(smtp_client_port.buf); - - /* - * Avoid surprises in the Dovecot authentication server. - */ - state->dest_addr = mystrdup(smtp_server_addr.buf); - - /* - * Enable normal buffering. - */ - vstream_control(state->client, - VSTREAM_CTL_BUFSIZE, VSTREAM_BUFSIZE, - VSTREAM_CTL_END); + } + if (haproxy_srvr_receive(vstream_fileno(state->client), &non_proxy, + &smtp_client_addr, &smtp_client_port, + &smtp_server_addr, &smtp_server_port) < 0) { + return (-1); + } + if (non_proxy) { + smtpd_peer_from_default(state); return (0); } + state->addr = mystrdup(smtp_client_addr.buf); + if (strrchr(state->addr, ':') != 0) { + state->rfc_addr = concatenate(IPV6_COL, state->addr, (char *) 0); + state->addr_family = AF_INET6; + } else { + state->rfc_addr = mystrdup(state->addr); + state->addr_family = AF_INET; + } + state->port = mystrdup(smtp_client_port.buf); + + /* + * The Dovecot authentication server needs the server IP address. + */ + state->dest_addr = mystrdup(smtp_server_addr.buf); + state->dest_port = mystrdup(smtp_server_port.buf); + return (0); } diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_milter.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_milter.c index 5ce1fb7c4d3..344266f93ca 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_milter.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_milter.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_milter.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_milter.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -115,6 +115,11 @@ const char *smtpd_milter_eval(const char *name, void *ptr) state->name_status == SMTPD_PEER_CODE_FORGED ? "FORGED" : state->name_status == SMTPD_PEER_CODE_TEMP ? "TEMP" : "FAIL"); + if (strcmp(name, S8_MAC_DAEMON_ADDR) == 0) + return (state->dest_addr); + if (strcmp(name, S8_MAC_DAEMON_PORT) == 0) + return (state->dest_port); + /* * HELO macros. */ diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_peer.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_peer.c index c2c2eb5096a..c26c9eb59b1 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_peer.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_peer.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_peer.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_peer.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -13,6 +13,9 @@ /* /* void smtpd_peer_reset(state) /* SMTPD_STATE *state; +/* AUXILIARY METHODS +/* void smtpd_peer_from_default(state) +/* SMTPD_STATE *state; /* DESCRIPTION /* The smtpd_peer_init() routine attempts to produce a printable /* version of the peer name and address of the specified socket. @@ -51,7 +54,12 @@ /* String of the form "ipv4addr" or "ipv6:ipv6addr" for use /* in Received: message headers. /* .IP dest_addr -/* Server address, used by the Dovecot authentication server. +/* Server address, used by the Dovecot authentication server, +/* available as Milter {daemon_addr} macro, and as server_address +/* policy delegation attribute. +/* .IP dest_port +/* Server port, available as Milter {daemon_port} macro, and +/* as server_port policy delegation attribute. /* .IP name_status /* The name_status result field specifies how the name /* information should be interpreted: @@ -70,16 +78,19 @@ /* .IP reverse_name_status /* The reverse_name_status result field specifies how the /* reverse_name information should be interpreted: -/* .RS .IP 2 +/* .RS +/* .IP 2 /* The address->name lookup succeeded. /* .IP 4 /* The address->name lookup failed with a recoverable error. /* .IP 5 /* The address->name lookup failed with an unrecoverable error. -/* .RE .IP forward_name_status +/* .RE +/* .IP forward_name_status /* The forward_name_status result field specifies how the /* forward_name information should be interpreted: -/* .RS .IP 2 +/* .RS +/* .IP 2 /* The address->name and name->address lookup succeeded. /* .IP 4 /* The address->name lookup or name->address failed with a @@ -90,6 +101,10 @@ /* .RE /* .PP /* smtpd_peer_reset() releases memory allocated by smtpd_peer_init(). +/* +/* smtpd_peer_from_default() looks up connection information +/* when an up-stream proxy indicates that a connection is not +/* proxied. /* LICENSE /* .ad /* .fi @@ -99,6 +114,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -137,14 +157,6 @@ static INET_PROTO_INFO *proto_info; /* - * XXX If we make local endpoint (getsockname) information available to - * Milter applications as {if_name} and {if_addr}, then we also must be able - * to provide this via the XCLIENT command for Milter testing. - * - * XXX If we make local port information available to policy servers or Milter - * applications, then we must also make this testable with the XCLIENT - * command, otherwise there will be confusion. - * * XXX If we make local port information available via logging, then we must * also support these attributes with the XFORWARD command. * @@ -175,6 +187,8 @@ static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state) ) { MAI_HOSTADDR_STR client_addr; MAI_SERVPORT_STR client_port; + MAI_HOSTADDR_STR server_addr; + MAI_SERVPORT_STR server_port; int aierr; char *colonp; @@ -276,6 +290,21 @@ static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state) state->rfc_addr = mystrdup(client_addr.buf); state->addr_family = sa->sa_family; } + + /* + * Convert the server address/port to printable form. + */ + if ((aierr = sockaddr_to_hostaddr((struct sockaddr *) + &state->dest_sockaddr, + state->dest_sockaddr_len, + &server_addr, + &server_port, 0)) != 0) + msg_fatal("%s: cannot convert server address/port to string: %s", + myname, MAI_STRERROR(aierr)); + /* TODO: convert IPv4-in-IPv6 to IPv4 form. */ + state->dest_addr = mystrdup(server_addr.buf); + state->dest_port = mystrdup(server_port.buf); + return (0); } @@ -414,6 +443,9 @@ static void smtpd_peer_not_inet(SMTPD_STATE *state) state->name_status = SMTPD_PEER_CODE_OK; state->reverse_name_status = SMTPD_PEER_CODE_OK; state->port = mystrdup("0"); /* XXX bogus. */ + + state->dest_addr = mystrdup(state->addr); /* XXX bogus. */ + state->dest_port = mystrdup(state->port); /* XXX bogus. */ } /* smtpd_peer_no_client - peer went away, or peer info unavailable */ @@ -429,6 +461,9 @@ static void smtpd_peer_no_client(SMTPD_STATE *state) state->name_status = SMTPD_PEER_CODE_PERM; state->reverse_name_status = SMTPD_PEER_CODE_PERM; state->port = mystrdup(CLIENT_PORT_UNKNOWN); + + state->dest_addr = mystrdup(SERVER_ADDR_UNKNOWN); + state->dest_port = mystrdup(SERVER_PORT_UNKNOWN); } /* smtpd_peer_from_pass_attr - initialize from attribute hash */ @@ -463,14 +498,20 @@ static void smtpd_peer_from_pass_attr(SMTPD_STATE *state) state->port = mystrdup(cp); /* - * Avoid surprises in the Dovecot authentication server. + * The Dovecot authentication server needs the server IP address. */ if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0) msg_fatal("missing server address from proxy"); if (valid_hostaddr(cp, DO_GRIPE) == 0) - msg_fatal("bad IPv6 client address syntax from proxy: %s", cp); + msg_fatal("bad IPv6 server address syntax from proxy: %s", cp); state->dest_addr = mystrdup(cp); + if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_PORT)) == 0) + msg_fatal("missing server port from proxy"); + if (valid_hostport(cp, DO_GRIPE) == 0) + msg_fatal("bad TCP server port number syntax from proxy: %s", cp); + state->dest_port = mystrdup(cp); + /* * Convert the client address from string to binary form. */ @@ -479,10 +520,8 @@ static void smtpd_peer_from_pass_attr(SMTPD_STATE *state) /* smtpd_peer_from_default - try to initialize peer information from socket */ -static void smtpd_peer_from_default(SMTPD_STATE *state) +void smtpd_peer_from_default(SMTPD_STATE *state) { - SOCKADDR_SIZE sa_length = sizeof(state->sockaddr); - struct sockaddr *sa = (struct sockaddr *) &(state->sockaddr); /* * The "no client" routine provides surrogate information so that the @@ -490,13 +529,19 @@ static void smtpd_peer_from_default(SMTPD_STATE *state) * before the server wakes up. The "not inet" routine provides surrogate * state for (presumably) local IPC channels. */ - if (getpeername(vstream_fileno(state->client), sa, &sa_length) < 0) { + state->sockaddr_len = sizeof(state->sockaddr); + state->dest_sockaddr_len = sizeof(state->dest_sockaddr); + if (getpeername(vstream_fileno(state->client), + (struct sockaddr *) &state->sockaddr, + &state->sockaddr_len) <0 + || getsockname(vstream_fileno(state->client), + (struct sockaddr *) &state->dest_sockaddr, + &state->dest_sockaddr_len) < 0) { if (errno == ENOTSOCK) smtpd_peer_not_inet(state); else smtpd_peer_no_client(state); } else { - state->sockaddr_len = sa_length; if (smtpd_peer_sockaddr_to_hostaddr(state) < 0) smtpd_peer_not_inet(state); } @@ -528,7 +573,7 @@ static void smtpd_peer_from_proxy(SMTPD_STATE *state) break; } if (pp->endpt_lookup(state) < 0) { - smtpd_peer_no_client(state); + smtpd_peer_from_default(state); state->flags |= SMTPD_FLAG_HANGUP; } else { smtpd_peer_hostaddr_to_sockaddr(state); @@ -558,6 +603,7 @@ void smtpd_peer_init(SMTPD_STATE *state) state->rfc_addr = 0; state->port = 0; state->dest_addr = 0; + state->dest_port = 0; /* * Determine the remote SMTP client address and port. @@ -610,4 +656,6 @@ void smtpd_peer_reset(SMTPD_STATE *state) myfree(state->port); if (state->dest_addr) myfree(state->dest_addr); + if (state->dest_port) + myfree(state->dest_port); } diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.c index c7a66735b30..55da55a0d43 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_resolve.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_resolve.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -48,6 +48,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.h b/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.h index 89540f9ae59..8b311095089 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.h +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.h @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_resolve.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_resolve.h,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -31,6 +31,11 @@ extern const RESOLVE_REPLY *smtpd_resolve_addr(const char*, const char *); /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* TLS support originally by: /* Lutz Jaenicke /* BTU Cottbus diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_glue.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_glue.c index 483fb4372c5..256fd4f9323 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_glue.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_glue.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_sasl_glue.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_sasl_glue.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -220,10 +220,15 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name, if ((state->sasl_server = XSASL_SERVER_CREATE(smtpd_sasl_impl, &create_args, stream = state->client, - server_addr = (state->dest_addr ? - state->dest_addr : ""), + addr_family = state->addr_family, + server_addr = ADDR_OR_EMPTY(state->dest_addr, + SERVER_ADDR_UNKNOWN), + server_port = ADDR_OR_EMPTY(state->dest_port, + SERVER_PORT_UNKNOWN), client_addr = ADDR_OR_EMPTY(state->addr, CLIENT_ADDR_UNKNOWN), + client_port = ADDR_OR_EMPTY(state->port, + CLIENT_PORT_UNKNOWN), service = var_smtpd_sasl_service, user_realm = REALM_OR_NULL(var_smtpd_sasl_realm), security_options = sasl_opts_val, @@ -305,12 +310,11 @@ int smtpd_sasl_authenticate(SMTPD_STATE *state, /* * Receive the client response. "*" means that the client gives up. - * XXX For now we ignore the fact that an excessively long response - * will be chopped into multiple reponses. To handle such responses, - * we need to change smtpd_chat_query() so that it returns an error - * indication. */ - smtpd_chat_query(state); + if (!smtpd_chat_query_limit(state, var_smtpd_sasl_resp_limit)) { + smtpd_chat_reply(state, "500 5.5.6 SASL response limit exceeded"); + return (-1); + } if (strcmp(STR(state->buffer), "*") == 0) { msg_warn("%s: SASL %s authentication aborted", state->namaddr, sasl_method); diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_proto.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_proto.c index bb75075fedc..11c67ba74fc 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_proto.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_sasl_proto.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_sasl_proto.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtpd_sasl_proto.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -9,7 +9,7 @@ /* #include "smtpd.h" /* #include "smtpd_sasl_proto.h" /* -/* void smtpd_sasl_auth_cmd(state, argc, argv) +/* int smtpd_sasl_auth_cmd(state, argc, argv) /* SMTPD_STATE *state; /* int argc; /* SMTPD_TOKEN *argv; @@ -101,6 +101,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* TLS support originally by: /* Lutz Jaenicke /* BTU Cottbus @@ -165,7 +170,7 @@ int smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "503 5.5.1 Error: MAIL transaction in progress"); return (-1); } - if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0) { + if (state->milters != 0 && (err = milter_other_event(state->milters)) != 0) { if (err[0] == '5') { state->error_mask |= MAIL_ERROR_POLICY; smtpd_chat_reply(state, "%s", err); diff --git a/external/ibm-public/postfix/dist/src/smtpd/smtpd_state.c b/external/ibm-public/postfix/dist/src/smtpd/smtpd_state.c index 4f9f1ef9d0f..48eff8b6850 100644 --- a/external/ibm-public/postfix/dist/src/smtpd/smtpd_state.c +++ b/external/ibm-public/postfix/dist/src/smtpd/smtpd_state.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtpd_state.c,v 1.1.1.6 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: smtpd_state.c,v 1.2 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/smtpstone/smtp-source.c b/external/ibm-public/postfix/dist/src/smtpstone/smtp-source.c index 7b6c08ff708..04f4699ea77 100644 --- a/external/ibm-public/postfix/dist/src/smtpstone/smtp-source.c +++ b/external/ibm-public/postfix/dist/src/smtpstone/smtp-source.c @@ -1,4 +1,4 @@ -/* $NetBSD: smtp-source.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: smtp-source.c,v 1.3 2020/03/18 19:05:20 christos Exp $ */ /*++ /* NAME @@ -306,14 +306,13 @@ static RESPONSE *response(VSTREAM *stream, VSTRING *buf) char *cp; /* - * Initialize the response data buffer. Defend against a denial of - * service attack by limiting the amount of multi-line text that we are + * Initialize the response data buffer. smtp_get() defends against a + * denial of service attack by limiting the amount of single-line text, + * and the loop below limits the amount of multi-line text that we are * willing to store. */ - if (rdata.buf == 0) { + if (rdata.buf == 0) rdata.buf = vstring_alloc(100); - vstring_ctl(rdata.buf, CA_VSTRING_CTL_MAXLEN(var_line_limit), 0); - } /* * Censor out non-printable characters in server responses. Concatenate @@ -337,10 +336,12 @@ static RESPONSE *response(VSTREAM *stream, VSTRING *buf) cp++; while (ISSPACE(*cp)) cp++; - vstring_strcat(rdata.buf, cp); + if (VSTRING_LEN(rdata.buf) < var_line_limit) + vstring_strcat(rdata.buf, cp); if (more == 0) break; - VSTRING_ADDCH(rdata.buf, '\n'); + if (VSTRING_LEN(rdata.buf) < var_line_limit) + VSTRING_ADDCH(rdata.buf, '\n'); } VSTRING_TERMINATE(rdata.buf); rdata.str = vstring_str(rdata.buf); @@ -1144,13 +1145,11 @@ int main(int argc, char **argv) } /* - * Make sure the SMTP server cannot run us out of memory by sending - * never-ending lines of text. + * smtp_get() makes sure the SMTP server cannot run us out of memory by + * sending never-ending lines of text. */ - if (buffer == 0) { + if (buffer == 0) buffer = vstring_alloc(100); - vstring_ctl(buffer, CA_VSTRING_CTL_MAXLEN(var_line_limit), 0); - } /* * Make sure we have sender and recipient addresses. diff --git a/external/ibm-public/postfix/dist/src/spawn/spawn.c b/external/ibm-public/postfix/dist/src/spawn/spawn.c index b3168630548..c710793cd7d 100644 --- a/external/ibm-public/postfix/dist/src/spawn/spawn.c +++ b/external/ibm-public/postfix/dist/src/spawn/spawn.c @@ -1,4 +1,4 @@ -/* $NetBSD: spawn.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: spawn.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -45,7 +45,7 @@ /* replaced by a more structural solution. /* DIAGNOSTICS /* The \fBspawn\fR(8) daemon reports abnormal child exits. -/* Problems are logged to \fBsyslogd\fR(8). +/* Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8). /* SECURITY /* .fi /* .ad @@ -68,13 +68,10 @@ /* RESOURCE AND RATE CONTROL /* .ad /* .fi -/* .IP "\fItransport\fB_time_limit ($command_time_limit)\fR" -/* The amount of time the command is allowed to run before it is -/* terminated. -/* -/* Postfix 2.4 and later support a suffix that specifies the -/* time unit: s (seconds), m (minutes), h (hours), d (days), -/* w (weeks). The default time unit is seconds. +/* .IP "\fBtransport_time_limit ($command_time_limit)\fR" +/* A transport-specific override for the command_time_limit parameter +/* value, where \fItransport\fR is the master.cf name of the message +/* delivery transport. /* MISCELLANEOUS /* .ad /* .fi @@ -108,11 +105,16 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* postconf(5), configuration parameters /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* LICENSE /* .ad diff --git a/external/ibm-public/postfix/dist/src/tls/tls.h b/external/ibm-public/postfix/dist/src/tls/tls.h index b070cd783f7..c180889bfdf 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls.h +++ b/external/ibm-public/postfix/dist/src/tls/tls.h @@ -1,4 +1,4 @@ -/* $NetBSD: tls.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _TLS_H_INCLUDED_ #define _TLS_H_INCLUDED_ @@ -86,8 +86,8 @@ extern const char *str_tls_level(int); #define ssl_cipher_stack_t STACK_OF(SSL_CIPHER) #define ssl_comp_stack_t STACK_OF(SSL_COMP) -#if (OPENSSL_VERSION_NUMBER < 0x00090700f) -#error "need OpenSSL version 0.9.7 or later" +#if (OPENSSL_VERSION_NUMBER < 0x1000200fUL) +#error "OpenSSL releases prior to 1.0.2 are no longer supported" #endif /* Backwards compatibility with OpenSSL < 1.1.0 */ @@ -95,6 +95,8 @@ extern const char *str_tls_level(int); #define OpenSSL_version_num SSLeay #define OpenSSL_version SSLeay_version #define OPENSSL_VERSION SSLEAY_VERSION +#define X509_STORE_up_ref(store) \ + CRYPTO_add(&((store)->references), 1, CRYPTO_LOCK_X509) #define X509_up_ref(x) \ CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509) #define EVP_PKEY_up_ref(k) \ @@ -106,20 +108,30 @@ extern const char *str_tls_level(int); #define ASN1_STRING_get0_data ASN1_STRING_data #define X509_getm_notBefore X509_get_notBefore #define X509_getm_notAfter X509_get_notAfter +#define TLS_method SSLv23_method +#define TLS_client_method SSLv23_client_method +#define TLS_server_method SSLv23_server_method #endif -/* SSL_CIPHER_get_name() got constified in 0.9.7g */ -#if OPENSSL_VERSION_NUMBER >= 0x0090707fL /* constification */ -#define SSL_CIPHER_const const -#else -#define SSL_CIPHER_const + /* Backwards compatibility with OpenSSL < 1.1.1 */ +#if OPENSSL_VERSION_NUMBER < 0x1010100fUL +#define SSL_CTX_set_num_tickets(ctx, num) ((void)0) #endif -/* d2i_X509() got constified in 0.9.8a */ -#if OPENSSL_VERSION_NUMBER >= 0x0090801fL -#define D2I_const const + /*- + * Backwards compatibility with OpenSSL < 1.1.1a. + * + * In OpenSSL 1.1.1a the client-only interface SSL_get_server_tmp_key() was + * updated to work on both the client and the server, and was renamed to + * SSL_get_peer_tmp_key(), with the original name left behind as an alias. We + * use the new name when available. + */ +#if OPENSSL_VERSION_NUMBER < 0x1010101fUL +#undef SSL_get_signature_nid +#define SSL_get_signature_nid(ssl, pnid) (NID_undef) +#define tls_get_peer_dh_pubkey SSL_get_server_tmp_key #else -#define D2I_const +#define tls_get_peer_dh_pubkey SSL_get_peer_tmp_key #endif /* @@ -135,6 +147,17 @@ extern const char *str_tls_level(int); #include <dns.h> /* + * TLS role, presently for logging. + */ +typedef enum { + TLS_ROLE_CLIENT, TLS_ROLE_SERVER, +} TLS_ROLE; + +typedef enum { + TLS_USAGE_NEW, TLS_USAGE_USED, +} TLS_USAGE; + + /* * Names of valid tlsmgr(8) session caches. */ #define TLS_MGR_SCACHE_SMTPD "smtpd" @@ -142,7 +165,7 @@ extern const char *str_tls_level(int); #define TLS_MGR_SCACHE_LMTP "lmtp" /* - * RFC 6698 DANE + * RFC 6698, 7671, 7672 DANE */ #define TLS_DANE_TA 0 /* Match trust-anchor digests */ #define TLS_DANE_EE 1 /* Match end-entity digests */ @@ -226,6 +249,7 @@ typedef struct { /* Public, read-only. */ char *peer_CN; /* Peer Common Name */ char *issuer_CN; /* Issuer Common Name */ + char *peer_sni; /* SNI sent to or by the peer */ char *peer_cert_fprint; /* ASCII certificate fingerprint */ char *peer_pkey_fprint; /* ASCII public key fingerprint */ int peer_status; /* Certificate and match status */ @@ -233,6 +257,17 @@ typedef struct { const char *cipher_name; int cipher_usebits; int cipher_algbits; + 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 */ + 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 */ + const char *clnt_sig_dgst; /* client's signature digest */ + const char *srvr_sig_name; /* server's signature key algorithm */ + const char *srvr_sig_curve; /* server's ECDSA curve name */ + int srvr_sig_bits; /* server's RSA signature key bits */ + const char *srvr_sig_dgst; /* server's signature digest */ /* Private. */ SSL *con; char *cache_type; /* tlsmgr(8) cache type if enabled */ @@ -245,7 +280,7 @@ typedef struct { const char *mdalg; /* default message digest algorithm */ /* Built-in vs external SSL_accept/read/write/shutdown support. */ VSTREAM *stream; /* Blocking-mode SMTP session */ - /* RFC 6698 DANE trust input and verification state */ + /* DANE TLSA trust input and verification state */ const TLS_DANE *dane; /* DANE TLSA digests */ int errordepth; /* Chain depth of error cert */ int tadepth; /* Chain depth of trust anchor */ @@ -302,12 +337,9 @@ extern int tls_log_mask(const char *, const char *); */ struct TLS_APPL_STATE { SSL_CTX *ssl_ctx; + SSL_CTX *sni_ctx; int log_mask; char *cache_type; - char *cipher_exclusions; /* Last cipher selection state */ - char *cipher_list; /* Last cipher selection state */ - int cipher_grade; /* Last cipher selection state */ - VSTRING *why; }; /* @@ -371,10 +403,15 @@ extern void tls_param_init(void); #define SSL_OP_NO_TLSv1_2 0L /* Noop */ #endif -#ifdef SSL_TXT_TLSV1_3 + /* + * OpenSSL 1.1.1 does not define a TXT macro for TLS 1.3, so we roll our + * own. + */ +#define TLS_PROTOCOL_TXT_TLSV1_3 "TLSv1.3" + +#if defined(TLS1_3_VERSION) && defined(SSL_OP_NO_TLSv1_3) #define TLS_PROTOCOL_TLSv1_3 (1<<5) /* TLSv1_3 */ #else -#define SSL_TXT_TLSV1_3 "TLSv1.3" #define TLS_PROTOCOL_TLSv1_3 0 /* Unknown */ #undef SSL_OP_NO_TLSv1_3 #define SSL_OP_NO_TLSv1_3 0L /* Noop */ @@ -382,7 +419,7 @@ extern void tls_param_init(void); #define TLS_KNOWN_PROTOCOLS \ ( TLS_PROTOCOL_SSLv2 | TLS_PROTOCOL_SSLv3 | TLS_PROTOCOL_TLSv1 \ - | TLS_PROTOCOL_TLSv1_1 | TLS_PROTOCOL_TLSv1_2 ) + | TLS_PROTOCOL_TLSv1_1 | TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3 ) #define TLS_SSL_OP_PROTOMASK(m) \ ((((m) & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L) \ | (((m) & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L) \ @@ -420,10 +457,15 @@ extern const NAME_CODE tls_cipher_grade_table[]; /* * Cipher lists with exclusions. */ -extern const char *tls_set_ciphers(TLS_APPL_STATE *, const char *, - const char *, const char *); +extern const char *tls_set_ciphers(TLS_SESS_STATE *, const char *, + const char *); -#endif + /* + * Populate TLS context with TLS 1.3-related signature parameters. + */ +extern void tls_get_signature_params(TLS_SESS_STATE *); + +#endif /* TLS_INTERNAL */ /* * tls_client.c @@ -433,6 +475,7 @@ typedef struct { const char *log_level; int verifydepth; const char *cache_type; + const char *chain_files; const char *cert_file; const char *key_file; const char *dcert_file; @@ -447,11 +490,13 @@ typedef struct { typedef struct { TLS_APPL_STATE *ctx; VSTREAM *stream; + int fd; /* Event-driven file descriptor */ int timeout; int tls_level; /* Security level */ const char *nexthop; /* destination domain */ const char *host; /* MX hostname */ const char *namaddr; /* nam[addr] for logging */ + const char *sni; /* optional SNI name when not DANE */ const char *serverid; /* Session cache key */ const char *helo; /* Server name from EHLO response */ const char *protocols; /* Enabled protocols */ @@ -459,28 +504,36 @@ typedef struct { const char *cipher_exclusions; /* Ciphers to exclude */ const ARGV *matchargv; /* Cert match patterns */ const char *mdalg; /* default message digest algorithm */ - const TLS_DANE *dane; /* RFC 6698 verification */ + const TLS_DANE *dane; /* DANE TLSA verification */ } TLS_CLIENT_START_PROPS; extern TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *); extern TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *); +extern TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *, + const TLS_CLIENT_START_PROPS *); #define tls_client_stop(ctx, stream, timeout, failure, TLScontext) \ tls_session_stop(ctx, (stream), (timeout), (failure), (TLScontext)) -#define TLS_CLIENT_INIT(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ - a10, a11, a12, a13) \ - tls_client_init((((props)->a1), ((props)->a2), ((props)->a3), \ +#define TLS_CLIENT_INIT_ARGS(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ + a10, a11, a12, a13, a14) \ + (((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))) + ((props)->a12), ((props)->a13), ((props)->a14), (props)) + +#define TLS_CLIENT_INIT(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ + a10, a11, a12, a13, a14) \ + tls_client_init(TLS_CLIENT_INIT_ARGS(props, a1, a2, a3, a4, a5, \ + 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) \ + a10, a11, a12, a13, a14, a15, a16, a17) \ 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))) + ((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15), \ + ((props)->a16), ((props)->a17), (props))) /* * tls_server.c @@ -491,6 +544,7 @@ typedef struct { int verifydepth; const char *cache_type; int set_sessid; + const char *chain_files; const char *cert_file; const char *key_file; const char *dcert_file; @@ -528,12 +582,13 @@ extern TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *); tls_session_stop(ctx, (stream), (timeout), (failure), (TLScontext)) #define TLS_SERVER_INIT(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ - a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) \ + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) \ tls_server_init((((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)->a18), ((props)->a19), (props))) + ((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) \ tls_server_start((((props)->a1), ((props)->a2), ((props)->a3), \ @@ -551,6 +606,8 @@ extern void tls_session_stop(TLS_APPL_STATE *, VSTREAM *, int, int, TLS_SESS_STA extern const char *tls_compile_version(void); extern const char *tls_run_version(void); extern const char **tls_pkey_algorithms(void); +extern void tls_log_summary(TLS_ROLE, TLS_USAGE, TLS_SESS_STATE *); +extern void tls_pre_jail_init(TLS_ROLE); #ifdef TLS_INTERNAL @@ -598,7 +655,8 @@ extern int tls_bio(int, int, TLS_SESS_STATE *, */ extern void tls_set_dh_from_file(const char *, int); extern DH *tls_tmp_dh_cb(SSL *, int, int); -extern int tls_set_eecdh_curve(SSL_CTX *, const char *); +extern void tls_set_eecdh_curve(SSL_CTX *, const char *); +extern void tls_auto_eecdh_curves(SSL_CTX *, const char *); /* * tls_rsa.c @@ -634,7 +692,8 @@ extern char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *, long, * tls_certkey.c */ extern int tls_set_ca_certificate_info(SSL_CTX *, const char *, const char *); -extern int tls_set_my_certificate_key_info(SSL_CTX *, +extern int tls_load_pem_chain(SSL *, const char *, const char *); +extern int tls_set_my_certificate_key_info(SSL_CTX *, /* All */ const char *, /* RSA */ const char *, const char *, /* DSA */ const char *, const char *, /* ECDSA */ const char *, const char *); @@ -644,7 +703,7 @@ extern int tls_set_my_certificate_key_info(SSL_CTX *, */ extern int TLScontext_index; -extern TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *, int); +extern TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *, SSL_CTX *, int); extern TLS_SESS_STATE *tls_alloc_sess_context(int, const char *); extern void tls_free_context(TLS_SESS_STATE *); extern void tls_check_version(void); @@ -672,6 +731,11 @@ extern int tls_ext_seed(int); /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Victor Duchovni /* Morgan Stanley /*--*/ diff --git a/external/ibm-public/postfix/dist/src/tls/tls_certkey.c b/external/ibm-public/postfix/dist/src/tls/tls_certkey.c index 3271c0fef27..97df6f5fb1e 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_certkey.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_certkey.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_certkey.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_certkey.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -14,16 +14,23 @@ /* const char *CAfile; /* const char *CApath; /* -/* int tls_set_my_certificate_key_info(ctx, cert_file, key_file, +/* int tls_set_my_certificate_key_info(ctx, chain_files, +/* cert_file, key_file, /* dcert_file, dkey_file, /* eccert_file, eckey_file) /* SSL_CTX *ctx; +/* const char *chain_files; /* const char *cert_file; /* const char *key_file; /* const char *dcert_file; /* const char *dkey_file; /* const char *eccert_file; /* const char *eckey_file; +/* +/* int tls_load_pem_chain(ssl, pem, origin); +/* SSL *ssl; +/* const char *pem; +/* const char *origin; /* DESCRIPTION /* OpenSSL supports two options to specify CA certificates: /* either one file CAfile that contains all CA certificates, @@ -40,7 +47,16 @@ /* certificates and private keys for the specified TLS server /* or client context. Up to 3 pairs of key pairs (RSA, DSA and /* ECDSA) may be specified; each certificate and key pair must -/* match. The result is -1 on failure, 0 on success. +/* match. The chain_files argument makes it possible to load +/* keys and certificates for more than 3 algorithms, via either +/* a single file, or a list of multiple files. The result is -1 +/* on failure, 0 on success. +/* +/* tls_load_pem_chain() loads one or more (key, cert, [chain]) +/* triples from an in-memory PEM blob. The "origin" argument +/* is used for error logging, to identify the provenance of the +/* PEM blob. "ssl" must be non-zero, and the keys and certificates +/* will be loaded into that object. /* LICENSE /* .ad /* .fi @@ -60,6 +76,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -81,6 +102,452 @@ #define TLS_INTERNAL #include <tls.h> +#define PEM_LOAD_STATE_NOGO -2 /* Unusable object or sequence */ +#define PEM_LOAD_STATE_FAIL -1 /* Error in libcrypto */ +#define PEM_LOAD_STATE_DONE 0 /* End of PEM file, return value only */ +#define PEM_LOAD_STATE_INIT 1 /* No PEM objects seen */ +#define PEM_LOAD_STATE_PKEY 2 /* Last object was a private key */ +#define PEM_LOAD_STATE_CERT 3 /* Last object was a certificate */ +#define PEM_LOAD_STATE_BOTH 4 /* Unordered, key + first cert seen */ + +#define PEM_LOAD_READ_LAST 0 /* Reading last file */ +#define PEM_LOAD_READ_MORE 1 /* More files to be read */ + +typedef struct pem_load_state_t { + const char *origin; /* PEM chain origin description */ + const char *source; /* PEM BIO origin description */ + const char *keysrc; /* Source of last key */ + BIO *pembio; /* PEM input stream */ + SSL_CTX *ctx; /* SSL connection factory */ + SSL *ssl; /* SSL connection handle */ + EVP_PKEY *pkey; /* current key */ + X509 *cert; /* current certificate */ + x509_stack_t *chain; /* current chain */ + int keynum; /* Index of last key */ + int objnum; /* Index in current source */ + int state; /* Current state, never "DONE" */ + int mixed; /* Single file with key anywhere */ +} pem_load_state_t; + +/* init_pem_load_state - fill in initial pem_load_state structure */ + +static void init_pem_load_state(pem_load_state_t *st, SSL_CTX *ctx, SSL *ssl, + const char *origin) +{ + st->origin = origin; + st->source = origin; + st->keysrc = 0; + st->pembio = 0; + st->ctx = ctx; + st->ssl = ssl; + st->pkey = 0; + st->cert = 0; + st->chain = 0; + st->keynum = 0; + st->objnum = 0; + st->state = PEM_LOAD_STATE_INIT; + st->mixed = 0; +} + +/* use_chain - load cert, key and chain into ctx or ssl */ + +#if OPENSSL_VERSION_NUMBER >= 0x1010100fUL +static int use_chain(pem_load_state_t *st) +{ + int ret; + int replace = 0; + + /* + * With replace == 0, an error is returned if the algorithm slot is + * already taken, and a previous key + chain of the same type would be + * clobbered. + */ + if (st->ctx) + ret = SSL_CTX_use_cert_and_key(st->ctx, st->cert, st->pkey, st->chain, + replace); + else + ret = SSL_use_cert_and_key(st->ssl, st->cert, st->pkey, st->chain, + replace); + + /* + * SSL_[CTX_]_use_cert_key() uprefs all the objects in question, so we + * must free ours. + */ + X509_free(st->cert); + st->cert = 0; + EVP_PKEY_free(st->pkey); + st->pkey = 0; + sk_X509_pop_free(st->chain, X509_free); + st->chain = 0; + + return ret; +} + +#else + +/* Legacy OpenSSL 1.0.2 and 1.1.0 interface */ +static int use_chain(pem_load_state_t *st) +{ + int ret = 1; + +#define TRY(op, o) \ + ((st->ctx && SSL_CTX_##op(st->ctx, st->o)) || \ + (st->ssl && SSL_##op(st->ssl, st->o))) + + /* + * This ensures the cert and key have the same type and match. A similar + * check is performed in use_PrivateKey(), but only if if the key and + * cert are of the same type. + */ + if (!X509_check_private_key(st->cert, st->pkey)) + ret = 0; + + /* + * XXX: With OpenSSL 1.0.2, setting the certificate clears any previous + * mismatched key of the same type, so we don't detect conflicting chains + * for the same algorithm, and silently use the last one. + */ + + /* use_certificate() increments the refcount */ + if (ret && !TRY(use_certificate, cert)) + ret = 0; + X509_free(st->cert); + st->cert = 0; + + /* use_PrivateKey() increments the refcount */ + if (ret && !TRY(use_PrivateKey, pkey)) + ret = 0; + EVP_PKEY_free(st->pkey); + st->pkey = 0; + + /* set0_chain() does not increment the refcount */ + if (!ret || !(ret = TRY(set0_chain, chain))) + sk_X509_pop_free(st->chain, X509_free); + /* The chain is now owned by the SSL library or freed, zero for next use */ + st->chain = 0; + + return ret; +} + +#endif + +/* load_cert - decode and load a DER-encoded X509 certificate */ + +static void load_cert(pem_load_state_t *st, unsigned char *buf, + long buflen) +{ + const unsigned char *p = buf; + X509 *cert = d2i_X509(0, &p, buflen); + + /* + * When expecting one or more keys, each key must precede the associated + * certificate (chain). + */ + if (!st->mixed && st->state == PEM_LOAD_STATE_INIT) { + msg_warn("error loading chain from %s: key not first", st->source); + if (cert) + X509_free(cert); + st->state = PEM_LOAD_STATE_NOGO; + return; + } + if (!cert) { + msg_warn("error loading certificate (PEM object number %d) from %s", + st->objnum, st->source); + st->state = PEM_LOAD_STATE_FAIL; + return; + } + if (p - buf != buflen) { + msg_warn("error loading certificate (PEM object number %d) from %s:" + " excess data", st->objnum, st->source); + X509_free(cert); + st->state = PEM_LOAD_STATE_NOGO; + return; + } + + /* + * The first certificate after a new key becomes the leaf certificate for + * that key. Subsequent certificates are added to the issuer chain. + * + * In "mixed" mode, the first certificate is either after the key, or else + * comes first. + */ + switch (st->state) { + case PEM_LOAD_STATE_PKEY: + st->cert = cert; + st->state = st->mixed ? PEM_LOAD_STATE_BOTH : PEM_LOAD_STATE_CERT; + return; + case PEM_LOAD_STATE_INIT: + st->cert = cert; + st->state = PEM_LOAD_STATE_CERT; + return; + case PEM_LOAD_STATE_CERT: + case PEM_LOAD_STATE_BOTH: + if ((!st->chain && (st->chain = sk_X509_new_null()) == 0) + || !sk_X509_push(st->chain, cert)) { + X509_free(cert); + st->state = PEM_LOAD_STATE_FAIL; + } + return; + } +} + +/* load_pkey - decode and load a DER-encoded private key */ + +static void load_pkey(pem_load_state_t *st, int pkey_type, + unsigned char *buf, long buflen) +{ + const char *myname = "load_pkey"; + const unsigned char *p = buf; + PKCS8_PRIV_KEY_INFO *p8; + EVP_PKEY *pkey = 0; + + /* + * Keys are either algorithm-specific, or else (ideally) algorithm + * agnostic, in which case they are wrapped as PKCS#8 objects with an + * algorithm OID. + */ + if (pkey_type != NID_undef) { + pkey = d2i_PrivateKey(pkey_type, 0, &p, buflen); + } else { + p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, buflen); + if (p8) { + pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + } + } + + /* + * Except in "mixed" mode, where a single key appears anywhere in a file + * with multiple certificates, a given key is either at the first object + * we process, or occurs after a previous key and one or more associated + * certificates. Thus, encountering a key in a state other than "INIT" + * or "CERT" is an error, except in "mixed" mode where a second key is + * ignored with a warning. + */ + switch (st->state) { + case PEM_LOAD_STATE_CERT: + + /* + * When processing the key of a "next" chain, we're in the "CERT" + * state, and first complete the processing of the previous chain. + */ + if (!st->mixed && !use_chain(st)) { + msg_warn("error loading certificate chain: " + "key at index %d in %s does not match the certificate", + st->keynum, st->keysrc); + st->state = PEM_LOAD_STATE_FAIL; + return; + } + /* FALLTHROUGH */ + case PEM_LOAD_STATE_INIT: + + if (!pkey) { + msg_warn("error loading private key (PEM object number %d) from %s", + st->objnum, st->source); + st->state = PEM_LOAD_STATE_FAIL; + return; + } + /* Reject unexpected data beyond the end of the DER-encoded object */ + if (p - buf != buflen) { + msg_warn("error loading private key (PEM object number %d) from" + " %s: excess data", st->objnum, st->source); + EVP_PKEY_free(pkey); + st->state = PEM_LOAD_STATE_NOGO; + return; + } + /* All's well, update the state */ + st->pkey = pkey; + if (st->state == PEM_LOAD_STATE_INIT) + st->state = PEM_LOAD_STATE_PKEY; + else if (st->mixed) + st->state = PEM_LOAD_STATE_BOTH; + else + st->state = PEM_LOAD_STATE_PKEY; + return; + + case PEM_LOAD_STATE_PKEY: + case PEM_LOAD_STATE_BOTH: + if (pkey) + EVP_PKEY_free(pkey); + + /* XXX: Legacy behaviour was silent, should we stay silent? */ + if (st->mixed) { + msg_warn("ignoring 2nd key at index %d in %s after 1st at %d", + st->objnum, st->source, st->keynum); + return; + } + /* else back-to-back keys */ + msg_warn("error loading certificate chain: " + "key at index %d in %s not followed by a certificate", + st->keynum, st->keysrc); + st->state = PEM_LOAD_STATE_NOGO; + return; + + default: + msg_error("%s: internal error: bad state: %d", myname, st->state); + st->state = PEM_LOAD_STATE_NOGO; + return; + } +} + +/* load_pem_object - load next pkey or cert from open BIO */ + +static int load_pem_object(pem_load_state_t *st) +{ + char *name = 0; + char *header = 0; + unsigned char *buf = 0; + long buflen; + int pkey_type = NID_undef; + + if (!PEM_read_bio(st->pembio, &name, &header, &buf, &buflen)) { + if (ERR_GET_REASON(ERR_peek_last_error()) != PEM_R_NO_START_LINE) + return (st->state = PEM_LOAD_STATE_FAIL); + + ERR_clear_error(); + /* Clean EOF, preserve stored state for any next input file */ + return (PEM_LOAD_STATE_DONE); + } + if (strcmp(name, PEM_STRING_X509) == 0 + || strcmp(name, PEM_STRING_X509_OLD) == 0) { + load_cert(st, buf, buflen); + } else if (strcmp(name, PEM_STRING_PKCS8INF) == 0 + || ((pkey_type = EVP_PKEY_RSA) != NID_undef + && strcmp(name, PEM_STRING_RSA) == 0) + || ((pkey_type = EVP_PKEY_EC) != NID_undef + && strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) + || ((pkey_type = EVP_PKEY_DSA) != NID_undef + && strcmp(name, PEM_STRING_DSA) == 0)) { + load_pkey(st, pkey_type, buf, buflen); + } else if (!st->mixed) { + msg_warn("loading %s: ignoring PEM type: %s", st->source, name); + } + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(buf); + return (st->state); +} + +/* load_pem_bio - load all key/certs from bio and free the bio */ + +static int load_pem_bio(pem_load_state_t *st, int more) +{ + int state = st->state; + + /* Don't report old news */ + ERR_clear_error(); + + /* + * When "more" is PEM_LOAD_READ_MORE, more files will be loaded after the + * current file, and final processing for the last key and chain is + * deferred. + * + * When "more" is PEM_LOAD_READ_LAST, this is the last file in the list, and + * we validate the final chain. + * + * When st->mixed is true, this is the only file, and its key can occur at + * any location. In this case we load at most one key. + */ + for (st->objnum = 1; state > PEM_LOAD_STATE_DONE; ++st->objnum) { + state = load_pem_object(st); + if ((st->mixed && st->keynum == 0 && + (state == PEM_LOAD_STATE_PKEY || state == PEM_LOAD_STATE_BOTH)) + || (!st->mixed && state == PEM_LOAD_STATE_PKEY)) { + /* Squirrel-away the current key location */ + st->keynum = st->objnum; + st->keysrc = st->source; + } + } + /* We're responsible for unconditionally freeing the BIO */ + BIO_free(st->pembio); + + /* Success with current file, go back for more? */ + if (more == PEM_LOAD_READ_MORE && state >= PEM_LOAD_STATE_DONE) + return 0; + + /* + * If all is well so far, complete processing for the final chain. + */ + switch (st->state) { + case PEM_LOAD_STATE_FAIL: + tls_print_errors(); + break; + default: + break; + case PEM_LOAD_STATE_INIT: + msg_warn("No PEM data in %s", st->origin); + break; + case PEM_LOAD_STATE_PKEY: + msg_warn("No certs for key at index %d in %s", st->keynum, st->keysrc); + break; + case PEM_LOAD_STATE_CERT: + if (st->mixed) { + msg_warn("No private key found in %s", st->origin); + break; + } + /* FALLTHROUGH */ + case PEM_LOAD_STATE_BOTH: + /* use_chain() frees the key and certs, and zeroes the pointers */ + if (use_chain(st)) + return (0); + msg_warn("key at index %d in %s does not match next certificate", + st->keynum, st->keysrc); + tls_print_errors(); + break; + } + /* Free any left-over unused keys and certs */ + EVP_PKEY_free(st->pkey); + X509_free(st->cert); + sk_X509_pop_free(st->chain, X509_free); + + msg_warn("error loading private keys and certificates from: %s: %s", + st->origin, st->ctx ? "disabling TLS support" : + "aborting TLS handshake"); + return (-1); +} + +/* load_chain_files - load sequence of (key, cert, [chain]) from files */ + +static int load_chain_files(SSL_CTX *ctx, const char *chain_files) +{ + pem_load_state_t st; + ARGV *files = argv_split(chain_files, CHARS_COMMA_SP); + char **filep; + int ret = 0; + int more; + + init_pem_load_state(&st, ctx, 0, chain_files); + for (filep = files->argv; ret == 0 && *filep; ++filep) { + st.source = *filep; + if ((st.pembio = BIO_new_file(st.source, "r")) == NULL) { + msg_warn("error opening chain file: %s: %m", st.source); + st.state = PEM_LOAD_STATE_NOGO; + break; + } + more = filep[1] ? PEM_LOAD_READ_MORE : PEM_LOAD_READ_LAST; + /* load_pem_bio() frees the BIO */ + ret = load_pem_bio(&st, more); + } + argv_free(files); + return (ret); +} + +/* load_mixed_file - load certs with single key anywhere in the file */ + +static int load_mixed_file(SSL_CTX *ctx, const char *file) +{ + pem_load_state_t st; + + init_pem_load_state(&st, ctx, 0, file); + if ((st.pembio = BIO_new_file(st.source, "r")) == NULL) { + msg_warn("error opening chain file: %s: %m", st.source); + return (-1); + } + st.mixed = 1; + /* load_pem_bio() frees the BIO */ + return load_pem_bio(&st, PEM_LOAD_READ_LAST); +} + /* tls_set_ca_certificate_info - load Certification Authority certificates */ int tls_set_ca_certificate_info(SSL_CTX *ctx, const char *CAfile, @@ -124,8 +591,15 @@ static int set_cert_stuff(SSL_CTX *ctx, const char *cert_type, { /* + * When the certfile and keyfile are one and the same, load both in a + * single pass, avoiding potential race conditions during key rollover. + */ + if (strcmp(cert_file, key_file) == 0) + return (load_mixed_file(ctx, cert_file) == 0); + + /* * We need both the private key (in key_file) and the public key - * certificate (in cert_file). Both may specify the same file. + * certificate (in cert_file). * * Code adapted from OpenSSL apps/s_cb.c. */ @@ -156,7 +630,7 @@ static int set_cert_stuff(SSL_CTX *ctx, const char *cert_type, /* tls_set_my_certificate_key_info - load client or server certificates/keys */ -int tls_set_my_certificate_key_info(SSL_CTX *ctx, +int tls_set_my_certificate_key_info(SSL_CTX *ctx, const char *chain_files, const char *cert_file, const char *key_file, const char *dcert_file, @@ -165,15 +639,19 @@ int tls_set_my_certificate_key_info(SSL_CTX *ctx, const char *eckey_file) { + /* The "chain_files" parameter overrides all the legacy parameters */ + if (chain_files && *chain_files) + return load_chain_files(ctx, chain_files); + /* * Lack of certificates is fine so long as we are prepared to use * anonymous ciphers. */ if (*cert_file && !set_cert_stuff(ctx, "RSA", cert_file, key_file)) - return (-1); /* logged */ + return (-1); /* logged */ if (*dcert_file && !set_cert_stuff(ctx, "DSA", dcert_file, dkey_file)) return (-1); /* logged */ -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH) +#ifndef OPENSSL_NO_ECDH if (*eccert_file && !set_cert_stuff(ctx, "ECDSA", eccert_file, eckey_file)) return (-1); /* logged */ #else @@ -184,4 +662,122 @@ int tls_set_my_certificate_key_info(SSL_CTX *ctx, return (0); } +/* tls_load_pem_chain - load in-memory PEM client or server chain */ + +int tls_load_pem_chain(SSL *ssl, const char *pem, const char *origin) +{ + static VSTRING *obuf; + pem_load_state_t st; + + if (!obuf) + obuf = vstring_alloc(100); + vstring_sprintf(obuf, "SNI data for %s", origin); + init_pem_load_state(&st, 0, ssl, vstring_str(obuf)); + + if ((st.pembio = BIO_new_mem_buf(pem, -1)) == NULL) { + msg_warn("error opening memory BIO for %s", st.origin); + tls_print_errors(); + return (-1); + } + /* load_pem_bio() frees the BIO */ + return (load_pem_bio(&st, PEM_LOAD_READ_LAST)); +} + +#ifdef TEST + +static NORETURN usage(void) +{ + fprintf(stderr, "usage: tls_certkey [-m] <chainfiles>\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int ch; + int mixed = 0; + int ret; + char *key_file = 0; + SSL_CTX *ctx; + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + + /* + * Initialize the OpenSSL library by the book! To start with, we must + * initialize the algorithms. We want cleartext error messages instead of + * just error codes, so we load the error_strings. + */ + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); +#endif + + if (!(ctx = SSL_CTX_new(TLS_client_method()))) { + tls_print_errors(); + exit(1); + } + while ((ch = GETOPT(argc, argv, "mk:")) > 0) { + switch (ch) { + case 'k': + key_file = optarg; + break; + case 'm': + mixed = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + if (key_file) + ret = set_cert_stuff(ctx, "any", argv[0], key_file) == 0; + else if (mixed) + ret = load_mixed_file(ctx, argv[0]); + else + ret = load_chain_files(ctx, argv[0]); + + if (ret != 0) + exit(1); + + if (SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST) != 1) { + fprintf(stderr, "error selecting first certificate\n"); + tls_print_errors(); + exit(1); + } + do { + STACK_OF(X509) *chain; + int i; + + if (SSL_CTX_get0_chain_certs(ctx, &chain) != 1) { + fprintf(stderr, "error locating certificate chain\n"); + tls_print_errors(); + exit(1); + } + for (i = 0; i <= sk_X509_num(chain); ++i) { + char buf[CCERT_BUFSIZ]; + X509 *cert; + + if (i > 0) + cert = sk_X509_value(chain, i - 1); + else + cert = SSL_CTX_get0_certificate(ctx); + + printf("depth = %d\n", i); + + X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); + printf("issuer = %s\n", buf); + + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); + printf("subject = %s\n\n", buf); + } + } while (SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT) != 0); + + exit(0); +} + +#endif + #endif diff --git a/external/ibm-public/postfix/dist/src/tls/tls_client.c b/external/ibm-public/postfix/dist/src/tls/tls_client.c index de2ae63ccd2..53d68183859 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_client.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_client.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_client.c,v 1.10 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_client.c,v 1.11 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -14,6 +14,10 @@ /* TLS_SESS_STATE *tls_client_start(start_props) /* const TLS_CLIENT_START_PROPS *start_props; /* +/* TLS_SESS_STATE *tls_client_post_connect(TLScontext, start_props) +/* TLS_SESS_STATE *TLScontext; +/* const TLS_CLIENT_START_PROPS *start_props; +/* /* void tls_client_stop(app_ctx, stream, failure, TLScontext) /* TLS_APPL_STATE *app_ctx; /* VSTREAM *stream; @@ -98,6 +102,31 @@ /* the fingerprint of the certificate. /* .PP /* If no peer certificate is presented the peer_status is set to 0. +/* EVENT_DRIVEN APPLICATIONS +/* .ad +/* .fi +/* Event-driven programs manage multiple I/O channels. Such +/* programs cannot use the synchronous VSTREAM-over-TLS +/* implementation that the TLS library historically provides, +/* including tls_client_stop() and the underlying tls_stream(3) +/* and tls_bio_ops(3) routines. +/* +/* With the current TLS library implementation, this means +/* that an event-driven application is responsible for calling +/* and retrying SSL_connect(), SSL_read(), SSL_write() and +/* SSL_shutdown(). +/* +/* To maintain control over TLS I/O, an event-driven client +/* invokes tls_client_start() with a null VSTREAM argument and +/* with an fd argument that specifies the I/O file descriptor. +/* Then, tls_client_start() performs all the necessary +/* preparations before the TLS handshake and returns a partially +/* populated TLS context. The event-driven application is then +/* responsible for invoking SSL_connect(), and if successful, +/* for invoking tls_client_post_connect() to finish the work +/* that was started by tls_client_start(). In case of unrecoverable +/* failure, tls_client_post_connect() destroys the TLS context +/* and returns a null pointer value. /* LICENSE /* .ad /* .fi @@ -118,6 +147,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Victor Duchovni /* Morgan Stanley /*--*/ @@ -352,17 +386,9 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) * we want to be as compatible as possible, so we will start off with a * SSLv2 greeting allowing the best we can offer: TLSv1. We can restrict * this with the options setting later, anyhow. - * - * OpenSSL 1.1.0-dev deprecates SSLv23_client_method() in favour of - * TLS_client_method(), with the change in question signalled via a new - * TLS_ANY_VERSION macro. */ ERR_clear_error(); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && defined(TLS_ANY_VERSION) client_ctx = SSL_CTX_new(TLS_client_method()); -#else - client_ctx = SSL_CTX_new(SSLv23_client_method()); -#endif if (client_ctx == 0) { msg_warn("cannot allocate client SSL_CTX: disabling TLS support"); tls_print_errors(); @@ -429,6 +455,7 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) * uses certificates). */ if (tls_set_my_certificate_key_info(client_ctx, + props->chain_files, props->cert_file, props->key_file, props->dcert_file, @@ -454,6 +481,13 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) #endif /* + * With OpenSSL 1.0.2 and later the client EECDH curve list becomes + * configurable with the preferred curve negotiated via the supported + * curves extension. + */ + tls_auto_eecdh_curves(client_ctx, var_tls_eecdh_auto); + + /* * Finally, the setup for the server certificate checking, done "by the * book". */ @@ -481,7 +515,7 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) * Allocate an application context, and populate with mandatory protocol * and cipher data. */ - app_ctx = tls_alloc_app_context(client_ctx, log_mask); + app_ctx = tls_alloc_app_context(client_ctx, 0, log_mask); /* * The external session cache is implemented by the tlsmgr(8) process. @@ -840,10 +874,9 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) int protomask; const char *cipher_list; SSL_SESSION *session = 0; - SSL_CIPHER_const SSL_CIPHER *cipher; - X509 *peercert; TLS_SESS_STATE *TLScontext; TLS_APPL_STATE *app_ctx = props->ctx; + const char *sni = 0; char *myserverid; int log_mask = app_ctx->log_mask; @@ -877,17 +910,35 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) protomask |= TLS_PROTOCOL_SSLv2; /* + * Allocate a new TLScontext for the new connection and get an SSL + * structure. Add the location of TLScontext to the SSL to later retrieve + * the information inside the tls_verify_certificate_callback(). + * + * If session caching was enabled when TLS was initialized, the cache type + * is stored in the client SSL context. + */ + TLScontext = tls_alloc_sess_context(log_mask, props->namaddr); + TLScontext->cache_type = app_ctx->cache_type; + + if ((TLScontext->con = SSL_new(app_ctx->ssl_ctx)) == NULL) { + msg_warn("Could not allocate 'TLScontext->con' with SSL_new()"); + tls_print_errors(); + tls_free_context(TLScontext); + return (0); + } + + /* * Per session cipher selection for sessions with mandatory encryption * * The cipherlist is applied to the global SSL context, since it is likely * to stay the same between connections, so we make use of a 1-element * cache to return the same result for identical inputs. */ - cipher_list = tls_set_ciphers(app_ctx, "TLS", props->cipher_grade, + cipher_list = tls_set_ciphers(TLScontext, props->cipher_grade, props->cipher_exclusions); if (cipher_list == 0) { - msg_warn("%s: %s: aborting TLS session", - props->namaddr, vstring_str(app_ctx->why)); + /* already warned */ + tls_free_context(TLScontext); return (0); } if (log_mask & TLS_LOG_VERBOSE) @@ -918,17 +969,6 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) */ myserverid = tls_serverid_digest(props, protomask, cipher_list); - /* - * Allocate a new TLScontext for the new connection and get an SSL - * structure. Add the location of TLScontext to the SSL to later retrieve - * the information inside the tls_verify_certificate_callback(). - * - * If session caching was enabled when TLS was initialized, the cache type - * is stored in the client SSL context. - */ - TLScontext = tls_alloc_sess_context(log_mask, props->namaddr); - TLScontext->cache_type = app_ctx->cache_type; - TLScontext->serverid = myserverid; TLScontext->stream = props->stream; TLScontext->mdalg = props->mdalg; @@ -936,12 +976,6 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) /* Alias DANE digest info from props */ TLScontext->dane = props->dane; - if ((TLScontext->con = SSL_new(app_ctx->ssl_ctx)) == NULL) { - msg_warn("Could not allocate 'TLScontext->con' with SSL_new()"); - tls_print_errors(); - tls_free_context(TLScontext); - return (0); - } if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) { msg_warn("Could not set application data for 'TLScontext->con'"); tls_print_errors(); @@ -974,8 +1008,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) } } #ifdef TLSEXT_MAXLEN_host_name - if (TLS_DANE_BASED(props->tls_level) - && strlen(props->host) <= TLSEXT_MAXLEN_host_name) { + if (TLS_DANE_BASED(props->tls_level)) { /* * With DANE sessions, send an SNI hint. We don't care whether the @@ -988,19 +1021,41 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) * SMTP server). * * Since the hostname is DNSSEC-validated, it must be a DNS FQDN and - * thererefore valid for use with SNI. Failure to set a valid SNI - * hostname is a memory allocation error, and thus transient. Since - * we must not cache the session if we failed to send the SNI name, - * we have little choice but to abort. + * thererefore valid for use with SNI. */ - if (!SSL_set_tlsext_host_name(TLScontext->con, props->host)) { + sni = props->host; + } else if (props->sni && *props->sni) { + if (strcmp(props->sni, "hostname") == 0) + sni = props->host; + else if (strcmp(props->sni, "nexthop") == 0) + sni = props->nexthop; + else + sni = props->sni; + } + if (sni && strlen(sni) <= TLSEXT_MAXLEN_host_name) { + + /* + * Failure to set a valid SNI hostname is a memory allocation error, + * and thus transient. Since we must not cache the session if we + * failed to send the SNI name, we have little choice but to abort. + */ + if (!SSL_set_tlsext_host_name(TLScontext->con, sni)) { msg_warn("%s: error setting SNI hostname to: %s", props->namaddr, - props->host); + sni); tls_free_context(TLScontext); return (0); } + + /* + * The saved value is not presently used client-side, but could later + * be logged if acked by the server (requires new client-side + * callback to detect the ack). For now this just maintains symmetry + * with the server code, where do record the received SNI for + * logging. + */ + TLScontext->peer_sni = mystrdup(sni); if (log_mask & TLS_LOG_DEBUG) - msg_info("%s: SNI hostname: %s", props->namaddr, props->host); + msg_info("%s: SNI hostname: %s", props->namaddr, sni); } #endif @@ -1012,16 +1067,10 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) (void) tls_ext_seed(var_tls_daemon_rand_bytes); /* - * Initialize the SSL connection to connect state. This should not be - * necessary anymore since 0.9.3, but the call is still in the library - * and maintaining compatibility never hurts. - */ - SSL_set_connect_state(TLScontext->con); - - /* * Connect the SSL connection with the network socket. */ - if (SSL_set_fd(TLScontext->con, vstream_fileno(props->stream)) != 1) { + if (SSL_set_fd(TLScontext->con, props->stream == 0 ? props->fd : + vstream_fileno(props->stream)) != 1) { msg_info("SSL_set_fd error to %s", props->namaddr); tls_print_errors(); uncache_session(app_ctx->ssl_ctx, TLScontext); @@ -1030,12 +1079,6 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) } /* - * Turn on non-blocking I/O so that we can enforce timeouts on network - * I/O. - */ - non_blocking(vstream_fileno(props->stream), NON_BLOCKING); - - /* * If the debug level selected is high enough, all of the data is dumped: * TLS_LOG_TLSPKTS will dump the SSL negotiation, TLS_LOG_ALLPKTS will * dump everything. @@ -1050,10 +1093,23 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) tls_dane_set_callback(app_ctx->ssl_ctx, TLScontext); /* + * If we don't trigger the handshake in the library, leave control over + * SSL_connect/read/write/etc with the application. + */ + if (props->stream == 0) + return (TLScontext); + + /* + * Turn on non-blocking I/O so that we can enforce timeouts on network + * I/O. + */ + non_blocking(vstream_fileno(props->stream), NON_BLOCKING); + + /* * Start TLS negotiations. This process is a black box that invokes our * call-backs for certificate verification. * - * Error handling: If the SSL handhake fails, we print out an error message + * Error handling: If the SSL handshake fails, we print out an error message * and remove all TLS state concerning this session. */ sts = tls_bio_connect(vstream_fileno(props->stream), props->timeout, @@ -1072,8 +1128,19 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) tls_free_context(TLScontext); return (0); } + return (tls_client_post_connect(TLScontext, props)); +} + +/* tls_client_post_connect - post-handshake processing */ + +TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext, + const TLS_CLIENT_START_PROPS *props) +{ + const SSL_CIPHER *cipher; + X509 *peercert; + /* Turn off packet dump if only dumping the handshake */ - if ((log_mask & TLS_LOG_ALLPKTS) == 0) + if ((TLScontext->log_mask & TLS_LOG_ALLPKTS) == 0) BIO_set_callback(SSL_get_rbio(TLScontext->con), 0); /* @@ -1081,7 +1148,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) * session was negotiated. */ TLScontext->session_reused = SSL_session_reused(TLScontext->con); - if ((log_mask & TLS_LOG_CACHE) && TLScontext->session_reused) + if ((TLScontext->log_mask & TLS_LOG_CACHE) && TLScontext->session_reused) msg_info("%s: Reusing old session", TLScontext->namaddr); /* @@ -1128,7 +1195,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) * The TLS engine is active. Switch to the tls_timed_read/write() * functions and make the TLScontext available to those functions. */ - tls_stream_start(props->stream, TLScontext); + if (TLScontext->stream != 0) + tls_stream_start(props->stream, TLScontext); /* * Fully secured only if trusted, matched and not insecure like halfdane. @@ -1143,16 +1211,12 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) TLScontext->peer_status |= TLS_CERT_FLAG_SECURED; /* - * All the key facts in a single log entry. + * With the handshake done, extract TLS 1.3 signature metadata. */ - if (log_mask & TLS_LOG_SUMMARY) - msg_info("%s TLS connection established to %s: %s with cipher %s " - "(%d/%d bits)", - !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" : - TLS_CERT_IS_SECURED(TLScontext) ? "Verified" : - TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted", - props->namaddr, TLScontext->protocol, TLScontext->cipher_name, - TLScontext->cipher_usebits, TLScontext->cipher_algbits); + tls_get_signature_params(TLScontext); + + if (TLScontext->log_mask & TLS_LOG_SUMMARY) + tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW, TLScontext); tls_int_seed(); diff --git a/external/ibm-public/postfix/dist/src/tls/tls_dane.c b/external/ibm-public/postfix/dist/src/tls/tls_dane.c index 55593a76c06..ff56ff0da6a 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_dane.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_dane.c @@ -1,10 +1,10 @@ -/* $NetBSD: tls_dane.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_dane.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME /* tls_dane 3 /* SUMMARY -/* Support for RFC 6698 (DANE) certificate matching +/* Support for RFC 6698, 7671, 7672 (DANE) certificate matching /* SYNOPSIS /* #include <tls.h> /* @@ -156,6 +156,11 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* /* Viktor Dukhovni /*--*/ @@ -202,41 +207,10 @@ /* Application-specific. */ -#undef TRUST_ANCHOR_SUPPORT #undef DANE_TLSA_SUPPORT -#undef WRAP_SIGNED - -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL && \ - (defined(X509_V_FLAG_PARTIAL_CHAIN) || !defined(OPENSSL_NO_ECDH)) -#define TRUST_ANCHOR_SUPPORT - -#ifndef X509_V_FLAG_PARTIAL_CHAIN -#define WRAP_SIGNED -#endif #if defined(TLSEXT_MAXLEN_host_name) && RES_USE_DNSSEC && RES_USE_EDNS0 #define DANE_TLSA_SUPPORT -#endif - -#endif /* OPENSSL_VERSION_NUMBER ... */ - -#ifdef TRUST_ANCHOR_SUPPORT -static int ta_support = 1; - -#else -static int ta_support = 0; - -#endif - -#ifdef WRAP_SIGNED -static int wrap_signed = 1; - -#else -static int wrap_signed = 0; - -#endif - -#ifdef DANE_TLSA_SUPPORT static int dane_tlsa_support = 1; #else @@ -244,8 +218,6 @@ static int dane_tlsa_support = 0; #endif -static EVP_PKEY *signkey; -static const EVP_MD *signmd; static const char *signalg; static ASN1_OBJECT *serverAuth; @@ -275,18 +247,6 @@ typedef struct dane_digest { #define MAXDIGESTS 256 /* RFC limit */ static dane_digest *digest_list; -static int digest_agility = -1; - -#define AGILITY_OFF 0 -#define AGILITY_ON 1 -#define AGILITY_MAYBE 2 - -static NAME_CODE agility[] = { - {TLS_DANE_AGILITY_OFF, AGILITY_OFF}, - {TLS_DANE_AGILITY_ON, AGILITY_ON}, - {TLS_DANE_AGILITY_MAYBE, AGILITY_MAYBE}, - {0, -1} -}; /* * This is not intended to be a long-term cache of pre-parsed TLSA data, @@ -426,36 +386,6 @@ static int digest_pref_byid(uint8_t dane_id) return (d ? (d->pref) : (MAXDIGESTS + dane_id)); } -/* gencakey - generate interal DANE root CA key */ - -static EVP_PKEY *gencakey(void) -{ - EVP_PKEY *key = 0; - -#ifdef WRAP_SIGNED - EC_KEY *eckey; - EC_GROUP *group = 0; - - ERR_clear_error(); - - if ((eckey = EC_KEY_new()) != 0 - && (group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) != 0 - && (EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE), - EC_KEY_set_group(eckey, group)) - && EC_KEY_generate_key(eckey) - && (key = EVP_PKEY_new()) != 0 - && !EVP_PKEY_set1_EC_KEY(key, eckey)) { - EVP_PKEY_free(key); - key = 0; - } - if (group) - EC_GROUP_free(group); - if (eckey) - EC_KEY_free(eckey); -#endif /* WRAP_SIGNED */ - return (key); -} - /* dane_init - initialize DANE parameters */ static void dane_init(void) @@ -471,23 +401,18 @@ static void dane_init(void) * Add the full matching type at highest preference and then the users * configured list. * - * The most preferred digest will be used for cert signing and hashing full - * values for comparison. + * The most preferred digest will be used for hashing full values for + * comparison. */ - if ((digest_agility = name_code(agility, 0, var_tls_dane_agility)) < 0) { - msg_warn("Invalid %s syntax: %s. DANE support disabled.", - VAR_TLS_DANE_AGILITY, var_tls_dane_agility); - } else if (add_digest(fullmtype, 0)) { + if (add_digest(fullmtype, 0)) { save = cp = mystrdup(var_tls_dane_digests); while ((tok = mystrtok(&cp, CHARS_COMMA_SP)) != 0) { if ((d = add_digest(tok, ++digest_pref)) == 0) { signalg = 0; - signmd = 0; break; } if (digest_pref == 1) { signalg = d->mdalg; - signmd = d->md; } } myfree(save); @@ -496,17 +421,14 @@ static void dane_init(void) ERR_clear_error(); /* - * DANE TLSA support requires trust-anchor support plus working DANE - * digests. + * DANE TLSA support requires working DANE digests. */ - if (!ta_support - || (wrap_signed && (signkey = gencakey()) == 0) - || (serverAuth = OBJ_nid2obj(NID_server_auth)) == 0) { - msg_warn("cannot generate TA certificates, " - "no trust-anchor or DANE support"); + if ((serverAuth = OBJ_nid2obj(NID_server_auth)) == 0) { + msg_warn("cannot designate intermediate TA certificates, " + "no DANE support"); tls_print_errors(); - dane_tlsa_support = ta_support = 0; - } else if (signmd == 0) { + dane_tlsa_support = 0; + } else if (signalg == 0) { msg_warn("digest algorithm initializaton failed, no DANE support"); tls_print_errors(); dane_tlsa_support = 0; @@ -728,7 +650,6 @@ static void dane_add(TLS_DANE *dane, int certusage, int selector, case DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: certusage = TLS_DANE_TA; break; - case DNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: case DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: certusage = TLS_DANE_EE; /* Collapse 1/3 -> 3 */ break; @@ -757,9 +678,8 @@ static void dane_add(TLS_DANE *dane, int certusage, int selector, } #define FILTER_CTX_AGILITY_OK (1<<0) -#define FILTER_CTX_CHECK_AGILITY (1<<1) -#define FILTER_CTX_APPLY_AGILITY (1<<2) -#define FILTER_CTX_PARSE_DATA (1<<3) +#define FILTER_CTX_APPLY_AGILITY (1<<1) +#define FILTER_CTX_PARSE_DATA (1<<2) #define FILTER_RR_DROP 0 #define FILTER_RR_KEEP 1 @@ -851,8 +771,8 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) uint8_t selector; uint8_t mtype; ssize_t dlen; - D2I_const unsigned char *data; - D2I_const unsigned char *p; + const unsigned char *data; + const unsigned char *p; int iscname = strcasecmp(rr->rname, rr->qname); const char *q = (iscname) ? (rr)->qname : ""; const char *a = (iscname) ? " -> " : ""; @@ -875,7 +795,7 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) selector = *ip++; mtype = *ip++; change = usmdelta(usage, selector, mtype, rr->next); - p = data = (D2I_const unsigned char *) ip; + p = data = (const unsigned char *) ip; /* * Handle digest agility for non-zero matching types. @@ -886,31 +806,13 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) ctx->count = 0; /* disable drop */ return (FILTER_RR_DROP); } - if ((ctx->flags & FILTER_CTX_CHECK_AGILITY) - && (ctx->flags & FILTER_CTX_AGILITY_OK)) { - ++ctx->count; - if (change) { - /*- - * Count changed from last mtype for same usage/selector? - * Yes, disable agility. - * Else, set or (on usage/selector change) reset target. - */ - if (ctx->target && ctx->target != ctx->count) - ctx->flags &= ~FILTER_CTX_AGILITY_OK; - else - ctx->target = (change & 0xffff00) ? 0 : ctx->count; - ctx->count = 0; - } - } } /*- * Drop unsupported usages. - * Note: NO SUPPORT for usage 0 which does not apply to SMTP. - * Note: Best-effort support for usage 1, which simply maps to 3. + * Note: NO SUPPORT for usages 0/1 which do not apply to SMTP. */ switch (usage) { case DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: - case DNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: case DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: break; default: @@ -951,13 +853,6 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) ctx->flags &= ~FILTER_CTX_AGILITY_OK; return (FILTER_RR_DROP); } - if (!var_tls_dane_taa_dgst - && usage == DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION) { - msg_warn("trust-anchor digests disabled, ignoring RR: " - "%s%s%s IN TLSA %u %u %u ...", q, a, r, - usage, selector, mtype); - return (FILTER_RR_DROP); - } /* New digest mtype next? Prepare to drop following RRs */ if (change && (change & 0xffff00) == 0 && (ctx->flags & FILTER_CTX_APPLY_AGILITY)) @@ -1057,30 +952,10 @@ static DNS_RR *process_rrs(TLS_DANE *dane, DNS_RR *rrset) ctx.dane = dane; ctx.count = ctx.target = 0; - ctx.flags = 0; - - switch (digest_agility) { - case AGILITY_ON: - ctx.flags |= FILTER_CTX_APPLY_AGILITY | FILTER_CTX_PARSE_DATA; - break; - case AGILITY_OFF: - ctx.flags |= FILTER_CTX_PARSE_DATA; - break; - case AGILITY_MAYBE: - ctx.flags |= FILTER_CTX_CHECK_AGILITY | FILTER_CTX_AGILITY_OK; - break; - } + ctx.flags = FILTER_CTX_APPLY_AGILITY | FILTER_CTX_PARSE_DATA; rrset = tlsa_apply(rrset, parse_tlsa_rr, &ctx); - if (digest_agility == AGILITY_MAYBE) { - /* Two-pass algorithm */ - if (ctx.flags & FILTER_CTX_AGILITY_OK) - ctx.flags = FILTER_CTX_APPLY_AGILITY | FILTER_CTX_PARSE_DATA; - else - ctx.flags = FILTER_CTX_PARSE_DATA; - rrset = tlsa_apply(rrset, parse_tlsa_rr, &ctx); - } if (dane->ta == 0 && dane->ee == 0) dane->flags |= TLS_DANE_FLAG_EMPTY; @@ -1252,7 +1127,6 @@ TLS_DANE *tls_dane_resolve(unsigned port, const char *proto, DNS_RR *hostrr, int tls_dane_load_trustfile(TLS_DANE *dane, const char *tafile) { -#ifdef TRUST_ANCHOR_SUPPORT BIO *bp; char *name = 0; char *header = 0; @@ -1269,10 +1143,7 @@ int tls_dane_load_trustfile(TLS_DANE *dane, const char *tafile) if (!dane_initialized) dane_init(); - if (!ta_support) { - msg_warn("trust-anchor files not supported"); - return (0); - } + /* Per-destination TA support is available even when DANE is not */ mdalg = signalg ? signalg : "sha1"; /* @@ -1291,7 +1162,7 @@ int tls_dane_load_trustfile(TLS_DANE *dane, const char *tafile) for (tacount = 0; errtype == 0 && PEM_read_bio(bp, &name, &header, &data, &len); ++tacount) { - D2I_const unsigned char *p = data; + const unsigned char *p = data; int usage = DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION; int selector; char *digest; @@ -1347,9 +1218,6 @@ int tls_dane_load_trustfile(TLS_DANE *dane, const char *tafile) } /* Some other PEM read error */ tls_print_errors(); -#else - msg_warn("Trust anchor files not supported"); -#endif return (0); } @@ -1404,26 +1272,20 @@ int tls_dane_match(TLS_SESS_STATE *TLScontext, int usage, return (matched); } -/* push_ext - push extension onto certificate's stack, else free it */ - -static int push_ext(X509 *cert, X509_EXTENSION *ext) -{ - if (ext) { - if (X509_add_ext(cert, ext, -1)) - return 1; - X509_EXTENSION_free(ext); - } - return 0; -} - /* add_ext - add simple extension (no config section references) */ static int add_ext(X509 *issuer, X509 *subject, int ext_nid, char *ext_val) { + int ret = 0; X509V3_CTX v3ctx; + X509_EXTENSION *ext; X509V3_set_ctx(&v3ctx, issuer, subject, 0, 0, 0); - return push_ext(subject, X509V3_EXT_conf_nid(0, &v3ctx, ext_nid, ext_val)); + if ((ext = X509V3_EXT_conf_nid(0, &v3ctx, ext_nid, ext_val)) != 0) { + ret = X509_add_ext(subject, ext, -1); + X509_EXTENSION_free(ext); + } + return ret; } /* set_serial - set serial number to match akid or use subject's plus 1 */ @@ -1513,17 +1375,17 @@ static X509_NAME *akid_issuer_name(AUTHORITY_KEYID *akid) /* set_issuer - set issuer DN to match akid if specified */ -static int set_issuer_name(X509 *cert, AUTHORITY_KEYID *akid) +static int set_issuer_name(X509 *cert, AUTHORITY_KEYID *akid, X509_NAME *subj) { X509_NAME *name = akid_issuer_name(akid); /* - * If subject's akid specifies an authority key identifer issuer name, we - * must use that. + * If subject's akid specifies an authority key identifier issuer name, + * we must use that. */ if (name) return (X509_set_issuer_name(cert, name)); - return (X509_set_issuer_name(cert, X509_get_subject_name(cert))); + return (X509_set_issuer_name(cert, subj)); } /* grow_chain - add certificate to trusted or untrusted chain */ @@ -1577,33 +1439,23 @@ static void wrap_key(TLS_SESS_STATE *TLScontext, int depth, ERR_clear_error(); - /* - * If key is NULL generate a self-signed root CA, with key "signkey", - * otherwise an intermediate CA signed by above. - * - * CA cert valid for +/- 30 days. - */ + /* CA cert valid for +/- 30 days. */ if (!X509_set_version(cert, 2) || !set_serial(cert, akid, subject) - || !set_issuer_name(cert, akid) + || !set_issuer_name(cert, akid, name) || !X509_gmtime_adj(X509_getm_notBefore(cert), -30 * 86400L) || !X509_gmtime_adj(X509_getm_notAfter(cert), 30 * 86400L) || !X509_set_subject_name(cert, name) - || !X509_set_pubkey(cert, key ? key : signkey) + || !X509_set_pubkey(cert, key) || !add_ext(0, cert, NID_basic_constraints, "CA:TRUE") || (key && !add_akid(cert, akid)) - || !add_skid(cert, akid) - || (wrap_signed && !X509_sign(cert, signkey, signmd))) { + || !add_skid(cert, akid)) { tls_print_errors(); msg_fatal("error generating DANE wrapper certificate"); } if (akid) AUTHORITY_KEYID_free(akid); - if (key && wrap_signed) { - wrap_key(TLScontext, depth + 1, 0, cert); - grow_chain(TLScontext, UNTRUSTED, cert); - } else - grow_chain(TLScontext, TRUSTED, cert); + grow_chain(TLScontext, TRUSTED, cert); if (cert) X509_free(cert); } @@ -1612,11 +1464,6 @@ static void wrap_key(TLS_SESS_STATE *TLScontext, int depth, static void wrap_cert(TLS_SESS_STATE *TLScontext, X509 *tacert, int depth) { - X509 *cert; - int len; - unsigned char *asn1; - unsigned char *buf; - if (TLScontext->tadepth < 0) TLScontext->tadepth = depth + 1; @@ -1624,35 +1471,8 @@ static void wrap_cert(TLS_SESS_STATE *TLScontext, X509 *tacert, int depth) msg_info("%s: depth=%d trust-anchor certificate", TLScontext->namaddr, depth); - /* - * If the TA certificate is self-issued, use it directly. - */ - if (!wrap_signed || X509_check_issued(tacert, tacert) == X509_V_OK) { - grow_chain(TLScontext, TRUSTED, tacert); - return; - } - /* Deep-copy tacert by converting to ASN.1 and back */ - len = i2d_X509(tacert, NULL); - asn1 = buf = (unsigned char *) mymalloc(len); - i2d_X509(tacert, &buf); - if (buf - asn1 != len) - msg_panic("i2d_X509 failed to encode TA certificate"); - - buf = asn1; - cert = d2i_X509(0, (D2I_const unsigned char **) &buf, len); - if (!cert || (buf - asn1) != len) - msg_panic("d2i_X509 failed to decode TA certificate"); - myfree((void *) asn1); - - grow_chain(TLScontext, UNTRUSTED, cert); - - /* Sign and wrap TA cert with internal "signkey" */ - if (!X509_sign(cert, signkey, signmd)) { - tls_print_errors(); - msg_fatal("error generating DANE wrapper certificate"); - } - wrap_key(TLScontext, depth + 1, signkey, cert); - X509_free(cert); + grow_chain(TLScontext, TRUSTED, tacert); + return; } /* ta_signed - is certificate signed by a TLSA cert or pkey */ @@ -1846,7 +1666,7 @@ static int dane_cb(X509_STORE_CTX *ctx, void *app_ctx) void tls_dane_set_callback(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext) { - if (ta_support && TLS_DANE_HASTA(TLScontext->dane)) + if (TLS_DANE_HASTA(TLScontext->dane)) SSL_CTX_set_cert_verify_callback(ctx, dane_cb, (void *) TLScontext); else SSL_CTX_set_cert_verify_callback(ctx, 0, 0); @@ -1861,38 +1681,39 @@ void tls_dane_set_callback(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext) #include <mail_conf.h> #include <msg_vstream.h> -/* Cut/paste from OpenSSL 1.0.1: ssl/ssl_cert.c */ - -static int ssl_verify_cert_chain(SSL *s, x509_stack_t *sk) +static int verify_chain(SSL *ssl, x509_stack_t *chain, TLS_SESS_STATE *tctx) { - X509 *x; - int i; - X509_STORE_CTX ctx; - - if ((sk == NULL) || (sk_X509_num(sk) == 0)) - return (0); - - x = sk_X509_value(sk, 0); - if (!X509_STORE_CTX_init(&ctx, s->ctx->cert_store, x, sk)) { - SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB); - return (0); + int ret; + X509 *cert; + X509_STORE_CTX *store_ctx; + SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(ssl); + X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); + int store_ctx_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); + + cert = sk_X509_value(chain, 0); + if ((store_ctx = X509_STORE_CTX_new()) == NULL) { + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!X509_STORE_CTX_init(store_ctx, store, cert, chain)) { + X509_STORE_CTX_free(store_ctx); + return 0; } - X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s); - X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server"); - X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); + X509_STORE_CTX_set_ex_data(store_ctx, store_ctx_idx, ssl); - if (s->verify_callback) - X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); + X509_STORE_CTX_set_default(store_ctx, "ssl_server"); + X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(store_ctx), + SSL_get0_param(ssl)); - if (s->ctx->app_verify_callback != NULL) - i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); - else - i = X509_verify_cert(&ctx); + if (SSL_get_verify_callback(ssl)) + X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl)); + + ret = dane_cb(store_ctx, tctx); - s->verify_result = ctx.error; - X509_STORE_CTX_cleanup(&ctx); + SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(store_ctx)); + X509_STORE_CTX_free(store_ctx); - return (i); + return (ret); } static void add_tlsa(TLS_DANE *dane, char *argv[]) @@ -1908,6 +1729,28 @@ static void add_tlsa(TLS_DANE *dane, char *argv[]) const char *mdname = argv[3]; EVP_PKEY *pkey; + /* Unsupported usages are fatal */ + switch (u) { + case DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: + case DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: + break; + default: + msg_fatal("unsupported certificate usage %u", u); + } + + /* Unsupported selectors are fatal */ + switch (s) { + case DNS_TLSA_SELECTOR_FULL_CERTIFICATE: + case DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO: + break; + default: + msg_fatal("unsupported selector %u", s); + } + + /* Unsupported digests are fatal */ + if (*mdname && !tls_validate_digest(mdname)) + msg_fatal("unsupported digest algorithm: %s", mdname); + if ((bp = BIO_new_file(argv[4], "r")) == NULL) msg_fatal("error opening %s: %m", argv[4]); if (!PEM_read_bio_X509(bp, &cert, 0, 0)) { @@ -2178,7 +2021,7 @@ static SSL_CTX *ctx_init(const char *CAfile) msg_fatal("Cannot allocate SSL application data index"); ERR_clear_error(); - if ((client_ctx = SSL_CTX_new(SSLv23_client_method())) == 0) + if ((client_ctx = SSL_CTX_new(TLS_client_method())) == 0) msg_fatal("cannot allocate client SSL_CTX"); SSL_CTX_set_verify_depth(client_ctx, 5); @@ -2224,7 +2067,7 @@ int main(int argc, char *argv[]) /* Verify saved server chain */ chain = load_chain(argv[6]); - ssl_verify_cert_chain(tctx->con, chain); + verify_chain(tctx->con, chain, tctx); check_peer(tctx, sk_X509_value(chain, 0), argc - 7, argv + 7); tls_print_errors(); diff --git a/external/ibm-public/postfix/dist/src/tls/tls_dh.c b/external/ibm-public/postfix/dist/src/tls/tls_dh.c index 9744c7ce7f7..529d06659e8 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_dh.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_dh.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_dh.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_dh.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -13,7 +13,11 @@ /* const char *path; /* int bits; /* -/* int tls_set_eecdh_curve(server_ctx, grade) +/* void tls_auto_eecdh_curves(ctx, configured) +/* SSL_CTX *ctx; +/* char *configured; +/* +/* void tls_set_eecdh_curve(server_ctx, grade) /* SSL_CTX *server_ctx; /* const char *grade; /* @@ -32,6 +36,9 @@ /* is as expected by the PEM_read_DHparams() routine. The /* "bits" argument must be 512 or 1024. /* +/* tls_auto_eecdh_curves() enables negotiation of the most preferred curve +/* among the curves specified by the "configured" argument. +/* /* tls_set_eecdh_curve() enables ephemeral Elliptic-Curve DH /* key exchange algorithms by instantiating in the server SSL /* context a suitable curve (corresponding to the specified @@ -39,7 +46,9 @@ /* 4492 Section 5.1.1. Errors generate warnings, but do not /* disable TLS, rather we continue without EECDH. A zero /* result indicates that the grade is invalid or the corresponding -/* curve could not be used. +/* curve could not be used. The "auto" grade enables multiple +/* curves, with the actual curve chosen as the most preferred +/* among those supported by both the server and the client. /* DIAGNOSTICS /* In case of error, tls_set_dh_from_file() logs a warning and /* ignores the request. @@ -74,6 +83,8 @@ /* Utility library. */ #include <msg.h> +#include <mymalloc.h> +#include <stringops.h> /* * Global library @@ -85,6 +96,9 @@ #define TLS_INTERNAL #include <tls.h> #include <openssl/dh.h> +#ifndef OPENSSL_NO_ECDH +#include <openssl/ec.h> +#endif /* Application-specific. */ @@ -230,22 +244,104 @@ DH *tls_tmp_dh_cb(SSL *unused_ssl, int export, int keylength) return (dh_tmp); } -int tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade) +void tls_auto_eecdh_curves(SSL_CTX *ctx, const char *configured) { -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL && !defined(OPENSSL_NO_ECDH) - int nid; - EC_KEY *ecdh; - const char *curve; - int g; +#ifndef OPENSSL_NO_ECDH + SSL_CTX *tmpctx; + int *nids; + int space = 5; + int n = 0; + int unknown = 0; + char *save; + char *curves; + char *curve; + + if ((tmpctx = SSL_CTX_new(TLS_method())) == 0) { + msg_warn("cannot allocate temp SSL_CTX, using default ECDHE curves"); + tls_print_errors(); + return; + } + nids = mymalloc(space * sizeof(int)); + curves = save = mystrdup(configured); +#define RETURN do { \ + myfree(save); \ + myfree(nids); \ + SSL_CTX_free(tmpctx); \ + return; \ + } while (0) + + while ((curve = mystrtok(&curves, CHARS_COMMA_SP)) != 0) { + int nid = EC_curve_nist2nid(curve); + + if (nid == NID_undef) + nid = OBJ_sn2nid(curve); + if (nid == NID_undef) + nid = OBJ_ln2nid(curve); + if (nid == NID_undef) { + msg_warn("ignoring unknown ECDHE curve \"%s\"", + curve); + continue; + } + + /* + * Validate the NID by trying it as the sole EC curve for a + * throw-away SSL context. Silently skip unsupported code points. + * This way, we can list X25519 and X448 as soon as the nids are + * assigned, and before the supporting code is implemented. They'll + * be silently skipped when not yet supported. + */ + if (SSL_CTX_set1_curves(tmpctx, &nid, 1) <= 0) { + ++unknown; + continue; + } + if (++n > space) { + space *= 2; + nids = myrealloc(nids, space * sizeof(int)); + } + nids[n - 1] = nid; + } + + if (n == 0) { + if (unknown > 0) + msg_warn("none of the configured ECDHE curves are supported"); + RETURN; + } + if (SSL_CTX_set1_curves(ctx, nids, n) <= 0) { + msg_warn("failed to configure ECDHE curves"); + tls_print_errors(); + RETURN; + } + + /* + * This is a NOP in OpenSSL 1.1.0 and later, where curves are always + * auto-negotiated. + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000UL + if (SSL_CTX_set_ecdh_auto(ctx, 1) <= 0) { + msg_warn("failed to enable automatic ECDHE curve selection"); + tls_print_errors(); + RETURN; + } +#endif + RETURN; +#endif +} #define TLS_EECDH_INVALID 0 #define TLS_EECDH_NONE 1 #define TLS_EECDH_STRONG 2 #define TLS_EECDH_ULTRA 3 +#define TLS_EECDH_AUTO 4 + +void tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade) +{ +#ifndef OPENSSL_NO_ECDH + int g; static NAME_CODE eecdh_table[] = { "none", TLS_EECDH_NONE, "strong", TLS_EECDH_STRONG, "ultra", TLS_EECDH_ULTRA, + "auto", TLS_EECDH_AUTO, 0, TLS_EECDH_INVALID, }; @@ -254,41 +350,27 @@ int tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade) msg_panic("Invalid eecdh grade code: %d", g); case TLS_EECDH_INVALID: msg_warn("Invalid TLS eecdh grade \"%s\": EECDH disabled", grade); - return (0); - case TLS_EECDH_NONE: - return (1); + return; case TLS_EECDH_STRONG: - curve = var_tls_eecdh_strong; - break; + tls_auto_eecdh_curves(server_ctx, var_tls_eecdh_strong); + return; case TLS_EECDH_ULTRA: - curve = var_tls_eecdh_ultra; - break; - } - - /* - * Elliptic-Curve Diffie-Hellman parameters are either "named curves" - * from RFC 4492 section 5.1.1, or explicitly described curves over - * binary fields. OpenSSL only supports the "named curves", which provide - * maximum interoperability. The recommended curve for 128-bit - * work-factor key exchange is "prime256v1" a.k.a. "secp256r1" from - * Section 2.7 of http://www.secg.org/download/aid-386/sec2_final.pdf - */ + tls_auto_eecdh_curves(server_ctx, var_tls_eecdh_ultra); + return; + case TLS_EECDH_NONE: - if ((nid = OBJ_sn2nid(curve)) == NID_undef) { - msg_warn("unknown curve \"%s\": disabling EECDH support", curve); - return (0); - } - ERR_clear_error(); - if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0 - || SSL_CTX_set_tmp_ecdh(server_ctx, ecdh) == 0) { - EC_KEY_free(ecdh); /* OK if NULL */ - msg_warn("unable to use curve \"%s\": disabling EECDH support", curve); - tls_print_errors(); - return (0); + /* + * Pretend "none" is "auto", the former is no longer supported or + * wise + */ + msg_warn("The \"none\" eecdh grade is no longer supported, " + "using \"auto\" instead"); + case TLS_EECDH_AUTO: + tls_auto_eecdh_curves(server_ctx, var_tls_eecdh_auto); + return; } - EC_KEY_free(ecdh); #endif - return (1); + return; } #ifdef TEST diff --git a/external/ibm-public/postfix/dist/src/tls/tls_mgr.c b/external/ibm-public/postfix/dist/src/tls/tls_mgr.c index ea63ad9c38a..4340f944e56 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_mgr.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_mgr.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_mgr.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_mgr.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -443,7 +443,7 @@ int main(int unused_ac, char **av) status = tls_mgr_lookup(argv->argv[1], argv->argv[2], buf); vstream_printf("status=%d session=%.*s\n", - status, LEN(buf), STR(buf)); + status, (int) LEN(buf), STR(buf)); vstring_free(buf); } else if (COMMAND(argv, "update", 4)) { status = tls_mgr_update(argv->argv[1], argv->argv[2], diff --git a/external/ibm-public/postfix/dist/src/tls/tls_misc.c b/external/ibm-public/postfix/dist/src/tls/tls_misc.c index bf05e89874b..4405d981fc4 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_misc.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_misc.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_misc.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -6,6 +6,28 @@ /* SUMMARY /* miscellaneous TLS support routines /* SYNOPSIS +/* .SH Public functions +/* .nf +/* .na +/* #include <tls.h> +/* +/* void tls_log_summary(role, usage, TLScontext) +/* TLS_ROLE role; +/* TLS_USAGE usage; +/* TLS_SESS_STATE *TLScontext; +/* +/* const char *tls_compile_version(void) +/* +/* const char *tls_run_version(void) +/* +/* const char **tls_pkey_algorithms(void) +/* +/* void tls_pre_jail_init(TLS_ROLE) +/* TLS_ROLE role; +/* +/* .SH Internal functions +/* .nf +/* .na /* #define TLS_INTERNAL /* #include <tls.h> /* @@ -14,19 +36,20 @@ /* char *var_tls_low_clist; /* char *var_tls_export_clist; /* char *var_tls_null_clist; +/* char *var_tls_eecdh_auto; /* char *var_tls_eecdh_strong; /* char *var_tls_eecdh_ultra; -/* char *var_tls_dane_agility; /* char *var_tls_dane_digests; /* int var_tls_daemon_rand_bytes; /* bool var_tls_append_def_CA; -/* bool var_tls_dane_taa_dgst; /* bool var_tls_preempt_clist; /* bool var_tls_bc_pkey_fprint; /* bool var_tls_multi_wildcard; /* char *var_tls_mgr_service; /* char *var_tls_tkt_cipher; /* char *var_openssl_path; +/* char *var_tls_server_sni_maps; +/* bool var_tls_fast_shutdown; /* /* TLS_APPL_STATE *tls_alloc_app_context(ssl_ctx, log_mask) /* SSL_CTX *ssl_ctx; @@ -57,12 +80,14 @@ /* const char *str_tls_cipher_grade(grade) /* int grade; /* -/* const char *tls_set_ciphers(app_ctx, context, grade, exclusions) -/* TLS_APPL_STATE *app_ctx; -/* const char *context; +/* const char *tls_set_ciphers(TLScontext, grade, exclusions) +/* TLS_SESS_STATE *TLScontext; /* int grade; /* const char *exclusions; /* +/* void tls_get_signature_params(TLScontext) +/* TLS_SESS_STATE *TLScontext; +/* /* void tls_print_errors() /* /* void tls_info_callback(ssl, where, ret) @@ -88,15 +113,24 @@ /* /* int tls_validate_digest(dgst) /* const char *dgst; +/* DESCRIPTION +/* This module implements public and internal routines that +/* support the TLS client and server. /* -/* const char *tls_compile_version(void) +/* tls_log_summary() logs a summary of a completed TLS connection. +/* The "role" argument must be TLS_ROLE_CLIENT for outgoing client +/* connections, or TLS_ROLE_SERVER for incoming server connections, +/* and the "usage" must be TLS_USAGE_NEW or TLS_USAGE_USED. /* -/* const char *tls_run_version(void) +/* tls_compile_version() returns a text string description of +/* the compile-time TLS library. /* -/* const char **tls_pkey_algorithms(void) -/* DESCRIPTION -/* This module implements routines that support the TLS client -/* and server internals. +/* tls_run_version() is just tls_compile_version() but with the runtime +/* version instead of the compile-time version. +/* +/* tls_pkey_algorithms() returns a pointer to null-terminated +/* array of string constants with the names of the supported +/* public-key algorithms. /* /* tls_alloc_app_context() creates an application context that /* holds the SSL context for the application and related cached state. @@ -121,6 +155,10 @@ /* tls_param_init() loads main.cf parameters used internally in /* TLS library. Any errors are fatal. /* +/* tls_pre_jail_init() opens any tables that need to be opened before +/* entering a chroot jail. The "role" parameter must be TLS_ROLE_CLIENT +/* for clients and TLS_ROLE_SERVER for servers. Any errors are fatal. +/* /* tls_protocol_mask() returns a bitmask of excluded protocols, given /* a list (plist) of protocols to include or (preceded by a '!') exclude. /* If "plist" contains invalid protocol names, TLS_PROTOCOL_INVALID is @@ -136,13 +174,17 @@ /* When the input specifies an undefined grade, str_tls_cipher_grade() /* logs no warning, returns a null pointer. /* -/* tls_set_ciphers() generates a cipher list from the specified -/* grade, minus any ciphers specified via a list of exclusions. -/* The cipherlist is applied to the supplied SSL context if it -/* is different from the most recently applied value. The return -/* value is the cipherlist used and is overwritten upon each call. -/* When the input is invalid, tls_set_ciphers() logs a warning with -/* the specified context, and returns a null pointer result. +/* tls_set_ciphers() applies the requested cipher grade and exclusions +/* to the provided TLS session context, returning the resulting cipher +/* list string. The return value is the cipherlist used and is +/* overwritten upon each call. When the input is invalid, +/* tls_set_ciphers() logs a warning, and returns a null result. +/* +/* tls_get_signature_params() updates the "TLScontext" with handshake +/* signature parameters pertaining to TLS 1.3, where the ciphersuite +/* no longer describes the asymmetric algorithms employed in the +/* handshake, which are negotiated separately. This function +/* has no effect for TLS 1.2 and earlier. /* /* tls_print_errors() queries the OpenSSL error stack, /* logs the error messages, and clears the error stack. @@ -164,16 +206,6 @@ /* /* tls_validate_digest() returns non-zero if the named digest /* is usable and zero otherwise. -/* -/* tls_compile_version() returns a text string description of -/* the compile-time TLS library. -/* -/* tls_run_version() is just tls_compile_version() but with the runtime -/* version instead of the compile-time version. -/* -/* tls_pkey_algorithms() returns a pointer to null-terminated -/* array of string constants with the names of the supported -/* public-key algorithms. /* LICENSE /* .ad /* .fi @@ -221,12 +253,15 @@ #include <argv.h> #include <name_mask.h> #include <name_code.h> +#include <dict.h> +#include <valid_hostname.h> /* * Global library. */ #include <mail_params.h> #include <mail_conf.h> +#include <maps.h> /* * TLS library. @@ -245,19 +280,22 @@ char *var_tls_low_clist; char *var_tls_export_clist; char *var_tls_null_clist; int var_tls_daemon_rand_bytes; +char *var_tls_eecdh_auto; char *var_tls_eecdh_strong; char *var_tls_eecdh_ultra; -char *var_tls_dane_agility; char *var_tls_dane_digests; bool var_tls_append_def_CA; char *var_tls_bug_tweaks; char *var_tls_ssl_options; bool var_tls_bc_pkey_fprint; -bool var_tls_dane_taa_dgst; bool var_tls_multi_wildcard; char *var_tls_mgr_service; char *var_tls_tkt_cipher; char *var_openssl_path; +char *var_tls_server_sni_maps; +bool var_tls_fast_shutdown; + +static MAPS *tls_server_sni_maps; #ifdef VAR_TLS_PREEMPT_CLIST bool var_tls_preempt_clist; @@ -279,7 +317,7 @@ static const NAME_CODE protocol_table[] = { SSL_TXT_TLSV1, TLS_PROTOCOL_TLSv1, SSL_TXT_TLSV1_1, TLS_PROTOCOL_TLSv1_1, SSL_TXT_TLSV1_2, TLS_PROTOCOL_TLSv1_2, - SSL_TXT_TLSV1_3, TLS_PROTOCOL_TLSv1_3, + TLS_PROTOCOL_TXT_TLSV1_3, TLS_PROTOCOL_TLSv1_3, 0, TLS_PROTOCOL_INVALID, }; @@ -355,6 +393,29 @@ static const LONG_NAME_MASK ssl_bug_tweaks[] = { #define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0 #endif NAMEBUG(CRYPTOPRO_TLSEXT_BUG), + +#ifndef SSL_OP_TLSEXT_PADDING +#define SSL_OP_TLSEXT_PADDING 0 +#endif + NAMEBUG(TLSEXT_PADDING), + +#if 0 + + /* + * XXX: New with OpenSSL 1.1.1, this is turned on implicitly in + * SSL_CTX_new() and is not included in SSL_OP_ALL. Allowing users to + * disable this would thus be a code change that would require clearing + * bug work-around bits in SSL_CTX, after setting SSL_OP_ALL. Since this + * is presumably required for TLS 1.3 on today's Internet, the code + * change will be done separately later. For now this implicit bug + * work-around cannot be disabled via supported Postfix mechanisms. + */ +#ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT +#define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0 +#endif + NAMEBUG(ENABLE_MIDDLEBOX_COMPAT), +#endif + 0, 0, }; @@ -380,10 +441,43 @@ static const LONG_NAME_MASK ssl_op_tweaks[] = { #define SSL_OP_NO_COMPRESSION 0 #endif NAME_SSL_OP(NO_COMPRESSION), + +#ifndef SSL_OP_NO_RENEGOTIATION +#define SSL_OP_NO_RENEGOTIATION 0 +#endif + NAME_SSL_OP(NO_RENEGOTIATION), + +#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0 +#endif + NAME_SSL_OP(NO_SESSION_RESUMPTION_ON_RENEGOTIATION), + +#ifndef SSL_OP_PRIORITIZE_CHACHA +#define SSL_OP_PRIORITIZE_CHACHA 0 +#endif + NAME_SSL_OP(PRIORITIZE_CHACHA), + +#ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT +#define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0 +#endif + NAME_SSL_OP(ENABLE_MIDDLEBOX_COMPAT), + 0, 0, }; /* + * Once these have been a NOOP long enough, they might some day be removed + * from OpenSSL. The defines below will avoid bitrot issues if/when that + * happens. + */ +#ifndef SSL_OP_SINGLE_DH_USE +#define SSL_OP_SINGLE_DH_USE 0 +#endif +#ifndef SSL_OP_SINGLE_ECDH_USE +#define SSL_OP_SINGLE_ECDH_USE 0 +#endif + + /* * Ciphersuite name <=> code conversion. */ const NAME_CODE tls_cipher_grade_table[] = { @@ -444,22 +538,6 @@ typedef struct { int status; } TLS_VINFO; - /* - * OpenSSL adopted the cipher selection patch, so we don't expect any more - * broken ciphers other than AES and CAMELLIA. - */ -typedef struct { - const char *ssl_name; - const int alg_bits; - const char *evp_name; -} cipher_probe_t; - -static const cipher_probe_t cipher_probes[] = { - "AES", 256, "AES-256-CBC", - "CAMELLIA", 256, "CAMELLIA-256-CBC", - 0, 0, 0, -}; - /* tls_log_mask - Convert user TLS loglevel to internal log feature mask */ int tls_log_mask(const char *log_param, const char *log_level) @@ -478,113 +556,6 @@ void tls_update_app_logmask(TLS_APPL_STATE *app_ctx, int log_mask) app_ctx->log_mask = log_mask; } -/* tls_exclude_missing - Append exclusions for missing ciphers */ - -static const char *tls_exclude_missing(SSL_CTX *ctx, VSTRING *buf) -{ - const char *myname = "tls_exclude_missing"; - static ARGV *exclude; /* Cached */ - SSL *s = 0; - ssl_cipher_stack_t *ciphers; - const SSL_CIPHER *c; - const cipher_probe_t *probe; - int alg_bits; - int num; - int i; - - /* - * Process a list of probes which specify: - * - * An SSL cipher-suite name for a family of ciphers that use the same - * symmetric algorithm at two or more key sizes, typically 128/256 bits. - * - * The key size (typically 256) that OpenSSL fails to check, and assumes - * available when another key size (typically 128) is usable. - * - * The OpenSSL name of the symmetric algorithm associated with the SSL - * cipher-suite. Typically, this is MUMBLE-256-CBC, where "MUMBLE" is the - * name of the SSL cipher-suite that use the MUMBLE symmetric algorithm. - * On systems that support the required encryption algorithm, the name is - * listed in the output of "openssl list-cipher-algorithms". - * - * When an encryption algorithm is not available at the given key size but - * the corresponding OpenSSL cipher-suite contains ciphers that have have - * this key size, the problem ciphers are explicitly disabled in Postfix. - * The list is cached in the static "exclude" array. - */ - if (exclude == 0) { - exclude = argv_alloc(1); - - /* - * Iterate over the probe list - */ - for (probe = cipher_probes; probe->ssl_name; ++probe) { - /* No exclusions if evp_name is a valid algorithm */ - if (EVP_get_cipherbyname(probe->evp_name)) - continue; - - /* - * Sadly there is no SSL_CTX_get_ciphers() interface, so we are - * forced to allocate and free an SSL object. Fatal error if we - * can't allocate the SSL object. - */ - ERR_clear_error(); - if (s == 0 && (s = SSL_new(ctx)) == 0) { - tls_print_errors(); - msg_fatal("%s: error allocating SSL object", myname); - } - - /* - * Cipher is not supported by libcrypto, nothing to do if also - * not supported by libssl. Flush the OpenSSL error stack. - * - * XXX: There may be additional places in pre-existing code where - * SSL errors are generated and ignored, that require a similar - * "flush". Better yet, is to always flush before calls that run - * tls_print_errors() on failure. - * - * Contrary to documentation, on SunOS 5.10 SSL_set_cipher_list() - * returns success with no ciphers selected, when this happens - * SSL_get_ciphers() produces a stack with 0 elements! - */ - if (SSL_set_cipher_list(s, probe->ssl_name) == 0 - || (ciphers = SSL_get_ciphers(s)) == 0 - || (num = sk_SSL_CIPHER_num(ciphers)) == 0) { - ERR_clear_error(); /* flush any generated errors */ - continue; - } - for (i = 0; i < num; ++i) { - c = sk_SSL_CIPHER_value(ciphers, i); - (void) SSL_CIPHER_get_bits(c, &alg_bits); - if (alg_bits == probe->alg_bits) - argv_add(exclude, SSL_CIPHER_get_name(c), ARGV_END); - } - } - if (s != 0) - SSL_free(s); - } - for (i = 0; i < exclude->argc; ++i) - vstring_sprintf_append(buf, ":!%s", exclude->argv[i]); - return (vstring_str(buf)); -} - -/* tls_apply_cipher_list - update SSL_CTX cipher list */ - -static const char *tls_apply_cipher_list(TLS_APPL_STATE *app_ctx, - const char *context, VSTRING *spec) -{ - const char *new = tls_exclude_missing(app_ctx->ssl_ctx, spec); - - ERR_clear_error(); - if (SSL_CTX_set_cipher_list(app_ctx->ssl_ctx, new) == 0) { - tls_print_errors(); - vstring_sprintf(app_ctx->why, "invalid %s cipher list: \"%s\"", - context, new); - return (0); - } - return (new); -} - /* tls_protocol_mask - Bitmask of protocols to exclude */ int tls_protocol_mask(const char *plist) @@ -628,33 +599,38 @@ int tls_protocol_mask(const char *plist) void tls_param_init(void) { + /* If this changes, update TLS_CLIENT_PARAMS in tls_proxy.h. */ static const CONFIG_STR_TABLE str_table[] = { VAR_TLS_HIGH_CLIST, DEF_TLS_HIGH_CLIST, &var_tls_high_clist, 1, 0, VAR_TLS_MEDIUM_CLIST, DEF_TLS_MEDIUM_CLIST, &var_tls_medium_clist, 1, 0, VAR_TLS_LOW_CLIST, DEF_TLS_LOW_CLIST, &var_tls_low_clist, 1, 0, VAR_TLS_EXPORT_CLIST, DEF_TLS_EXPORT_CLIST, &var_tls_export_clist, 1, 0, VAR_TLS_NULL_CLIST, DEF_TLS_NULL_CLIST, &var_tls_null_clist, 1, 0, + VAR_TLS_EECDH_AUTO, DEF_TLS_EECDH_AUTO, &var_tls_eecdh_auto, 1, 0, VAR_TLS_EECDH_STRONG, DEF_TLS_EECDH_STRONG, &var_tls_eecdh_strong, 1, 0, VAR_TLS_EECDH_ULTRA, DEF_TLS_EECDH_ULTRA, &var_tls_eecdh_ultra, 1, 0, VAR_TLS_BUG_TWEAKS, DEF_TLS_BUG_TWEAKS, &var_tls_bug_tweaks, 0, 0, VAR_TLS_SSL_OPTIONS, DEF_TLS_SSL_OPTIONS, &var_tls_ssl_options, 0, 0, - VAR_TLS_DANE_AGILITY, DEF_TLS_DANE_AGILITY, &var_tls_dane_agility, 1, 0, VAR_TLS_DANE_DIGESTS, DEF_TLS_DANE_DIGESTS, &var_tls_dane_digests, 1, 0, VAR_TLS_MGR_SERVICE, DEF_TLS_MGR_SERVICE, &var_tls_mgr_service, 1, 0, VAR_TLS_TKT_CIPHER, DEF_TLS_TKT_CIPHER, &var_tls_tkt_cipher, 0, 0, VAR_OPENSSL_PATH, DEF_OPENSSL_PATH, &var_openssl_path, 1, 0, 0, }; + + /* If this changes, update TLS_CLIENT_PARAMS in tls_proxy.h. */ static const CONFIG_INT_TABLE int_table[] = { VAR_TLS_DAEMON_RAND_BYTES, DEF_TLS_DAEMON_RAND_BYTES, &var_tls_daemon_rand_bytes, 1, 0, 0, }; + + /* If this changes, update TLS_CLIENT_PARAMS in tls_proxy.h. */ static const CONFIG_BOOL_TABLE bool_table[] = { VAR_TLS_APPEND_DEF_CA, DEF_TLS_APPEND_DEF_CA, &var_tls_append_def_CA, VAR_TLS_BC_PKEY_FPRINT, DEF_TLS_BC_PKEY_FPRINT, &var_tls_bc_pkey_fprint, - VAR_TLS_DANE_TAA_DGST, DEF_TLS_DANE_TAA_DGST, &var_tls_dane_taa_dgst, VAR_TLS_PREEMPT_CLIST, DEF_TLS_PREEMPT_CLIST, &var_tls_preempt_clist, VAR_TLS_MULTI_WILDCARD, DEF_TLS_MULTI_WILDCARD, &var_tls_multi_wildcard, + VAR_TLS_FAST_SHUTDOWN, DEF_TLS_FAST_SHUTDOWN, &var_tls_fast_shutdown, 0, }; static int init_done; @@ -668,47 +644,105 @@ void tls_param_init(void) get_mail_conf_bool_table(bool_table); } +/* tls_pre_jail_init - Load TLS related pre-jail tables */ + +void tls_pre_jail_init(TLS_ROLE role) +{ + static const CONFIG_STR_TABLE str_table[] = { + VAR_TLS_SERVER_SNI_MAPS, DEF_TLS_SERVER_SNI_MAPS, &var_tls_server_sni_maps, 0, 0, + 0, + }; + int flags; + + tls_param_init(); + + /* Nothing for clients at this time */ + if (role != TLS_ROLE_SERVER) + return; + + get_mail_conf_str_table(str_table); + if (*var_tls_server_sni_maps == 0) + return; + + flags = DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX | DICT_FLAG_SRC_RHS_IS_FILE; + tls_server_sni_maps = + maps_create(VAR_TLS_SERVER_SNI_MAPS, var_tls_server_sni_maps, flags); +} + +/* server_sni_callback - process client's SNI extension */ + +static int server_sni_callback(SSL *ssl, int *alert, void *arg) +{ + SSL_CTX *sni_ctx = (SSL_CTX *) arg; + TLS_SESS_STATE *TLScontext = SSL_get_ex_data(ssl, TLScontext_index); + const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + const char *cp = sni; + const char *pem; + + /* SNI is silently ignored when we don't care or is NULL or empty */ + if (!sni_ctx || !tls_server_sni_maps || !sni || !*sni) + return SSL_TLSEXT_ERR_NOACK; + + if (!valid_hostname(sni, DONT_GRIPE)) { + msg_warn("TLS SNI from %s is invalid: %s", + TLScontext->namaddr, sni); + return SSL_TLSEXT_ERR_NOACK; + } + do { + /* Don't silently skip maps opened with the wrong flags. */ + pem = maps_file_find(tls_server_sni_maps, cp, 0); + } while (!pem + && !tls_server_sni_maps->error + && (cp = strchr(cp + 1, '.')) != 0); + + if (!pem) { + if (tls_server_sni_maps->error) { + msg_warn("%s: %s map lookup problem", + tls_server_sni_maps->title, sni); + *alert = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + msg_info("TLS SNI %s from %s not matched, using default chain", + sni, TLScontext->namaddr); + + /* + * XXX: We could lie and pretend to accept the name, but since we've + * previously not implemented the callback (with OpenSSL then + * declining the extension), and nothing bad happened, declining it + * explicitly should be safe. + */ + return SSL_TLSEXT_ERR_NOACK; + } + SSL_set_SSL_CTX(ssl, sni_ctx); + if (tls_load_pem_chain(ssl, pem, sni) != 0) { + /* errors already logged */ + *alert = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + TLScontext->peer_sni = mystrdup(sni); + return SSL_TLSEXT_ERR_OK; +} + /* tls_set_ciphers - Set SSL context cipher list */ -const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context, - const char *grade, const char *exclusions) +const char *tls_set_ciphers(TLS_SESS_STATE *TLScontext, const char *grade, + const char *exclusions) { const char *myname = "tls_set_ciphers"; static VSTRING *buf; - int new_grade; char *save; char *cp; char *tok; - const char *new_list; - new_grade = tls_cipher_grade(grade); - if (new_grade == TLS_CIPHER_NONE) { - vstring_sprintf(app_ctx->why, "invalid %s cipher grade: \"%s\"", - context, grade); - return (0); - } if (buf == 0) buf = vstring_alloc(10); VSTRING_RESET(buf); - /* - * Given cached state and identical input, we return the same result. - */ - if (app_ctx->cipher_list) { - if (new_grade == app_ctx->cipher_grade - && strcmp(app_ctx->cipher_exclusions, exclusions) == 0) - return (app_ctx->cipher_list); - - /* Change required, flush cached state */ - app_ctx->cipher_grade = TLS_CIPHER_NONE; - - myfree(app_ctx->cipher_exclusions); - app_ctx->cipher_exclusions = 0; - - myfree(app_ctx->cipher_list); - app_ctx->cipher_list = 0; - } - switch (new_grade) { + switch (tls_cipher_grade(grade)) { + case TLS_CIPHER_NONE: + msg_warn("%s: invalid cipher grade: \"%s\"", + TLScontext->namaddr, grade); + return (0); case TLS_CIPHER_HIGH: vstring_strcpy(buf, var_tls_high_clist); break; @@ -725,11 +759,8 @@ const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context, vstring_strcpy(buf, var_tls_null_clist); break; default: - - /* - * The caller MUST provide a valid cipher grade - */ - msg_panic("invalid %s cipher grade: %d", context, new_grade); + /* Internal error, valid grade, but missing case label. */ + msg_panic("%s: unexpected cipher grade: %s", myname, grade); } /* @@ -750,28 +781,253 @@ const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context, * Can't exclude ciphers that start with modifiers. */ if (strchr("!+-@", *tok)) { - vstring_sprintf(app_ctx->why, - "invalid unary '!+-@' in %s cipher " - "exclusion: \"%s\"", context, tok); + msg_warn("%s: invalid unary '!+-@' in cipher exclusion: %s", + TLScontext->namaddr, tok); return (0); } vstring_sprintf_append(buf, ":!%s", tok); } myfree(save); } - if ((new_list = tls_apply_cipher_list(app_ctx, context, buf)) == 0) + ERR_clear_error(); + if (SSL_set_cipher_list(TLScontext->con, vstring_str(buf)) == 0) { + msg_warn("%s: error setting cipher grade: \"%s\"", + TLScontext->namaddr, grade); + tls_print_errors(); return (0); + } + return (vstring_str(buf)); +} + +/* tls_get_signature_params - TLS 1.3 signature details */ + +void tls_get_signature_params(TLS_SESS_STATE *TLScontext) +{ +#if OPENSSL_VERSION_NUMBER >= 0x1010100fUL && defined(TLS1_3_VERSION) + const char *kex_name = 0; + const char *kex_curve = 0; + const char *locl_sig_name = 0; + const char *locl_sig_curve = 0; + const char *locl_sig_dgst = 0; + const char *peer_sig_name = 0; + const char *peer_sig_curve = 0; + const char *peer_sig_dgst = 0; + int nid; + SSL *ssl = TLScontext->con; + int srvr = SSL_is_server(ssl); + X509 *cert; + EVP_PKEY *pkey = 0; + +#ifndef OPENSSL_NO_EC + EC_KEY *eckey; + +#endif - /* Cache new state */ - app_ctx->cipher_grade = new_grade; - app_ctx->cipher_exclusions = mystrdup(exclusions); +#define SIG_PROP(c, s, p) (*((s) ? &c->srvr_sig_##p : &c->clnt_sig_##p)) - return (app_ctx->cipher_list = mystrdup(new_list)); + if (SSL_version(ssl) < TLS1_3_VERSION) + return; + + if (tls_get_peer_dh_pubkey(ssl, &pkey)) { + switch (nid = EVP_PKEY_id(pkey)) { + default: + kex_name = OBJ_nid2sn(EVP_PKEY_type(nid)); + break; + + case EVP_PKEY_DH: + kex_name = "DHE"; + TLScontext->kex_bits = EVP_PKEY_bits(pkey); + break; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + kex_name = "ECDHE"; + eckey = EVP_PKEY_get0_EC_KEY(pkey); + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + kex_curve = EC_curve_nid2nist(nid); + if (!kex_curve) + kex_curve = OBJ_nid2sn(nid); + break; +#endif + } + EVP_PKEY_free(pkey); + } + + /* + * On the client end, the certificate may be preset, 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)) + cert = SSL_get_certificate(ssl); + else + cert = 0; + + /* Signature algorithms for the local end of the connection */ + if (cert) { + pkey = X509_get0_pubkey(cert); + + /* + * Override the built-in name for the "ECDSA" algorithms OID, with + * the more familiar name. For "RSA" keys report "RSA-PSS", which + * must be used with TLS 1.3. + */ + if ((nid = EVP_PKEY_type(EVP_PKEY_id(pkey))) != NID_undef) { + switch (nid) { + default: + locl_sig_name = OBJ_nid2sn(nid); + break; + + case EVP_PKEY_RSA: + /* For RSA, TLS 1.3 mandates PSS signatures */ + locl_sig_name = "RSA-PSS"; + SIG_PROP(TLScontext, srvr, bits) = EVP_PKEY_bits(pkey); + break; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + locl_sig_name = "ECDSA"; + eckey = EVP_PKEY_get0_EC_KEY(pkey); + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + locl_sig_curve = EC_curve_nid2nist(nid); + if (!locl_sig_curve) + locl_sig_curve = OBJ_nid2sn(nid); + break; +#endif + } + } + + /* + * With Ed25519 and Ed448 there is no pre-signature digest, but the + * accessor does not fail, rather we get NID_undef. + */ + 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 ((cert = SSL_get_peer_certificate(ssl)) != 0) { + pkey = X509_get0_pubkey(cert); + + /* + * Override the built-in name for the "ECDSA" algorithms OID, with + * the more familiar name. For "RSA" keys report "RSA-PSS", which + * must be used with TLS 1.3. + */ + if ((nid = EVP_PKEY_type(EVP_PKEY_id(pkey))) != NID_undef) { + switch (nid) { + default: + peer_sig_name = OBJ_nid2sn(nid); + break; + + case EVP_PKEY_RSA: + /* For RSA, TLS 1.3 mandates PSS signatures */ + peer_sig_name = "RSA-PSS"; + SIG_PROP(TLScontext, !srvr, bits) = EVP_PKEY_bits(pkey); + break; + +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + peer_sig_name = "ECDSA"; + eckey = EVP_PKEY_get0_EC_KEY(pkey); + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + peer_sig_curve = EC_curve_nid2nist(nid); + if (!peer_sig_curve) + peer_sig_curve = OBJ_nid2sn(nid); + break; +#endif + } + } + + /* + * With Ed25519 and Ed448 there is no pre-signature digest, but the + * accessor does not fail, rather we get NID_undef. + */ + if (SSL_get_peer_signature_nid(ssl, &nid) && nid != NID_undef) + peer_sig_dgst = OBJ_nid2sn(nid); + } + if (kex_name) { + TLScontext->kex_name = mystrdup(kex_name); + if (kex_curve) + TLScontext->kex_curve = mystrdup(kex_curve); + } + if (locl_sig_name) { + SIG_PROP(TLScontext, srvr, name) = mystrdup(locl_sig_name); + if (locl_sig_curve) + SIG_PROP(TLScontext, srvr, curve) = mystrdup(locl_sig_curve); + if (locl_sig_dgst) + SIG_PROP(TLScontext, srvr, dgst) = mystrdup(locl_sig_dgst); + } + if (peer_sig_name) { + SIG_PROP(TLScontext, !srvr, name) = mystrdup(peer_sig_name); + if (peer_sig_curve) + SIG_PROP(TLScontext, !srvr, curve) = mystrdup(peer_sig_curve); + if (peer_sig_dgst) + SIG_PROP(TLScontext, !srvr, dgst) = mystrdup(peer_sig_dgst); + } +#endif /* OPENSSL_VERSION_NUMBER ... */ +} + +/* tls_log_summary - TLS loglevel 1 one-liner, embellished with TLS 1.3 details */ + +void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx) +{ + VSTRING *msg = vstring_alloc(100); + const char *direction = (role == TLS_ROLE_CLIENT) ? "to" : "from"; + const char *sni = (role == TLS_ROLE_CLIENT) ? 0 : ctx->peer_sni; + + /* + * When SNI was sent and accepted, the server-side log message now + * includes a "to <sni-name>" detail after the "from <namaddr>" detail + * identifying the remote client. We don't presently log (purportedly) + * accepted SNI on the client side. + */ + 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_CERT_IS_SECURED(ctx) ? "Verified" : + TLS_CERT_IS_TRUSTED(ctx) ? "Trusted" : "Untrusted", + usage == TLS_USAGE_NEW ? "established" : "reused", + direction, ctx->namaddr, sni ? " to " : "", sni ? sni : "", + ctx->protocol, ctx->cipher_name, ctx->cipher_usebits, + ctx->cipher_algbits); + + if (ctx->kex_name && *ctx->kex_name) { + vstring_sprintf_append(msg, " key-exchange %s", ctx->kex_name); + if (ctx->kex_curve && *ctx->kex_curve) + vstring_sprintf_append(msg, " (%s)", ctx->kex_curve); + else if (ctx->kex_bits > 0) + vstring_sprintf_append(msg, " (%d bits)", ctx->kex_bits); + } + if (ctx->srvr_sig_name && *ctx->srvr_sig_name) { + 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); + else if (ctx->srvr_sig_bits > 0) + vstring_sprintf_append(msg, " (%d bits)", ctx->srvr_sig_bits); + if (ctx->srvr_sig_dgst && *ctx->srvr_sig_dgst) + vstring_sprintf_append(msg, " server-digest %s", + ctx->srvr_sig_dgst); + } + if (ctx->clnt_sig_name && *ctx->clnt_sig_name) { + 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); + else if (ctx->clnt_sig_bits > 0) + vstring_sprintf_append(msg, " (%d bits)", ctx->clnt_sig_bits); + if (ctx->clnt_sig_dgst && *ctx->clnt_sig_dgst) + vstring_sprintf_append(msg, " client-digest %s", + ctx->clnt_sig_dgst); + } + msg_info("%s", vstring_str(msg)); + vstring_free(msg); } /* tls_alloc_app_context - allocate TLS application context */ -TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, int log_mask) +TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, SSL_CTX *sni_ctx, + int log_mask) { TLS_APPL_STATE *app_ctx; @@ -780,15 +1036,16 @@ TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, int log_mask) /* See portability note below with other memset() call. */ memset((void *) app_ctx, 0, sizeof(*app_ctx)); app_ctx->ssl_ctx = ssl_ctx; + app_ctx->sni_ctx = sni_ctx; app_ctx->log_mask = log_mask; /* See also: cache purging code in tls_set_ciphers(). */ - app_ctx->cipher_grade = TLS_CIPHER_NONE; - app_ctx->cipher_exclusions = 0; - app_ctx->cipher_list = 0; app_ctx->cache_type = 0; - app_ctx->why = vstring_alloc(1); + if (tls_server_sni_maps) { + SSL_CTX_set_tlsext_servername_callback(ssl_ctx, server_sni_callback); + SSL_CTX_set_tlsext_servername_arg(ssl_ctx, (void *) sni_ctx); + } return (app_ctx); } @@ -798,15 +1055,10 @@ void tls_free_app_context(TLS_APPL_STATE *app_ctx) { if (app_ctx->ssl_ctx) SSL_CTX_free(app_ctx->ssl_ctx); + if (app_ctx->sni_ctx) + SSL_CTX_free(app_ctx->sni_ctx); if (app_ctx->cache_type) myfree(app_ctx->cache_type); - /* See also: cache purging code in tls_set_ciphers(). */ - if (app_ctx->cipher_exclusions) - myfree(app_ctx->cipher_exclusions); - if (app_ctx->cipher_list) - myfree(app_ctx->cipher_list); - if (app_ctx->why) - vstring_free(app_ctx->why); myfree((void *) app_ctx); } @@ -832,10 +1084,19 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr) TLScontext->serverid = 0; TLScontext->peer_CN = 0; TLScontext->issuer_CN = 0; + TLScontext->peer_sni = 0; TLScontext->peer_cert_fprint = 0; TLScontext->peer_pkey_fprint = 0; TLScontext->protocol = 0; TLScontext->cipher_name = 0; + TLScontext->kex_name = 0; + TLScontext->kex_curve = 0; + TLScontext->clnt_sig_name = 0; + TLScontext->clnt_sig_curve = 0; + TLScontext->clnt_sig_dgst = 0; + TLScontext->srvr_sig_name = 0; + TLScontext->srvr_sig_curve = 0; + TLScontext->srvr_sig_dgst = 0; TLScontext->log_mask = log_mask; TLScontext->namaddr = lowercase(mystrdup(namaddr)); TLScontext->mdalg = 0; /* Alias for props->mdalg */ @@ -872,6 +1133,8 @@ void tls_free_context(TLS_SESS_STATE *TLScontext) myfree(TLScontext->peer_CN); if (TLScontext->issuer_CN) myfree(TLScontext->issuer_CN); + if (TLScontext->peer_sni) + myfree(TLScontext->peer_sni); if (TLScontext->peer_cert_fprint) myfree(TLScontext->peer_cert_fprint); if (TLScontext->peer_pkey_fprint) @@ -963,9 +1226,16 @@ void tls_check_version(void) tls_version_split(OPENSSL_VERSION_NUMBER, &hdr_info); tls_version_split(OpenSSL_version_num(), &lib_info); + /* + * Warn if run-time library is different from compile-time library, + * allowing later run-time "micro" versions starting with 1.1.0. + */ if (lib_info.major != hdr_info.major || lib_info.minor != hdr_info.minor - || lib_info.micro != hdr_info.micro) + || (lib_info.micro != hdr_info.micro + && (lib_info.micro < hdr_info.micro + || hdr_info.major == 0 + || (hdr_info.major == 1 && hdr_info.minor == 0)))) msg_warn("run-time library vs. compile-time header version mismatch: " "OpenSSL %d.%d.%d may not be compatible with OpenSSL %d.%d.%d", lib_info.major, lib_info.minor, lib_info.micro, @@ -997,7 +1267,7 @@ const char **tls_pkey_algorithms(void) #ifndef OPENSSL_NO_DSA "dsa", #endif -#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_ECDSA) +#ifndef OPENSSL_NO_ECDSA "ecdsa", #endif #ifndef OPENSSL_NO_RSA @@ -1015,25 +1285,6 @@ long tls_bug_bits(void) { long bits = SSL_OP_ALL; /* Work around all known bugs */ -#if OPENSSL_VERSION_NUMBER >= 0x00908000L && \ - OPENSSL_VERSION_NUMBER < 0x10000000L - long lib_version = OpenSSL_version_num(); - - /* - * In OpenSSL 0.9.8[ab], enabling zlib compression breaks the padding bug - * work-around, leading to false positives and failed connections. We may - * not interoperate with systems with the bug, but this is better than - * breaking on all 0.9.8[ab] systems that have zlib support enabled. - */ - if (lib_version >= 0x00908000L && lib_version <= 0x0090802fL) { - ssl_comp_stack_t *comp_methods = SSL_COMP_get_compression_methods(); - - comp_methods = SSL_COMP_get_compression_methods(); - if (comp_methods != 0 && sk_SSL_COMP_num(comp_methods) > 0) - bits &= ~SSL_OP_TLS_BLOCK_PADDING_BUG; - } -#endif - /* * Silently ignore any strings that don't appear in the tweaks table, or * hex bits that are not in SSL_OP_ALL. @@ -1061,6 +1312,14 @@ long tls_bug_bits(void) enable &= ~(SSL_OP_ALL | TLS_SSL_OP_MANAGED_BITS); bits |= enable; } + + /* + * We unconditionally avoid re-use of ephemeral keys, note that we set DH + * keys via a callback, so reuse was never possible, but the ECDH key is + * set statically, so that is potentially subject to reuse. Set both + * options just in case. + */ + bits |= SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE; return (bits); } diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy.h b/external/ibm-public/postfix/dist/src/tls/tls_proxy.h index 495360a9408..ff9d21c076c 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy.h +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy.h @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy.h,v 1.1.1.2 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _TLS_PROXY_H_INCLUDED_ #define _TLS_PROXY_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_misc.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_misc.c index 03ce33cdb68..54c75cc0114 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_misc.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_client_misc.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_client_misc.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_print.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_print.c index f747d84f8cb..f32644f6afe 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_print.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_print.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_client_print.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_client_print.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_scan.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_scan.c index 309124858c1..6e1f708787f 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_scan.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_client_scan.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_client_scan.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_client_scan.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_clnt.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_clnt.c index 4c9ca1fdc71..8184481da0c 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_clnt.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_clnt.c @@ -1,27 +1,41 @@ -/* $NetBSD: tls_proxy_clnt.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_proxy_clnt.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME /* tlsproxy_clnt 3 /* SUMMARY -/* postscreen TLS proxy support +/* tlsproxy(8) client support /* SYNOPSIS /* #include <tlsproxy_clnt.h> /* /* VSTREAM *tls_proxy_open(service, flags, peer_stream, peer_addr, -/* peer_port, timeout) +/* peer_port, handshake_timeout, session_timeout, +/* serverid, tls_params, init_props, start_props) /* const char *service; /* int flags; /* VSTREAM *peer_stream; /* const char *peer_addr; /* const char *peer_port; -/* int timeout; +/* int handshake_timeout; +/* int session_timeout; +/* const char *serverid; +/* void *tls_params; +/* void *init_props; +/* void *start_props; /* /* TLS_SESS_STATE *tls_proxy_context_receive(proxy_stream) /* VSTREAM *proxy_stream; -/* -/* void tls_proxy_context_free(tls_context) -/* TLS_SESS_STATE *tls_context; +/* AUXILIARY FUNCTIONS +/* VSTREAM *tls_proxy_legacy_open(service, flags, peer_stream, +/* peer_addr, peer_port, +/* timeout, serverid) +/* const char *service; +/* int flags; +/* VSTREAM *peer_stream; +/* const char *peer_addr; +/* const char *peer_port; +/* int timeout; +/* const char *serverid; /* DESCRIPTION /* tls_proxy_open() prepares for inserting the tlsproxy(8) /* daemon between the current process and a remote peer (the @@ -46,8 +60,8 @@ /* /* After this, the proxy_stream is ready for plain-text I/O. /* -/* tls_proxy_context_free() destroys a TLS context object that -/* was received with tls_proxy_context_receive(). +/* tls_proxy_legacy_open() is a backwards-compatibility feature +/* that provides a historical interface. /* /* Arguments: /* .IP service @@ -68,8 +82,20 @@ /* Printable IP address of the remote peer_stream endpoint. /* .IP peer_port /* Printable TCP port of the remote peer_stream endpoint. -/* .IP timeout -/* Time limit that the tlsproxy(8) daemon should use. +/* .IP handshake_timeout +/* Time limit that the tlsproxy(8) daemon should use during +/* the TLS handshake. +/* .IP session_timeout +/* Time limit that the tlsproxy(8) daemon should use after the +/* TLS handshake. +/* .IP serverid +/* Unique service identifier. +/* .IP tls_params +/* Pointer to TLS_CLIENT_PARAMS or TLS_SERVER_PARAMS. +/* .IP init_props +/* Pointer to TLS_CLIENT_INIT_PROPS or TLS_SERVER_INIT_PROPS. +/* .IP start_props +/* Pointer to TLS_CLIENT_START_PROPS or TLS_SERVER_START_PROPS. /* .IP proxy_stream /* Stream from tls_proxy_open(). /* .IP tls_context @@ -83,6 +109,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #ifdef USE_TLS @@ -121,8 +152,14 @@ VSTREAM *tls_proxy_open(const char *service, int flags, VSTREAM *peer_stream, const char *peer_addr, const char *peer_port, - int timeout) + int handshake_timeout, + int session_timeout, + const char *serverid, + void *tls_params, + void *init_props, + void *start_props) { + const char myname[] = "tls_proxy_open"; VSTREAM *tlsproxy_stream; int status; int fd; @@ -148,19 +185,45 @@ VSTREAM *tls_proxy_open(const char *service, int flags, } /* - * Initial handshake. Send the data attributes now, and send the client - * file descriptor in a later transaction. - * - * XXX The formatted endpoint should be a state member. Then, we can - * simplify all the format strings throughout the program. + * Initial handshake. Send common data attributes now, and send the + * remote peer file descriptor in a later transaction. */ tlsproxy_stream = vstream_fdopen(fd, O_RDWR); vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port); attr_print(tlsproxy_stream, ATTR_FLAG_NONE, - SEND_ATTR_STR(MAIL_ATTR_REMOTE_ENDPT, STR(remote_endpt)), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags), - SEND_ATTR_INT(MAIL_ATTR_TIMEOUT, timeout), + SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)), + SEND_ATTR_INT(TLS_ATTR_FLAGS, flags), + SEND_ATTR_INT(TLS_ATTR_TIMEOUT, handshake_timeout), + SEND_ATTR_INT(TLS_ATTR_TIMEOUT, session_timeout), + SEND_ATTR_STR(TLS_ATTR_SERVERID, serverid), ATTR_TYPE_END); + /* Do not flush the stream yet. */ + if (vstream_ferror(tlsproxy_stream) != 0) { + msg_warn("error sending request to %s service: %m", + STR(tlsproxy_service)); + vstream_fclose(tlsproxy_stream); + return (0); + } + switch (flags & (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_ROLE_SERVER)) { + case TLS_PROXY_FLAG_ROLE_CLIENT: + attr_print(tlsproxy_stream, ATTR_FLAG_NONE, + SEND_ATTR_FUNC(tls_proxy_client_param_print, tls_params), + SEND_ATTR_FUNC(tls_proxy_client_init_print, init_props), + SEND_ATTR_FUNC(tls_proxy_client_start_print, start_props), + ATTR_TYPE_END); + break; + case TLS_PROXY_FLAG_ROLE_SERVER: +#if 0 + attr_print(tlsproxy_stream, ATTR_FLAG_NONE, + SEND_ATTR_FUNC(tls_proxy_server_param_print, tls_params), + SEND_ATTR_FUNC(tls_proxy_server_init_print, init_props), + SEND_ATTR_FUNC(tls_proxy_server_start_print, start_props), + ATTR_TYPE_END); +#endif + break; + default: + msg_panic("%s: bad flags: 0x%x", myname, flags); + } if (vstream_fflush(tlsproxy_stream) != 0) { msg_warn("error sending request to %s service: %m", STR(tlsproxy_service)); @@ -172,11 +235,12 @@ VSTREAM *tls_proxy_open(const char *service, int flags, * Receive the "TLS is available" indication. * * This may seem out of order, but we must have a read transaction between - * sending the request attributes and sending the SMTP client file + * sending the request attributes and sending the plaintext file * descriptor. We can't assume UNIX-domain socket semantics here. */ if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), + /* TODO: informative message. */ ATTR_TYPE_END) != 1 || status == 0) { /* @@ -193,7 +257,7 @@ VSTREAM *tls_proxy_open(const char *service, int flags, } /* - * Send the remote SMTP client file descriptor. + * Send the remote peer file descriptor. */ if (LOCAL_SEND_FD(vstream_fileno(tlsproxy_stream), vstream_fileno(peer_stream)) < 0) { @@ -209,39 +273,22 @@ VSTREAM *tls_proxy_open(const char *service, int flags, return (tlsproxy_stream); } + /* tls_proxy_context_receive - receive TLS session object from tlsproxy(8) */ TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *proxy_stream) { - TLS_SESS_STATE *tls_context; - - tls_context = (TLS_SESS_STATE *) mymalloc(sizeof(*tls_context)); + TLS_SESS_STATE *tls_context = 0; if (attr_scan(proxy_stream, ATTR_FLAG_STRICT, - RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) tls_context), + RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) &tls_context), ATTR_TYPE_END) != 1) { - tls_proxy_context_free(tls_context); + if (tls_context) + tls_proxy_context_free(tls_context); return (0); } else { return (tls_context); } } -/* tls_proxy_context_free - destroy object from tls_proxy_context_receive() */ - -void tls_proxy_context_free(TLS_SESS_STATE *tls_context) -{ - if (tls_context->peer_CN) - myfree(tls_context->peer_CN); - if (tls_context->issuer_CN) - myfree(tls_context->issuer_CN); - if (tls_context->peer_cert_fprint) - myfree(tls_context->peer_cert_fprint); - if (tls_context->protocol) - myfree((void *) tls_context->protocol); - if (tls_context->cipher_name) - myfree((void *) tls_context->cipher_name); - myfree((void *) tls_context); -} - #endif diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_print.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_print.c index 572fce1dde0..b5b13e4cdf5 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_print.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_print.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_context_print.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_context_print.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_scan.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_scan.c index 7731fe957d8..415b0142802 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_scan.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_context_scan.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_context_scan.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_context_scan.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_print.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_print.c deleted file mode 100644 index 49d2e29eba2..00000000000 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_print.c +++ /dev/null @@ -1,88 +0,0 @@ -/* $NetBSD: tls_proxy_print.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ - -/*++ -/* NAME -/* tls_proxy_print -/* SUMMARY -/* write DSN structure to stream -/* SYNOPSIS -/* #include <tls_proxy.h> -/* -/* int tls_proxy_context_print(print_fn, stream, flags, ptr) -/* ATTR_PRINT_MASTER_FN print_fn; -/* VSTREAM *stream; -/* int flags; -/* void *ptr; -/* DESCRIPTION -/* tls_proxy_context_print() writes a TLS_SESS_STATE structure -/* to the named stream using the specified attribute print -/* routine. TLS_SESS_STATE() is meant to be passed as a call-back -/* to attr_print(), thusly: -/* -/* ... SEND_ATTR_FUNC(tls_proxy_context_print, (void *) tls_context), ... -/* DIAGNOSTICS -/* Fatal: out of memory. -/* 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 -/*--*/ - -#ifdef USE_TLS - -/* System library. */ - -#include <sys_defs.h> - -/* Utility library */ - -#include <attr.h> - -/* Global library. */ - -#include <mail_proto.h> - -/* TLS library. */ - -#include <tls.h> -#include <tls_proxy.h> - -/* tls_proxy_context_print - send TLS session state over stream */ - -int tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, - int flags, void *ptr) -{ - TLS_SESS_STATE *tp = (TLS_SESS_STATE *) ptr; - int ret; - -#define STRING_OR_EMPTY(s) ((s) ? (s) : "") - - ret = print_fn(fp, flags | ATTR_FLAG_MORE, - SEND_ATTR_STR(MAIL_ATTR_PEER_CN, - STRING_OR_EMPTY(tp->peer_CN)), - SEND_ATTR_STR(MAIL_ATTR_ISSUER_CN, - STRING_OR_EMPTY(tp->issuer_CN)), - SEND_ATTR_STR(MAIL_ATTR_PEER_CERT_FPT, - STRING_OR_EMPTY(tp->peer_cert_fprint)), - SEND_ATTR_STR(MAIL_ATTR_PEER_PKEY_FPT, - STRING_OR_EMPTY(tp->peer_pkey_fprint)), - SEND_ATTR_INT(MAIL_ATTR_PEER_STATUS, - tp->peer_status), - SEND_ATTR_STR(MAIL_ATTR_CIPHER_PROTOCOL, - STRING_OR_EMPTY(tp->protocol)), - SEND_ATTR_STR(MAIL_ATTR_CIPHER_NAME, - STRING_OR_EMPTY(tp->cipher_name)), - SEND_ATTR_INT(MAIL_ATTR_CIPHER_USEBITS, - tp->cipher_usebits), - SEND_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS, - tp->cipher_algbits), - ATTR_TYPE_END); - return (ret); -} - -#endif diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_scan.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_scan.c deleted file mode 100644 index 40444273e73..00000000000 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_scan.c +++ /dev/null @@ -1,96 +0,0 @@ -/* $NetBSD: tls_proxy_scan.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ - -/*++ -/* NAME -/* tls_proxy_scan -/* SUMMARY -/* read TLS session state from stream -/* SYNOPSIS -/* #include <tls_proxy.h> -/* -/* int tls_proxy_context_scan(scan_fn, stream, flags, ptr) -/* ATTR_SCAN_MASTER_FN scan_fn; -/* VSTREAM *stream; -/* int flags; -/* void *ptr; -/* DESCRIPTION -/* tls_proxy_context_scan() reads a TLS_SESS_STATE structure -/* from the named stream using the specified attribute scan -/* routine. tls_proxy_context_scan() is meant to be passed as -/* a call-back to attr_scan(), thusly: -/* -/* ... RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) tls_context), ... -/* DIAGNOSTICS -/* Fatal: out of memory. -/* 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 -/*--*/ - -#ifdef USE_TLS - -/* System library. */ - -#include <sys_defs.h> - -/* Utility library */ - -#include <attr.h> - -/* Global library. */ - -#include <mail_proto.h> - -/* TLS library. */ - -#include <tls.h> -#include <tls_proxy.h> - -/* tls_proxy_context_scan - receive TLS session state from stream */ - -int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, - int flags, void *ptr) -{ - TLS_SESS_STATE *tls_context = (TLS_SESS_STATE *) ptr; - int ret; - VSTRING *peer_CN = vstring_alloc(25); - VSTRING *issuer_CN = vstring_alloc(25); - VSTRING *peer_cert_fprint = vstring_alloc(60); /* 60 for SHA-1 */ - VSTRING *peer_pkey_fprint = vstring_alloc(60); /* 60 for SHA-1 */ - VSTRING *protocol = vstring_alloc(25); - VSTRING *cipher_name = vstring_alloc(25); - - /* - * Note: memset() is not a portable way to initialize non-integer types. - */ - memset(ptr, 0, sizeof(TLS_SESS_STATE)); - ret = scan_fn(fp, flags | ATTR_FLAG_MORE, - RECV_ATTR_STR(MAIL_ATTR_PEER_CN, peer_CN), - RECV_ATTR_STR(MAIL_ATTR_ISSUER_CN, issuer_CN), - RECV_ATTR_STR(MAIL_ATTR_PEER_CERT_FPT, peer_cert_fprint), - RECV_ATTR_STR(MAIL_ATTR_PEER_PKEY_FPT, peer_pkey_fprint), - RECV_ATTR_INT(MAIL_ATTR_PEER_STATUS, - &tls_context->peer_status), - RECV_ATTR_STR(MAIL_ATTR_CIPHER_PROTOCOL, protocol), - RECV_ATTR_STR(MAIL_ATTR_CIPHER_NAME, cipher_name), - RECV_ATTR_INT(MAIL_ATTR_CIPHER_USEBITS, - &tls_context->cipher_usebits), - RECV_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS, - &tls_context->cipher_algbits), - ATTR_TYPE_END); - tls_context->peer_CN = vstring_export(peer_CN); - tls_context->issuer_CN = vstring_export(issuer_CN); - tls_context->peer_cert_fprint = vstring_export(peer_cert_fprint); - tls_context->peer_pkey_fprint = vstring_export(peer_pkey_fprint); - tls_context->protocol = vstring_export(protocol); - tls_context->cipher_name = vstring_export(cipher_name); - return (ret == 9 ? 1 : -1); -} - -#endif diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_print.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_print.c index b5d56b88bfa..f44d08e55e4 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_print.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_print.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_server_print.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_server_print.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_scan.c b/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_scan.c index caa46d3cbee..0f28691947b 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_scan.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_proxy_server_scan.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_proxy_server_scan.c,v 1.1.1.1 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_proxy_server_scan.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_rsa.c b/external/ibm-public/postfix/dist/src/tls/tls_rsa.c index 616662e8476..9e4c59ff5d1 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_rsa.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_rsa.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_rsa.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_rsa.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -78,7 +78,6 @@ RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int export, int keylength) export ? "" : "non-", keylength); return 0; } -#if OPENSSL_VERSION_NUMBER >= 0x10000000L if (rsa_tmp == 0) { BIGNUM *e = BN_new(); @@ -90,11 +89,6 @@ RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int export, int keylength) if (e) BN_free(e); } -#else - if (rsa_tmp == 0) - rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL); -#endif - return (rsa_tmp); } diff --git a/external/ibm-public/postfix/dist/src/tls/tls_scache.c b/external/ibm-public/postfix/dist/src/tls/tls_scache.c index 32f14474245..523a1783335 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_scache.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_scache.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_scache.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_scache.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -92,7 +92,7 @@ /* .IP verbose /* Do verbose logging of cache operations? (zero == no) /* .IP timeout -/* The time after wich a session cache entry is considered too old. +/* The time after which a session cache entry is considered too old. /* .IP first_next /* One of DICT_SEQ_FUN_FIRST (first cache element) or DICT_SEQ_FUN_NEXT /* (next cache element). diff --git a/external/ibm-public/postfix/dist/src/tls/tls_server.c b/external/ibm-public/postfix/dist/src/tls/tls_server.c index 6a002598cc0..c15bb155a00 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_server.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_server.c,v 1.9 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_server.c,v 1.10 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -166,15 +166,8 @@ */ static const char server_session_id_context[] = "Postfix/TLS"; -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL #define GET_SID(s, v, lptr) ((v) = SSL_SESSION_get_id((s), (lptr))) -#else /* Older OpenSSL releases */ -#define GET_SID(s, v, lptr) \ - do { (v) = (s)->session_id; *(lptr) = (s)->session_id_length; } while (0) - -#endif /* OPENSSL_VERSION_NUMBER */ - /* OpenSSL 1.1.0 bitrot */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L typedef const unsigned char *session_id_t; @@ -308,9 +301,7 @@ static int new_server_session_cb(SSL *ssl, SSL_SESSION *session) /* ticket_cb - configure tls session ticket encrypt/decrypt context */ -#if defined(SSL_OP_NO_TICKET) \ - && !defined(OPENSSL_NO_TLSEXT) \ - && OPENSSL_VERSION_NUMBER >= 0x0090808fL +#if defined(SSL_OP_NO_TICKET) && !defined(OPENSSL_NO_TLSEXT) static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[], EVP_CIPHER_CTX * ctx, HMAC_CTX * hctx, int create) @@ -352,6 +343,8 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[], TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) { SSL_CTX *server_ctx; + SSL_CTX *sni_ctx; + X509_STORE *cert_store; long off = 0; int verify_flags = SSL_VERIFY_NONE; int cachable; @@ -443,31 +436,32 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) * SSLv2), so we need to have the SSLv23 server here. If we want to limit * the protocol level, we can add an option to not use SSLv2/v3/TLSv1 * later. - * - * OpenSSL 1.1.0-dev deprecates SSLv23_server_method() in favour of - * TLS_client_method(), with the change in question signalled via a new - * TLS_ANY_VERSION macro. */ ERR_clear_error(); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && defined(TLS_ANY_VERSION) server_ctx = SSL_CTX_new(TLS_server_method()); -#else - server_ctx = SSL_CTX_new(SSLv23_server_method()); -#endif if (server_ctx == 0) { msg_warn("cannot allocate server SSL_CTX: disabling TLS support"); tls_print_errors(); return (0); } + sni_ctx = SSL_CTX_new(TLS_server_method()); + if (sni_ctx == 0) { + SSL_CTX_free(server_ctx); + msg_warn("cannot allocate server SNI SSL_CTX: disabling TLS support"); + tls_print_errors(); + return (0); + } #ifdef SSL_SECOP_PEER /* Backwards compatible security as a base for opportunistic TLS. */ SSL_CTX_set_security_level(server_ctx, 0); + SSL_CTX_set_security_level(sni_ctx, 0); #endif /* * See the verify callback in tls_verify.c */ SSL_CTX_set_verify_depth(server_ctx, props->verifydepth + 1); + SSL_CTX_set_verify_depth(sni_ctx, props->verifydepth + 1); /* * The session cache is implemented by the tlsmgr(8) server. @@ -492,11 +486,10 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) /* * Add SSL_OP_NO_TICKET when the timeout is zero or library support is - * incomplete. The SSL_CTX_set_tlsext_ticket_key_cb feature was added in - * OpenSSL 0.9.8h, while SSL_NO_TICKET was added in 0.9.8f. + * incomplete. */ #ifdef SSL_OP_NO_TICKET -#if !defined(OPENSSL_NO_TLSEXT) && OPENSSL_VERSION_NUMBER >= 0x0090808fL +#ifndef OPENSSL_NO_TLSEXT ticketable = (*var_tls_tkt_cipher && scache_timeout > 0 && !(off & SSL_OP_NO_TICKET)); if (ticketable) { @@ -512,8 +505,23 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) ticketable = 0; } } - if (ticketable) + if (ticketable) { SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, ticket_cb); + + /* + * OpenSSL 1.1.1 introduces support for TLS 1.3, which can issue more + * than one ticket per handshake. While this may be appropriate for + * communication between browsers and webservers, it is not terribly + * useful for MTAs, many of which other than Postfix don't do TLS + * session caching at all, and Postfix has no mechanism for storing + * multiple session tickets, if more than one sent, the second + * clobbers the first. OpenSSL 1.1.1 servers default to issuing two + * tickets for non-resumption handshakes, we reduce this to one. Our + * ticket decryption callback already (since 2.11) asks OpenSSL to + * avoid issuing new tickets when the presented ticket is re-usable. + */ + SSL_CTX_set_num_tickets(server_ctx, 1); + } #endif if (!ticketable) off |= SSL_OP_NO_TICKET; @@ -532,18 +540,21 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) * this could trigger inter-operability issues, the client should not * offer ciphers it implements poorly, but this hasn't stopped some * vendors from getting it wrong. - * - * XXX: Given OpenSSL's security history, nobody should still be using - * 0.9.7, let alone 0.9.6 or earlier. Warning added to TLS_README.html. */ if (var_tls_preempt_clist) SSL_CTX_set_options(server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + /* Done with server_ctx options, clone to sni_ctx */ + SSL_CTX_clear_options(sni_ctx, ~0); + SSL_CTX_set_options(sni_ctx, SSL_CTX_get_options(server_ctx)); + /* * Set the call-back routine to debug handshake progress. */ - if (log_mask & TLS_LOG_DEBUG) + if (log_mask & TLS_LOG_DEBUG) { SSL_CTX_set_info_callback(server_ctx, tls_info_callback); + SSL_CTX_set_info_callback(sni_ctx, tls_info_callback); + } /* * Load the CA public key certificates for both the server cert and for @@ -560,10 +571,19 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) props->CAfile, props->CApath) < 0) { /* tls_set_ca_certificate_info() already logs a warning. */ SSL_CTX_free(server_ctx); /* 200411 */ + SSL_CTX_free(sni_ctx); return (0); } /* + * 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. + */ + cert_store = SSL_CTX_get_cert_store(server_ctx); + X509_STORE_up_ref(cert_store); + SSL_CTX_set_cert_store(sni_ctx, cert_store); + + /* * Load the server public key certificate and private key from file and * check whether the cert matches the key. We can use RSA certificates * ("cert") DSA certificates ("dcert") or ECDSA certificates ("eccert"). @@ -576,6 +596,7 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) * changed in the cipher setup. */ if (tls_set_my_certificate_key_info(server_ctx, + props->chain_files, props->cert_file, props->key_file, props->dcert_file, @@ -584,6 +605,7 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) props->eckey_file) < 0) { /* tls_set_my_certificate_key_info() already logs a warning. */ SSL_CTX_free(server_ctx); /* 200411 */ + SSL_CTX_free(sni_ctx); return (0); } @@ -598,6 +620,7 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) * directly used. */ SSL_CTX_set_tmp_rsa_callback(server_ctx, tls_tmp_rsa_cb); + SSL_CTX_set_tmp_rsa_callback(sni_ctx, tls_tmp_rsa_cb); #endif /* @@ -609,6 +632,7 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) * will not abort but just log the error message. */ SSL_CTX_set_tmp_dh_callback(server_ctx, tls_tmp_dh_cb); + SSL_CTX_set_tmp_dh_callback(sni_ctx, tls_tmp_dh_cb); if (*props->dh1024_param_file != 0) tls_set_dh_from_file(props->dh1024_param_file, 1024); if (*props->dh512_param_file != 0) @@ -618,7 +642,8 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) * Enable EECDH if available, errors are not fatal, we just keep going * with any remaining key-exchange algorithms. */ - (void) tls_set_eecdh_curve(server_ctx, props->eecdh_grade); + tls_set_eecdh_curve(server_ctx, props->eecdh_grade); + tls_set_eecdh_curve(sni_ctx, props->eecdh_grade); /* * If we want to check client certificates, we have to indicate it in @@ -644,15 +669,36 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; SSL_CTX_set_verify(server_ctx, verify_flags, tls_verify_certificate_callback); - if (*props->CAfile) - SSL_CTX_set_client_CA_list(server_ctx, - SSL_load_client_CA_file(props->CAfile)); + SSL_CTX_set_verify(sni_ctx, verify_flags, + tls_verify_certificate_callback); + if (props->ask_ccert && *props->CAfile) { + STACK_OF(X509_NAME) *calist = SSL_load_client_CA_file(props->CAfile); + + if (calist == 0) { + /* Not generally critical */ + msg_warn("error loading client CA names from: %s", + props->CAfile); + tls_print_errors(); + } + SSL_CTX_set_client_CA_list(server_ctx, calist); + + if (calist != 0 && sk_X509_NAME_num(calist) > 0) { + calist = SSL_dup_CA_list(calist); + + if (calist == 0) { + msg_warn("error duplicating client CA names for SNI"); + tls_print_errors(); + } else { + SSL_CTX_set_client_CA_list(sni_ctx, calist); + } + } + } /* * Initialize our own TLS server handle, before diving into the details * of TLS session cache management. */ - app_ctx = tls_alloc_app_context(server_ctx, log_mask); + app_ctx = tls_alloc_app_context(server_ctx, sni_ctx, log_mask); if (cachable || ticketable || props->set_sessid) { @@ -735,16 +781,6 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) if (log_mask & TLS_LOG_VERBOSE) msg_info("setting up TLS connection from %s", props->namaddr); - cipher_list = tls_set_ciphers(app_ctx, "TLS", props->cipher_grade, - props->cipher_exclusions); - if (cipher_list == 0) { - msg_warn("%s: %s: aborting TLS session", props->namaddr, - vstring_str(app_ctx->why)); - return (0); - } - if (log_mask & TLS_LOG_VERBOSE) - msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list); - /* * Allocate a new TLScontext for the new connection and get an SSL * structure. Add the location of TLScontext to the SSL to later retrieve @@ -753,11 +789,6 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) TLScontext = tls_alloc_sess_context(log_mask, props->namaddr); TLScontext->cache_type = app_ctx->cache_type; - TLScontext->serverid = mystrdup(props->serverid); - TLScontext->am_server = 1; - TLScontext->stream = props->stream; - TLScontext->mdalg = props->mdalg; - ERR_clear_error(); if ((TLScontext->con = (SSL *) SSL_new(app_ctx->ssl_ctx)) == 0) { msg_warn("Could not allocate 'TLScontext->con' with SSL_new()"); @@ -765,6 +796,21 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) tls_free_context(TLScontext); return (0); } + cipher_list = tls_set_ciphers(TLScontext, props->cipher_grade, + props->cipher_exclusions); + if (cipher_list == 0) { + /* already warned */ + tls_free_context(TLScontext); + return (0); + } + if (log_mask & TLS_LOG_VERBOSE) + msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list); + + TLScontext->serverid = mystrdup(props->serverid); + TLScontext->am_server = 1; + TLScontext->stream = props->stream; + TLScontext->mdalg = props->mdalg; + if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) { msg_warn("Could not set application data for 'TLScontext->con'"); tls_print_errors(); @@ -785,13 +831,6 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) (void) tls_ext_seed(var_tls_daemon_rand_bytes); /* - * Initialize the SSL connection to accept state. This should not be - * necessary anymore since 0.9.3, but the call is still in the library - * and maintaining compatibility never hurts. - */ - SSL_set_accept_state(TLScontext->con); - - /* * Connect the SSL connection with the network socket. */ if (SSL_set_fd(TLScontext->con, props->stream == 0 ? props->fd : @@ -832,7 +871,7 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) * Start TLS negotiations. This process is a black box that invokes our * call-backs for session caching and certificate verification. * - * Error handling: If the SSL handhake fails, we print out an error message + * Error handling: If the SSL handshake fails, we print out an error message * and remove all TLS state concerning this session. */ sts = tls_bio_accept(vstream_fileno(props->stream), props->timeout, @@ -857,7 +896,7 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) { - SSL_CIPHER_const SSL_CIPHER *cipher; + const SSL_CIPHER *cipher; X509 *peer; char buf[CCERT_BUFSIZ]; @@ -948,14 +987,15 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) tls_stream_start(TLScontext->stream, TLScontext); /* + * With the handshake done, extract TLS 1.3 signature metadata. + */ + tls_get_signature_params(TLScontext); + + /* * All the key facts in a single log entry. */ if (TLScontext->log_mask & TLS_LOG_SUMMARY) - msg_info("%s TLS connection established from %s: %s with cipher %s " - "(%d/%d bits)", !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" - : TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted", - TLScontext->namaddr, TLScontext->protocol, TLScontext->cipher_name, - TLScontext->cipher_usebits, TLScontext->cipher_algbits); + tls_log_summary(TLS_ROLE_SERVER, TLS_USAGE_NEW, TLScontext); tls_int_seed(); diff --git a/external/ibm-public/postfix/dist/src/tls/tls_session.c b/external/ibm-public/postfix/dist/src/tls/tls_session.c index a93fe6d2cf2..6d6c0ea402e 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_session.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_session.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_session.c,v 1.1.1.2 2020/03/18 18:59:35 christos Exp $ */ +/* $NetBSD: tls_session.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tls/tls_verify.c b/external/ibm-public/postfix/dist/src/tls/tls_verify.c index 171866b7e8f..3695c6a153e 100644 --- a/external/ibm-public/postfix/dist/src/tls/tls_verify.c +++ b/external/ibm-public/postfix/dist/src/tls/tls_verify.c @@ -1,4 +1,4 @@ -/* $NetBSD: tls_verify.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tls_verify.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -430,7 +430,7 @@ const char *tls_dns_name(const GENERAL_NAME * gn, msg_panic("%s: Non DNS input argument", myname); /* - * We expect the OpenSSL library to construct GEN_DNS extesion objects as + * We expect the OpenSSL library to construct GEN_DNS extension objects as * ASN1_IA5STRING values. Check we got the right union member. */ if (ASN1_STRING_type(gn->d.ia5) != V_ASN1_IA5STRING) { diff --git a/external/ibm-public/postfix/dist/src/tlsmgr/tlsmgr.c b/external/ibm-public/postfix/dist/src/tlsmgr/tlsmgr.c index 8593aa2e865..a95fb611282 100644 --- a/external/ibm-public/postfix/dist/src/tlsmgr/tlsmgr.c +++ b/external/ibm-public/postfix/dist/src/tlsmgr/tlsmgr.c @@ -1,4 +1,4 @@ -/* $NetBSD: tlsmgr.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tlsmgr.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -51,7 +51,8 @@ /* to the Postfix-owned \fBdata_directory\fR, and a warning /* is logged. /* DIAGNOSTICS -/* Problems and transactions are logged to the syslog daemon. +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* There is no automatic means to limit the number of entries in the /* TLS session caches and/or the size of the TLS cache files. @@ -132,14 +133,19 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* smtp(8), Postfix SMTP client /* smtpd(8), Postfix SMTP server /* postconf(5), configuration parameters /* master(5), generic daemon options /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad @@ -755,8 +761,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, } else { VSTRING_SPACE(buffer, len); RAND_bytes((unsigned char *) STR(buffer), len); - VSTRING_AT_OFFSET(buffer, len); /* XXX not part of the - * official interface */ + vstring_set_payload_size(buffer, len); status = TLS_MGR_STAT_OK; } } diff --git a/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.c b/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.c index 87b4b67d206..a92eb469b6f 100644 --- a/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.c +++ b/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.c @@ -1,4 +1,4 @@ -/* $NetBSD: tlsproxy.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tlsproxy.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -8,11 +8,12 @@ /* SYNOPSIS /* \fBtlsproxy\fR [generic Postfix daemon options] /* DESCRIPTION -/* The \fBtlsproxy\fR(8) server implements a server-side TLS -/* proxy. It is used by \fBpostscreen\fR(8) to talk SMTP-over-TLS +/* The \fBtlsproxy\fR(8) server implements a two-way TLS proxy. It +/* is used by the \fBpostscreen\fR(8) server to talk SMTP-over-TLS /* with remote SMTP clients that are not whitelisted (including -/* clients whose whitelist status has expired), -/* but it should also work for non-SMTP protocols. +/* clients whose whitelist status has expired), and by the +/* \fBsmtp\fR(8) client to support TLS connection reuse, but it +/* should also work for non-SMTP protocols. /* /* Although one \fBtlsproxy\fR(8) process can serve multiple /* sessions at the same time, it is a good idea to allow the @@ -46,7 +47,8 @@ /* It talks to untrusted clients on the network. The process /* can be run chrooted at fixed low privilege. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -57,9 +59,94 @@ /* /* The text below provides only a parameter summary. See /* \fBpostconf\fR(5) for more details including examples. -/* STARTTLS SUPPORT CONTROLS +/* STARTTLS GLOBAL CONTROLS /* .ad /* .fi +/* The following settings are global and therefore cannot be +/* overruled by information specified in a \fBtlsproxy\fR(8) +/* client request. +/* .IP "\fBtls_append_default_CA (no)\fR" +/* Append the system-supplied default Certification Authority +/* certificates to the ones specified with *_tls_CApath or *_tls_CAfile. +/* .IP "\fBtls_daemon_random_bytes (32)\fR" +/* 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 +/* internal pseudo random number generator (PRNG). +/* .IP "\fBtls_high_cipherlist (see 'postconf -d' output)\fR" +/* The OpenSSL cipherlist for "high" grade ciphers. +/* .IP "\fBtls_medium_cipherlist (see 'postconf -d' output)\fR" +/* The OpenSSL cipherlist for "medium" or higher grade ciphers. +/* .IP "\fBtls_low_cipherlist (see 'postconf -d' output)\fR" +/* The OpenSSL cipherlist for "low" or higher grade ciphers. +/* .IP "\fBtls_export_cipherlist (see 'postconf -d' output)\fR" +/* The OpenSSL cipherlist for "export" or higher grade ciphers. +/* .IP "\fBtls_null_cipherlist (eNULL:!aNULL)\fR" +/* The OpenSSL cipherlist for "NULL" grade ciphers that provide +/* authentication without encryption. +/* .IP "\fBtls_eecdh_strong_curve (prime256v1)\fR" +/* The elliptic curve used by the Postfix SMTP server for sensibly +/* strong +/* ephemeral ECDH key exchange. +/* .IP "\fBtls_eecdh_ultra_curve (secp384r1)\fR" +/* The elliptic curve used by the Postfix SMTP server for maximally +/* strong +/* ephemeral ECDH key exchange. +/* .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR" +/* List or bit-mask of OpenSSL bug work-arounds to disable. +/* .IP "\fBtls_preempt_cipherlist (no)\fR" +/* With SSLv3 and later, use the Postfix SMTP server's cipher +/* preference order instead of the remote client's cipher preference +/* order. +/* .PP +/* Available in Postfix version 2.9 and later: +/* .IP "\fBtls_legacy_public_key_fingerprints (no)\fR" +/* A temporary migration aid for sites that use certificate +/* \fIpublic-key\fR fingerprints with Postfix 2.9.0..2.9.5, which use +/* an incorrect algorithm. +/* .PP +/* Available in Postfix version 2.11-3.1: +/* .IP "\fBtls_dane_digest_agility (on)\fR" +/* Configure RFC7671 DANE TLSA digest algorithm agility. +/* .IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR" +/* Enable support for RFC 6698 (DANE TLSA) DNS records that contain +/* digests of trust-anchors with certificate usage "2". +/* .PP +/* Available in Postfix version 2.11 and later: +/* .IP "\fBtlsmgr_service_name (tlsmgr)\fR" +/* The name of the \fBtlsmgr\fR(8) service entry in master.cf. +/* .PP +/* Available in Postfix version 3.0 and later: +/* .IP "\fBtls_session_ticket_cipher (Postfix >= 3.0: aes-256-cbc, Postfix < 3.0: aes-128-cbc)\fR" +/* Algorithm used to encrypt RFC5077 TLS session tickets. +/* .IP "\fBopenssl_path (openssl)\fR" +/* The location of the OpenSSL command line program \fBopenssl\fR(1). +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBtls_eecdh_auto_curves (see 'postconf -d' output)\fR" +/* The prioritized list of elliptic curves supported by the Postfix +/* SMTP client and server. +/* .PP +/* Available in Postfix version 3.4 and later: +/* .IP "\fBtls_server_sni_maps (empty)\fR" +/* Optional lookup tables that map names received from remote SMTP +/* clients via the TLS Server Name Indication (SNI) extension to the +/* appropriate keys and certificate chains. +/* .PP +/* Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later: +/* .IP "\fBtls_fast_shutdown_enable (yes)\fR" +/* A workaround for implementations that hang Postfix while shutting +/* down a TLS session, until Postfix times out. +/* STARTTLS SERVER CONTROLS +/* .ad +/* .fi +/* These settings are clones of Postfix SMTP server settings. +/* They allow \fBtlsproxy\fR(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 \fBtlsproxy\fR(8) client +/* request, but that limitation may be removed in a future +/* version. /* .IP "\fBtlsproxy_tls_CAfile ($smtpd_tls_CAfile)\fR" /* A file containing (PEM format) CA certificates of root CAs /* trusted to sign either remote SMTP client certificates or intermediate @@ -94,11 +181,11 @@ /* File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM /* format. /* .IP "\fBtlsproxy_tls_eccert_file ($smtpd_tls_eccert_file)\fR" -/* File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in -/* PEM format. +/* File with the Postfix \fBtlsproxy\fR(8) server ECDSA certificate in PEM +/* format. /* .IP "\fBtlsproxy_tls_eckey_file ($smtpd_tls_eckey_file)\fR" -/* File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in -/* PEM format. +/* File with the Postfix \fBtlsproxy\fR(8) server ECDSA private key in PEM +/* format. /* .IP "\fBtlsproxy_tls_eecdh_grade ($smtpd_tls_eecdh_grade)\fR" /* The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral /* elliptic-curve Diffie-Hellman (EECDH) key exchange. @@ -134,10 +221,74 @@ /* The SMTP TLS security level for the Postfix \fBtlsproxy\fR(8) server; /* when a non-empty value is specified, this overrides the obsolete /* 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. +/* STARTTLS CLIENT CONTROLS +/* .ad +/* .fi +/* These settings are clones of Postfix SMTP client settings. +/* They allow \fBtlsproxy\fR(8) to load the same certificate +/* and private key information as 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 \fBtlsproxy\fR(8) client request. /* .PP -/* Available in Postfix version 2.11 and later: -/* .IP "\fBtlsmgr_service_name (tlsmgr)\fR" -/* The name of the \fBtlsmgr\fR(8) service entry in master.cf. +/* Available in Postfix version 3.4 and later: +/* .IP "\fBtlsproxy_client_CAfile ($smtp_tls_CAfile)\fR" +/* A file containing CA certificates of root CAs trusted to sign +/* either remote TLS server certificates or intermediate CA certificates. +/* .IP "\fBtlsproxy_client_CApath ($smtp_tls_CApath)\fR" +/* Directory with PEM format Certification Authority certificates +/* that the Postfix \fBtlsproxy\fR(8) client uses to verify a remote TLS +/* server certificate. +/* .IP "\fBtlsproxy_client_chain_files ($smtp_tls_chain_files)\fR" +/* Files with the Postfix \fBtlsproxy\fR(8) client keys and certificate +/* chains in PEM format. +/* .IP "\fBtlsproxy_client_cert_file ($smtp_tls_cert_file)\fR" +/* File with the Postfix \fBtlsproxy\fR(8) client RSA certificate in PEM +/* format. +/* .IP "\fBtlsproxy_client_key_file ($smtp_tls_key_file)\fR" +/* File with the Postfix \fBtlsproxy\fR(8) client RSA private key in PEM +/* format. +/* .IP "\fBtlsproxy_client_dcert_file ($smtp_tls_dcert_file)\fR" +/* File with the Postfix \fBtlsproxy\fR(8) client DSA certificate in PEM +/* format. +/* .IP "\fBtlsproxy_client_dkey_file ($smtp_tls_dkey_file)\fR" +/* File with the Postfix \fBtlsproxy\fR(8) client DSA private key in PEM +/* format. +/* .IP "\fBtlsproxy_client_eccert_file ($smtp_tls_eccert_file)\fR" +/* File with the Postfix \fBtlsproxy\fR(8) client ECDSA certificate in PEM +/* format. +/* .IP "\fBtlsproxy_client_eckey_file ($smtp_tls_eckey_file)\fR" +/* File with the Postfix \fBtlsproxy\fR(8) client ECDSA private key in PEM +/* format. +/* .IP "\fBtlsproxy_client_fingerprint_digest ($smtp_tls_fingerprint_digest)\fR" +/* The message digest algorithm used to construct remote TLS server +/* certificate fingerprints. +/* .IP "\fBtlsproxy_client_loglevel ($smtp_tls_loglevel)\fR" +/* Enable additional Postfix \fBtlsproxy\fR(8) client logging of TLS +/* activity. +/* .IP "\fBtlsproxy_client_loglevel_parameter (smtp_tls_loglevel)\fR" +/* The name of the parameter that provides the tlsproxy_client_loglevel +/* value. +/* .IP "\fBtlsproxy_client_scert_verifydepth ($smtp_tls_scert_verifydepth)\fR" +/* The verification depth for remote TLS server certificates. +/* .IP "\fBtlsproxy_client_security_level ($smtp_tls_security_level)\fR" +/* The default TLS security level for the Postfix \fBtlsproxy\fR(8) +/* client. +/* .IP "\fBtlsproxy_client_policy_maps ($smtp_tls_policy_maps)\fR" +/* Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS +/* security policy by next-hop destination. +/* .IP "\fBtlsproxy_client_use_tls ($smtp_use_tls)\fR" +/* Opportunistic mode: use TLS when a remote server announces TLS +/* support. +/* .IP "\fBtlsproxy_client_enforce_tls ($smtp_enforce_tls)\fR" +/* Enforcement mode: require that SMTP servers use TLS encryption. +/* .IP "\fBtlsproxy_client_per_site ($smtp_tls_per_site)\fR" +/* Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS +/* usage policy by next-hop destination and by remote TLS server +/* hostname. /* OBSOLETE STARTTLS SUPPORT CONTROLS /* .ad /* .fi @@ -168,13 +319,18 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* postscreen(8), Postfix zombie blocker /* smtpd(8), Postfix SMTP server /* postconf(5), configuration parameters -/* syslogd(5), system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* LICENSE /* .ad /* .fi @@ -213,10 +369,12 @@ #include <iostuff.h> #include <nbbio.h> #include <mymalloc.h> +#include <split_at.h> /* * Global library. */ +#include <been_here.h> #include <mail_proto.h> #include <mail_params.h> #include <mail_conf.h> @@ -252,6 +410,7 @@ bool var_smtpd_tls_ask_ccert; bool var_smtpd_tls_req_ccert; bool var_smtpd_tls_set_sessid; char *var_smtpd_relay_ccerts; +char *var_smtpd_tls_chain_files; char *var_smtpd_tls_cert_file; char *var_smtpd_tls_key_file; char *var_smtpd_tls_dcert_file; @@ -279,6 +438,7 @@ bool var_tlsp_enforce_tls; bool var_tlsp_tls_ask_ccert; bool var_tlsp_tls_req_ccert; bool var_tlsp_tls_set_sessid; +char *var_tlsp_tls_chain_files; char *var_tlsp_tls_cert_file; char *var_tlsp_tls_key_file; char *var_tlsp_tls_dcert_file; @@ -302,19 +462,83 @@ char *var_tlsp_tls_level; int var_tlsp_watchdog; /* + * Defaults for tlsp_clnt_*. + */ +char *var_smtp_tls_loglevel; +int var_smtp_tls_scert_vd; +char *var_smtp_tls_chain_files; +char *var_smtp_tls_cert_file; +char *var_smtp_tls_key_file; +char *var_smtp_tls_dcert_file; +char *var_smtp_tls_dkey_file; +char *var_smtp_tls_eccert_file; +char *var_smtp_tls_eckey_file; +char *var_smtp_tls_CAfile; +char *var_smtp_tls_CApath; +char *var_smtp_tls_fpt_dgst; +char *var_smtp_tls_level; +bool var_smtp_use_tls; +bool var_smtp_enforce_tls; +char *var_smtp_tls_per_site; +char *var_smtp_tls_policy; + +char *var_tlsp_clnt_loglevel; +char *var_tlsp_clnt_logparam; +int var_tlsp_clnt_scert_vd; +char *var_tlsp_clnt_chain_files; +char *var_tlsp_clnt_cert_file; +char *var_tlsp_clnt_key_file; +char *var_tlsp_clnt_dcert_file; +char *var_tlsp_clnt_dkey_file; +char *var_tlsp_clnt_eccert_file; +char *var_tlsp_clnt_eckey_file; +char *var_tlsp_clnt_CAfile; +char *var_tlsp_clnt_CApath; +char *var_tlsp_clnt_fpt_dgst; +char *var_tlsp_clnt_level; +bool var_tlsp_clnt_use_tls; +bool var_tlsp_clnt_enforce_tls; +char *var_tlsp_clnt_per_site; +char *var_tlsp_clnt_policy; + + /* * TLS per-process status. */ static TLS_APPL_STATE *tlsp_server_ctx; +static bool tlsp_pre_jail_done; static int ask_client_cert; +static char *tlsp_pre_jail_client_param_key; /* pre-jail global params */ +static char *tlsp_pre_jail_client_init_key; /* pre-jail init props */ + + /* + * TLS per-client status. + */ +static HTABLE *tlsp_client_app_cache; /* per-client init props */ +static BH_TABLE *tlsp_params_mismatch_filter; /* per-client nag filter */ + + /* + * Error handling: if a function detects an error, then that function is + * responsible for destroying TLSP_STATE. Exceptions to this principle are + * indicated in the code. + */ + + /* + * Internal status API. + */ +#define TLSP_STAT_OK 0 +#define TLSP_STAT_ERR (-1) /* * SLMs. */ #define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) /* - * This code looks simpler than expected. That is the result of a great deal - * of effort, mainly in design and analysis. + * The code that implements the TLS engine looks simpler than expected. That + * is the result of a great deal of effort, mainly in design and analysis. + * + * The initial use case was to provide TLS support for postscreen(8). * * By design, postscreen(8) is an event-driven server that must scale up to a * large number of clients. This means that postscreen(8) must avoid doing @@ -341,12 +565,17 @@ static int ask_client_cert; * public mailing lists. After some field experience with this code, we may * be able to factor it out as a library module, like nbbio(3), that can * become part of the TLS library. + * + * Later in the life cycle, tlsproxy(8) has also become an enabler for TLS + * connection reuse across different SMTP client processes. */ static void tlsp_ciphertext_event(int, void *); #define TLSP_INIT_TIMEOUT 100 +static void tlsp_plaintext_event(int event, void *context); + /* tlsp_drain - delayed exit after "postfix reload" */ static void tlsp_drain(char *unused_service, char **unused_argv) @@ -391,11 +620,11 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err) switch (err) { /* - * No error from SSL_read and SSL_write means that the plaintext - * output buffer is full and that the plaintext input buffer is - * empty. Stop read/write events on the ciphertext stream. Keep the - * timer alive as a safety mechanism for the case that the plaintext - * pseudothreads get stuck. + * No error means a successful SSL_accept/connect/shutdown request or + * sequence of SSL_read/write requests. Disable read/write events on + * the ciphertext stream. Keep the ciphertext stream timer alive as a + * safety mechanism for the case that the plaintext pseudothreads get + * stuck. */ case SSL_ERROR_NONE: if (state->ssl_last_err != SSL_ERROR_NONE) { @@ -404,7 +633,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err) state->timeout); state->ssl_last_err = SSL_ERROR_NONE; } - return (0); + return (TLSP_STAT_OK); /* * The TLS engine wants to write to the network. Turn on @@ -420,7 +649,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err) } event_request_timer(tlsp_ciphertext_event, (void *) state, state->timeout); - return (0); + return (TLSP_STAT_OK); /* * The TLS engine wants to read from the network. Turn on @@ -436,7 +665,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err) } event_request_timer(tlsp_ciphertext_event, (void *) state, state->timeout); - return (0); + return (TLSP_STAT_OK); /* * Some error. Self-destruct. This automagically cleans up all @@ -447,11 +676,83 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err) tls_print_errors(); /* FALLTHROUGH */ default: + + /* + * Allow buffered-up plaintext output to trickle out. Permanently + * disable read/write activity on the ciphertext stream, so that this + * function will no longer be called. Keep the ciphertext stream + * timer alive as a safety mechanism for the case that the plaintext + * pseudothreads get stuck. Return into tlsp_strategy(), which will + * enable plaintext write events. + */ +#define TLSP_CAN_TRICKLE_OUT_PLAINTEXT(buf) \ + ((buf) && !NBBIO_ERROR_FLAGS(buf) && NBBIO_WRITE_PEND(buf)) + + if (TLSP_CAN_TRICKLE_OUT_PLAINTEXT(state->plaintext_buf)) { + event_disable_readwrite(ciphertext_fd); + event_request_timer(tlsp_ciphertext_event, (void *) state, + state->timeout); + state->flags |= TLSP_FLAG_NO_MORE_CIPHERTEXT_IO; + return (TLSP_STAT_OK); + } tlsp_state_free(state); - return (-1); + return (TLSP_STAT_ERR); } } +/* tlsp_post_handshake - post-handshake processing */ + +static int tlsp_post_handshake(TLSP_STATE *state) +{ + + /* + * Do not assume that tls_server_post_accept() and + * tls_client_post_connect() will always succeed. + */ + if (state->is_server_role) + state->tls_context = tls_server_post_accept(state->tls_context); + else + state->tls_context = tls_client_post_connect(state->tls_context, + state->client_start_props); + if (state->tls_context == 0) { + tlsp_state_free(state); + return (TLSP_STAT_ERR); + } + + /* + * Report TLS handshake results to the tlsproxy client. + * + * Security: this sends internal data over the same local plaintext stream + * that will also be used for sending decrypted remote content from an + * arbitrary remote peer. For this reason we enable decrypted I/O only + * after reporting the TLS handshake results. The Postfix attribute + * protocol is robust enough that an attacker cannot append content. + */ + if ((state->req_flags & TLS_PROXY_FLAG_SEND_CONTEXT) != 0 + && (attr_print(state->plaintext_stream, ATTR_FLAG_NONE, + SEND_ATTR_FUNC(tls_proxy_context_print, + (void *) state->tls_context), + ATTR_TYPE_END) != 0 + || vstream_fflush(state->plaintext_stream) != 0)) { + msg_warn("cannot send TLS context: %m"); + tlsp_state_free(state); + return (TLSP_STAT_ERR); + } + + /* + * Initialize plaintext-related session state. Once we have this behind + * us, the TLSP_STATE destructor will automagically clean up requests for + * plaintext read/write/timeout events, which makes error recovery + * easier. + */ + state->plaintext_buf = + nbbio_create(vstream_fileno(state->plaintext_stream), + VSTREAM_BUFSIZE, state->server_id, + tlsp_plaintext_event, + (void *) state); + return (TLSP_STAT_OK); +} + /* tlsp_strategy - decide what to read or write next. */ static void tlsp_strategy(TLSP_STATE *state) @@ -464,147 +765,173 @@ static void tlsp_strategy(TLSP_STATE *state) int handshake_err; /* - * Be sure to complete the TLS handshake before enabling plain-text I/O. - * In case of an unrecoverable error, this automagically cleans up all - * pending read/write and timeout event requests. + * This function is called after every ciphertext or plaintext event, to + * schedule new ciphertext or plaintext I/O. */ - if (state->flags & TLSP_FLAG_DO_HANDSHAKE) { - ssl_stat = SSL_accept(tls_context->con); - if (ssl_stat != 1) { - handshake_err = SSL_get_error(tls_context->con, ssl_stat); - tlsp_eval_tls_error(state, handshake_err); - /* At this point, state could be a dangling pointer. */ - return; + + /* + * Try to make an SSL I/O request. If this fails with SSL_ERROR_WANT_READ + * or SSL_ERROR_WANT_WRITE, enable ciphertext read or write events, and + * retry the SSL I/O request in a later tlsp_strategy() call. + */ + if ((state->flags & TLSP_FLAG_NO_MORE_CIPHERTEXT_IO) == 0) { + + /* + * Do not enable plain-text I/O before completing the TLS handshake. + * Otherwise the remote peer can prepend plaintext to the optional + * TLS_SESS_STATE object. + */ + if (state->flags & TLSP_FLAG_DO_HANDSHAKE) { + state->timeout = state->handshake_timeout; + if (state->is_server_role) + ssl_stat = SSL_accept(tls_context->con); + else + ssl_stat = SSL_connect(tls_context->con); + if (ssl_stat != 1) { + handshake_err = SSL_get_error(tls_context->con, ssl_stat); + tlsp_eval_tls_error(state, handshake_err); + /* At this point, state could be a dangling pointer. */ + return; + } + state->flags &= ~TLSP_FLAG_DO_HANDSHAKE; + state->timeout = state->session_timeout; + if (tlsp_post_handshake(state) != TLSP_STAT_OK) { + /* At this point, state is a dangling pointer. */ + return; + } } - if ((state->tls_context = tls_server_post_accept(tls_context)) == 0) { + + /* + * Shutdown and self-destruct after NBBIO error. This automagically + * cleans up all pending read/write and timeout event requests. + * Before shutting down TLS, we stop all plain-text I/O events but + * keep the NBBIO error flags. + */ + plaintext_buf = state->plaintext_buf; + if (NBBIO_ERROR_FLAGS(plaintext_buf)) { + if (NBBIO_ACTIVE_FLAGS(plaintext_buf)) + nbbio_disable_readwrite(state->plaintext_buf); + if (!SSL_in_init(tls_context->con) + && (ssl_stat = SSL_shutdown(tls_context->con)) < 0) { + handshake_err = SSL_get_error(tls_context->con, ssl_stat); + tlsp_eval_tls_error(state, handshake_err); + /* At this point, state could be a dangling pointer. */ + return; + } tlsp_state_free(state); return; } - if ((state->req_flags & TLS_PROXY_FLAG_SEND_CONTEXT) != 0 - && (attr_print(state->plaintext_stream, ATTR_FLAG_NONE, - SEND_ATTR_FUNC(tls_proxy_context_print, - (void *) state->tls_context), - ATTR_TYPE_END) != 0 - || vstream_fflush(state->plaintext_stream) != 0)) { - msg_warn("cannot send TLS context: %m"); - tlsp_state_free(state); - return; + + /* + * Try to move data from the plaintext input buffer to the TLS + * engine. + * + * XXX We're supposed to repeat the exact same SSL_write() call + * arguments after an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE + * result. Rumor has it that this is because each SSL_write() call + * reads from the buffer incrementally, and returns > 0 only after + * the final byte is processed. Rumor also has it that setting + * SSL_MODE_ENABLE_PARTIAL_WRITE and + * SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER voids this requirement, and + * that repeating the request with an increased request size is OK. + * Unfortunately all this is not or poorly documented, and one has to + * rely on statements from OpenSSL developers in public mailing + * archives. + */ + ssl_write_err = SSL_ERROR_NONE; + while (NBBIO_READ_PEND(plaintext_buf) > 0) { + ssl_stat = SSL_write(tls_context->con, NBBIO_READ_BUF(plaintext_buf), + NBBIO_READ_PEND(plaintext_buf)); + ssl_write_err = SSL_get_error(tls_context->con, ssl_stat); + if (ssl_write_err != SSL_ERROR_NONE) + break; + /* Allow the plaintext pseudothread to read more data. */ + NBBIO_READ_PEND(plaintext_buf) -= ssl_stat; + if (NBBIO_READ_PEND(plaintext_buf) > 0) + memmove(NBBIO_READ_BUF(plaintext_buf), + NBBIO_READ_BUF(plaintext_buf) + ssl_stat, + NBBIO_READ_PEND(plaintext_buf)); } - state->flags &= ~TLSP_FLAG_DO_HANDSHAKE; - } - /* - * Shutdown and self-destruct after NBBIO error. This automagically - * cleans up all pending read/write and timeout event requests. Before - * shutting down TLS, we stop all plain-text I/O events but keep the - * NBBIO error flags. - */ - plaintext_buf = state->plaintext_buf; - if (NBBIO_ERROR_FLAGS(plaintext_buf)) { - if (NBBIO_ACTIVE_FLAGS(plaintext_buf)) - nbbio_disable_readwrite(state->plaintext_buf); - ssl_stat = SSL_shutdown(tls_context->con); - /* XXX Wait for return value 1 if sessions are to be reused? */ - if (ssl_stat < 0) { - handshake_err = SSL_get_error(tls_context->con, ssl_stat); - tlsp_eval_tls_error(state, handshake_err); - /* At this point, state could be a dangling pointer. */ - return; + /* + * Try to move data from the TLS engine to the plaintext output + * buffer. Note: data may arrive as a side effect of calling + * SSL_write(), therefore we call SSL_read() after calling + * SSL_write(). + * + * XXX We're supposed to repeat the exact same SSL_read() call arguments + * after an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE result. This + * supposedly means that our plaintext writer must not memmove() the + * plaintext output buffer until after the SSL_read() call succeeds. + * For now I'll ignore this, because 1) SSL_read() is documented to + * return the bytes available, instead of returning > 0 only after + * the entire buffer is processed like SSL_write() does; and 2) there + * is no "read" equivalent of the SSL_R_BAD_WRITE_RETRY, + * SSL_MODE_ENABLE_PARTIAL_WRITE or + * SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER features. + */ + ssl_read_err = SSL_ERROR_NONE; + while (NBBIO_WRITE_PEND(state->plaintext_buf) < NBBIO_BUFSIZE(plaintext_buf)) { + ssl_stat = SSL_read(tls_context->con, + NBBIO_WRITE_BUF(plaintext_buf) + + NBBIO_WRITE_PEND(state->plaintext_buf), + NBBIO_BUFSIZE(plaintext_buf) + - NBBIO_WRITE_PEND(state->plaintext_buf)); + ssl_read_err = SSL_get_error(tls_context->con, ssl_stat); + if (ssl_read_err != SSL_ERROR_NONE) + break; + NBBIO_WRITE_PEND(plaintext_buf) += ssl_stat; } - tlsp_state_free(state); - return; - } - /* - * Try to move data from the plaintext input buffer to the TLS engine. - * - * XXX We're supposed to repeat the exact same SSL_write() call arguments - * after an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE result. Rumor has - * it that this is because each SSL_write() call reads from the buffer - * incrementally, and returns > 0 only after the final byte is processed. - * Rumor also has it that setting SSL_MODE_ENABLE_PARTIAL_WRITE and - * SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER voids this requirement, and that - * repeating the request with an increased request size is OK. - * Unfortunately all this is not or poorly documented, and one has to - * rely on statements from OpenSSL developers in public mailing archives. - */ - ssl_write_err = SSL_ERROR_NONE; - while (NBBIO_READ_PEND(plaintext_buf) > 0) { - ssl_stat = SSL_write(tls_context->con, NBBIO_READ_BUF(plaintext_buf), - NBBIO_READ_PEND(plaintext_buf)); - ssl_write_err = SSL_get_error(tls_context->con, ssl_stat); - if (ssl_write_err != SSL_ERROR_NONE) - break; - /* Allow the plaintext pseudothread to read more data. */ - NBBIO_READ_PEND(plaintext_buf) -= ssl_stat; - if (NBBIO_READ_PEND(plaintext_buf) > 0) - memmove(NBBIO_READ_BUF(plaintext_buf), - NBBIO_READ_BUF(plaintext_buf) + ssl_stat, - NBBIO_READ_PEND(plaintext_buf)); + /* + * Try to enable/disable ciphertext read/write events. If SSL_write() + * was satisfied, see if SSL_read() wants to do some work. In case of + * an unrecoverable error, this automagically destroys the session + * state after cleaning up all pending read/write and timeout event + * requests. + */ + if (tlsp_eval_tls_error(state, ssl_write_err != SSL_ERROR_NONE ? + ssl_write_err : ssl_read_err) < 0) + /* At this point, state is a dangling pointer. */ + return; } /* - * Try to move data from the TLS engine to the plaintext output buffer. - * Note: data may arrive as a side effect of calling SSL_write(), - * therefore we call SSL_read() after calling SSL_write(). - * - * XXX We're supposed to repeat the exact same SSL_read() call arguments - * after an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE result. This - * supposedly means that our plaintext writer must not memmove() the - * plaintext output buffer until after the SSL_read() call succeeds. For - * now I'll ignore this, because 1) SSL_read() is documented to return - * the bytes available, instead of returning > 0 only after the entire - * buffer is processed like SSL_write() does; and 2) there is no "read" - * equivalent of the SSL_R_BAD_WRITE_RETRY, SSL_MODE_ENABLE_PARTIAL_WRITE - * or SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER features. + * Destroy state when the ciphertext I/O was permanently disabled and we + * can no longer trickle out plaintext. */ - ssl_read_err = SSL_ERROR_NONE; - while (NBBIO_WRITE_PEND(state->plaintext_buf) < NBBIO_BUFSIZE(plaintext_buf)) { - ssl_stat = SSL_read(tls_context->con, - NBBIO_WRITE_BUF(plaintext_buf) - + NBBIO_WRITE_PEND(state->plaintext_buf), - NBBIO_BUFSIZE(plaintext_buf) - - NBBIO_WRITE_PEND(state->plaintext_buf)); - ssl_read_err = SSL_get_error(tls_context->con, ssl_stat); - if (ssl_read_err != SSL_ERROR_NONE) - break; - NBBIO_WRITE_PEND(plaintext_buf) += ssl_stat; + else { + plaintext_buf = state->plaintext_buf; + if (!TLSP_CAN_TRICKLE_OUT_PLAINTEXT(plaintext_buf)) { + tlsp_state_free(state); + return; + } } /* - * Try to enable/disable ciphertext read/write events. If SSL_write() was - * satisfied, see if SSL_read() wants to do some work. In case of an - * unrecoverable error, this automagically destroys the session state - * after cleaning up all pending read/write and timeout event requests. - */ - if (tlsp_eval_tls_error(state, ssl_write_err != SSL_ERROR_NONE ? - ssl_write_err : ssl_read_err) < 0) - return; - - /* * Try to enable/disable plaintext read/write events. Basically, if we - * have nothing to write to the postscreen(8) server, see if there is + * have nothing to write to the plaintext stream, see if there is * something to read. If the write buffer is empty and the read buffer is * full, suspend plaintext I/O until conditions change (but keep the * timer active, as a safety mechanism in case ciphertext I/O gets * stuck). * - * XXX In theory, if the client keeps writing fast enough then we would - * never read from postscreen(8), and cause postscreen(8) to block. In - * practice, postscreen(8) limits the number of client commands, and thus - * postscreen(8)'s output will fit in a kernel buffer. This may not be - * true in other scenarios where the tlsproxy(8) server could be used. + * XXX In theory, if the ciphertext peer keeps writing fast enough then we + * would never read from the plaintext stream and cause the latter to + * block. In practice, postscreen(8) limits the number of client + * commands, and thus postscreen(8)'s output will fit in a kernel buffer. + * A remote SMTP server is not supposed to flood the local SMTP client + * with massive replies; it it does, then the local SMTP client should + * deal with it. */ if (NBBIO_WRITE_PEND(plaintext_buf) > 0) { if (NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_READ) nbbio_disable_readwrite(plaintext_buf); - if ((NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_WRITE) == 0) - nbbio_enable_write(plaintext_buf, state->timeout); + nbbio_enable_write(plaintext_buf, state->timeout); } else if (NBBIO_READ_PEND(plaintext_buf) < NBBIO_BUFSIZE(plaintext_buf)) { if (NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_WRITE) nbbio_disable_readwrite(plaintext_buf); - if ((NBBIO_ACTIVE_FLAGS(plaintext_buf) & NBBIO_FLAG_READ) == 0) - nbbio_enable_read(plaintext_buf, state->timeout); + nbbio_enable_read(plaintext_buf, state->timeout); } else { if (NBBIO_ACTIVE_FLAGS(plaintext_buf)) nbbio_slumber(plaintext_buf, state->timeout); @@ -632,6 +959,7 @@ static void tlsp_plaintext_event(int event, void *context) * want to read or write more plaintext. */ tlsp_strategy(state); + /* At this point, state could be a dangling pointer. */ } /* tlsp_ciphertext_event - ciphertext is ready to read/write */ @@ -647,6 +975,7 @@ static void tlsp_ciphertext_event(int event, void *context) */ if (event == EVENT_READ || event == EVENT_WRITE) { tlsp_strategy(state); + /* At this point, state could be a dangling pointer. */ } else { if (event == EVENT_TIME && state->ssl_last_err == SSL_ERROR_NONE) msg_warn("deadlock on plaintext stream for %s", @@ -659,9 +988,29 @@ static void tlsp_ciphertext_event(int event, void *context) } } -/* tlsp_start_tls - turn on TLS or force disconnect */ +/* tlsp_client_start_pre_handshake - turn on TLS or force disconnect */ + +static int tlsp_client_start_pre_handshake(TLSP_STATE *state) +{ + state->client_start_props->ctx = state->appl_state; + state->client_start_props->fd = state->ciphertext_fd; + /* These predicates and warning belong inside tls_client_start(). */ + if (!TLS_DANE_BASED(state->client_start_props->tls_level) + || tls_dane_avail()) + state->tls_context = tls_client_start(state->client_start_props); + else + msg_warn("%s: DANE requested, but not available", + state->client_start_props->namaddr); + if (state->tls_context != 0) + return (TLSP_STAT_OK); + + tlsp_state_free(state); + return (TLSP_STAT_ERR); +} + +/* tlsp_server_start_pre_handshake - turn on TLS or force disconnect */ -static void tlsp_start_tls(TLSP_STATE *state) +static int tlsp_server_start_pre_handshake(TLSP_STATE *state) { TLS_SERVER_START_PROPS props; static char *cipher_grade; @@ -674,8 +1023,8 @@ static void tlsp_start_tls(TLSP_STATE *state) */ /* - * Perform the before-handshake portion of the per-session initalization. - * Pass a null VSTREAM to indicate that this program, will do the + * Perform the before-handshake portion of per-session initialization. + * Pass a null VSTREAM to indicate that this program will do the * ciphertext I/O, not libtls. * * The cipher grade and exclusions don't change between sessions. Compute @@ -714,7 +1063,7 @@ static void tlsp_start_tls(TLSP_STATE *state) if (state->tls_context == 0) { tlsp_state_free(state); - return; + return (TLSP_STAT_ERR); } /* @@ -723,66 +1072,273 @@ static void tlsp_start_tls(TLSP_STATE *state) * whitelist status, but bad clients hammering the server can suck up * lots of CPU cycles. Per-client concurrency limits in postscreen(8) * will divert only naive security "researchers". - * - * XXX Do we care about certificate verification results? Not as long as - * postscreen(8) doesn't actually receive email. */ + return (TLSP_STAT_OK); } -/* tlsp_get_fd_event - receive final postscreen(8) hand-off information */ + /* + * From here on down is low-level code that sets up the plumbing before + * passing control to the TLS engine above. + */ + +/* tlsp_request_read_event - pre-handshake event boiler plate */ + +static void tlsp_request_read_event(int fd, EVENT_NOTIFY_FN handler, + int timeout, void *context) +{ + event_enable_read(fd, handler, context); + event_request_timer(handler, context, timeout); +} + +/* tlsp_accept_event - pre-handshake event boiler plate */ + +static void tlsp_accept_event(int event, EVENT_NOTIFY_FN handler, + void *context) +{ + if (event != EVENT_TIME) + event_cancel_timer(handler, context); + else + errno = ETIMEDOUT; + /* tlsp_state_free() disables pre-handshake plaintext I/O events. */ +} + +/* tlsp_get_fd_event - receive final connection hand-off information */ static void tlsp_get_fd_event(int event, void *context) { const char *myname = "tlsp_get_fd_event"; TLSP_STATE *state = (TLSP_STATE *) context; int plaintext_fd = vstream_fileno(state->plaintext_stream); + int status; /* * At this point we still manually manage plaintext read/write/timeout - * events. Disable I/O and timer events. Don't assume that the first - * plaintext request will be a read. + * events. Disable I/O events on the plaintext stream until the TLS + * handshake is completed. Every code path must either destroy state, or + * request the next event, otherwise we have a file and memory leak. */ + tlsp_accept_event(event, tlsp_get_fd_event, (void *) state); event_disable_readwrite(plaintext_fd); - if (event != EVENT_TIME) - event_cancel_timer(tlsp_get_fd_event, (void *) state); - else - errno = ETIMEDOUT; - /* - * Initialize plaintext-related session state. Once we have this behind - * us, the TLSP_STATE destructor will automagically clean up requests for - * read/write/timeout events, which makes error recovery easier. - * - * Register the plaintext event handler for timer cleanup in the TLSP_STATE - * destructor. Insert the NBBIO event-driven I/O layer between the - * postscreen(8) server and the TLS engine. - */ if (event != EVENT_READ || (state->ciphertext_fd = LOCAL_RECV_FD(plaintext_fd)) < 0) { - msg_warn("%s: receive SMTP client file descriptor: %m", myname); + msg_warn("%s: receive remote SMTP peer file descriptor: %m", myname); tlsp_state_free(state); return; } - non_blocking(state->ciphertext_fd, NON_BLOCKING); + + /* + * This is a bit early, to ensure that timer events for this file handle + * are guaranteed to be turned off by the TLSP_STATE destructor. + */ state->ciphertext_timer = tlsp_ciphertext_event; - state->plaintext_buf = nbbio_create(plaintext_fd, - VSTREAM_BUFSIZE, "postscreen", - tlsp_plaintext_event, - (void *) state); + non_blocking(state->ciphertext_fd, NON_BLOCKING); /* * Perform the TLS layer before-handshake initialization. We perform the - * remainder after the TLS handshake completes. + * remainder after the actual TLS handshake completes. */ - tlsp_start_tls(state); + if (state->is_server_role) + status = tlsp_server_start_pre_handshake(state); + else + status = tlsp_client_start_pre_handshake(state); + if (status != TLSP_STAT_OK) + /* At this point, state is a dangling pointer. */ + return; /* * Trigger the initial proxy server I/Os. */ tlsp_strategy(state); + /* At this point, state could be a dangling pointer. */ +} + +/* tlsp_config_diff - report server-client config differences */ + +static void tlsp_log_config_diff(const char *server_cfg, const char *client_cfg) +{ + VSTRING *diff_summary = vstring_alloc(100); + char *saved_server = mystrdup(server_cfg); + char *saved_client = mystrdup(client_cfg); + char *server_field; + char *client_field; + char *server_next; + char *client_next; + + /* + * Not using argv_split(), because it would treat multiple consecutive + * newline characters as one. + */ + for (server_field = saved_server, client_field = saved_client; + server_field && client_field; + server_field = server_next, client_field = client_next) { + server_next = split_at(server_field, '\n'); + client_next = split_at(client_field, '\n'); + if (strcmp(server_field, client_field) != 0) { + if (LEN(diff_summary) > 0) + vstring_sprintf_append(diff_summary, "; "); + vstring_sprintf_append(diff_summary, + "(server) '%s' != (client) '%s'", + server_field, client_field); + } + } + msg_warn("%s", STR(diff_summary)); + + vstring_free(diff_summary); + myfree(saved_client); + myfree(saved_server); +} + +/* tlsp_client_init - initialize a TLS client engine */ + +static TLS_APPL_STATE *tlsp_client_init(TLS_CLIENT_PARAMS *tls_params, + TLS_CLIENT_INIT_PROPS *init_props, + int dane_based) +{ + TLS_APPL_STATE *appl_state; + VSTRING *param_buf; + char *param_key; + VSTRING *init_buf; + char *init_key; + VSTRING *init_buf_for_hashing; + char *init_key_for_hashing; + int log_hints = 0; + + /* + * Use one TLS_APPL_STATE object for all requests that specify the same + * TLS_CLIENT_INIT_PROPS. Each TLS_APPL_STATE owns an SSL_CTX, which is + * expensive to create. Bug: TLS_CLIENT_PARAMS are not used when creating + * a TLS_APPL_STATE instance. + * + * First, compute the TLS_APPL_STATE cache lookup key. Save a copy of the + * pre-jail request TLS_CLIENT_PARAMS and TLSPROXY_CLIENT_INIT_PROPS + * settings, so that we can detect post-jail requests that do not match. + * + * Workaround: salt the hash-table key with DANE on/off info. This avoids + * cross-talk between DANE and non-DANE sessions. Postfix DANE support + * modifies SSL_CTX to override certificate verification because there is + * no other way to do this before OpenSSL 1.1.0. + */ + param_buf = vstring_alloc(100); + param_key = tls_proxy_client_param_with_names_to_string( + param_buf, tls_params); + init_buf = vstring_alloc(100); + init_key = tls_proxy_client_init_with_names_to_string( + init_buf, init_props); + init_buf_for_hashing = vstring_alloc(100); + init_key_for_hashing = STR(vstring_sprintf(init_buf_for_hashing, "%s%d\n", + init_key, dane_based)); + if (tlsp_pre_jail_done == 0) { + if (tlsp_pre_jail_client_param_key == 0 + || tlsp_pre_jail_client_init_key == 0) { + tlsp_pre_jail_client_param_key = mystrdup(param_key); + tlsp_pre_jail_client_init_key = mystrdup(init_key); + } else if (strcmp(tlsp_pre_jail_client_param_key, param_key) != 0 + || strcmp(tlsp_pre_jail_client_init_key, init_key) != 0) { + msg_panic("tlsp_client_init: too many pre-jail calls"); + } + } + + /* + * Log a warning if a post-jail request uses unexpected TLS_CLIENT_PARAMS + * settings. Bug: TLS_CLIENT_PARAMS settings are not used when creating a + * TLS_APPL_STATE instance; this makes a mismatch of TLS_CLIENT_PARAMS + * settings problematic. + */ + if (tlsp_pre_jail_done + && !been_here_fixed(tlsp_params_mismatch_filter, param_key) + && strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) { + msg_warn("request from tlsproxy client with unexpected settings"); + tlsp_log_config_diff(tlsp_pre_jail_client_param_key, param_key); + log_hints = 1; + } + + /* + * Look up the cached TLS_APPL_STATE for this tls_client_init request. + */ + if ((appl_state = (TLS_APPL_STATE *) + htable_find(tlsp_client_app_cache, init_key_for_hashing)) == 0) { + + /* + * Before creating a TLS_APPL_STATE instance, log a warning if a + * post-jail request differs from the saved pre-jail request AND the + * post-jail request specifies file/directory pathname arguments. + * Unexpected requests containing pathnames are problematic after + * chroot (pathname resolution) and after dropping privileges (key + * files must be root read-only). Unexpected requests are not a + * problem as long as they contain no pathnames (for example a + * tls_loglevel change). + * + * We could eliminate some of this complication by adding code that + * opens a cert/key lookup table at pre-jail time, and by reading + * cert/key info on-the-fly from that table. But then all requests + * would still have to specify the same table. + */ +#define NOT_EMPTY(x) ((x) && *(x)) + + if (tlsp_pre_jail_done + && strcmp(tlsp_pre_jail_client_init_key, init_key) != 0 + && (NOT_EMPTY(init_props->chain_files) + || NOT_EMPTY(init_props->cert_file) + || NOT_EMPTY(init_props->key_file) + || NOT_EMPTY(init_props->dcert_file) + || NOT_EMPTY(init_props->dkey_file) + || NOT_EMPTY(init_props->eccert_file) + || NOT_EMPTY(init_props->eckey_file) + || NOT_EMPTY(init_props->CAfile) + || NOT_EMPTY(init_props->CApath))) { + msg_warn("request from tlsproxy client with unexpected settings"); + tlsp_log_config_diff(tlsp_pre_jail_client_init_key, init_key); + log_hints = 1; + } + } + if (log_hints) + msg_warn("to avoid this warning, 1) identify the tlsproxy " + "client that is making this request, 2) configure " + "a custom tlsproxy service with settings that " + "match that tlsproxy client, and 3) configure " + "that tlsproxy client with a tlsproxy_service_name " + "setting that resolves to that custom tlsproxy " + "service"); + + /* + * TLS_APPL_STATE creation may fail when a post-jail request specifies + * unexpected cert/key information, but that is OK because we already + * logged a warning with configuration suggestions. + */ + if (appl_state == 0 + && (appl_state = tls_client_init(init_props)) != 0) { + (void) htable_enter(tlsp_client_app_cache, init_key_for_hashing, + (void *) appl_state); + + /* + * To maintain sanity, allow partial SSL_write() operations, and + * allow SSL_write() buffer pointers to change after a WANT_READ or + * WANT_WRITE result. This is based on OpenSSL developers talking on + * a mailing list, but is not supported by documentation. If this + * code stops working then no-one can be held responsible. + */ + SSL_CTX_set_mode(appl_state->ssl_ctx, + SSL_MODE_ENABLE_PARTIAL_WRITE + | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + } + vstring_free(init_buf_for_hashing); + vstring_free(init_buf); + vstring_free(param_buf); + return (appl_state); +} + +/* tlsp_close_event - pre-handshake plaintext-client close event */ + +static void tlsp_close_event(int event, void *context) +{ + TLSP_STATE *state = (TLSP_STATE *) context; + + tlsp_accept_event(event, tlsp_close_event, (void *) state); + tlsp_state_free(state); } -/* tlsp_get_request_event - receive initial postscreen(8) hand-off info */ +/* tlsp_get_request_event - receive initial hand-off info */ static void tlsp_get_request_event(int event, void *context) { @@ -793,8 +1349,17 @@ static void tlsp_get_request_event(int event, void *context) static VSTRING *remote_endpt; static VSTRING *server_id; int req_flags; - int timeout; - int ready; + int handshake_timeout; + int session_timeout; + int ready = 0; + + /* + * At this point we still manually manage plaintext read/write/timeout + * events. Every code path must either destroy state or request the next + * event, otherwise this pseudo-thread is idle until the client goes + * away. + */ + tlsp_accept_event(event, tlsp_get_request_event, (void *) state); /* * One-time initialization. @@ -805,68 +1370,92 @@ static void tlsp_get_request_event(int event, void *context) } /* - * At this point we still manually manage plaintext read/write/timeout - * events. Turn off timer events. Below we disable read events on error, - * and redefine read events on success. - */ - if (event != EVENT_TIME) - event_cancel_timer(tlsp_get_request_event, (void *) state); - else - errno = ETIMEDOUT; - - /* - * We must send some data, after receiving the request attributes and - * before receiving the remote file descriptor. We can't assume - * UNIX-domain socket semantics here. + * Receive the initial request attributes. Receive the remainder after we + * figure out what role we are expected to play. */ if (event != EVENT_READ || attr_scan(plaintext_stream, ATTR_FLAG_STRICT, - RECV_ATTR_STR(MAIL_ATTR_REMOTE_ENDPT, remote_endpt), - RECV_ATTR_INT(MAIL_ATTR_FLAGS, &req_flags), - RECV_ATTR_INT(MAIL_ATTR_TIMEOUT, &timeout), - RECV_ATTR_STR(MAIL_ATTR_SERVER_ID, server_id), - ATTR_TYPE_END) != 4) { + RECV_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, remote_endpt), + RECV_ATTR_INT(TLS_ATTR_FLAGS, &req_flags), + RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &handshake_timeout), + RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &session_timeout), + RECV_ATTR_STR(TLS_ATTR_SERVERID, server_id), + ATTR_TYPE_END) != 5) { msg_warn("%s: receive request attributes: %m", myname); - event_disable_readwrite(plaintext_fd); tlsp_state_free(state); return; } /* + * XXX We use the same fixed timeout throughout the entire session for + * both plaintext and ciphertext communication. This timeout is just a + * safety feature; the real timeout will be enforced by our plaintext + * peer (except during TLS the handshake, when we intentionally disable + * plaintext I/O). + */ + state->remote_endpt = mystrdup(STR(remote_endpt)); + state->server_id = mystrdup(STR(server_id)); + msg_info("CONNECT %s %s", + (req_flags & TLS_PROXY_FLAG_ROLE_SERVER) ? "from" : + (req_flags & TLS_PROXY_FLAG_ROLE_CLIENT) ? "to" : + "(bogus_direction)", state->remote_endpt); + state->req_flags = req_flags; + /* state->is_server_role is set below. */ + state->handshake_timeout = handshake_timeout; + state->session_timeout = session_timeout + 10; /* XXX */ + + /* + * Receive the TLS preferences now, to reduce the number of protocol + * roundtrips. + */ + switch (req_flags & (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_ROLE_SERVER)) { + case TLS_PROXY_FLAG_ROLE_CLIENT: + state->is_server_role = 0; + if (attr_scan(plaintext_stream, ATTR_FLAG_STRICT, + RECV_ATTR_FUNC(tls_proxy_client_param_scan, + (void *) &state->tls_params), + RECV_ATTR_FUNC(tls_proxy_client_init_scan, + (void *) &state->client_init_props), + RECV_ATTR_FUNC(tls_proxy_client_start_scan, + (void *) &state->client_start_props), + ATTR_TYPE_END) != 3) { + msg_warn("%s: receive client TLS settings: %m", myname); + tlsp_state_free(state); + return; + } + state->appl_state = tlsp_client_init(state->tls_params, + state->client_init_props, + TLS_DANE_BASED(state->client_start_props->tls_level)); + ready = state->appl_state != 0; + break; + case TLS_PROXY_FLAG_ROLE_SERVER: + state->is_server_role = 1; + ready = (tlsp_server_ctx != 0); + break; + default: + state->is_server_role = 0; + msg_warn("%s: bad request flags: 0x%x", myname, req_flags); + ready = 0; + } + + /* + * For portability we must send some data, after receiving the request + * attributes and before receiving the remote file descriptor. + * * If the requested TLS engine is unavailable, hang up after making sure * that the plaintext peer has received our "sorry" indication. */ - ready = ((req_flags & TLS_PROXY_FLAG_ROLE_SERVER) != 0 - && tlsp_server_ctx != 0); if (attr_print(plaintext_stream, ATTR_FLAG_NONE, SEND_ATTR_INT(MAIL_ATTR_STATUS, ready), ATTR_TYPE_END) != 0 || vstream_fflush(plaintext_stream) != 0 || ready == 0) { - read_wait(plaintext_fd, TLSP_INIT_TIMEOUT); /* XXX */ - event_disable_readwrite(plaintext_fd); - tlsp_state_free(state); + tlsp_request_read_event(plaintext_fd, tlsp_close_event, + TLSP_INIT_TIMEOUT, (void *) state); return; - } - - /* - * XXX We use the same fixed timeout throughout the entire session for - * both plaintext and ciphertext communication. This timeout is just a - * safety feature; the real timeout will be enforced by our plaintext - * peer. - */ - else { - state->remote_endpt = mystrdup(STR(remote_endpt)); - state->server_id = mystrdup(STR(server_id)); - msg_info("CONNECT %s %s", - (req_flags & TLS_PROXY_FLAG_ROLE_SERVER) ? "from" : - (req_flags & TLS_PROXY_FLAG_ROLE_CLIENT) ? "to" : - "(bogus_direction)", state->remote_endpt); - state->req_flags = req_flags; - state->timeout = timeout + 10; /* XXX */ - event_enable_read(plaintext_fd, tlsp_get_fd_event, (void *) state); - event_request_timer(tlsp_get_fd_event, (void *) state, - TLSP_INIT_TIMEOUT); + } else { + tlsp_request_read_event(plaintext_fd, tlsp_get_fd_event, + TLSP_INIT_TIMEOUT, (void *) state); return; } } @@ -902,9 +1491,8 @@ static void tlsp_service(VSTREAM *plaintext_stream, * Receive postscreen's remote SMTP client address/port and socket. */ state = tlsp_state_create(service, plaintext_stream); - event_enable_read(plaintext_fd, tlsp_get_request_event, (void *) state); - event_request_timer(tlsp_get_request_event, (void *) state, - TLSP_INIT_TIMEOUT); + tlsp_request_read_event(plaintext_fd, tlsp_get_request_event, + TLSP_INIT_TIMEOUT, (void *) state); } /* pre_jail_init - pre-jail initialization */ @@ -916,6 +1504,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv) int have_server_cert; int no_server_cert_ok; int require_server_cert; + int clnt_use_tls; /* * The code in this routine is pasted literally from smtpd(8). I am not @@ -972,13 +1561,27 @@ static void pre_jail_init(char *unused_name, char **unused_argv) have_server_cert = (*cert_file || *var_tlsp_tls_dcert_file || *var_tlsp_tls_eccert_file); + if (*var_tlsp_tls_chain_files != 0) { + if (!have_server_cert) + have_server_cert = 1; + else + msg_warn("Both %s and one or more of the legacy " + " %s, %s or %s are non-empty; the legacy " + " parameters will be ignored", + VAR_TLSP_TLS_CHAIN_FILES, + VAR_TLSP_TLS_CERT_FILE, + VAR_TLSP_TLS_ECCERT_FILE, + VAR_TLSP_TLS_DCERT_FILE); + } /* Some TLS configuration errors are not show stoppers. */ if (!have_server_cert && require_server_cert) msg_warn("Need a server cert to request client certs"); if (!var_tlsp_enforce_tls && var_tlsp_tls_req_ccert) msg_warn("Can't require client certs unless TLS is required"); /* After a show-stopper error, log a warning. */ - if (have_server_cert || (no_server_cert_ok && !require_server_cert)) + if (have_server_cert || (no_server_cert_ok && !require_server_cert)) { + + tls_pre_jail_init(TLS_ROLE_SERVER); /* * Large parameter lists are error-prone, so we emulate a language @@ -991,6 +1594,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv) verifydepth = var_tlsp_tls_ccert_vd, cache_type = TLS_MGR_SCACHE_SMTPD, set_sessid = var_tlsp_tls_set_sessid, + chain_files = var_tlsp_tls_chain_files, cert_file = cert_file, key_file = var_tlsp_tls_key_file, dcert_file = var_tlsp_tls_dcert_file, @@ -1009,8 +1613,9 @@ static void pre_jail_init(char *unused_name, char **unused_argv) var_tlsp_tls_proto, ask_ccert = ask_client_cert, mdalg = var_tlsp_tls_fpt_dgst); - else + } else { msg_warn("No server certs available. TLS can't be enabled"); + } /* * To maintain sanity, allow partial SSL_write() operations, and allow @@ -1023,13 +1628,129 @@ static void pre_jail_init(char *unused_name, char **unused_argv) SSL_CTX_set_mode(tlsp_server_ctx->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); -} -/* post_jail_init - post-jail initialization */ + /* + * The cache with TLS_APPL_STATE instances for different TLS_CLIENT_INIT + * configurations. + */ + tlsp_client_app_cache = htable_create(10); -static void post_jail_init(char *unused_name, char **unused_argv) -{ - /* void */ ; + /* + * Most sites don't use TLS client certs/keys. In that case, enabling + * tlsproxy-based connection caching is trivial. + * + * But some sites do use TLS client certs/keys, and that is challenging when + * tlsproxy runs in a post-jail environment: chroot breaks pathname + * resolution, and an unprivileged process should not be able to open + * files with secrets. The workaround: assume that most of those sites + * will use a fixed TLS client identity. In that case, tlsproxy can load + * the corresponding certs/keys at pre-jail time, so that secrets can + * remain read-only for root. As long as the tlsproxy pre-jail TLS client + * configuration with cert or key pathnames is the same as the one used + * in the Postfix SMTP client, sites can selectively or globally enable + * tlsproxy-based connection caching without additional TLS + * configuration. + * + * Loading one TLS client configuration at pre-jail time is not sufficient + * for the minority of sites that want to use TLS connection caching with + * multiple TLS client identities. To alert the operator, tlsproxy will + * log a warning when a TLS_CLIENT_INIT message specifies a different + * configuration than the tlsproxy pre-jail client configuration, and + * that different configuration specifies file/directory pathname + * arguments. The workaround is to have one tlsproxy process per TLS + * client identity. + * + * The general solution for single-identity or multi-identity clients is to + * stop loading certs and keys from individual files. Instead, have a + * cert/key map, indexed by client identity, read-only by root. After + * opening the map as root at pre-jail time, tlsproxy can read certs/keys + * on-the-fly as an unprivileged process at post-jail time. This is the + * approach that was already proposed for server-side SNI support, and it + * could be reused here. It would also end the proliferation of RSA + * cert/key parameters, DSA cert/key parameters, EC cert/key parameters, + * and so on. + * + * Horror: In order to create the same pre-jail TLS client context as the + * one used in the Postfix SMTP client, we have to duplicate intricate + * SMTP client code, including a handful configuration parameters that + * tlsproxy does not need. We must duplicate the logic, so that we only + * load certs and keys when the SMTP client would load them. + */ + if (*var_tlsp_clnt_level != 0) + switch (tls_level_lookup(var_tlsp_clnt_level)) { + case TLS_LEV_SECURE: + case TLS_LEV_VERIFY: + case TLS_LEV_DANE_ONLY: + case TLS_LEV_FPRINT: + case TLS_LEV_ENCRYPT: + var_tlsp_clnt_use_tls = var_tlsp_clnt_enforce_tls = 1; + break; + case TLS_LEV_DANE: + case TLS_LEV_MAY: + var_tlsp_clnt_use_tls = 1; + var_tlsp_clnt_enforce_tls = 0; + break; + case TLS_LEV_NONE: + var_tlsp_clnt_use_tls = var_tlsp_clnt_enforce_tls = 0; + break; + default: + /* tls_level_lookup() logs no warning. */ + /* session_tls_init() assumes that var_tlsp_clnt_level is sane. */ + msg_fatal("Invalid TLS level \"%s\"", var_tlsp_clnt_level); + } + clnt_use_tls = (var_tlsp_clnt_use_tls || var_tlsp_clnt_enforce_tls); + + /* + * Initialize the TLS data before entering the chroot jail. + */ + if (clnt_use_tls || var_tlsp_clnt_per_site[0] || var_tlsp_clnt_policy[0]) { + TLS_CLIENT_PARAMS tls_params; + TLS_CLIENT_INIT_PROPS init_props; + int dane_based_mode; + + tls_pre_jail_init(TLS_ROLE_CLIENT); + + /* + * We get stronger type safety and a cleaner interface by combining + * the various parameters into a single tls_client_props structure. + * + * Large parameter lists are error-prone, so we emulate a language + * feature that C does not have natively: named parameter lists. + */ + (void) tls_proxy_client_param_from_config(&tls_params); + (void) TLS_CLIENT_INIT_ARGS(&init_props, + log_param = var_tlsp_clnt_logparam, + log_level = var_tlsp_clnt_loglevel, + verifydepth = var_tlsp_clnt_scert_vd, + cache_type = TLS_MGR_SCACHE_SMTP, + chain_files = var_tlsp_clnt_chain_files, + cert_file = var_tlsp_clnt_cert_file, + key_file = var_tlsp_clnt_key_file, + dcert_file = var_tlsp_clnt_dcert_file, + dkey_file = var_tlsp_clnt_dkey_file, + eccert_file = var_tlsp_clnt_eccert_file, + eckey_file = var_tlsp_clnt_eckey_file, + CAfile = var_tlsp_clnt_CAfile, + CApath = var_tlsp_clnt_CApath, + mdalg = var_tlsp_clnt_fpt_dgst); + for (dane_based_mode = 0; dane_based_mode < 2; dane_based_mode++) { + if (tlsp_client_init(&tls_params, &init_props, + dane_based_mode) == 0) + msg_warn("TLS client initialization failed"); + } + } + + /* + * tlsp_client_init() needs to know if it is called pre-jail or + * post-jail. + */ + tlsp_pre_jail_done = 1; + + /* + * Bug: TLS_CLIENT_PARAMS attributes are not used when creating a + * TLS_APPL_STATE instance; we can only warn about attribute mismatches. + */ + tlsp_params_mismatch_filter = been_here_init(BH_BOUND_NONE, BH_FLAG_NONE); } MAIL_VERSION_STAMP_DECLARE; @@ -1038,24 +1759,38 @@ MAIL_VERSION_STAMP_DECLARE; int main(int argc, char **argv) { - static const CONFIG_INT_TABLE int_table[] = { + + /* + * Each table below initializes the named variables to their implicit + * default value, or to the explicit value in main.cf or master.cf. Here, + * "compat" means that a table initializes a variable "smtpd_blah" or + * "smtp_blah" that provides the implicit default value for variable + * "tlsproxy_blah" which is initialized by a different table. To make + * this work, the variables in a "compat" table must be initialized + * before the variables in the corresponding non-compat table. + */ + static const CONFIG_INT_TABLE compat_int_table[] = { VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0, + VAR_SMTP_TLS_SCERT_VD, DEF_SMTP_TLS_SCERT_VD, &var_smtp_tls_scert_vd, 0, 0, 0, }; static const CONFIG_NINT_TABLE nint_table[] = { VAR_TLSP_TLS_CCERT_VD, DEF_TLSP_TLS_CCERT_VD, &var_tlsp_tls_ccert_vd, 0, 0, + VAR_TLSP_CLNT_SCERT_VD, DEF_TLSP_CLNT_SCERT_VD, &var_tlsp_clnt_scert_vd, 0, 0, 0, }; static const CONFIG_TIME_TABLE time_table[] = { VAR_TLSP_WATCHDOG, DEF_TLSP_WATCHDOG, &var_tlsp_watchdog, 10, 0, 0, }; - static const CONFIG_BOOL_TABLE bool_table[] = { + static const CONFIG_BOOL_TABLE compat_bool_table[] = { VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls, 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_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, 0, }; static const CONFIG_NBOOL_TABLE nbool_table[] = { @@ -1064,9 +1799,12 @@ int main(int argc, char **argv) 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_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, 0, }; - static const CONFIG_STR_TABLE str_table[] = { + static const CONFIG_STR_TABLE compat_str_table[] = { + VAR_SMTPD_TLS_CHAIN_FILES, DEF_SMTPD_TLS_CHAIN_FILES, &var_smtpd_tls_chain_files, 0, 0, VAR_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CERT_FILE, &var_smtpd_tls_cert_file, 0, 0, VAR_SMTPD_TLS_KEY_FILE, DEF_SMTPD_TLS_KEY_FILE, &var_smtpd_tls_key_file, 0, 0, VAR_SMTPD_TLS_DCERT_FILE, DEF_SMTPD_TLS_DCERT_FILE, &var_smtpd_tls_dcert_file, 0, 0, @@ -1087,6 +1825,24 @@ int main(int argc, char **argv) VAR_SMTPD_TLS_FPT_DGST, DEF_SMTPD_TLS_FPT_DGST, &var_smtpd_tls_fpt_dgst, 1, 0, VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0, VAR_SMTPD_TLS_LEVEL, DEF_SMTPD_TLS_LEVEL, &var_smtpd_tls_level, 0, 0, + VAR_SMTP_TLS_CHAIN_FILES, DEF_SMTP_TLS_CHAIN_FILES, &var_smtp_tls_chain_files, 0, 0, + VAR_SMTP_TLS_CERT_FILE, DEF_SMTP_TLS_CERT_FILE, &var_smtp_tls_cert_file, 0, 0, + VAR_SMTP_TLS_KEY_FILE, DEF_SMTP_TLS_KEY_FILE, &var_smtp_tls_key_file, 0, 0, + VAR_SMTP_TLS_DCERT_FILE, DEF_SMTP_TLS_DCERT_FILE, &var_smtp_tls_dcert_file, 0, 0, + VAR_SMTP_TLS_DKEY_FILE, DEF_SMTP_TLS_DKEY_FILE, &var_smtp_tls_dkey_file, 0, 0, + VAR_SMTP_TLS_CA_FILE, DEF_SMTP_TLS_CA_FILE, &var_smtp_tls_CAfile, 0, 0, + VAR_SMTP_TLS_CA_PATH, DEF_SMTP_TLS_CA_PATH, &var_smtp_tls_CApath, 0, 0, + VAR_SMTP_TLS_FPT_DGST, DEF_SMTP_TLS_FPT_DGST, &var_smtp_tls_fpt_dgst, 1, 0, + VAR_SMTP_TLS_ECCERT_FILE, DEF_SMTP_TLS_ECCERT_FILE, &var_smtp_tls_eccert_file, 0, 0, + VAR_SMTP_TLS_ECKEY_FILE, DEF_SMTP_TLS_ECKEY_FILE, &var_smtp_tls_eckey_file, 0, 0, + VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0, + VAR_SMTP_TLS_PER_SITE, DEF_SMTP_TLS_PER_SITE, &var_smtp_tls_per_site, 0, 0, + VAR_SMTP_TLS_LEVEL, DEF_SMTP_TLS_LEVEL, &var_smtp_tls_level, 0, 0, + VAR_SMTP_TLS_POLICY, DEF_SMTP_TLS_POLICY, &var_smtp_tls_policy, 0, 0, + 0, + }; + static const CONFIG_STR_TABLE str_table[] = { + VAR_TLSP_TLS_CHAIN_FILES, DEF_TLSP_TLS_CHAIN_FILES, &var_tlsp_tls_chain_files, 0, 0, VAR_TLSP_TLS_CERT_FILE, DEF_TLSP_TLS_CERT_FILE, &var_tlsp_tls_cert_file, 0, 0, VAR_TLSP_TLS_KEY_FILE, DEF_TLSP_TLS_KEY_FILE, &var_tlsp_tls_key_file, 0, 0, VAR_TLSP_TLS_DCERT_FILE, DEF_TLSP_TLS_DCERT_FILE, &var_tlsp_tls_dcert_file, 0, 0, @@ -1107,6 +1863,21 @@ int main(int argc, char **argv) VAR_TLSP_TLS_FPT_DGST, DEF_TLSP_TLS_FPT_DGST, &var_tlsp_tls_fpt_dgst, 1, 0, VAR_TLSP_TLS_LOGLEVEL, DEF_TLSP_TLS_LOGLEVEL, &var_tlsp_tls_loglevel, 0, 0, VAR_TLSP_TLS_LEVEL, DEF_TLSP_TLS_LEVEL, &var_tlsp_tls_level, 0, 0, + VAR_TLSP_CLNT_LOGLEVEL, DEF_TLSP_CLNT_LOGLEVEL, &var_tlsp_clnt_loglevel, 0, 0, + VAR_TLSP_CLNT_LOGPARAM, DEF_TLSP_CLNT_LOGPARAM, &var_tlsp_clnt_logparam, 0, 0, + VAR_TLSP_CLNT_CHAIN_FILES, DEF_TLSP_CLNT_CHAIN_FILES, &var_tlsp_clnt_chain_files, 0, 0, + VAR_TLSP_CLNT_CERT_FILE, DEF_TLSP_CLNT_CERT_FILE, &var_tlsp_clnt_cert_file, 0, 0, + VAR_TLSP_CLNT_KEY_FILE, DEF_TLSP_CLNT_KEY_FILE, &var_tlsp_clnt_key_file, 0, 0, + VAR_TLSP_CLNT_DCERT_FILE, DEF_TLSP_CLNT_DCERT_FILE, &var_tlsp_clnt_dcert_file, 0, 0, + VAR_TLSP_CLNT_DKEY_FILE, DEF_TLSP_CLNT_DKEY_FILE, &var_tlsp_clnt_dkey_file, 0, 0, + VAR_TLSP_CLNT_ECCERT_FILE, DEF_TLSP_CLNT_ECCERT_FILE, &var_tlsp_clnt_eccert_file, 0, 0, + VAR_TLSP_CLNT_ECKEY_FILE, DEF_TLSP_CLNT_ECKEY_FILE, &var_tlsp_clnt_eckey_file, 0, 0, + VAR_TLSP_CLNT_CAFILE, DEF_TLSP_CLNT_CAFILE, &var_tlsp_clnt_CAfile, 0, 0, + VAR_TLSP_CLNT_CAPATH, DEF_TLSP_CLNT_CAPATH, &var_tlsp_clnt_CApath, 0, 0, + VAR_TLSP_CLNT_FPT_DGST, DEF_TLSP_CLNT_FPT_DGST, &var_tlsp_clnt_fpt_dgst, 1, 0, + VAR_TLSP_CLNT_LEVEL, DEF_TLSP_CLNT_LEVEL, &var_tlsp_clnt_level, 0, 0, + VAR_TLSP_CLNT_PER_SITE, DEF_TLSP_CLNT_PER_SITE, &var_tlsp_clnt_per_site, 0, 0, + VAR_TLSP_CLNT_POLICY, DEF_TLSP_CLNT_POLICY, &var_tlsp_clnt_policy, 0, 0, 0, }; @@ -1116,19 +1887,21 @@ int main(int argc, char **argv) MAIL_VERSION_STAMP_ALLOCATE; /* - * Pass control to the single-threaded service skeleton. + * Pass control to the event-driven service skeleton. */ event_server_main(argc, argv, tlsp_service, - CA_MAIL_SERVER_INT_TABLE(int_table), + CA_MAIL_SERVER_INT_TABLE(compat_int_table), CA_MAIL_SERVER_NINT_TABLE(nint_table), + CA_MAIL_SERVER_STR_TABLE(compat_str_table), CA_MAIL_SERVER_STR_TABLE(str_table), - CA_MAIL_SERVER_BOOL_TABLE(bool_table), + CA_MAIL_SERVER_BOOL_TABLE(compat_bool_table), CA_MAIL_SERVER_NBOOL_TABLE(nbool_table), CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_PRE_INIT(pre_jail_init), - CA_MAIL_SERVER_POST_INIT(post_jail_init), CA_MAIL_SERVER_SLOW_EXIT(tlsp_drain), + CA_MAIL_SERVER_RETIRE_ME, CA_MAIL_SERVER_WATCHDOG(&var_tlsp_watchdog), + CA_MAIL_SERVER_UNLIMITED, 0); } diff --git a/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.h b/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.h index b95434b81fd..2f9f8e1356f 100644 --- a/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.h +++ b/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy.h @@ -1,4 +1,4 @@ -/* $NetBSD: tlsproxy.h,v 1.1.1.3 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: tlsproxy.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy_state.c b/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy_state.c index 777bee703b5..593daca0359 100644 --- a/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy_state.c +++ b/external/ibm-public/postfix/dist/src/tlsproxy/tlsproxy_state.c @@ -1,4 +1,4 @@ -/* $NetBSD: tlsproxy_state.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: tlsproxy_state.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -20,7 +20,8 @@ /* /* tlsp_state_create() initializes session context. /* -/* tlsp_state_free() destroys session context. +/* tlsp_state_free() destroys session context. If the handshake +/* was in progress, it logs a 'handshake failed' message. /* /* Arguments: /* .IP service @@ -62,6 +63,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -87,6 +93,7 @@ #ifdef USE_TLS #define TLS_INTERNAL /* XXX */ #include <tls.h> +#include <tls_proxy.h> /* * Application-specific. @@ -110,6 +117,11 @@ TLSP_STATE *tlsp_state_create(const char *service, state->remote_endpt = 0; state->server_id = 0; state->tls_context = 0; + state->tls_params = 0; + state->server_init_props = 0; + state->server_start_props = 0; + state->client_init_props = 0; + state->client_start_props = 0; return (state); } @@ -118,9 +130,16 @@ TLSP_STATE *tlsp_state_create(const char *service, void tlsp_state_free(TLSP_STATE *state) { + /* Don't log failure after plaintext EOF. */ + if (state->remote_endpt && state->server_id + && (state->flags & TLSP_FLAG_DO_HANDSHAKE)) + msg_info("TLS handshake failed for service=%s peer=%s", + state->server_id, state->remote_endpt); myfree(state->service); if (state->plaintext_buf) /* turns off plaintext events */ nbbio_free(state->plaintext_buf); + else + event_disable_readwrite(vstream_fileno(state->plaintext_stream)); event_server_disconnect(state->plaintext_stream); if (state->ciphertext_fd >= 0) { event_disable_readwrite(state->ciphertext_fd); @@ -136,6 +155,16 @@ void tlsp_state_free(TLSP_STATE *state) myfree(state->server_id); if (state->tls_context) tls_free_context(state->tls_context); + if (state->tls_params) + tls_proxy_client_param_free(state->tls_params); + if (state->server_init_props) + tls_proxy_server_init_free(state->server_init_props); + if (state->server_start_props) + tls_proxy_server_start_free(state->server_start_props); + if (state->client_init_props) + tls_proxy_client_init_free(state->client_init_props); + if (state->client_start_props) + tls_proxy_client_start_free(state->client_start_props); myfree((void *) state); } diff --git a/external/ibm-public/postfix/dist/src/trivial-rewrite/resolve.c b/external/ibm-public/postfix/dist/src/trivial-rewrite/resolve.c index 323508ad8b0..2918da31ef4 100644 --- a/external/ibm-public/postfix/dist/src/trivial-rewrite/resolve.c +++ b/external/ibm-public/postfix/dist/src/trivial-rewrite/resolve.c @@ -1,4 +1,4 @@ -/* $NetBSD: resolve.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: resolve.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -34,7 +34,8 @@ /* nexthop, internalized recipient) triple. /* STANDARDS /* DIAGNOSTICS -/* Problems and transactions are logged to the syslog daemon. +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* SEE ALSO /* LICENSE diff --git a/external/ibm-public/postfix/dist/src/trivial-rewrite/rewrite.c b/external/ibm-public/postfix/dist/src/trivial-rewrite/rewrite.c index 07d8f898ce4..b9d96050d7b 100644 --- a/external/ibm-public/postfix/dist/src/trivial-rewrite/rewrite.c +++ b/external/ibm-public/postfix/dist/src/trivial-rewrite/rewrite.c @@ -1,4 +1,4 @@ -/* $NetBSD: rewrite.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: rewrite.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -45,7 +45,8 @@ /* completing incomplete address forms. /* STANDARDS /* DIAGNOSTICS -/* Problems and transactions are logged to the syslog daemon. +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* SEE ALSO /* LICENSE diff --git a/external/ibm-public/postfix/dist/src/trivial-rewrite/transport.c b/external/ibm-public/postfix/dist/src/trivial-rewrite/transport.c index fd69c2129bb..cafedd4928c 100644 --- a/external/ibm-public/postfix/dist/src/trivial-rewrite/transport.c +++ b/external/ibm-public/postfix/dist/src/trivial-rewrite/transport.c @@ -1,4 +1,4 @@ -/* $NetBSD: transport.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: transport.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -39,7 +39,7 @@ /* domain, and returns 1 if something was found. Otherwise, 0 /* is returned. /* DIAGNOSTICS -/* The global \fIdict_errno\fR is non-zero when the lookup +/* info->transport_path->error is non-zero when the lookup /* should be tried again. /* SEE ALSO /* maps(3), multi-dictionary search @@ -56,6 +56,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -77,7 +82,7 @@ #include <strip_addr.h> #include <mail_params.h> -#include <maps.h> +#include <mail_addr_find.h> #include <match_parent_style.h> #include <mail_proto.h> @@ -163,42 +168,28 @@ static void update_entry(const char *new_channel, const char *new_nexthop, } } -/* find_transport_entry - look up and parse transport table entry */ +/* parse_transport_entry - parse transport table entry */ -static int find_transport_entry(TRANSPORT_INFO *tp, const char *key, - const char *rcpt_domain, int flags, - VSTRING *channel, VSTRING *nexthop) +static void parse_transport_entry(const char *value, const char *rcpt_domain, + VSTRING *channel, VSTRING *nexthop) { char *saved_value; const char *host; - const char *value; #define FOUND 1 #define NOTFOUND 0 /* - * Look up an entry with extreme prejudice. - * - * XXX Should report lookup failure status to caller instead of aborting. - */ - if ((value = maps_find(tp->transport_path, key, flags)) == 0) - return (NOTFOUND); - - /* * It would be great if we could specify a recipient address in the * lookup result. Unfortunately, we cannot simply run the result through * a parser that recognizes "transport:user@domain" because the lookup * result can have arbitrary content (especially in the case of the error * mailer). */ - else { - saved_value = mystrdup(value); - host = split_at(saved_value, ':'); - update_entry(saved_value, host ? host : "", rcpt_domain, - channel, nexthop); - myfree(saved_value); - return (FOUND); - } + saved_value = mystrdup(value); + host = split_at(saved_value, ':'); + update_entry(saved_value, host ? host : "", rcpt_domain, channel, nexthop); + myfree(saved_value); } /* transport_wildcard_init - (re) initialize wild-card lookup result */ @@ -207,6 +198,7 @@ static void transport_wildcard_init(TRANSPORT_INFO *tp) { VSTRING *channel = vstring_alloc(10); VSTRING *nexthop = vstring_alloc(10); + const char *value; /* * Both channel and nexthop may be zero-length strings. Therefore we must @@ -232,7 +224,8 @@ static void transport_wildcard_init(TRANSPORT_INFO *tp) #define FULL 0 #define PARTIAL DICT_FLAG_FIXED - if (find_transport_entry(tp, WILDCARD, "", FULL, channel, nexthop)) { + if ((value = maps_find(tp->transport_path, WILDCARD, FULL)) != 0) { + parse_transport_entry(value, "", channel, nexthop); tp->wildcard_errno = 0; tp->wildcard_channel = channel; tp->wildcard_nexthop = nexthop; @@ -255,11 +248,8 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, const char *rcpt_domain, VSTRING *channel, VSTRING *nexthop) { - char *stripped_addr; char *ratsign = 0; - const char *name; - const char *next; - int found; + const char *value; #define STREQ(x,y) (strcmp((x), (y)) == 0) #define DISCARD_EXTENSION ((char **) 0) @@ -273,62 +263,27 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, } /* - * Look up the full address with the FULL flag to include regexp maps in - * the query. + * Look up the full and extension-stripped address, then match the domain + * and subdomains. Try the external form before the backwards-compatible + * internal form. */ +#define LOOKUP_STRATEGY \ + (MA_FIND_FULL | MA_FIND_NOEXT | MA_FIND_DOMAIN | \ + (transport_match_parent_style == MATCH_FLAG_PARENT ? \ + MA_FIND_PDMS : MA_FIND_PDDMDS)) + if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0) msg_panic("transport_lookup: bad address: \"%s\"", addr); - if (find_transport_entry(tp, addr, rcpt_domain, FULL, channel, nexthop)) + if ((value = mail_addr_find_strategy(tp->transport_path, addr, (char **) 0, + LOOKUP_STRATEGY)) != 0) { + parse_transport_entry(value, rcpt_domain, channel, nexthop); return (FOUND); + } if (tp->transport_path->error != 0) return (NOTFOUND); /* - * If the full address did not match, and there is an address extension, - * look up the stripped address with the PARTIAL flag to avoid matching - * partial lookup keys with regular expressions. - */ - if ((stripped_addr = strip_addr(addr, DISCARD_EXTENSION, - var_rcpt_delim)) != 0) { - found = find_transport_entry(tp, stripped_addr, rcpt_domain, PARTIAL, - channel, nexthop); - - myfree(stripped_addr); - if (found) - return (FOUND); - if (tp->transport_path->error != 0) - return (NOTFOUND); - } - - /* - * If the full and stripped address lookup fails, try domain name lookup. - * - * Keep stripping domain components until nothing is left or until a - * matching entry is found. - * - * After checking the full domain name, check for .upper.domain, to - * distinguish between the parent domain and it's decendants, a la - * sendmail and tcp wrappers. - * - * Before changing the DB lookup result, make a copy first, in order to - * avoid DB cache corruption. - * - * Specify that the lookup key is partial, to avoid matching partial keys - * with regular expressions. - */ - for (name = ratsign + 1; *name != 0; name = next) { - if (find_transport_entry(tp, name, rcpt_domain, PARTIAL, channel, nexthop)) - return (FOUND); - if (tp->transport_path->error != 0) - return (NOTFOUND); - if ((next = strchr(name + 1, '.')) == 0) - break; - if (transport_match_parent_style == MATCH_FLAG_PARENT) - next++; - } - - /* * Fall back to the wild-card entry. */ if (tp->wildcard_errno || event_time() > tp->expire) @@ -347,3 +302,139 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, */ return (NOTFOUND); } + +#ifdef TEST + + /* + * Proof-of-concept test program. Read an address from stdin, and spit out + * the lookup result. + */ + +#include <string.h> + +#include <mail_conf.h> +#include <vstream.h> +#include <vstring_vstream.h> + +static NORETURN usage(const char *progname) +{ + msg_fatal("usage: %s [-v] database", progname); +} + +int main(int argc, char **argv) +{ + VSTRING *buffer = vstring_alloc(100); + VSTRING *channel = vstring_alloc(100); + VSTRING *nexthop = vstring_alloc(100); + TRANSPORT_INFO *tp; + char *bp; + char *addr_field; + char *rcpt_domain; + char *expect_channel; + char *expect_nexthop; + int status; + int ch; + int errs = 0; + + /* + * Parse JCL. + */ + while ((ch = GETOPT(argc, argv, "v")) > 0) { + switch (ch) { + case 'v': + msg_verbose++; + break; + default: + usage(argv[0]); + } + } + if (argc != optind + 1) + usage(argv[0]); + + /* + * Initialize. + */ +#define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0) + + mail_conf_read(); /* XXX eliminate dependency. */ + UPDATE(var_rcpt_delim, "+"); + UPDATE(var_mydomain, "localdomain"); + UPDATE(var_myorigin, "localhost.localdomain"); + UPDATE(var_mydest, "localhost.localdomain"); + + tp = transport_pre_init("transport map", argv[optind]); + transport_post_init(tp); + + while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { + bp = STR(buffer); + + /* + * Parse the input and expectations. XXX We can't expect empty + * fields, so require '-' instead. + */ + if ((addr_field = mystrtok(&bp, ":")) == 0) + msg_fatal("no address field"); + if ((rcpt_domain = strrchr(addr_field, '@')) == 0) + msg_fatal("no recipient domain"); + rcpt_domain += 1; + expect_channel = mystrtok(&bp, ":"); + expect_nexthop = mystrtok(&bp, ":"); + if ((expect_channel != 0) != (expect_nexthop != 0)) + msg_fatal("specify both channel and nexthop, or specify neither"); + if (expect_channel) { + if (strcmp(expect_channel, "-") == 0) + *expect_channel = 0; + if (strcmp(expect_nexthop, "-") == 0) + *expect_nexthop = 0; + vstring_strcpy(channel, "DEFAULT"); + vstring_strcpy(nexthop, rcpt_domain); + } + if (mystrtok(&bp, ":") != 0) + msg_fatal("garbage after nexthop field"); + + /* + * Lookups. + */ + status = transport_lookup(tp, addr_field, rcpt_domain, + channel, nexthop); + + /* + * Enforce expectations. + */ + if (expect_nexthop && status) { + vstream_printf("%s:%s -> %s:%s \n", + addr_field, rcpt_domain, + STR(channel), STR(nexthop)); + vstream_fflush(VSTREAM_OUT); + if (strcmp(expect_channel, STR(channel)) != 0) { + msg_warn("expect channel '%s' but got '%s'", + expect_channel, STR(channel)); + errs = 1; + } + if (strcmp(expect_nexthop, STR(nexthop)) != 0) { + msg_warn("expect nexthop '%s' but got '%s'", + expect_nexthop, STR(nexthop)); + errs = 1; + } + } else if (expect_nexthop && !status) { + vstream_printf("%s:%s -> %s\n", addr_field, rcpt_domain, + tp->transport_path->error ? + "(try again)" : "(not found)"); + vstream_fflush(VSTREAM_OUT); + msg_warn("expect channel '%s' but got none", expect_channel); + msg_warn("expect nexthop '%s' but got none", expect_nexthop); + errs = 1; + } else if (!status) { + vstream_printf("%s:%s -> %s\n", addr_field, rcpt_domain, + tp->transport_path->error ? + "(try again)" : "(not found)"); + } + } + transport_free(tp); + vstring_free(nexthop); + vstring_free(channel); + vstring_free(buffer); + exit(errs != 0); +} + +#endif diff --git a/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.c b/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.c index 9ff0abbd3d4..572698d4094 100644 --- a/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.c +++ b/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.c @@ -1,4 +1,4 @@ -/* $NetBSD: trivial-rewrite.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: trivial-rewrite.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -69,7 +69,8 @@ /* By default, this daemon does not talk to remote or local users. /* It can run at a fixed low privilege in a chrooted environment. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -250,18 +251,23 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 2.0 and later: /* .IP "\fBhelpful_warnings (yes)\fR" /* Log warnings about problematic configuration settings, and provide /* helpful suggestions. +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* postconf(5), configuration parameters /* transport(5), transport table format /* relocated(5), format of the "user has moved" table /* master(8), process manager +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README FILES /* .ad diff --git a/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.h b/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.h index 523457e9ae8..59beeb9b768 100644 --- a/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.h +++ b/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.h @@ -1,4 +1,4 @@ -/* $NetBSD: trivial-rewrite.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: trivial-rewrite.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -25,7 +25,7 @@ /* * Connection management. */ -int server_flags; +extern int server_flags; /* * rewrite.c @@ -86,4 +86,9 @@ extern int resolve_class(const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ diff --git a/external/ibm-public/postfix/dist/src/util/allascii.c b/external/ibm-public/postfix/dist/src/util/allascii.c index 9d690e6b722..3bf77b0e3aa 100644 --- a/external/ibm-public/postfix/dist/src/util/allascii.c +++ b/external/ibm-public/postfix/dist/src/util/allascii.c @@ -1,4 +1,4 @@ -/* $NetBSD: allascii.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: allascii.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -31,6 +31,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/util/argv_attr.h b/external/ibm-public/postfix/dist/src/util/argv_attr.h index 071c6ba59b9..e3e7df60367 100644 --- a/external/ibm-public/postfix/dist/src/util/argv_attr.h +++ b/external/ibm-public/postfix/dist/src/util/argv_attr.h @@ -1,4 +1,4 @@ -/* $NetBSD: argv_attr.h,v 1.1.1.1 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: argv_attr.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _ARGV_ATTR_H_INCLUDED_ #define _ARGV_ATTR_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/argv_attr_print.c b/external/ibm-public/postfix/dist/src/util/argv_attr_print.c index f9a25bec9eb..f0e533a1647 100644 --- a/external/ibm-public/postfix/dist/src/util/argv_attr_print.c +++ b/external/ibm-public/postfix/dist/src/util/argv_attr_print.c @@ -1,4 +1,4 @@ -/* $NetBSD: argv_attr_print.c,v 1.1.1.1 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: argv_attr_print.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/argv_attr_scan.c b/external/ibm-public/postfix/dist/src/util/argv_attr_scan.c index c6170a425a8..59d9b571d77 100644 --- a/external/ibm-public/postfix/dist/src/util/argv_attr_scan.c +++ b/external/ibm-public/postfix/dist/src/util/argv_attr_scan.c @@ -1,4 +1,4 @@ -/* $NetBSD: argv_attr_scan.c,v 1.1.1.1 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: argv_attr_scan.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/attr.h b/external/ibm-public/postfix/dist/src/util/attr.h index 6f275d0bc72..f23c1fc69e2 100644 --- a/external/ibm-public/postfix/dist/src/util/attr.h +++ b/external/ibm-public/postfix/dist/src/util/attr.h @@ -1,4 +1,4 @@ -/* $NetBSD: attr.h,v 1.2 2017/02/14 01:16:48 christos Exp $ */ +/* $NetBSD: attr.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _ATTR_H_INCLUDED_ #define _ATTR_H_INCLUDED_ @@ -173,6 +173,11 @@ extern int WARN_UNUSED_RESULT attr_vscan_plain(VSTREAM *, int, va_list); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/auto_clnt.c b/external/ibm-public/postfix/dist/src/util/auto_clnt.c index 976b022ce28..107a54e0f15 100644 --- a/external/ibm-public/postfix/dist/src/util/auto_clnt.c +++ b/external/ibm-public/postfix/dist/src/util/auto_clnt.c @@ -1,4 +1,4 @@ -/* $NetBSD: auto_clnt.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: auto_clnt.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -155,7 +155,7 @@ static void auto_clnt_ttl_event(int event, void *context) * with the call-back routine, but there is too much code that would have * to be changed. * - * XXX Should we be concerned that an overly agressive optimizer will + * XXX Should we be concerned that an overly aggressive optimizer will * eliminate this function and replace calls to auto_clnt_ttl_event() by * direct calls to auto_clnt_event()? It should not, because there exists * code that takes the address of both functions. diff --git a/external/ibm-public/postfix/dist/src/util/base32_code.h b/external/ibm-public/postfix/dist/src/util/base32_code.h index 154b2dfda94..d29782a09b1 100644 --- a/external/ibm-public/postfix/dist/src/util/base32_code.h +++ b/external/ibm-public/postfix/dist/src/util/base32_code.h @@ -1,4 +1,4 @@ -/* $NetBSD: base32_code.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: base32_code.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _BASE32_CODE_H_INCLUDED_ #define _BASE32_CODE_H_INCLUDED_ @@ -33,6 +33,11 @@ extern VSTRING *WARN_UNUSED_RESULT base32_decode(VSTRING *, const char *, ssize_ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/base64_code.h b/external/ibm-public/postfix/dist/src/util/base64_code.h index 556842f2dbb..195cf198e54 100644 --- a/external/ibm-public/postfix/dist/src/util/base64_code.h +++ b/external/ibm-public/postfix/dist/src/util/base64_code.h @@ -1,4 +1,4 @@ -/* $NetBSD: base64_code.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: base64_code.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _BASE64_CODE_H_INCLUDED_ #define _BASE64_CODE_H_INCLUDED_ @@ -41,6 +41,11 @@ extern VSTRING *WARN_UNUSED_RESULT base64_decode_opt(VSTRING *, const char *, ss /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/byte_mask.c b/external/ibm-public/postfix/dist/src/util/byte_mask.c index 087f9fd000f..afe25b7ce16 100644 --- a/external/ibm-public/postfix/dist/src/util/byte_mask.c +++ b/external/ibm-public/postfix/dist/src/util/byte_mask.c @@ -1,4 +1,4 @@ -/* $NetBSD: byte_mask.c,v 1.1.1.1 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: byte_mask.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/byte_mask.h b/external/ibm-public/postfix/dist/src/util/byte_mask.h index 75aa02a6105..c3f2f73e0a4 100644 --- a/external/ibm-public/postfix/dist/src/util/byte_mask.h +++ b/external/ibm-public/postfix/dist/src/util/byte_mask.h @@ -1,4 +1,4 @@ -/* $NetBSD: byte_mask.h,v 1.1.1.1 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: byte_mask.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _BYTE_MASK_H_INCLUDED_ #define _BYTE_MASK_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/casefold.c b/external/ibm-public/postfix/dist/src/util/casefold.c index ccfd49cd660..df4508a6f79 100644 --- a/external/ibm-public/postfix/dist/src/util/casefold.c +++ b/external/ibm-public/postfix/dist/src/util/casefold.c @@ -1,4 +1,4 @@ -/* $NetBSD: casefold.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: casefold.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -85,6 +85,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -189,7 +194,7 @@ char *casefoldx(int flags, VSTRING *dest, const char *src, ssize_t len) * with space_needed below) does not include storage for the null * terminator. The terminator is written only when the output buffer is * large enough. This is why we overallocate space when the output does - * not fit. But if the output fits exactly, then the ouput will be + * not fit. But if the output fits exactly, then the output will be * unterminated, and we have to terminate the output ourselves. */ for (n = 0; n < 3; n++) { @@ -197,7 +202,7 @@ char *casefoldx(int flags, VSTRING *dest, const char *src, ssize_t len) space_needed = ucasemap_utf8FoldCase(csm, STR(dest) + old_len, vstring_avail(dest), src, len, &error); if (U_SUCCESS(error)) { - VSTRING_AT_OFFSET(dest, old_len + space_needed); + vstring_set_payload_size(dest, old_len + space_needed); if (vstring_avail(dest) == 0) /* exact fit, no terminator */ VSTRING_TERMINATE(dest); /* add terminator */ break; diff --git a/external/ibm-public/postfix/dist/src/util/cidr_match.c b/external/ibm-public/postfix/dist/src/util/cidr_match.c index 2100ef9e55b..90df3385a58 100644 --- a/external/ibm-public/postfix/dist/src/util/cidr_match.c +++ b/external/ibm-public/postfix/dist/src/util/cidr_match.c @@ -1,4 +1,4 @@ -/* $NetBSD: cidr_match.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: cidr_match.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -8,7 +8,7 @@ /* SYNOPSIS /* #include <cidr_match.h> /* -/* VSTRING *cidr_match_parse(info, pattern, why) +/* VSTRING *cidr_match_parse(info, pattern, match, why) /* CIDR_MATCH *info; /* char *pattern; /* VSTRING *why; @@ -16,6 +16,14 @@ /* int cidr_match_execute(info, address) /* CIDR_MATCH *info; /* const char *address; +/* AUXILIARY FUNCTIONS +/* VSTRING *cidr_match_parse_if(info, pattern, match, why) +/* CIDR_MATCH *info; +/* char *pattern; +/* VSTRING *why; +/* +/* void cidr_match_endif(info) +/* CIDR_MATCH *info; /* DESCRIPTION /* This module parses address or address/length patterns and /* provides simple address matching. The implementation is @@ -26,11 +34,21 @@ /* /* cidr_match_parse() parses an address or address/mask /* expression and stores the result into the info argument. +/* A non-zero (or zero) match argument requests a positive (or +/* negative) match. The symbolic constants CIDR_MATCH_TRUE and +/* CIDR_MATCH_FALSE may help to improve code readability. /* The result is non-zero in case of problems: either the /* value of the why argument, or a newly allocated VSTRING /* (the caller should give the latter to vstring_free()). /* The pattern argument is destroyed. /* +/* cidr_match_parse_if() parses the address that follows an IF +/* token, and stores the result into the info argument. +/* The arguments are the same as for cidr_match_parse(). +/* +/* cidr_match_endif() handles the occurrence of an ENDIF token, +/* and updates the info argument. +/* /* cidr_match_execute() matches the specified address against /* a list of parsed expressions, and returns the matching /* expression's data structure. @@ -41,6 +59,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -90,15 +113,44 @@ (msg_panic("%s: bad address family %d", myname, (f)), 0)) #endif +/* cidr_match_entry - match one entry */ + +static inline int cidr_match_entry(CIDR_MATCH *entry, + unsigned char *addr_bytes) +{ + unsigned char *mp; + unsigned char *np; + unsigned char *ap; + + /* Unoptimized case: netmask with some or all bits zero. */ + if (entry->mask_shift < entry->addr_bit_count) { + for (np = entry->net_bytes, mp = entry->mask_bytes, + ap = addr_bytes; /* void */ ; np++, mp++, ap++) { + if (ap >= addr_bytes + entry->addr_byte_count) + return (entry->match); + if ((*ap & *mp) != *np) + break; + } + } + /* Optimized case: all 1 netmask (i.e. no netmask specified). */ + else { + for (np = entry->net_bytes, + ap = addr_bytes; /* void */ ; np++, ap++) { + if (ap >= addr_bytes + entry->addr_byte_count) + return (entry->match); + if (*ap != *np) + break; + } + } + return (!entry->match); +} + /* cidr_match_execute - match address against compiled CIDR pattern list */ CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr) { unsigned char addr_bytes[CIDR_MATCH_ABYTES]; unsigned addr_family; - unsigned char *mp; - unsigned char *np; - unsigned char *ap; CIDR_MATCH *entry; addr_family = CIDR_MATCH_ADDR_FAMILY(addr); @@ -106,27 +158,26 @@ CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr) return (0); for (entry = list; entry; entry = entry->next) { - if (entry->addr_family == addr_family) { - /* Unoptimized case: netmask with some or all bits zero. */ - if (entry->mask_shift < entry->addr_bit_count) { - for (np = entry->net_bytes, mp = entry->mask_bytes, - ap = addr_bytes; /* void */ ; np++, mp++, ap++) { - if (ap >= addr_bytes + entry->addr_byte_count) - return (entry); - if ((*ap & *mp) != *np) - break; - } - } - /* Optimized case: all 1 netmask (i.e. no netmask specified). */ - else { - for (np = entry->net_bytes, - ap = addr_bytes; /* void */ ; np++, ap++) { - if (ap >= addr_bytes + entry->addr_byte_count) - return (entry); - if (*ap != *np) - break; - } - } + + switch (entry->op) { + + case CIDR_MATCH_OP_MATCH: + if (entry->addr_family == addr_family) + if (cidr_match_entry(entry, addr_bytes)) + return (entry); + break; + + case CIDR_MATCH_OP_IF: + if (entry->addr_family == addr_family) + if (cidr_match_entry(entry, addr_bytes)) + continue; + /* An IF without matching ENDIF has no end-of block entry. */ + if ((entry = entry->block_end) == 0) + return (0); + /* FALLTHROUGH */ + + case CIDR_MATCH_OP_ENDIF: + continue; } } return (0); @@ -134,7 +185,8 @@ CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr) /* cidr_match_parse - parse CIDR pattern */ -VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, VSTRING *why) +VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, int match, + VSTRING *why) { const char *myname = "cidr_match_parse"; char *mask_search; @@ -226,7 +278,32 @@ VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, VSTRING *why) /* * Wrap up the result. */ + ip->op = CIDR_MATCH_OP_MATCH; + ip->match = match; ip->next = 0; + ip->block_end = 0; return (0); } + +/* cidr_match_parse_if - parse CIDR pattern after IF */ + +VSTRING *cidr_match_parse_if(CIDR_MATCH *ip, char *pattern, int match, + VSTRING *why) +{ + VSTRING *ret; + + if ((ret = cidr_match_parse(ip, pattern, match, why)) == 0) + ip->op = CIDR_MATCH_OP_IF; + return (ret); +} + +/* cidr_match_endif - handle ENDIF pattern */ + +void cidr_match_endif(CIDR_MATCH *ip) +{ + memset(ip, 0, sizeof(*ip)); + ip->op = CIDR_MATCH_OP_ENDIF; + ip->next = 0; /* maybe not all bits 0 */ + ip->block_end = 0; +} diff --git a/external/ibm-public/postfix/dist/src/util/cidr_match.h b/external/ibm-public/postfix/dist/src/util/cidr_match.h index 7d575de9115..deaf89676ba 100644 --- a/external/ibm-public/postfix/dist/src/util/cidr_match.h +++ b/external/ibm-public/postfix/dist/src/util/cidr_match.h @@ -1,4 +1,4 @@ -/* $NetBSD: cidr_match.h,v 1.1.1.2 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: cidr_match.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _CIDR_MATCH_H_INCLUDED_ #define _CIDR_MATCH_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/clean_env.c b/external/ibm-public/postfix/dist/src/util/clean_env.c index de74f3cf06b..1a5e2fbc2d7 100644 --- a/external/ibm-public/postfix/dist/src/util/clean_env.c +++ b/external/ibm-public/postfix/dist/src/util/clean_env.c @@ -1,4 +1,4 @@ -/* $NetBSD: clean_env.c,v 1.1.1.2 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: clean_env.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/clean_env.h b/external/ibm-public/postfix/dist/src/util/clean_env.h index 515c3b7e73e..6cbc820805a 100644 --- a/external/ibm-public/postfix/dist/src/util/clean_env.h +++ b/external/ibm-public/postfix/dist/src/util/clean_env.h @@ -1,4 +1,4 @@ -/* $NetBSD: clean_env.h,v 1.1.1.2 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: clean_env.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _CLEAN_ENV_H_INCLUDED_ #define _CLEAN_ENV_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/connect.h b/external/ibm-public/postfix/dist/src/util/connect.h index 21f8ad87ccd..5b910c33282 100644 --- a/external/ibm-public/postfix/dist/src/util/connect.h +++ b/external/ibm-public/postfix/dist/src/util/connect.h @@ -1,4 +1,4 @@ -/* $NetBSD: connect.h,v 1.1.1.4 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: connect.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _CONNECT_H_INCLUDED_ #define _CONNECT_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/dict.c b/external/ibm-public/postfix/dist/src/util/dict.c index df09623cca4..c84a07443f0 100644 --- a/external/ibm-public/postfix/dist/src/util/dict.c +++ b/external/ibm-public/postfix/dist/src/util/dict.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -641,6 +641,7 @@ static const NAME_MASK dict_mask[] = { "multi_writer", DICT_FLAG_MULTI_WRITER, /* multi-writer safe */ "utf8_request", DICT_FLAG_UTF8_REQUEST, /* request UTF-8 activation */ "utf8_active", DICT_FLAG_UTF8_ACTIVE, /* UTF-8 is activated */ + "src_rhs_is_file", DICT_FLAG_SRC_RHS_IS_FILE, /* value from file */ 0, }; diff --git a/external/ibm-public/postfix/dist/src/util/dict.h b/external/ibm-public/postfix/dist/src/util/dict.h index 12b9be73511..f0c24c344aa 100644 --- a/external/ibm-public/postfix/dist/src/util/dict.h +++ b/external/ibm-public/postfix/dist/src/util/dict.h @@ -1,4 +1,4 @@ -/* $NetBSD: dict.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _DICT_H_INCLUDED_ #define _DICT_H_INCLUDED_ @@ -96,6 +96,8 @@ typedef struct DICT { int error; /* last operation only */ DICT_JMP_BUF *jbuf; /* exception handling */ struct DICT_UTF8_BACKUP *utf8_backup; /* see below */ + struct VSTRING *file_buf; /* dict_file_to_buf() */ + struct VSTRING *file_b64; /* dict_file_to_b64() */ } DICT; extern DICT *dict_alloc(const char *, const char *, ssize_t); @@ -131,6 +133,8 @@ extern DICT *dict_debug(DICT *); #define DICT_FLAG_MULTI_WRITER (1<<18) /* multi-writer safe map */ #define DICT_FLAG_UTF8_REQUEST (1<<19) /* activate UTF-8 if possible */ #define DICT_FLAG_UTF8_ACTIVE (1<<20) /* UTF-8 proxy layer is present */ +#define DICT_FLAG_SRC_RHS_IS_FILE \ + (1<<21) /* Map source RHS is a file */ #define DICT_FLAG_UTF8_MASK (DICT_FLAG_UTF8_REQUEST) @@ -155,7 +159,7 @@ extern DICT *dict_debug(DICT *); * changes to its copy of some of these flags). The proxymap server opens * only one map instance for all client requests with the same values of * these flags, and the proxymap client uses its own saved copy of these - * flags. + * flags. DICT_FLAG_SRC_RHS_IS_FILE is an example of such a flag. */ #define DICT_FLAG_PARANOID \ (DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH) @@ -255,7 +259,7 @@ typedef struct DICT_UTF8_BACKUP { const char *(*lookup) (struct DICT *, const char *); int (*update) (struct DICT *, const char *, const char *); int (*delete) (struct DICT *, const char *); -} DICT_UTF8_BACKUP; +} DICT_UTF8_BACKUP; extern DICT *dict_utf8_activate(DICT *); @@ -302,6 +306,16 @@ extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, in */ extern void dict_jmp_alloc(DICT *); + /* + * dict_file(3). + */ +extern struct VSTRING *dict_file_to_buf(DICT *, const char *); +extern struct VSTRING *dict_file_to_b64(DICT *, const char *); +extern struct VSTRING *dict_file_from_b64(DICT *, const char *); +extern char *dict_file_get_error(DICT *); +extern void dict_file_purge_buffers(DICT *); +extern const char *dict_file_lookup(DICT *dict, const char *); + /* LICENSE /* .ad /* .fi @@ -311,6 +325,11 @@ extern void dict_jmp_alloc(DICT *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/dict_alloc.c b/external/ibm-public/postfix/dist/src/util/dict_alloc.c index 405d9f6b394..1e3b25c9f09 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_alloc.c +++ b/external/ibm-public/postfix/dist/src/util/dict_alloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_alloc.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_alloc.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -66,6 +66,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System libraries. */ @@ -157,6 +162,8 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size) dict->error = DICT_ERR_NONE; dict->jbuf = 0; dict->utf8_backup = 0; + dict->file_buf = 0; + dict->file_b64 = 0; return dict; } @@ -170,6 +177,10 @@ void dict_free(DICT *dict) myfree((void *) dict->jbuf); if (dict->utf8_backup) myfree((void *) dict->utf8_backup); + if (dict->file_buf) + vstring_free(dict->file_buf); + if (dict->file_b64) + vstring_free(dict->file_b64); myfree((void *) dict); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_cidr.c b/external/ibm-public/postfix/dist/src/util/dict_cidr.c index 7d3fcbe3d79..138aabec995 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_cidr.c +++ b/external/ibm-public/postfix/dist/src/util/dict_cidr.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_cidr.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_cidr.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -29,6 +29,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -56,6 +61,7 @@ #include <cidr_match.h> #include <dict_cidr.h> #include <warn_stat.h> +#include <mvect.h> /* Application-specific. */ @@ -65,6 +71,7 @@ typedef struct DICT_CIDR_ENTRY { CIDR_MATCH cidr_info; /* must be first */ char *value; /* lookup result */ + int lineno; } DICT_CIDR_ENTRY; typedef struct { @@ -108,42 +115,119 @@ static void dict_cidr_close(DICT *dict) /* dict_cidr_parse_rule - parse CIDR table rule into network, mask and value */ -static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why) +static DICT_CIDR_ENTRY *dict_cidr_parse_rule(DICT *dict, char *p, int lineno, + int nesting, VSTRING *why) { DICT_CIDR_ENTRY *rule; char *pattern; char *value; CIDR_MATCH cidr_info; MAI_HOSTADDR_STR hostaddr; + int match = 1; /* - * Split the rule into key and value. We already eliminated leading - * whitespace, comments, empty lines or lines with whitespace only. This - * means a null key can't happen but we will handle this anyway. + * IF must be followed by a pattern. */ - pattern = p; - while (*p && !ISSPACE(*p)) /* Skip over key */ - p++; - if (*p) /* Terminate key */ - *p++ = 0; - while (*p && ISSPACE(*p)) /* Skip whitespace */ - p++; - value = p; - trimblanks(value, 0)[0] = 0; /* Trim trailing blanks */ - if (*pattern == 0) { - vstring_sprintf(why, "no address pattern"); - return (0); + if (strncasecmp(p, "IF", 2) == 0 && !ISALNUM(p[2])) { + p += 2; + for (;;) { + if (*p == '!') + match = !match; + else if (!ISSPACE(*p)) + break; + p++; + } + if (*p == 0) { + vstring_sprintf(why, "no address pattern"); + return (0); + } + trimblanks(p, 0)[0] = 0; /* Trim trailing blanks */ + if (cidr_match_parse_if(&cidr_info, p, match, why) != 0) + return (0); + value = ""; } - if (*value == 0) { - vstring_sprintf(why, "no lookup result"); - return (0); + + /* + * ENDIF must not be followed by other text. + */ + else if (strncasecmp(p, "ENDIF", 5) == 0 && !ISALNUM(p[5])) { + p += 5; + while (*p && ISSPACE(*p)) /* Skip whitespace */ + p++; + if (*p != 0) { + vstring_sprintf(why, "garbage after ENDIF"); + return (0); + } + if (nesting == 0) { + vstring_sprintf(why, "ENDIF without IF"); + return (0); + } + cidr_match_endif(&cidr_info); + value = ""; } /* - * Parse the pattern, destroying it in the process. + * An address pattern. */ - if (cidr_match_parse(&cidr_info, pattern, why) != 0) - return (0); + else { + + /* + * Process negation operators. + */ + for (;;) { + if (*p == '!') + match = !match; + else if (!ISSPACE(*p)) + break; + p++; + } + + /* + * Split the rule into key and value. We already eliminated leading + * whitespace, comments, empty lines or lines with whitespace only. + * This means a null key can't happen but we will handle this anyway. + */ + pattern = p; + while (*p && !ISSPACE(*p)) /* Skip over key */ + p++; + if (*p) /* Terminate key */ + *p++ = 0; + while (*p && ISSPACE(*p)) /* Skip whitespace */ + p++; + value = p; + trimblanks(value, 0)[0] = 0; /* Trim trailing blanks */ + if (*pattern == 0) { + vstring_sprintf(why, "no address pattern"); + return (0); + } + + /* + * Parse the pattern, destroying it in the process. + */ + if (cidr_match_parse(&cidr_info, pattern, match, why) != 0) + return (0); + + if (*value == 0) { + vstring_sprintf(why, "no lookup result"); + return (0); + } + } + + /* + * Optionally replace the value file the contents of a file. + */ + if (dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) { + VSTRING *base64_buf; + char *err; + + if ((base64_buf = dict_file_to_b64(dict, value)) == 0) { + err = dict_file_get_error(dict); + vstring_strcpy(why, err); + myfree(err); + return (0); + } + value = vstring_str(base64_buf); + } /* * Bundle up the result. @@ -151,6 +235,7 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why) rule = (DICT_CIDR_ENTRY *) mymalloc(sizeof(DICT_CIDR_ENTRY)); rule->cidr_info = cidr_info; rule->value = mystrdup(value); + rule->lineno = lineno; if (msg_verbose) { if (inet_ntop(cidr_info.addr_family, cidr_info.net_bytes, @@ -166,6 +251,7 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why) DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) { + const char myname[] = "dict_cidr_open"; DICT_CIDR *dict_cidr; VSTREAM *map_fp = 0; struct stat st; @@ -175,6 +261,9 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) DICT_CIDR_ENTRY *last_rule = 0; int last_line = 0; int lineno; + int nesting = 0; + DICT_CIDR_ENTRY **rule_stack = 0; + MVECT mvect; /* * Let the optimizer worry about eliminating redundant code. @@ -227,12 +316,36 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) dict_cidr->dict.owner.status = (st.st_uid != 0); while (readllines(line_buffer, map_fp, &last_line, &lineno)) { - rule = dict_cidr_parse_rule(vstring_str(line_buffer), why); + rule = dict_cidr_parse_rule(&dict_cidr->dict, + vstring_str(line_buffer), lineno, + nesting, why); if (rule == 0) { msg_warn("cidr map %s, line %d: %s: skipping this rule", mapname, lineno, vstring_str(why)); continue; } + if (rule->cidr_info.op == CIDR_MATCH_OP_IF) { + if (rule_stack == 0) + rule_stack = (DICT_CIDR_ENTRY **) mvect_alloc(&mvect, + sizeof(*rule_stack), nesting + 1, + (MVECT_FN) 0, (MVECT_FN) 0); + else + rule_stack = + (DICT_CIDR_ENTRY **) mvect_realloc(&mvect, nesting + 1); + rule_stack[nesting] = rule; + nesting++; + } else if (rule->cidr_info.op == CIDR_MATCH_OP_ENDIF) { + DICT_CIDR_ENTRY *if_rule; + + if (nesting-- <= 0) + /* Already handled in dict_cidr_parse_rule(). */ + msg_panic("%s: ENDIF without IF", myname); + if_rule = rule_stack[nesting]; + if (if_rule->cidr_info.op != CIDR_MATCH_OP_IF) + msg_panic("%s: unexpected rule stack element type %d", + myname, if_rule->cidr_info.op); + if_rule->cidr_info.block_end = &(rule->cidr_info); + } if (last_rule == 0) dict_cidr->head = rule; else @@ -240,5 +353,13 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) last_rule = rule; } + while (nesting-- > 0) + msg_warn("cidr map %s, line %d: IF has no matching ENDIF", + mapname, rule_stack[nesting]->lineno); + + if (rule_stack) + (void) mvect_free(&mvect); + + dict_file_purge_buffers(&dict_cidr->dict); DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict)); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_db.c b/external/ibm-public/postfix/dist/src/util/dict_db.c index 04b10385f07..5b365367005 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_db.c +++ b/external/ibm-public/postfix/dist/src/util/dict_db.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_db.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_db.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -55,6 +55,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #include "sys_defs.h" @@ -124,6 +129,9 @@ typedef struct { DICT dict; /* generic members */ DB *db; /* open db file */ +#if DB_VERSION_MAJOR > 2 + DB_ENV *dbenv; +#endif #if DB_VERSION_MAJOR > 1 DBC *cursor; /* dict_db_sequence() */ #endif @@ -555,6 +563,9 @@ static void dict_db_close(DICT *dict) if (DICT_DB_CLOSE(dict_db->db) < 0) msg_info("close database %s: %m (possible Berkeley DB bug)", dict_db->dict.name); +#if DB_VERSION_MAJOR > 2 + dict_db->dbenv->close(dict_db->dbenv, 0); +#endif if (dict_db->key_buf) vstring_free(dict_db->key_buf); if (dict_db->val_buf) @@ -564,6 +575,44 @@ static void dict_db_close(DICT *dict) dict_free(dict); } +#if DB_VERSION_MAJOR > 2 + +/* dict_db_new_env - workaround for undocumented ./DB_CONFIG read */ + +static DB_ENV *dict_db_new_env(const char *db_path) +{ + VSTRING *db_home_buf; + DB_ENV *dbenv; + u_int32_t cache_size_gbytes; + u_int32_t cache_size_bytes; + int ncache; + + if ((errno = db_env_create(&dbenv, 0)) != 0) + msg_fatal("create DB environment: %m"); +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 7) + if ((errno = dbenv->get_cachesize(dbenv, &cache_size_gbytes, + &cache_size_bytes, &ncache)) != 0) + msg_fatal("get DB cache size: %m"); + if (cache_size_gbytes == 0 && cache_size_bytes < dict_db_cache_size) { + if ((errno = dbenv->set_cache_max(dbenv, cache_size_gbytes, + dict_db_cache_size)) != 0) + msg_fatal("set DB max cache size %d: %m", dict_db_cache_size); + if ((errno = dbenv->set_cachesize(dbenv, cache_size_gbytes, + dict_db_cache_size, ncache)) != 0) + msg_fatal("set DB cache size %d: %m", dict_db_cache_size); + } +#endif + /* XXX db_home is also the default directory for the .db file. */ + db_home_buf = vstring_alloc(100); + if ((errno = dbenv->open(dbenv, sane_dirname(db_home_buf, db_path), + DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0)) != 0) + msg_fatal("open DB environment: %m"); + vstring_free(db_home_buf); + return (dbenv); +} + +#endif + /* dict_db_open - open data base */ static DICT *dict_db_open(const char *class, const char *path, int open_flags, @@ -573,6 +622,7 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags, struct stat st; DB *db = 0; char *db_path = 0; + VSTRING *db_base_buf = 0; int lock_fd = -1; int dbfd; @@ -580,6 +630,10 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags, int db_flags; #endif +#if DB_VERSION_MAJOR > 2 + DB_ENV *dbenv = 0; + +#endif /* * Mismatches between #include file and library are a common cause for @@ -622,11 +676,22 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags, * db_open() create a non-existent file for us. */ #define LOCK_OPEN_FLAGS(f) ((f) & ~(O_CREAT|O_TRUNC)) +#if DB_VERSION_MAJOR <= 2 +#define FREE_RETURN(e) do { \ + DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \ + if (lock_fd >= 0) (void) close(lock_fd); \ + if (db_base_buf) vstring_free(db_base_buf); \ + if (db_path) myfree(db_path); return (_dict); \ + } while (0) +#else #define FREE_RETURN(e) do { \ DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \ + if (dbenv) dbenv->close(dbenv, 0); \ if (lock_fd >= 0) (void) close(lock_fd); \ + if (db_base_buf) vstring_free(db_base_buf); \ if (db_path) myfree(db_path); return (_dict); \ } while (0) +#endif if (dict_flags & DICT_FLAG_LOCK) { if ((lock_fd = open(db_path, LOCK_OPEN_FLAGS(open_flags), 0644)) < 0) { @@ -683,26 +748,28 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags, db_flags |= DB_CREATE; if (open_flags & O_TRUNC) db_flags |= DB_TRUNCATE; - if ((errno = db_create(&db, 0, 0)) != 0) + if ((errno = db_create(&db, dbenv = dict_db_new_env(db_path), 0)) != 0) msg_fatal("create DB database: %m"); if (db == 0) msg_panic("db_create null result"); - if ((errno = db->set_cachesize(db, 0, dict_db_cache_size, 0)) != 0) - msg_fatal("set DB cache size %d: %m", dict_db_cache_size); if (type == DB_HASH && db->set_h_nelem(db, DICT_DB_NELM) != 0) msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM); + db_base_buf = vstring_alloc(100); #if DB_VERSION_MAJOR == 6 || DB_VERSION_MAJOR == 5 || \ (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) - if ((errno = db->open(db, 0, db_path, 0, type, db_flags, 0644)) != 0) + if ((errno = db->open(db, 0, sane_basename(db_base_buf, db_path), + 0, type, db_flags, 0644)) != 0) FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags, "open database %s: %m", db_path)); #elif (DB_VERSION_MAJOR == 3 || DB_VERSION_MAJOR == 4) - if ((errno = db->open(db, db_path, 0, type, db_flags, 0644)) != 0) + if ((errno = db->open(db, sane_basename(db_base_buf, db_path), 0, + type, db_flags, 0644)) != 0) FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags, "open database %s: %m", db_path)); #else #error "Unsupported Berkeley DB version" #endif + vstring_free(db_base_buf); if ((errno = db->fd(db, &dbfd)) != 0) msg_fatal("get database file descriptor: %m"); #endif @@ -745,6 +812,9 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags, if (dict_flags & DICT_FLAG_FOLD_FIX) dict_db->dict.fold_buf = vstring_alloc(10); dict_db->db = db; +#if DB_VERSION_MAJOR > 2 + dict_db->dbenv = dbenv; +#endif #if DB_VERSION_MAJOR > 1 dict_db->cursor = 0; #endif diff --git a/external/ibm-public/postfix/dist/src/util/dict_db.h b/external/ibm-public/postfix/dist/src/util/dict_db.h index 10971031a3b..e89dc23a17c 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_db.h +++ b/external/ibm-public/postfix/dist/src/util/dict_db.h @@ -1,4 +1,4 @@ -/* $NetBSD: dict_db.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_db.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _DICT_DB_H_INCLUDED_ #define _DICT_DB_H_INCLUDED_ @@ -47,6 +47,11 @@ extern int dict_db_cache_size; /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/dict_file.c b/external/ibm-public/postfix/dist/src/util/dict_file.c index 57adf29d9c9..f8879ca72bf 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_file.c +++ b/external/ibm-public/postfix/dist/src/util/dict_file.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_file.c,v 1.1.1.1 2020/03/18 18:59:37 christos Exp $ */ +/* $NetBSD: dict_file.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/dict_inline.c b/external/ibm-public/postfix/dist/src/util/dict_inline.c index f5a9df5f480..2d5dc36f935 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_inline.c +++ b/external/ibm-public/postfix/dist/src/util/dict_inline.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_inline.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_inline.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -28,6 +28,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -55,7 +60,7 @@ DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) size_t len; char *nameval, *vname, *value; const char *err = 0; - char *xperr = 0; + char *free_me = 0; int count = 0; /* @@ -65,8 +70,8 @@ DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) DICT *__d = (x); \ if (saved_name != 0) \ myfree(saved_name); \ - if (xperr != 0) \ - myfree(xperr); \ + if (free_me != 0) \ + myfree(free_me); \ return (__d); \ } while (0) @@ -111,10 +116,19 @@ DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) dict_type_override(dict, DICT_TYPE_INLINE); while ((nameval = mystrtokq(&cp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { if ((nameval[0] != CHARS_BRACE[0] - || (err = xperr = extpar(&nameval, CHARS_BRACE, EXTPAR_FLAG_STRIP)) == 0) - && (err = split_nameval(nameval, &vname, &value)) != 0) + || (err = free_me = extpar(&nameval, CHARS_BRACE, EXTPAR_FLAG_STRIP)) == 0) + && (err = split_qnameval(nameval, &vname, &value)) != 0) break; + if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) != 0) { + VSTRING *base64_buf; + + if ((base64_buf = dict_file_to_b64(dict, value)) == 0) { + err = free_me = dict_file_get_error(dict); + break; + } + value = vstring_str(base64_buf); + } /* No duplicate checks. See comments in dict_thash.c. */ dict->update(dict, vname, value); count += 1; @@ -124,12 +138,15 @@ DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, open_flags, dict_flags, "%s: \"%s:%s\"; " - "need \"%s:{name=value...}\"", + "need \"%s:{name=%s...}\"", err != 0 ? err : "empty table", DICT_TYPE_INLINE, name, - DICT_TYPE_INLINE)); + DICT_TYPE_INLINE, + (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) ? + "filename" : "value")); } dict->owner.status = DICT_OWNER_TRUSTED; + dict_file_purge_buffers(dict); DICT_INLINE_RETURN(DICT_DEBUG (dict)); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_lmdb.c b/external/ibm-public/postfix/dist/src/util/dict_lmdb.c index 45cb3a4b1d7..3fbc1b21d0b 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_lmdb.c +++ b/external/ibm-public/postfix/dist/src/util/dict_lmdb.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_lmdb.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_lmdb.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -50,6 +50,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #include <sys_defs.h> @@ -111,10 +116,6 @@ typedef struct { * We do not expose these details to the Postfix user interface. The purpose of * Postfix is to solve problems, not punt them to the user. */ -#ifndef SSIZE_T_MAX /* The maximum map size */ -#define SSIZE_T_MAX __MAXINT__(ssize_t) /* XXX Assumes two's complement */ -#endif - #define DICT_LMDB_SIZE_INCR 2 /* Increase size by 1 bit on retry */ #define DICT_LMDB_SIZE_MAX SSIZE_T_MAX diff --git a/external/ibm-public/postfix/dist/src/util/dict_open.c b/external/ibm-public/postfix/dist/src/util/dict_open.c index 0bed7be313e..c5b1135b12b 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_open.c +++ b/external/ibm-public/postfix/dist/src/util/dict_open.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_open.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_open.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -164,6 +164,26 @@ /* request with a non-UTF-8 key, skip an update request with /* a non-UTF-8 value, and fail a lookup request with a non-UTF-8 /* value. +/* .IP DICT_FLAG_SRC_RHS_IS_FILE +/* With dictionaries that are created from source text, each +/* value in the source of a dictionary specifies a list of +/* file names separated by comma and/or whitespace. The file +/* contents are concatenated with a newline inserted between +/* files, and the base64-encoded result is stored under the +/* key. +/* .sp +/* NOTE 1: it is up to the application to decode lookup results +/* with dict_file_lookup() or equivalent (this requires that +/* the dictionary is opened with DICT_FLAG_SRC_RHS_IS_FILE). +/* Decoding is not built into the normal dictionary lookup +/* method, because that would complicate dictionary nesting, +/* pipelining, and proxying. +/* .sp +/* NOTE 2: it is up to the application to convert file names +/* into base64-encoded file content before calling the dictionary +/* update method (see dict_file(3) for support). Automatic +/* file content encoding is available only when a dictionary +/* is created from source text. /* .PP /* Specify DICT_FLAG_NONE for no special processing. /* @@ -284,6 +304,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/util/dict_pcre.c b/external/ibm-public/postfix/dist/src/util/dict_pcre.c index 0f7b3599ca7..f51a4bd2519 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_pcre.c +++ b/external/ibm-public/postfix/dist/src/util/dict_pcre.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_pcre.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_pcre.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -29,6 +29,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #include "sys_defs.h" @@ -62,6 +67,7 @@ #include "mac_parse.h" #include "pcre.h" #include "warn_stat.h" +#include "mvect.h" /* * Backwards compatibility. @@ -103,7 +109,6 @@ typedef struct { */ typedef struct DICT_PCRE_RULE { int op; /* DICT_PCRE_OP_MATCH/IF/ENDIF */ - int nesting; /* level of IF/ENDIF nesting */ int lineno; /* source file line number */ struct DICT_PCRE_RULE *next; /* next rule in dict */ } DICT_PCRE_RULE; @@ -122,6 +127,7 @@ typedef struct { pcre *pattern; /* compiled pattern */ pcre_extra *hints; /* hints to speed pattern execution */ int match; /* positive or negative match */ + struct DICT_PCRE_RULE *endif_rule; /* matching endif rule */ } DICT_PCRE_IF_RULE; /* @@ -258,12 +264,23 @@ static void dict_pcre_exec_error(const char *mapname, int lineno, int errval) return; #endif default: - msg_warn("pcre map %s, line %d: unknown re_exec error: %d", + msg_warn("pcre map %s, line %d: unknown pcre_exec error: %d", mapname, lineno, errval); return; } } + /* + * Inlined to reduce function call overhead in the time-critical loop. + */ +#define DICT_PCRE_EXEC(ctxt, map, line, pattern, hints, match, str, len) \ + ((ctxt).matches = pcre_exec((pattern), (hints), (str), (len), \ + NULL_STARTOFFSET, NULL_EXEC_OPTIONS, \ + (ctxt).offsets, PCRE_MAX_CAPTURE * 3), \ + (ctxt).matches > 0 ? (match) : \ + (ctxt).matches == PCRE_ERROR_NOMATCH ? !(match) : \ + (dict_pcre_exec_error((map), (line), (ctxt).matches), 0)) + /* dict_pcre_lookup - match string and perform optional substitution */ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) @@ -274,7 +291,6 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) DICT_PCRE_MATCH_RULE *match_rule; int lookup_len = strlen(lookup_string); DICT_PCRE_EXPAND_CONTEXT ctxt; - int nesting = 0; dict->error = 0; @@ -292,12 +308,6 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) } for (rule = dict_pcre->head; rule; rule = rule->next) { - /* - * Skip rules inside failed IF/ENDIF. - */ - if (nesting < rule->nesting) - continue; - switch (rule->op) { /* @@ -305,22 +315,10 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) */ case DICT_PCRE_OP_MATCH: match_rule = (DICT_PCRE_MATCH_RULE *) rule; - ctxt.matches = pcre_exec(match_rule->pattern, match_rule->hints, - lookup_string, lookup_len, - NULL_STARTOFFSET, NULL_EXEC_OPTIONS, - ctxt.offsets, PCRE_MAX_CAPTURE * 3); - - if (ctxt.matches > 0) { - if (!match_rule->match) - continue; /* Negative rule matched */ - } else if (ctxt.matches == PCRE_ERROR_NOMATCH) { - if (match_rule->match) - continue; /* Positive rule did not - * match */ - } else { - dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches); - continue; /* pcre_exec failed */ - } + if (!DICT_PCRE_EXEC(ctxt, dict->name, rule->lineno, + match_rule->pattern, match_rule->hints, + match_rule->match, lookup_string, lookup_len)) + continue; /* * Skip $number substitutions when the replacement text contains @@ -356,30 +354,19 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) */ case DICT_PCRE_OP_IF: if_rule = (DICT_PCRE_IF_RULE *) rule; - ctxt.matches = pcre_exec(if_rule->pattern, if_rule->hints, - lookup_string, lookup_len, - NULL_STARTOFFSET, NULL_EXEC_OPTIONS, - ctxt.offsets, PCRE_MAX_CAPTURE * 3); - - if (ctxt.matches > 0) { - if (!if_rule->match) - continue; /* Negative rule matched */ - } else if (ctxt.matches == PCRE_ERROR_NOMATCH) { - if (if_rule->match) - continue; /* Positive rule did not - * match */ - } else { - dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches); - continue; /* pcre_exec failed */ - } - nesting++; - continue; + if (DICT_PCRE_EXEC(ctxt, dict->name, rule->lineno, + if_rule->pattern, if_rule->hints, + if_rule->match, lookup_string, lookup_len)) + continue; + /* An IF without matching ENDIF has no "endif" rule. */ + if ((rule = if_rule->endif_rule) == 0) + return (0); + /* FALLTHROUGH */ /* - * ENDIF after successful IF. + * ENDIF after IF. */ case DICT_PCRE_OP_ENDIF: - nesting--; continue; default: @@ -444,16 +431,13 @@ static int dict_pcre_get_pattern(const char *mapname, int lineno, char **bufp, * Process negation operators. */ pattern->match = 1; - while (*p == '!') { - pattern->match = !pattern->match; + for (;;) { + if (*p == '!') + pattern->match = !pattern->match; + else if (!ISSPACE(*p)) + break; p++; } - - /* - * Grr...aceful handling of whitespace after '!'. - */ - while (*p && ISSPACE(*p)) - p++; if (*p == 0) { msg_warn("pcre map %s, line %d: no regexp: skipping this rule", mapname, lineno); @@ -590,15 +574,12 @@ static int dict_pcre_compile(const char *mapname, int lineno, /* dict_pcre_rule_alloc - fill in a generic rule structure */ -static DICT_PCRE_RULE *dict_pcre_rule_alloc(int op, int nesting, - int lineno, - size_t size) +static DICT_PCRE_RULE *dict_pcre_rule_alloc(int op, int lineno, size_t size) { DICT_PCRE_RULE *rule; rule = (DICT_PCRE_RULE *) mymalloc(size); rule->op = op; - rule->nesting = nesting; rule->lineno = lineno; rule->next = 0; @@ -607,9 +588,9 @@ static DICT_PCRE_RULE *dict_pcre_rule_alloc(int op, int nesting, /* dict_pcre_parse_rule - parse and compile one rule */ -static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, - char *line, int nesting, - int dict_flags) +static DICT_PCRE_RULE *dict_pcre_parse_rule(DICT *dict, const char *mapname, + int lineno, char *line, + int nesting) { char *p; int actual_sub; @@ -637,8 +618,8 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, while (*p && ISSPACE(*p)) ++p; if (!*p) - msg_warn("%s, line %d: no replacement text: using empty string", - mapname, lineno); + msg_warn("pcre map %s, line %d: no replacement text: " + "using empty string", mapname, lineno); /* * Sanity check the $number instances in the replacement text. @@ -657,6 +638,19 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, return (rval); \ } while (0) + if (dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) { + VSTRING *base64_buf; + char *err; + + if ((base64_buf = dict_file_to_b64(dict, p)) == 0) { + err = dict_file_get_error(dict); + msg_warn("pcre map %s, line %d: %s: skipping this rule", + mapname, lineno, err); + myfree(err); + CREATE_MATCHOP_ERROR_RETURN(0); + } + p = vstring_str(base64_buf); + } if (mac_parse(p, dict_pcre_prescan, (void *) &prescan_context) & MAC_PARSE_ERROR) { msg_warn("pcre map %s, line %d: bad replacement syntax: " @@ -672,7 +666,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, "replacement text: skipping this rule", mapname, lineno); CREATE_MATCHOP_ERROR_RETURN(0); } - if (prescan_context.max_sub > 0 && (dict_flags & DICT_FLAG_NO_REGSUB)) { + if (prescan_context.max_sub > 0 && (dict->flags & DICT_FLAG_NO_REGSUB)) { msg_warn("pcre map %s, line %d: " "regular expression substitution is not allowed: " "skipping this rule", mapname, lineno); @@ -706,7 +700,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, * Save the result. */ match_rule = (DICT_PCRE_MATCH_RULE *) - dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, nesting, lineno, + dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, lineno, sizeof(DICT_PCRE_MATCH_RULE)); match_rule->match = regexp.match; match_rule->max_sub = prescan_context.max_sub; @@ -759,11 +753,12 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, * Save the result. */ if_rule = (DICT_PCRE_IF_RULE *) - dict_pcre_rule_alloc(DICT_PCRE_OP_IF, nesting, lineno, + dict_pcre_rule_alloc(DICT_PCRE_OP_IF, lineno, sizeof(DICT_PCRE_IF_RULE)); if_rule->match = regexp.match; if_rule->pattern = engine.pattern; if_rule->hints = engine.hints; + if_rule->endif_rule = 0; return ((DICT_PCRE_RULE *) if_rule); } @@ -796,7 +791,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, /* * Save the result. */ - rule = dict_pcre_rule_alloc(DICT_PCRE_OP_ENDIF, nesting, lineno, + rule = dict_pcre_rule_alloc(DICT_PCRE_OP_ENDIF, lineno, sizeof(DICT_PCRE_RULE)); return (rule); } @@ -815,6 +810,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) { + const char myname[] = "dict_pcre_open"; DICT_PCRE *dict_pcre; VSTREAM *map_fp = 0; struct stat st; @@ -825,6 +821,8 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) int lineno; int nesting = 0; char *p; + DICT_PCRE_RULE **rule_stack = 0; + MVECT mvect; /* * Let the optimizer worry about eliminating redundant code. @@ -885,13 +883,31 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) trimblanks(p, 0)[0] = 0; /* Trim space at end */ if (*p == 0) continue; - rule = dict_pcre_parse_rule(mapname, lineno, p, nesting, dict_flags); + rule = dict_pcre_parse_rule(&dict_pcre->dict, mapname, lineno, + p, nesting); if (rule == 0) continue; if (rule->op == DICT_PCRE_OP_IF) { + if (rule_stack == 0) + rule_stack = (DICT_PCRE_RULE **) mvect_alloc(&mvect, + sizeof(*rule_stack), nesting + 1, + (MVECT_FN) 0, (MVECT_FN) 0); + else + rule_stack = + (DICT_PCRE_RULE **) mvect_realloc(&mvect, nesting + 1); + rule_stack[nesting] = rule; nesting++; } else if (rule->op == DICT_PCRE_OP_ENDIF) { - nesting--; + DICT_PCRE_IF_RULE *if_rule; + + if (nesting-- <= 0) + /* Already handled in dict_pcre_parse_rule(). */ + msg_panic("%s: ENDIF without IF", myname); + if (rule_stack[nesting]->op != DICT_PCRE_OP_IF) + msg_panic("%s: unexpected rule stack element type %d", + myname, rule_stack[nesting]->op); + if_rule = (DICT_PCRE_IF_RULE *) rule_stack[nesting]; + if_rule->endif_rule = rule; } if (last_rule == 0) dict_pcre->head = rule; @@ -900,10 +916,14 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) last_rule = rule; } - if (nesting) - msg_warn("pcre map %s, line %d: more IFs than ENDIFs", - mapname, lineno); + while (nesting-- > 0) + msg_warn("pcre map %s, line %d: IF has no matching ENDIF", + mapname, rule_stack[nesting]->lineno); + + if (rule_stack) + (void) mvect_free(&mvect); + dict_file_purge_buffers(&dict_pcre->dict); DICT_PCRE_OPEN_RETURN(DICT_DEBUG (&dict_pcre->dict)); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_random.c b/external/ibm-public/postfix/dist/src/util/dict_random.c index 45ba60af10d..aade76a1357 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_random.c +++ b/external/ibm-public/postfix/dist/src/util/dict_random.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_random.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_random.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -33,6 +33,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -73,26 +78,60 @@ static void dict_random_close(DICT *dict) { DICT_RANDOM *dict_random = (DICT_RANDOM *) dict; - argv_free(dict_random->replies); + if (dict_random->replies) + argv_free(dict_random->replies); dict_free(dict); } +static char *dict_random_parse_name(DICT *dict, ARGV **argv, + const char *string, + const char *delim, + const char *parens) +{ + ARGV *argvp = argv_alloc(1); + char *saved_string = mystrdup(string); + char *bp = saved_string; + char *arg; + VSTRING *b64 = 0; + char *err = 0; + + while ((arg = mystrtokq(&bp, delim, parens)) != 0) { + if (dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) { + if ((b64 = dict_file_to_b64(dict, arg)) != 0) { + argv_add(argvp, vstring_str(b64), (char *) 0); + } else { + err = dict_file_get_error(dict); + break; + } + } else { + argv_add(argvp, arg, (char *) 0); + } + } + argv_terminate(argvp); + myfree(saved_string); + *argv = argvp; + return (err); +} + /* dict_random_open - open a randomized table */ DICT *dict_random_open(const char *name, int open_flags, int dict_flags) { DICT_RANDOM *dict_random; char *saved_name = 0; - ARGV *argv; size_t len; + char *err = 0; /* * Clarity first. Let the optimizer worry about redundant code. */ #define DICT_RANDOM_RETURN(x) do { \ + DICT *__d = (x); \ if (saved_name != 0) \ myfree(saved_name); \ - return (x); \ + if (err != 0) \ + myfree(err); \ + return (__d); \ } while (0) /* @@ -105,30 +144,38 @@ DICT *dict_random_open(const char *name, int open_flags, int dict_flags) DICT_TYPE_RANDOM, name)); /* - * Split the name name into its constituent parts. - */ - if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0 - || *(saved_name = mystrndup(name + 1, len - 2)) == 0 - || ((argv = argv_splitq(saved_name, CHARS_COMMA_SP, CHARS_BRACE)), - (argv->argc == 0))) - DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name, - open_flags, dict_flags, - "bad syntax: \"%s:%s\"; " - "need \"%s:{value...}\"", - DICT_TYPE_RANDOM, name, - DICT_TYPE_RANDOM)); - - /* - * Bundle up the result. + * Bundle up preliminary results. */ dict_random = (DICT_RANDOM *) dict_alloc(DICT_TYPE_RANDOM, name, sizeof(*dict_random)); dict_random->dict.lookup = dict_random_lookup; dict_random->dict.close = dict_random_close; dict_random->dict.flags = dict_flags | DICT_FLAG_PATTERN; - dict_random->replies = argv; + dict_random->replies = 0; dict_random->dict.owner.status = DICT_OWNER_TRUSTED; dict_random->dict.owner.uid = 0; + /* + * Split the name name into its constituent parts. + */ + if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0 + || *(saved_name = mystrndup(name + 1, len - 2)) == 0 + || (err = dict_random_parse_name(&dict_random->dict, + &dict_random->replies, saved_name, + CHARS_COMMA_SP, CHARS_BRACE)) != 0 + || dict_random->replies->argc == 0) { + dict_random_close(&dict_random->dict); + DICT_RANDOM_RETURN(err == 0 ? + dict_surrogate(DICT_TYPE_RANDOM, name, + open_flags, dict_flags, + "bad syntax: \"%s:%s\"; " + "need \"%s:{value...}\"", + DICT_TYPE_RANDOM, name, + DICT_TYPE_RANDOM) : + dict_surrogate(DICT_TYPE_RANDOM, name, + open_flags, dict_flags, + "%s", err)); + } + dict_file_purge_buffers(&dict_random->dict); DICT_RANDOM_RETURN(DICT_DEBUG (&dict_random->dict)); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_regexp.c b/external/ibm-public/postfix/dist/src/util/dict_regexp.c index e842ac17c1f..056affd817a 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_regexp.c +++ b/external/ibm-public/postfix/dist/src/util/dict_regexp.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_regexp.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_regexp.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -33,6 +33,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -64,6 +69,7 @@ #include "dict_regexp.h" #include "mac_parse.h" #include "warn_stat.h" +#include "mvect.h" /* * Support for IF/ENDIF based on an idea by Bert Driehuis. @@ -86,7 +92,6 @@ typedef struct { */ typedef struct DICT_REGEXP_RULE { int op; /* DICT_REGEXP_OP_MATCH/IF/ENDIF */ - int nesting; /* Level of search nesting */ int lineno; /* source file line number */ struct DICT_REGEXP_RULE *next; /* next rule in dict */ } DICT_REGEXP_RULE; @@ -105,6 +110,7 @@ typedef struct { DICT_REGEXP_RULE rule; /* generic members */ regex_t *expr; /* the condition */ int match; /* positive or negative match */ + struct DICT_REGEXP_RULE *endif_rule;/* matching endif rule */ } DICT_REGEXP_IF_RULE; /* @@ -218,7 +224,6 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) DICT_REGEXP_MATCH_RULE *match_rule; DICT_REGEXP_EXPAND_CONTEXT expand_context; int error; - int nesting = 0; dict->error = 0; @@ -236,12 +241,6 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) } for (rule = dict_regexp->head; rule; rule = rule->next) { - /* - * Skip rules inside failed IF/ENDIF. - */ - if (nesting < rule->nesting) - continue; - switch (rule->op) { /* @@ -303,14 +302,16 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) if (DICT_REGEXP_REGEXEC(error, dict->name, rule->lineno, if_rule->expr, if_rule->match, lookup_string, NULL_SUBSTITUTIONS, NULL_MATCH_RESULT)) - nesting++; - continue; + continue; + /* An IF without matching ENDIF has no "endif" rule. */ + if ((rule = if_rule->endif_rule) == 0) + return (0); + /* FALLTHROUGH */ /* - * ENDIF after successful IF. + * ENDIF after IF. */ case DICT_REGEXP_OP_ENDIF: - nesting--; continue; default: @@ -381,16 +382,13 @@ static int dict_regexp_get_pat(const char *mapname, int lineno, char **bufp, * Process negation operators. */ pat->match = 1; - while (*p == '!') { - pat->match = !pat->match; + for (;;) { + if (*p == '!') + pat->match = !pat->match; + else if (!ISSPACE(*p)) + break; p++; } - - /* - * Grr...aceful handling of whitespace after '!'. - */ - while (*p && ISSPACE(*p)) - p++; if (*p == 0) { msg_warn("regexp map %s, line %d: no regexp: skipping this rule", mapname, lineno); @@ -536,15 +534,12 @@ static regex_t *dict_regexp_compile_pat(const char *mapname, int lineno, /* dict_regexp_rule_alloc - fill in a generic rule structure */ -static DICT_REGEXP_RULE *dict_regexp_rule_alloc(int op, int nesting, - int lineno, - size_t size) +static DICT_REGEXP_RULE *dict_regexp_rule_alloc(int op, int lineno, size_t size) { DICT_REGEXP_RULE *rule; rule = (DICT_REGEXP_RULE *) mymalloc(size); rule->op = op; - rule->nesting = nesting; rule->lineno = lineno; rule->next = 0; @@ -553,9 +548,9 @@ static DICT_REGEXP_RULE *dict_regexp_rule_alloc(int op, int nesting, /* dict_regexp_parseline - parse one rule */ -static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, - char *line, int nesting, - int dict_flags) +static DICT_REGEXP_RULE *dict_regexp_parseline(DICT *dict, const char *mapname, + int lineno, char *line, + int nesting) { char *p; @@ -584,8 +579,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, while (*p && ISSPACE(*p)) ++p; if (!*p) { - msg_warn("regexp map %s, line %d: using empty replacement string", - mapname, lineno); + msg_warn("regexp map %s, line %d: no replacement text: " + "using empty string", mapname, lineno); } /* @@ -614,6 +609,19 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, return (rval); \ } while (0) + if (dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) { + VSTRING *base64_buf; + char *err; + + if ((base64_buf = dict_file_to_b64(dict, p)) == 0) { + err = dict_file_get_error(dict); + msg_warn("regexp map %s, line %d: %s: skipping this rule", + mapname, lineno, err); + myfree(err); + CREATE_MATCHOP_ERROR_RETURN(0); + } + p = vstring_str(base64_buf); + } if (mac_parse(p, dict_regexp_prescan, (void *) &prescan_context) & MAC_PARSE_ERROR) { msg_warn("regexp map %s, line %d: bad replacement syntax: " @@ -634,7 +642,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, "replacement text: skipping this rule", mapname, lineno); CREATE_MATCHOP_ERROR_RETURN(0); } - if (prescan_context.max_sub > 0 && (dict_flags & DICT_FLAG_NO_REGSUB)) { + if (prescan_context.max_sub > 0 && (dict->flags & DICT_FLAG_NO_REGSUB)) { msg_warn("regexp map %s, line %d: " "regular expression substitution is not allowed: " "skipping this rule", mapname, lineno); @@ -658,7 +666,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, second_exp = 0; } match_rule = (DICT_REGEXP_MATCH_RULE *) - dict_regexp_rule_alloc(DICT_REGEXP_OP_MATCH, nesting, lineno, + dict_regexp_rule_alloc(DICT_REGEXP_OP_MATCH, lineno, sizeof(DICT_REGEXP_MATCH_RULE)); match_rule->first_exp = first_exp; match_rule->first_match = first_pat.match; @@ -696,10 +704,11 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, if ((expr = dict_regexp_compile_pat(mapname, lineno, &pattern)) == 0) return (0); if_rule = (DICT_REGEXP_IF_RULE *) - dict_regexp_rule_alloc(DICT_REGEXP_OP_IF, nesting, lineno, + dict_regexp_rule_alloc(DICT_REGEXP_OP_IF, lineno, sizeof(DICT_REGEXP_IF_RULE)); if_rule->expr = expr; if_rule->match = pattern.match; + if_rule->endif_rule = 0; return ((DICT_REGEXP_RULE *) if_rule); } @@ -720,7 +729,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, if (*p) msg_warn("regexp map %s, line %d: ignoring extra text after ENDIF", mapname, lineno); - rule = dict_regexp_rule_alloc(DICT_REGEXP_OP_ENDIF, nesting, lineno, + rule = dict_regexp_rule_alloc(DICT_REGEXP_OP_ENDIF, lineno, sizeof(DICT_REGEXP_RULE)); return (rule); } @@ -739,6 +748,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) { + const char myname[] = "dict_regexp_open"; DICT_REGEXP *dict_regexp; VSTREAM *map_fp = 0; struct stat st; @@ -750,6 +760,8 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) size_t max_sub = 0; int nesting = 0; char *p; + DICT_REGEXP_RULE **rule_stack = 0; + MVECT mvect; /* * Let the optimizer worry about eliminating redundant code. @@ -805,16 +817,34 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) trimblanks(p, 0)[0] = 0; if (*p == 0) continue; - rule = dict_regexp_parseline(mapname, lineno, p, nesting, dict_flags); + rule = dict_regexp_parseline(&dict_regexp->dict, mapname, lineno, + p, nesting); if (rule == 0) continue; if (rule->op == DICT_REGEXP_OP_MATCH) { if (((DICT_REGEXP_MATCH_RULE *) rule)->max_sub > max_sub) max_sub = ((DICT_REGEXP_MATCH_RULE *) rule)->max_sub; } else if (rule->op == DICT_REGEXP_OP_IF) { + if (rule_stack == 0) + rule_stack = (DICT_REGEXP_RULE **) mvect_alloc(&mvect, + sizeof(*rule_stack), nesting + 1, + (MVECT_FN) 0, (MVECT_FN) 0); + else + rule_stack = + (DICT_REGEXP_RULE **) mvect_realloc(&mvect, nesting + 1); + rule_stack[nesting] = rule; nesting++; } else if (rule->op == DICT_REGEXP_OP_ENDIF) { - nesting--; + DICT_REGEXP_IF_RULE *if_rule; + + if (nesting-- <= 0) + /* Already handled in dict_regexp_parseline(). */ + msg_panic("%s: ENDIF without IF", myname); + if (rule_stack[nesting]->op != DICT_REGEXP_OP_IF) + msg_panic("%s: unexpected rule stack element type %d", + myname, rule_stack[nesting]->op); + if_rule = (DICT_REGEXP_IF_RULE *) rule_stack[nesting]; + if_rule->endif_rule = rule; } if (last_rule == 0) dict_regexp->head = rule; @@ -823,9 +853,12 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) last_rule = rule; } - if (nesting) - msg_warn("regexp map %s, line %d: more IFs than ENDIFs", - mapname, lineno); + while (nesting-- > 0) + msg_warn("regexp map %s, line %d: IF has no matching ENDIF", + mapname, rule_stack[nesting]->lineno); + + if (rule_stack) + (void) mvect_free(&mvect); /* * Allocate space for only as many matched substrings as used in the @@ -835,6 +868,7 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) dict_regexp->pmatch = (regmatch_t *) mymalloc(sizeof(regmatch_t) * (max_sub + 1)); + dict_file_purge_buffers(&dict_regexp->dict); DICT_REGEXP_OPEN_RETURN(DICT_DEBUG (&dict_regexp->dict)); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_static.c b/external/ibm-public/postfix/dist/src/util/dict_static.c index 75e4dd5aa26..44c1a19a58b 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_static.c +++ b/external/ibm-public/postfix/dist/src/util/dict_static.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_static.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_static.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -25,6 +25,11 @@ /* AUTHOR(S) /* jeffm /* ghostgun.com +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -43,17 +48,33 @@ #include "dict.h" #include "dict_static.h" + /* + * Subclass of DICT. + */ +typedef struct { + DICT dict; /* parent class */ + char *value; +} DICT_STATIC; + +#define STR(x) vstring_str(x) + /* dict_static_lookup - access static value*/ static const char *dict_static_lookup(DICT *dict, const char *unused_name) { - DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, dict->name); + DICT_STATIC *dict_static = (DICT_STATIC *) dict; + + DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, dict_static->value); } /* dict_static_close - close static dictionary */ static void dict_static_close(DICT *dict) { + DICT_STATIC *dict_static = (DICT_STATIC *) dict; + + if (dict_static->value) + myfree(dict_static->value); dict_free(dict); } @@ -61,9 +82,11 @@ static void dict_static_close(DICT *dict) DICT *dict_static_open(const char *name, int open_flags, int dict_flags) { - DICT *dict; + DICT_STATIC *dict_static; char *err = 0; char *cp, *saved_name = 0; + const char *value; + VSTRING *base64_buf; /* * Let the optimizer worry about eliminating redundant code. @@ -72,8 +95,8 @@ DICT *dict_static_open(const char *name, int open_flags, int dict_flags) DICT *__d = (d); \ if (saved_name != 0) \ myfree(saved_name); \ - if (err != 0) \ - myfree(err); \ + if (err != 0) \ + myfree(err); \ return (__d); \ } while (0) @@ -86,17 +109,43 @@ DICT *dict_static_open(const char *name, int open_flags, int dict_flags) DICT_STATIC_OPEN_RETURN(dict_surrogate(DICT_TYPE_STATIC, name, open_flags, dict_flags, "bad %s:name syntax: %s", - DICT_TYPE_STATIC, err)); - name = cp; + DICT_TYPE_STATIC, + err)); + value = cp; + } else { + value = name; } /* - * Bundle up the request. + * Bundle up the preliminary result. + */ + dict_static = (DICT_STATIC *) dict_alloc(DICT_TYPE_STATIC, name, + sizeof(*dict_static)); + dict_static->dict.lookup = dict_static_lookup; + dict_static->dict.close = dict_static_close; + dict_static->dict.flags = dict_flags | DICT_FLAG_FIXED; + dict_static->dict.owner.status = DICT_OWNER_TRUSTED; + dict_static->value = 0; + + /* + * Optionally replace the value with file contents. */ - dict = dict_alloc(DICT_TYPE_STATIC, name, sizeof(*dict)); - dict->lookup = dict_static_lookup; - dict->close = dict_static_close; - dict->flags = dict_flags | DICT_FLAG_FIXED; - dict->owner.status = DICT_OWNER_TRUSTED; - DICT_STATIC_OPEN_RETURN(DICT_DEBUG (dict)); + if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) { + if ((base64_buf = dict_file_to_b64(&dict_static->dict, value)) == 0) { + err = dict_file_get_error(&dict_static->dict); + dict_close(&dict_static->dict); + DICT_STATIC_OPEN_RETURN(dict_surrogate(DICT_TYPE_STATIC, name, + open_flags, dict_flags, + "%s", err)); + } + value = vstring_str(base64_buf); + } + + /* + * Finalize the result. + */ + dict_static->value = mystrdup(value); + dict_file_purge_buffers(&dict_static->dict); + + DICT_STATIC_OPEN_RETURN(DICT_DEBUG (&(dict_static->dict))); } diff --git a/external/ibm-public/postfix/dist/src/util/dict_thash.c b/external/ibm-public/postfix/dist/src/util/dict_thash.c index 3a328419876..1327fe41cc3 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_thash.c +++ b/external/ibm-public/postfix/dist/src/util/dict_thash.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_thash.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_thash.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -31,6 +31,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -101,7 +106,7 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags, "open database %s: %m", path)); - } + } /* * Reuse the "internal" dictionary type. @@ -109,17 +114,21 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) dict = dict_open3(DICT_TYPE_HT, path, open_flags, dict_flags); dict_type_override(dict, DICT_TYPE_THASH); + /* + * XXX This duplicates the parser in postmap.c. + */ if (line_buffer == 0) line_buffer = vstring_alloc(100); last_line = 0; while (readllines(line_buffer, fp, &last_line, &lineno)) { + int in_quotes = 0; /* * First some UTF-8 checks sans casefolding. */ if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) && allascii(STR(line_buffer)) == 0 - && valid_utf8_string(STR(line_buffer), LEN(line_buffer)) == 0) { + && valid_utf8_string(STR(line_buffer), LEN(line_buffer)) == 0) { msg_warn("%s, line %d: non-UTF-8 input \"%s\"" " -- ignoring this line", VSTREAM_PATH(fp), lineno, STR(line_buffer)); @@ -130,16 +139,36 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) * Split on the first whitespace character, then trim leading and * trailing whitespace from key and value. */ - key = STR(line_buffer); - value = key + strcspn(key, CHARS_SPACE); + for (value = STR(line_buffer); *value; value++) { + if (*value == '\\') { + if (*++value == 0) + break; + } else if (ISSPACE(*value)) { + if (!in_quotes) + break; + } else if (*value == '"') { + in_quotes = !in_quotes; + } + } + if (in_quotes) { + msg_warn("%s, line %d: unbalanced '\"' in '%s'" + " -- ignoring this line", + VSTREAM_PATH(fp), lineno, STR(line_buffer)); + continue; + } if (*value) *value++ = 0; while (ISSPACE(*value)) value++; - trimblanks(key, 0)[0] = 0; trimblanks(value, 0)[0] = 0; /* + * Leave the key in quoted form, for consistency with postmap.c + * and dict_inline.c. + */ + key = STR(line_buffer); + + /* * Enforce the "key whitespace value" format. Disallow missing * keys or missing values. */ @@ -158,7 +187,8 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) * ignores duplicates by default and we would have to check that * we won't break existing code that depends on such benavior; 2) * by inlining the checks here we can degrade gracefully instead - * of terminating with a fatal error. See comment in dict_inline.c. + * of terminating with a fatal error. See comment in + * dict_inline.c. */ if (dict->lookup(dict, key) != 0) { if (dict_flags & DICT_FLAG_DUP_IGNORE) { diff --git a/external/ibm-public/postfix/dist/src/util/dict_union.c b/external/ibm-public/postfix/dist/src/util/dict_union.c index 21c25d6060e..19ddaeeb2df 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_union.c +++ b/external/ibm-public/postfix/dist/src/util/dict_union.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_union.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_union.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -38,6 +38,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/util/dict_utf8.c b/external/ibm-public/postfix/dist/src/util/dict_utf8.c index fa52212ce68..ca8a9139e12 100644 --- a/external/ibm-public/postfix/dist/src/util/dict_utf8.c +++ b/external/ibm-public/postfix/dist/src/util/dict_utf8.c @@ -1,4 +1,4 @@ -/* $NetBSD: dict_utf8.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: dict_utf8.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -35,6 +35,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -106,8 +111,9 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string, /* * Casefold UTF-8. */ - if (fold_flag != 0 && (fold_flag & (dict->flags & DICT_FLAG_FIXED) ? - DICT_FLAG_FOLD_FIX : DICT_FLAG_FOLD_MUL)) { + if (fold_flag != 0 + && (fold_flag & ((dict->flags & DICT_FLAG_FIXED) ? + DICT_FLAG_FOLD_FIX : DICT_FLAG_FOLD_MUL))) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); return (casefold(dict->fold_buf, string)); diff --git a/external/ibm-public/postfix/dist/src/util/edit_file.c b/external/ibm-public/postfix/dist/src/util/edit_file.c index 60f546fb837..e79dcf07c65 100644 --- a/external/ibm-public/postfix/dist/src/util/edit_file.c +++ b/external/ibm-public/postfix/dist/src/util/edit_file.c @@ -1,4 +1,4 @@ -/* $NetBSD: edit_file.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: edit_file.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -57,7 +57,7 @@ /* pathname into the place of the original file. When any of /* these operations fails, edit_file_close() behaves as if /* edit_file_cleanup() was called. Regardless of whether these -/* operations suceed, edit_file_close() releases the exclusive +/* operations succeed, edit_file_close() releases the exclusive /* lock, closes the output file, and frees up memory that was /* allocated by edit_file_open(). /* diff --git a/external/ibm-public/postfix/dist/src/util/edit_file.h b/external/ibm-public/postfix/dist/src/util/edit_file.h index 676fb5eacc4..a5ad0c9cb84 100644 --- a/external/ibm-public/postfix/dist/src/util/edit_file.h +++ b/external/ibm-public/postfix/dist/src/util/edit_file.h @@ -1,4 +1,4 @@ -/* $NetBSD: edit_file.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: edit_file.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _EDIT_FILE_H_INCLUDED_ #define _EDIT_FILE_H_INCLUDED_ @@ -45,6 +45,11 @@ extern void edit_file_cleanup(EDIT_FILE *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/extpar.c b/external/ibm-public/postfix/dist/src/util/extpar.c index 96aaefb852c..927297d5e47 100644 --- a/external/ibm-public/postfix/dist/src/util/extpar.c +++ b/external/ibm-public/postfix/dist/src/util/extpar.c @@ -1,4 +1,4 @@ -/* $NetBSD: extpar.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: extpar.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -41,7 +41,7 @@ /* In case of error the result value is a dynamically-allocated /* string with a description of the problem that includes a /* copy of the offending input. A non-null result value should -/* be destroyed with myfree(). The following decribes the errors +/* be destroyed with myfree(). The following describes the errors /* and the state of the buffer and buffer pointer. /* .IP "missing closing parenthesis" /* The buffer pointer points to text as if a closing parenthesis diff --git a/external/ibm-public/postfix/dist/src/util/hex_code.h b/external/ibm-public/postfix/dist/src/util/hex_code.h index b8c7ee87062..8dce400133c 100644 --- a/external/ibm-public/postfix/dist/src/util/hex_code.h +++ b/external/ibm-public/postfix/dist/src/util/hex_code.h @@ -1,4 +1,4 @@ -/* $NetBSD: hex_code.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: hex_code.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _HEX_CODE_H_INCLUDED_ #define _HEX_CODE_H_INCLUDED_ @@ -33,6 +33,11 @@ extern VSTRING *WARN_UNUSED_RESULT hex_decode(VSTRING *, const char *, ssize_t); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/hex_quote.c b/external/ibm-public/postfix/dist/src/util/hex_quote.c index e93e574bd96..bb9946b5412 100644 --- a/external/ibm-public/postfix/dist/src/util/hex_quote.c +++ b/external/ibm-public/postfix/dist/src/util/hex_quote.c @@ -1,4 +1,4 @@ -/* $NetBSD: hex_quote.c,v 1.1.1.2 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: hex_quote.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/host_port.h b/external/ibm-public/postfix/dist/src/util/host_port.h index 60702711fc3..e4c34a4d08a 100644 --- a/external/ibm-public/postfix/dist/src/util/host_port.h +++ b/external/ibm-public/postfix/dist/src/util/host_port.h @@ -1,4 +1,4 @@ -/* $NetBSD: host_port.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: host_port.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _HOST_PORT_H_INCLUDED_ #define _HOST_PORT_H_INCLUDED_ @@ -27,6 +27,11 @@ extern const char *WARN_UNUSED_RESULT host_port(char *, char **, char *, /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/inet_proto.c b/external/ibm-public/postfix/dist/src/util/inet_proto.c index e5cb557eba1..7ada9be092a 100644 --- a/external/ibm-public/postfix/dist/src/util/inet_proto.c +++ b/external/ibm-public/postfix/dist/src/util/inet_proto.c @@ -1,4 +1,4 @@ -/* $NetBSD: inet_proto.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: inet_proto.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -216,7 +216,7 @@ INET_PROTO_INFO *inet_proto_init(const char *context, const char *protocols) } /* - * Store addess family etc. info as null-terminated vectors. If that + * Store address family etc. info as null-terminated vectors. If that * breaks because we must be able to store nulls, we'll deal with the * additional complexity. * diff --git a/external/ibm-public/postfix/dist/src/util/killme_after.c b/external/ibm-public/postfix/dist/src/util/killme_after.c index 5f4d8b593ba..cbbb727207a 100644 --- a/external/ibm-public/postfix/dist/src/util/killme_after.c +++ b/external/ibm-public/postfix/dist/src/util/killme_after.c @@ -1,4 +1,4 @@ -/* $NetBSD: killme_after.c,v 1.1.1.2 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: killme_after.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/listen.h b/external/ibm-public/postfix/dist/src/util/listen.h index 65cf11b196c..76ffc0bbe0c 100644 --- a/external/ibm-public/postfix/dist/src/util/listen.h +++ b/external/ibm-public/postfix/dist/src/util/listen.h @@ -1,4 +1,4 @@ -/* $NetBSD: listen.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: listen.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _LISTEN_H_INCLUDED_ #define _LISTEN_H_INCLUDED_ @@ -26,6 +26,7 @@ extern int unix_listen(const char *, int, int); extern int inet_listen(const char *, int, int); extern int fifo_listen(const char *, int, int); extern int stream_listen(const char *, int, int); +extern int unix_dgram_listen(const char *, int); extern int inet_accept(int); extern int unix_accept(int); @@ -44,6 +45,11 @@ extern int pass_accept_attr(int, HTABLE **); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/logwriter.c b/external/ibm-public/postfix/dist/src/util/logwriter.c index 76f21c2a7cc..ff3dd8a208d 100644 --- a/external/ibm-public/postfix/dist/src/util/logwriter.c +++ b/external/ibm-public/postfix/dist/src/util/logwriter.c @@ -1,4 +1,4 @@ -/* $NetBSD: logwriter.c,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: logwriter.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/logwriter.h b/external/ibm-public/postfix/dist/src/util/logwriter.h index 737c56d4be6..7fa6d1c26a0 100644 --- a/external/ibm-public/postfix/dist/src/util/logwriter.h +++ b/external/ibm-public/postfix/dist/src/util/logwriter.h @@ -1,4 +1,4 @@ -/* $NetBSD: logwriter.h,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: logwriter.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _LOGWRITER_H_INCLUDED_ #define _LOGWRITER_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/lstat_as.h b/external/ibm-public/postfix/dist/src/util/lstat_as.h index 9cd3acf56cb..65c79b78d30 100644 --- a/external/ibm-public/postfix/dist/src/util/lstat_as.h +++ b/external/ibm-public/postfix/dist/src/util/lstat_as.h @@ -1,4 +1,4 @@ -/* $NetBSD: lstat_as.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: lstat_as.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _LSTAT_AS_H_INCLUDED_ #define _LSTAT_AS_H_INCLUDED_ @@ -27,6 +27,11 @@ extern int WARN_UNUSED_RESULT lstat_as(const char *, struct stat *, uid_t, gid_t /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/mac_expand.c b/external/ibm-public/postfix/dist/src/util/mac_expand.c index 35436e91847..2ca13c7e2a4 100644 --- a/external/ibm-public/postfix/dist/src/util/mac_expand.c +++ b/external/ibm-public/postfix/dist/src/util/mac_expand.c @@ -1,4 +1,4 @@ -/* $NetBSD: mac_expand.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: mac_expand.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -18,7 +18,7 @@ /* DESCRIPTION /* This module implements parameter-less named attribute /* expansions, both conditional and unconditional. As of Postfix -/* 3.0 this code supports logical expression evaluation. +/* 3.0 this code supports relational expression evaluation. /* /* In this text, an attribute is considered "undefined" when its value /* is a null pointer. Otherwise, the attribute is considered "defined" @@ -26,7 +26,9 @@ /* /* In the text below, the legacy form $(...) is equivalent to /* ${...}. The legacy form $(...) may eventually disappear -/* from documentation. +/* from documentation. In the text below, the name in $name +/* and ${name...} must contain only characters from the set +/* [a-zA-Z0-9_]. /* /* The following substitutions are supported: /* .IP "$name, ${name}" @@ -36,28 +38,28 @@ /* .IP "${name?text}, ${name?{text}}" /* Conditional attribute-based substition. If the named attribute /* value is non-empty, the result is the given text, after -/* named attribute expansion and logical expression evaluation. +/* named attribute expansion and relational expression evaluation. /* Otherwise, the result is empty. Whitespace before or after /* {text} is ignored. /* .IP "${name:text}, ${name:{text}}" /* Conditional attribute-based substition. If the attribute /* value is empty or undefined, the expansion is the given -/* text, after named attribute expansion and logical expression +/* text, after named attribute expansion and relational expression /* evaluation. Otherwise, the result is empty. Whitespace /* before or after {text} is ignored. /* .IP "${name?{text1}:{text2}}, ${name?{text1}:text2}" /* Conditional attribute-based substition. If the named attribute /* value is non-empty, the result is text1. Otherwise, the /* result is text2. In both cases the result is subject to -/* named attribute expansion and logical expression evaluation. +/* named attribute expansion and relational expression evaluation. /* Whitespace before or after {text1} or {text2} is ignored. /* .IP "${{text1} == ${text2} ? {text3} : {text4}}" -/* Logical expression-based substition. First, the content +/* Relational expression-based substition. First, the content /* of {text1} and ${text2} is subjected to named attribute and -/* logical expression-based substitution. Next, the logical +/* relational expression-based substitution. Next, the relational /* expression is evaluated. If it evaluates to "true", the /* result is the content of {text3}, otherwise it is the content -/* of {text4}, after named attribute and logical expression-based +/* of {text4}, after named attribute and relational expression-based /* substitution. In addition to ==, this supports !=, <, <=, /* >=, and >. Comparisons are numerical when both operands are /* all digits, otherwise the comparisons are lexicographical. @@ -119,12 +121,18 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ #include <sys_defs.h> #include <ctype.h> +#include <errno.h> #include <string.h> #include <stdlib.h> @@ -152,21 +160,22 @@ typedef struct { } MAC_EXP_CONTEXT; /* - * Support for logical expressions. + * Support for relational expressions. * * As of Postfix 2.2, ${attr-name?result} or ${attr-name:result} return the * result respectively when the parameter value is non-empty, or when the * parameter value is undefined or empty; support for the ternary ?: * operator was anticipated, but not implemented for 10 years. * - * To make ${logical-expr?result} and ${logical-expr:result} work as expected - * without breaking the way that ? and : work, logical expressions evaluate - * to a non-empty or empty value. It does not matter what non-empty value we - * use for TRUE. However we must not use the undefined (null pointer) value - * for FALSE - that would raise the MAC_PARSE_UNDEF flag. + * To make ${relational-expr?result} and ${relational-expr:result} work as + * expected without breaking the way that ? and : work, relational + * expressions evaluate to a non-empty or empty value. It does not matter + * what non-empty value we use for TRUE. However we must not use the + * undefined (null pointer) value for FALSE - that would raise the + * MAC_PARSE_UNDEF flag. * - * The value of a logical expression can be exposed with ${logical-expr}, i.e. - * a logical expression that is not followed by ? or : conditional + * The value of a relational expression can be exposed with ${relational-expr}, + * i.e. a relational expression that is not followed by ? or : conditional * expansion. */ #define MAC_EXP_BVAL_TRUE "true" @@ -212,6 +221,19 @@ static const NAME_CODE mac_exp_op_table[] = */ #define MAC_EXP_WHITESPACE CHARS_SPACE +/* atol_or_die - convert or die */ + +static long atol_or_die(const char *strval) +{ + long result; + char *remainder; + + result = strtol(strval, &remainder, 10); + if (*strval == 0 /* can't happen */ || *remainder != 0 || errno == ERANGE) + msg_fatal("mac_exp_eval: bad conversion: %s", strval); + return (result); +} + /* mac_exp_eval - evaluate binary expression */ static int mac_exp_eval(const char *left, int tok_val, @@ -224,7 +246,7 @@ static int mac_exp_eval(const char *left, int tok_val, * Numerical or string comparison. */ if (alldig(left) && alldig(rite)) { - delta = atol(left) - atol(rite); + delta = atol_or_die(left) - atol_or_die(rite); } else { delta = strcmp(left, rite); } @@ -267,14 +289,14 @@ static int PRINTFLIKE(2, 3) mac_exp_parse_error(MAC_EXP_CONTEXT *mc, } while (0) /* - * Postfix 3.0 introduces support for {text} operands. Only with these do - * we support the ternary ?: operator and logical operators. + * Postfix 3.0 introduces support for {text} operands. Only with these do we + * support the ternary ?: operator and relational operators. * * We cannot support operators in random text, because that would break Postfix * 2.11 compatibility. For example, with the expression "${name?value}", the * value is random text that may contain ':', '?', '{' and '}' characters. * In particular, with Postfix 2.2 .. 2.11, "${name??foo:{b}ar}" evaluates - * to "??foo:{b}ar" or empty. There are explicit tests in this directory and + * to "?foo:{b}ar" or empty. There are explicit tests in this directory and * the postconf directory to ensure that Postfix 2.11 compatibility is * maintained. * @@ -324,10 +346,10 @@ static char *mac_exp_extract_curly_payload(MAC_EXP_CONTEXT *mc, char **bp) return (payload); } -/* mac_exp_parse_logical - parse logical expression, advance read ptr */ +/* mac_exp_parse_relational - parse relational expression, advance read ptr */ -static int mac_exp_parse_logical(MAC_EXP_CONTEXT *mc, const char **lookup, - char **bp) +static int mac_exp_parse_relational(MAC_EXP_CONTEXT *mc, const char **lookup, + char **bp) { char *cp = *bp; VSTRING *left_op_buf; @@ -372,7 +394,7 @@ static int mac_exp_parse_logical(MAC_EXP_CONTEXT *mc, const char **lookup, return (mc->status); /* - * Evaluate the logical expression. Todo: regexp support. + * Evaluate the relational expression. Todo: regexp support. */ mc->status |= mac_expand(left_op_buf = vstring_alloc(100), left_op_strval, @@ -422,7 +444,7 @@ static int mac_expand_callback(int type, VSTRING *buf, void *ptr) return (mc->status); /* - * Named parameter or logical expression. In case of a syntax error, + * Named parameter or relational expression. In case of a syntax error, * return without doing damage, and issue a warning instead. */ if (type == MAC_PARSE_EXPR) { @@ -430,11 +452,11 @@ static int mac_expand_callback(int type, VSTRING *buf, void *ptr) cp = vstring_str(buf); /* - * Logical expression. If recursion is disabled, perform only one + * Relational expression. If recursion is disabled, perform only one * level of $name expansion. */ if (MAC_EXP_FIND_LEFT_CURLY(tmp_len, cp)) { - if (mac_exp_parse_logical(mc, &lookup, &cp) != 0) + if (mac_exp_parse_relational(mc, &lookup, &cp) != 0) return (mc->status); /* @@ -452,21 +474,26 @@ static int mac_expand_callback(int type, VSTRING *buf, void *ptr) * Named parameter. */ else { + char *start; /* * Look for the ? or : operator. In case of a syntax error, * return without doing damage, and issue a warning instead. */ + start = (cp += strspn(cp, MAC_EXP_WHITESPACE)); for ( /* void */ ; /* void */ ; cp++) { - if ((ch = *cp) == 0) { + if ((ch = cp[tmp_len = strspn(cp, MAC_EXP_WHITESPACE)]) == 0) { + *cp = 0; lookup_mode = MAC_EXP_MODE_USE; break; } if (ch == '?' || ch == ':') { *cp++ = 0; + cp += tmp_len; lookup_mode = MAC_EXP_MODE_TEST; break; } + ch = *cp; if (!ISALNUM(ch) && ch != '_') { MAC_EXP_ERR_RETURN(mc, "attribute name syntax error at: " "\"...%.*s>>>%.20s\"", @@ -479,7 +506,7 @@ static int mac_expand_callback(int type, VSTRING *buf, void *ptr) * Look up the named parameter. Todo: allow the lookup function * to specify if the result is safe for $name expanson. */ - lookup = mc->lookup(vstring_str(buf), lookup_mode, mc->context); + lookup = mc->lookup(start, lookup_mode, mc->context); } /* diff --git a/external/ibm-public/postfix/dist/src/util/mac_expand.h b/external/ibm-public/postfix/dist/src/util/mac_expand.h index 97682192585..035bfcf04cb 100644 --- a/external/ibm-public/postfix/dist/src/util/mac_expand.h +++ b/external/ibm-public/postfix/dist/src/util/mac_expand.h @@ -1,4 +1,4 @@ -/* $NetBSD: mac_expand.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: mac_expand.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MAC_EXPAND_H_INCLUDED_ #define _MAC_EXPAND_H_INCLUDED_ @@ -47,6 +47,11 @@ extern int mac_expand(VSTRING *, const char *, int, const char *, MAC_EXP_LOOKUP /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/match_ops.c b/external/ibm-public/postfix/dist/src/util/match_ops.c index dae6369d3f4..d24e7d848b4 100644 --- a/external/ibm-public/postfix/dist/src/util/match_ops.c +++ b/external/ibm-public/postfix/dist/src/util/match_ops.c @@ -1,4 +1,4 @@ -/* $NetBSD: match_ops.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: match_ops.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -60,6 +60,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -296,7 +301,8 @@ int match_hostaddr(MATCH_LIST *list, const char *addr, const char *pattern) * everything into to binary form, and to do the comparison there. */ saved_patt = mystrdup(pattern); - err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0); + err = cidr_match_parse(&match_info, saved_patt, CIDR_MATCH_TRUE, + (VSTRING *) 0); myfree(saved_patt); if (err != 0) { list->error = DICT_ERR_RETRY; diff --git a/external/ibm-public/postfix/dist/src/util/midna_domain.c b/external/ibm-public/postfix/dist/src/util/midna_domain.c index ff928f6583c..44d84be45e8 100644 --- a/external/ibm-public/postfix/dist/src/util/midna_domain.c +++ b/external/ibm-public/postfix/dist/src/util/midna_domain.c @@ -1,4 +1,4 @@ -/* $NetBSD: midna_domain.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: midna_domain.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -9,6 +9,7 @@ /* #include <midna_domain.h> /* /* int midna_domain_cache_size; +/* int midna_domain_transitional; /* /* const char *midna_domain_to_ascii( /* const char *name) @@ -49,8 +50,10 @@ /* /* midna_domain_cache_size specifies the size of the conversion /* result cache. This value is used only once, upon the first -/* lookup -/* request. +/* lookup request. +/* +/* midna_domain_transitional enables transitional conversion +/* between UTF8 and ASCII labels. /* SEE ALSO /* http://unicode.org/reports/tr46/ Unicode IDNA Compatibility processing /* msg(3) diagnostics interface @@ -68,6 +71,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -88,6 +96,7 @@ #include <ctable.h> #include <stringops.h> #include <valid_hostname.h> +#include <name_mask.h> #include <midna_domain.h> /* @@ -96,10 +105,47 @@ #define DEF_MIDNA_CACHE_SIZE 256 int midna_domain_cache_size = DEF_MIDNA_CACHE_SIZE; +int midna_domain_transitional = 0; static VSTRING *midna_domain_buf; /* x.suffix */ #define STR(x) vstring_str(x) +/* midna_domain_strerror - pick one for error reporting */ + +static const char *midna_domain_strerror(UErrorCode error, int info_errors) +{ + + /* + * XXX The UIDNA_ERROR_EMPTY_LABEL etc. names are defined in an ENUM, so + * we can't use #ifdef to dynamically determine which names exist. + */ + static LONG_NAME_MASK uidna_errors[] = { + "UIDNA_ERROR_EMPTY_LABEL", UIDNA_ERROR_EMPTY_LABEL, + "UIDNA_ERROR_LABEL_TOO_LONG", UIDNA_ERROR_LABEL_TOO_LONG, + "UIDNA_ERROR_DOMAIN_NAME_TOO_LONG", UIDNA_ERROR_DOMAIN_NAME_TOO_LONG, + "UIDNA_ERROR_LEADING_HYPHEN", UIDNA_ERROR_LEADING_HYPHEN, + "UIDNA_ERROR_TRAILING_HYPHEN", UIDNA_ERROR_TRAILING_HYPHEN, + "UIDNA_ERROR_HYPHEN_3_4", UIDNA_ERROR_HYPHEN_3_4, + "UIDNA_ERROR_LEADING_COMBINING_MARK", UIDNA_ERROR_LEADING_COMBINING_MARK, + "UIDNA_ERROR_DISALLOWED", UIDNA_ERROR_DISALLOWED, + "UIDNA_ERROR_PUNYCODE", UIDNA_ERROR_PUNYCODE, + "UIDNA_ERROR_LABEL_HAS_DOT", UIDNA_ERROR_LABEL_HAS_DOT, + "UIDNA_ERROR_INVALID_ACE_LABEL", UIDNA_ERROR_INVALID_ACE_LABEL, + "UIDNA_ERROR_BIDI", UIDNA_ERROR_BIDI, + "UIDNA_ERROR_CONTEXTJ", UIDNA_ERROR_CONTEXTJ, + /* The above errors are defined with ICU 46 and later. */ + 0, + }; + + if (info_errors) { + return (str_long_name_mask_opt((VSTRING *) 0, "idna error", + uidna_errors, info_errors, + NAME_MASK_NUMBER | NAME_MASK_COMMA)); + } else { + return u_errorName(error); + } +} + /* midna_domain_to_ascii_create - convert domain to ASCII */ static void *midna_domain_to_ascii_create(const char *name, void *unused_context) @@ -123,7 +169,8 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context /* * Perform the requested conversion. */ - idna = uidna_openUTS46(UIDNA_DEFAULT, &error);/* XXX check error */ + idna = uidna_openUTS46(midna_domain_transitional ? UIDNA_DEFAULT + : UIDNA_NONTRANSITIONAL_TO_ASCII, &error); anl = uidna_nameToASCII_UTF8(idna, name, strlen(name), buf, sizeof(buf) - 1, @@ -148,7 +195,7 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context return (mystrndup(buf, anl)); } else { msg_warn("%s: Problem translating domain \"%.100s\" to ASCII form: %s", - myname, name, u_errorName(info.errors)); + myname, name, midna_domain_strerror(error, info.errors)); return (0); } } @@ -176,7 +223,8 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context) /* * Perform the requested conversion. */ - idna = uidna_openUTS46(UIDNA_DEFAULT, &error);/* XXX check error */ + idna = uidna_openUTS46(midna_domain_transitional ? UIDNA_DEFAULT + : UIDNA_NONTRANSITIONAL_TO_UNICODE, &error); anl = uidna_nameToUnicodeUTF8(idna, name, strlen(name), buf, sizeof(buf) - 1, @@ -197,7 +245,7 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context) return (mystrndup(buf, anl)); } else { msg_warn("%s: Problem translating domain \"%.100s\" to UTF8 form: %s", - myname, name, u_errorName(info.errors)); + myname, name, midna_domain_strerror(error, info.errors)); return (0); } } diff --git a/external/ibm-public/postfix/dist/src/util/midna_domain.h b/external/ibm-public/postfix/dist/src/util/midna_domain.h index 1faf15f2a6b..e0276ed10ba 100644 --- a/external/ibm-public/postfix/dist/src/util/midna_domain.h +++ b/external/ibm-public/postfix/dist/src/util/midna_domain.h @@ -1,4 +1,4 @@ -/* $NetBSD: midna_domain.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: midna_domain.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MIDNA_H_INCLUDED_ #define _MIDNA_H_INCLUDED_ @@ -21,6 +21,8 @@ extern const char *midna_domain_to_utf8(const char *); extern const char *midna_domain_suffix_to_ascii(const char *); extern const char *midna_domain_suffix_to_utf8(const char *); +extern int midna_domain_cache_size; +extern int midna_domain_transitional; /* LICENSE /* .ad /* .fi @@ -32,6 +34,11 @@ extern const char *midna_domain_suffix_to_utf8(const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/msg_logger.c b/external/ibm-public/postfix/dist/src/util/msg_logger.c index 75a74e72fc8..3a5b7634a58 100644 --- a/external/ibm-public/postfix/dist/src/util/msg_logger.c +++ b/external/ibm-public/postfix/dist/src/util/msg_logger.c @@ -1,4 +1,4 @@ -/* $NetBSD: msg_logger.c,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: msg_logger.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/msg_logger.h b/external/ibm-public/postfix/dist/src/util/msg_logger.h index 68d5a098604..0b85a450fc1 100644 --- a/external/ibm-public/postfix/dist/src/util/msg_logger.h +++ b/external/ibm-public/postfix/dist/src/util/msg_logger.h @@ -1,4 +1,4 @@ -/* $NetBSD: msg_logger.h,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: msg_logger.h,v 1.2 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MSG_LOGGER_H_INCLUDED_ #define _MSG_LOGGER_H_INCLUDED_ diff --git a/external/ibm-public/postfix/dist/src/util/msg_output.c b/external/ibm-public/postfix/dist/src/util/msg_output.c index 9f27f27c372..4279eaefd68 100644 --- a/external/ibm-public/postfix/dist/src/util/msg_output.c +++ b/external/ibm-public/postfix/dist/src/util/msg_output.c @@ -1,4 +1,4 @@ -/* $NetBSD: msg_output.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: msg_output.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -21,10 +21,6 @@ /* int level; /* const char *format; /* va_list ap; -/* -/* void msg_text(level, text) -/* int level; -/* const char *text; /* DESCRIPTION /* This module implements low-level output management for the /* msg(3) diagnostics interface. @@ -81,6 +77,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -102,26 +103,31 @@ /* * Global scope, to discourage the compiler from doing smart things. */ -volatile int msg_vprintf_lock; -volatile int msg_text_lock; +volatile int msg_vprintf_level; /* - * Private state. + * Private state. Allow one nested call, so that one logging error can be + * reported to stderr before bailing out. */ +#define MSG_OUT_NESTING_LIMIT 2 static MSG_OUTPUT_FN *msg_output_fn = 0; static int msg_output_fn_count = 0; -static VSTRING *msg_buffer = 0; +static VSTRING *msg_buffers[MSG_OUT_NESTING_LIMIT]; /* msg_output - specify output handler */ void msg_output(MSG_OUTPUT_FN output_fn) { + int i; /* - * Allocate all resources during initialization. + * Allocate all resources during initialization. This may result in a + * recursive call due to memory allocation error. */ - if (msg_buffer == 0) - msg_buffer = vstring_alloc(100); + if (msg_buffers[MSG_OUT_NESTING_LIMIT - 1] == 0) { + for (i = 0; i < MSG_OUT_NESTING_LIMIT; i++) + msg_buffers[i] = vstring_alloc(100); + } /* * We're not doing this often, so avoid complexity and allocate memory @@ -151,40 +157,21 @@ void msg_printf(int level, const char *format,...) void msg_vprintf(int level, const char *format, va_list ap) { int saved_errno = errno; - - if (msg_vprintf_lock == 0) { - msg_vprintf_lock = 1; - /* On-the-fly initialization for debugging test programs only. */ - if (msg_output_fn_count == 0) - msg_vstream_init("unknown", VSTREAM_ERR); - /* OK if terminating signal handler hijacks control before next stmt. */ - vstring_vsprintf(msg_buffer, percentm(format, errno), ap); - msg_text(level, vstring_str(msg_buffer)); - msg_vprintf_lock = 0; - } - errno = saved_errno; -} - -/* msg_text - sanitize and log pre-formatted text */ - -void msg_text(int level, const char *text) -{ + VSTRING *vp; int i; - /* - * Sanitize the text. Use a private copy if necessary. - */ - if (msg_text_lock == 0) { - msg_text_lock = 1; - /* OK if terminating signal handler hijacks control before next stmt. */ - if (text != vstring_str(msg_buffer)) - vstring_strcpy(msg_buffer, text); - printable(vstring_str(msg_buffer), '?'); - /* On-the-fly initialization for debugging test programs only. */ + if (msg_vprintf_level < MSG_OUT_NESTING_LIMIT) { + msg_vprintf_level += 1; + /* On-the-fly initialization for test programs and startup errors. */ if (msg_output_fn_count == 0) msg_vstream_init("unknown", VSTREAM_ERR); + vp = msg_buffers[msg_vprintf_level - 1]; + /* OK if terminating signal handler hijacks control before next stmt. */ + vstring_vsprintf(vp, percentm(format, errno), ap); + printable(vstring_str(vp), '?'); for (i = 0; i < msg_output_fn_count; i++) - msg_output_fn[i] (level, vstring_str(msg_buffer)); - msg_text_lock = 0; + msg_output_fn[i] (level, vstring_str(vp)); + msg_vprintf_level -= 1; } + errno = saved_errno; } diff --git a/external/ibm-public/postfix/dist/src/util/msg_output.h b/external/ibm-public/postfix/dist/src/util/msg_output.h index 2d173860ad6..2d70b030cd7 100644 --- a/external/ibm-public/postfix/dist/src/util/msg_output.h +++ b/external/ibm-public/postfix/dist/src/util/msg_output.h @@ -1,4 +1,4 @@ -/* $NetBSD: msg_output.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: msg_output.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MSG_OUTPUT_FN_ #define _MSG_OUTPUT_FN_ @@ -25,7 +25,6 @@ typedef void (*MSG_OUTPUT_FN) (int, const char *); extern void msg_output(MSG_OUTPUT_FN); extern void PRINTFLIKE(2, 3) msg_printf(int, const char *,...); extern void msg_vprintf(int, const char *, va_list); -extern void msg_text(int, const char *); #define MSG_INFO 0 /* informative */ #define MSG_WARN 1 /* warning (non-fatal) */ @@ -44,6 +43,11 @@ extern void msg_text(int, const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/msg_syslog.c b/external/ibm-public/postfix/dist/src/util/msg_syslog.c index 00b7079b9ac..9c21b6b0e9e 100644 --- a/external/ibm-public/postfix/dist/src/util/msg_syslog.c +++ b/external/ibm-public/postfix/dist/src/util/msg_syslog.c @@ -1,4 +1,4 @@ -/* $NetBSD: msg_syslog.c,v 1.1.1.2 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: msg_syslog.c,v 1.2 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/msg_syslog.h b/external/ibm-public/postfix/dist/src/util/msg_syslog.h index b389f0e957d..eceb5ff3580 100644 --- a/external/ibm-public/postfix/dist/src/util/msg_syslog.h +++ b/external/ibm-public/postfix/dist/src/util/msg_syslog.h @@ -1,4 +1,4 @@ -/* $NetBSD: msg_syslog.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: msg_syslog.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MSG_SYSLOG_H_INCLUDED_ #define _MSG_SYSLOG_H_INCLUDED_ @@ -21,7 +21,8 @@ * External interface. */ extern void msg_syslog_init(const char *, int, int); -extern int msg_syslog_facility(const char *); +extern int msg_syslog_set_facility(const char *); +extern void msg_syslog_disable(void); /* LICENSE /* .ad @@ -32,6 +33,11 @@ extern int msg_syslog_facility(const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/mvect.c b/external/ibm-public/postfix/dist/src/util/mvect.c index 35c0f7d68d2..3c5646b17c7 100644 --- a/external/ibm-public/postfix/dist/src/util/mvect.c +++ b/external/ibm-public/postfix/dist/src/util/mvect.c @@ -1,4 +1,4 @@ -/* $NetBSD: mvect.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: mvect.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -56,6 +56,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -110,6 +115,5 @@ char *mvect_free(MVECT *vect) if (vect->wipe_fn) vect->wipe_fn(vect->ptr, vect->nelm); myfree(vect->ptr); - myfree((void *) vect); return (0); } diff --git a/external/ibm-public/postfix/dist/src/util/myaddrinfo.h b/external/ibm-public/postfix/dist/src/util/myaddrinfo.h index 899dd1309c5..34a6c8a0c31 100644 --- a/external/ibm-public/postfix/dist/src/util/myaddrinfo.h +++ b/external/ibm-public/postfix/dist/src/util/myaddrinfo.h @@ -1,4 +1,4 @@ -/* $NetBSD: myaddrinfo.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: myaddrinfo.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MYADDRINFO_H_INCLUDED_ #define _MYADDRINFO_H_INCLUDED_ @@ -221,6 +221,11 @@ extern void myaddrinfo_control(int,...); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/myflock.c b/external/ibm-public/postfix/dist/src/util/myflock.c index 7a4ca394031..c7cf261f284 100644 --- a/external/ibm-public/postfix/dist/src/util/myflock.c +++ b/external/ibm-public/postfix/dist/src/util/myflock.c @@ -1,4 +1,4 @@ -/* $NetBSD: myflock.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: myflock.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -16,7 +16,7 @@ /* myflock() locks or unlocks an entire open file. /* /* In the case of a blocking request, a call that fails due to -/* forseeable transient problems is retried once per second. +/* foreseeable transient problems is retried once per second. /* /* Arguments: /* .IP fd diff --git a/external/ibm-public/postfix/dist/src/util/myflock.h b/external/ibm-public/postfix/dist/src/util/myflock.h index e29e5b81d17..2ee154d0ce3 100644 --- a/external/ibm-public/postfix/dist/src/util/myflock.h +++ b/external/ibm-public/postfix/dist/src/util/myflock.h @@ -1,4 +1,4 @@ -/* $NetBSD: myflock.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: myflock.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MYFLOCK_H_INCLUDED_ #define _MYFLOCK_H_INCLUDED_ @@ -44,6 +44,11 @@ extern int WARN_UNUSED_RESULT myflock(int, int, int); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/mymalloc.c b/external/ibm-public/postfix/dist/src/util/mymalloc.c index 924f46be1c8..835dad61302 100644 --- a/external/ibm-public/postfix/dist/src/util/mymalloc.c +++ b/external/ibm-public/postfix/dist/src/util/mymalloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: mymalloc.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: mymalloc.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -74,6 +74,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System libraries. */ @@ -221,13 +226,17 @@ void myfree(void *ptr) char *mystrdup(const char *str) { + size_t len; + if (str == 0) msg_panic("mystrdup: null pointer argument"); #ifndef NO_SHARED_EMPTY_STRINGS if (*str == 0) return ((char *) empty_string); #endif - return (strcpy(mymalloc(strlen(str) + 1), str)); + if ((len = strlen(str) + 1) > SSIZE_T_MAX) + msg_panic("mystrdup: string length >= SSIZE_T_MAX"); + return (memcpy(mymalloc(len), str, len)); } /* mystrndup - save substring to heap */ diff --git a/external/ibm-public/postfix/dist/src/util/mymalloc.h b/external/ibm-public/postfix/dist/src/util/mymalloc.h index 1e158c482ff..7e2ddff8856 100644 --- a/external/ibm-public/postfix/dist/src/util/mymalloc.h +++ b/external/ibm-public/postfix/dist/src/util/mymalloc.h @@ -1,4 +1,4 @@ -/* $NetBSD: mymalloc.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: mymalloc.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ #ifndef _MALLOC_H_INCLUDED_ #define _MALLOC_H_INCLUDED_ @@ -10,8 +10,8 @@ /* memory management wrappers /* SYNOPSIS /* #include "mymalloc.h" - DESCRIPTION - .nf +/* DESCRIPTION +/* .nf /* * External interface. @@ -32,6 +32,11 @@ extern char *mymemdup(const void *, ssize_t); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/nbbio.c b/external/ibm-public/postfix/dist/src/util/nbbio.c index af6430d7e9c..8f527712a35 100644 --- a/external/ibm-public/postfix/dist/src/util/nbbio.c +++ b/external/ibm-public/postfix/dist/src/util/nbbio.c @@ -1,4 +1,4 @@ -/* $NetBSD: nbbio.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: nbbio.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -76,15 +76,17 @@ /* the named buffer pair, closes the stream, and destroys the /* buffer pair. /* -/* nbbio_enable_read() enables a read pseudothread for the -/* named buffer pair. It is an error to enable a read -/* pseudothread while the read buffer is full, or while a read -/* or write pseudothread is still enabled. +/* nbbio_enable_read() enables a read pseudothread (if one +/* does not already exist) for the named buffer pair, and +/* (re)starts the buffer pair's timer. It is an error to enable +/* a read pseudothread while the read buffer is full, or while +/* a write pseudothread is still enabled. /* -/* nbbio_enable_write() enables a write pseudothread for the -/* named buffer pair. It is an error to enable a write -/* pseudothread while the write buffer is empty, or while a -/* read or write pseudothread is still enabled. +/* nbbio_enable_write() enables a write pseudothread (if one +/* does not already exist) for the named buffer pair, and +/* (re)starts the buffer pair's timer. It is an error to enable +/* a write pseudothread while the write buffer is empty, or +/* while a read pseudothread is still enabled. /* /* nbbio_disable_readwrite() disables any read/write pseudothreads /* for the named buffer pair, including timeouts. To ensure @@ -133,6 +135,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -262,7 +269,7 @@ void nbbio_enable_read(NBBIO *np, int timeout) /* * Sanity checks. */ - if (np->flags & NBBIO_MASK_ACTIVE) + if (np->flags & (NBBIO_MASK_ACTIVE & ~NBBIO_FLAG_READ)) msg_panic("%s: socket fd=%d is enabled for %s", myname, np->fd, NBBIO_OP_NAME(np)); if (timeout <= 0) @@ -275,9 +282,11 @@ void nbbio_enable_read(NBBIO *np, int timeout) /* * Enable events. */ - event_enable_read(np->fd, nbbio_event, (void *) np); + if ((np->flags & NBBIO_FLAG_READ) == 0) { + event_enable_read(np->fd, nbbio_event, (void *) np); + np->flags |= NBBIO_FLAG_READ; + } event_request_timer(nbbio_event, (void *) np, timeout); - np->flags |= NBBIO_FLAG_READ; } /* nbbio_enable_write - enable writing from buffer to socket */ @@ -289,11 +298,11 @@ void nbbio_enable_write(NBBIO *np, int timeout) /* * Sanity checks. */ - if (np->flags & NBBIO_MASK_ACTIVE) + if (np->flags & (NBBIO_MASK_ACTIVE & ~NBBIO_FLAG_WRITE)) msg_panic("%s: socket fd=%d is enabled for %s", myname, np->fd, NBBIO_OP_NAME(np)); if (timeout <= 0) - msg_panic("%s: socket fd=%d bad timeout %d", + msg_panic("%s: socket fd=%d: bad timeout %d", myname, np->fd, timeout); if (np->write_pend <= 0) msg_panic("%s: socket fd=%d: empty write buffer", @@ -302,9 +311,11 @@ void nbbio_enable_write(NBBIO *np, int timeout) /* * Enable events. */ - event_enable_write(np->fd, nbbio_event, (void *) np); + if ((np->flags & NBBIO_FLAG_WRITE) == 0) { + event_enable_write(np->fd, nbbio_event, (void *) np); + np->flags |= NBBIO_FLAG_WRITE; + } event_request_timer(nbbio_event, (void *) np, timeout); - np->flags |= NBBIO_FLAG_WRITE; } /* nbbio_disable_readwrite - disable read/write/timer events */ diff --git a/external/ibm-public/postfix/dist/src/util/netstring.c b/external/ibm-public/postfix/dist/src/util/netstring.c index a3fa176a653..331b7552f97 100644 --- a/external/ibm-public/postfix/dist/src/util/netstring.c +++ b/external/ibm-public/postfix/dist/src/util/netstring.c @@ -1,4 +1,4 @@ -/* $NetBSD: netstring.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: netstring.c,v 1.3 2020/03/18 19:05:21 christos Exp $ */ /*++ /* NAME @@ -153,6 +153,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -198,6 +203,7 @@ ssize_t netstring_get_length(VSTREAM *stream) const char *myname = "netstring_get_length"; ssize_t len = 0; int ch; + int digit; for (;;) { switch (ch = VSTREAM_GETC(stream)) { @@ -211,10 +217,11 @@ ssize_t netstring_get_length(VSTREAM *stream) default: if (!ISDIGIT(ch)) netstring_except(stream, NETSTRING_ERR_FORMAT); - len = len * 10 + ch - '0'; - /* vstream_fread() would read zero bytes. Reject input anyway. */ - if (len < 0) + digit = ch - '0'; + if (len > SSIZE_T_MAX / 10 + || (len *= 10) > SSIZE_T_MAX - digit) netstring_except(stream, NETSTRING_ERR_SIZE); + len += digit; break; } } @@ -227,15 +234,9 @@ VSTRING *netstring_get_data(VSTREAM *stream, VSTRING *buf, ssize_t len) const char *myname = "netstring_get_data"; /* - * Allocate buffer space. - */ - VSTRING_RESET(buf); - VSTRING_SPACE(buf, len); - - /* * Read the payload and absorb the terminator. */ - if (vstream_fread(stream, STR(buf), len) != len) + if (vstream_fread_buf(stream, buf, len) != len) netstring_except(stream, vstream_ftimeout(stream) ? NETSTRING_ERR_TIME : NETSTRING_ERR_EOF); if (msg_verbose > 1) @@ -244,9 +245,8 @@ VSTRING *netstring_get_data(VSTREAM *stream, VSTRING *buf, ssize_t len) netstring_get_terminator(stream); /* - * Position the buffer. + * Return the buffer. */ - VSTRING_AT_OFFSET(buf, len); return (buf); } @@ -265,7 +265,7 @@ VSTRING *netstring_get(VSTREAM *stream, VSTRING *buf, ssize_t limit) ssize_t len; len = netstring_get_length(stream); - if (limit && len > limit) + if (ENFORCING_SIZE_LIMIT(limit) && len > limit) netstring_except(stream, NETSTRING_ERR_SIZE); netstring_get_data(stream, buf, len); return (buf); diff --git a/external/ibm-public/postfix/dist/src/util/peekfd.c b/external/ibm-public/postfix/dist/src/util/peekfd.c index a642825731f..a48fdc96e0b 100644 --- a/external/ibm-public/postfix/dist/src/util/peekfd.c +++ b/external/ibm-public/postfix/dist/src/util/peekfd.c @@ -1,4 +1,4 @@ -/* $NetBSD: peekfd.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: peekfd.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -30,6 +30,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/util/printable.c b/external/ibm-public/postfix/dist/src/util/printable.c index 0c2bb0db7ab..dea6b583c1e 100644 --- a/external/ibm-public/postfix/dist/src/util/printable.c +++ b/external/ibm-public/postfix/dist/src/util/printable.c @@ -1,4 +1,4 @@ -/* $NetBSD: printable.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: printable.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -13,6 +13,11 @@ /* char *printable(buffer, replacement) /* char *buffer; /* int replacement; +/* +/* char *printable_except(buffer, replacement, except) +/* char *buffer; +/* int replacement; +/* const char *except; /* DESCRIPTION /* printable() replaces non-printable characters /* in its input with the given replacement. @@ -26,6 +31,8 @@ /* .IP replacement /* Replacement value for characters in \fIbuffer\fR that do not /* pass the ASCII isprint(3) test or that are not valid UTF8. +/* .IP except +/* Null-terminated sequence of non-replaced ASCII characters. /* LICENSE /* .ad /* .fi @@ -35,12 +42,18 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ #include "sys_defs.h" #include <ctype.h> +#include <string.h> /* Utility library. */ @@ -48,8 +61,21 @@ int util_utf8_enable = 0; +/* printable - binary compatibility */ + +#undef printable + +char *printable(char *, int); + char *printable(char *string, int replacement) { + return (printable_except(string, replacement, (char *) 0)); +} + +/* printable_except - pass through printable or other preserved characters */ + +char *printable_except(char *string, int replacement, const char *except) +{ unsigned char *cp; int ch; @@ -59,7 +85,7 @@ char *printable(char *string, int replacement) */ cp = (unsigned char *) string; while ((ch = *cp) != 0) { - if (ISASCII(ch) && ISPRINT(ch)) { + 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) { diff --git a/external/ibm-public/postfix/dist/src/util/recv_pass_attr.c b/external/ibm-public/postfix/dist/src/util/recv_pass_attr.c index 5cfbe6fe686..b105dfe4636 100644 --- a/external/ibm-public/postfix/dist/src/util/recv_pass_attr.c +++ b/external/ibm-public/postfix/dist/src/util/recv_pass_attr.c @@ -1,4 +1,4 @@ -/* $NetBSD: recv_pass_attr.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: recv_pass_attr.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -39,6 +39,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ diff --git a/external/ibm-public/postfix/dist/src/util/sane_fsops.h b/external/ibm-public/postfix/dist/src/util/sane_fsops.h index 7a7d6ab1673..fa2c0f07e4c 100644 --- a/external/ibm-public/postfix/dist/src/util/sane_fsops.h +++ b/external/ibm-public/postfix/dist/src/util/sane_fsops.h @@ -1,4 +1,4 @@ -/* $NetBSD: sane_fsops.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: sane_fsops.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _SANE_FSOPS_H_ #define _SANE_FSOPS_H_ @@ -27,6 +27,11 @@ extern int WARN_UNUSED_RESULT sane_link(const char *, const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/sane_socketpair.h b/external/ibm-public/postfix/dist/src/util/sane_socketpair.h index 353a4d6c327..af039be0283 100644 --- a/external/ibm-public/postfix/dist/src/util/sane_socketpair.h +++ b/external/ibm-public/postfix/dist/src/util/sane_socketpair.h @@ -1,4 +1,4 @@ -/* $NetBSD: sane_socketpair.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: sane_socketpair.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _SANE_SOCKETPAIR_H_ #define _SANE_SOCKETPAIR_H_ @@ -26,6 +26,11 @@ extern int WARN_UNUSED_RESULT sane_socketpair(int, int, int, int *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/slmdb.c b/external/ibm-public/postfix/dist/src/util/slmdb.c index 80773ca1dea..96a4a752447 100644 --- a/external/ibm-public/postfix/dist/src/util/slmdb.c +++ b/external/ibm-public/postfix/dist/src/util/slmdb.c @@ -1,4 +1,4 @@ -/* $NetBSD: slmdb.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: slmdb.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -158,7 +158,7 @@ /* result value. /* .IP "CA_SLMDB_CTL_NOTIFY_FN(void (*)(void *, int, ...))" /* Call-back function pointer. The function is called to report -/* succesful error recovery. The arguments are the application +/* successful error recovery. The arguments are the application /* context, the MDB error code, and additional arguments that /* depend on the error code. Details are given in the section /* "ERROR RECOVERY". diff --git a/external/ibm-public/postfix/dist/src/util/split_qnameval.c b/external/ibm-public/postfix/dist/src/util/split_qnameval.c index 6fbd8731ade..b52b15bfc8f 100644 --- a/external/ibm-public/postfix/dist/src/util/split_qnameval.c +++ b/external/ibm-public/postfix/dist/src/util/split_qnameval.c @@ -1,4 +1,4 @@ -/* $NetBSD: split_qnameval.c,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: split_qnameval.c,v 1.2 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/stat_as.h b/external/ibm-public/postfix/dist/src/util/stat_as.h index 9846c480f35..024fe619ca7 100644 --- a/external/ibm-public/postfix/dist/src/util/stat_as.h +++ b/external/ibm-public/postfix/dist/src/util/stat_as.h @@ -1,4 +1,4 @@ -/* $NetBSD: stat_as.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: stat_as.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _STAT_AS_H_INCLUDED_ #define _STAT_AS_H_INCLUDED_ @@ -27,6 +27,11 @@ extern int WARN_UNUSED_RESULT stat_as(const char *, struct stat *, uid_t, gid_t) /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/stringops.h b/external/ibm-public/postfix/dist/src/util/stringops.h index 3035b372e59..96e2e61ec6a 100644 --- a/external/ibm-public/postfix/dist/src/util/stringops.h +++ b/external/ibm-public/postfix/dist/src/util/stringops.h @@ -1,4 +1,4 @@ -/* $NetBSD: stringops.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: stringops.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _STRINGOPS_H_INCLUDED_ #define _STRINGOPS_H_INCLUDED_ @@ -22,7 +22,7 @@ * External interface. */ extern int util_utf8_enable; -extern char *printable(char *, int); +extern char *printable_except(char *, int, const char *); extern char *neuter(char *, const char *, int); extern char *lowercase(char *); extern char *casefoldx(int, VSTRING *, const char *, ssize_t); @@ -34,6 +34,9 @@ extern char *mystrtok(char **, const char *); extern char *mystrtokq(char **, const char *, const char *); extern char *translit(char *, const char *, const char *); +#define printable(string, replacement) \ + printable_except((string), (replacement), (char *) 0) + #ifndef HAVE_BASENAME #define basename postfix_basename extern char *basename(const char *); @@ -48,6 +51,7 @@ extern int allprint(const char *); extern int allspace(const char *); 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 size_t balpar(const char *, const char *); extern char *WARN_UNUSED_RESULT extpar(char **, const char *, int); @@ -87,6 +91,11 @@ extern int strncasecmp_utf8x(int, const char *, const char *, ssize_t); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/sys_compat.c b/external/ibm-public/postfix/dist/src/util/sys_compat.c index a987a9c23f2..37c570098c1 100644 --- a/external/ibm-public/postfix/dist/src/util/sys_compat.c +++ b/external/ibm-public/postfix/dist/src/util/sys_compat.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_compat.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: sys_compat.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -19,6 +19,9 @@ /* const char *value; /* int clobber; /* +/* int unsetenv(name) +/* const char *name; +/* /* int seteuid(euid) /* uid_t euid; /* @@ -42,7 +45,7 @@ /* int af; /* const void *src; /* char *dst; -/* size_t size; +/* SOCKADDR_SIZE size; /* /* int inet_pton(af, src, dst) /* int af; @@ -60,6 +63,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -118,6 +126,27 @@ int setenv(const char *name, const char *value, int clobber) return (putenv(cp)); } +/* unsetenv - remove all instances of the name */ + +int unsetenv(const char *name) +{ + extern char **environ; + ssize_t name_len = strlen(name); + char **src_pp; + char **dst_pp; + + for (dst_pp = src_pp = environ; *src_pp; src_pp++, dst_pp++) { + if (strncmp(*src_pp, name, name_len) == 0 + && *(*src_pp + name_len) == '=') { + dst_pp--; + } else if (dst_pp != src_pp) { + *dst_pp = *src_pp; + } + } + *dst_pp = 0; + return (0); +} + #endif /* @@ -295,7 +324,7 @@ int closefrom(int lowfd) /* inet_ntop - convert binary address to printable address */ -const char *inet_ntop(int af, const void *src, char *dst, size_t size) +const char *inet_ntop(int af, const void *src, char *dst, SOCKADDR_SIZE size) { const unsigned char *addr; char buffer[sizeof("255.255.255.255")]; diff --git a/external/ibm-public/postfix/dist/src/util/sys_defs.h b/external/ibm-public/postfix/dist/src/util/sys_defs.h index d37435ce550..89fe2bab843 100644 --- a/external/ibm-public/postfix/dist/src/util/sys_defs.h +++ b/external/ibm-public/postfix/dist/src/util/sys_defs.h @@ -1,4 +1,4 @@ -/* $NetBSD: sys_defs.h,v 1.11 2017/02/20 05:43:12 rin Exp $ */ +/* $NetBSD: sys_defs.h,v 1.12 2020/03/18 19:05:22 christos Exp $ */ #ifndef _SYS_DEFS_H_INCLUDED_ #define _SYS_DEFS_H_INCLUDED_ @@ -21,6 +21,10 @@ * directory. Adding support for a new system type means updating the * makedefs script, and adding a section below for the new system. */ +#ifdef SUNOS5 +#define _SVID_GETTOD /* Solaris 2.5, XSH4.2 versus SVID */ +#endif +#include <sys/types.h> /* * 4.4BSD and close derivatives. @@ -28,6 +32,7 @@ #if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4) \ || defined(FREEBSD5) || defined(FREEBSD6) || defined(FREEBSD7) \ || defined(FREEBSD8) || defined(FREEBSD9) || defined(FREEBSD10) \ + || defined(FREEBSD11) \ || defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \ || defined(OPENBSD2) || defined(OPENBSD3) || defined(OPENBSD4) \ || defined(OPENBSD5) || defined(OPENBSD6) \ @@ -36,7 +41,6 @@ || defined(NETBSD7) \ || defined(EKKOBSD1) || defined(DRAGONFLY) #define SUPPORTED -#include <sys/types.h> #include <sys/param.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short @@ -127,7 +131,7 @@ #define HAS_FUTIMES /* XXX maybe earlier */ #endif -#if (defined(OpenBSD) && OpenBSD >= 199608) +#if (defined(OpenBSD) && OpenBSD >= 199608 && OpenBSD < 201105) #define PREFERRED_RAND_SOURCE "dev:/dev/arandom" /* XXX earlier */ #endif @@ -220,7 +224,6 @@ */ #if defined(RHAPSODY5) || defined(MACOSX) #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define USE_PATHS_H @@ -278,7 +281,6 @@ #ifndef FD_SETSIZE #define FD_SETSIZE 96 #endif -#include <sys/types.h> #define _PATH_MAILDIR "/var/spool/mail" #define _PATH_BSHELL "/bin/sh" #define _PATH_DEFPATH "/bin:/usr/bin:/usr/ucb" @@ -326,7 +328,6 @@ extern int h_errno; */ #ifdef OSF1 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define MISSING_SETENV @@ -367,7 +368,6 @@ extern int opterr; /* XXX use <getopt.h> */ */ #ifdef SUNOS4 #define SUPPORTED -#include <sys/types.h> #include <memory.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short @@ -411,6 +411,7 @@ extern int opterr; #define size_t unsigned #define ssize_t int #define getsid getpgrp +#define NO_SNPRINTF #endif /* @@ -418,11 +419,8 @@ extern int opterr; */ #ifdef SUNOS5 #define SUPPORTED -#define _SVID_GETTOD /* Solaris 2.5, XSH4.2 versus SVID */ -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short -#define MISSING_SETENV #define _PATH_MAILDIR "/var/mail" #define _PATH_BSHELL "/bin/sh" #define _PATH_DEFPATH "/usr/bin:/usr/ucb" @@ -500,7 +498,6 @@ extern int opterr; */ #ifdef UW7 /* UnixWare 7 */ #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define _PATH_MAILDIR "/var/mail" @@ -531,7 +528,6 @@ extern int opterr; #ifdef UW21 /* UnixWare 2.1.x */ #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define _PATH_MAILDIR "/var/mail" @@ -564,7 +560,6 @@ extern int opterr; */ #if defined(AIX5) || defined(AIX6) #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define MISSING_SETENV @@ -627,7 +622,6 @@ extern int opterr; #ifdef AIX4 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define MISSING_SETENV @@ -673,7 +667,6 @@ extern int initgroups(const char *, int); #ifdef AIX3 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define MISSING_SETENV @@ -716,7 +709,6 @@ extern int initgroups(const char *, int); */ #if defined(IRIX5) || defined(IRIX6) #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define MISSING_SETENV @@ -760,9 +752,8 @@ extern int initgroups(const char *, int); /* * LINUX. */ -#if defined(LINUX2) || defined(LINUX3) || defined(LINUX4) +#if defined(LINUX2) || defined(LINUX3) || defined(LINUX4) || defined(LINUX5) #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #include <features.h> @@ -795,11 +786,14 @@ extern int initgroups(const char *, int); #define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) __GLIBC_PREREQ(maj, min) #else #define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) \ - ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) + (defined(__GLIBC__) && \ + ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))) #endif #if HAVE_GLIBC_API_VERSION_SUPPORT(2, 1) #define SOCKADDR_SIZE socklen_t #define SOCKOPT_SIZE socklen_t +#else +#define NO_SNPRINTF #endif #ifndef NO_IPV6 #define HAS_IPV6 @@ -816,7 +810,7 @@ extern int initgroups(const char *, int); #define KERNEL_VERSION(a,b,c) (LINUX_VERSION_CODE + 1) #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) \ - || (__GLIBC__ < 2) + || (defined(__GLIBC__) && __GLIBC__ < 2) #define CANT_USE_SEND_RECV_MSG #define DEF_SMTP_CACHE_DEMAND 0 #else @@ -841,7 +835,6 @@ extern int initgroups(const char *, int); #ifdef LINUX1 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define USE_PATHS_H @@ -877,7 +870,6 @@ extern int initgroups(const char *, int); */ #ifdef GNU0 #define SUPPORTED -#include <sys/types.h> #include <features.h> #define USE_PATHS_H #define HAS_FCNTL_LOCK @@ -943,7 +935,6 @@ extern int initgroups(const char *, int); #ifdef HPUX11 #define SUPPORTED #define USE_SIG_RETURN -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define HAS_DBM @@ -983,7 +974,6 @@ extern int h_errno; /* <netdb.h> imports too much stuff */ #ifdef HPUX10 #define SUPPORTED #define USE_SIG_RETURN -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define HAS_DBM @@ -1023,7 +1013,6 @@ extern int h_errno; /* <netdb.h> imports too much stuff */ #ifdef HPUX9 #define SUPPORTED #define USE_SIG_RETURN -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define HAS_DBM @@ -1066,7 +1055,6 @@ extern int h_errno; */ #ifdef NEXTSTEP3 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define HAS_DBM @@ -1121,7 +1109,6 @@ typedef unsigned short mode_t; */ #ifdef OPENSTEP4 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define HAS_DBM @@ -1173,7 +1160,6 @@ typedef unsigned short mode_t; #ifdef ReliantUnix543 #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define MISSING_SETENV @@ -1205,7 +1191,6 @@ extern int opterr; /* XXX use <getopt.h> */ #ifdef DCOSX1 /* Siemens Pyramid */ #define SUPPORTED -#include <sys/types.h> #define UINT32_TYPE unsigned int #define UINT16_TYPE unsigned short #define _PATH_MAILDIR "/var/mail" @@ -1235,7 +1220,6 @@ extern int opterr; /* XXX use <getopt.h> */ #ifdef SCO5 #define SUPPORTED -#include <sys/types.h> #include <sys/socket.h> extern int h_errno; @@ -1334,6 +1318,12 @@ extern int dup2_pass_on_exec(int oldd, int newd); #endif #define OPTIND (optind > 0 ? optind : 1) +#if !defined(__UCLIBC__) && !defined(NO_RES_SEND) +#define HAVE_RES_SEND +#else +#undef HAVE_RES_SEND +#endif + /* * Check for required but missing definitions. */ @@ -1362,10 +1352,11 @@ extern int dup2_pass_on_exec(int oldd, int newd); */ #ifndef __NetBSD__ #ifndef HAS_IPV6 +#include <sys/socket.h> #define EMULATE_IPV4_ADDRINFO #define MISSING_INET_PTON #define MISSING_INET_NTOP -extern const char *inet_ntop(int, const void *, char *, size_t); +extern const char *inet_ntop(int, const void *, char *, SOCKADDR_SIZE); extern int inet_pton(int, const char *, void *); #endif @@ -1693,18 +1684,26 @@ typedef int pid_t; /* * Bit banging!! There is no official constant that defines the INT_MAX - * equivalent of the off_t type. Wietse came up with the following macro - * that works as long as off_t is some two's complement number. - * - * Note, however, that C99 permits signed integer representations other than - * two's complement. + * equivalent for off_t, ssize_t, etc. Wietse came up with the following + * macro that works as long as off_t, ssize_t, etc. use one's or two's + * complement logic (that is, the maximum value is binary 01...1). Don't use + * right-shift for signed types: the result is implementation-defined. */ #include <limits.h> -#define __MAXINT__(T) ((T) (((((T) 1) << ((sizeof(T) * CHAR_BIT) - 1)) ^ ((T) -1)))) +#define __MAXINT__(T) ((T) ~(((T) 1) << ((sizeof(T) * CHAR_BIT) - 1))) #ifndef OFF_T_MAX #define OFF_T_MAX __MAXINT__(off_t) #endif +#ifndef SSIZE_T_MAX +#define SSIZE_T_MAX __MAXINT__(ssize_t) +#endif + + /* + * Consistent enforcement of size limits. + */ +#define ENFORCING_SIZE_LIMIT(param) ((param) > 0) + /* * Setting globals like h_errno can be problematic when Postfix is linked * with multi-threaded libraries. @@ -1795,6 +1794,11 @@ extern int REMOVE(const char *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/timed_wait.h b/external/ibm-public/postfix/dist/src/util/timed_wait.h index c9abbd731ba..8bb1d01f0b5 100644 --- a/external/ibm-public/postfix/dist/src/util/timed_wait.h +++ b/external/ibm-public/postfix/dist/src/util/timed_wait.h @@ -1,4 +1,4 @@ -/* $NetBSD: timed_wait.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: timed_wait.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _TIMED_WAIT_H_INCLUDED_ #define _TIMED_WAIT_H_INCLUDED_ @@ -27,6 +27,11 @@ extern int WARN_UNUSED_RESULT timed_waitpid(pid_t, WAIT_STATUS_T *, int, int); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/unix_dgram_connect.c b/external/ibm-public/postfix/dist/src/util/unix_dgram_connect.c index 1c50ba59cde..8f6d067a2f6 100644 --- a/external/ibm-public/postfix/dist/src/util/unix_dgram_connect.c +++ b/external/ibm-public/postfix/dist/src/util/unix_dgram_connect.c @@ -1,4 +1,4 @@ -/* $NetBSD: unix_dgram_connect.c,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: unix_dgram_connect.c,v 1.2 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/unix_dgram_listen.c b/external/ibm-public/postfix/dist/src/util/unix_dgram_listen.c index 233745b1aa2..67a7ed74659 100644 --- a/external/ibm-public/postfix/dist/src/util/unix_dgram_listen.c +++ b/external/ibm-public/postfix/dist/src/util/unix_dgram_listen.c @@ -1,4 +1,4 @@ -/* $NetBSD: unix_dgram_listen.c,v 1.1.1.1 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: unix_dgram_listen.c,v 1.2 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/unsafe.c b/external/ibm-public/postfix/dist/src/util/unsafe.c index 27e02f32dff..25504af14a4 100644 --- a/external/ibm-public/postfix/dist/src/util/unsafe.c +++ b/external/ibm-public/postfix/dist/src/util/unsafe.c @@ -1,4 +1,4 @@ -/* $NetBSD: unsafe.c,v 1.1.1.2 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: unsafe.c,v 1.2 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/vbuf.c b/external/ibm-public/postfix/dist/src/util/vbuf.c index 714cb262fbf..e89b6e6836e 100644 --- a/external/ibm-public/postfix/dist/src/util/vbuf.c +++ b/external/ibm-public/postfix/dist/src/util/vbuf.c @@ -1,4 +1,4 @@ -/* $NetBSD: vbuf.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vbuf.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -142,6 +142,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -171,7 +176,8 @@ int vbuf_unget(VBUF *bp, int ch) int vbuf_get(VBUF *bp) { - return (bp->get_ready(bp) ? VBUF_EOF : VBUF_GET(bp)); + return (bp->get_ready(bp) ? + ((bp->flags |= VBUF_FLAG_EOF), VBUF_EOF) : VBUF_GET(bp)); } /* vbuf_put - handle write buffer full condition */ diff --git a/external/ibm-public/postfix/dist/src/util/vbuf_print.c b/external/ibm-public/postfix/dist/src/util/vbuf_print.c index 52686c557cb..bf8c1ea1536 100644 --- a/external/ibm-public/postfix/dist/src/util/vbuf_print.c +++ b/external/ibm-public/postfix/dist/src/util/vbuf_print.c @@ -1,4 +1,4 @@ -/* $NetBSD: vbuf_print.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vbuf_print.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -43,6 +43,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -56,11 +61,12 @@ #include <stdio.h> /* sprintf() prototype */ #include <float.h> /* range of doubles */ #include <errno.h> -#include <limits.h> /* CHAR_BIT */ +#include <limits.h> /* CHAR_BIT, INT_MAX */ /* Application-specific. */ #include "msg.h" +#include "mymalloc.h" #include "vbuf.h" #include "vstring.h" #include "vbuf_print.h" @@ -70,16 +76,19 @@ * in 4.4 BSD). However, that functionality is not widely available, and I * have no plans to maintain a complete 4.4 BSD *sprintf() alternative. * - * This means we're stuck with plain old ugly sprintf() for all non-trivial - * conversions. We cannot use snprintf() even if it is available, because - * that routine truncates output, and we want everything. Therefore, it is - * up to us to ensure that sprintf() output always stays within bounds. + * Postfix vbuf_print() was implemented when many mainstream systems had no + * usable snprintf() implementation (usable means: return the length, + * excluding terminator, that the output would have if the buffer were large + * enough). For example, GLIBC before 2.1 (1999) snprintf() did not + * distinguish between formatting error and buffer size error, while SUN had + * no snprintf() implementation before Solaris 2.6 (1997). * - * Due to the complexity of *printf() format strings we cannot easily predict - * how long results will be without actually doing the conversions. A trick - * used by some people is to print to a temporary file and to read the - * result back. In programs that do a lot of formatting, that might be too - * expensive. + * For the above reasons, vbuf_print() was implemented with sprintf() and a + * generously-sized output buffer. Current vbuf_print() implementations use + * snprintf(), and report an error if the output does not fit (in that case, + * the old sprintf()-based implementation would have had a buffer overflow + * vulnerability). The old implementation is still available for building + * Postfix on ancient systems. * * Guessing the output size of a string (%s) conversion is not hard. The * problem is with numerical results. Instead of making an accurate guess we @@ -97,23 +106,43 @@ * Helper macros... Note that there is no need to check the result from * VSTRING_SPACE() because that always succeeds or never returns. */ -#define VBUF_SKIP(bp) { \ +#ifndef NO_SNPRINTF +#define VBUF_SNPRINTF(bp, sz, fmt, arg) do { \ + ssize_t _ret; \ + if (VBUF_SPACE((bp), (sz)) != 0) \ + return (bp); \ + _ret = snprintf((char *) (bp)->ptr, (bp)->cnt, (fmt), (arg)); \ + if (_ret < 0) \ + msg_panic("%s: output error for '%s'", myname, mystrdup(fmt)); \ + if (_ret >= (bp)->cnt) \ + msg_panic("%s: output for '%s' exceeds space %ld", \ + myname, mystrdup(fmt), (long) (bp)->cnt); \ + VBUF_SKIP(bp); \ + } while (0) +#else +#define VBUF_SNPRINTF(bp, sz, fmt, arg) do { \ + if (VBUF_SPACE((bp), (sz)) != 0) \ + return (bp); \ + sprintf((char *) (bp)->ptr, (fmt), (arg)); \ + VBUF_SKIP(bp); \ + } while (0) +#endif + +#define VBUF_SKIP(bp) do { \ while ((bp)->cnt > 0 && *(bp)->ptr) \ (bp)->ptr++, (bp)->cnt--; \ - } + } while (0) -#define VSTRING_ADDNUM(vp, n) { \ - VSTRING_SPACE(vp, INT_SPACE); \ - sprintf(vstring_end(vp), "%d", n); \ - VBUF_SKIP(&vp->vbuf); \ - } +#define VSTRING_ADDNUM(vp, n) do { \ + VBUF_SNPRINTF(&(vp)->vbuf, INT_SPACE, "%d", n); \ + } while (0) -#define VBUF_STRCAT(bp, s) { \ +#define VBUF_STRCAT(bp, s) do { \ unsigned char *_cp = (unsigned char *) (s); \ int _ch; \ while ((_ch = *_cp++) != 0) \ VBUF_PUT((bp), _ch); \ - } + } while (0) /* vbuf_print - format string, vsprintf-like interface */ @@ -153,7 +182,7 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) * strings, since we are ging to let sprintf() do the hard work. * In regular expression notation, we recognize: * - * %-?0?([0-9]+|\*)?\.(?[0-9]+|\*)?l?[a-zA-Z] + * %-?+?0?([0-9]+|\*)?(\.([0-9]+|\*))?l?[a-zA-Z] * * which includes some combinations that do not make sense. Garbage * in, garbage out. @@ -168,34 +197,48 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) VSTRING_ADDCH(fmt, *cp++); if (*cp == '*') { /* dynamic field width */ width = va_arg(ap, int); - VSTRING_ADDNUM(fmt, width); + if (width < 0) { + msg_warn("%s: bad width %d in %.50s", + myname, width, format); + width = 0; + } else + VSTRING_ADDNUM(fmt, width); cp++; } else { /* hard-coded field width */ for (width = 0; ch = *cp, ISDIGIT(ch); cp++) { - width = width * 10 + ch - '0'; + int digit = ch - '0'; + + if (width > INT_MAX / 10 + || (width *= 10) > INT_MAX - digit) + msg_panic("%s: bad width %d... in %.50s", + myname, width, format); + width += digit; VSTRING_ADDCH(fmt, ch); } } - if (width < 0) { - msg_warn("%s: bad width %d in %.50s", myname, width, format); - width = 0; - } if (*cp == '.') { /* width/precision separator */ VSTRING_ADDCH(fmt, *cp++); if (*cp == '*') { /* dynamic precision */ prec = va_arg(ap, int); - VSTRING_ADDNUM(fmt, prec); + if (prec < 0) { + msg_warn("%s: bad precision %d in %.50s", + myname, prec, format); + prec = -1; + } else + VSTRING_ADDNUM(fmt, prec); cp++; } else { /* hard-coded precision */ for (prec = 0; ch = *cp, ISDIGIT(ch); cp++) { - prec = prec * 10 + ch - '0'; + int digit = ch - '0'; + + if (prec > INT_MAX / 10 + || (prec *= 10) > INT_MAX - digit) + msg_panic("%s: bad precision %d... in %.50s", + myname, prec, format); + prec += digit; VSTRING_ADDCH(fmt, ch); } } - if (prec < 0) { - msg_warn("%s: bad precision %d in %.50s", myname, prec, format); - prec = -1; - } } else { prec = -1; } @@ -214,46 +257,48 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) */ switch (*cp) { case 's': /* string-valued argument */ + if (long_flag) + msg_panic("%s: %%l%c is not supported", myname, *cp); s = va_arg(ap, char *); if (prec >= 0 || (width > 0 && width > strlen(s))) { - if (VBUF_SPACE(bp, (width > prec ? width : prec) + INT_SPACE)) - return (bp); - sprintf((char *) bp->ptr, vstring_str(fmt), s); - VBUF_SKIP(bp); + VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE, + vstring_str(fmt), s); } else { VBUF_STRCAT(bp, s); } break; case 'c': /* integral-valued argument */ + if (long_flag) + msg_panic("%s: %%l%c is not supported", myname, *cp); + /* FALLTHROUGH */ case 'd': case 'u': case 'o': case 'x': case 'X': - if (VBUF_SPACE(bp, (width > prec ? width : prec) + INT_SPACE)) - return (bp); if (long_flag) - sprintf((char *) bp->ptr, vstring_str(fmt), va_arg(ap, long)); + VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE, + vstring_str(fmt), va_arg(ap, long)); else - sprintf((char *) bp->ptr, vstring_str(fmt), va_arg(ap, int)); - VBUF_SKIP(bp); + VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE, + vstring_str(fmt), va_arg(ap, int)); break; case 'e': /* float-valued argument */ case 'f': case 'g': - if (VBUF_SPACE(bp, (width > prec ? width : prec) + DBL_SPACE)) - return (bp); - sprintf((char *) bp->ptr, vstring_str(fmt), va_arg(ap, double)); - VBUF_SKIP(bp); + /* C99 *printf ignore the 'l' modifier. */ + VBUF_SNPRINTF(bp, (width > prec ? width : prec) + DBL_SPACE, + vstring_str(fmt), va_arg(ap, double)); break; case 'm': + /* Ignore the 'l' modifier, width and precision. */ VBUF_STRCAT(bp, strerror(saved_errno)); break; case 'p': - if (VBUF_SPACE(bp, (width > prec ? width : prec) + PTR_SPACE)) - return (bp); - sprintf((char *) bp->ptr, vstring_str(fmt), va_arg(ap, char *)); - VBUF_SKIP(bp); + if (long_flag) + msg_panic("%s: %%l%c is not supported", myname, *cp); + VBUF_SNPRINTF(bp, (width > prec ? width : prec) + PTR_SPACE, + vstring_str(fmt), va_arg(ap, char *)); break; default: /* anything else is bad */ msg_panic("vbuf_print: unknown format type: %c", *cp); @@ -264,3 +309,78 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap) } return (bp); } + +#ifdef TEST +#include <argv.h> +#include <msg_vstream.h> +#include <vstring.h> +#include <vstring_vstream.h> + +int main(int argc, char **argv) +{ + VSTRING *ibuf = vstring_alloc(100); + + msg_vstream_init(argv[0], VSTREAM_ERR); + + while (vstring_fgets_nonl(ibuf, VSTREAM_IN)) { + ARGV *args = argv_split(vstring_str(ibuf), CHARS_SPACE); + char *cp; + + if (args->argc == 0 || *(cp = args->argv[0]) == '#') { + /* void */ ; + } else if (args->argc != 2 || *cp != '%') { + msg_warn("usage: format number"); + } else { + char *fmt = cp++; + int lflag; + + /* Determine the vstring_sprintf() argument type. */ + cp += strspn(cp, "+-*0123456789."); + if ((lflag = (*cp == 'l')) != 0) + cp++; + if (cp[1] != 0) { + msg_warn("bad format: \"%s\"", fmt); + } else { + VSTRING *obuf = vstring_alloc(1); + char *val = args->argv[1]; + + /* Test the worst-case memory allocation. */ +#ifdef CA_VSTRING_CTL_EXACT + vstring_ctl(obuf, CA_VSTRING_CTL_EXACT, CA_VSTRING_CTL_END); +#endif + switch (*cp) { + case 'c': + case 'd': + case 'o': + case 'u': + case 'x': + case 'X': + if (lflag) + vstring_sprintf(obuf, fmt, atol(val)); + else + vstring_sprintf(obuf, fmt, atoi(val)); + msg_info("\"%s\"", vstring_str(obuf)); + break; + case 's': + vstring_sprintf(obuf, fmt, val); + msg_info("\"%s\"", vstring_str(obuf)); + break; + case 'f': + case 'g': + vstring_sprintf(obuf, fmt, atof(val)); + msg_info("\"%s\"", vstring_str(obuf)); + break; + default: + msg_warn("bad format: \"%s\"", fmt); + break; + } + vstring_free(obuf); + } + } + argv_free(args); + } + vstring_free(ibuf); + return (0); +} + +#endif diff --git a/external/ibm-public/postfix/dist/src/util/vstream.c b/external/ibm-public/postfix/dist/src/util/vstream.c index 06d8fab45e5..53af5bab72e 100644 --- a/external/ibm-public/postfix/dist/src/util/vstream.c +++ b/external/ibm-public/postfix/dist/src/util/vstream.c @@ -1,4 +1,4 @@ -/* $NetBSD: vstream.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vstream.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -17,6 +17,15 @@ /* int fd; /* int flags; /* +/* VSTREAM *vstream_memopen(string, flags) +/* VSTRING *string; +/* int flags; +/* +/* VSTREAM *vstream_memreopen(stream, string, flags) +/* VSTREAM *stream; +/* VSTRING *string; +/* int flags; +/* /* int vstream_fclose(stream) /* VSTREAM *stream; /* @@ -71,7 +80,17 @@ /* /* ssize_t vstream_fwrite(stream, buf, len) /* VSTREAM *stream; -/* const void *buf; +/* void *buf; +/* ssize_t len; +/* +/* ssize_t vstream_fread_app(stream, buf, len) +/* VSTREAM *stream; +/* VSTRING *buf; +/* ssize_t len; +/* +/* ssize_t vstream_fread_buf(stream, buf, len) +/* VSTREAM *stream; +/* VSTRING *buf; /* ssize_t len; /* /* void vstream_control(stream, name, ...) @@ -192,6 +211,21 @@ /* stream with it. The \fIflags\fR argument specifies how the file /* was opened. vstream_fdopen() either succeeds or never returns. /* +/* vstream_memopen() opens a VSTRING as a stream. The \fIflags\fR +/* argument must specify one of O_RDONLY, O_WRONLY, or O_APPEND. +/* vstream_memopen() either succeeds or never returns. Streams +/* opened with vstream_memopen() have limitations: they can't +/* be opened in read/write mode, they can't seek beyond the +/* end of the VSTRING, and they don't support vstream_control() +/* methods that manipulate buffers, file descriptors, or I/O +/* functions. After a VSTRING is opened for writing, its content +/* will be in an indeterminate state while the stream is open, +/* and will be null-terminated when the stream is closed. +/* +/* vstream_memreopen() reopens a memory stream. When the +/* \fIstream\fR argument is a null pointer, the behavior is that +/* of vstream_memopen(). +/* /* vstream_fclose() closes the named buffered stream. The result /* is 0 in case of success, VSTREAM_EOF in case of problems. /* vstream_fclose() reports the same errors as vstream_ferror(). @@ -265,6 +299,19 @@ /* transferred. A short count is returned in case of end-of-file /* or error conditions. /* +/* vstream_fread_buf() resets the buffer write position, +/* allocates space for the specified number of bytes in the +/* buffer, reads the bytes from the specified VSTREAM, and +/* adjusts the buffer write position. The buffer is NOT +/* null-terminated. The result value is as with vstream_fread(). +/* NOTE: do not skip calling vstream_fread_buf() when len == 0. +/* This function has side effects including resetting the buffer +/* write position, and skipping the call would invalidate the +/* buffer state. +/* +/* vstream_fread_app() is like vstream_fread_buf() but appends +/* to existing buffer content, instead of writing over it. +/* /* vstream_control() allows the user to fine tune the behavior of /* the specified stream. The arguments are a list of macros with /* zero or more arguments, terminated with CA_VSTREAM_CTL_END @@ -367,7 +414,7 @@ /* vstream_feof() returns non-zero when a previous operation on the /* specified stream caused an end-of-file condition. /* Although further read requests after EOF may complete -/* succesfully, vstream_feof() will keep returning non-zero +/* successfully, vstream_feof() will keep returning non-zero /* until vstream_clearerr() is called for that stream. /* /* vstream_ferror() returns non-zero when a previous operation on the @@ -433,6 +480,8 @@ /* The deadline feature is activated. /* .IP VSTREAM_FLAG_DOUBLE /* The double-buffering feature is activated. +/* .IP VSTREAM_FLAG_MEMORY +/* The stream is connected to a VSTRING buffer. /* DIAGNOSTICS /* Panics: interface violations. Fatal errors: out of memory. /* SEE ALSO @@ -451,6 +500,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -467,6 +521,8 @@ /* Utility library. */ +#define VSTRING_INTERNAL + #include "mymalloc.h" #include "msg.h" #include "vbuf_print.h" @@ -982,6 +1038,8 @@ static int vstream_buf_space(VBUF *bp, ssize_t want) */ if (bp->put_ready == 0) msg_panic("%s: read-only stream", myname); + if (want < 0) + msg_panic("%s: bad length %ld", myname, (long) want); switch (bp->flags & (VSTREAM_FLAG_READ | VSTREAM_FLAG_WRITE)) { case VSTREAM_FLAG_READ: /* change direction */ bp->flags &= ~VSTREAM_FLAG_READ; @@ -1091,6 +1149,29 @@ off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence) VBUF *bp = &stream->buf; /* + * TODO: support data length (data length != buffer length). Without data + * length information, vstream_fseek() would break vstream_fflush() for + * memory streams. + */ + if (stream->buf.flags & VSTREAM_FLAG_MEMORY) { +#ifdef PENDING_VSTREAM_FSEEK_FOR_MEMORY + if (whence == SEEK_CUR) + offset += (bp->ptr - bp->data); + else if (whence == SEEK_END) + offset += bp->len; + if (offset < 0 || offset > bp->data_len) { + errno = EINVAL; + return (-1); + } + VSTREAM_BUF_AT_OFFSET(bp, offset); + return (offset); +#else + errno = EOPNOTSUPP; + return (-1); +#endif + } + + /* * Flush any unwritten output. Discard any unread input. Position the * buffer at the end, so that the next GET or PUT operation triggers a * buffer boundary action. @@ -1154,6 +1235,12 @@ off_t vstream_ftell(VSTREAM *stream) VBUF *bp = &stream->buf; /* + * Special case for memory buffer. + */ + if (stream->buf.flags & VSTREAM_FLAG_MEMORY) + return (bp->ptr - bp->data); + + /* * Shave an unnecessary syscall. */ if (bp->flags & VSTREAM_FLAG_NSEEK) { @@ -1194,6 +1281,28 @@ off_t vstream_ftell(VSTREAM *stream) return (stream->offset); } +/* vstream_subopen - initialize everything except buffers and I/O handlers */ + +static VSTREAM *vstream_subopen(void) +{ + VSTREAM *stream; + + /* Note: memset() is not a portable way to initialize non-integer types. */ + stream = (VSTREAM *) mymalloc(sizeof(*stream)); + stream->offset = 0; + stream->path = 0; + stream->pid = 0; + stream->waitpid_fn = 0; + stream->timeout = 0; + stream->context = 0; + stream->jbuf = 0; + stream->iotime.tv_sec = stream->iotime.tv_usec = 0; + stream->time_limit.tv_sec = stream->time_limit.tv_usec = 0; + stream->req_bufsize = 0; + stream->vstring = 0; + return (stream); +} + /* vstream_fdopen - add buffering to pre-opened stream */ VSTREAM *vstream_fdopen(int fd, int flags) @@ -1213,21 +1322,11 @@ VSTREAM *vstream_fdopen(int fd, int flags) * have a really ugly interface with lots of mostly-unused arguments (can * you say VMS?). */ - stream = (VSTREAM *) mymalloc(sizeof(*stream)); + stream = vstream_subopen(); stream->fd = fd; stream->read_fn = VSTREAM_CAN_READ(flags) ? (VSTREAM_RW_FN) timed_read : 0; stream->write_fn = VSTREAM_CAN_WRITE(flags) ? (VSTREAM_RW_FN) timed_write : 0; vstream_buf_init(&stream->buf, flags); - stream->offset = 0; - stream->path = 0; - stream->pid = 0; - stream->waitpid_fn = 0; - stream->timeout = 0; - stream->context = 0; - stream->jbuf = 0; - stream->iotime.tv_sec = stream->iotime.tv_usec = 0; - stream->time_limit.tv_sec = stream->time_limit.tv_usec = 0; - stream->req_bufsize = 0; return (stream); } @@ -1251,6 +1350,25 @@ VSTREAM *vstream_fopen(const char *path, int flags, mode_t mode) int vstream_fflush(VSTREAM *stream) { + + /* + * With VSTRING, the write pointer must be positioned behind the end of + * data. Without knowing the actual data length, VSTREAM can't support + * vstream_fseek() for memory streams, because vstream_fflush() would + * leave the VSTRING in a broken state. + */ + if (stream->buf.flags & VSTREAM_FLAG_MEMORY) { + if (stream->buf.flags & VSTREAM_FLAG_WRITE) { + VSTRING *string = stream->vstring; + +#ifdef PENDING_VSTREAM_FSEEK_FOR_MEMORY + VSTREAM_BUF_AT_OFFSET(&stream->buf, stream->buf.data_len); +#endif + memcpy(&string->vbuf, &stream->buf, sizeof(stream->buf)); + VSTRING_TERMINATE(string); + } + return (0); + } if ((stream->buf.flags & VSTREAM_FLAG_READ_DOUBLE) == VSTREAM_FLAG_READ_DOUBLE && stream->write_buf.len > stream->write_buf.cnt) @@ -1272,7 +1390,9 @@ int vstream_fclose(VSTREAM *stream) */ if (stream->pid != 0) msg_panic("vstream_fclose: stream has process"); - if ((stream->buf.flags & VSTREAM_FLAG_WRITE_DOUBLE) != 0 && stream->fd >= 0) + if ((stream->buf.flags & VSTREAM_FLAG_MEMORY) + || ((stream->buf.flags & VSTREAM_FLAG_WRITE_DOUBLE) != 0 + && stream->fd >= 0)) vstream_fflush(stream); /* Do not remove: vstream_fdclose() depends on this error test. */ err = vstream_ferror(stream); @@ -1288,7 +1408,8 @@ int vstream_fclose(VSTREAM *stream) } else { if (stream->fd >= 0) err |= close(stream->fd); - vstream_buf_wipe(&stream->buf); + if ((stream->buf.flags & VSTREAM_FLAG_MEMORY) == 0) + vstream_buf_wipe(&stream->buf); } if (stream->path) myfree(stream->path); @@ -1362,6 +1483,33 @@ int vstream_fputs(const char *str, VSTREAM *stream) return (0); } +/* vstream_fread_buf - unformatted read to VSTRING */ + +ssize_t vstream_fread_buf(VSTREAM *fp, VSTRING *vp, ssize_t len) +{ + ssize_t ret; + + VSTRING_RESET(vp); + VSTRING_SPACE(vp, len); + ret = vstream_fread(fp, vstring_str(vp), len); + if (ret > 0) + VSTRING_AT_OFFSET(vp, ret); + return (ret); +} + +/* vstream_fread_app - unformatted read to VSTRING */ + +ssize_t vstream_fread_app(VSTREAM *fp, VSTRING *vp, ssize_t len) +{ + ssize_t ret; + + VSTRING_SPACE(vp, len); + ret = vstream_fread(fp, vstring_end(vp), len); + if (ret > 0) + VSTRING_AT_OFFSET(vp, VSTRING_LEN(vp) + ret); + return (ret); +} + /* vstream_control - fine control */ void vstream_control(VSTREAM *stream, int name,...) @@ -1375,7 +1523,18 @@ void vstream_control(VSTREAM *stream, int name,...) #define SWAP(type,a,b) do { type temp = (a); (a) = (b); (b) = (temp); } while (0) + /* + * A crude 'allow' filter for memory streams. + */ + int memory_ops = + ((1 << VSTREAM_CTL_END) | (1 << VSTREAM_CTL_CONTEXT) + | (1 << VSTREAM_CTL_PATH) | (1 << VSTREAM_CTL_EXCEPT)); + for (va_start(ap, name); name != VSTREAM_CTL_END; name = va_arg(ap, int)) { + if ((stream->buf.flags & VSTREAM_FLAG_MEMORY) + && (memory_ops & (1 << name)) == 0) + msg_panic("%s: memory stream does not support VSTREAM_CTL_%d", + VSTREAM_PATH(stream), name); switch (name) { case VSTREAM_CTL_READ_FN: stream->read_fn = va_arg(ap, VSTREAM_RW_FN); @@ -1596,14 +1755,49 @@ const char *vstream_peek_data(VSTREAM *vp) } } +/* vstream_memopen - open a VSTRING */ + +VSTREAM *vstream_memreopen(VSTREAM *stream, VSTRING *string, int flags) +{ + if (stream == 0) + stream = vstream_subopen(); + else if ((stream->buf.flags & VSTREAM_FLAG_MEMORY) == 0) + msg_panic("vstream_memreopen: cannot reopen non-memory stream"); + stream->fd = -1; + stream->read_fn = 0; + stream->write_fn = 0; + stream->vstring = string; + memcpy(&stream->buf, &stream->vstring->vbuf, sizeof(stream->buf)); + stream->buf.flags |= VSTREAM_FLAG_MEMORY; + switch (VSTREAM_ACC_MASK(flags)) { + case O_RDONLY: + stream->buf.flags |= VSTREAM_FLAG_READ; + stream->buf.len = stream->buf.ptr - stream->buf.data; + VSTREAM_BUF_AT_OFFSET(&stream->buf, 0); + break; + case O_WRONLY: + stream->buf.flags |= VSTREAM_FLAG_WRITE; + VSTREAM_BUF_AT_OFFSET(&stream->buf, 0); + break; + case O_APPEND: + stream->buf.flags |= VSTREAM_FLAG_WRITE; + VSTREAM_BUF_AT_END(&stream->buf); + break; + default: + msg_panic("vstream_memopen: flags must be one of " + "O_RDONLY, O_WRONLY, or O_APPEND"); + } + return (stream); +} + #ifdef TEST static void copy_line(ssize_t bufsize) { int c; - vstream_control(VSTREAM_IN, VSTREAM_CTL_BUFSIZE(bufsize), VSTREAM_CTL_END); - vstream_control(VSTREAM_OUT, VSTREAM_CTL_BUFSIZE(bufsize), VSTREAM_CTL_END); + vstream_control(VSTREAM_IN, CA_VSTREAM_CTL_BUFSIZE(bufsize), VSTREAM_CTL_END); + vstream_control(VSTREAM_OUT, CA_VSTREAM_CTL_BUFSIZE(bufsize), VSTREAM_CTL_END); while ((c = VSTREAM_GETC(VSTREAM_IN)) != VSTREAM_EOF) { VSTREAM_PUTC(c, VSTREAM_OUT); if (c == '\n') @@ -1614,8 +1808,58 @@ static void copy_line(ssize_t bufsize) static void printf_number(void) { - vstream_printf("%d\n", __MAXINT__(int)); + vstream_printf("%d\n", 1234567890); + vstream_fflush(VSTREAM_OUT); +} + +static void do_memory_stream(void) +{ + VSTRING *buf = vstring_alloc(1); + VSTREAM *fp = vstream_memopen(buf, O_WRONLY); + +#ifdef PENDING_VSTREAM_FSEEK_FOR_MEMORY + off_t offset; + +#endif + int ch; + + vstream_fprintf(fp, "hallo world\n"); + if (vstream_fflush(fp)) + msg_fatal("vstream_fflush: %m"); + vstream_printf("final memory stream write offset: %ld\n", + (long) vstream_ftell(fp)); +#ifdef PENDING_VSTREAM_FSEEK_FOR_MEMORY + vstream_fflush(fp); + vstream_printf("buffer size: %ld, content: %s", + (long) VSTRING_LEN(buf), vstring_str(buf)); + if ((offset = vstream_fseek(fp, 1, SEEK_SET)) != 1) + msg_panic("unexpected vstream_fseek return: %ld, expected: %ld", + (long) offset, (long) 1); + VSTREAM_PUTC('e', fp); +#endif + vstream_fclose(fp); + + vstream_printf("buffer size: %ld, content: %s", + (long) VSTRING_LEN(buf), vstring_str(buf)); + vstream_fflush(VSTREAM_OUT); + + fp = vstream_memopen(buf, O_RDONLY); + vstream_printf("reading memory stream: "); + while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) + VSTREAM_PUTCHAR(ch); +#ifdef PENDING_VSTREAM_FSEEK_FOR_MEMORY + vstream_printf("reading memory stream from offset 6: "); + if ((offset = vstream_fseek(fp, 6, SEEK_SET)) != 6) + msg_panic("unexpected vstream_fseek return: %ld, expected: %ld", + (long) offset, (long) 6); + while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) + VSTREAM_PUTCHAR(ch); +#endif + vstream_printf("final memory stream read offset: %ld\n", + (long) vstream_ftell(fp)); vstream_fflush(VSTREAM_OUT); + vstream_fclose(fp); + vstring_free(buf); } /* @@ -1632,6 +1876,8 @@ int main(int argc, char **argv) copy_line(2); /* two-byte read/write */ copy_line(1); /* two-byte read/write */ printf_number(); /* multi-byte write */ + do_memory_stream(); + exit(0); } diff --git a/external/ibm-public/postfix/dist/src/util/vstream.h b/external/ibm-public/postfix/dist/src/util/vstream.h index 0e17db095b1..d0c368a6c7a 100644 --- a/external/ibm-public/postfix/dist/src/util/vstream.h +++ b/external/ibm-public/postfix/dist/src/util/vstream.h @@ -1,4 +1,4 @@ -/* $NetBSD: vstream.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vstream.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _VSTREAM_H_INCLUDED_ #define _VSTREAM_H_INCLUDED_ @@ -46,7 +46,7 @@ typedef struct VSTREAM { VBUF buf; /* generic intelligent buffer */ int fd; /* file handle, no 256 limit */ VSTREAM_RW_FN read_fn; /* buffer fill action */ - VSTREAM_RW_FN write_fn; /* buffer fill action */ + VSTREAM_RW_FN write_fn; /* buffer flush action */ ssize_t req_bufsize; /* requested read/write buffer size */ void *context; /* application context */ off_t offset; /* cached seek info */ @@ -57,10 +57,11 @@ typedef struct VSTREAM { VBUF write_buf; /* write buffer (double-buffered) */ pid_t pid; /* vstream_popen/close() */ VSTREAM_WAITPID_FN waitpid_fn; /* vstream_popen/close() */ - int timeout; /* read/write timout */ + int timeout; /* read/write timeout */ VSTREAM_JMP_BUF *jbuf; /* exception handling */ struct timeval iotime; /* time of last fill/flush */ struct timeval time_limit; /* read/write time limit */ + struct VSTRING *vstring; /* memory-backed stream */ } VSTREAM; extern VSTREAM vstream_fstd[]; /* pre-defined streams */ @@ -80,12 +81,14 @@ extern VSTREAM vstream_fstd[]; /* pre-defined streams */ #define VSTREAM_FLAG_FIXED VBUF_FLAG_FIXED /* fixed-size buffer */ #define VSTREAM_FLAG_BAD VBUF_FLAG_BAD +/* Flags 1<<24 and above are reserved for VSTRING. */ #define VSTREAM_FLAG_READ (1<<8) /* read buffer */ #define VSTREAM_FLAG_WRITE (1<<9) /* write buffer */ #define VSTREAM_FLAG_SEEK (1<<10) /* seek info valid */ #define VSTREAM_FLAG_NSEEK (1<<11) /* can't seek this file */ #define VSTREAM_FLAG_DOUBLE (1<<12) /* double buffer */ #define VSTREAM_FLAG_DEADLINE (1<<13) /* deadline active */ +#define VSTREAM_FLAG_MEMORY (1<<14) /* internal stream */ #define VSTREAM_PURGE_READ (1<<0) /* flush unread data */ #define VSTREAM_PURGE_WRITE (1<<1) /* flush unwritten data */ @@ -131,6 +134,8 @@ extern int vstream_fdclose(VSTREAM *); #define vstream_fstat(vp, fl) ((vp)->buf.flags & (fl)) +extern ssize_t vstream_fread_buf(VSTREAM *, struct VSTRING *, ssize_t); +extern ssize_t vstream_fread_app(VSTREAM *, struct VSTRING *, ssize_t); extern void vstream_control(VSTREAM *, int,...); /* Legacy API: type-unchecked arguments, internal use. */ @@ -259,6 +264,13 @@ extern int vstream_tweak_tcp(VSTREAM *); #define vstream_flags(stream) ((const int) (stream)->buf.flags) + /* + * Read/write VSTRING memory. + */ +#define vstream_memopen(string, flags) \ + vstream_memreopen((VSTREAM *) 0, (string), (flags)) +VSTREAM *vstream_memreopen(VSTREAM *, struct VSTRING *, int); + /* LICENSE /* .ad /* .fi @@ -268,6 +280,11 @@ extern int vstream_tweak_tcp(VSTREAM *); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/vstream_tweak.c b/external/ibm-public/postfix/dist/src/util/vstream_tweak.c index 151f1318848..ac85d992d42 100644 --- a/external/ibm-public/postfix/dist/src/util/vstream_tweak.c +++ b/external/ibm-public/postfix/dist/src/util/vstream_tweak.c @@ -1,4 +1,4 @@ -/* $NetBSD: vstream_tweak.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vstream_tweak.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -34,6 +34,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -126,12 +131,20 @@ int vstream_tweak_tcp(VSTREAM *fp) * stream buffer size to less than VSTREAM_BUFSIZE, when the request is * made before the first stream read or write operation. We don't want to * reduce the buffer size. + * + * As of 20190820 we increase the mss size multiplier from 2x to 4x, because + * some LINUX loopback TCP stacks report an MSS of 21845 which is 3x + * smaller than the MTU of 65536. Even with a VSTREAM buffer 2x the + * reported MSS size, performance would suck due to Nagle or delayed ACK + * delays. */ #define EFF_BUFFER_SIZE(fp) (vstream_req_bufsize(fp) ? \ vstream_req_bufsize(fp) : VSTREAM_BUFSIZE) #ifdef CA_VSTREAM_CTL_BUFSIZE - if (mss > EFF_BUFFER_SIZE(fp) / 2) { + if (mss > EFF_BUFFER_SIZE(fp) / 4) { + if (mss < INT_MAX / 2) + mss *= 2; if (mss < INT_MAX / 2) mss *= 2; vstream_control(fp, diff --git a/external/ibm-public/postfix/dist/src/util/vstring.c b/external/ibm-public/postfix/dist/src/util/vstring.c index 6d1d505e2ed..a5da3bd79ae 100644 --- a/external/ibm-public/postfix/dist/src/util/vstring.c +++ b/external/ibm-public/postfix/dist/src/util/vstring.c @@ -1,4 +1,4 @@ -/* $NetBSD: vstring.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vstring.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -42,6 +42,10 @@ /* VSTRING *vp; /* ssize_t len; /* +/* VSTRING *vstring_set_payload_size(vp, len) +/* VSTRING *vp; +/* ssize_t len; +/* /* void VSTRING_RESET(vp) /* VSTRING *vp; /* @@ -141,6 +145,9 @@ /* length would be exceeded, the program simulates a memory /* allocation problem (i.e. it terminates through msg_fatal()). /* This fuctionality is currently unimplemented. +/* .IP "CA_VSTRING_CTL_EXACT (no argument)" +/* Allocate the requested amounts, instead of rounding up. +/* This should be used for tests only. /* .IP "CA_VSTRING_CTL_END (no argument)" /* Specifies the end of the argument list. Forgetting to terminate /* the argument list may cause the program to crash. @@ -179,6 +186,15 @@ /* The operation has no effect when the string is shorter. /* The string is not null-terminated. /* +/* vstring_set_payload_size() sets the number of 'used' bytes +/* in the named buffer's metadata. This determines the buffer +/* write position and the VSTRING_LEN() result. The payload +/* size must be within the closed range [0, number of allocated +/* bytes]. The typical usage is to request buffer space with +/* VSTRING_SPACE(), to use some non-VSTRING operations to write +/* to the buffer, and to call vstring_set_payload_size() to +/* update buffer metadata, perhaps followed by VSTRING_TERMINATE(). +/* /* VSTRING_RESET() is a macro that resets the write position of its /* string argument to the very beginning. Note that VSTRING_RESET() /* is an unsafe macro that evaluates some arguments more than once. @@ -265,6 +281,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System libraries. */ @@ -277,6 +298,8 @@ /* Utility library. */ +#define VSTRING_INTERNAL + #include "mymalloc.h" #include "msg.h" #include "vbuf_print.h" @@ -298,13 +321,17 @@ static void vstring_extend(VBUF *bp, ssize_t incr) * * The length overflow tests here and in vstring_alloc() should protect us * against all length overflow problems within vstring library routines. - * (The tests are redundant as long as mymalloc() and myrealloc() reject - * negative length parameters). + * + * Safety net: add a gratuitous null terminator so that C-style string + * operations won't scribble past the end. */ - new_len = bp->len + (bp->len > incr ? bp->len : incr); - if (new_len <= bp->len) + if ((bp->flags & VSTRING_FLAG_EXACT) == 0 && bp->len > incr) + incr = bp->len; + if (bp->len > SSIZE_T_MAX - incr - 1) msg_fatal("vstring_extend: length overflow"); - bp->data = (unsigned char *) myrealloc((void *) bp->data, new_len); + new_len = bp->len + incr; + bp->data = (unsigned char *) myrealloc((void *) bp->data, new_len + 1); + bp->data[new_len] = 0; bp->len = new_len; bp->ptr = bp->data + used; bp->cnt = bp->len - used; @@ -314,14 +341,14 @@ static void vstring_extend(VBUF *bp, ssize_t incr) static int vstring_buf_get_ready(VBUF *unused_buf) { - msg_panic("vstring_buf_get: write-only buffer"); + return (VBUF_EOF); /* be VSTREAM-friendly */ } /* vstring_buf_put_ready - vbuf callback for write buffer full condition */ static int vstring_buf_put_ready(VBUF *bp) { - vstring_extend(bp, 0); + vstring_extend(bp, 1); return (0); } @@ -344,19 +371,23 @@ VSTRING *vstring_alloc(ssize_t len) { VSTRING *vp; - if (len < 1) + /* + * Safety net: add a gratuitous null terminator so that C-style string + * operations won't scribble past the end. + */ + if (len < 1 || len > SSIZE_T_MAX - 1) msg_panic("vstring_alloc: bad length %ld", (long) len); vp = (VSTRING *) mymalloc(sizeof(*vp)); vp->vbuf.flags = 0; vp->vbuf.len = 0; - vp->vbuf.data = (unsigned char *) mymalloc(len); + vp->vbuf.data = (unsigned char *) mymalloc(len + 1); + vp->vbuf.data[len] = 0; vp->vbuf.len = len; VSTRING_RESET(vp); vp->vbuf.data[0] = 0; vp->vbuf.get_ready = vstring_buf_get_ready; vp->vbuf.put_ready = vstring_buf_put_ready; vp->vbuf.space = vstring_buf_space; - vp->maxlen = 0; return (vp); } @@ -382,10 +413,8 @@ void vstring_ctl(VSTRING *vp,...) switch (code) { default: msg_panic("vstring_ctl: unknown code: %d", code); - case VSTRING_CTL_MAXLEN: - vp->maxlen = va_arg(ap, ssize_t); - if (vp->maxlen < 0) - msg_panic("vstring_ctl: bad max length %ld", (long) vp->maxlen); + case VSTRING_CTL_EXACT: + vp->vbuf.flags |= VSTRING_FLAG_EXACT; break; } } @@ -408,6 +437,18 @@ VSTRING *vstring_truncate(VSTRING *vp, ssize_t len) return (vp); } +/* vstring_set_payload_size - public version of VSTRING_AT_OFFSET */ + +VSTRING *vstring_set_payload_size(VSTRING *vp, ssize_t len) +{ + if (len < 0 || len > vp->vbuf.len) + msg_panic("vstring_set_payload_size: invalid offset: %ld", (long) len); + if (vp->vbuf.data[vp->vbuf.len] != 0) + msg_panic("vstring_set_payload_size: no safety null byte"); + VSTRING_AT_OFFSET(vp, len); + return (vp); +} + /* vstring_strcpy - copy string */ VSTRING *vstring_strcpy(VSTRING *vp, const char *src) @@ -575,7 +616,6 @@ VSTRING *vstring_import(char *str) vp->vbuf.get_ready = vstring_buf_get_ready; vp->vbuf.put_ready = vstring_buf_put_ready; vp->vbuf.space = vstring_buf_space; - vp->maxlen = 0; return (vp); } @@ -657,7 +697,18 @@ VSTRING *vstring_sprintf_prepend(VSTRING *vp, const char *format,...) int main(int argc, char **argv) { VSTRING *vp = vstring_alloc(1); + int n; + /* + * Report the location of the gratuitous null terminator. + */ + for (n = 1; n <= 5; n++) { + VSTRING_ADDCH(vp, 'x'); + printf("payload/buffer size %d/%ld, strlen() %ld\n", + n, (long) (vp)->vbuf.len, (long) strlen(vstring_str(vp))); + } + + VSTRING_RESET(vp); while (argc-- > 0) { vstring_strcat(vp, *argv++); vstring_strcat(vp, "."); diff --git a/external/ibm-public/postfix/dist/src/util/vstring.h b/external/ibm-public/postfix/dist/src/util/vstring.h index bb238afb2a9..4d88b61891c 100644 --- a/external/ibm-public/postfix/dist/src/util/vstring.h +++ b/external/ibm-public/postfix/dist/src/util/vstring.h @@ -1,4 +1,4 @@ -/* $NetBSD: vstring.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vstring.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _VSTRING_H_INCLUDED_ #define _VSTRING_H_INCLUDED_ @@ -30,12 +30,12 @@ */ typedef struct VSTRING { VBUF vbuf; - ssize_t maxlen; } VSTRING; extern VSTRING *vstring_alloc(ssize_t); extern void vstring_ctl(VSTRING *,...); extern VSTRING *vstring_truncate(VSTRING *, ssize_t); +extern VSTRING *vstring_set_payload_size(VSTRING *, ssize_t); extern VSTRING *vstring_free(VSTRING *); extern VSTRING *vstring_strcpy(VSTRING *, const char *); extern VSTRING *vstring_strncpy(VSTRING *, const char *, ssize_t); @@ -53,15 +53,18 @@ extern char *vstring_export(VSTRING *); extern VSTRING *vstring_import(char *); /* Legacy API: constant plus type-unchecked argument. */ -#define VSTRING_CTL_MAXLEN 1 +#define VSTRING_CTL_EXACT 2 #define VSTRING_CTL_END 0 /* Safer API: type-checked arguments. */ #define CA_VSTRING_CTL_END VSTRING_CTL_END -#define CA_VSTRING_CTL_MAXLEN(val) VSTRING_CTL_MAXLEN, CHECK_VAL(VSTRING_CTL, ssize_t, (val)) +#define CA_VSTRING_CTL_EXACT VSTRING_CTL_EXACT CHECK_VAL_HELPER_DCL(VSTRING_CTL, ssize_t); +/* Flags 24..31 are reserved for VSTRING. */ +#define VSTRING_FLAG_EXACT (1<<24) /* exact allocation for tests */ + /* * Macros. Unsafe macros have UPPERCASE names. */ @@ -70,8 +73,6 @@ CHECK_VAL_HELPER_DCL(VSTRING_CTL, ssize_t); #define VSTRING_LEN(vp) ((ssize_t) ((vp)->vbuf.ptr - (vp)->vbuf.data)) #define vstring_end(vp) ((char *) (vp)->vbuf.ptr) #define VSTRING_TERMINATE(vp) do { \ - if ((vp)->vbuf.cnt <= 0) \ - VSTRING_SPACE((vp),1); \ *(vp)->vbuf.ptr = 0; \ } while (0) #define VSTRING_RESET(vp) do { \ @@ -89,10 +90,12 @@ CHECK_VAL_HELPER_DCL(VSTRING_CTL, ssize_t); * The following macro is not part of the public interface, because it can * really screw up a buffer by positioning past allocated memory. */ +#ifdef VSTRING_INTERNAL #define VSTRING_AT_OFFSET(vp, offset) do { \ (vp)->vbuf.ptr = (vp)->vbuf.data + (offset); \ (vp)->vbuf.cnt = (vp)->vbuf.len - (offset); \ } while (0) +#endif extern VSTRING *vstring_vsprintf(VSTRING *, const char *, va_list); extern VSTRING *vstring_vsprintf_append(VSTRING *, const char *, va_list); @@ -113,6 +116,11 @@ extern VSTRING *vstring_vsprintf_append(VSTRING *, const char *, va_list); /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/vstring_vstream.c b/external/ibm-public/postfix/dist/src/util/vstring_vstream.c index 72501c5566a..db7a69cd250 100644 --- a/external/ibm-public/postfix/dist/src/util/vstring_vstream.c +++ b/external/ibm-public/postfix/dist/src/util/vstring_vstream.c @@ -1,4 +1,4 @@ -/* $NetBSD: vstring_vstream.c,v 1.1.1.3 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: vstring_vstream.c,v 1.2 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/dist/src/util/vstring_vstream.h b/external/ibm-public/postfix/dist/src/util/vstring_vstream.h index 7df6047f551..a387ae91b27 100644 --- a/external/ibm-public/postfix/dist/src/util/vstring_vstream.h +++ b/external/ibm-public/postfix/dist/src/util/vstring_vstream.h @@ -1,4 +1,4 @@ -/* $NetBSD: vstring_vstream.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: vstring_vstream.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _VSTRING_VSTREAM_H_INCLUDED_ #define _VSTRING_VSTREAM_H_INCLUDED_ @@ -21,12 +21,34 @@ /* * External interface. */ -extern int WARN_UNUSED_RESULT vstring_get(VSTRING *, VSTREAM *); -extern int WARN_UNUSED_RESULT vstring_get_nonl(VSTRING *, VSTREAM *); -extern int WARN_UNUSED_RESULT vstring_get_null(VSTRING *, VSTREAM *); -extern int WARN_UNUSED_RESULT vstring_get_bound(VSTRING *, VSTREAM *, ssize_t); -extern int WARN_UNUSED_RESULT vstring_get_nonl_bound(VSTRING *, VSTREAM *, ssize_t); -extern int WARN_UNUSED_RESULT vstring_get_null_bound(VSTRING *, VSTREAM *, ssize_t); +#define VSTRING_GET_FLAG_NONE (0) +#define VSTRING_GET_FLAG_APPEND (1<<1) /* append instead of overwrite */ + +extern int WARN_UNUSED_RESULT vstring_get_flags(VSTRING *, VSTREAM *, int); +extern int WARN_UNUSED_RESULT vstring_get_flags_nonl(VSTRING *, VSTREAM *, int); +extern int WARN_UNUSED_RESULT vstring_get_flags_null(VSTRING *, VSTREAM *, int); +extern int WARN_UNUSED_RESULT vstring_get_flags_bound(VSTRING *, VSTREAM *, int, ssize_t); +extern int WARN_UNUSED_RESULT vstring_get_flags_nonl_bound(VSTRING *, VSTREAM *, int, ssize_t); +extern int WARN_UNUSED_RESULT vstring_get_flags_null_bound(VSTRING *, VSTREAM *, int, ssize_t); + + /* + * Convenience aliases for most use cases. + */ +#define vstring_get(string, stream) \ + vstring_get_flags((string), (stream), VSTRING_GET_FLAG_NONE) +#define vstring_get_nonl(string, stream) \ + vstring_get_flags_nonl((string), (stream), VSTRING_GET_FLAG_NONE) +#define vstring_get_null(string, stream) \ + vstring_get_flags_null((string), (stream), VSTRING_GET_FLAG_NONE) + +#define vstring_get_bound(string, stream, size) \ + vstring_get_flags_bound((string), (stream), VSTRING_GET_FLAG_NONE, size) +#define vstring_get_nonl_bound(string, stream, size) \ + vstring_get_flags_nonl_bound((string), (stream), \ + VSTRING_GET_FLAG_NONE, size) +#define vstring_get_null_bound(string, stream, size) \ + vstring_get_flags_null_bound((string), (stream), \ + VSTRING_GET_FLAG_NONE, size) /* * Backwards compatibility for code that still uses the vstring_fgets() @@ -52,6 +74,11 @@ extern int WARN_UNUSED_RESULT vstring_get_null_bound(VSTRING *, VSTREAM *, ssize /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ #endif diff --git a/external/ibm-public/postfix/dist/src/util/watchdog.c b/external/ibm-public/postfix/dist/src/util/watchdog.c index 39c7fa24885..9ffa1ace99a 100644 --- a/external/ibm-public/postfix/dist/src/util/watchdog.c +++ b/external/ibm-public/postfix/dist/src/util/watchdog.c @@ -1,4 +1,4 @@ -/* $NetBSD: watchdog.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: watchdog.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -76,6 +76,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -218,6 +223,8 @@ WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context) msg_fatal("%s: pipe: %m", myname); non_blocking(watchdog_pipe[0], NON_BLOCKING); non_blocking(watchdog_pipe[1], NON_BLOCKING); + close_on_exec(watchdog_pipe[0], CLOSE_ON_EXEC); /* Fix 20190126 */ + close_on_exec(watchdog_pipe[1], CLOSE_ON_EXEC); /* Fix 20190126 */ event_enable_read(watchdog_pipe[0], watchdog_read, (void *) 0); } #endif diff --git a/external/ibm-public/postfix/dist/src/verify/verify.c b/external/ibm-public/postfix/dist/src/verify/verify.c index ae8ceff5b83..f00b65d2404 100644 --- a/external/ibm-public/postfix/dist/src/verify/verify.c +++ b/external/ibm-public/postfix/dist/src/verify/verify.c @@ -1,4 +1,4 @@ -/* $NetBSD: verify.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: verify.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -57,7 +57,8 @@ /* non-Postfix directory is redirected to the Postfix-owned /* \fBdata_directory\fR, and a warning is logged. /* DIAGNOSTICS -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* BUGS /* Address verification probe messages add additional traffic /* to the mail queue. @@ -157,6 +158,12 @@ /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. +/* .PP +/* Available in Postfix version 3.2 and later: +/* .IP "\fBenable_idna2003_compatibility (no)\fR" +/* Enable 'transitional' compatibility between IDNA2003 and IDNA2008, +/* when converting UTF-8 domain names to/from the ASCII form that is +/* used for DNS lookups. /* MISCELLANEOUS CONTROLS /* .ad /* .fi @@ -178,13 +185,18 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.3 and later: +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. /* SEE ALSO /* smtpd(8), Postfix SMTP server /* cleanup(8), enqueue Postfix message /* postconf(5), configuration parameters -/* syslogd(5), system logging +/* postlogd(8), Postfix logging +/* syslogd(8), system logging /* README FILES /* .ad /* .fi @@ -391,6 +403,7 @@ static void verify_update_service(VSTREAM *client_stream) || STATUS_FROM_RAW_ENTRY(raw_data) != DEL_RCPT_STAT_OK) { probed = 0; updated = (long) time((time_t *) 0); + printable(STR(text), '?'); verify_make_entry(buf, addr_status, probed, updated, STR(text)); if (msg_verbose) msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s", diff --git a/external/ibm-public/postfix/dist/src/virtual/mailbox.c b/external/ibm-public/postfix/dist/src/virtual/mailbox.c index 3b268a94d51..615775877ec 100644 --- a/external/ibm-public/postfix/dist/src/virtual/mailbox.c +++ b/external/ibm-public/postfix/dist/src/virtual/mailbox.c @@ -1,4 +1,4 @@ -/* $NetBSD: mailbox.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: mailbox.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -36,6 +36,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* System library. */ @@ -134,7 +139,7 @@ static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) VAR_STRICT_MBOX_OWNER); } else { if (vstream_fseek(mp->fp, (off_t) 0, SEEK_END) < 0) - msg_fatal("%s: seek queue file %s: %m", + msg_fatal("%s: seek mailbox file %s: %m", myname, VSTREAM_PATH(mp->fp)); mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp, copy_flags, "\n", why); diff --git a/external/ibm-public/postfix/dist/src/virtual/virtual.c b/external/ibm-public/postfix/dist/src/virtual/virtual.c index b22d9f6abb0..44a53a7e36f 100644 --- a/external/ibm-public/postfix/dist/src/virtual/virtual.c +++ b/external/ibm-public/postfix/dist/src/virtual/virtual.c @@ -1,4 +1,4 @@ -/* $NetBSD: virtual.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: virtual.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -135,7 +135,8 @@ /* recipient is over disk quota. In all other cases, mail for /* an existing recipient is deferred and a warning is logged. /* -/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* Problems and transactions are logged to \fBsyslogd\fR(8) +/* or \fBpostlogd\fR(8). /* Corrupted message files are marked so that the queue /* manager can move them to the \fBcorrupt\fR queue afterwards. /* @@ -206,15 +207,17 @@ /* RESOURCE AND RATE CONTROLS /* .ad /* .fi +/* .IP "\fBvirtual_mailbox_limit (51200000)\fR" +/* The maximal size in bytes of an individual \fBvirtual\fR(8) mailbox or +/* maildir file, or zero (no limit). +/* .PP +/* Implemented in the qmgr(8) daemon: /* .IP "\fBvirtual_destination_concurrency_limit ($default_destination_concurrency_limit)\fR" /* The maximal number of parallel deliveries to the same destination /* via the virtual message delivery transport. /* .IP "\fBvirtual_destination_recipient_limit ($default_destination_recipient_limit)\fR" /* The maximal number of recipients per message for the virtual /* message delivery transport. -/* .IP "\fBvirtual_mailbox_limit (51200000)\fR" -/* The maximal size in bytes of an individual \fBvirtual\fR(8) mailbox or -/* maildir file, or zero (no limit). /* MISCELLANEOUS CONTROLS /* .ad /* .fi @@ -245,18 +248,32 @@ /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" -/* The mail system name that is prepended to the process name in syslog -/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .PP /* Available in Postfix version 3.0 and later: /* .IP "\fBvirtual_delivery_status_filter ($default_delivery_status_filter)\fR" /* Optional filter for the \fBvirtual\fR(8) delivery agent to change the /* delivery status code or explanatory text of successful or unsuccessful /* deliveries. +/* .PP +/* Available in Postfix version 3.3 and later: +/* .IP "\fBenable_original_recipient (yes)\fR" +/* Enable support for the original recipient address after an +/* address is rewritten to a different address (for example with +/* aliasing or with canonical mapping). +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .PP +/* 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.). /* SEE ALSO /* qmgr(8), queue manager /* bounce(8), delivery status reports /* postconf(5), configuration parameters +/* postlogd(8), Postfix logging /* syslogd(8), system logging /* README_FILES /* Use "\fBpostconf readme_directory\fR" or @@ -493,9 +510,12 @@ static void pre_init(char *unused_name, char **unused_argv) * because that prohibits the delivery agent from updating the queue * file. */ - if (var_virt_mailbox_limit) { - if (var_virt_mailbox_limit < var_message_limit || var_message_limit == 0) - msg_fatal("main.cf configuration error: %s is smaller than %s", + if (ENFORCING_SIZE_LIMIT(var_virt_mailbox_limit)) { + if (!ENFORCING_SIZE_LIMIT(var_message_limit)) + msg_fatal("configuration error: %s is limited but %s is " + "unlimited", VAR_VIRT_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT); + if (var_virt_mailbox_limit < var_message_limit) + msg_fatal("configuration error: %s is smaller than %s", VAR_VIRT_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT); set_file_limit(var_virt_mailbox_limit); } diff --git a/external/ibm-public/postfix/dist/src/xsasl/xsasl.h b/external/ibm-public/postfix/dist/src/xsasl/xsasl.h index b473a72c213..6f9758b42e8 100644 --- a/external/ibm-public/postfix/dist/src/xsasl/xsasl.h +++ b/external/ibm-public/postfix/dist/src/xsasl/xsasl.h @@ -1,4 +1,4 @@ -/* $NetBSD: xsasl.h,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: xsasl.h,v 1.3 2020/03/18 19:05:22 christos Exp $ */ #ifndef _XSASL_H_INCLUDED_ #define _XSASL_H_INCLUDED_ @@ -48,8 +48,11 @@ typedef struct XSASL_SERVER { */ typedef struct XSASL_SERVER_CREATE_ARGS { VSTREAM *stream; + int addr_family; const char *server_addr; + const char *server_port; const char *client_addr; + const char *client_port; const char *service; const char *user_realm; const char *security_options; @@ -66,9 +69,10 @@ extern ARGV *xsasl_server_types(void); #define xsasl_server_create(impl, args) \ (impl)->create((impl), (args)) -#define XSASL_SERVER_CREATE(impl, args, a1, a2, a3, a4, a5, a6, a7) \ +#define XSASL_SERVER_CREATE(impl, args, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ xsasl_server_create((impl), (((args)->a1), ((args)->a2), ((args)->a3), \ - ((args)->a4), ((args)->a5), ((args)->a6), ((args)->a7), (args))) + ((args)->a4), ((args)->a5), ((args)->a6), ((args)->a7), ((args)->a8), \ + ((args)->a9), ((args)->a10), (args))) #define xsasl_server_done(impl) (impl)->done((impl)); /* diff --git a/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_client.c b/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_client.c index 94ec8b088d1..b69c909ac98 100644 --- a/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_client.c +++ b/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_client.c @@ -1,4 +1,4 @@ -/* $NetBSD: xsasl_cyrus_client.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: xsasl_cyrus_client.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -51,6 +51,11 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA /*--*/ /* @@ -486,7 +491,7 @@ static int xsasl_cyrus_client_first(XSASL_CLIENT *xp, &enc_length_out)) != SASL_OK) msg_panic("%s: sasl_encode64 botch: %s", myname, xsasl_cyrus_strerror(sasl_status)); - VSTRING_AT_OFFSET(init_resp, enc_length_out); /* XXX */ + vstring_set_payload_size(init_resp, enc_length_out); #if SASL_VERSION_MAJOR < 2 /* SASL version 1 doesn't free memory that it allocates. */ free(clientout); diff --git a/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_server.c b/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_server.c index f0e113c9404..5af62d06a19 100644 --- a/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_server.c +++ b/external/ibm-public/postfix/dist/src/xsasl/xsasl_cyrus_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: xsasl_cyrus_server.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: xsasl_cyrus_server.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -59,6 +59,7 @@ /* System library. */ #include <sys_defs.h> +#include <sys/socket.h> #include <stdlib.h> #include <string.h> @@ -143,6 +144,10 @@ typedef const void *VOID_SERVEROUT_TYPE; #endif +#ifndef NO_IP_CYRUS_SASL_AUTH +#define USE_IP_CYRUS_SASL_AUTH +#endif + /* * The XSASL_CYRUS_SERVER object is derived from the generic XSASL_SERVER * object. @@ -266,8 +271,8 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, XSASL_SERVER_CREATE_ARGS *args) { const char *myname = "xsasl_cyrus_server_create"; - char *server_address; - char *client_address; + char *server_addr_port = 0; + char *client_addr_port = 0; sasl_conn_t *sasl_conn = 0; XSASL_CYRUS_SERVER *server = 0; int sasl_status; @@ -288,6 +293,15 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, if (sasl_conn) \ sasl_dispose(&sasl_conn); \ } \ + XSASL_CYRUS_SERVER_CREATE_RETURN(x); \ + } while (0) + +#define XSASL_CYRUS_SERVER_CREATE_RETURN(x) \ + do { \ + if (server_addr_port) \ + myfree(server_addr_port); \ + if (client_addr_port) \ + myfree(client_addr_port); \ return (x); \ } while (0) @@ -298,27 +312,31 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, #define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0) #define NO_AUTH_REALM ((char *) 0) -#if SASL_VERSION_MAJOR >= 2 && defined(USE_SASL_IP_AUTH) +#if SASL_VERSION_MAJOR >= 2 && defined(USE_IP_CYRUS_SASL_AUTH) /* - * Get IP addresses of local and remote endpoints for SASL. + * Get IP address and port of local and remote endpoints for SASL. Some + * implementation supports "[ipv6addr]:port" and "ipv4addr:port" (e.g., + * https://illumos.org/man/3sasl/sasl_server_new), They still support the + * historical "address;port" syntax, so we stick with that for now. */ -#error "USE_SASL_IP_AUTH is not implemented" - + server_addr_port = (*args->server_addr && *args->server_port ? + concatenate(args->server_addr, ";", + args->server_port, (char *) 0) : 0); + client_addr_port = (*args->client_addr && *args->client_port ? + concatenate(args->client_addr, ";", + args->client_port, (char *) 0) : 0); #else /* - * Don't give any IP address information to SASL. SASLv1 doesn't use it, - * and in SASLv2 this will disable any mechanisms that do. + * Don't give any IP address information to SASL. */ - server_address = 0; - client_address = 0; #endif if ((sasl_status = SASL_SERVER_NEW(args->service, var_myhostname, args->user_realm ? args->user_realm : NO_AUTH_REALM, - server_address, client_address, + server_addr_port, client_addr_port, NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS, &sasl_conn)) != SASL_OK) { msg_warn("SASL per-connection server initialization: %s", @@ -347,7 +365,7 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, != XSASL_AUTH_OK) XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0); - return (&server->xsasl); + XSASL_CYRUS_SERVER_CREATE_RETURN(&server->xsasl); } /* xsasl_cyrus_server_set_security - set security properties */ @@ -482,6 +500,8 @@ static int xsasl_cyrus_server_auth_response(int sasl_status, sasl_status = SASL_BADAUTH; vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); switch (sasl_status) { + case SASL_FAIL: + case SASL_NOMEM: case SASL_TRYAGAIN: case SASL_UNAVAIL: return XSASL_AUTH_TEMP; diff --git a/external/ibm-public/postfix/dist/src/xsasl/xsasl_dovecot_server.c b/external/ibm-public/postfix/dist/src/xsasl/xsasl_dovecot_server.c index 5e6b42285fa..887847e0b96 100644 --- a/external/ibm-public/postfix/dist/src/xsasl/xsasl_dovecot_server.c +++ b/external/ibm-public/postfix/dist/src/xsasl/xsasl_dovecot_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: xsasl_dovecot_server.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ +/* $NetBSD: xsasl_dovecot_server.c,v 1.3 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME @@ -586,10 +586,20 @@ static int xsasl_dovecot_handle_reply(XSASL_DOVECOT_SERVER *server, if (xsasl_dovecot_parse_reply(server, &line) == 0) { /* authentication successful */ xsasl_dovecot_parse_reply_args(server, line, reply, 1); + if (server->username == 0) { + msg_warn("missing Dovecot server %s username field", cmd); + vstring_strcpy(reply, "Authentication backend error"); + return XSASL_AUTH_FAIL; + } return XSASL_AUTH_DONE; } } else if (strcmp(cmd, "CONT") == 0) { if (xsasl_dovecot_parse_reply(server, &line) == 0) { + if (line == 0) { + msg_warn("missing Dovecot server %s reply field", cmd); + vstring_strcpy(reply, "Authentication backend error"); + return XSASL_AUTH_FAIL; + } vstring_strcpy(reply, line); return XSASL_AUTH_MORE; } diff --git a/external/ibm-public/postfix/dist/src/xsasl/xsasl_server.c b/external/ibm-public/postfix/dist/src/xsasl/xsasl_server.c index 278fdb227a5..dd6e24f8c98 100644 --- a/external/ibm-public/postfix/dist/src/xsasl/xsasl_server.c +++ b/external/ibm-public/postfix/dist/src/xsasl/xsasl_server.c @@ -1,4 +1,4 @@ -/* $NetBSD: xsasl_server.c,v 1.1.1.2 2020/03/18 18:59:38 christos Exp $ */ +/* $NetBSD: xsasl_server.c,v 1.2 2020/03/18 19:05:22 christos Exp $ */ /*++ /* NAME diff --git a/external/ibm-public/postfix/lib/dns/Makefile b/external/ibm-public/postfix/lib/dns/Makefile index 017fc831c90..889cf71d54c 100644 --- a/external/ibm-public/postfix/lib/dns/Makefile +++ b/external/ibm-public/postfix/lib/dns/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2017/02/14 01:16:49 christos Exp $ +# $NetBSD: Makefile,v 1.3 2020/03/18 19:05:22 christos Exp $ LIBISPRIVATE= yes @@ -9,8 +9,18 @@ LIB= dns DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -SRCS= dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c dns_rr_to_pa.c \ - dns_sa_to_rr.c dns_rr_eq_sa.c dns_rr_to_sa.c dns_rr_filter.c \ - dns_strrecord.c +SRCS= \ +dns_lookup.c \ +dns_rr.c \ +dns_rr_eq_sa.c \ +dns_rr_filter.c \ +dns_rr_to_pa.c \ +dns_rr_to_sa.c \ +dns_sa_to_rr.c \ +dns_str_resflags.c \ +dns_strerror.c \ +dns_strrecord.c \ +dns_strtype.c \ +test_dns_lookup.c .include <bsd.lib.mk> diff --git a/external/ibm-public/postfix/lib/global/Makefile b/external/ibm-public/postfix/lib/global/Makefile index b604d02bafb..c73f53ce52f 100644 --- a/external/ibm-public/postfix/lib/global/Makefile +++ b/external/ibm-public/postfix/lib/global/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.7 2017/02/14 01:16:49 christos Exp $ +# $NetBSD: Makefile,v 1.8 2020/03/18 19:05:22 christos Exp $ LIBISPRIVATE= yes @@ -9,41 +9,172 @@ LIB= global DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -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_memcache.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 \ - header_token.c input_transp.c int_filt.c is_header.c log_adhoc.c \ - mail_addr.c mail_addr_crunch.c mail_addr_find.c mail_addr_map.c \ - mail_command_client.c mail_command_server.c mail_conf.c \ - mail_conf_bool.c mail_conf_int.c mail_conf_long.c mail_conf_raw.c \ - mail_conf_str.c mail_conf_time.c mail_connect.c mail_copy.c \ - mail_date.c mail_dict.c mail_error.c mail_flush.c mail_open_ok.c \ - mail_params.c mail_pathname.c mail_queue.c mail_run.c \ - mail_scan_dir.c mail_stream.c mail_task.c mail_trigger.c maps.c \ - mark_corrupt.c match_parent_style.c mbox_conf.c mbox_open.c \ - mime_state.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c mkmap_open.c \ - mkmap_sdbm.c msg_stats_print.c msg_stats_scan.c mynetworks.c \ - mypwd.c namadr_list.c off_cvt.c opened.c own_inet_addr.c \ - pipe_command.c post_mail.c quote_821_local.c quote_822_local.c \ - rcpt_buf.c rcpt_print.c rec_attr_map.c rec_streamlf.c rec_type.c \ - recipient_list.c record.c remove.c resolve_clnt.c resolve_local.c \ - rewrite_clnt.c scache_clnt.c scache_multi.c scache_single.c \ - sent.c smtp_stream.c split_addr.c string_list.c strip_addr.c \ - sys_exits.c timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \ - tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c \ - user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \ - verp_sender.c wildcard_inet_addr.c xtext.c data_redirect.c \ - delivered_hdr.c fold_addr.c mkmap_proxy.c header_body_checks.c \ - mail_conf_nint.c match_service.c match_service.h mail_conf_nbool.c \ - smtp_reply_footer.c memcache_proto.c mkmap_fail.c safe_ultostr.c \ - server_acl.c verify_sender_addr.c mail_version.c haproxy_srvr.c \ - mkmap_lmdb.c dsn_filter.c smtputf8.c attr_override.c mail_parm_split.c \ - uxtext.c +SRCS= \ +abounce.c \ +addr_match_list.c \ +anvil_clnt.c \ +attr_override.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 \ +data_redirect.c \ +db_common.c \ +debug_peer.c \ +debug_process.c \ +defer.c \ +deliver_completed.c \ +deliver_flock.c \ +deliver_pass.c \ +deliver_request.c \ +delivered_hdr.c \ +dict_ldap.c \ +dict_memcache.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_filter.c \ +dsn_mask.c \ +dsn_print.c \ +dsn_util.c \ +dynamicmaps.c \ +ehlo_mask.c \ +ext_prop.c \ +file_id.c \ +flush_clnt.c \ +fold_addr.c \ +haproxy_srvr.c \ +header_body_checks.c \ +header_opts.c \ +header_token.c \ +info_log_addr_form.c \ +input_transp.c \ +int_filt.c \ +is_header.c \ +log_adhoc.c \ +mail_addr.c \ +mail_addr_crunch.c \ +mail_addr_find.c \ +mail_addr_form.c \ +mail_addr_map.c \ +mail_command_client.c \ +mail_command_server.c \ +mail_conf.c \ +mail_conf_bool.c \ +mail_conf_int.c \ +mail_conf_long.c \ +mail_conf_nbool.c \ +mail_conf_nint.c \ +mail_conf_raw.c \ +mail_conf_str.c \ +mail_conf_time.c \ +mail_connect.c \ +mail_copy.c \ +mail_date.c \ +mail_dict.c \ +mail_error.c \ +mail_flush.c \ +mail_open_ok.c \ +mail_params.c \ +mail_parm_split.c \ +mail_pathname.c \ +mail_queue.c \ +mail_run.c \ +mail_scan_dir.c \ +mail_stream.c \ +mail_task.c \ +mail_trigger.c \ +mail_version.c \ +maillog_client.c \ +map_search.c \ +maps.c \ +mark_corrupt.c \ +match_parent_style.c \ +match_service.c \ +mbox_conf.c \ +mbox_open.c \ +memcache_proto.c \ +midna_adomain.c \ +mime_state.c \ +mkmap_cdb.c \ +mkmap_db.c \ +mkmap_dbm.c \ +mkmap_fail.c \ +mkmap_lmdb.c \ +mkmap_open.c \ +mkmap_proxy.c \ +mkmap_sdbm.c \ +msg_stats_print.c \ +msg_stats_scan.c \ +mynetworks.c \ +mypwd.c \ +namadr_list.c \ +normalize_mailhost_addr.c \ +off_cvt.c \ +opened.c \ +own_inet_addr.c \ +pipe_command.c \ +post_mail.c \ +quote_821_local.c \ +quote_822_local.c \ +quote_flags.c \ +rcpt_buf.c \ +rcpt_print.c \ +rec2stream.c \ +rec_attr_map.c \ +rec_streamlf.c \ +rec_type.c \ +recdump.c \ +recipient_list.c \ +record.c \ +reject_deliver_request.c \ +remove.c \ +resolve_clnt.c \ +resolve_local.c \ +rewrite_clnt.c \ +safe_ultostr.c \ +scache.c \ +scache_clnt.c \ +scache_multi.c \ +scache_single.c \ +sent.c \ +server_acl.c \ +smtp_reply_footer.c \ +smtp_stream.c \ +smtputf8.c \ +split_addr.c \ +stream2rec.c \ +string_list.c \ +strip_addr.c \ +sys_exits.c \ +timed_ipc.c \ +tok822_find.c \ +tok822_node.c \ +tok822_parse.c \ +tok822_resolve.c \ +tok822_rewrite.c \ +tok822_tree.c \ +trace.c \ +user_acl.c \ +uxtext.c \ +valid_mailhost_addr.c \ +verify.c \ +verify_clnt.c \ +verify_sender_addr.c \ +verp_sender.c \ +wildcard_inet_addr.c \ +xtext.c .include <bsd.lib.mk> diff --git a/external/ibm-public/postfix/lib/masterlib/Makefile b/external/ibm-public/postfix/lib/masterlib/Makefile index 7598d1d692a..feffc20dfbf 100644 --- a/external/ibm-public/postfix/lib/masterlib/Makefile +++ b/external/ibm-public/postfix/lib/masterlib/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2011/03/02 22:24:55 tron Exp $ +# $NetBSD: Makefile,v 1.3 2020/03/18 19:05:22 christos Exp $ LIBISPRIVATE= yes @@ -9,7 +9,24 @@ LIB= master DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -SRCS= single_server.c multi_server.c trigger_server.c master_proto.c \ - mail_flow.c event_server.c +SRCS= \ +dgram_server.c \ +event_server.c \ +mail_flow.c \ +master_avail.c \ +master_conf.c \ +master_flow.c \ +master_listen.c \ +master_monitor.c \ +master_proto.c \ +master_service.c \ +master_sig.c \ +master_spawn.c \ +master_status.c \ +master_wakeup.c \ +master_watch.c \ +multi_server.c \ +single_server.c \ +trigger_server.c .include <bsd.lib.mk> diff --git a/external/ibm-public/postfix/lib/milter/Makefile b/external/ibm-public/postfix/lib/milter/Makefile index 2ac6cea100d..6bc31c7037e 100644 --- a/external/ibm-public/postfix/lib/milter/Makefile +++ b/external/ibm-public/postfix/lib/milter/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.1 2009/06/25 18:21:52 tron Exp $ +# $NetBSD: Makefile,v 1.2 2020/03/18 19:05:22 christos Exp $ LIBISPRIVATE= yes @@ -9,6 +9,9 @@ LIB= milter DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -SRCS= milter.c milter8.c milter_macros.c +SRCS+= \ +milter.c \ +milter8.c \ +milter_macros.c .include <bsd.lib.mk> diff --git a/external/ibm-public/postfix/lib/tls/Makefile b/external/ibm-public/postfix/lib/tls/Makefile index e56d5256414..23010eac937 100644 --- a/external/ibm-public/postfix/lib/tls/Makefile +++ b/external/ibm-public/postfix/lib/tls/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.3 2014/07/06 19:53:05 tron Exp $ +# $NetBSD: Makefile,v 1.4 2020/03/18 19:05:23 christos Exp $ LIBISPRIVATE= yes @@ -9,11 +9,34 @@ LIB= tls DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -SRCS= tls_prng_dev.c tls_prng_egd.c tls_prng_file.c \ - tls_prng_exch.c tls_stream.c tls_bio_ops.c tls_misc.c tls_dh.c \ - tls_rsa.c tls_verify.c tls_certkey.c tls_session.c \ - tls_client.c tls_server.c tls_scache.c tls_mgr.c tls_seed.c \ - tls_level.c tls_proxy_clnt.c tls_proxy_print.c tls_dane.c \ - tls_fprint.c +SRCS= \ +tls_bio_ops.c \ +tls_certkey.c \ +tls_client.c \ +tls_dane.c \ +tls_dh.c \ +tls_fprint.c \ +tls_level.c \ +tls_mgr.c \ +tls_misc.c \ +tls_prng_dev.c \ +tls_prng_egd.c \ +tls_prng_exch.c \ +tls_prng_file.c \ +tls_proxy_client_misc.c \ +tls_proxy_client_print.c \ +tls_proxy_client_scan.c \ +tls_proxy_clnt.c \ +tls_proxy_context_print.c \ +tls_proxy_context_scan.c \ +tls_proxy_server_print.c \ +tls_proxy_server_scan.c \ +tls_rsa.c \ +tls_scache.c \ +tls_seed.c \ +tls_server.c \ +tls_session.c \ +tls_stream.c \ +tls_verify.c .include <bsd.lib.mk> diff --git a/external/ibm-public/postfix/lib/util/Makefile b/external/ibm-public/postfix/lib/util/Makefile index c2916ea8f73..60b05b8c0ab 100644 --- a/external/ibm-public/postfix/lib/util/Makefile +++ b/external/ibm-public/postfix/lib/util/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.8 2017/02/14 01:16:49 christos Exp $ +# $NetBSD: Makefile,v 1.9 2020/03/18 19:05:23 christos Exp $ LIBISPRIVATE= yes @@ -9,47 +9,216 @@ LIB= util DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -SRCS= alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ - attr_print64.c attr_print_plain.c attr_scan0.c attr_scan64.c \ - attr_scan_plain.c auto_clnt.c base64_code.c basename.c binhash.c \ - chroot_uid.c cidr_match.c clean_env.c close_on_exec.c concatenate.c \ - ctable.c dict.c dict_alloc.c dict_cdb.c dict_cidr.c dict_db.c \ - dict_dbm.c dict_debug.c dict_env.c dict_ht.c dict_inline.c \ - dict_ni.c dict_nis.c dict_pipe.c dict_random.c \ - dict_nisplus.c dict_open.c dict_pcre.c dict_regexp.c dict_sdbm.c \ - dict_static.c dict_tcp.c dict_unix.c dict_union.c dict_utf8.c \ - dir_forest.c doze.c dummy_read.c \ - dummy_write.c duplex_pipe.c environ.c events.c exec_command.c \ - fifo_listen.c fifo_trigger.c file_limit.c find_inet.c fsspace.c \ - fullname.c get_domainname.c get_hostname.c hex_code.c hex_quote.c \ - host_port.c htable.c inet_addr_host.c inet_addr_list.c \ - inet_addr_local.c inet_connect.c inet_listen.c inet_proto.c \ - inet_trigger.c line_wrap.c lowercase.c lstat_as.c mac_expand.c \ - mac_parse.c make_dirs.c mask_addr.c match_list.c match_ops.c msg.c \ - msg_output.c msg_syslog.c msg_vstream.c mvect.c myaddrinfo.c myflock.c \ - mymalloc.c myrand.c mystrtok.c name_code.c name_mask.c netstring.c \ - neuter.c non_blocking.c nvtable.c open_as.c open_limit.c open_lock.c \ - peekfd.c percentm.c posix_signals.c printable.c rand_sleep.c \ - readlline.c ring.c safe_getenv.c safe_open.c \ - sane_accept.c sane_connect.c sane_link.c sane_rename.c \ - sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \ - sigdelay.c skipblanks.c sock_addr.c spawn_command.c split_at.c \ - split_nameval.c stat_as.c strcasecmp.c stream_connect.c \ - stream_listen.c stream_recv_fd.c stream_send_fd.c stream_trigger.c \ - sys_compat.c timed_connect.c timed_read.c timed_wait.c timed_write.c \ - translit.c trimblanks.c unescape.c unix_connect.c unix_listen.c \ - unix_recv_fd.c unix_send_fd.c unix_trigger.c unsafe.c uppercase.c \ - username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \ - vstream_popen.c vstring.c vstring_vstream.c watchdog.c \ - write_buf.c sane_basename.c format_tv.c allspace.c \ - allascii.c load_file.c killme_after.c vstream_tweak.c edit_file.c \ - inet_windowsize.c unix_pass_fd_fix.c dict_cache.c dict_thash.c \ - ip_match.c nbbio.c myrand.c base32_code.c dict_fail.c \ - dict_surrogate.c dict_test.c msg_rate_delay.c warn_stat.c \ - dict_sockmap.c line_number.c pass_accept.c pass_trigger.c \ - recv_pass_attr.c slmdb.c dict_lmdb.c poll_fd.c timecmp.c \ - valid_utf8_string.c casefold.c strcasecmp_utf8.c balpar.c \ - extpar.c valid_utf8_hostname.c argv_splitq.c midna_domain.c +SRCS= \ +allascii.c \ +alldig.c \ +allprint.c \ +allspace.c \ +argv.c \ +argv_attr_print.c \ +argv_attr_scan.c \ +argv_split.c \ +argv_splitq.c \ +attr_clnt.c \ +attr_print0.c \ +attr_print64.c \ +attr_print_plain.c \ +attr_scan0.c \ +attr_scan64.c \ +attr_scan_plain.c \ +auto_clnt.c \ +balpar.c \ +base32_code.c \ +base64_code.c \ +basename.c \ +binhash.c \ +byte_mask.c \ +casefold.c \ +chroot_uid.c \ +cidr_match.c \ +clean_env.c \ +close_on_exec.c \ +concatenate.c \ +ctable.c \ +dict.c \ +dict_alloc.c \ +dict_cache.c \ +dict_cdb.c \ +dict_cidr.c \ +dict_db.c \ +dict_dbm.c \ +dict_debug.c \ +dict_env.c \ +dict_fail.c \ +dict_file.c \ +dict_ht.c \ +dict_inline.c \ +dict_lmdb.c \ +dict_ni.c \ +dict_nis.c \ +dict_nisplus.c \ +dict_open.c \ +dict_pcre.c \ +dict_pipe.c \ +dict_random.c \ +dict_regexp.c \ +dict_sdbm.c \ +dict_sockmap.c \ +dict_static.c \ +dict_surrogate.c \ +dict_tcp.c \ +dict_test.c \ +dict_thash.c \ +dict_union.c \ +dict_unix.c \ +dict_utf8.c \ +dir_forest.c \ +doze.c \ +dummy_read.c \ +dummy_write.c \ +dup2_pass_on_exec.c \ +duplex_pipe.c \ +edit_file.c \ +environ.c \ +events.c \ +exec_command.c \ +extpar.c \ +fifo_listen.c \ +fifo_open.c \ +fifo_rdonly_bug.c \ +fifo_rdwr_bug.c \ +fifo_trigger.c \ +file_limit.c \ +find_inet.c \ +format_tv.c \ +fsspace.c \ +fullname.c \ +get_domainname.c \ +get_hostname.c \ +hex_code.c \ +hex_quote.c \ +host_port.c \ +htable.c \ +inet_addr_host.c \ +inet_addr_list.c \ +inet_addr_local.c \ +inet_connect.c \ +inet_listen.c \ +inet_proto.c \ +inet_trigger.c \ +inet_windowsize.c \ +ip_match.c \ +killme_after.c \ +line_number.c \ +line_wrap.c \ +load_file.c \ +load_lib.c \ +logwriter.c \ +lowercase.c \ +lstat_as.c \ +mac_expand.c \ +mac_parse.c \ +make_dirs.c \ +mask_addr.c \ +match_list.c \ +match_ops.c \ +midna_domain.c \ +msg.c \ +msg_logger.c \ +msg_output.c \ +msg_rate_delay.c \ +msg_syslog.c \ +msg_vstream.c \ +mvect.c \ +myaddrinfo.c \ +myflock.c \ +mymalloc.c \ +myrand.c \ +mystrtok.c \ +name_code.c \ +name_mask.c \ +nbbio.c \ +netstring.c \ +neuter.c \ +non_blocking.c \ +nvtable.c \ +open_as.c \ +open_limit.c \ +open_lock.c \ +pass_accept.c \ +pass_trigger.c \ +peekfd.c \ +percentm.c \ +poll_fd.c \ +posix_signals.c \ +printable.c \ +rand_sleep.c \ +readlline.c \ +recv_pass_attr.c \ +ring.c \ +safe_getenv.c \ +safe_open.c \ +sane_accept.c \ +sane_basename.c \ +sane_connect.c \ +sane_link.c \ +sane_rename.c \ +sane_socketpair.c \ +sane_time.c \ +scan_dir.c \ +select_bug.c \ +set_eugid.c \ +set_ugid.c \ +sigdelay.c \ +skipblanks.c \ +slmdb.c \ +sock_addr.c \ +spawn_command.c \ +split_at.c \ +split_nameval.c \ +split_qnameval.c \ +stat_as.c \ +strcasecmp.c \ +strcasecmp_utf8.c \ +stream_connect.c \ +stream_listen.c \ +stream_recv_fd.c \ +stream_send_fd.c \ +stream_test.c \ +stream_trigger.c \ +sys_compat.c \ +timecmp.c \ +timed_connect.c \ +timed_read.c \ +timed_wait.c \ +timed_write.c \ +translit.c \ +trimblanks.c \ +unescape.c \ +unix_connect.c \ +unix_dgram_connect.c \ +unix_dgram_listen.c \ +unix_listen.c \ +unix_pass_fd_fix.c \ +unix_recv_fd.c \ +unix_send_fd.c \ +unix_trigger.c \ +unsafe.c \ +uppercase.c \ +username.c \ +valid_hostname.c \ +valid_utf8_hostname.c \ +valid_utf8_string.c \ +vbuf.c \ +vbuf_print.c \ +vstream.c \ +vstream_popen.c \ +vstream_tweak.c \ +vstring.c \ +vstring_vstream.c \ +warn_stat.c \ +watchdog.c \ +write_buf.c COPTS.unix_recv_fd.c = -Wno-stack-protector COPTS.unix_send_fd.c = -Wno-stack-protector diff --git a/external/ibm-public/postfix/lib/xsasl/Makefile b/external/ibm-public/postfix/lib/xsasl/Makefile index 80820722977..7fd23af05f9 100644 --- a/external/ibm-public/postfix/lib/xsasl/Makefile +++ b/external/ibm-public/postfix/lib/xsasl/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2011/02/12 19:07:09 christos Exp $ +# $NetBSD: Makefile,v 1.3 2020/03/18 19:05:23 christos Exp $ LIBISPRIVATE= yes @@ -9,8 +9,14 @@ LIB= xsasl DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB} .PATH: ${DIST} -SRCS= xsasl_server.c xsasl_cyrus_server.c xsasl_cyrus_log.c \ - xsasl_cyrus_security.c xsasl_client.c xsasl_cyrus_client.c \ - xsasl_dovecot_server.c xsasl_saslc_client.c +SRCS+= \ +xsasl_client.c \ +xsasl_cyrus_client.c \ +xsasl_cyrus_log.c \ +xsasl_cyrus_security.c \ +xsasl_cyrus_server.c \ +xsasl_dovecot_server.c \ +xsasl_saslc_client.c \ +xsasl_server.c .include <bsd.lib.mk> diff --git a/external/ibm-public/postfix/libexec/smtp/Makefile b/external/ibm-public/postfix/libexec/smtp/Makefile index c6c640fcb1b..352dbd08ca0 100644 --- a/external/ibm-public/postfix/libexec/smtp/Makefile +++ b/external/ibm-public/postfix/libexec/smtp/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.3 2017/05/21 15:28:40 riastradh Exp $ +# $NetBSD: Makefile,v 1.4 2020/03/18 19:05:23 christos Exp $ NOMAN= # defined @@ -9,10 +9,25 @@ PROG= smtp DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${PROG} .PATH: ${DIST} -SRCS= smtp.c smtp_connect.c smtp_proto.c smtp_chat.c smtp_session.c \ - smtp_addr.c smtp_trouble.c smtp_state.c smtp_rcpt.c \ - smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c \ - smtp_sasl_auth_cache.c smtp_key.c smtp_tls_policy.c +SRCS+= \ +smtp.c \ +smtp_addr.c \ +smtp_chat.c \ +smtp_connect.c \ +smtp_key.c \ +smtp_map11.c \ +smtp_misc.c \ +smtp_proto.c \ +smtp_rcpt.c \ +smtp_reuse.c \ +smtp_sasl_auth_cache.c \ +smtp_sasl_glue.c \ +smtp_sasl_proto.c \ +smtp_session.c \ +smtp_state.c \ +smtp_tls_policy.c \ +smtp_trouble.c \ +smtp_unalias.c LINKS+= ${PFIX_LIBEXECDIR}/smtp ${PFIX_LIBEXECDIR}/lmtp diff --git a/external/ibm-public/postfix/libexec/smtpd/Makefile b/external/ibm-public/postfix/libexec/smtpd/Makefile index 2569cd0fbcd..8af5d2fb592 100644 --- a/external/ibm-public/postfix/libexec/smtpd/Makefile +++ b/external/ibm-public/postfix/libexec/smtpd/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.7 2018/02/01 03:29:41 christos Exp $ +# $NetBSD: Makefile,v 1.8 2020/03/18 19:05:23 christos Exp $ NOMAN= # defined @@ -10,10 +10,23 @@ TOP= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist DIST=${TOP}/src/${PROG} .PATH: ${DIST} -SRCS= smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \ - smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \ - smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c smtpd_resolve.c \ - smtpd_expand.c smtpd_haproxy.c pfilter.c +SRCS+= \ +pfilter.c \ +smtpd.c \ +smtpd_chat.c \ +smtpd_check.c \ +smtpd_dsn_fix.c \ +smtpd_expand.c \ +smtpd_haproxy.c \ +smtpd_milter.c \ +smtpd_peer.c \ +smtpd_proxy.c \ +smtpd_resolve.c \ +smtpd_sasl_glue.c \ +smtpd_sasl_proto.c \ +smtpd_state.c \ +smtpd_token.c \ +smtpd_xforward.c DPADD+= ${LIBPMASTER} ${LIBPMILTER} ${LIBPGLOBAL} ${LIBPDNS} ${LIBPXSASL} LDADD+= ${LIBPMASTER} ${LIBPMILTER} ${LIBPGLOBAL} ${LIBPDNS} ${LIBPXSASL} diff --git a/external/ibm-public/postfix/libexec/tlsproxy/Makefile b/external/ibm-public/postfix/libexec/tlsproxy/Makefile index 8f25449db35..1a2d224e5f6 100644 --- a/external/ibm-public/postfix/libexec/tlsproxy/Makefile +++ b/external/ibm-public/postfix/libexec/tlsproxy/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.1 2011/03/02 22:24:56 tron Exp $ +# $NetBSD: Makefile,v 1.2 2020/03/18 19:05:23 christos Exp $ NOMAN= # defined @@ -11,8 +11,8 @@ DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${PROG} SRCS= tlsproxy_state.c tlsproxy.c -DPADD+= ${LIBPTLS} ${LIBPMASTER} ${LIBPGLOBAL} ${LIBPUTIL} -LDADD+= ${LIBPTLS} ${LIBPMASTER} ${LIBPGLOBAL} ${LIBPUTIL} +DPADD+= ${LIBPTLS} ${LIBPMASTER} ${LIBPGLOBAL} ${LIBPDNS} ${LIBPUTIL} +LDADD+= ${LIBPTLS} ${LIBPMASTER} ${LIBPGLOBAL} ${LIBPDNS} ${LIBPUTIL} DPADD+= ${LIBSSL} ${LIBCRYPTO} LDADD+= -lssl -lcrypto diff --git a/external/ibm-public/postfix/sbin/postconf/Makefile b/external/ibm-public/postfix/sbin/postconf/Makefile index 7fcb659f0e9..d46ee62f43d 100644 --- a/external/ibm-public/postfix/sbin/postconf/Makefile +++ b/external/ibm-public/postfix/sbin/postconf/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.8 2017/02/14 01:16:49 christos Exp $ +# $NetBSD: Makefile,v 1.9 2020/03/18 19:05:23 christos Exp $ # XXX Note we aren't building ../conf/main.cf.default # The shipped makefiles construct it using postconf -d after building @@ -31,8 +31,8 @@ CLEANFILES+= ${GENSRCS} CPPFLAGS+= -I. -DPADD+= ${LIBPGLOBAL} ${LIBPTLS} ${LIBPXSASL} ${LIBPUTIL} -LDADD+= ${LIBPGLOBAL} ${LIBPTLS} ${LIBPXSASL} ${LIBPUTIL} +DPADD+= ${LIBPTLS} ${LIBPGLOBAL} ${LIBPXSASL} ${LIBPUTIL} +LDADD+= ${LIBPTLS} ${LIBPGLOBAL} ${LIBPXSASL} ${LIBPUTIL} ${GENSRCS}: postconf-hdrs.stamp CLEANFILES+= postconf-hdrs.stamp |
