- DANE_SELECTOR_LIST issuer_rrs;
- DANE_SELECTOR_LIST leaf_rrs;
- int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb;
- int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
- SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx);
- SSL_DANE *dane = SSL_get_ex_data(ssl, dane_idx);
- X509 *cert = ctx->cert; /* XXX: accessor? */
- int matched = 0;
- int chain_length = sk_X509_num(ctx->chain);
-
- issuer_rrs = dane->selectors[SSL_DANE_USAGE_LIMIT_ISSUER];
- leaf_rrs = dane->selectors[SSL_DANE_USAGE_LIMIT_LEAF];
- ctx->verify = dane->verify;
-
- if ((matched = name_check(dane, cert)) < 0) {
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_OUT_OF_MEM);
- return 0;
+dane_selector_list issuer_rrs;
+dane_selector_list leaf_rrs;
+int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb;
+int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
+SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx);
+ssl_dane *dane = SSL_get_ex_data(ssl, dane_idx);
+X509 *cert = ctx->cert; /* XXX: accessor? */
+int matched = 0;
+int chain_length = sk_X509_num(ctx->chain);
+
+issuer_rrs = dane->selectors[SSL_DANE_USAGE_LIMIT_ISSUER];
+leaf_rrs = dane->selectors[SSL_DANE_USAGE_LIMIT_LEAF];
+ctx->verify = dane->verify;
+
+if((matched = name_check(dane, cert)) < 0)
+ {
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_OUT_OF_MEM);
+ return 0;
+ }
+
+if(!matched)
+ {
+ ctx->error_depth = 0;
+ ctx->current_cert = cert;
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
+ if(!cb(0, ctx))
+ return 0;
+ }
+matched = 0;
+
+/*
+ * Satisfy at least one usage 0 or 1 constraint, unless we've already
+ * matched a usage 2 trust anchor.
+ *
+ * XXX: internal_verify() doesn't callback with top certs that are not
+ * self-issued. This should be fixed in a future OpenSSL.
+ */
+if(dane->roots && sk_X509_num(dane->roots))
+ {
+#ifndef NO_CALLBACK_WORKAROUND
+ X509 *top = sk_X509_value(ctx->chain, dane->depth);
+
+ if(X509_check_issued(top, top) != X509_V_OK)
+ {
+ ctx->error_depth = dane->depth;
+ ctx->current_cert = top;
+ if(!cb(1, ctx))
+ return 0;
+ }
+#endif
+ /* Pop synthetic trust-anchor ancestors off the chain! */
+ while (--chain_length > dane->depth)
+ X509_free(sk_X509_pop(ctx->chain));
+ }
+else if(issuer_rrs || leaf_rrs)
+ {
+ int n = chain_length;
+
+ /*
+ * Check for an EE match, then a CA match at depths > 0, and
+ * finally, if the EE cert is self-issued, for a depth 0 CA match.
+ */
+ if(leaf_rrs)
+ matched = match(leaf_rrs, cert, 0);
+ while(!matched && issuer_rrs && --n >= 0)
+ {
+ X509 *xn = sk_X509_value(ctx->chain, n);
+
+ if(n > 0 || X509_check_issued(xn, xn) == X509_V_OK)
+ matched = match(issuer_rrs, xn, n);