diff --git a/postfix/HISTORY b/postfix/HISTORY index 47bb88bfc..bdcd8bb57 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -22059,3 +22059,40 @@ Apologies for any names omitted. global/post_mail.h, global/verify.c, oqmgr/qmgr.c, oqmgr/qmgr.h, oqmgr/qmgr_message.c, qmgr/qmgr.c, qmgr/qmgr.h, qmgr/qmgr_message.c, verify/verify.c. + +20160102 + + Workaround: MacOS/X 10.11.x /bin/sh unsets DYLD_LIBRARY_PATH, + which breaks the build and install. Viktor Dukhovni and + Wietse. Files: makedefs, postfix-install, Makefile.in. + + Bitrot: OpenSSL 1.1.0-dev drops support for EXPORT ciphers + and ephemeral RSA. Viktor Dukhovni. Files: tls/tls_client.c, + tls/tls_rsa.c, tls/tls_server.c. + + Bugfix: memory leak in tls_set_eecdh_curve(). Viktor Dukhovni. + File: tls/tls_dh.c. + + Bugfix (introduced 20150326): when lmtp_fallback_relay + support was added, the code that generates lmtp_mumble + parameters from smtp_mumble parameters wasn't updated. File: + smtp/smtp-only. + + Bugfix (introduced 20151017): the smtpd_client_auth_rate_limit + implementation was not guarded with #ifdef USE_SASL_AUTH. + File: smtpd/smtpd.c. + +20160103 + + Feature: enable DANE policies when an MX host has a secure + TLSA DNS record, even if the MX DNS record was obtained + with insecure lookups. The existence of a secure TLSA record + implies that the host wants to talk TLS and not plaintext. + This behavior is controlled with smtp_tls_dane_insecure_mx_policy + (default: "dane", other settings: "encrypt" and "may"; the + latter is backwards-compatible with earlier Postfix releases). + Viktor Dukhovni. Files: mantools/postlink, proto/postconf.proto, + src/global/mail_params.h, src/posttls-finger/posttls-finger.c, + src/smtp/smtp-only, src/smtp/smtp.c, src/smtp/smtp.h, + src/smtp/smtp_addr.c, src/smtp/smtp_params.c, + src/smtp/smtp_tls_policy.c, src/tls/tls.h, src/tls/tls_client.c. diff --git a/postfix/Makefile.in b/postfix/Makefile.in index 47b1d699d..4d978de6c 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -117,19 +117,23 @@ printfck: update # shared=yes<->shared=no. install: update + SHLIB_ENV_VAR= SHLIB_ENV_VAL= \ $(SHLIB_ENV) shlib_directory=$(SHLIB_DIR_OVERRIDE) $(SHELL) \ postfix-install package: update + SHLIB_ENV_VAR= SHLIB_ENV_VAL= \ $(SHLIB_ENV) shlib_directory=$(SHLIB_DIR_OVERRIDE) $(SHELL) \ postfix-install -package upgrade: update + SHLIB_ENV_VAR= SHLIB_ENV_VAL= \ $(SHLIB_ENV) shlib_directory=$(SHLIB_DIR_OVERRIDE) $(SHELL) \ postfix-install -non-interactive non-interactive-package: update + SHLIB_ENV_VAR= SHLIB_ENV_VAL= \ $(SHLIB_ENV) shlib_directory=$(SHLIB_DIR_OVERRIDE) $(SHELL) \ postfix-install -non-interactive -package diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index 946f64b7f..430e381fc 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -562,6 +562,13 @@ SMTP(8) SMTP(8) Request that the Postfix SMTP client connects using the legacy SMTPS protocol instead of using the STARTTLS command. + Available in Postfix version 3.1 and later: + + smtp_tls_dane_insecure_mx_policy (dane) + The TLS policy for MX hosts with "secure" TLSA records when the + nexthop destination security level is dane, but the MX record + was found via an "insecure" MX lookup. + OBSOLETE STARTTLS CONTROLS The following configuration parameters exist for compatibility with Postfix versions before 2.3. Support for these will be removed in a diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 0cab4cfd1..986a82296 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -11797,6 +11797,45 @@ releases only the smtp_tls_ and opportunistic TLS always uses "export" or better (i.e. all) ciphers.

+ + +
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 dane, but the MX +record was found via an "insecure" MX lookup. The choices are: +

+ +
+
may
+
The TLSA records will be ignored and TLS will be optional. If +the MX host does not appear to support STARTTLS, or the STARTTLS +handshake fails, mail may be sent in the clear.
+
encrypt
+
The TLSA records will signal a requirement to use TLS. While +TLS encryption will be required, authentication will not be performed. +
+
dane (default)
+
The TLSA records will be used just as with "secure" MX records. +TLS encryption will be required, and, if at least one of the TLSA +records is "usable", authentication will be required. When +authentication succeeds, it will be logged only as "Trusted", not +"Verified", because the MX host name could have been forged.
+
+ +

Though with "insecure" MX records an active attacker can +compromise SMTP transport security by returning forged MX records, +such attacks are "tamper-evident" since any forged MX hostnames +will be recorded in the mail logs. Attackers who place a high value +staying hidden may be deterred from forging MX records.

+ +

+This feature is available in Postfix 3.1 and later. The may +policy is backwards-compatible with earlier Postfix versions. +

+ +
smtp_tls_dcert_file diff --git a/postfix/html/posttls-finger.1.html b/postfix/html/posttls-finger.1.html index c34c4db60..44dbd9eaa 100644 --- a/postfix/html/posttls-finger.1.html +++ b/postfix/html/posttls-finger.1.html @@ -231,31 +231,37 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) with these servers there will never be more than 1 reconnection attempt. + -M insecure_mx_policy (default: dane) + The TLS policy for MX hosts with "secure" TLSA records when the + nexthop destination security level is dane, but the MX record + was found via an "insecure" MX lookup. See the main.cf documen- + tation for smtp_tls_insecure_mx_policy for details. + -o name=value - Specify zero or more times to override the value of the main.cf - parameter name with value. Possible use-cases include overrid- - ing the values of TLS library parameters, or "myhostname" to + Specify zero or more times to override the value of the main.cf + parameter name with value. Possible use-cases include overrid- + ing the values of TLS library parameters, or "myhostname" to configure the SMTP EHLO name sent to the remote server. -p protocols (default: !SSLv2) - List of TLS protocols that posttls-finger will exclude or + List of TLS protocols that posttls-finger will exclude or include. See smtp_tls_mandatory_protocols for details. -P CApath/ (default: none) - The OpenSSL CApath/ directory (indexed via c_rehash(1)) for + The OpenSSL CApath/ directory (indexed via c_rehash(1)) for remote SMTP server certificate verification. By default no CAp- ath is used and no public CAs are trusted. -r delay - With a cacheable TLS session, disconnect and reconnect after + With a cacheable TLS session, disconnect and reconnect after delay seconds. Report whether the session is re-used. Retry if a - new server is encountered, up to 5 times or as specified with - the -m option. By default reconnection is disabled, specify a + new server is encountered, up to 5 times or as specified with + the -m option. By default reconnection is disabled, specify a positive delay to enable this behavior. - -S Disable SMTP; that is, connect to an LMTP server. The default - port for LMTP over TCP is 24. Alternative ports can specified - by appending ":servicename" or ":portnumber" to the destination + -S Disable SMTP; that is, connect to an LMTP server. The default + port for LMTP over TCP is 24. Alternative ports can specified + by appending ":servicename" or ":portnumber" to the destination argument. -t timeout (default: 30) @@ -263,28 +269,28 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) reading the remote server's 220 banner. -T timeout (default: 30) - The SMTP/LMTP command timeout for EHLO/LHLO, STARTTLS and QUIT. + The SMTP/LMTP command timeout for EHLO/LHLO, STARTTLS and QUIT. - -v Enable verbose Postfix logging. Specify more than once to + -v Enable verbose Postfix logging. Specify more than once to increase the level of verbose logging. - -w Enable outgoing TLS wrapper mode, or SMTPS support. This is - typically provided on port 465 by servers that are compatible - with the ad-hoc SMTP in SSL protocol, rather than the standard + -w Enable outgoing TLS wrapper mode, or SMTPS support. This is + typically 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 domain:port should of course provide such a service. [inet:]domain[:port] Connect via TCP to domain domain, port port. The default port is - smtp (or 24 with LMTP). With SMTP an MX lookup is performed to - resolve the domain to a host, unless the domain is enclosed in - []. If you want to connect to a specific MX host, for instance - mx1.example.com, specify [mx1.example.com] as the destination + smtp (or 24 with LMTP). With SMTP an MX lookup is performed to + resolve the domain to a host, unless the domain is enclosed in + []. If you want to connect to a specific MX host, for instance + mx1.example.com, specify [mx1.example.com] as the destination and example.com as a match argument. When using DNS, the desti- - nation domain is assumed fully qualified and no default domain - or search suffixes are applied; you must use fully-qualified - names or also enable native host lookups (these don't support - dane or dane-only as no DNSSEC validation information is avail- + nation domain is assumed fully qualified and no default domain + or search suffixes are applied; you must use fully-qualified + names or also enable native host lookups (these don't support + dane or dane-only as no DNSSEC validation information is avail- able via native lookups). unix:pathname @@ -293,8 +299,8 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) match ... With no match arguments specified, certificate peername matching uses the compiled-in default strategies for each security level. - If you specify one or more arguments, these will be used as the - list of certificate or public-key digests to match for the fin- + If you specify one or more arguments, these will be used as the + list of certificate or public-key digests to match for the fin- gerprint level, or as the list of DNS names to match in the cer- tificate at the verify and secure levels. If the security level is dane, or dane-only the match names are ignored, and hostname, diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index 946f64b7f..430e381fc 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -562,6 +562,13 @@ SMTP(8) SMTP(8) Request that the Postfix SMTP client connects using the legacy SMTPS protocol instead of using the STARTTLS command. + Available in Postfix version 3.1 and later: + + smtp_tls_dane_insecure_mx_policy (dane) + The TLS policy for MX hosts with "secure" TLSA records when the + nexthop destination security level is dane, but the MX record + was found via an "insecure" MX lookup. + OBSOLETE STARTTLS CONTROLS The following configuration parameters exist for compatibility with Postfix versions before 2.3. Support for these will be removed in a diff --git a/postfix/makedefs b/postfix/makedefs index 754eabac2..be79708ee 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -664,7 +664,9 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543 : ${SHLIB_SUFFIX=.dylib} : ${SHLIB_LD='cc -shared -Wl,-flat_namespace -Wl,-undefined,dynamic_lookup -Wl,-install_name,@rpath/${LIB}'} : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'} - : ${SHLIB_ENV="DYLD_LIBRARY_PATH=`pwd`/lib"} + # In MacOS/X 10.11.x /bin/sh unsets DYLD_LIBRARY_PATH, so we + # have export it into postfix-install indirectly! + : ${SHLIB_ENV="DYLD_LIBRARY_PATH=`pwd`/lib SHLIB_ENV_VAR=DYLD_LIBRARY_PATH SHLIB_ENV_VAL=`pwd`/lib"} : ${PLUGIN_LD='cc -shared -Wl,-flat_namespace -Wl,-undefined,dynamic_lookup'} ;; dcosx.1*) SYSTYPE=DCOSX1 diff --git a/postfix/man/man1/posttls-finger.1 b/postfix/man/man1/posttls-finger.1 index d9a2447cc..ca773102a 100644 --- a/postfix/man/man1/posttls-finger.1 +++ b/postfix/man/man1/posttls-finger.1 @@ -209,6 +209,11 @@ is likely to be effective for this destination. Some MTAs don't expose the underlying server identity in their EHLO response; with these servers there will never be more than 1 reconnection attempt. +.IP "\fB\-M \fIinsecure_mx_policy\fR (default: \fBdane\fR)" +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. See the main.cf +documentation for smtp_tls_insecure_mx_policy for details. .IP "\fB\-o \fIname=value\fR" Specify zero or more times to override the value of the main.cf parameter \fIname\fR with \fIvalue\fR. Possible use\-cases include diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 273a6164f..122b49545 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -7437,6 +7437,35 @@ 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_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 +record was found via an "insecure" MX lookup. The choices are: +.IP "\fBmay\fR" +The TLSA records will be ignored and TLS will be optional. If +the MX host does not appear to support STARTTLS, or the STARTTLS +handshake fails, mail may be sent in the clear. +.br +.IP "\fBencrypt\fR" +The TLSA records will signal a requirement to use TLS. While +TLS encryption will be required, authentication will not be performed. +.br +.IP "\fBdane\fR (default)" +The TLSA records will be used just as with "secure" MX records. +TLS encryption will be required, and, if at least one of the TLSA +records is "usable", authentication will be required. When +authentication succeeds, it will be logged only as "Trusted", not +"Verified", because the MX host name could have been forged. +.br +.br +Though with "insecure" MX records an active attacker can +compromise SMTP transport security by returning forged MX records, +such attacks are "tamper\-evident" since any forged MX hostnames +will be recorded in the mail logs. Attackers who place a high value +staying hidden may be deterred from forging MX records. +.PP +This feature is available in Postfix 3.1 and later. The \fBmay\fR +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. diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index 933151b65..9a3214318 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -498,6 +498,12 @@ Available in Postfix version 3.0 and later: .IP "\fBsmtp_tls_wrappermode (no)\fR" Request that the Postfix SMTP client connects using the legacy SMTPS protocol instead of using the STARTTLS command. +.PP +Available in Postfix version 3.1 and later: +.IP "\fBsmtp_tls_dane_insecure_mx_policy (dane)\fR" +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. .SH "OBSOLETE STARTTLS CONTROLS" .na .nf diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 2d1ab0736..9b5bfcd22 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -672,6 +672,7 @@ while (<>) { s;\bsmtp_tls_session_cache_database\b;$&;g; s;\bsmtp_tls_session_cache_timeout\b;$&;g; s;\bsmtp_tls_block_early_mail_reply\b;$&;g; + s;\bsmtp_tls_dane_insecure_mx_policy\b;$&;g; s;\bsmtp_tls_force_insecure_host_tlsa_lookup\b;$&;g; s;\bsmtp_tls_wrappermode\b;$&;g; s;\bsmtp_use_tls\b;$&;g; diff --git a/postfix/postfix-install b/postfix/postfix-install index b80069093..922402bfa 100644 --- a/postfix/postfix-install +++ b/postfix/postfix-install @@ -204,6 +204,11 @@ BACKUP_IFS="$IFS" # Override all LC_* settings and LANG for robustness. LC_ALL=C; export LC_ALL +if [ -n "$SHLIB_ENV_VAR" ]; then + junk="${SHLIB_ENV_VAL}" + eval export "$SHLIB_ENV_VAR=\$junk" +fi + USAGE="Usage: $0 [name=value] [option] -non-interactive Do not ask for installation parameters. -package Build a ready-to-install package. diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 33cf62923..09e5f0ebb 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -16593,6 +16593,41 @@ clients).

