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,