From 3525c001ea10a09aab8d995763d7c02e9c3cc99f Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Fri, 23 Nov 2018 00:00:00 -0500 Subject: [PATCH] postfix-3.4-20181123 --- postfix/HISTORY | 7 +++ postfix/html/tlsproxy.8.html | 49 ++++++++-------- postfix/man/man8/tlsproxy.8 | 8 ++- postfix/src/global/mail_version.h | 2 +- postfix/src/tlsproxy/tlsproxy.c | 98 ++++++++++++++++++++----------- 5 files changed, 101 insertions(+), 63 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 4d86d67b1..e6bf8b484 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -23835,3 +23835,10 @@ Apologies for any names omitted. cert/key information on-the-fly at post-jail time. Files: proto/postconf.proto, mantools/postlink, global/mail_params.h, tlsproxy/tlsproxy.c. + +20181123 + + Cleanup: tlsproxy now logs better instructions when a + tls_client_init request specifies an unexpected client + identity, and the test for that condition is now moved to + the right place. File: tlsproxy/tlsproxy.c. diff --git a/postfix/html/tlsproxy.8.html b/postfix/html/tlsproxy.8.html index f0b7b8883..809706801 100644 --- a/postfix/html/tlsproxy.8.html +++ b/postfix/html/tlsproxy.8.html @@ -161,44 +161,45 @@ TLSPROXY(8) TLSPROXY(8) The name of the tlsmgr(8) service entry in master.cf. TLS CLIENT CONTROLS - These parameters allow tlsproxy(8) to load certificate and private key - information before dropping privileges, so that the key files can be - kept read-only for root. + These parameters are clones of SMTP client settings. They allow + tlsproxy(8) to load the same certificate and private key information as + the SMTP client, before dropping privileges, so that the key files can + be kept read-only for root. Available in Postfix version 3.4 and later: tlsproxy_client_CAfile ($smtp_tls_CAfile) - A file containing CA certificates of root CAs trusted to sign - either remote TLS server certificates or intermediate CA cer- + A file containing CA certificates of root CAs trusted to sign + either remote TLS server certificates or intermediate CA cer- tificates. tlsproxy_client_CApath ($smtp_tls_CApath) - Directory with PEM format Certification Authority certificates - that the Postfix tlsproxy(8) client uses to verify a remote TLS + Directory with PEM format Certification Authority certificates + that the Postfix tlsproxy(8) client uses to verify a remote TLS server certificate. tlsproxy_client_cert_file ($smtp_tls_cert_file) - File with the Postfix tlsproxy(8) client RSA certificate in PEM + File with the Postfix tlsproxy(8) client RSA certificate in PEM format. tlsproxy_client_key_file ($smtp_tls_key_file) - File with the Postfix tlsproxy(8) client RSA private key in PEM + File with the Postfix tlsproxy(8) client RSA private key in PEM format. tlsproxy_client_dcert_file ($smtp_tls_dcert_file) - File with the Postfix tlsproxy(8) client DSA certificate in PEM + File with the Postfix tlsproxy(8) client DSA certificate in PEM format. tlsproxy_client_dkey_file ($smtp_tls_dkey_file) - File with the Postfix tlsproxy(8) client DSA private key in PEM + File with the Postfix tlsproxy(8) client DSA private key in PEM format. tlsproxy_client_eccert_file ($smtp_tls_eccert_file) - File with the Postfix tlsproxy(8) client ECDSA certificate in + File with the Postfix tlsproxy(8) client ECDSA certificate in PEM format. tlsproxy_client_eckey_file ($smtp_tls_eckey_file) - File with the Postfix tlsproxy(8) client ECDSA private key in + File with the Postfix tlsproxy(8) client ECDSA private key in PEM format. tlsproxy_client_fingerprint_digest ($smtp_tls_fingerprint_digest) @@ -206,7 +207,7 @@ TLSPROXY(8) TLSPROXY(8) certificate fingerprints. tlsproxy_client_loglevel ($smtp_tls_loglevel) - Enable additional Postfix tlsproxy(8) client logging of TLS + Enable additional Postfix tlsproxy(8) client logging of TLS activity. tlsproxy_client_loglevel_parameter (smtp_tls_loglevel) @@ -217,31 +218,31 @@ TLSPROXY(8) TLSPROXY(8) The verification depth for remote TLS server certificates. tlsproxy_client_security_level ($smtp_tls_security_level) - The default TLS security level for the Postfix tlsproxy(8) + The default TLS security level for the Postfix tlsproxy(8) client. tlsproxy_client_policy_maps ($smtp_tls_policy_maps) - Optional lookup tables with the Postfix tlsproxy(8) client TLS + Optional lookup tables with the Postfix tlsproxy(8) client TLS security policy by next-hop destination. tlsproxy_client_use_tls ($smtp_use_tls) - Opportunistic mode: use TLS when a remote server announces TLS + Opportunistic mode: use TLS when a remote server announces TLS support. tlsproxy_client_enforce_tls ($smtp_enforce_tls) - Enforcement mode: require that SMTP servers use TLS encryption. + Enforcement mode: require that SMTP servers use TLS encryption. tlsproxy_client_per_site ($smtp_tls_per_site) - Optional lookup tables with the Postfix tlsproxy(8) client TLS - usage policy by next-hop destination and by remote TLS server + Optional lookup tables with the Postfix tlsproxy(8) client TLS + usage policy by next-hop destination and by remote TLS server hostname. OBSOLETE STARTTLS SUPPORT CONTROLS - These parameters are supported for compatibility with smtpd(8) legacy + These parameters are supported for compatibility with smtpd(8) legacy parameters. tlsproxy_use_tls ($smtpd_use_tls) - Opportunistic TLS: announce STARTTLS support to remote SMTP + Opportunistic TLS: announce STARTTLS support to remote SMTP clients, but do not require that clients use TLS encryption. tlsproxy_enforce_tls ($smtpd_enforce_tls) @@ -255,7 +256,7 @@ TLSPROXY(8) TLSPROXY(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. process_id (read-only) @@ -268,7 +269,7 @@ TLSPROXY(8) TLSPROXY(8) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix 3.3 and later: diff --git a/postfix/man/man8/tlsproxy.8 b/postfix/man/man8/tlsproxy.8 index 72e7a157b..ac02bba64 100644 --- a/postfix/man/man8/tlsproxy.8 +++ b/postfix/man/man8/tlsproxy.8 @@ -158,9 +158,11 @@ The name of the \fBtlsmgr\fR(8) service entry in master.cf. .nf .ad .fi -These parameters allow \fBtlsproxy\fR(8) to load certificate -and private key information before dropping privileges, so -that the key files can be kept read\-only for root. +These parameters are clones of SMTP client settings. They +allow \fBtlsproxy\fR(8) to load the same certificate and +private key information as the SMTP client, before dropping +privileges, so that the key files can be kept read\-only for +root. .PP Available in Postfix version 3.4 and later: .IP "\fBtlsproxy_client_CAfile ($smtp_tls_CAfile)\fR" diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f3a11fab8..b20946ead 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20181122" +#define MAIL_RELEASE_DATE "20181123" #define MAIL_VERSION_NUMBER "3.4" #ifdef SNAPSHOT diff --git a/postfix/src/tlsproxy/tlsproxy.c b/postfix/src/tlsproxy/tlsproxy.c index 29af7bc58..cf93c6c44 100644 --- a/postfix/src/tlsproxy/tlsproxy.c +++ b/postfix/src/tlsproxy/tlsproxy.c @@ -140,9 +140,11 @@ /* TLS CLIENT CONTROLS /* .ad /* .fi -/* These parameters allow \fBtlsproxy\fR(8) to load certificate -/* and private key information before dropping privileges, so -/* that the key files can be kept read-only for root. +/* These parameters are clones of SMTP client settings. They +/* allow \fBtlsproxy\fR(8) to load the same certificate and +/* private key information as the SMTP client, before dropping +/* privileges, so that the key files can be kept read-only for +/* root. /* .PP /* Available in Postfix version 3.4 and later: /* .IP "\fBtlsproxy_client_CAfile ($smtp_tls_CAfile)\fR" @@ -413,6 +415,7 @@ static int ask_client_cert; * TLS per-client status. */ static HTABLE *tlsp_client_app_cache; +static char *tlsp_pre_jail_client_props_key; /* * Error handling: if a function detects an error, then that function is @@ -1021,44 +1024,69 @@ static int tlsp_client_init(TLS_APPL_STATE **client_appl_state, char *key; /* - * Share a TLS_APPL_STATE object among multiple requests that specify the - * same TLS_CLIENT_INIT_PROPS. TLS_APPL_STATE owns an SSL_CTX which is + * 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. + * + * First, compute the TLS_APPL_STATE cache lookup key. Save a copy of the + * key that corresponds to the pre-jail internal call, which uses the + * tlsproxy_client_* settings. */ buf = vstring_alloc(100); key = tls_proxy_client_init_to_string(buf, init_props); + if (tlsp_pre_jail_done == 0) { + if (tlsp_pre_jail_client_props_key != 0) + msg_panic("tlsp_client_init: multiple pre-jail calls"); + tlsp_pre_jail_client_props_key = mystrdup(key); + } + + /* + * Log a warning if a post-jail request differs from the tlsproxy_client_* + * settings AND the request specifies file or directory arguments. Those + * are problematic after chroot (pathname resolution) and after dropping + * privileges (key files must be root read-only). + * + * We can eliminate 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. + */ +#define NOT_EMPTY(x) ((x) && *(x)) + + else if ((tlsp_pre_jail_client_props_key == 0 + || strcmp(tlsp_pre_jail_client_props_key, key) != 0) + && (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("tls_client_init request with key_file='%s' dkey_file='%s' " + "eckey_file='%s' differs from tlsproxy_client_* settings", + init_props->key_file, init_props->dkey_file, + init_props->eckey_file); + msg_warn("to avoid this warning, 1) identify the SMTP client that is " + "making this tls_client_init request, 2) configure a " + "custom tlsproxy service with tlsproxy_client_* settings " + "that match that SMTP client, and 3) configure that SMTP " + "client with a tlsproxy_service setting that resolves to " + "that custom tlsproxy service"); + } + + /* + * Now, back to our regular program: look up the cached TLS_APPL_STATE + * for this tls_client_init request, or create one and add it the + * TLS_APPL_STATE cache. 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 = (TLS_APPL_STATE *) htable_find(tlsp_client_app_cache, key)) == 0 && (appl_state = tls_client_init(init_props)) != 0) { (void) htable_enter(tlsp_client_app_cache, key, (void *) appl_state); - /* - * Log a warning if these client settings differ from the - * tlsproxy_client_* settings AND the settings specify file or - * directory arguments. Those are problematic after chroot (pathname - * resolution) and dropping permission (key files must be root - * read-only). We can eliminate this 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. - */ -#define NOT_NULL_NOT_EMPTY(x) ((x) && *(x)) - - if (tlsp_pre_jail_done && appl_state && appl_state != tlsp_client_ctx - && (NOT_NULL_NOT_EMPTY(init_props->cert_file) - || NOT_NULL_NOT_EMPTY(init_props->key_file) - || NOT_NULL_NOT_EMPTY(init_props->dcert_file) - || NOT_NULL_NOT_EMPTY(init_props->dkey_file) - || NOT_NULL_NOT_EMPTY(init_props->eccert_file) - || NOT_NULL_NOT_EMPTY(init_props->eckey_file) - || NOT_NULL_NOT_EMPTY(init_props->CAfile) - || NOT_NULL_NOT_EMPTY(init_props->CApath))) { - msg_warn("client request differs from tlsproxy_client_* settings"); - msg_warn("to avoid this warning, 1) configure a custom tlsproxy"); - msg_warn("service and 2) configure an smtp client with a"); - msg_warn("tlsproxy_service setting that resolves to the custom"); - msg_warn("tlsproxy service"); - } - /* * To maintain sanity, allow partial SSL_write() operations, and * allow SSL_write() buffer pointers to change after a WANT_READ or @@ -1473,9 +1501,9 @@ int main(int argc, char **argv) * 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". To make this work, the variables in a "compat" table - * must be initialized before the variables in the corresponding - * non-compat table. + * "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,