This feature is available in Postfix 3.1 and later.

+%PARAM smtp_tls_dane_insecure_mx_policy dane + +

The TLS policy for MX hosts with "secure" TLSA records when the +nexthop destination security level is dane, but the MX +record was found via an "insecure" MX lookup. The choices are: +

+ +
+
may
+
The TLSA records will be ignored and TLS will be optional. If +the MX host does not appear to support STARTTLS, or the STARTTLS +handshake fails, mail may be sent in the clear.
+
encrypt
+
The TLSA records will signal a requirement to use TLS. While +TLS encryption will be required, authentication will not be performed. +
+
dane (default)
+
The TLSA records will be used just as with "secure" MX records. +TLS encryption will be required, and, if at least one of the TLSA +records is "usable", authentication will be required. When +authentication succeeds, it will be logged only as "Trusted", not +"Verified", because the MX host name could have been forged.
+
+ +

Though with "insecure" MX records an active attacker can +compromise SMTP transport security by returning forged MX records, +such attacks are "tamper-evident" since any forged MX hostnames +will be recorded in the mail logs. Attackers who place a high value +staying hidden may be deterred from forging MX records.

+ +

+This feature is available in Postfix 3.1 and later. The may +policy is backwards-compatible with earlier Postfix versions. +

+ %PARAM address_verify_pending_request_limit see "postconf -d" output

