return 0; /* reject */
}
# endif
-#endif
+#endif /*EXPERIMENTAL_CERTNAMES*/
DEBUG(D_tls) debug_printf("SSL%s verify ok: depth=0 SN=%s\n",
*calledp ? "" : " authenticated", txt);
}
+#ifdef EXPERIMENTAL_DANE
+/* This gets called *by* the dane library verify callback, which interposes
+itself.
+*/
+static int
+verify_callback_client_dane(int state, X509_STORE_CTX * x509ctx)
+{
+X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx);
+static uschar txt[256];
+
+X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt));
+
+DEBUG(D_tls) debug_printf("verify_callback_client_dane: %s\n", txt);
+tls_out.peerdn = txt;
+tls_out.peercert = X509_dup(cert);
+
+if (state == 1)
+ tls_out.certificate_verified = TRUE;
+return 1;
+}
+#endif
+
/*************************************************
* Information callback *
#endif /*!DISABLE_OCSP*/
-
/*************************************************
* Initialize for TLS *
*************************************************/
#endif
#ifdef EXPERIMENTAL_DANE
-/*XXX TBD: test for transport options, and for TLSA records */
-/*dane = TRUE;*/
-
-# ifdef notyet
dane_required = verify_check_this_host(&ob->hosts_require_dane, NULL,
host->name, host->address, NULL) == OK;
-# else
-dane_required = FALSE;
-#endif
if (host->dnssec == DS_YES)
{
{
/* move this out to host.c given the similarity to dns_lookup() ? */
uschar buffer[300];
- int prefix_length; /* why do we want this? */
uschar * fullname = buffer;
/* TLSA lookup string */
- (void)sprintf(CS buffer, "_%d._tcp.%n%.256s", host->port, &prefix_length,
+ (void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port,
host->name);
switch (rc = dns_lookup(&tlsa_dnsa, buffer, T_TLSA, &fullname))
case DNS_FAIL:
if (dane_required)
{
- /* log that TLSA lookup failed */
+ log_write(0, LOG_MAIN, "DANE error: TLSA lookup failed");
return FAIL;
}
break;
case DNS_SUCCEED:
if (!dns_is_secure(&tlsa_dnsa))
{
- /*log it - tlsa should never be non-dnssec */
+ log_write(0, LOG_MAIN, "DANE error: TLSA lookup not DNSSEC");
return DEFER;
}
dane = TRUE;
}
}
}
-else if (dane_required && !dane)
+else if (dane_required)
{
- /* log that dnssec pre-req failed. Hmm - what? */
+ /*XXX a shame we only find this after making tcp & smtp connection */
+ /* move the test earlier? */
+ log_write(0, LOG_MAIN, "DANE error: previous lookup not DNSSEC");
return FAIL;
}
#ifdef EXPERIMENTAL_DANE
if (dane)
{
+ SSL_CTX_set_verify(client_ctx, SSL_VERIFY_PEER, verify_callback_client_dane);
+
if (!DANESSL_library_init())
- return tls_error(US"library init", host, US"DANE library error");
+ return tls_error(US"library init", host, NULL);
if (DANESSL_CTX_init(client_ctx) <= 0)
- return tls_error(US"context init", host, US"DANE library error");
+ return tls_error(US"context init", host, NULL);
}
else
uschar * hostnames[2] = { host->name, NULL };
if (DANESSL_init(client_ssl, NULL, hostnames) != 1)
- return tls_error(US"hostnames load", host, US"DANE library error");
+ return tls_error(US"hostnames load", host, NULL);
for (rr = dns_next_rr(&tlsa_dnsa, &dnss, RESET_ANSWERS);
rr;
{
default: /* log bad */ return FAIL;
case 0: mdname = NULL; break;
- case 1: mdname = "SHA2-256"; break;
- case 2: mdname = "SHA2-512"; break;
+ case 1: mdname = "sha256"; break;
+ case 2: mdname = "sha512"; break;
}
switch (DANESSL_add_tlsa(client_ssl,
mdname, p, rr->size - (p - rr->data)))
{
default:
- case 0: /* action not taken; log error */
- return FAIL;
+ case 0: /* action not taken */
+ return tls_error(US"tlsa load", host, NULL);
case 1: break;
}
}