From 28646fa9c74b94722eadd7bc2d9c285245aded80 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 20 Dec 2017 21:14:06 +0000 Subject: [PATCH] DANE/GnuTLS: ignore traditional CA anchor validation in DANE-EE mode Not quite right for a mixed TA+EE set of TLSA records, but better than always-enforcing --- src/src/tls-gnu.c | 21 +++++++++++++++------ test/confs/5820 | 2 +- test/confs/5840 | 2 +- test/dnszones-src/db.example.com | 20 ++++++++++++++++++++ test/log/5820 | 13 +++++++++++++ test/log/5840 | 12 ++++++++++++ test/scripts/5820-DANE-GnuTLS/5820 | 15 +++++++++++++++ test/scripts/5840-DANE-OpenSSL/5840 | 15 +++++++++++++++ test/stderr/5820 | 4 ++++ test/stderr/5840 | 4 ++++ test/stdout/5820 | 4 ++++ test/stdout/5840 | 4 ++++ 12 files changed, 108 insertions(+), 8 deletions(-) diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 9f166691a..8c8a00f72 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1573,7 +1573,7 @@ Returns: */ static BOOL -verify_certificate(exim_gnutls_state_st *state, uschar ** errstr) +verify_certificate(exim_gnutls_state_st * state, uschar ** errstr) { int rc; uint verify; @@ -1625,6 +1625,16 @@ else goto badcert; } state->peer_dane_verified = TRUE; + + /* If there were only EE-mode TLSA records present, no checks on cert anchor + valididation or cert names are required. For a TA record only, or a mixed + set, do them (we cannot tell if an EE record worked). */ + + if (!(tls_out.tlsa_usage & (1 << 2))) + { + state->peer_cert_verified = TRUE; + goto goodcert; + } } #endif @@ -1633,9 +1643,7 @@ else /* Handle the result of verification. INVALID is set if any others are. */ -if (rc < 0 || - verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED) - ) +if (rc < 0 || verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) { state->peer_cert_verified = FALSE; if (!*errstr) @@ -1676,8 +1684,9 @@ else state->peerdn ? state->peerdn : US""); } -state->tlsp->peerdn = state->peerdn; -return TRUE; +goodcert: + state->tlsp->peerdn = state->peerdn; + return TRUE; badcert: gnutls_alert_send(state->session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE); diff --git a/test/confs/5820 b/test/confs/5820 index d4dce2f85..72402881a 100644 --- a/test/confs/5820 +++ b/test/confs/5820 @@ -64,7 +64,7 @@ begin transports send_to_server: driver = smtp allow_localhost - port = ${if match {$host}{\Ntest.ex$\N} {PORT_D}{25}} + port = PORT_D hosts_try_dane = * hosts_require_dane = HOSTIPV4 diff --git a/test/confs/5840 b/test/confs/5840 index 10ca2111b..754945d6e 100644 --- a/test/confs/5840 +++ b/test/confs/5840 @@ -69,7 +69,7 @@ begin transports send_to_server: driver = smtp allow_localhost - port = ${if match {$host}{\Ntest.ex$\N} {PORT_D}{25}} + port = PORT_D hosts_try_dane = * hosts_require_dane = HOSTIPV4 diff --git a/test/dnszones-src/db.example.com b/test/dnszones-src/db.example.com index bc209ce5a..b00c87d13 100644 --- a/test/dnszones-src/db.example.com +++ b/test/dnszones-src/db.example.com @@ -22,4 +22,24 @@ example.com. NS exim.example.com. server1 A HOSTIPV4 +; DANE testing + +; a broken dane config where the name does not match in the cert, TA-mode, dane-requested +; NOTE: the server uses the example.net cert hence the mismatch +; +; openssl x509 -in aux-fixed/exim-ca/example.net/CA/CA.pem -fingerprint -sha256 -noout \ +; | awk -F= '{print $2}' | tr -d : | tr '[A-F]' '[a-f]' +; +; +DNSSEC danebroken7 A 127.0.0.1 +DNSSEC _1225._tcp.danebroken7 TLSA 2 0 1 13646cc92c038932f57f752559271b893045eda39f765fc8369b05b2b9c3ac88 + +; the same, EE-mode +; +; openssl x509 -in aux-fixed/exim-ca/example.net/server1.example.net/server1.example.net.pem -noout -pubkey \ +; | openssl pkey -pubin -outform DER | openssl dgst -sha256 | awk '{print $2}' +; +DNSSEC danebroken8 A 127.0.0.1 +DNSSEC _1225._tcp.danebroken8 TLSA 3 1 1 3cc2a6efabd847663b92f827681fd8612fd4d001ea85057d79ea541fb2de02ac + ; End diff --git a/test/log/5820 b/test/log/5820 index 767e70e68..81d4d0799 100644 --- a/test/log/5820 +++ b/test/log/5820 @@ -59,6 +59,12 @@ 1999-03-02 09:44:33 10HmbV-0005vi-00 ** CALLER@danebroken6.test.ex R=client T=send_to_server: DANE error: danebroken6.test.ex lookup not DNSSEC 1999-03-02 09:44:33 10HmbV-0005vi-00 CALLER@danebroken6.test.ex: error ignored 1999-03-02 09:44:33 10HmbV-0005vi-00 Completed +1999-03-02 09:44:33 10HmbW-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken7.example.com +1999-03-02 09:44:33 10HmbW-0005vi-00 DANE attempt failed; TLS connection to danebroken7.example.com [127.0.0.1]: (certificate verification failed): certificate invalid +1999-03-02 09:44:33 10HmbW-0005vi-00 == CALLER@danebroken7.example.com R=client T=send_to_server defer (-37) H=danebroken7.example.com [127.0.0.1]: TLS session: (certificate verification failed): certificate invalid +1999-03-02 09:44:33 10HmbX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken8.example.com +1999-03-02 09:44:33 10HmbX-0005vi-00 => CALLER@danebroken8.example.com R=client T=send_to_server H=danebroken8.example.com [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=dane DN="CN=server1.example.net" C="250 OK id=10HmbY-0005vi-00" +1999-03-02 09:44:33 10HmbX-0005vi-00 Completed ******** SERVER ******** 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 @@ -105,3 +111,10 @@ 1999-03-02 09:44:33 10HmbU-0005vi-00 <= <> H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=no S=sss id=E10HmbT-0005vi-00@myhost.test.ex for CALLER@danebroken5.test.ex 1999-03-02 09:44:33 10HmbU-0005vi-00 => :blackhole: R=server 1999-03-02 09:44:33 10HmbU-0005vi-00 Completed +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 TLS error on connection from localhost [127.0.0.1] (recv): A TLS fatal alert has been received.: Certificate is bad +1999-03-02 09:44:33 TLS error on connection from localhost [127.0.0.1] (send): The specified session has been invalidated for some reason. +1999-03-02 09:44:33 "rcpt ACL" +1999-03-02 09:44:33 10HmbY-0005vi-00 <= <> H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=no S=sss id=E10HmbX-0005vi-00@myhost.test.ex for CALLER@danebroken8.example.com +1999-03-02 09:44:33 10HmbY-0005vi-00 => :blackhole: R=server +1999-03-02 09:44:33 10HmbY-0005vi-00 Completed diff --git a/test/log/5840 b/test/log/5840 index 2c9a16f0f..756f442fb 100644 --- a/test/log/5840 +++ b/test/log/5840 @@ -65,6 +65,12 @@ 1999-03-02 09:44:33 10HmbX-0005vi-00 ** CALLER@danebroken6.test.ex R=client T=send_to_server: DANE error: danebroken6.test.ex lookup not DNSSEC 1999-03-02 09:44:33 10HmbX-0005vi-00 CALLER@danebroken6.test.ex: error ignored 1999-03-02 09:44:33 10HmbX-0005vi-00 Completed +1999-03-02 09:44:33 10HmbY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken7.example.com +1999-03-02 09:44:33 10HmbY-0005vi-00 DANE attempt failed; TLS connection to danebroken7.example.com [127.0.0.1]: (SSL_connect): error:xxxxxxxx:SSL routines:ssl3_get_server_certificate:certificate verify failed +1999-03-02 09:44:33 10HmbY-0005vi-00 == CALLER@danebroken7.example.com R=client T=send_to_server defer (-37) H=danebroken7.example.com [127.0.0.1]: TLS session: (SSL_connect): error: <> +1999-03-02 09:44:33 10HmbZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken8.example.com +1999-03-02 09:44:33 10HmbZ-0005vi-00 => CALLER@danebroken8.example.com R=client T=send_to_server H=danebroken8.example.com [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=dane DN="/CN=server1.example.net" C="250 OK id=10HmcA-0005vi-00" +1999-03-02 09:44:33 10HmbZ-0005vi-00 Completed ******** SERVER ******** 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 @@ -115,3 +121,9 @@ 1999-03-02 09:44:33 10HmbW-0005vi-00 <= <> H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLSv1:ke-RSA-AES256-SHA:xxx CV=no S=sss id=E10HmbV-0005vi-00@myhost.test.ex for CALLER@danebroken5.test.ex 1999-03-02 09:44:33 10HmbW-0005vi-00 => :blackhole: R=server 1999-03-02 09:44:33 10HmbW-0005vi-00 Completed +1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 +1999-03-02 09:44:33 TLS error on connection from localhost (myhost.test.ex) [127.0.0.1] (SSL_accept): error: <> +1999-03-02 09:44:33 "rcpt ACL" +1999-03-02 09:44:33 10HmcA-0005vi-00 <= <> H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLSv1:ke-RSA-AES256-SHA:xxx CV=no S=sss id=E10HmbZ-0005vi-00@myhost.test.ex for CALLER@danebroken8.example.com +1999-03-02 09:44:33 10HmcA-0005vi-00 => :blackhole: R=server +1999-03-02 09:44:33 10HmcA-0005vi-00 Completed diff --git a/test/scripts/5820-DANE-GnuTLS/5820 b/test/scripts/5820-DANE-GnuTLS/5820 index 84684da53..f5ac4a7fe 100644 --- a/test/scripts/5820-DANE-GnuTLS/5820 +++ b/test/scripts/5820-DANE-GnuTLS/5820 @@ -103,4 +103,19 @@ Testing **** # killdaemon + + +### A server with a name not matching the cert. TA-mode; should fail +exim -DSERVER=server -DDETAILS=cert.net -bd -oX PORT_D +**** +exim -odf CALLER@danebroken7.example.com +Testing +**** +# +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode +exim -odf CALLER@danebroken8.example.com +Testing +**** +# +killdaemon no_msglog_check diff --git a/test/scripts/5840-DANE-OpenSSL/5840 b/test/scripts/5840-DANE-OpenSSL/5840 index 7d86621cc..b1ea2f307 100644 --- a/test/scripts/5840-DANE-OpenSSL/5840 +++ b/test/scripts/5840-DANE-OpenSSL/5840 @@ -111,4 +111,19 @@ Testing **** # killdaemon + + +### A server with a name not matching the cert. TA-mode; should fail +exim -DSERVER=server -DDETAILS=cert.net -bd -oX PORT_D +**** +exim -odf CALLER@danebroken7.example.com +Testing +**** +# +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode +exim -odf CALLER@danebroken8.example.com +Testing +**** +# +killdaemon no_msglog_check diff --git a/test/stderr/5820 b/test/stderr/5820 index 8cd66384e..43492b5f7 100644 --- a/test/stderr/5820 +++ b/test/stderr/5820 @@ -79,6 +79,8 @@ LOG: unexpected disconnection while reading SMTP command from [127.0.0.1] D=qqs ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode ******** SERVER ******** ### TLSA (3 1 1) @@ -98,3 +100,5 @@ LOG: unexpected disconnection while reading SMTP command from [127.0.0.1] D=qqs ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode diff --git a/test/stderr/5840 b/test/stderr/5840 index 81a812149..629277126 100644 --- a/test/stderr/5840 +++ b/test/stderr/5840 @@ -81,6 +81,8 @@ LOG: unexpected disconnection while reading SMTP command from [127.0.0.1] D=qqs ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode ******** SERVER ******** ### TLSA (3 1 1) @@ -101,3 +103,5 @@ LOG: unexpected disconnection while reading SMTP command from [127.0.0.1] D=qqs ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode diff --git a/test/stdout/5820 b/test/stdout/5820 index 49dac098a..35e52c5d1 100644 --- a/test/stdout/5820 +++ b/test/stdout/5820 @@ -24,6 +24,8 @@ ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode ******** SERVER ******** ### TLSA (3 1 1) @@ -43,3 +45,5 @@ ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode diff --git a/test/stdout/5840 b/test/stdout/5840 index 36a3bd158..947f802a7 100644 --- a/test/stdout/5840 +++ b/test/stdout/5840 @@ -25,6 +25,8 @@ ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode ******** SERVER ******** ### TLSA (3 1 1) @@ -45,3 +47,5 @@ ### A server insecurely serving a good TLSA record, dane required (delivery should fail) ### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE) ### A server insecurely serving a good A record, dane required (delivery should fail) +### A server with a name not matching the cert. TA-mode; should fail +### A server with a name not matching the cert. EE-mode; should deliver and claim DANE mode -- 2.30.2