A safety limit that prevents address verification requests from diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 81464b1e0..2706981da 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1580,6 +1580,11 @@ extern bool var_smtp_tls_blk_early_mail_reply; #define DEF_LMTP_TLS_FORCE_TLSA 0 extern bool var_smtp_tls_force_tlsa; + /* SMTP only */ +#define VAR_SMTP_TLS_INSECURE_MX_POLICY "smtp_tls_dane_insecure_mx_policy" +#define DEF_SMTP_TLS_INSECURE_MX_POLICY "dane" +extern char *var_smtp_tls_insecure_mx_policy; + /* * SASL authentication support, SMTP server side. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 3fa1ccd16..1890675fc 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 "20151227" +#define MAIL_RELEASE_DATE "20160103" #define MAIL_VERSION_NUMBER "3.1" #ifdef SNAPSHOT diff --git a/postfix/src/posttls-finger/posttls-finger.c b/postfix/src/posttls-finger/posttls-finger.c index b3fe68b8d..bbba7aa36 100644 --- a/postfix/src/posttls-finger/posttls-finger.c +++ b/postfix/src/posttls-finger/posttls-finger.c @@ -203,6 +203,11 @@ /* don't expose the underlying server identity in their EHLO /* response; with these servers there will never be more than /* 1 reconnection attempt. +/* .IP "\fB-M \fIinsecure_mx_policy\fR (default: \fBdane\fR)" +/* 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. See the main.cf +/* documentation for smtp_tls_insecure_mx_policy for details. /* .IP "\fB-o \fIname=value\fR" /* Specify zero or more times to override the value of the main.cf /* parameter \fIname\fR with \fIvalue\fR. Possible use-cases include @@ -453,6 +458,7 @@ typedef struct STATE { TLS_DANE *ddane; /* DANE TLSA from DNS */ char *grade; /* Minimum cipher grade */ char *protocols; /* Protocol inclusion/exclusion */ + int mxinsec_level; /* DANE for insecure MX RRs? */ #endif OPTIONS options; /* JCL */ } STATE; @@ -1107,7 +1113,14 @@ static DNS_RR *mx_addr_list(STATE *state, DNS_RR *mx_names) static const char *myname = "mx_addr_list"; DNS_RR *addr_list = 0; DNS_RR *rr; - int res_opt = mx_names->dnssec_valid ? RES_USE_DNSSEC : 0; + int res_opt = 0; + + if (mx_names->dnssec_valid) + res_opt = RES_USE_DNSSEC; +#ifdef USE_TLS + else if (state->mxinsec_level > TLS_LEV_MAY) + res_opt = RES_USE_DNSSEC; +#endif for (rr = mx_names; rr; rr = rr->next) { if (rr->type != T_MX) @@ -1226,7 +1239,8 @@ static int dane_host_level(STATE *state, DNS_RR *addr) #ifdef USE_TLS if (TLS_DANE_BASED(level)) { - if (state->mx == 0 || state->mx->dnssec_valid) { + if (state->mx == 0 || state->mx->dnssec_valid || + state->mxinsec_level > TLS_LEV_MAY) { if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE)) tls_dane_verbose(1); else @@ -1259,12 +1273,22 @@ static int dane_host_level(STATE *state, DNS_RR *addr) } else if (!TLS_DANE_HASTA(state->ddane) && !TLS_DANE_HASEE(state->ddane)) { msg_panic("DANE activated with no TLSA records to match"); + } else if (state->mx && !state->mx->dnssec_valid && + state->mxinsec_level == TLS_LEV_ENCRYPT) { + msg_info("TLSA RRs found, MX RRset insecure: just encrypt"); + tls_dane_free(state->ddane); + state->ddane = 0; + level = TLS_LEV_ENCRYPT; } else { if (state->match) argv_free(state->match); argv_add(state->match = argv_alloc(2), state->ddane->base_domain, ARGV_END); if (state->mx) { + if (!state->mx->dnssec_valid) { + msg_info("MX RRset insecure: log verified as trusted"); + state->ddane->flags |= TLS_DANE_FLAG_MXINSEC; + } if (strcmp(state->mx->qname, state->mx->rname) == 0) argv_add(state->match, state->mx->qname, ARGV_END); else @@ -1272,6 +1296,10 @@ static int dane_host_level(STATE *state, DNS_RR *addr) state->mx->qname, ARGV_END); } } + } else if (state->mx && !state->mx->dnssec_valid && + state->mxinsec_level == TLS_LEV_MAY) { + msg_info("MX RRset is insecure: try to encrypt"); + level = TLS_LEV_MAY; } else { level = TLS_LEV_SECURE; } @@ -1642,7 +1670,7 @@ 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:p:P:r:w" +#define TLSOPTS "A:Cd:fF:g:k:K:l:L:m:M:p:P:r:w" state->mdalg = mystrdup("sha1"); state->CApath = mystrdup(""); @@ -1652,6 +1680,7 @@ static void parse_options(STATE *state, int argc, char *argv[]) state->options.tas = argv_alloc(1); state->options.logopts = 0; state->level = TLS_LEV_DANE; + state->mxinsec_level = TLS_LEV_DANE; #else #define TLSOPTS "" state->level = TLS_LEV_NONE; @@ -1738,6 +1767,16 @@ static void parse_options(STATE *state, int argc, char *argv[]) case 'm': state->max_reconnect = atoi(optarg); break; + case 'M': + switch (state->mxinsec_level = tls_level_lookup(optarg)) { + case TLS_LEV_MAY: + case TLS_LEV_ENCRYPT: + case TLS_LEV_DANE: + break; + default: + msg_fatal("bad '-M' option value: %s", optarg); + } + break; case 'p': myfree(state->protocols); state->protocols = mystrdup(optarg); diff --git a/postfix/src/smtp/smtp-only b/postfix/src/smtp/smtp-only index 134dcd452..ee9288da1 100644 --- a/postfix/src/smtp/smtp-only +++ b/postfix/src/smtp/smtp-only @@ -1,4 +1,4 @@ _ALWAYS_EHLO _NEVER_EHLO -_SMTP_FALLBACK _IGN_MX_LOOKUP_ERR +_INSECURE_MX_POLICY diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index 6ca453749..437d8423c 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -468,6 +468,12 @@ /* .IP "\fBsmtp_tls_wrappermode (no)\fR" /* Request that the Postfix SMTP client connects using the /* legacy SMTPS protocol instead of using the STARTTLS command. +/* .PP +/* Available in Postfix version 3.1 and later: +/* .IP "\fBsmtp_tls_dane_insecure_mx_policy (dane)\fR" +/* 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. /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -890,6 +896,7 @@ char *var_smtp_tls_eccert_file; char *var_smtp_tls_eckey_file; bool var_smtp_tls_blk_early_mail_reply; bool var_smtp_tls_force_tlsa; +char *var_smtp_tls_insecure_mx_policy; #endif @@ -942,6 +949,7 @@ HBC_CHECKS *smtp_body_checks; /* limited body checks */ * OpenSSL client state (opaque handle) */ TLS_APPL_STATE *smtp_tls_ctx; +int smtp_tls_insecure_mx_policy; #endif @@ -1061,6 +1069,22 @@ static void post_init(char *unused_name, char **unused_argv) var_disable_dns = (smtp_dns_support == SMTP_DNS_DISABLED); } +#ifdef USE_TLS + if (smtp_mode) { + smtp_tls_insecure_mx_policy = + tls_level_lookup(var_smtp_tls_insecure_mx_policy); + switch (smtp_tls_insecure_mx_policy) { + case TLS_LEV_MAY: + case TLS_LEV_ENCRYPT: + case TLS_LEV_DANE: + break; + default: + msg_fatal("invalid %s: \"%s\"", VAR_SMTP_TLS_INSECURE_MX_POLICY, + var_smtp_tls_insecure_mx_policy); + } + } +#endif + /* * Select hostname lookup mechanisms. */ diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 90e7c3b2c..1a0a6a6a7 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -290,6 +290,7 @@ extern unsigned smtp_dns_res_opt; /* DNS query flags */ #ifdef USE_TLS extern TLS_APPL_STATE *smtp_tls_ctx; /* client-side TLS engine */ +extern int smtp_tls_insecure_mx_policy; /* DANE post insecure MX? */ #endif diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c index d9de504bd..789a21806 100644 --- a/postfix/src/smtp/smtp_addr.c +++ b/postfix/src/smtp/smtp_addr.c @@ -247,7 +247,14 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why) { DNS_RR *addr_list = 0; DNS_RR *rr; - int res_opt = mx_names->dnssec_valid ? RES_USE_DNSSEC : 0; + int res_opt = 0; + + if (mx_names->dnssec_valid) + res_opt = RES_USE_DNSSEC; +#ifdef USE_TLS + else if (smtp_tls_insecure_mx_policy > TLS_LEV_MAY) + res_opt = RES_USE_DNSSEC; +#endif /* * As long as we are able to look up any host address, we ignore problems diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c index 234644137..34f83e80a 100644 --- a/postfix/src/smtp/smtp_params.c +++ b/postfix/src/smtp/smtp_params.c @@ -29,6 +29,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_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, VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0, diff --git a/postfix/src/smtp/smtp_tls_policy.c b/postfix/src/smtp/smtp_tls_policy.c index afaaff769..87f928985 100644 --- a/postfix/src/smtp/smtp_tls_policy.c +++ b/postfix/src/smtp/smtp_tls_policy.c @@ -714,7 +714,7 @@ static int global_tls_level(void) #define NONDANE_CONFIG 0 /* Administrator's fault */ #define NONDANE_DEST 1 /* Remote server's fault */ -#define DANE_UNUSABLE 2 /* Remote server's fault */ +#define DANE_CANTAUTH 2 /* Remote server's fault */ static void PRINTFLIKE(4, 5) dane_incompat(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter, @@ -725,7 +725,7 @@ static void PRINTFLIKE(4, 5) dane_incompat(SMTP_TLS_POLICY *tls, va_start(ap, fmt); if (tls->level == TLS_LEV_DANE) { - tls->level = (errtype == DANE_UNUSABLE) ? TLS_LEV_ENCRYPT : TLS_LEV_MAY; + tls->level = (errtype == DANE_CANTAUTH) ? TLS_LEV_ENCRYPT : TLS_LEV_MAY; if (errtype == NONDANE_CONFIG) vmsg_warn(fmt, ap); else if (msg_verbose) @@ -792,8 +792,9 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter) STR(iter->dest), policy_name(tls->level)); return; } - /* When the MX name is present and insecure, DANE does not apply. */ - if (iter->mx && !iter->mx->dnssec_valid) { + /* When the MX name is present and insecure, DANE may not apply. */ + if (iter->mx && !iter->mx->dnssec_valid + && smtp_tls_insecure_mx_policy <= TLS_LEV_MAY) { dane_incompat(tls, iter, NONDANE_DEST, "non DNSSEC destination"); return; } @@ -825,11 +826,25 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter) * given verifier some of the CAs are surely not trustworthy). */ if (tls_dane_unusable(dane)) { - dane_incompat(tls, iter, DANE_UNUSABLE, "TLSA records unusable"); + dane_incompat(tls, iter, DANE_CANTAUTH, "TLSA records unusable"); tls_dane_free(dane); return; } + /* + * Perhaps downgrade to "encrypt" if MX is insecure. + */ + if (iter->mx && !iter->mx->dnssec_valid) { + if (smtp_tls_insecure_mx_policy == TLS_LEV_ENCRYPT) { + dane_incompat(tls, iter, DANE_CANTAUTH, + "Verification not possible, MX RRset is insecure"); + tls_dane_free(dane); + return; + } + /* For correct logging in tls_client_start() */ + dane->flags |= TLS_DANE_FLAG_MXINSEC; + } + /* * With DANE trust anchors, peername matching is not configurable. */ diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 7111808cc..e19a586bf 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1905,6 +1905,8 @@ static void helo_reset(SMTPD_STATE *state) } } +#ifdef USE_SASL_AUTH + /* smtpd_sasl_auth_cmd_wrapper - smtpd_sasl_auth_cmd front-end */ static int smtpd_sasl_auth_cmd_wrapper(SMTPD_STATE *state, int argc, @@ -1931,6 +1933,8 @@ static int smtpd_sasl_auth_cmd_wrapper(SMTPD_STATE *state, int argc, return (smtpd_sasl_auth_cmd(state, argc, argv)); } +#endif + /* mail_open_stream - open mail queue file or IPC stream */ static int mail_open_stream(SMTPD_STATE *state) diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index c5a6d4eb8..7df2ccad8 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -141,6 +141,7 @@ extern const NAME_CODE tls_level_table[]; #define TLS_DANE_FLAG_NORRS (1<<0) /* Nothing found in DNS */ #define TLS_DANE_FLAG_EMPTY (1<<1) /* Nothing usable found in DNS */ #define TLS_DANE_FLAG_ERROR (1<<2) /* TLSA record lookup error */ +#define TLS_DANE_FLAG_MXINSEC (1<<3) /* Insecure MX record */ #define tls_dane_unusable(dane) ((dane)->flags & TLS_DANE_FLAG_EMPTY) #define tls_dane_notfound(dane) ((dane)->flags & TLS_DANE_FLAG_NORRS) @@ -181,7 +182,7 @@ typedef struct TLS_DANE { TLS_CERTS *certs; /* Full trust-anchor certificates */ TLS_PKEYS *pkeys; /* Full trust-anchor public keys */ char *base_domain; /* Base domain of TLSA RRset */ - int flags; /* Conflate cert and pkey digests */ + int flags; /* Lookup status */ time_t expires; /* Expiration time of this record */ int refs; /* Reference count */ } TLS_DANE; diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c index 4584a37d6..9868384c3 100644 --- a/postfix/src/tls/tls_client.c +++ b/postfix/src/tls/tls_client.c @@ -347,7 +347,7 @@ 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. @@ -431,12 +431,18 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) return (0); } + /* + * 2015-12-05: Ephemeral RSA removed from OpenSSL 1.1.0-dev + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /* * According to the OpenSSL documentation, temporary RSA key is needed * export ciphers are in use. We have to provide one, so well, we just do * it. */ SSL_CTX_set_tmp_rsa_callback(client_ctx, tls_tmp_rsa_cb); +#endif /* * Finally, the setup for the server certificate checking, done "by the @@ -1109,6 +1115,14 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) */ tls_stream_start(props->stream, TLScontext); + /* + * Can't really be DANE verified if the MX RRset was insecure + */ + if (TLS_DANE_BASED(props->tls_level) + && (props->dane->flags & TLS_DANE_FLAG_MXINSEC) != 0) { + TLScontext->peer_status &= ~TLS_CERT_FLAG_MATCHED; + } + /* * All the key facts in a single log entry. */ diff --git a/postfix/src/tls/tls_dh.c b/postfix/src/tls/tls_dh.c index f42b8c795..af3c59e0d 100644 --- a/postfix/src/tls/tls_dh.c +++ b/postfix/src/tls/tls_dh.c @@ -88,13 +88,14 @@ /* * Compiled-in DH parameters. Used when no parameters are explicitly loaded - * from a site-specific file. Using an ASN.1 DER encoding avoids the need to - * explicitly manipulate the internal represenation of DH parameter objects. - * + * from a site-specific file. Using an ASN.1 DER encoding avoids the need + * to explicitly manipulate the internal representation of DH parameter + * objects. + * * 512-bit parameters are used for export ciphers, and 2048-bit parameters are - * used for non-export ciphers. The non-export group is now 2048-bit, as 1024 - * bits is increasingly considered to weak by clients. When greater security - * is required, use EECDH. + * used for non-export ciphers. The non-export group is now 2048-bit, as + * 1024 bits is increasingly considered to weak by clients. When greater + * security is required, use EECDH. */ /*- @@ -173,14 +174,13 @@ void tls_set_dh_from_file(const char *path, int bits) } /* - * This function is the first to set the DH parameters, but free any prior - * value just in case the call sequence changes some day. + * This function is the first to set the DH parameters, but free any + * prior value just in case the call sequence changes some day. */ if (*dhPtr) { DH_free(*dhPtr); *dhPtr = 0; } - if ((paramfile = fopen(path, "r")) != 0) { if ((*dhPtr = PEM_read_DHparams(paramfile, 0, 0, 0)) == 0) { msg_warn("cannot load %d-bit DH parameters from file %s" @@ -279,10 +279,12 @@ int tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade) 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); } + EC_KEY_free(ecdh); #endif return (1); } diff --git a/postfix/src/tls/tls_rsa.c b/postfix/src/tls/tls_rsa.c index aba4142d2..c440b1e9f 100644 --- a/postfix/src/tls/tls_rsa.c +++ b/postfix/src/tls/tls_rsa.c @@ -54,6 +54,11 @@ #include #include + /* + * 2015-12-05: Ephemeral RSA removed from OpenSSL 1.1.0-dev + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /* tls_tmp_rsa_cb - call-back to generate ephemeral RSA key */ RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int export, int keylength) @@ -91,14 +96,21 @@ RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int export, int keylength) return (rsa_tmp); } +#endif /* OPENSSL_VERSION_NUMBER */ + #ifdef TEST #include int main(int unused_argc, char *const argv[]) { + int ok = 0; + + /* + * 2015-12-05: Ephemeral RSA removed from OpenSSL 1.1.0-dev + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L RSA *rsa; - int ok; msg_vstream_init(argv[0], VSTREAM_ERR); @@ -111,6 +123,7 @@ int main(int unused_argc, char *const argv[]) /* Non-export or unexpected bit length should fail */ ok = ok && tls_tmp_rsa_cb(0, 0, 512) == 0; ok = ok && tls_tmp_rsa_cb(0, 1, 1024) == 0; +#endif return ok ? 0 : 1; } diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c index 1444a44e3..0a78ae653 100644 --- a/postfix/src/tls/tls_server.c +++ b/postfix/src/tls/tls_server.c @@ -569,12 +569,18 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) return (0); } + /* + * 2015-12-05: Ephemeral RSA removed from OpenSSL 1.1.0-dev + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /* * According to OpenSSL documentation, a temporary RSA key is needed when * export ciphers are in use, because the certified key cannot be * directly used. */ SSL_CTX_set_tmp_rsa_callback(server_ctx, tls_tmp_rsa_cb); +#endif /* * Diffie-Hellman key generation parameters can either be loaded from