summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/src/functions.h2
-rw-r--r--src/src/tls-gnu.c5
-rw-r--r--src/src/tls-openssl.c23
-rw-r--r--src/src/transports/smtp.c14
-rw-r--r--src/src/transports/smtp.h2
-rw-r--r--src/src/verify.c3
6 files changed, 40 insertions, 9 deletions
diff --git a/src/src/functions.h b/src/src/functions.h
index 9d933fea7..32bd0bc07 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -30,7 +30,7 @@ extern int tls_client_start(int, host_item *, address_item *,
# ifdef EXPERIMENTAL_OCSP
uschar *,
# endif
- int, int);
+ int, int, uschar *, uschar *);
extern void tls_close(BOOL, BOOL);
extern int tls_feof(void);
extern int tls_ferror(void);
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index 4f1169aa4..280744ec0 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -1563,6 +1563,8 @@ Arguments:
require_ciphers list of allowed ciphers or NULL
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
Returns: OK/DEFER/FAIL (because using common functions),
but for a client, DEFER and FAIL have the same meaning
@@ -1577,7 +1579,8 @@ tls_client_start(int fd, host_item *host,
#ifdef EXPERIMENTAL_OCSP
uschar *require_ocsp ARG_UNUSED,
#endif
- int dh_min_bits, int timeout)
+ int dh_min_bits, int timeout,
+ uschar *verify_hosts, uschar *try_verify_hosts)
{
int rc;
const char *error;
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 2b8d798c9..a9adb6134 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1504,6 +1504,8 @@ Argument:
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
Returns: OK on success
FAIL otherwise - note that tls_error() will not give DEFER
@@ -1518,7 +1520,8 @@ tls_client_start(int fd, host_item *host, address_item *addr,
#ifdef EXPERIMENTAL_OCSP
uschar *hosts_require_ocsp,
#endif
- int dh_min_bits ARG_UNUSED, int timeout)
+ int dh_min_bits ARG_UNUSED, int timeout,
+ uschar *verify_hosts, uschar *try_verify_hosts)
{
static uschar txt[256];
uschar *expciphers;
@@ -1556,8 +1559,22 @@ if (expciphers != NULL)
return tls_error(US"SSL_CTX_set_cipher_list", host, NULL);
}
-rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE, verify_callback_client);
-if (rc != OK) return rc;
+/* 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
+ the specified host patterns if one of them is defined */
+if (((verify_hosts == NULL) && (try_verify_hosts == NULL)) ||
+ (verify_check_host(&verify_hosts) == OK))
+ {
+ rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE, verify_callback_client);
+ if (rc != OK) return rc;
+ client_verify_optional = FALSE;
+ }
+else if (verify_check_host(&try_verify_hosts) == OK)
+ {
+ rc = setup_certs(client_ctx, verify_certs, crl, host, TRUE, verify_callback_client);
+ if (rc != OK) return rc;
+ client_verify_optional = TRUE;
+ }
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));
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index a77e472d6..938844799 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -153,8 +153,12 @@ optionlist smtp_transport_options[] = {
(void *)offsetof(smtp_transport_options_block, tls_sni) },
{ "tls_tempfail_tryclear", opt_bool,
(void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) },
+ { "tls_try_verify_hosts", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, tls_try_verify_hosts) },
{ "tls_verify_certificates", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) }
+ (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) },
+ { "tls_verify_hosts", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, tls_verify_hosts) }
#endif
#ifdef EXPERIMENTAL_TPDA
,{ "tpda_host_defer_action", opt_stringptr,
@@ -227,7 +231,9 @@ smtp_transport_options_block smtp_transport_option_defaults = {
NULL, /* tls_verify_certificates */
EXIM_CLIENT_DH_DEFAULT_MIN_BITS,
/* tls_dh_min_bits */
- TRUE /* tls_tempfail_tryclear */
+ TRUE, /* tls_tempfail_tryclear */
+ NULL, /* tls_verify_hosts */
+ NULL /* tls_try_verify_hosts */
#endif
#ifndef DISABLE_DKIM
,NULL, /* dkim_canon */
@@ -1446,7 +1452,9 @@ if (tls_offered && !suppress_tls &&
ob->hosts_require_ocsp,
#endif
ob->tls_dh_min_bits,
- ob->command_timeout);
+ ob->command_timeout,
+ ob->tls_verify_hosts,
+ ob->tls_try_verify_hosts);
/* 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/transports/smtp.h b/src/src/transports/smtp.h
index 6c22e4b96..fc4e014c1 100644
--- a/src/src/transports/smtp.h
+++ b/src/src/transports/smtp.h
@@ -64,6 +64,8 @@ typedef struct {
uschar *tls_verify_certificates;
int tls_dh_min_bits;
BOOL tls_tempfail_tryclear;
+ uschar *tls_verify_hosts;
+ uschar *tls_try_verify_hosts;
#endif
#ifndef DISABLE_DKIM
uschar *dkim_domain;
diff --git a/src/src/verify.c b/src/src/verify.c
index 711b3af5a..c83748a12 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -641,7 +641,8 @@ else
#ifdef EXPERIMENTAL_OCSP
ob->hosts_require_ocsp,
#endif
- ob->tls_dh_min_bits, callout);
+ ob->tls_dh_min_bits, callout,
+ ob->tls_verify_hosts, ob->tls_try_verify_hosts);
/* TLS negotiation failed; give an error. Try in clear on a new connection,
if the options permit it for this host. */