+static int
+tls_client_basic_ctx_init(SSL_CTX * ctx,
+ host_item * host, smtp_transport_options_block * ob
+#ifdef EXPERIMENTAL_CERTNAMES
+ , tls_ext_ctx_cb * cbinfo
+#endif
+ )
+{
+int 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 ((!ob->tls_verify_hosts && !ob->tls_try_verify_hosts) ||
+ (verify_check_host(&ob->tls_verify_hosts) == OK))
+ {
+ if ((rc = setup_certs(ctx, ob->tls_verify_certificates,
+ ob->tls_crl, host, FALSE, verify_callback_client)) != OK)
+ return rc;
+ client_verify_optional = FALSE;
+
+#ifdef EXPERIMENTAL_CERTNAMES
+ if (ob->tls_verify_cert_hostnames)
+ {
+ if (!expand_check(ob->tls_verify_cert_hostnames,
+ US"tls_verify_cert_hostnames",
+ &cbinfo->verify_cert_hostnames))
+ return FAIL;
+ if (cbinfo->verify_cert_hostnames)
+ DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n",
+ cbinfo->verify_cert_hostnames);
+ }
+#endif
+ }
+else if (verify_check_host(&ob->tls_try_verify_hosts) == OK)
+ {
+ if ((rc = setup_certs(ctx, ob->tls_verify_certificates,
+ ob->tls_crl, host, TRUE, verify_callback_client)) != OK)
+ return rc;
+ client_verify_optional = TRUE;
+ }
+
+return OK;
+}
+
+
+#ifdef EXPERIMENTAL_DANE
+static int
+tlsa_lookup(host_item * host, dns_answer * dnsa,
+ BOOL dane_required, BOOL * dane)
+{
+/* move this out to host.c given the similarity to dns_lookup() ? */
+uschar buffer[300];
+uschar * fullname = buffer;
+
+/* TLSA lookup string */
+(void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port, host->name);
+
+switch (dns_lookup(dnsa, buffer, T_TLSA, &fullname))
+ {
+ case DNS_AGAIN:
+ return DEFER; /* just defer this TLS'd conn */
+
+ default:
+ case DNS_FAIL:
+ if (dane_required)
+ {
+ log_write(0, LOG_MAIN, "DANE error: TLSA lookup failed");
+ return FAIL;
+ }
+ break;
+
+ case DNS_SUCCEED:
+ if (!dns_is_secure(dnsa))
+ {
+ log_write(0, LOG_MAIN, "DANE error: TLSA lookup not DNSSEC");
+ return DEFER;
+ }
+ *dane = TRUE;
+ break;
+ }
+return OK;
+}
+
+
+static int
+dane_tlsa_load(SSL * ssl, host_item * host, dns_answer * dnsa)
+{
+dns_record * rr;
+dns_scan dnss;
+const char * hostnames[2] = { CS host->name, NULL };
+int found = 0;
+
+if (DANESSL_init(ssl, NULL, hostnames) != 1)
+ return tls_error(US"hostnames load", host, NULL);
+
+for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
+ rr;
+ rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
+ ) if (rr->type == T_TLSA)
+ {
+ uschar * p = rr->data;
+ uint8_t usage, selector, mtype;
+ const char * mdname;
+
+ found++;
+ usage = *p++;
+ selector = *p++;
+ mtype = *p++;
+
+ switch (mtype)
+ {
+ default:
+ log_write(0, LOG_MAIN,
+ "DANE error: TLSA record w/bad mtype 0x%x", mtype);
+ return FAIL;
+ case 0: mdname = NULL; break;
+ case 1: mdname = "sha256"; break;
+ case 2: mdname = "sha512"; break;
+ }
+
+ switch (DANESSL_add_tlsa(ssl, usage, selector, mdname, p, rr->size - 3))
+ {
+ default:
+ case 0: /* action not taken */
+ return tls_error(US"tlsa load", host, NULL);
+ case 1: break;
+ }
+
+ tls_out.tlsa_usage |= 1<<usage;
+ }
+
+if (found)
+ return OK;
+
+log_write(0, LOG_MAIN, "DANE error: No TLSA records");
+return FAIL;
+}
+#endif /*EXPERIMENTAL_DANE*/
+
+