summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-docbook/spec.xfpt20
-rw-r--r--doc/doc-txt/NewStuff2
-rw-r--r--src/src/transports/smtp.c19
-rw-r--r--test/confs/586196
l---------test/confs/58811
-rw-r--r--test/log/5861102
-rw-r--r--test/log/5881101
-rw-r--r--test/scripts/5860-DANE-OpenSSL-events/5861104
l---------test/scripts/5880-DANE-GnuTLS-events/58811
-rw-r--r--test/stdout/586132
-rw-r--r--test/stdout/588132
11 files changed, 503 insertions, 7 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 738ed332f..f950a4dac 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -28153,7 +28153,16 @@ If verification was successful using DANE then the "CV" item in the delivery log
There is a new variable &$tls_out_dane$& which will have "yes" if
verification succeeded using DANE and "no" otherwise (only useful
-in combination with EXPERIMENTAL_EVENT), and a new variable &$tls_out_tlsa_usage$& (detailed above).
+in combination with events; see &<<CHAPevents>>&),
+and a new variable &$tls_out_tlsa_usage$& (detailed above).
+
+.cindex DANE reporting
+An event (see &<<CHAPevents>>&) of type "dane:fail" will be raised on failures
+to achieve DANE-verified connection, if one was either requested and offered, or
+required. This is intended to support TLS-reporting as defined in
+&url(https://tools.ietf.org/html/draft-ietf-uta-smtp-tlsrpt-17).
+The &$event_data$& will be one of the Result Types defined in
+Section 4.3 of that document.
Under GnuTLS, DANE is only supported from version 3.0.0 onwards.
.wen
@@ -39709,6 +39718,7 @@ expansion must check this, as it will be called for every possible event type.
The current list of events is:
.display
+&`dane:fail after transport `& per connection
&`msg:complete after main `& per message
&`msg:delivery after transport `& per recipient
&`msg:rcpt:host:defer after transport `& per recipient per host
@@ -39737,6 +39747,7 @@ should define the event action.
An additional variable, &$event_data$&, is filled with information varying
with the event type:
.display
+&`dane:fail `& failure reason
&`msg:delivery `& smtp confirmation message
&`msg:rcpt:host:defer `& error string
&`msg:rcpt:defer `& error string
@@ -39764,15 +39775,12 @@ The expansion of the event_action option should normally
return an empty string. Should it return anything else the
following will be forced:
.display
-&`msg:delivery `& (ignored)
-&`msg:host:defer `& (ignored)
-&`msg:fail:delivery`& (ignored)
&`tcp:connect `& do not connect
-&`tcp:close `& (ignored)
&`tls:cert `& refuse verification
&`smtp:connect `& close connection
.endd
-No other use is made of the result string.
+All other message types ignore the result string, and
+no other use is made of it.
For a tcp:connect event, if the connection is being made to a proxy
then the address and port variables will be that of the proxy and not
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 071d4a5dc..1ff45b425 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -46,6 +46,8 @@ Version 4.91
13. EXPERIMENTAL_ARC. See the experimental.spec file.
+14: A dane:fail event, intended to facilitate reporting.
+
Version 4.90
------------
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 2d81f3bff..add425326 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1618,6 +1618,9 @@ if (!continue_hostname)
string_sprintf("DANE error: tlsa lookup %s",
rc == DEFER ? "DEFER" : "FAIL"),
rc, FALSE);
+ (void) event_raise(sx->tblock->event_action,
+ US"dane:fail", sx->dane_required
+ ? US"dane-required" : US"dnssec-invalid");
return rc;
}
}
@@ -1626,6 +1629,8 @@ if (!continue_hostname)
set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: %s lookup not DNSSEC", sx->host->name),
FAIL, FALSE);
+ (void) event_raise(sx->tblock->event_action,
+ US"dane:fail", US"dane-required");
return FAIL;
}
}
@@ -1959,9 +1964,14 @@ if ( smtp_peer_options & OPTION_TLS
if (rc != OK)
{
# ifdef SUPPORT_DANE
- if (sx->dane) log_write(0, LOG_MAIN,
+ if (sx->dane)
+ {
+ log_write(0, LOG_MAIN,
"DANE attempt failed; TLS connection to %s [%s]: %s",
sx->host->name, sx->host->address, errstr);
+ (void) event_raise(sx->tblock->event_action,
+ US"dane:fail", US"validation-failure"); /* could do with better detail */
+ }
# endif
errno = ERRNO_TLSFAILURE;
@@ -2055,6 +2065,13 @@ else if ( sx->smtps
message = string_sprintf("a TLS session is required, but %s",
smtp_peer_options & OPTION_TLS
? "an attempt to start TLS failed" : "the server did not offer TLS support");
+# ifdef SUPPORT_DANE
+ if (sx->dane)
+ (void) event_raise(sx->tblock->event_action, US"dane:fail",
+ smtp_peer_options & OPTION_TLS
+ ? US"validation-failure" /* could do with better detail */
+ : US"starttls-not-supported");
+# endif
goto TLS_FAILED;
}
#endif /*SUPPORT_TLS*/
diff --git a/test/confs/5861 b/test/confs/5861
new file mode 100644
index 000000000..93e2bb715
--- /dev/null
+++ b/test/confs/5861
@@ -0,0 +1,96 @@
+# Exim test configuration 5890
+# DANE/fail-events
+
+SERVER=
+
+.include DIR/aux-var/tls_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+.ifndef OPT
+acl_smtp_rcpt = accept logwrite = "rcpt ACL"
+.else
+acl_smtp_rcpt = accept verify = recipient/callout
+.endif
+
+log_selector = +received_recipients +tls_peerdn +tls_certificate_verified
+
+queue_run_in_order
+
+tls_advertise_hosts = *
+
+.ifdef _HAVE_GNUTLS
+# needed to force generation
+tls_dhparam = historic
+.endif
+
+# Set certificate only if server
+CDIR1 = DIR/aux-fixed/exim-ca/example.net/server1.example.net
+CDIR2 = DIR/aux-fixed/exim-ca/example.com/server1.example.com
+
+
+tls_certificate = ${if eq {SERVER}{server} \
+ {${if or {{eq {DETAILS}{ta}} {eq {DETAILS}{ca}} {eq {DETAILS}{ee}}} \
+ {CDIR2/fullchain.pem}\
+ {CDIR1/fullchain.pem}}}\
+ fail}
+
+tls_privatekey = ${if eq {SERVER}{server} \
+ {${if or {{eq {DETAILS}{ta}} {eq {DETAILS}{ca}} {eq {DETAILS}{ee}}} \
+ {CDIR2/server1.example.com.unlocked.key}\
+ {CDIR1/server1.example.net.unlocked.key}}}\
+ fail}
+
+# ----- ACL -----
+begin acl
+
+dane_fail:
+ accept condition = ${if eq {dane} {${listextract{1}{$event_name}}}}
+ logwrite = $event_name <$event_data>
+
+# ----- Routers -----
+
+begin routers
+
+client:
+ driver = dnslookup
+ condition = ${if eq {SERVER}{}}
+ dnssec_request_domains = *
+ self = send
+ transport = send_to_server
+ errors_to = ""
+
+server:
+ driver = redirect
+ data = :blackhole:
+
+
+# ----- Transports -----
+
+begin transports
+
+send_to_server:
+ driver = smtp
+ allow_localhost
+ port = PORT_D
+
+ hosts_try_dane = *
+ hosts_require_dane = HOSTIPV4
+ tls_verify_cert_hostnames = ${if eq {OPT}{no_certname} {}{*}}
+ tls_try_verify_hosts = thishost.test.ex
+ tls_verify_certificates = CDIR2/ca_chain.pem
+ event_action = ${acl {dane_fail}}
+
+
+
+# ----- Retry -----
+
+
+begin retry
+
+* * F,5d,10s
+
+
+# End
diff --git a/test/confs/5881 b/test/confs/5881
new file mode 120000
index 000000000..290da5418
--- /dev/null
+++ b/test/confs/5881
@@ -0,0 +1 @@
+5861 \ No newline at end of file
diff --git a/test/log/5861 b/test/log/5861
new file mode 100644
index 000000000..30c489faa
--- /dev/null
+++ b/test/log/5861
@@ -0,0 +1,102 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 [127.0.0.1] SSL verify error: depth=2 error=self signed certificate in certificate chain cert=/O=example.net/CN=clica CA rsa
+1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER@thishost.test.ex R=client T=send_to_server H=thishost.test.ex [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=no DN="/CN=server1.example.net" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => CALLER@thishost.test.ex R=client T=send_to_server H=thishost.test.ex [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@mxdanelazy.test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbB-0005vi-00 H=danelazy.test.ex [ip4.ip4.ip4.ip4]: DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbB-0005vi-00 dane:fail <dnssec-invalid>
+1999-03-02 09:44:33 10HmbB-0005vi-00 H=danelazy2.test.ex [127.0.0.1]: DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbB-0005vi-00 == CALLER@mxdanelazy.test.ex R=client T=send_to_server defer (-36): DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.1.test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** CALLER@dane.no.1.test.ex R=client T=send_to_server: DANE error: tlsa lookup FAIL
+1999-03-02 09:44:33 10HmbC-0005vi-00 CALLER@dane.no.1.test.ex: error ignored
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.2.test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 [127.0.0.1] SSL verify error: certificate name mismatch: DN="/CN=server1.example.com" H="dane.no.2.test.ex"
+1999-03-02 09:44:33 10HmbD-0005vi-00 => CALLER@dane.no.2.test.ex R=client T=send_to_server H=dane.no.2.test.ex [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=no DN="/CN=server1.example.com" C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken1.test.ex
+1999-03-02 09:44:33 10HmbF-0005vi-00 dane:fail <dnssec-invalid>
+1999-03-02 09:44:33 10HmbF-0005vi-00 H=danebroken1.test.ex [127.0.0.1]: DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbF-0005vi-00 == CALLER@danebroken1.test.ex R=client T=send_to_server defer (-36): DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.3.test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbG-0005vi-00 ** CALLER@dane.no.3.test.ex R=client T=send_to_server: DANE error: tlsa lookup FAIL
+1999-03-02 09:44:33 10HmbG-0005vi-00 CALLER@dane.no.3.test.ex: error ignored
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.4.test.ex
+1999-03-02 09:44:33 10HmbH-0005vi-00 [127.0.0.1] SSL verify error: certificate name mismatch: DN="/CN=server1.example.com" H="dane.no.4.test.ex"
+1999-03-02 09:44:33 10HmbH-0005vi-00 => CALLER@dane.no.4.test.ex R=client T=send_to_server H=dane.no.4.test.ex [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=no DN="/CN=server1.example.com" C="250 OK id=10HmbI-0005vi-00"
+1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken2.test.ex
+1999-03-02 09:44:33 10HmbJ-0005vi-00 DANE attempt failed; TLS connection to danebroken2.test.ex [127.0.0.1]: (SSL_connect): error:xxxxxxxx:SSL routines:ssl3_get_server_certificate:certificate verify failed
+1999-03-02 09:44:33 10HmbJ-0005vi-00 dane:fail <validation-failure>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 == CALLER@danebroken2.test.ex R=client T=send_to_server defer (-37) H=danebroken2.test.ex [127.0.0.1]: TLS session: (SSL_connect): error: <<detail omitted>>
+1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken3.test.ex
+1999-03-02 09:44:33 10HmbK-0005vi-00 DANE error: TLSA lookup for danebroken3.test.ex not DNSSEC
+1999-03-02 09:44:33 10HmbK-0005vi-00 => CALLER@danebroken3.test.ex R=client T=send_to_server H=danebroken3.test.ex [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbL-0005vi-00"
+1999-03-02 09:44:33 10HmbK-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken4.test.ex
+1999-03-02 09:44:33 10HmbM-0005vi-00 DANE error: TLSA lookup for danebroken4.test.ex not DNSSEC
+1999-03-02 09:44:33 10HmbM-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbM-0005vi-00 ** CALLER@danebroken4.test.ex R=client T=send_to_server: DANE error: tlsa lookup FAIL
+1999-03-02 09:44:33 10HmbM-0005vi-00 CALLER@danebroken4.test.ex: error ignored
+1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken5.test.ex
+1999-03-02 09:44:33 10HmbN-0005vi-00 => CALLER@danebroken5.test.ex R=client T=send_to_server H=danebroken5.test.ex [127.0.0.1] X=TLSv1:ke-RSA-AES256-SHA:xxx CV=yes DN="/CN=server1.example.com" C="250 OK id=10HmbO-0005vi-00"
+1999-03-02 09:44:33 10HmbN-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken6.test.ex
+1999-03-02 09:44:33 10HmbP-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbP-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 10HmbP-0005vi-00 CALLER@danebroken6.test.ex: error ignored
+1999-03-02 09:44:33 10HmbP-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken7.example.com
+1999-03-02 09:44:33 10HmbQ-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 10HmbQ-0005vi-00 dane:fail <validation-failure>
+1999-03-02 09:44:33 10HmbQ-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: <<detail omitted>>
+1999-03-02 09:44:33 10HmbR-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken8.example.com
+1999-03-02 09:44:33 10HmbR-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=10HmbS-0005vi-00"
+1999-03-02 09:44:33 10HmbR-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
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmaY-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=E10HmaX-0005vi-00@myhost.test.ex for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <CALLER@thishost.test.ex> R=server
+1999-03-02 09:44:33 10HmaY-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 "rcpt ACL"
+1999-03-02 09:44:33 10HmbA-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=E10HmaZ-0005vi-00@myhost.test.ex for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <CALLER@thishost.test.ex> R=server
+1999-03-02 09:44:33 10HmbA-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 "rcpt ACL"
+1999-03-02 09:44:33 10HmbE-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=E10HmbD-0005vi-00@myhost.test.ex for CALLER@dane.no.2.test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <CALLER@dane.no.2.test.ex> R=server
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmbI-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=E10HmbH-0005vi-00@myhost.test.ex for CALLER@dane.no.4.test.ex
+1999-03-02 09:44:33 10HmbI-0005vi-00 => :blackhole: <CALLER@dane.no.4.test.ex> R=server
+1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
+1999-03-02 09:44:33 TLS error on connection from localhost (myhost.test.ex) [127.0.0.1] (SSL_accept): error: <<detail omitted>>
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmbL-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=E10HmbK-0005vi-00@myhost.test.ex for CALLER@danebroken3.test.ex
+1999-03-02 09:44:33 10HmbL-0005vi-00 => :blackhole: <CALLER@danebroken3.test.ex> R=server
+1999-03-02 09:44:33 10HmbL-0005vi-00 Completed
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmbO-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=E10HmbN-0005vi-00@myhost.test.ex for CALLER@danebroken5.test.ex
+1999-03-02 09:44:33 10HmbO-0005vi-00 => :blackhole: <CALLER@danebroken5.test.ex> R=server
+1999-03-02 09:44:33 10HmbO-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: <<detail omitted>>
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmbS-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=E10HmbR-0005vi-00@myhost.test.ex for CALLER@danebroken8.example.com
+1999-03-02 09:44:33 10HmbS-0005vi-00 => :blackhole: <CALLER@danebroken8.example.com> R=server
+1999-03-02 09:44:33 10HmbS-0005vi-00 Completed
diff --git a/test/log/5881 b/test/log/5881
new file mode 100644
index 000000000..c67bd11f6
--- /dev/null
+++ b/test/log/5881
@@ -0,0 +1,101 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER@thishost.test.ex R=client T=send_to_server H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=no DN="CN=server1.example.net" C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => CALLER@thishost.test.ex R=client T=send_to_server H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@mxdanelazy.test.ex
+1999-03-02 09:44:33 10HmbB-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbB-0005vi-00 H=danelazy.test.ex [ip4.ip4.ip4.ip4]: DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbB-0005vi-00 dane:fail <dnssec-invalid>
+1999-03-02 09:44:33 10HmbB-0005vi-00 H=danelazy2.test.ex [127.0.0.1]: DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbB-0005vi-00 == CALLER@mxdanelazy.test.ex R=client T=send_to_server defer (-36): DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.1.test.ex
+1999-03-02 09:44:33 10HmbC-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** CALLER@dane.no.1.test.ex R=client T=send_to_server: DANE error: tlsa lookup FAIL
+1999-03-02 09:44:33 10HmbC-0005vi-00 CALLER@dane.no.1.test.ex: error ignored
+1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.2.test.ex
+1999-03-02 09:44:33 10HmbD-0005vi-00 => CALLER@dane.no.2.test.ex R=client T=send_to_server H=dane.no.2.test.ex [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=no DN="CN=server1.example.com" C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken1.test.ex
+1999-03-02 09:44:33 10HmbF-0005vi-00 dane:fail <dnssec-invalid>
+1999-03-02 09:44:33 10HmbF-0005vi-00 H=danebroken1.test.ex [127.0.0.1]: DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbF-0005vi-00 == CALLER@danebroken1.test.ex R=client T=send_to_server defer (-36): DANE error: tlsa lookup DEFER
+1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.3.test.ex
+1999-03-02 09:44:33 10HmbG-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbG-0005vi-00 ** CALLER@dane.no.3.test.ex R=client T=send_to_server: DANE error: tlsa lookup FAIL
+1999-03-02 09:44:33 10HmbG-0005vi-00 CALLER@dane.no.3.test.ex: error ignored
+1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane.no.4.test.ex
+1999-03-02 09:44:33 10HmbH-0005vi-00 => CALLER@dane.no.4.test.ex R=client T=send_to_server H=dane.no.4.test.ex [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=no DN="CN=server1.example.com" C="250 OK id=10HmbI-0005vi-00"
+1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken2.test.ex
+1999-03-02 09:44:33 10HmbJ-0005vi-00 DANE attempt failed; TLS connection to danebroken2.test.ex [127.0.0.1]: (certificate verification failed): Verification failed. CA constrains were violated.
+1999-03-02 09:44:33 10HmbJ-0005vi-00 dane:fail <validation-failure>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 == CALLER@danebroken2.test.ex R=client T=send_to_server defer (-37) H=danebroken2.test.ex [127.0.0.1]: TLS session: (certificate verification failed): Verification failed. CA constrains were violated.
+1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken3.test.ex
+1999-03-02 09:44:33 10HmbK-0005vi-00 DANE error: TLSA lookup for danebroken3.test.ex not DNSSEC
+1999-03-02 09:44:33 10HmbK-0005vi-00 => CALLER@danebroken3.test.ex R=client T=send_to_server H=danebroken3.test.ex [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbL-0005vi-00"
+1999-03-02 09:44:33 10HmbK-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken4.test.ex
+1999-03-02 09:44:33 10HmbM-0005vi-00 DANE error: TLSA lookup for danebroken4.test.ex not DNSSEC
+1999-03-02 09:44:33 10HmbM-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbM-0005vi-00 ** CALLER@danebroken4.test.ex R=client T=send_to_server: DANE error: tlsa lookup FAIL
+1999-03-02 09:44:33 10HmbM-0005vi-00 CALLER@danebroken4.test.ex: error ignored
+1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken5.test.ex
+1999-03-02 09:44:33 10HmbN-0005vi-00 => CALLER@danebroken5.test.ex R=client T=send_to_server H=danebroken5.test.ex [127.0.0.1] X=TLS1.x:ke_RSA_AES_256_CBC_SHAnnn:256 CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbO-0005vi-00"
+1999-03-02 09:44:33 10HmbN-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken6.test.ex
+1999-03-02 09:44:33 10HmbP-0005vi-00 dane:fail <dane-required>
+1999-03-02 09:44:33 10HmbP-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 10HmbP-0005vi-00 CALLER@danebroken6.test.ex: error ignored
+1999-03-02 09:44:33 10HmbP-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken7.example.com
+1999-03-02 09:44:33 10HmbQ-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 10HmbQ-0005vi-00 dane:fail <validation-failure>
+1999-03-02 09:44:33 10HmbQ-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 10HmbR-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@danebroken8.example.com
+1999-03-02 09:44:33 10HmbR-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=10HmbS-0005vi-00"
+1999-03-02 09:44:33 10HmbR-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
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmaY-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=E10HmaX-0005vi-00@myhost.test.ex for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <CALLER@thishost.test.ex> R=server
+1999-03-02 09:44:33 10HmaY-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 "rcpt ACL"
+1999-03-02 09:44:33 10HmbA-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=E10HmaZ-0005vi-00@myhost.test.ex for CALLER@thishost.test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <CALLER@thishost.test.ex> R=server
+1999-03-02 09:44:33 10HmbA-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 "rcpt ACL"
+1999-03-02 09:44:33 10HmbE-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=E10HmbD-0005vi-00@myhost.test.ex for CALLER@dane.no.2.test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <CALLER@dane.no.2.test.ex> R=server
+1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmbI-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=E10HmbH-0005vi-00@myhost.test.ex for CALLER@dane.no.4.test.ex
+1999-03-02 09:44:33 10HmbI-0005vi-00 => :blackhole: <CALLER@dane.no.4.test.ex> R=server
+1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
+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 10HmbL-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=E10HmbK-0005vi-00@myhost.test.ex for CALLER@danebroken3.test.ex
+1999-03-02 09:44:33 10HmbL-0005vi-00 => :blackhole: <CALLER@danebroken3.test.ex> R=server
+1999-03-02 09:44:33 10HmbL-0005vi-00 Completed
+1999-03-02 09:44:33 "rcpt ACL"
+1999-03-02 09:44:33 10HmbO-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=E10HmbN-0005vi-00@myhost.test.ex for CALLER@danebroken5.test.ex
+1999-03-02 09:44:33 10HmbO-0005vi-00 => :blackhole: <CALLER@danebroken5.test.ex> R=server
+1999-03-02 09:44:33 10HmbO-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 10HmbS-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=E10HmbR-0005vi-00@myhost.test.ex for CALLER@danebroken8.example.com
+1999-03-02 09:44:33 10HmbS-0005vi-00 => :blackhole: <CALLER@danebroken8.example.com> R=server
+1999-03-02 09:44:33 10HmbS-0005vi-00 Completed
diff --git a/test/scripts/5860-DANE-OpenSSL-events/5861 b/test/scripts/5860-DANE-OpenSSL-events/5861
new file mode 100644
index 000000000..ac9397d93
--- /dev/null
+++ b/test/scripts/5860-DANE-OpenSSL-events/5861
@@ -0,0 +1,104 @@
+# DANE client: dane-fail events
+#
+### A server with a nonverifying cert and no TLSA
+# Check we get a non-CV but TLS connection, with try_dane but no require_dane
+# There should not be a dane-fail event
+exim -DSERVER=server -DDETAILS=no -bd -oX PORT_D
+****
+exim -odf CALLER@thishost.test.ex
+Testing
+****
+killdaemon
+#
+### A server with a verifying cert and no TLSA
+# Check we get a CV and TLS connection, with try_dane but no require_dane
+# There should not be a dane-fail event
+exim -DSERVER=server -DDETAILS=ca -bd -oX PORT_D
+****
+exim -odf CALLER@thishost.test.ex
+Testing
+****
+exim -DOPT=no_certname -qf
+****
+killdaemon
+#
+#
+exim -DSERVER=server -DDETAILS=ee -bd -oX PORT_D
+****
+### A server with two MXs for which both TLSA lookups return defer (delivery should defer)
+# One dane-fail event, as one of the MXs was dane-required
+exim -odf CALLER@mxdanelazy.test.ex
+Testing
+****
+### A server lacking a TLSA, dane required (should fail; should get an event)
+exim -odf CALLER@dane.no.1.test.ex
+Testing
+****
+### A server lacking a TLSA, dane requested only (should deliver, non-DANE, as the NXDOMAIN is not DNSSEC)
+# No event
+exim -odf CALLER@dane.no.2.test.ex
+Testing
+****
+### A server where the A is dnssec and the TLSA lookup _fails_ (delivery should defer)
+# gets an event, as the TLSA fail was non-dnssec
+exim -odf CALLER@danebroken1.test.ex
+Testing
+****
+### A server securely saying "no TLSA records here", dane required (delivery should fail)
+# An event; dane-required
+exim -odf CALLER@dane.no.3.test.ex
+Testing
+****
+### A server securely saying "no TLSA records here", dane requested only (should deliver)
+# No event (dane is not supported by this target, so not a failure)
+exim -odf CALLER@dane.no.4.test.ex
+Testing
+****
+#
+### A server securely serving a wrong TLSA record, dane requested only (delivery should fail)
+# An event (validation-failure)
+exim -odf CALLER@danebroken2.test.ex
+Testing
+****
+### A server insecurely serving a good TLSA record, dane requested only (should deliver, non-DANE)
+# No event (we didn't get a usable TLSA, so dane is not supported by...)
+exim -odf CALLER@danebroken3.test.ex
+Testing
+****
+### A server insecurely serving a good TLSA record, dane required (delivery should fail)
+# An event (dane-required)
+exim -odf CALLER@danebroken4.test.ex
+Testing
+****
+### A server insecurely serving a good A record, dane requested only (should deliver, non-DANE)
+# No event (not dane-worthy)
+exim -odf CALLER@danebroken5.test.ex
+Testing
+****
+### A server insecurely serving a good A record, dane required (delivery should fail)
+# An event (dane-required)
+exim -odf CALLER@danebroken6.test.ex
+Testing
+****
+#
+killdaemon
+#
+#
+#
+### A server with a name not matching the cert. TA-mode; should fail
+# An event (validation-failure)
+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
+# No event (no failure)
+exim -odf CALLER@danebroken8.example.com
+Testing
+****
+#
+killdaemon
+no_msglog_check
+no_stderr_check
diff --git a/test/scripts/5880-DANE-GnuTLS-events/5881 b/test/scripts/5880-DANE-GnuTLS-events/5881
new file mode 120000
index 000000000..619ccba11
--- /dev/null
+++ b/test/scripts/5880-DANE-GnuTLS-events/5881
@@ -0,0 +1 @@
+../5860-DANE-OpenSSL-events/5861 \ No newline at end of file
diff --git a/test/stdout/5861 b/test/stdout/5861
new file mode 100644
index 000000000..5aa35e8d0
--- /dev/null
+++ b/test/stdout/5861
@@ -0,0 +1,32 @@
+### A server with a nonverifying cert and no TLSA
+### A server with a verifying cert and no TLSA
+### A server with two MXs for which both TLSA lookups return defer (delivery should defer)
+### A server lacking a TLSA, dane required (should fail; should get an event)
+### A server lacking a TLSA, dane requested only (should deliver, non-DANE, as the NXDOMAIN is not DNSSEC)
+### A server where the A is dnssec and the TLSA lookup _fails_ (delivery should defer)
+### A server securely saying "no TLSA records here", dane required (delivery should fail)
+### A server securely saying "no TLSA records here", dane requested only (should deliver)
+### A server securely serving a wrong TLSA record, dane requested only (delivery should fail)
+### A server insecurely serving a good TLSA record, dane requested only (should deliver, non-DANE)
+### 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 ********
+### A server with a nonverifying cert and no TLSA
+### A server with a verifying cert and no TLSA
+### A server with two MXs for which both TLSA lookups return defer (delivery should defer)
+### A server lacking a TLSA, dane required (should fail; should get an event)
+### A server lacking a TLSA, dane requested only (should deliver, non-DANE, as the NXDOMAIN is not DNSSEC)
+### A server where the A is dnssec and the TLSA lookup _fails_ (delivery should defer)
+### A server securely saying "no TLSA records here", dane required (delivery should fail)
+### A server securely saying "no TLSA records here", dane requested only (should deliver)
+### A server securely serving a wrong TLSA record, dane requested only (delivery should fail)
+### A server insecurely serving a good TLSA record, dane requested only (should deliver, non-DANE)
+### 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/5881 b/test/stdout/5881
new file mode 100644
index 000000000..5aa35e8d0
--- /dev/null
+++ b/test/stdout/5881
@@ -0,0 +1,32 @@
+### A server with a nonverifying cert and no TLSA
+### A server with a verifying cert and no TLSA
+### A server with two MXs for which both TLSA lookups return defer (delivery should defer)
+### A server lacking a TLSA, dane required (should fail; should get an event)
+### A server lacking a TLSA, dane requested only (should deliver, non-DANE, as the NXDOMAIN is not DNSSEC)
+### A server where the A is dnssec and the TLSA lookup _fails_ (delivery should defer)
+### A server securely saying "no TLSA records here", dane required (delivery should fail)
+### A server securely saying "no TLSA records here", dane requested only (should deliver)
+### A server securely serving a wrong TLSA record, dane requested only (delivery should fail)
+### A server insecurely serving a good TLSA record, dane requested only (should deliver, non-DANE)
+### 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 ********
+### A server with a nonverifying cert and no TLSA
+### A server with a verifying cert and no TLSA
+### A server with two MXs for which both TLSA lookups return defer (delivery should defer)
+### A server lacking a TLSA, dane required (should fail; should get an event)
+### A server lacking a TLSA, dane requested only (should deliver, non-DANE, as the NXDOMAIN is not DNSSEC)
+### A server where the A is dnssec and the TLSA lookup _fails_ (delivery should defer)
+### A server securely saying "no TLSA records here", dane required (delivery should fail)
+### A server securely saying "no TLSA records here", dane requested only (should deliver)
+### A server securely serving a wrong TLSA record, dane requested only (delivery should fail)
+### A server insecurely serving a good TLSA record, dane requested only (should deliver, non-DANE)
+### 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