summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2014-05-06 08:44:59 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2014-05-06 10:25:19 +0100
commit65867078f62db450bd8f91100600f6de559e7590 (patch)
tree3634c893155659f3b2339e124dcbbe4ca03341f5
parent9e4dddbde4228e83fc7c882a4ef410ddbe0a6e79 (diff)
Refactor tls_client_init interface
-rw-r--r--src/src/functions.h6
-rw-r--r--src/src/tls-gnu.c70
-rw-r--r--src/src/tls-openssl.c57
-rw-r--r--src/src/tls.c1
-rw-r--r--src/src/transports/smtp.c17
-rw-r--r--src/src/verify.c16
-rw-r--r--test/stderr/54101
-rw-r--r--test/stderr/54203
8 files changed, 65 insertions, 106 deletions
diff --git a/src/src/functions.h b/src/src/functions.h
index 566a32bd6..8d249b8f2 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -40,11 +40,7 @@ extern uschar * tls_cert_subject_altname(void *, uschar * mod);
extern uschar * tls_cert_version(void *, uschar * mod);
extern int tls_client_start(int, host_item *, address_item *,
- uschar *, uschar *, uschar *, uschar *, uschar *, uschar *,
-# ifdef EXPERIMENTAL_OCSP
- uschar *,
-# endif
- int, int, uschar *, uschar *);
+ void *);
extern void tls_close(BOOL, BOOL);
extern int tls_export_cert(uschar *, size_t, void *);
extern int tls_feof(void);
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index 880aaeb14..d0e1c35d7 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -1610,17 +1610,7 @@ Arguments:
fd the fd of the connection
host connected host (for messages)
addr the first address (not used)
- certificate certificate file
- privatekey private key file
- sni TLS SNI to send to remote host
- verify_certs file for certificate verify
- verify_crl CRL for verify
- require_ciphers list of allowed ciphers or NULL
- hosts_require_ocsp hosts for which to request certificate-status (OCSP)
- dh_min_bits minimum number of bits acceptable in server's DH prime
- timeout startup timeout
- verify_hosts mandatory client verification
- try_verify_hosts optional client verification
+ ob smtp transport options
Returns: OK/DEFER/FAIL (because using common functions),
but for a client, DEFER and FAIL have the same meaning
@@ -1629,58 +1619,58 @@ Returns: OK/DEFER/FAIL (because using common functions),
int
tls_client_start(int fd, host_item *host,
address_item *addr ARG_UNUSED,
- uschar *certificate, uschar *privatekey, uschar *sni,
- uschar *verify_certs, uschar *verify_crl,
- uschar *require_ciphers,
-#ifdef EXPERIMENTAL_OCSP
- uschar *hosts_require_ocsp,
-#endif
- int dh_min_bits, int timeout,
- uschar *verify_hosts, uschar *try_verify_hosts)
+ void *v_ob)
{
+smtp_transport_options_block *ob = v_ob;
int rc;
const char *error;
exim_gnutls_state_st *state = NULL;
#ifdef EXPERIMENTAL_OCSP
-BOOL require_ocsp = verify_check_this_host(&hosts_require_ocsp,
+BOOL require_ocsp = verify_check_this_host(&ob->hosts_require_ocsp,
NULL, host->name, host->address, NULL) == OK;
#endif
DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", fd);
-if ((rc = tls_init(host, certificate, privatekey,
- sni, verify_certs, verify_crl, require_ciphers, &state)) != OK)
+if ((rc = tls_init(host, ob->tls_certificate, ob->tls_privatekey,
+ ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl,
+ ob->tls_require_ciphers, &state)) != OK)
return rc;
-if (dh_min_bits < EXIM_CLIENT_DH_MIN_MIN_BITS)
{
- DEBUG(D_tls)
- debug_printf("WARNING: tls_dh_min_bits far too low, clamping %d up to %d\n",
- dh_min_bits, EXIM_CLIENT_DH_MIN_MIN_BITS);
- dh_min_bits = EXIM_CLIENT_DH_MIN_MIN_BITS;
- }
+ int dh_min_bits = ob->tls_dh_min_bits;
+ if (dh_min_bits < EXIM_CLIENT_DH_MIN_MIN_BITS)
+ {
+ DEBUG(D_tls)
+ debug_printf("WARNING: tls_dh_min_bits far too low,"
+ " clamping %d up to %d\n",
+ dh_min_bits, EXIM_CLIENT_DH_MIN_MIN_BITS);
+ dh_min_bits = EXIM_CLIENT_DH_MIN_MIN_BITS;
+ }
-DEBUG(D_tls) debug_printf("Setting D-H prime minimum acceptable bits to %d\n",
- dh_min_bits);
-gnutls_dh_set_prime_bits(state->session, dh_min_bits);
+ DEBUG(D_tls) debug_printf("Setting D-H prime minimum"
+ " acceptable bits to %d\n",
+ dh_min_bits);
+ gnutls_dh_set_prime_bits(state->session, dh_min_bits);
+ }
/* Stick to the old behaviour for compatibility if tls_verify_certificates is
set but both tls_verify_hosts and tls_try_verify_hosts are unset. Check only
the specified host patterns if one of them is defined */
if (( state->exp_tls_verify_certificates
- && !verify_hosts
- && !try_verify_hosts
+ && !ob->tls_verify_hosts
+ && !ob->tls_try_verify_hosts
)
||
- verify_check_host(&verify_hosts) == OK
+ verify_check_host(&ob->tls_verify_hosts) == OK
)
{
DEBUG(D_tls) debug_printf("TLS: server certificate verification required.\n");
state->verify_requirement = VERIFY_REQUIRED;
gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUIRE);
}
-else if (verify_check_host(&try_verify_hosts) == OK)
+else if (verify_check_host(&ob->tls_try_verify_hosts) == OK)
{
DEBUG(D_tls) debug_printf("TLS: server certificate verification optional.\n");
state->verify_requirement = VERIFY_OPTIONAL;
@@ -1697,9 +1687,8 @@ else
if (require_ocsp)
{
DEBUG(D_tls) debug_printf("TLS: will request OCSP stapling\n");
- rc = gnutls_ocsp_status_request_enable_client(state->session,
- NULL, 0, NULL);
- if (rc != OK)
+ if ((rc = gnutls_ocsp_status_request_enable_client(state->session,
+ NULL, 0, NULL)) != OK)
return tls_error(US"cert-status-req",
gnutls_strerror(rc), state->host);
}
@@ -1713,7 +1702,7 @@ DEBUG(D_tls) debug_printf("about to gnutls_handshake\n");
/* There doesn't seem to be a built-in timeout on connection. */
sigalrm_seen = FALSE;
-alarm(timeout);
+alarm(ob->command_timeout);
do
{
rc = gnutls_handshake(state->session);
@@ -1747,14 +1736,13 @@ if (require_ocsp)
&& (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
)
{
- fprintf(stderr, "%.4096s", printed.data);
+ debug_printf("%.4096s", printed.data);
gnutls_free(printed.data);
}
else
(void) tls_error(US"ocsp decode", gnutls_strerror(rc), state->host);
}
- fprintf(stderr, "%s: checking ocsp\n", __FUNCTION__);
if (gnutls_ocsp_status_request_is_checked(state->session, 0) == 0)
return tls_error(US"certificate status check failed", NULL, state->host);
DEBUG(D_tls) debug_printf("Passed OCSP checking\n");
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 2f08e43c6..66fca7dbb 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1477,17 +1477,7 @@ Argument:
fd the fd of the connection
host connected host (for messages)
addr the first address
- certificate certificate file
- privatekey private key file
- sni TLS SNI to send to remote host
- verify_certs file for certificate verify
- crl file containing CRL
- require_ciphers list of allowed ciphers
- dh_min_bits minimum number of bits acceptable in server's DH prime
- (unused in OpenSSL)
- timeout startup timeout
- verify_hosts mandatory client verification
- try_verify_hosts optional client verification
+ ob smtp transport options
Returns: OK on success
FAIL otherwise - note that tls_error() will not give DEFER
@@ -1496,26 +1486,21 @@ Returns: OK on success
int
tls_client_start(int fd, host_item *host, address_item *addr,
- uschar *certificate, uschar *privatekey, uschar *sni,
- uschar *verify_certs, uschar *crl,
- uschar *require_ciphers,
-#ifdef EXPERIMENTAL_OCSP
- uschar *hosts_require_ocsp,
-#endif
- int dh_min_bits ARG_UNUSED, int timeout,
- uschar *verify_hosts, uschar *try_verify_hosts)
+ void *v_ob)
{
+smtp_transport_options_block * ob = v_ob;
static uschar txt[256];
uschar *expciphers;
X509* server_cert;
int rc;
static uschar cipherbuf[256];
#ifdef EXPERIMENTAL_OCSP
-BOOL require_ocsp = verify_check_this_host(&hosts_require_ocsp,
+BOOL require_ocsp = verify_check_this_host(&ob->hosts_require_ocsp,
NULL, host->name, host->address, NULL) == OK;
#endif
-rc = tls_init(&client_ctx, host, NULL, certificate, privatekey,
+rc = tls_init(&client_ctx, host, NULL,
+ ob->tls_certificate, ob->tls_privatekey,
#ifdef EXPERIMENTAL_OCSP
require_ocsp ? US"" : NULL,
#endif
@@ -1525,7 +1510,8 @@ if (rc != OK) return rc;
tls_out.certificate_verified = FALSE;
client_verify_callback_called = FALSE;
-if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
+if (!expand_check(ob->tls_require_ciphers, US"tls_require_ciphers",
+ &expciphers))
return FAIL;
/* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they
@@ -1542,30 +1528,33 @@ if (expciphers != NULL)
}
/* stick to the old behaviour for compatibility if tls_verify_certificates is
- set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only
+ set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only
the specified host patterns if one of them is defined */
-if (((verify_hosts == NULL) && (try_verify_hosts == NULL)) ||
- (verify_check_host(&verify_hosts) == OK))
+if ((!ob->tls_verify_hosts && !ob->tls_try_verify_hosts) ||
+ (verify_check_host(&ob->tls_verify_hosts) == OK))
{
- rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE, verify_callback_client);
- if (rc != OK) return rc;
+ if ((rc = setup_certs(client_ctx, ob->tls_verify_certificates,
+ ob->tls_crl, host, FALSE, verify_callback_client)) != OK)
+ return rc;
client_verify_optional = FALSE;
}
-else if (verify_check_host(&try_verify_hosts) == OK)
+else if (verify_check_host(&ob->tls_try_verify_hosts) == OK)
{
- rc = setup_certs(client_ctx, verify_certs, crl, host, TRUE, verify_callback_client);
- if (rc != OK) return rc;
+ if ((rc = setup_certs(client_ctx, ob->tls_verify_certificates,
+ ob->tls_crl, host, TRUE, verify_callback_client)) != OK)
+ return rc;
client_verify_optional = TRUE;
}
-if ((client_ssl = SSL_new(client_ctx)) == NULL) return tls_error(US"SSL_new", host, NULL);
+if ((client_ssl = SSL_new(client_ctx)) == NULL)
+ return tls_error(US"SSL_new", host, NULL);
SSL_set_session_id_context(client_ssl, sid_ctx, Ustrlen(sid_ctx));
SSL_set_fd(client_ssl, fd);
SSL_set_connect_state(client_ssl);
-if (sni)
+if (ob->tls_sni)
{
- if (!expand_check(sni, US"tls_sni", &tls_out.sni))
+ if (!expand_check(ob->tls_sni, US"tls_sni", &tls_out.sni))
return FAIL;
if (tls_out.sni == NULL)
{
@@ -1597,7 +1586,7 @@ if (require_ocsp)
DEBUG(D_tls) debug_printf("Calling SSL_connect\n");
sigalrm_seen = FALSE;
-alarm(timeout);
+alarm(ob->command_timeout);
rc = SSL_connect(client_ssl);
alarm(0);
diff --git a/src/src/tls.c b/src/src/tls.c
index ad7fe609c..f0ac60308 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -17,6 +17,7 @@ functions from the OpenSSL or GNU TLS libraries. */
#include "exim.h"
+#include "transports/smtp.h"
/* This module is compiled only when it is specifically requested in the
build-time configuration. However, some compilers don't like compiling empty
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 16c2b6011..7223f9c89 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1446,22 +1446,7 @@ if (tls_offered && !suppress_tls &&
else
TLS_NEGOTIATE:
{
- int rc = tls_client_start(inblock.sock,
- host,
- addrlist,
- ob->tls_certificate,
- ob->tls_privatekey,
- ob->tls_sni,
- ob->tls_verify_certificates,
- ob->tls_crl,
- ob->tls_require_ciphers,
-#ifdef EXPERIMENTAL_OCSP
- ob->hosts_require_ocsp,
-#endif
- ob->tls_dh_min_bits,
- ob->command_timeout,
- ob->tls_verify_hosts,
- ob->tls_try_verify_hosts);
+ int rc = tls_client_start(inblock.sock, host, addrlist, ob);
/* TLS negotiation failed; give an error. From outside, this function may
be called again to try in clear on a new connection, if the options permit
diff --git a/src/src/verify.c b/src/src/verify.c
index c5ffdae4e..ea733b605 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -636,16 +636,12 @@ else
/* STARTTLS accepted or ssl-on-connect: try to negotiate a TLS session. */
else
{
- int rc = tls_client_start(inblock.sock, host, addr,
- ob->tls_certificate, ob->tls_privatekey,
- ob->tls_sni,
- ob->tls_verify_certificates, ob->tls_crl,
- ob->tls_require_ciphers,
-#ifdef EXPERIMENTAL_OCSP
- ob->hosts_require_ocsp,
-#endif
- ob->tls_dh_min_bits, callout,
- ob->tls_verify_hosts, ob->tls_try_verify_hosts);
+ int oldtimeout = ob->command_timeout;
+ int rc;
+
+ ob->command_timeout = callout;
+ rc = tls_client_start(inblock.sock, host, addr, ob);
+ ob->command_timeout = oldtimeout;
/* TLS negotiation failed; give an error. Try in clear on a new connection,
if the options permit it for this host. */
diff --git a/test/stderr/5410 b/test/stderr/5410
index 334301139..b84c26492 100644
--- a/test/stderr/5410
+++ b/test/stderr/5410
@@ -80,6 +80,7 @@ expanding: ${if eq {$address_data}{userz}{*}{:}}
127.0.0.1 in hosts_verify_avoid_tls? no (end of list)
SMTP>> STARTTLS
SMTP<< 220 TLS go ahead
+127.0.0.1 in hosts_require_ocsp? no (option unset)
SMTP>> EHLO myhost.test.ex
SMTP<< 250-myhost.test.ex Hello the.local.host.name [ip4.ip4.ip4.ip4]
250-SIZE 52428800
diff --git a/test/stderr/5420 b/test/stderr/5420
index 36d163f25..d2fb575b5 100644
--- a/test/stderr/5420
+++ b/test/stderr/5420
@@ -80,6 +80,9 @@ expanding: ${if eq {$address_data}{userz}{*}{:}}
127.0.0.1 in hosts_verify_avoid_tls? no (end of list)
SMTP>> STARTTLS
SMTP<< 220 TLS go ahead
+127.0.0.1 in hosts_require_ocsp? no (option unset)
+ in tls_verify_hosts? no (option unset)
+ in tls_try_verify_hosts? no (option unset)
SMTP>> EHLO myhost.test.ex
SMTP<< 250-myhost.test.ex Hello the.local.host.name [ip4.ip4.ip4.ip4]
250-SIZE 52428800