# 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);
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
#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;
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
#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;
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));
(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,
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 */
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
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;
#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. */