Gitweb:
http://git.exim.org/exim.git/commitdiff/723fe533c452eb258a5a7e0b808d714bbbc7cb01
Commit: 723fe533c452eb258a5a7e0b808d714bbbc7cb01
Parent: aec45841f9139404fd61122e3db1401b13ebb0a8
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Thu Oct 23 18:22:33 2014 +0100
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Sat Oct 25 21:37:59 2014 +0100
Add event for inbound cert visibility
---
doc/doc-txt/ChangeLog | 4 +++-
doc/doc-txt/experimental-spec.txt | 6 +++++-
src/src/globals.c | 14 +++++++-------
src/src/tls-gnu.c | 17 +++++++++++++----
src/src/tls-openssl.c | 15 +++++++--------
test/confs/5750 | 9 +++++++++
test/confs/5760 | 9 +++++++++
test/log/5750 | 2 ++
test/log/5760 | 3 +++
9 files changed, 58 insertions(+), 21 deletions(-)
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 50a6e49..ed45747 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -55,7 +55,9 @@ JH/08 Rename the TPDA expermimental facility to Event Actions. The #ifdef
is EXPERIMENTAL_EVENT, the main-configuration and transport options
both become "event_action", the variables become $event_name, $event_data
and $event_defer_errno. There is a new variable $verify_mode, usable in
- routers, transports and related events.
+ routers, transports and related events. The tls:cert event is now also
+ raised for inbound connections, if the main configuration event_action
+ option is defined.
Exim version 4.84
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index 1d3715f..faa64df 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -791,7 +791,7 @@ expansion is done. The current list of events is:
msg:fail:internal after main per recipient
tcp:connect before transport per connection
tcp:close after transport per connection
- tls:cert before transport per certificate in verification chain
+ tls:cert before both per certificate in verification chain
smtp:connect after transport per connection
The expansion is called for all event types, and should use the $event_name
@@ -852,6 +852,10 @@ following will be forced:
No other use is made of the result string.
+Known issues:
+- the tls:cert event is only called for the cert chain elements
+ received over the wire, with GnuTLS. OpenSSL gives the entire
+ chain including thse loaded locally.
Redis Lookup
diff --git a/src/src/globals.c b/src/src/globals.c
index 1eae4a8..fb705d9 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -668,6 +668,13 @@ uschar *errors_copy = NULL;
int error_handling = ERRORS_SENDER;
uschar *errors_reply_to = NULL;
int errors_sender_rc = EXIT_FAILURE;
+#ifdef EXPERIMENTAL_EVENT
+uschar *event_action = NULL; /* expansion for delivery events */
+uschar *event_data = NULL; /* auxilary data variable for event */
+int event_defer_errno = 0;
+uschar *event_name = NULL; /* event name variable */
+#endif
+
gid_t exim_gid = EXIM_GID;
BOOL exim_gid_set = TRUE; /* This gid is always set */
@@ -1336,13 +1343,6 @@ int thismessage_size_limit = 0;
int timeout_frozen_after = 0;
BOOL timestamps_utc = FALSE;
-#ifdef EXPERIMENTAL_EVENT
-uschar *event_action = NULL; /* expansion for delivery events */
-uschar *event_data = NULL; /* auxilary data variable for event */
-int event_defer_errno = 0;
-uschar *event_name = NULL; /* event name variable */
-#endif
-
transport_instance *transports = NULL;
transport_instance transport_defaults = {
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index 20e11ca..1966c55 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -1545,15 +1545,15 @@ return 0;
#ifdef EXPERIMENTAL_EVENT
/*
We use this callback to get observability and detail-level control
-for an exim client TLS connection, raising a tls:cert event
-for each cert in the chain presented by the server. Any event
+for an exim TLS connection (either direction), raising a tls:cert event
+for each cert in the chain presented by the peer. Any event
can deny verification.
Return 0 for the handshake to continue or non-zero to terminate.
*/
static int
-client_verify_cb(gnutls_session_t session)
+verify_cb(gnutls_session_t session)
{
const gnutls_datum * cert_list;
unsigned int cert_list_size = 0;
@@ -1664,6 +1664,15 @@ else
gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_IGNORE);
}
+#ifdef EXPERIMENTAL_EVENT
+if (event_action)
+ {
+ state->event_action = event_action;
+ gnutls_session_set_ptr(state->session, state);
+ gnutls_certificate_set_verify_function(state->x509_cred, verify_cb);
+ }
+#endif
+
/* Register SNI handling; always, even if not in tls_certificate, so that the
expansion variable $tls_sni is always available. */
@@ -1890,7 +1899,7 @@ if (tb->event_action)
{
state->event_action = tb->event_action;
gnutls_session_set_ptr(state->session, state);
- gnutls_certificate_set_verify_function(state->x509_cred, client_verify_cb);
+ gnutls_certificate_set_verify_function(state->x509_cred, verify_cb);
}
#endif
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 13a3cd0..4de3cad 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -287,6 +287,7 @@ verify_callback(int state, X509_STORE_CTX *x509ctx,
{
X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx);
int depth = X509_STORE_CTX_get_error_depth(x509ctx);
+uschar * ev;
static uschar txt[256];
X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt));
@@ -323,11 +324,11 @@ else if (depth != 0)
}
#endif
#ifdef EXPERIMENTAL_EVENT
- if (tlsp == &tls_out && client_static_cbinfo->event_action)
+ ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action;
+ if (ev)
{
tlsp->peercert = X509_dup(cert);
- if (event_raise(client_static_cbinfo->event_action,
- US"tls:cert", string_sprintf("%d", depth)) == DEFER)
+ if (event_raise(ev, US"tls:cert", string_sprintf("%d", depth)) == DEFER)
{
log_write(0, LOG_MAIN, "SSL verify denied by event-action: "
"depth=%d cert=%s", depth, txt);
@@ -392,10 +393,9 @@ else
#endif /*EXPERIMENTAL_CERTNAMES*/
#ifdef EXPERIMENTAL_EVENT
- if (tlsp == &tls_out)
- {
- if (event_raise(client_static_cbinfo->event_action,
- US"tls:cert", US"0") == DEFER)
+ ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action;
+ if (ev)
+ if (event_raise(ev, US"tls:cert", US"0") == DEFER)
{
log_write(0, LOG_MAIN, "SSL verify denied by event-action: "
"depth=0 cert=%s", txt);
@@ -403,7 +403,6 @@ else
*calledp = TRUE;
return 0; /* reject */
}
- }
#endif
DEBUG(D_tls) debug_printf("SSL%s verify ok: depth=0 SN=%s\n",
diff --git a/test/confs/5750 b/test/confs/5750
index 8cfef31..3898530 100644
--- a/test/confs/5750
+++ b/test/confs/5750
@@ -29,10 +29,19 @@ tls_privatekey = DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.e
tls_verify_hosts = *
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/server2.example.com/ca_chain.pem
+event_action = ${acl {server_cert_log}}
+
#
begin acl
+server_cert_log:
+ accept condition = ${if eq {tls:cert}{$event_name}}
+ logwrite = [$sender_host_address] \
+ depth=$event_data \
+ ${certextract{subject}{$tls_in_peercert}}
+ accept
+
ev_tls:
accept logwrite = $event_name depth=$event_data \
<${certextract {subject} {$tls_out_peercert}}>
diff --git a/test/confs/5760 b/test/confs/5760
index b8cab04..d07aa8d 100644
--- a/test/confs/5760
+++ b/test/confs/5760
@@ -29,10 +29,19 @@ tls_privatekey = DIR/aux-fixed/exim-ca/example.com/server1.example.com/server1.e
tls_verify_hosts = *
tls_verify_certificates = DIR/aux-fixed/exim-ca/example.com/server2.example.com/ca_chain.pem
+event_action = ${acl {server_cert_log}}
+
#
begin acl
+server_cert_log:
+ accept condition = ${if eq {tls:cert}{$event_name}}
+ logwrite = [$sender_host_address] \
+ depth=$event_data \
+ ${certextract{subject}{$tls_in_peercert}}
+ accept
+
ev_tls:
accept logwrite = $event_name depth=$event_data \
<${certextract {subject} {$tls_out_peercert}}>
diff --git a/test/log/5750 b/test/log/5750
index 9e85d1a..d085892 100644
--- a/test/log/5750
+++ b/test/log/5750
@@ -40,7 +40,9 @@
******** 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 [127.0.0.1] depth=0 CN=server2.example.com
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 10HmaZ-0005vi-00 <= CALLER@??? H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 [127.0.0.1] depth=0 CN=server2.example.com
1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 DN="CN=server2.example.com" S=sss id=E10HmaY-0005vi-00@???
diff --git a/test/log/5760 b/test/log/5760
index 6d382ca..691ccda 100644
--- a/test/log/5760
+++ b/test/log/5760
@@ -47,4 +47,7 @@
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 TLS client disconnected cleanly (rejected our certificate?)
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@??? H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 [127.0.0.1] depth=2 CN=clica CA,O=example.com
+1999-03-02 09:44:33 [127.0.0.1] depth=1 CN=clica Signing Cert,O=example.com
+1999-03-02 09:44:33 [127.0.0.1] depth=0 CN=server2.example.com
1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLSv1:AES256-SHA:256 DN="/CN=server2.example.com" S=sss id=E10HmaY-0005vi-00@???