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.
The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
<b>TLS CLIENT CONTROLS</b>
- These parameters allow <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> 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
+ <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> 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:
<b><a href="postconf.5.html#tlsproxy_client_CAfile">tlsproxy_client_CAfile</a> ($<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>)</b>
- 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.
<b><a href="postconf.5.html#tlsproxy_client_CApath">tlsproxy_client_CApath</a> ($<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a>)</b>
- Directory with PEM format Certification Authority certificates
- that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client uses to verify a remote TLS
+ Directory with PEM format Certification Authority certificates
+ that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client uses to verify a remote TLS
server certificate.
<b><a href="postconf.5.html#tlsproxy_client_cert_file">tlsproxy_client_cert_file</a> ($<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA certificate in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA certificate in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_key_file">tlsproxy_client_key_file</a> ($<a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA private key in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA private key in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_dcert_file">tlsproxy_client_dcert_file</a> ($<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA certificate in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA certificate in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_dkey_file">tlsproxy_client_dkey_file</a> ($<a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA private key in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA private key in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_eccert_file">tlsproxy_client_eccert_file</a> ($<a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA certificate in
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA certificate in
PEM format.
<b><a href="postconf.5.html#tlsproxy_client_eckey_file">tlsproxy_client_eckey_file</a> ($<a href="postconf.5.html#smtp_tls_eckey_file">smtp_tls_eckey_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA private key in
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA private key in
PEM format.
<b><a href="postconf.5.html#tlsproxy_client_fingerprint_digest">tlsproxy_client_fingerprint_digest</a> ($<a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a>)</b>
certificate fingerprints.
<b><a href="postconf.5.html#tlsproxy_client_loglevel">tlsproxy_client_loglevel</a> ($<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a>)</b>
- Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client logging of TLS
+ Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client logging of TLS
activity.
<b><a href="postconf.5.html#tlsproxy_client_loglevel_parameter">tlsproxy_client_loglevel_parameter</a> (<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a>)</b>
The verification depth for remote TLS server certificates.
<b><a href="postconf.5.html#tlsproxy_client_security_level">tlsproxy_client_security_level</a> ($<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>)</b>
- The default TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
+ The default TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
client.
<b><a href="postconf.5.html#tlsproxy_client_policy_maps">tlsproxy_client_policy_maps</a> ($<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>)</b>
- Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
+ Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
security policy by next-hop destination.
<b><a href="postconf.5.html#tlsproxy_client_use_tls">tlsproxy_client_use_tls</a> ($<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>)</b>
- Opportunistic mode: use TLS when a remote server announces TLS
+ Opportunistic mode: use TLS when a remote server announces TLS
support.
<b><a href="postconf.5.html#tlsproxy_client_enforce_tls">tlsproxy_client_enforce_tls</a> ($<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>)</b>
- Enforcement mode: require that SMTP servers use TLS encryption.
+ Enforcement mode: require that SMTP servers use TLS encryption.
<b><a href="postconf.5.html#tlsproxy_client_per_site">tlsproxy_client_per_site</a> ($<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>)</b>
- Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
- usage policy by next-hop destination and by remote TLS server
+ Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
+ usage policy by next-hop destination and by remote TLS server
hostname.
<b>OBSOLETE STARTTLS SUPPORT CONTROLS</b>
- These parameters are supported for compatibility with <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy
+ These parameters are supported for compatibility with <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy
parameters.
<b><a href="postconf.5.html#tlsproxy_use_tls">tlsproxy_use_tls</a> ($<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b>
- 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.
<b><a href="postconf.5.html#tlsproxy_enforce_tls">tlsproxy_enforce_tls</a> ($<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b>
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- 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:
.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"
* 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
/* 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"
* 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
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
* 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,