Disconnect hostapd from building in base
[dragonfly.git] / contrib / ldns / dane.c
CommitLineData
d1b2b5ca
JM
1/*
2 * Verify or create TLS authentication with DANE (RFC6698)
3 *
4 * (c) NLnetLabs 2012
5 *
6 * See the file LICENSE for the license.
7 *
8 */
9
10#include <ldns/config.h>
11
12#include <ldns/ldns.h>
13#include <ldns/dane.h>
14
15#include <unistd.h>
16#include <stdlib.h>
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <netdb.h>
20
21#ifdef HAVE_SSL
22#include <openssl/ssl.h>
23#include <openssl/err.h>
24#include <openssl/x509v3.h>
25#endif
26
27ldns_status
28ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
29 uint16_t port, ldns_dane_transport transport)
30{
31 char buf[LDNS_MAX_DOMAINLEN];
32 size_t s;
33
34 assert(tlsa_owner != NULL);
35 assert(name != NULL);
36 assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);
37
38 s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
39 buf[0] = (char)(s - 1);
40
41 switch(transport) {
42 case LDNS_DANE_TRANSPORT_TCP:
43 s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
44 break;
45
46 case LDNS_DANE_TRANSPORT_UDP:
47 s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
48 break;
49
50 case LDNS_DANE_TRANSPORT_SCTP:
51 s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
52 break;
53
54 default:
55 return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
56 }
57 if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
58 return LDNS_STATUS_DOMAINNAME_OVERFLOW;
59 }
60 memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
61 *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
62 s + ldns_rdf_size(name), buf);
63 if (*tlsa_owner == NULL) {
64 return LDNS_STATUS_MEM_ERR;
65 }
66 return LDNS_STATUS_OK;
67}
68
69
70#ifdef HAVE_SSL
71ldns_status
72ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
73 ldns_tlsa_selector selector,
74 ldns_tlsa_matching_type matching_type)
75{
76 unsigned char* buf = NULL;
77 size_t len;
78
79 X509_PUBKEY* xpubkey;
80 EVP_PKEY* epubkey;
81
82 unsigned char* digest;
83
84 assert(rdf != NULL);
85 assert(cert != NULL);
86
87 switch(selector) {
88 case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
89
90 len = (size_t)i2d_X509(cert, &buf);
91 break;
92
93 case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
94
95#ifndef S_SPLINT_S
96 xpubkey = X509_get_X509_PUBKEY(cert);
97#endif
98 if (! xpubkey) {
99 return LDNS_STATUS_SSL_ERR;
100 }
101 epubkey = X509_PUBKEY_get(xpubkey);
102 if (! epubkey) {
103 return LDNS_STATUS_SSL_ERR;
104 }
105 len = (size_t)i2d_PUBKEY(epubkey, &buf);
106 break;
107
108 default:
109 return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
110 }
111
112 switch(matching_type) {
113 case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
114
115 *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
116
117 return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
118 break;
119
120 case LDNS_TLSA_MATCHING_TYPE_SHA256:
121
122 digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH);
123 if (digest == NULL) {
124 LDNS_FREE(buf);
125 return LDNS_STATUS_MEM_ERR;
126 }
127 (void) ldns_sha256(buf, (unsigned int)len, digest);
128 *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH,
129 digest);
130 LDNS_FREE(buf);
131
132 return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
133 break;
134
135 case LDNS_TLSA_MATCHING_TYPE_SHA512:
136
137 digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH);
138 if (digest == NULL) {
139 LDNS_FREE(buf);
140 return LDNS_STATUS_MEM_ERR;
141 }
142 (void) ldns_sha512(buf, (unsigned int)len, digest);
143 *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH,
144 digest);
145 LDNS_FREE(buf);
146
147 return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
148 break;
149
150 default:
151 LDNS_FREE(buf);
152 return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
153 }
154}
155
156
157/* Ordinary PKIX validation of cert (with extra_certs to help)
158 * against the CA's in store
159 */
160static ldns_status
161ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
162 X509_STORE* store)
163{
164 X509_STORE_CTX* vrfy_ctx;
165 ldns_status s;
166
167 if (! store) {
168 return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
169 }
170 vrfy_ctx = X509_STORE_CTX_new();
171 if (! vrfy_ctx) {
172
173 return LDNS_STATUS_SSL_ERR;
174
175 } else if (X509_STORE_CTX_init(vrfy_ctx, store,
176 cert, extra_certs) != 1) {
177 s = LDNS_STATUS_SSL_ERR;
178
179 } else if (X509_verify_cert(vrfy_ctx) == 1) {
180
181 s = LDNS_STATUS_OK;
182
183 } else {
184 s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
185 }
186 X509_STORE_CTX_free(vrfy_ctx);
187 return s;
188}
189
190
191/* Orinary PKIX validation of cert (with extra_certs to help)
192 * against the CA's in store, but also return the validation chain.
193 */
194static ldns_status
195ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
196 STACK_OF(X509)* extra_certs, X509_STORE* store)
197{
198 ldns_status s;
199 X509_STORE* empty_store = NULL;
200 X509_STORE_CTX* vrfy_ctx;
201
202 assert(chain != NULL);
203
204 if (! store) {
205 store = empty_store = X509_STORE_new();
206 }
207 s = LDNS_STATUS_SSL_ERR;
208 vrfy_ctx = X509_STORE_CTX_new();
209 if (! vrfy_ctx) {
210
211 goto exit_free_empty_store;
212
213 } else if (X509_STORE_CTX_init(vrfy_ctx, store,
214 cert, extra_certs) != 1) {
215 goto exit_free_vrfy_ctx;
216
217 } else if (X509_verify_cert(vrfy_ctx) == 1) {
218
219 s = LDNS_STATUS_OK;
220
221 } else {
222 s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
223 }
224 *chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
225 if (! *chain) {
226 s = LDNS_STATUS_SSL_ERR;
227 }
228
229exit_free_vrfy_ctx:
230 X509_STORE_CTX_free(vrfy_ctx);
231
232exit_free_empty_store:
233 if (empty_store) {
234 X509_STORE_free(empty_store);
235 }
236 return s;
237}
238
239
240/* Return the validation chain that can be build out of cert, with extra_certs.
241 */
242static ldns_status
243ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
244 X509* cert, STACK_OF(X509)* extra_certs)
245{
246 ldns_status s;
247 X509_STORE* empty_store = NULL;
248 X509_STORE_CTX* vrfy_ctx;
249
250 assert(chain != NULL);
251
252 empty_store = X509_STORE_new();
253 s = LDNS_STATUS_SSL_ERR;
254 vrfy_ctx = X509_STORE_CTX_new();
255 if (! vrfy_ctx) {
256
257 goto exit_free_empty_store;
258
259 } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
260 cert, extra_certs) != 1) {
261 goto exit_free_vrfy_ctx;
262 }
263 (void) X509_verify_cert(vrfy_ctx);
264 *chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
265 if (! *chain) {
266 s = LDNS_STATUS_SSL_ERR;
267 } else {
268 s = LDNS_STATUS_OK;
269 }
270exit_free_vrfy_ctx:
271 X509_STORE_CTX_free(vrfy_ctx);
272
273exit_free_empty_store:
274 X509_STORE_free(empty_store);
275 return s;
276}
277
278
279/* Pop n+1 certs and return the last popped.
280 */
281static ldns_status
282ldns_dane_get_nth_cert_from_validation_chain(
283 X509** cert, STACK_OF(X509)* chain, int n, bool ca)
284{
285 if (n >= sk_X509_num(chain) || n < 0) {
286 return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE;
287 }
288 *cert = sk_X509_pop(chain);
289 while (n-- > 0) {
290 X509_free(*cert);
291 *cert = sk_X509_pop(chain);
292 }
293 if (ca && ! X509_check_ca(*cert)) {
294 return LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
295 }
296 return LDNS_STATUS_OK;
297}
298
299
300/* Create validation chain with cert and extra_certs and returns the last
301 * self-signed (if present).
302 */
303static ldns_status
304ldns_dane_pkix_get_last_self_signed(X509** out_cert,
305 X509* cert, STACK_OF(X509)* extra_certs)
306{
307 ldns_status s;
308 X509_STORE* empty_store = NULL;
309 X509_STORE_CTX* vrfy_ctx;
310
311 assert(out_cert != NULL);
312
313 empty_store = X509_STORE_new();
314 s = LDNS_STATUS_SSL_ERR;
315 vrfy_ctx = X509_STORE_CTX_new();
316 if (! vrfy_ctx) {
317 goto exit_free_empty_store;
318
319 } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
320 cert, extra_certs) != 1) {
321 goto exit_free_vrfy_ctx;
322
323 }
324 (void) X509_verify_cert(vrfy_ctx);
325 if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
326 vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
327
328 *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
329 s = LDNS_STATUS_OK;
330 } else {
331 s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR;
332 }
333exit_free_vrfy_ctx:
334 X509_STORE_CTX_free(vrfy_ctx);
335
336exit_free_empty_store:
337 X509_STORE_free(empty_store);
338 return s;
339}
340
341
342ldns_status
343ldns_dane_select_certificate(X509** selected_cert,
344 X509* cert, STACK_OF(X509)* extra_certs,
345 X509_STORE* pkix_validation_store,
346 ldns_tlsa_certificate_usage cert_usage, int offset)
347{
348 ldns_status s;
349 STACK_OF(X509)* pkix_validation_chain = NULL;
350
351 assert(selected_cert != NULL);
352 assert(cert != NULL);
353
354 /* With PKIX validation explicitely turned off (pkix_validation_store
355 * == NULL), treat the "CA constraint" and "Service certificate
356 * constraint" the same as "Trust anchor assertion" and "Domain issued
357 * certificate" respectively.
358 */
359 if (pkix_validation_store == NULL) {
360 switch (cert_usage) {
361
362 case LDNS_TLSA_USAGE_CA_CONSTRAINT:
363
364 cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION;
365 break;
366
367 case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
368
369 cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE;
370 break;
371
372 default:
373 break;
374 }
375 }
376
377 /* Now what to do with each Certificate usage...
378 */
379 switch (cert_usage) {
380
381 case LDNS_TLSA_USAGE_CA_CONSTRAINT:
382
383 s = ldns_dane_pkix_validate_and_get_chain(
384 &pkix_validation_chain,
385 cert, extra_certs,
386 pkix_validation_store);
387 if (! pkix_validation_chain) {
388 return s;
389 }
390 if (s == LDNS_STATUS_OK) {
391 if (offset == -1) {
392 offset = 0;
393 }
394 s = ldns_dane_get_nth_cert_from_validation_chain(
395 selected_cert, pkix_validation_chain,
396 offset, true);
397 }
398 sk_X509_pop_free(pkix_validation_chain, X509_free);
399 return s;
400 break;
401
402
403 case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
404
405 *selected_cert = cert;
406 return ldns_dane_pkix_validate(cert, extra_certs,
407 pkix_validation_store);
408 break;
409
410
411 case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
412
413 if (offset == -1) {
414 s = ldns_dane_pkix_get_last_self_signed(
415 selected_cert, cert, extra_certs);
416 return s;
417 } else {
418 s = ldns_dane_pkix_get_chain(
419 &pkix_validation_chain,
420 cert, extra_certs);
421 if (s == LDNS_STATUS_OK) {
422 s =
423 ldns_dane_get_nth_cert_from_validation_chain(
424 selected_cert, pkix_validation_chain,
425 offset, false);
426 } else if (! pkix_validation_chain) {
427 return s;
428 }
429 sk_X509_pop_free(pkix_validation_chain, X509_free);
430 return s;
431 }
432 break;
433
434
435 case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
436
437 *selected_cert = cert;
438 return LDNS_STATUS_OK;
439 break;
440
441 default:
442 return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
443 break;
444 }
445}
446
447
448ldns_status
449ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
450 ldns_tlsa_certificate_usage certificate_usage,
451 ldns_tlsa_selector selector,
452 ldns_tlsa_matching_type matching_type,
453 X509* cert)
454{
455 ldns_rdf* rdf;
456 ldns_status s;
457
458 assert(tlsa != NULL);
459 assert(cert != NULL);
460
461 /* create rr */
462 *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA);
463 if (*tlsa == NULL) {
464 return LDNS_STATUS_MEM_ERR;
465 }
466
467 rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
468 (uint8_t)certificate_usage);
469 if (rdf == NULL) {
470 goto memerror;
471 }
472 (void) ldns_rr_set_rdf(*tlsa, rdf, 0);
473
474 rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector);
475 if (rdf == NULL) {
476 goto memerror;
477 }
478 (void) ldns_rr_set_rdf(*tlsa, rdf, 1);
479
480 rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type);
481 if (rdf == NULL) {
482 goto memerror;
483 }
484 (void) ldns_rr_set_rdf(*tlsa, rdf, 2);
485
486 s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type);
487 if (s == LDNS_STATUS_OK) {
488 (void) ldns_rr_set_rdf(*tlsa, rdf, 3);
489 return LDNS_STATUS_OK;
490 }
491 ldns_rr_free(*tlsa);
492 *tlsa = NULL;
493 return s;
494
495memerror:
496 ldns_rr_free(*tlsa);
497 *tlsa = NULL;
498 return LDNS_STATUS_MEM_ERR;
499}
500
501
502/* Return tlsas that actually are TLSA resource records with known values
503 * for the Certificate usage, Selector and Matching type rdata fields.
504 */
505static ldns_rr_list*
506ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
507{
508 size_t i;
509 ldns_rr_list* r = ldns_rr_list_new();
510 ldns_rr* tlsa_rr;
511
512 if (! r) {
513 return NULL;
514 }
515 for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
516 tlsa_rr = ldns_rr_list_rr(tlsas, i);
517 if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA &&
518 ldns_rr_rd_count(tlsa_rr) == 4 &&
519 ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 &&
520 ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 &&
521 ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) {
522
523 if (! ldns_rr_list_push_rr(r, tlsa_rr)) {
524 ldns_rr_list_free(r);
525 return NULL;
526 }
527 }
528 }
529 return r;
530}
531
532
533/* Return whether cert/selector/matching_type matches data.
534 */
535static ldns_status
536ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
537 ldns_tlsa_matching_type matching_type, ldns_rdf* data)
538{
539 ldns_status s;
540 ldns_rdf* match_data;
541
542 s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type);
543 if (s == LDNS_STATUS_OK) {
544 if (ldns_rdf_compare(data, match_data) != 0) {
545 s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
546 }
547 ldns_rdf_free(match_data);
548 }
549 return s;
550}
551
552
553/* Return whether any certificate from the chain with selector/matching_type
554 * matches data.
555 * ca should be true if the certificate has to be a CA certificate too.
556 */
557static ldns_status
558ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
559 ldns_tlsa_selector selector,
560 ldns_tlsa_matching_type matching_type,
561 ldns_rdf* data, bool ca)
562{
563 ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
564 size_t n, i;
565 X509* cert;
566
567 n = (size_t)sk_X509_num(chain);
568 for (i = 0; i < n; i++) {
569 cert = sk_X509_pop(chain);
570 if (! cert) {
571 s = LDNS_STATUS_SSL_ERR;
572 break;
573 }
574 s = ldns_dane_match_cert_with_data(cert,
575 selector, matching_type, data);
576 if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
577 s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
578 }
579 X509_free(cert);
580 if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
581 break;
582 }
583 /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
584 * try to match the next certificate
585 */
586 }
587 return s;
588}
589
590
591ldns_status
592ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
593 X509* cert, STACK_OF(X509)* extra_certs,
594 X509_STORE* pkix_validation_store)
595{
596 ldns_status s;
597
598 STACK_OF(X509)* pkix_validation_chain = NULL;
599
600 ldns_tlsa_certificate_usage cert_usage;
601 ldns_tlsa_selector selector;
602 ldns_tlsa_matching_type matching_type;
603 ldns_rdf* data;
604
605 if (! tlsa_rr) {
606 /* No TLSA, so regular PKIX validation
607 */
608 return ldns_dane_pkix_validate(cert, extra_certs,
609 pkix_validation_store);
610 }
611 cert_usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
612 selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
613 matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
614 data = ldns_rr_rdf(tlsa_rr, 3) ;
615
616 switch (cert_usage) {
617 case LDNS_TLSA_USAGE_CA_CONSTRAINT:
618 s = ldns_dane_pkix_validate_and_get_chain(
619 &pkix_validation_chain,
620 cert, extra_certs,
621 pkix_validation_store);
622 if (! pkix_validation_chain) {
623 return s;
624 }
625 if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
626 /*
627 * NO PKIX validation. We still try to match *any*
628 * certificate from the chain, so we return
629 * TLSA errors over PKIX errors.
630 *
631 * i.e. When the TLSA matches no certificate, we return
632 * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE
633 */
634 s = ldns_dane_match_any_cert_with_data(
635 pkix_validation_chain,
636 selector, matching_type, data, true);
637
638 if (s == LDNS_STATUS_OK) {
639 /* A TLSA record did match a cert from the
640 * chain, thus the error is failed PKIX
641 * validation.
642 */
643 s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
644 }
645
646 } else if (s == LDNS_STATUS_OK) {
647 /* PKIX validated, does the TLSA match too? */
648
649 s = ldns_dane_match_any_cert_with_data(
650 pkix_validation_chain,
651 selector, matching_type, data, true);
652 }
653 sk_X509_pop_free(pkix_validation_chain, X509_free);
654 return s;
655 break;
656
657 case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
658 s = ldns_dane_match_cert_with_data(cert,
659 selector, matching_type, data);
660
661 if (s == LDNS_STATUS_OK) {
662 return ldns_dane_pkix_validate(cert, extra_certs,
663 pkix_validation_store);
664 }
665 return s;
666 break;
667
668 case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
669 s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
670 cert, extra_certs);
671
672 if (s == LDNS_STATUS_OK) {
673 s = ldns_dane_match_any_cert_with_data(
674 pkix_validation_chain,
675 selector, matching_type, data, false);
676
677 } else if (! pkix_validation_chain) {
678 return s;
679 }
680 sk_X509_pop_free(pkix_validation_chain, X509_free);
681 return s;
682 break;
683
684 case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
685 return ldns_dane_match_cert_with_data(cert,
686 selector, matching_type, data);
687 break;
688
689 default:
690 break;
691 }
692 return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
693}
694
695
696ldns_status
697ldns_dane_verify(ldns_rr_list* tlsas,
698 X509* cert, STACK_OF(X509)* extra_certs,
699 X509_STORE* pkix_validation_store)
700{
701 size_t i;
702 ldns_rr* tlsa_rr;
703 ldns_status s = LDNS_STATUS_OK, ps;
704
705 assert(cert != NULL);
706
707 if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) {
708 tlsas = ldns_dane_filter_unusable_records(tlsas);
709 if (! tlsas) {
710 return LDNS_STATUS_MEM_ERR;
711 }
712 }
713 if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
714 /* No TLSA's, so regular PKIX validation
715 */
716 return ldns_dane_pkix_validate(cert, extra_certs,
717 pkix_validation_store);
718 } else {
719 for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
720 tlsa_rr = ldns_rr_list_rr(tlsas, i);
721 ps = s;
722 s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
723 pkix_validation_store);
724
725 if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
726 s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
727
728 /* which would be LDNS_STATUS_OK (match)
729 * or some fatal error preventing use from
730 * trying the next TLSA record.
731 */
732 break;
733 }
734 s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE
735 * over TLSA_DID_NOT_MATCH
736 */
737 }
738 ldns_rr_list_free(tlsas);
739 }
740 return s;
741}
742#endif /* HAVE_SSL */