mirror of https://github.com/getdnsapi/getdns.git
Three NSEC3 related things:
- Better checking for type bits - NSEC3 Insecure proofs for opt-out on head's - NSEC3 wildcard NODATA proof
This commit is contained in:
parent
99f0026961
commit
f59b32414c
208
src/dnssec.c
208
src/dnssec.c
|
@ -716,38 +716,6 @@ static int bitmap_has_type(priv_getdns_rdf_iter *bitmap, uint16_t rr_type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nsec_bitmap_excludes_rrtype(getdns_rrset *nsec_rrset, uint16_t rr_type)
|
|
||||||
{
|
|
||||||
rrtype_iter nsec_spc, *nsec_rr;
|
|
||||||
priv_getdns_rdf_iter bitmap_spc, *bitmap;
|
|
||||||
|
|
||||||
return (nsec_rrset->rr_type == GETDNS_RRTYPE_NSEC ||
|
|
||||||
nsec_rrset->rr_type == GETDNS_RRTYPE_NSEC3 )
|
|
||||||
&& (nsec_rr = rrtype_iter_init(&nsec_spc, nsec_rrset))
|
|
||||||
|
|
||||||
/* On empty non terminals there might not be a bitmap
|
|
||||||
* since that means rrtype is excluded, we must return true then
|
|
||||||
*/
|
|
||||||
&& ( !(bitmap = priv_getdns_rdf_iter_init_at(
|
|
||||||
&bitmap_spc, &nsec_rr->rr_i,
|
|
||||||
nsec_rrset->rr_type == GETDNS_RRTYPE_NSEC ? 1: 5))
|
|
||||||
|| !bitmap_has_type(bitmap, rr_type)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nsec_bitmap_includes_rrtype(getdns_rrset *nsec_rrset, uint16_t rr_type)
|
|
||||||
{
|
|
||||||
rrtype_iter nsec_spc, *nsec_rr;
|
|
||||||
priv_getdns_rdf_iter bitmap_spc, *bitmap;
|
|
||||||
|
|
||||||
return (nsec_rrset->rr_type == GETDNS_RRTYPE_NSEC ||
|
|
||||||
nsec_rrset->rr_type == GETDNS_RRTYPE_NSEC3 )
|
|
||||||
&& (nsec_rr = rrtype_iter_init(&nsec_spc, nsec_rrset))
|
|
||||||
&& (bitmap = priv_getdns_rdf_iter_init_at(&bitmap_spc, &nsec_rr->rr_i,
|
|
||||||
nsec_rrset->rr_type == GETDNS_RRTYPE_NSEC ? 1: 5))
|
|
||||||
&& bitmap_has_type(bitmap, rr_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t **reverse_labels(uint8_t *dname, uint8_t **labels)
|
static uint8_t **reverse_labels(uint8_t *dname, uint8_t **labels)
|
||||||
{
|
{
|
||||||
if (*dname)
|
if (*dname)
|
||||||
|
@ -849,7 +817,10 @@ static int nsec_covers_name(
|
||||||
|
|
||||||
nsec_cmp = dname_compare(owner, next);
|
nsec_cmp = dname_compare(owner, next);
|
||||||
if (nsec_cmp < 0) {
|
if (nsec_cmp < 0) {
|
||||||
/* Regular NSEC */
|
/* Regular NSEC
|
||||||
|
* >= so it can match the wildcard
|
||||||
|
* (for wildcard NODATA proofs).
|
||||||
|
*/
|
||||||
return dname_compare(name, owner) >= 0
|
return dname_compare(name, owner) >= 0
|
||||||
&& dname_compare(name, next) < 0;
|
&& dname_compare(name, next) < 0;
|
||||||
|
|
||||||
|
@ -947,6 +918,7 @@ static int nsec3_covers_name(getdns_rrset *nsec3, uint8_t *name, int *opt_out)
|
||||||
|
|
||||||
if (!name2nsec3_label(nsec3, name, label, sizeof(label)-1))
|
if (!name2nsec3_label(nsec3, name, label, sizeof(label)-1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
label[label[0]+1] = 0;
|
label[label[0]+1] = 0;
|
||||||
|
|
||||||
if ( !(rr = rrtype_iter_init(&rr_spc, nsec3))
|
if ( !(rr = rrtype_iter_init(&rr_spc, nsec3))
|
||||||
|
@ -972,17 +944,18 @@ static int nsec3_covers_name(getdns_rrset *nsec3, uint8_t *name, int *opt_out)
|
||||||
debug_sec_print_dname(" and: ", next);
|
debug_sec_print_dname(" and: ", next);
|
||||||
|
|
||||||
nsec_cmp = dname_compare(owner, next);
|
nsec_cmp = dname_compare(owner, next);
|
||||||
if (nsec_cmp < 0) {
|
if (nsec_cmp >= 0) {
|
||||||
DEBUG_SEC("nsec owner < next\n");
|
/* The wrap around and apex-only nsec case */
|
||||||
|
return dname_compare(label, owner) > 0
|
||||||
|
|| dname_compare(label, next) < 0;
|
||||||
|
} else {
|
||||||
|
assert(nsec_cmp < 0);
|
||||||
|
/* The normal case
|
||||||
|
* >= so it can match the wildcard
|
||||||
|
* (for wildcard NODATA proofs).
|
||||||
|
*/
|
||||||
return dname_compare(label, owner) >= 0
|
return dname_compare(label, owner) >= 0
|
||||||
&& dname_compare(label, next) < 0;
|
&& dname_compare(label, next) < 0;
|
||||||
} else if (nsec_cmp > 0) {
|
|
||||||
/* The wrap around nsec */
|
|
||||||
DEBUG_SEC("nsec owner > next\n");
|
|
||||||
return dname_compare(label, owner) >= 0;
|
|
||||||
} else {
|
|
||||||
DEBUG_SEC("nsec owner == next\n");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,6 +976,26 @@ static int find_nsec_covering_name(
|
||||||
|
|
||||||
if ((n = rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC3
|
if ((n = rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC3
|
||||||
&& nsec3_covers_name(n, name, opt_out)
|
&& nsec3_covers_name(n, name, opt_out)
|
||||||
|
|
||||||
|
/* Get the bitmap rdata field */
|
||||||
|
&& (nsec_rr = rrtype_iter_init(&nsec_spc, n))
|
||||||
|
&& (bitmap = priv_getdns_rdf_iter_init_at(
|
||||||
|
&bitmap_spc, &nsec_rr->rr_i, 5))
|
||||||
|
|
||||||
|
/* NSEC should cover, but not match name...
|
||||||
|
* Unless it is wildcard match, but then we have to check
|
||||||
|
* that rrset->rr_type is not enlisted, because otherwise
|
||||||
|
* it should have matched the wildcard.
|
||||||
|
*
|
||||||
|
* Also no CNAME... cause that should have matched too.
|
||||||
|
*/
|
||||||
|
&& ( !nsec3_matches_name(n, name)
|
||||||
|
|| ( name[0] == 1 && name[1] == (uint8_t)'*'
|
||||||
|
&& !bitmap_has_type(bitmap, rrset->rr_type)
|
||||||
|
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_CNAME)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
&& (keytag = a_key_signed_rrset(dnskey, n))) {
|
&& (keytag = a_key_signed_rrset(dnskey, n))) {
|
||||||
|
|
||||||
debug_sec_print_rrset("NSEC3: ", n);
|
debug_sec_print_rrset("NSEC3: ", n);
|
||||||
|
@ -1056,14 +1049,21 @@ static int find_nsec_covering_name(
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nsec3_find_next_closer(
|
static int nsec3_find_next_closer(
|
||||||
getdns_rrset *dnskey, getdns_rrset *rrset, uint8_t *nc_name)
|
getdns_rrset *dnskey, getdns_rrset *rrset, uint8_t *nc_name, int *opt_out)
|
||||||
{
|
{
|
||||||
uint8_t wc_name[256] = { 1, (uint8_t)'*' };
|
uint8_t wc_name[256] = { 1, (uint8_t)'*' };
|
||||||
int opt_out, keytag;
|
int my_opt_out, keytag;
|
||||||
|
|
||||||
if (!(keytag = find_nsec_covering_name(dnskey, rrset, nc_name, &opt_out)))
|
if (opt_out)
|
||||||
|
*opt_out = 0;
|
||||||
|
|
||||||
|
if (!(keytag = find_nsec_covering_name(
|
||||||
|
dnskey, rrset, nc_name, &my_opt_out)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (opt_out)
|
||||||
|
*opt_out = my_opt_out;
|
||||||
|
|
||||||
/* Wild card not needed on a "covering" NODATA response,
|
/* Wild card not needed on a "covering" NODATA response,
|
||||||
* because of opt-out?
|
* because of opt-out?
|
||||||
*
|
*
|
||||||
|
@ -1072,13 +1072,13 @@ static int nsec3_find_next_closer(
|
||||||
* (if we came here via getdns_validate_dnssec) in which case
|
* (if we came here via getdns_validate_dnssec) in which case
|
||||||
* rcode is always NOERROR.
|
* rcode is always NOERROR.
|
||||||
*/
|
*/
|
||||||
if (opt_out)
|
if (my_opt_out)
|
||||||
return keytag;
|
return keytag;
|
||||||
|
|
||||||
nc_name += *nc_name + 1;
|
nc_name += *nc_name + 1;
|
||||||
(void) memcpy(wc_name + 2, nc_name, _dname_len(nc_name));
|
(void) memcpy(wc_name + 2, nc_name, _dname_len(nc_name));
|
||||||
|
|
||||||
return find_nsec_covering_name(dnskey, rrset, wc_name, NULL);
|
return find_nsec_covering_name(dnskey, rrset, wc_name, opt_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1088,7 +1088,8 @@ static int nsec3_find_next_closer(
|
||||||
* On success returns the keytag (+0x10000) of the key that signed the proof.
|
* On success returns the keytag (+0x10000) of the key that signed the proof.
|
||||||
* Or else returns 0.
|
* Or else returns 0.
|
||||||
*/
|
*/
|
||||||
static int key_proves_nonexistance(getdns_rrset *keyset, getdns_rrset *rrset)
|
static int key_proves_nonexistance(
|
||||||
|
getdns_rrset *keyset, getdns_rrset *rrset, int *opt_out)
|
||||||
{
|
{
|
||||||
getdns_rrset nsec_rrset, *cover, *ce;
|
getdns_rrset nsec_rrset, *cover, *ce;
|
||||||
rrtype_iter nsec_spc, *nsec_rr;
|
rrtype_iter nsec_spc, *nsec_rr;
|
||||||
|
@ -1100,6 +1101,9 @@ static int key_proves_nonexistance(getdns_rrset *keyset, getdns_rrset *rrset)
|
||||||
|
|
||||||
assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
|
assert(keyset->rr_type == GETDNS_RRTYPE_DNSKEY);
|
||||||
|
|
||||||
|
if (opt_out)
|
||||||
|
opt_out = 0;
|
||||||
|
|
||||||
/* The NSEC NODATA case
|
/* The NSEC NODATA case
|
||||||
* ====================
|
* ====================
|
||||||
* NSEC has same ownername as the rrset to deny.
|
* NSEC has same ownername as the rrset to deny.
|
||||||
|
@ -1125,9 +1129,12 @@ static int key_proves_nonexistance(getdns_rrset *keyset, getdns_rrset *rrset)
|
||||||
|
|
||||||
/* In case of a DS query, make sure we have the parent side NSEC
|
/* In case of a DS query, make sure we have the parent side NSEC
|
||||||
* and not the child (so no SOA).
|
* and not the child (so no SOA).
|
||||||
|
* Except for the root that is checked by itself.
|
||||||
*/
|
*/
|
||||||
&& ( rrset->rr_type != GETDNS_RRTYPE_DS
|
&& ( rrset->rr_type != GETDNS_RRTYPE_DS
|
||||||
|| !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
|
|| !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
|
||||||
|
|| *rrset->name == 0
|
||||||
|
)
|
||||||
|
|
||||||
/* If not a DS query, then make sure the NSEC does not contain NS,
|
/* If not a DS query, then make sure the NSEC does not contain NS,
|
||||||
* or if it does, then also contains SOA, otherwise we have a parent
|
* or if it does, then also contains SOA, otherwise we have a parent
|
||||||
|
@ -1226,21 +1233,74 @@ static int key_proves_nonexistance(getdns_rrset *keyset, getdns_rrset *rrset)
|
||||||
/* The NSEC3 NODATA case
|
/* The NSEC3 NODATA case
|
||||||
* =====================
|
* =====================
|
||||||
* NSEC3 has same (hashed) ownername as the rrset to deny.
|
* NSEC3 has same (hashed) ownername as the rrset to deny.
|
||||||
* Only the rr_type (and CNAME) is missing from the bitmap.
|
|
||||||
*/
|
*/
|
||||||
for ( i = rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len)
|
for ( i = rrset_iter_init(&i_spc, rrset->pkt, rrset->pkt_len)
|
||||||
; i ; i = rrset_iter_next(i)) {
|
; i ; i = rrset_iter_next(i)) {
|
||||||
|
|
||||||
if ((ce = rrset_iter_value(i))->rr_type == GETDNS_RRTYPE_NSEC3
|
/* ce is potentially the NSEC3 that matches complete qname
|
||||||
&& nsec_bitmap_excludes_rrtype(ce, rrset->rr_type)
|
* (so is also the closest encloser)
|
||||||
&& nsec_bitmap_excludes_rrtype(ce, GETDNS_RRTYPE_CNAME)
|
*/
|
||||||
|
ce = rrset_iter_value(i);
|
||||||
|
if ( ce->rr_type == GETDNS_RRTYPE_NSEC3
|
||||||
|
|
||||||
|
/* A NSEC3 RR exists at the owner name of rrset
|
||||||
|
* (this is always true)
|
||||||
|
*/
|
||||||
|
&& (nsec_rr = rrtype_iter_init(&nsec_spc, ce))
|
||||||
|
|
||||||
|
/* Get the bitmap rdata field */
|
||||||
|
&& (bitmap = priv_getdns_rdf_iter_init_at(
|
||||||
|
&bitmap_spc, &nsec_rr->rr_i, 5))
|
||||||
|
|
||||||
|
/* At least the rr_type of rrset should be missing */
|
||||||
|
&& !bitmap_has_type(bitmap, rrset->rr_type)
|
||||||
|
|
||||||
|
/* If the name is a CNAME, then we should have gotten it,
|
||||||
|
* So no CNAME bit either.
|
||||||
|
*/
|
||||||
|
&& !bitmap_has_type(bitmap, GETDNS_RRTYPE_CNAME)
|
||||||
|
|
||||||
|
/* In case of a DS query, make sure we have the parent side
|
||||||
|
* NSEC and not the child (so no SOA).
|
||||||
|
* (except for the root...)
|
||||||
|
*/
|
||||||
|
&& ( rrset->rr_type != GETDNS_RRTYPE_DS
|
||||||
|
|| !bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA)
|
||||||
|
|| *rrset->name == 0
|
||||||
|
)
|
||||||
|
|
||||||
|
/* If not a DS query, then make sure the NSEC does not
|
||||||
|
* contain NS, or if it does, then also contains SOA,
|
||||||
|
* otherwise we have a parent side delegation point NSEC
|
||||||
|
* where we should have gotten a child side NSEC!
|
||||||
|
*/
|
||||||
|
&& ( rrset->rr_type == GETDNS_RRTYPE_DS
|
||||||
|
|| !bitmap_has_type(bitmap, GETDNS_RRTYPE_NS)
|
||||||
|
|| bitmap_has_type(bitmap, GETDNS_RRTYPE_SOA))
|
||||||
|
|
||||||
|
/* The qname must match the NSEC3!
|
||||||
|
* (expensive tests done last)
|
||||||
|
*/
|
||||||
&& nsec3_matches_name(ce, rrset->name)
|
&& nsec3_matches_name(ce, rrset->name)
|
||||||
|
|
||||||
|
/* And it must have a valid signature */
|
||||||
&& (keytag = a_key_signed_rrset(keyset, ce))) {
|
&& (keytag = a_key_signed_rrset(keyset, ce))) {
|
||||||
|
|
||||||
debug_sec_print_rrset("NSEC3 No Data for: ", rrset);
|
debug_sec_print_rrset("NSEC3 No Data for: ", rrset);
|
||||||
return keytag;
|
return keytag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* More NSEC3 NODATA cases
|
||||||
|
* ======================
|
||||||
|
* There are a few NSEC NODATA cases where qname doesn't match
|
||||||
|
* NSEC->name:
|
||||||
|
*
|
||||||
|
* - NSEC3 ownername match for qtype != NSEC3 (TODO?)
|
||||||
|
* - Wildcard NODATA (wildcard owner name match has special handing
|
||||||
|
* find_nsec_covering_name())
|
||||||
|
* - Opt-In DS NODATA (TODO, don't understand yet)
|
||||||
|
*/
|
||||||
|
|
||||||
/* The NSEC3 Name error case
|
/* The NSEC3 Name error case
|
||||||
* ========================+
|
* ========================+
|
||||||
* First find the closest encloser.
|
* First find the closest encloser.
|
||||||
|
@ -1261,7 +1321,9 @@ static int key_proves_nonexistance(getdns_rrset *keyset, getdns_rrset *rrset)
|
||||||
debug_sec_print_dname("Closest Encloser: ", ce_name);
|
debug_sec_print_dname("Closest Encloser: ", ce_name);
|
||||||
debug_sec_print_dname(" Next closer: ", nc_name);
|
debug_sec_print_dname(" Next closer: ", nc_name);
|
||||||
|
|
||||||
if ((keytag = nsec3_find_next_closer(keyset, rrset, nc_name)))
|
if ((keytag = nsec3_find_next_closer(
|
||||||
|
keyset, rrset, nc_name, opt_out)))
|
||||||
|
|
||||||
return keytag;
|
return keytag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1294,7 +1356,7 @@ static int chain_node_get_trusted_keys(
|
||||||
return GETDNS_DNSSEC_SECURE;
|
return GETDNS_DNSSEC_SECURE;
|
||||||
}
|
}
|
||||||
/* ta is ZSK */
|
/* ta is ZSK */
|
||||||
if ((keytag = key_proves_nonexistance(ta, &node->ds))) {
|
if ((keytag = key_proves_nonexistance(ta, &node->ds, NULL))) {
|
||||||
node->ds_signer = keytag;
|
node->ds_signer = keytag;
|
||||||
return GETDNS_DNSSEC_INSECURE;
|
return GETDNS_DNSSEC_INSECURE;
|
||||||
}
|
}
|
||||||
|
@ -1318,7 +1380,7 @@ static int chain_node_get_trusted_keys(
|
||||||
/* keys is an authenticated dnskey rrset always now (i.e. ZSK) */
|
/* keys is an authenticated dnskey rrset always now (i.e. ZSK) */
|
||||||
ta = *keys;
|
ta = *keys;
|
||||||
/* Back up to the head */
|
/* Back up to the head */
|
||||||
if ((keytag = key_proves_nonexistance(ta, &node->ds))) {
|
if ((keytag = key_proves_nonexistance(ta, &node->ds, NULL))) {
|
||||||
node->ds_signer = keytag;
|
node->ds_signer = keytag;
|
||||||
return GETDNS_DNSSEC_INSECURE;
|
return GETDNS_DNSSEC_INSECURE;
|
||||||
}
|
}
|
||||||
|
@ -1339,7 +1401,7 @@ static int chain_node_get_trusted_keys(
|
||||||
static int chain_head_validate_with_ta(chain_head *head, getdns_rrset *ta)
|
static int chain_head_validate_with_ta(chain_head *head, getdns_rrset *ta)
|
||||||
{
|
{
|
||||||
getdns_rrset *keys;
|
getdns_rrset *keys;
|
||||||
int s, keytag;
|
int s, keytag, opt_out;
|
||||||
|
|
||||||
if ((s = chain_node_get_trusted_keys(head->parent, ta, &keys))
|
if ((s = chain_node_get_trusted_keys(head->parent, ta, &keys))
|
||||||
!= GETDNS_DNSSEC_SECURE)
|
!= GETDNS_DNSSEC_SECURE)
|
||||||
|
@ -1349,10 +1411,19 @@ static int chain_head_validate_with_ta(chain_head *head, getdns_rrset *ta)
|
||||||
if ((keytag = a_key_signed_rrset(keys, &head->rrset))) {
|
if ((keytag = a_key_signed_rrset(keys, &head->rrset))) {
|
||||||
head->signer = keytag;
|
head->signer = keytag;
|
||||||
return GETDNS_DNSSEC_SECURE;
|
return GETDNS_DNSSEC_SECURE;
|
||||||
|
|
||||||
|
} else if (!rrset_has_rrsigs(&head->rrset)
|
||||||
|
&& (keytag = key_proves_nonexistance(
|
||||||
|
keys, &head->rrset, &opt_out))
|
||||||
|
&& opt_out) {
|
||||||
|
|
||||||
|
head->signer = keytag;
|
||||||
|
return GETDNS_DNSSEC_INSECURE;
|
||||||
}
|
}
|
||||||
} else if ((keytag = key_proves_nonexistance(keys, &head->rrset))) {
|
} else if ((keytag = key_proves_nonexistance(
|
||||||
|
keys, &head->rrset, &opt_out))) {
|
||||||
head->signer = keytag;
|
head->signer = keytag;
|
||||||
return GETDNS_DNSSEC_SECURE;
|
return opt_out ? GETDNS_DNSSEC_INSECURE : GETDNS_DNSSEC_SECURE;
|
||||||
}
|
}
|
||||||
return GETDNS_DNSSEC_BOGUS;
|
return GETDNS_DNSSEC_BOGUS;
|
||||||
}
|
}
|
||||||
|
@ -1560,15 +1631,24 @@ static void check_chain_complete(chain_head *chain)
|
||||||
|
|
||||||
#ifdef STUB_NATIVE_DNSSEC
|
#ifdef STUB_NATIVE_DNSSEC
|
||||||
/* Perform validation only on GETDNS_RESOLUTION_STUB (unbound_id == -1)
|
/* Perform validation only on GETDNS_RESOLUTION_STUB (unbound_id == -1)
|
||||||
* TODO: When minimizing the validation chain (i.e. returning a single
|
* Or when asked for the validation chain (to identify the RRSIGs that
|
||||||
* RRSIG per RRSET, it might be usefull to perform a fake dnssec
|
* signed the RRSETs, so that only those will be included in the
|
||||||
* validation to find out which RRSIGs should be returned.
|
* validation chain)
|
||||||
|
* In any case we must have a trust anchor.
|
||||||
*/
|
*/
|
||||||
if (chain->netreq->unbound_id == -1 && context->trust_anchors)
|
if (( chain->netreq->unbound_id == -1
|
||||||
|
|| dnsreq->dnssec_return_validation_chain)
|
||||||
|
&& context->trust_anchors)
|
||||||
|
|
||||||
|
chain_set_netreq_dnssec_status(chain,rrset_iter_init(&tas_iter,
|
||||||
|
context->trust_anchors, context->trust_anchors_len));
|
||||||
|
#else
|
||||||
|
if (dnsreq->dnssec_return_validation_chain
|
||||||
|
&& context->trust_anchors)
|
||||||
|
|
||||||
chain_set_netreq_dnssec_status(chain,rrset_iter_init(&tas_iter,
|
chain_set_netreq_dnssec_status(chain,rrset_iter_init(&tas_iter,
|
||||||
context->trust_anchors, context->trust_anchors_len));
|
context->trust_anchors, context->trust_anchors_len));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
val_chain_list = dnsreq->dnssec_return_validation_chain
|
val_chain_list = dnsreq->dnssec_return_validation_chain
|
||||||
? getdns_list_create_with_context(context) : NULL;
|
? getdns_list_create_with_context(context) : NULL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue