/build/ldns-Ls6SRU/ldns-1.8.4/dnssec_verify.c
Go to the documentation of this file.
#include <ldns/config.h>
#include <ldns/ldns.h>
#include <strings.h>
#include <time.h>
#ifdef HAVE_SSL
/* this entire file is rather useless when you don't have
* crypto...
*/
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/md5.h>
ldns_dnssec_data_chain *
ldns_dnssec_data_chain_new(void)
{
ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1);
if(!nc) return NULL;
/*
* not needed anymore because CALLOC initializes everything to zero.
nc->rrset = NULL;
nc->parent_type = 0;
nc->parent = NULL;
nc->signatures = NULL;
nc->packet_rcode = 0;
nc->packet_qtype = 0;
nc->packet_nodata = false;
*/
return nc;
}
void
ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
{
LDNS_FREE(chain);
}
void
ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
{
ldns_rr_list_deep_free(chain->rrset);
ldns_rr_list_deep_free(chain->signatures);
if (chain->parent) {
ldns_dnssec_data_chain_deep_free(chain->parent);
}
LDNS_FREE(chain);
}
void
ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt,
const ldns_dnssec_data_chain *chain)
{
ldns_lookup_table *rcode;
const ldns_rr_descriptor *rr_descriptor;
if (chain) {
ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent);
if (ldns_rr_list_rr_count(chain->rrset) > 0) {
rcode = ldns_lookup_by_id(ldns_rcodes,
(int) chain->packet_rcode);
if (rcode) {
fprintf(out, ";; rcode: %s\n", rcode->name);
}
rr_descriptor = ldns_rr_descript(chain->packet_qtype);
if (rr_descriptor && rr_descriptor->_name) {
fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
} else if (chain->packet_qtype != 0) {
fprintf(out, "TYPE%u",
chain->packet_qtype);
}
if (chain->packet_nodata) {
fprintf(out, ";; NODATA response\n");
}
fprintf(out, "rrset:\n");
ldns_rr_list_print_fmt(out, fmt, chain->rrset);
fprintf(out, "sigs:\n");
ldns_rr_list_print_fmt(out, fmt, chain->signatures);
fprintf(out, "---\n");
} else {
fprintf(out, "<no data>\n");
}
}
}
void
ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
{
ldns_dnssec_data_chain_print_fmt(
out, ldns_output_format_default, chain);
}
static void
ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
uint16_t qflags,
const ldns_pkt *pkt,
ldns_rr_list *signatures,
ldns_dnssec_data_chain *new_chain,
ldns_rdf *key_name,
ldns_rr_class c) {
ldns_rr_list *keys;
ldns_pkt *my_pkt;
if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
new_chain->signatures = ldns_rr_list_clone(signatures);
new_chain->parent_type = 0;
keys = ldns_pkt_rr_list_by_name_and_type(
pkt,
key_name,
LDNS_RR_TYPE_DNSKEY,
LDNS_SECTION_ANY_NOQUESTION
);
if (!keys) {
my_pkt = ldns_resolver_query(res,
key_name,
LDNS_RR_TYPE_DNSKEY,
c,
qflags);
if (my_pkt) {
keys = ldns_pkt_rr_list_by_name_and_type(
my_pkt,
key_name,
LDNS_RR_TYPE_DNSKEY,
LDNS_SECTION_ANY_NOQUESTION
);
new_chain->parent = ldns_dnssec_build_data_chain(res,
qflags,
keys,
my_pkt,
NULL);
new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
ldns_pkt_free(my_pkt);
}
} else {
new_chain->parent = ldns_dnssec_build_data_chain(res,
qflags,
keys,
pkt,
NULL);
new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
}
ldns_rr_list_deep_free(keys);
}
}
static void
ldns_dnssec_build_data_chain_other(ldns_resolver *res,
uint16_t qflags,
ldns_dnssec_data_chain *new_chain,
ldns_rdf *key_name,
ldns_rr_class c,
ldns_rr_list *dss)
{
/* 'self-signed', parent is a DS */
/* okay, either we have other keys signing the current one,
* or the current
* one should have a DS record in the parent zone.
* How do we find this out? Try both?
*
* request DNSKEYS for current zone,
* add all signatures to current level
*/
ldns_pkt *my_pkt;
ldns_rr_list *signatures2;
new_chain->parent_type = 1;
my_pkt = ldns_resolver_query(res,
key_name,
LDNS_RR_TYPE_DS,
c,
qflags);
if (my_pkt) {
dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
key_name,
LDNS_RR_TYPE_DS,
LDNS_SECTION_ANY_NOQUESTION
);
if (dss) {
new_chain->parent = ldns_dnssec_build_data_chain(res,
qflags,
dss,
my_pkt,
NULL);
new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
ldns_rr_list_deep_free(dss);
}
ldns_pkt_free(my_pkt);
}
my_pkt = ldns_resolver_query(res,
key_name,
LDNS_RR_TYPE_DNSKEY,
c,
qflags);
if (my_pkt) {
signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
key_name,
LDNS_RR_TYPE_RRSIG,
LDNS_SECTION_ANSWER);
if (signatures2) {
if (new_chain->signatures) {
printf("There were already sigs!\n");
ldns_rr_list_deep_free(new_chain->signatures);
printf("replacing the old sigs\n");
}
new_chain->signatures = signatures2;
}
ldns_pkt_free(my_pkt);
}
}
static ldns_dnssec_data_chain *
ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res,
uint16_t qflags,
ldns_rr *orig_rr,
const ldns_rr_list *rrset,
ldns_dnssec_data_chain *new_chain)
{
ldns_rdf *possible_parent_name;
ldns_pkt *my_pkt;
/* apparently we were not able to find a signing key, so
we assume the chain ends here
*/
/* try parents for auth denial of DS */
if (orig_rr) {
possible_parent_name = ldns_rr_owner(orig_rr);
} else if (rrset && ldns_rr_list_rr_count(rrset) > 0) {
possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0));
} else {
/* no information to go on, give up */
return new_chain;
}
my_pkt = ldns_resolver_query(res,
possible_parent_name,
LDNS_RR_TYPE_DS,
LDNS_RR_CLASS_IN,
qflags);
if (!my_pkt) {
return new_chain;
}
if (ldns_pkt_ancount(my_pkt) > 0) {
/* add error, no sigs but DS in parent */
/*ldns_pkt_print(stdout, my_pkt);*/
ldns_pkt_free(my_pkt);
} else {
/* are there signatures? */
new_chain->parent = ldns_dnssec_build_data_chain(res,
qflags,
NULL,
my_pkt,
NULL);
new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
}
return new_chain;
}
ldns_dnssec_data_chain *
ldns_dnssec_build_data_chain(ldns_resolver *res,
uint16_t qflags,
const ldns_rr_list *rrset,
const ldns_pkt *pkt,
ldns_rr *orig_rr)
{
ldns_rr_list *signatures = NULL;
ldns_rr_list *dss = NULL;
ldns_rr_list *my_rrset;
ldns_pkt *my_pkt;
ldns_rdf *name = NULL, *key_name = NULL;
ldns_rr_type type = 0;
ldns_rr_class c = 0;
bool other_rrset = false;
ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
assert(pkt != NULL);
if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
/* hmm. no dnssec data in the packet. go up to try and deny
* DS? */
return new_chain;
}
if (orig_rr) {
new_chain->rrset = ldns_rr_list_new();
ldns_rr_list_push_rr(new_chain->rrset, orig_rr);
new_chain->parent = ldns_dnssec_build_data_chain(res,
qflags,
rrset,
pkt,
NULL);
new_chain->packet_rcode = ldns_pkt_get_rcode(pkt);
new_chain->packet_qtype = ldns_rr_get_type(orig_rr);
if (ldns_pkt_ancount(pkt) == 0) {
new_chain->packet_nodata = true;
}
return new_chain;
}
if (!rrset || ldns_rr_list_rr_count(rrset) < 1) {
/* hmm, no data, do we have denial? only works if pkt was given,
otherwise caller has to do the check himself */
new_chain->packet_nodata = true;
if (pkt) {
my_rrset = ldns_pkt_rr_list_by_type(pkt,
LDNS_RR_TYPE_NSEC,
LDNS_SECTION_ANY_NOQUESTION
);
if (my_rrset) {
if (ldns_rr_list_rr_count(my_rrset) > 0) {
type = LDNS_RR_TYPE_NSEC;
other_rrset = true;
} else {
ldns_rr_list_deep_free(my_rrset);
my_rrset = NULL;
}
} else {
/* nothing, try nsec3 */
my_rrset = ldns_pkt_rr_list_by_type(pkt,
LDNS_RR_TYPE_NSEC3,
LDNS_SECTION_ANY_NOQUESTION);
if (my_rrset) {
if (ldns_rr_list_rr_count(my_rrset) > 0) {
type = LDNS_RR_TYPE_NSEC3;
other_rrset = true;
} else {
ldns_rr_list_deep_free(my_rrset);
my_rrset = NULL;
}
} else {
/* nothing, stop */
/* try parent zone? for denied insecure? */
return new_chain;
}
}
} else {
return new_chain;
}
} else {
my_rrset = (ldns_rr_list *) rrset;
}
if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) {
new_chain->rrset = ldns_rr_list_clone(my_rrset);
name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0));
type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0));
c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0));
}
if (other_rrset) {
ldns_rr_list_deep_free(my_rrset);
}
/* normally there will only be 1 signature 'set'
but there can be more than 1 denial (wildcards)
so check for NSEC
*/
if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) {
/* just throw in all signatures, the tree builder must sort
this out */
if (pkt) {
signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
} else {
my_pkt = ldns_resolver_query(res, name, type, c, qflags);
if (my_pkt) {
signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
ldns_pkt_free(my_pkt);
}
}
} else {
if (pkt) {
signatures =
ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
name,
type);
}
if (!signatures) {
my_pkt = ldns_resolver_query(res, name, type, c, qflags);
if (my_pkt) {
signatures =
ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt,
name,
type);
ldns_pkt_free(my_pkt);
}
}
}
if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
}
if (!key_name) {
if (signatures) {
ldns_rr_list_deep_free(signatures);
}
return ldns_dnssec_build_data_chain_nokeyname(res,
qflags,
orig_rr,
rrset,
new_chain);
}
if (type != LDNS_RR_TYPE_DNSKEY) {
if (type != LDNS_RR_TYPE_DS ||
ldns_dname_is_subdomain(name, key_name)) {
ldns_dnssec_build_data_chain_dnskey(res,
qflags,
pkt,
signatures,
new_chain,
key_name,
c
);
}
} else {
ldns_dnssec_build_data_chain_other(res,
qflags,
new_chain,
key_name,
c,
dss
);
}
if (signatures) {
ldns_rr_list_deep_free(signatures);
}
return new_chain;
}
ldns_dnssec_trust_tree *
ldns_dnssec_trust_tree_new(void)
{
ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree,
1);
if(!new_tree) return NULL;
new_tree->rr = NULL;
new_tree->rrset = NULL;
new_tree->parent_count = 0;
return new_tree;
}
void
ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
{
size_t i;
if (tree) {
for (i = 0; i < tree->parent_count; i++) {
ldns_dnssec_trust_tree_free(tree->parents[i]);
}
}
LDNS_FREE(tree);
}
size_t
ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
{
size_t result = 0;
size_t parent = 0;
size_t i;
for (i = 0; i < tree->parent_count; i++) {
parent = ldns_dnssec_trust_tree_depth(tree->parents[i]);
if (parent > result) {
result = parent;
}
}
return 1 + result;
}
/* TODO ldns_ */
static void
print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth)
{
size_t i;
for (i = 0; i < nr; i++) {
if (i == nr - 1) {
fprintf(out, "|---");
} else if (map && i < treedepth && map[i] == 1) {
fprintf(out, "| ");
} else {
fprintf(out, " ");
}
}
}
static void
ldns_dnssec_trust_tree_print_sm_fmt(FILE *out,
const ldns_output_format *fmt,
ldns_dnssec_trust_tree *tree,
size_t tabs,
bool extended,
uint8_t *sibmap,
size_t treedepth)
{
size_t i;
const ldns_rr_descriptor *descriptor;
bool mapset = false;
if (!sibmap) {
treedepth = ldns_dnssec_trust_tree_depth(tree);
sibmap = LDNS_XMALLOC(uint8_t, treedepth);
if(!sibmap)
return; /* mem err */
memset(sibmap, 0, treedepth);
mapset = true;
}
if (tree) {
if (tree->rr) {
print_tabs(out, tabs, sibmap, treedepth);
ldns_rdf_print(out, ldns_rr_owner(tree->rr));
descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr));
if (descriptor->_name) {
fprintf(out, " (%s", descriptor->_name);
} else {
fprintf(out, " (TYPE%d",
ldns_rr_get_type(tree->rr));
}
if (tabs > 0) {
if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
fprintf(out, " keytag: %u",
(unsigned int) ldns_calc_keytag(tree->rr));
fprintf(out, " alg: ");
ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
fprintf(out, " flags: ");
ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
} else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
fprintf(out, " keytag: ");
ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
fprintf(out, " digest type: ");
ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
}
if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
fprintf(out, " ");
ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
fprintf(out, " ");
ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1));
}
}
fprintf(out, ")\n");
for (i = 0; i < tree->parent_count; i++) {
if (tree->parent_count > 1 && i < tree->parent_count - 1) {
sibmap[tabs] = 1;
} else {
sibmap[tabs] = 0;
}
/* only print errors */
if (ldns_rr_get_type(tree->parents[i]->rr) ==
LDNS_RR_TYPE_NSEC ||
ldns_rr_get_type(tree->parents[i]->rr) ==
LDNS_RR_TYPE_NSEC3) {
if (tree->parent_status[i] == LDNS_STATUS_OK) {
print_tabs(out, tabs + 1, sibmap, treedepth);
if (tabs == 0 &&
ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS &&
ldns_rr_rd_count(tree->rr) > 0) {
fprintf(out, "Existence of DS is denied by:\n");
} else {
fprintf(out, "Existence is denied by:\n");
}
} else {
/* NS records aren't signed */
if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) {
fprintf(out, "Existence of DS is denied by:\n");
} else {
print_tabs(out, tabs + 1, sibmap, treedepth);
fprintf(out,
"Error in denial of existence: %s\n",
ldns_get_errorstr_by_id(
tree->parent_status[i]));
}
}
} else
if (tree->parent_status[i] != LDNS_STATUS_OK) {
print_tabs(out, tabs + 1, sibmap, treedepth);
fprintf(out,
"%s:\n",
ldns_get_errorstr_by_id(
tree->parent_status[i]));
if (tree->parent_status[i]
== LDNS_STATUS_SSL_ERR) {
printf("; SSL Error: ");
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(HAVE_LIBRESSL)
ERR_load_crypto_strings();
#endif
ERR_print_errors_fp(stdout);
printf("\n");
}
ldns_rr_print_fmt(out, fmt,
tree->
parent_signature[i]);
printf("For RRset:\n");
ldns_rr_list_print_fmt(out, fmt,
tree->rrset);
printf("With key:\n");
ldns_rr_print_fmt(out, fmt,
tree->parents[i]->rr);
}
ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
tree->parents[i],
tabs+1,
extended,
sibmap,
treedepth);
}
} else {
print_tabs(out, tabs, sibmap, treedepth);
fprintf(out, "<no data>\n");
}
} else {
fprintf(out, "<null pointer>\n");
}
if (mapset) {
LDNS_FREE(sibmap);
}
}
void
ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt,
ldns_dnssec_trust_tree *tree,
size_t tabs,
bool extended)
{
ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
tree, tabs, extended, NULL, 0);
}
void
ldns_dnssec_trust_tree_print(FILE *out,
ldns_dnssec_trust_tree *tree,
size_t tabs,
bool extended)
{
ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default,
tree, tabs, extended);
}
ldns_status
ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
const ldns_dnssec_trust_tree *parent,
const ldns_rr *signature,
const ldns_status parent_status)
{
if (tree
&& parent
&& tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
/*
printf("Add parent for: ");
ldns_rr_print(stdout, tree->rr);
printf("parent: ");
ldns_rr_print(stdout, parent->rr);
*/
tree->parents[tree->parent_count] =
(ldns_dnssec_trust_tree *) parent;
tree->parent_status[tree->parent_count] = parent_status;
tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
tree->parent_count++;
return LDNS_STATUS_OK;
} else {
return LDNS_STATUS_ERR;
}
}
/* if rr is null, take the first from the rrset */
ldns_dnssec_trust_tree *
ldns_dnssec_derive_trust_tree_time(
ldns_dnssec_data_chain *data_chain,
ldns_rr *rr,
time_t check_time
)
{
ldns_rr_list *cur_rrset;
ldns_rr_list *cur_sigs;
ldns_rr *cur_rr = NULL;
ldns_rr *cur_sig_rr;
size_t i, j;
ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new();
if(!new_tree)
return NULL;
if (data_chain && data_chain->rrset) {
cur_rrset = data_chain->rrset;
cur_sigs = data_chain->signatures;
if (rr) {
cur_rr = rr;
}
if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
cur_rr = ldns_rr_list_rr(cur_rrset, 0);
}
if (cur_rr) {
new_tree->rr = cur_rr;
new_tree->rrset = cur_rrset;
/* there are three possibilities:
1 - 'normal' rrset, signed by a key
2 - dnskey signed by other dnskey
3 - dnskey proven by higher level DS
(data denied by nsec is a special case that can
occur in multiple places)
*/
if (cur_sigs) {
for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
/* find the appropriate key in the parent list */
cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
ldns_rr_owner(cur_rr)))
{
/* find first that does match */
for (j = 0;
j < ldns_rr_list_rr_count(cur_rrset) &&
ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
j++) {
cur_rr = ldns_rr_list_rr(cur_rrset, j);
}
if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
ldns_rr_owner(cur_rr)))
{
break;
}
}
}
/* option 1 */
if (data_chain->parent) {
ldns_dnssec_derive_trust_tree_normal_rrset_time(
new_tree,
data_chain,
cur_sig_rr,
check_time);
}
/* option 2 */
ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
new_tree,
data_chain,
cur_rr,
cur_sig_rr,
check_time);
}
ldns_dnssec_derive_trust_tree_ds_rrset_time(
new_tree, data_chain,
cur_rr, check_time);
} else {
/* no signatures? maybe it's nsec data */
/* just add every rr from parent as new parent */
ldns_dnssec_derive_trust_tree_no_sig_time(
new_tree, data_chain, check_time);
}
}
}
return new_tree;
}
ldns_dnssec_trust_tree *
ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
{
return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
}
void
ldns_dnssec_derive_trust_tree_normal_rrset_time(
ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
ldns_rr *cur_sig_rr,
time_t check_time)
{
size_t i, j;
ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset);
ldns_dnssec_trust_tree *cur_parent_tree;
ldns_rr *cur_parent_rr;
uint16_t cur_keytag;
ldns_rr_list *tmp_rrset = NULL;
ldns_status cur_status;
cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) {
/* TODO: check wildcard nsec too */
if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
tmp_rrset = cur_rrset;
if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
== LDNS_RR_TYPE_NSEC ||
ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
== LDNS_RR_TYPE_NSEC3) {
/* might contain different names!
sort and split */
ldns_rr_list_sort(cur_rrset);
assert(tmp_rrset == cur_rrset);
tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
/* with nsecs, this might be the wrong one */
while (tmp_rrset &&
ldns_rr_list_rr_count(cur_rrset) > 0 &&
ldns_dname_compare(
ldns_rr_owner(ldns_rr_list_rr(
tmp_rrset, 0)),
ldns_rr_owner(cur_sig_rr)) != 0) {
ldns_rr_list_deep_free(tmp_rrset);
tmp_rrset =
ldns_rr_list_pop_rrset(cur_rrset);
}
}
cur_status = ldns_verify_rrsig_time(
tmp_rrset,
cur_sig_rr,
cur_parent_rr,
check_time);
if (tmp_rrset && tmp_rrset != cur_rrset
) {
ldns_rr_list_deep_free(
tmp_rrset);
tmp_rrset = NULL;
}
/* avoid dupes */
for (i = 0; i < new_tree->parent_count; i++) {
if (cur_parent_rr == new_tree->parents[i]->rr) {
goto done;
}
}
cur_parent_tree =
ldns_dnssec_derive_trust_tree_time(
data_chain->parent,
cur_parent_rr,
check_time);
(void)ldns_dnssec_trust_tree_add_parent(new_tree,
cur_parent_tree,
cur_sig_rr,
cur_status);
}
}
}
}
done:
ldns_rr_list_deep_free(cur_rrset);
}
void
ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
ldns_rr *cur_sig_rr)
{
ldns_dnssec_derive_trust_tree_normal_rrset_time(
new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
}
void
ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
ldns_rr *cur_rr,
ldns_rr *cur_sig_rr,
time_t check_time)
{
size_t j;
ldns_rr_list *cur_rrset = data_chain->rrset;
ldns_dnssec_trust_tree *cur_parent_tree;
ldns_rr *cur_parent_rr;
uint16_t cur_keytag;
ldns_status cur_status;
cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) {
cur_parent_rr = ldns_rr_list_rr(cur_rrset, j);
if (cur_parent_rr != cur_rr &&
ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
) {
cur_parent_tree = ldns_dnssec_trust_tree_new();
cur_parent_tree->rr = cur_parent_rr;
cur_parent_tree->rrset = cur_rrset;
cur_status = ldns_verify_rrsig_time(
cur_rrset, cur_sig_rr,
cur_parent_rr, check_time);
if (ldns_dnssec_trust_tree_add_parent(new_tree,
cur_parent_tree, cur_sig_rr, cur_status))
ldns_dnssec_trust_tree_free(cur_parent_tree);
}
}
}
}
void
ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
ldns_rr *cur_rr,
ldns_rr *cur_sig_rr)
{
ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
}
void
ldns_dnssec_derive_trust_tree_ds_rrset_time(
ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
ldns_rr *cur_rr,
time_t check_time)
{
size_t j, h;
ldns_rr_list *cur_rrset = data_chain->rrset;
ldns_dnssec_trust_tree *cur_parent_tree;
ldns_rr *cur_parent_rr;
/* try the parent to see whether there are DSs there */
if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
data_chain->parent &&
data_chain->parent->rrset
) {
for (j = 0;
j < ldns_rr_list_rr_count(data_chain->parent->rrset);
j++) {
cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) {
cur_rr = ldns_rr_list_rr(cur_rrset, h);
if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
cur_parent_tree =
ldns_dnssec_derive_trust_tree_time(
data_chain->parent,
cur_parent_rr,
check_time);
(void) ldns_dnssec_trust_tree_add_parent(
new_tree,
cur_parent_tree,
NULL,
LDNS_STATUS_OK);
} else {
/*ldns_rr_print(stdout, cur_parent_rr);*/
}
}
}
}
}
}
void
ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
ldns_rr *cur_rr)
{
ldns_dnssec_derive_trust_tree_ds_rrset_time(
new_tree, data_chain, cur_rr, ldns_time(NULL));
}
void
ldns_dnssec_derive_trust_tree_no_sig_time(
ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain,
time_t check_time)
{
size_t i;
ldns_rr_list *cur_rrset;
ldns_rr *cur_parent_rr;
ldns_dnssec_trust_tree *cur_parent_tree;
ldns_status result;
if (data_chain->parent && data_chain->parent->rrset) {
cur_rrset = data_chain->parent->rrset;
/* nsec? */
if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
LDNS_RR_TYPE_NSEC3) {
result = ldns_dnssec_verify_denial_nsec3(
new_tree->rr,
cur_rrset,
data_chain->parent->signatures,
data_chain->packet_rcode,
data_chain->packet_qtype,
data_chain->packet_nodata);
} else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
LDNS_RR_TYPE_NSEC) {
result = ldns_dnssec_verify_denial(
new_tree->rr,
cur_rrset,
data_chain->parent->signatures);
} else {
/* unsigned zone, unsigned parent */
result = LDNS_STATUS_OK;
}
} else {
result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
}
for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
cur_parent_tree =
ldns_dnssec_derive_trust_tree_time(
data_chain->parent,
cur_parent_rr,
check_time);
if (ldns_dnssec_trust_tree_add_parent(new_tree,
cur_parent_tree, NULL, result))
ldns_dnssec_trust_tree_free(cur_parent_tree);
}
}
}
void
ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
ldns_dnssec_data_chain *data_chain)
{
ldns_dnssec_derive_trust_tree_no_sig_time(
new_tree, data_chain, ldns_time(NULL));
}
/*
* returns OK if there is a path from tree to key with only OK
* the (first) error in between otherwise
* or NOT_FOUND if the key wasn't present at all
*/
ldns_status
ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
ldns_rr_list *trusted_keys)
{
size_t i;
ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY;
bool equal;
ldns_status parent_result;
if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
{ if (tree->rr) {
for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
equal = ldns_rr_compare_ds(
tree->rr,
ldns_rr_list_rr(trusted_keys, i));
if (equal) {
result = LDNS_STATUS_OK;
return result;
}
}
}
for (i = 0; i < tree->parent_count; i++) {
parent_result =
ldns_dnssec_trust_tree_contains_keys(tree->parents[i],
trusted_keys);
if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
if (tree->parent_status[i] != LDNS_STATUS_OK) {
result = tree->parent_status[i];
} else {
if (tree->rr &&
ldns_rr_get_type(tree->rr)
== LDNS_RR_TYPE_NSEC &&
parent_result == LDNS_STATUS_OK
) {
result =
LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
} else {
result = parent_result;
}
}
}
}
} else {
result = LDNS_STATUS_ERR;
}
return result;
}
ldns_status
ldns_verify_time(
const ldns_rr_list *rrset,
const ldns_rr_list *rrsig,
const ldns_rr_list *keys,
time_t check_time,
ldns_rr_list *good_keys
)
{
uint16_t i;
ldns_status verify_result = LDNS_STATUS_ERR;
if (!rrset || !rrsig || !keys) {
return LDNS_STATUS_ERR;
}
if (ldns_rr_list_rr_count(rrset) < 1) {
return LDNS_STATUS_ERR;
}
if (ldns_rr_list_rr_count(rrsig) < 1) {
return LDNS_STATUS_CRYPTO_NO_RRSIG;
}
if (ldns_rr_list_rr_count(keys) < 1) {
verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
} else {
for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
ldns_status s = ldns_verify_rrsig_keylist_time(
rrset, ldns_rr_list_rr(rrsig, i),
keys, check_time, good_keys);
/* try a little to get more descriptive error */
if(s == LDNS_STATUS_OK) {
verify_result = LDNS_STATUS_OK;
} else if(verify_result == LDNS_STATUS_ERR)
verify_result = s;
else if(s != LDNS_STATUS_ERR && verify_result ==
LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY)
verify_result = s;
}
}
return verify_result;
}
ldns_status
ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
ldns_rr_list *good_keys)
{
return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
}
ldns_status
ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
const ldns_rr_list *keys, ldns_rr_list *good_keys)
{
uint16_t i;
ldns_status verify_result = LDNS_STATUS_ERR;
if (!rrset || !rrsig || !keys) {
return LDNS_STATUS_ERR;
}
if (ldns_rr_list_rr_count(rrset) < 1) {
return LDNS_STATUS_ERR;
}
if (ldns_rr_list_rr_count(rrsig) < 1) {
return LDNS_STATUS_CRYPTO_NO_RRSIG;
}
if (ldns_rr_list_rr_count(keys) < 1) {
verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
} else {
for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
ldns_status s = ldns_verify_rrsig_keylist_notime(rrset,
ldns_rr_list_rr(rrsig, i), keys, good_keys);
/* try a little to get more descriptive error */
if (s == LDNS_STATUS_OK) {
verify_result = LDNS_STATUS_OK;
} else if (verify_result == LDNS_STATUS_ERR) {
verify_result = s;
} else if (s != LDNS_STATUS_ERR && verify_result ==
LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
verify_result = s;
}
}
}
return verify_result;
}
ldns_rr_list *
ldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
const ldns_rdf *domain,
const ldns_rr_list *keys,
time_t check_time,
ldns_status *status)
{
ldns_rr_list * trusted_keys = NULL;
ldns_rr_list * ds_keys = NULL;
ldns_rdf * prev_parent_domain;
ldns_rdf * parent_domain;
ldns_rr_list * parent_keys = NULL;
if (res && domain && keys) {
if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
domain, keys, check_time))) {
*status = LDNS_STATUS_OK;
} else {
/* No trusted keys in this domain, we'll have to find some in the parent domain */
*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
parent_domain = ldns_dname_left_chop(domain);
while (parent_domain && /* Fail if we are at the root*/
ldns_rdf_size(parent_domain) > 0) {
if ((parent_keys =
ldns_fetch_valid_domain_keys_time(res,
parent_domain,
keys,
check_time,
status))) {
/* Check DS records */
if ((ds_keys =
ldns_validate_domain_ds_time(res,
domain,
parent_keys,
check_time))) {
trusted_keys =
ldns_fetch_valid_domain_keys_time(
res,
domain,
ds_keys,
check_time,
status);
ldns_rr_list_deep_free(ds_keys);
} else {
/* No valid DS at the parent -- fail */
*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
}
ldns_rr_list_deep_free(parent_keys);
break;
} else {
parent_domain = ldns_dname_left_chop((
prev_parent_domain
= parent_domain
));
ldns_rdf_deep_free(prev_parent_domain);
}
}
if (parent_domain) {
ldns_rdf_deep_free(parent_domain);
}
}
}
return trusted_keys;
}
ldns_rr_list *
ldns_fetch_valid_domain_keys(const ldns_resolver *res,
const ldns_rdf *domain,
const ldns_rr_list *keys,
ldns_status *status)
{
return ldns_fetch_valid_domain_keys_time(
res, domain, keys, ldns_time(NULL), status);
}
ldns_rr_list *
ldns_validate_domain_dnskey_time(
const ldns_resolver * res,
const ldns_rdf * domain,
const ldns_rr_list * keys,
time_t check_time
)
{
ldns_pkt * keypkt;
ldns_rr * cur_key;
uint16_t key_i; uint16_t key_j; uint16_t key_k;
uint16_t sig_i; ldns_rr * cur_sig;
ldns_rr_list * domain_keys = NULL;
ldns_rr_list * domain_sigs = NULL;
ldns_rr_list * trusted_keys = NULL;
/* Fetch keys for the domain */
keypkt = ldns_resolver_query(res, domain,
LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
if (keypkt) {
domain_keys = ldns_pkt_rr_list_by_type(keypkt,
LDNS_RR_TYPE_DNSKEY,
LDNS_SECTION_ANSWER);
domain_sigs = ldns_pkt_rr_list_by_type(keypkt,
LDNS_RR_TYPE_RRSIG,
LDNS_SECTION_ANSWER);
/* Try to validate the record using our keys */
for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
cur_key = ldns_rr_list_rr(domain_keys, key_i);
for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j),
cur_key)) {
/* Current key is trusted -- validate */
trusted_keys = ldns_rr_list_new();
for (sig_i=0;
sig_i<ldns_rr_list_rr_count(domain_sigs);
sig_i++) {
cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
/* Avoid non-matching sigs */
if (ldns_rdf2native_int16(
ldns_rr_rrsig_keytag(cur_sig))
== ldns_calc_keytag(cur_key)) {
if (ldns_verify_rrsig_time(
domain_keys,
cur_sig,
cur_key,
check_time)
== LDNS_STATUS_OK) {
/* Push the whole rrset
-- we can't do much more */
for (key_k=0;
key_k<ldns_rr_list_rr_count(
domain_keys);
key_k++) {
ldns_rr_list_push_rr(
trusted_keys,
ldns_rr_clone(
ldns_rr_list_rr(
domain_keys,
key_k)));
}
ldns_rr_list_deep_free(domain_keys);
ldns_rr_list_deep_free(domain_sigs);
ldns_pkt_free(keypkt);
return trusted_keys;
}
}
}
/* Only push our trusted key */
ldns_rr_list_push_rr(trusted_keys,
ldns_rr_clone(cur_key));
}
}
}
ldns_rr_list_deep_free(domain_keys);
ldns_rr_list_deep_free(domain_sigs);
ldns_pkt_free(keypkt);
} else {
/* LDNS_STATUS_CRYPTO_NO_DNSKEY */
}
return trusted_keys;
}
ldns_rr_list *
ldns_validate_domain_dnskey(const ldns_resolver * res,
const ldns_rdf * domain,
const ldns_rr_list * keys)
{
return ldns_validate_domain_dnskey_time(
res, domain, keys, ldns_time(NULL));
}
ldns_rr_list *
ldns_validate_domain_ds_time(
const ldns_resolver *res,
const ldns_rdf * domain,
const ldns_rr_list * keys,
time_t check_time)
{
ldns_pkt * dspkt;
uint16_t key_i;
ldns_rr_list * rrset = NULL;
ldns_rr_list * sigs = NULL;
ldns_rr_list * trusted_keys = NULL;
/* Fetch DS for the domain */
dspkt = ldns_resolver_query(res, domain,
LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
if (dspkt) {
rrset = ldns_pkt_rr_list_by_type(dspkt,
LDNS_RR_TYPE_DS,
LDNS_SECTION_ANSWER);
sigs = ldns_pkt_rr_list_by_type(dspkt,
LDNS_RR_TYPE_RRSIG,
LDNS_SECTION_ANSWER);
/* Validate sigs */
if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
== LDNS_STATUS_OK) {
trusted_keys = ldns_rr_list_new();
for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
ldns_rr_list_push_rr(trusted_keys,
ldns_rr_clone(ldns_rr_list_rr(rrset,
key_i)
)
);
}
}
ldns_rr_list_deep_free(rrset);
ldns_rr_list_deep_free(sigs);
ldns_pkt_free(dspkt);
} else {
/* LDNS_STATUS_CRYPTO_NO_DS */
}
return trusted_keys;
}
ldns_rr_list *
ldns_validate_domain_ds(const ldns_resolver *res,
const ldns_rdf * domain,
const ldns_rr_list * keys)
{
return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
}
ldns_status
ldns_verify_trusted_time(
ldns_resolver *res,
ldns_rr_list *rrset,
ldns_rr_list * rrsigs,
time_t check_time,
ldns_rr_list * validating_keys
)
{
uint16_t sig_i; uint16_t key_i;
ldns_rr * cur_sig; ldns_rr * cur_key;
ldns_rr_list * trusted_keys = NULL;
ldns_status result = LDNS_STATUS_ERR;
if (!res || !rrset || !rrsigs) {
return LDNS_STATUS_ERR;
}
if (ldns_rr_list_rr_count(rrset) < 1) {
return LDNS_STATUS_ERR;
}
if (ldns_rr_list_rr_count(rrsigs) < 1) {
return LDNS_STATUS_CRYPTO_NO_RRSIG;
}
/* Look at each sig */
for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
/* Get a valid signer key and validate the sig */
if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
res,
ldns_rr_rrsig_signame(cur_sig),
ldns_resolver_dnssec_anchors(res),
check_time,
&result))) {
for (key_i = 0;
key_i < ldns_rr_list_rr_count(trusted_keys);
key_i++) {
cur_key = ldns_rr_list_rr(trusted_keys, key_i);
if ((result = ldns_verify_rrsig_time(rrset,
cur_sig,
cur_key,
check_time))
== LDNS_STATUS_OK) {
if (validating_keys) {
ldns_rr_list_push_rr(validating_keys,
ldns_rr_clone(cur_key));
}
ldns_rr_list_deep_free(trusted_keys);
return LDNS_STATUS_OK;
}
}
}
}
ldns_rr_list_deep_free(trusted_keys);
return result;
}
ldns_status
ldns_verify_trusted(
ldns_resolver *res,
ldns_rr_list *rrset,
ldns_rr_list * rrsigs,
ldns_rr_list * validating_keys)
{
return ldns_verify_trusted_time(
res, rrset, rrsigs, ldns_time(NULL), validating_keys);
}
ldns_status
ldns_dnssec_verify_denial(ldns_rr *rr,
ldns_rr_list *nsecs,
ldns_rr_list *rrsigs)
{
ldns_rdf *rr_name;
ldns_rdf *wildcard_name = NULL;
ldns_rdf *chopped_dname;
ldns_rr *cur_nsec;
size_t i;
ldns_status result;
/* needed for wildcard check on exact match */
ldns_rr *rrsig;
bool name_covered = false;
bool type_covered = false;
bool wildcard_covered = false;
bool wildcard_type_covered = false;
bool rr_name_is_root = false;
rr_name = ldns_rr_owner(rr);
rr_name_is_root = ldns_rdf_size(rr_name) == 1
&& *ldns_rdf_data(rr_name) == 0;
if (!rr_name_is_root) {
wildcard_name = ldns_dname_new_frm_str("*");
chopped_dname = ldns_dname_left_chop(rr_name);
result = ldns_dname_cat(wildcard_name, chopped_dname);
ldns_rdf_deep_free(chopped_dname);
if (result != LDNS_STATUS_OK) {
return result;
}
}
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
cur_nsec = ldns_rr_list_rr(nsecs, i);
if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
/* see section 5.4 of RFC4035, if the label count of the NSEC's
RRSIG is equal, then it is proven that wildcard expansion
could not have been used to match the request */
rrsig = ldns_dnssec_get_rrsig_for_name_and_type(
ldns_rr_owner(cur_nsec),
ldns_rr_get_type(cur_nsec),
rrsigs);
if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig))
== ldns_dname_label_count(rr_name)) {
wildcard_covered = true;
}
if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
ldns_rr_get_type(rr))) {
type_covered = true;
}
}
if (ldns_nsec_covers_name(cur_nsec, rr_name)) {
name_covered = true;
}
if (rr_name_is_root)
continue;
if (ldns_dname_compare(wildcard_name,
ldns_rr_owner(cur_nsec)) == 0) {
if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
ldns_rr_get_type(rr))) {
wildcard_type_covered = true;
}
}
if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) {
wildcard_covered = true;
}
}
ldns_rdf_deep_free(wildcard_name);
if (type_covered || !name_covered) {
return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
}
if (rr_name_is_root)
return LDNS_STATUS_OK;
if (wildcard_type_covered || !wildcard_covered) {
return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
}
return LDNS_STATUS_OK;
}
ldns_status
ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
, ldns_rr_list *nsecs
, ATTR_UNUSED(ldns_rr_list *rrsigs)
, ldns_pkt_rcode packet_rcode
, ldns_rr_type packet_qtype
, bool packet_nodata
, ldns_rr **match
)
{
ldns_rdf *closest_encloser;
ldns_rdf *wildcard;
ldns_rdf *hashed_wildcard_name;
bool wildcard_covered = false;
ldns_rdf *zone_name;
ldns_rdf *hashed_name;
ldns_rdf *hashed_next_closer;
size_t i;
ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
if (match) {
*match = NULL;
}
zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0)));
/* section 8.4 */
if (packet_rcode == LDNS_RCODE_NXDOMAIN) {
closest_encloser = ldns_dnssec_nsec3_closest_encloser(
ldns_rr_owner(rr),
ldns_rr_get_type(rr),
nsecs);
if(!closest_encloser) {
result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
goto done;
}
wildcard = ldns_dname_new_frm_str("*");
(void) ldns_dname_cat(wildcard, closest_encloser);
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
hashed_wildcard_name =
ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
wildcard
);
(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
hashed_wildcard_name)) {
wildcard_covered = true;
if (match) {
*match = ldns_rr_list_rr(nsecs, i);
}
}
ldns_rdf_deep_free(hashed_wildcard_name);
}
if (! wildcard_covered) {
result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
} else {
result = LDNS_STATUS_OK;
}
ldns_rdf_deep_free(closest_encloser);
ldns_rdf_deep_free(wildcard);
} else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
/* section 8.5 */
hashed_name = ldns_nsec3_hash_name_frm_nsec3(
ldns_rr_list_rr(nsecs, 0),
ldns_rr_owner(rr));
(void) ldns_dname_cat(hashed_name, zone_name);
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
if (ldns_dname_compare(hashed_name,
ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
== 0) {
if (!ldns_nsec_bitmap_covers_type(
ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
packet_qtype)
&&
!ldns_nsec_bitmap_covers_type(
ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
LDNS_RR_TYPE_CNAME)) {
result = LDNS_STATUS_OK;
if (match) {
*match = ldns_rr_list_rr(nsecs, i);
}
goto done;
}
}
}
ldns_rdf_deep_free(hashed_name);
result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
/* wildcard no data? section 8.7 */
closest_encloser = ldns_dnssec_nsec3_closest_encloser(
ldns_rr_owner(rr),
ldns_rr_get_type(rr),
nsecs);
if(!closest_encloser) {
result = LDNS_STATUS_NSEC3_ERR;
goto done;
}
wildcard = ldns_dname_new_frm_str("*");
(void) ldns_dname_cat(wildcard, closest_encloser);
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
hashed_wildcard_name =
ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
wildcard);
(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
if (ldns_dname_compare(hashed_wildcard_name,
ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
== 0) {
if (!ldns_nsec_bitmap_covers_type(
ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
packet_qtype)
&&
!ldns_nsec_bitmap_covers_type(
ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
LDNS_RR_TYPE_CNAME)) {
result = LDNS_STATUS_OK;
if (match) {
*match = ldns_rr_list_rr(nsecs, i);
}
}
}
ldns_rdf_deep_free(hashed_wildcard_name);
if (result == LDNS_STATUS_OK) {
break;
}
}
ldns_rdf_deep_free(closest_encloser);
ldns_rdf_deep_free(wildcard);
} else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
/* section 8.6 */
/* note: up to XXX this is the same as for 8.5 */
hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs,
0),
ldns_rr_owner(rr)
);
(void) ldns_dname_cat(hashed_name, zone_name);
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
if (ldns_dname_compare(hashed_name,
ldns_rr_owner(ldns_rr_list_rr(nsecs,
i)))
== 0) {
if (!ldns_nsec_bitmap_covers_type(
ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
LDNS_RR_TYPE_DS)
&&
!ldns_nsec_bitmap_covers_type(
ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
LDNS_RR_TYPE_CNAME)) {
result = LDNS_STATUS_OK;
if (match) {
*match = ldns_rr_list_rr(nsecs, i);
}
goto done;
}
}
}
/* XXX see note above */
result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
closest_encloser = ldns_dnssec_nsec3_closest_encloser(
ldns_rr_owner(rr),
ldns_rr_get_type(rr),
nsecs);
if(!closest_encloser) {
result = LDNS_STATUS_NSEC3_ERR;
goto done;
}
/* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
if (ldns_dname_label_count(closest_encloser) + 1
>= ldns_dname_label_count(ldns_rr_owner(rr))) {
/* Query name *is* the "next closer". */
hashed_next_closer = hashed_name;
} else {
ldns_rdf *next_closer;
ldns_rdf_deep_free(hashed_name);
/* "next closer" has less labels than the query name.
* Create the name and hash it.
*/
next_closer = ldns_dname_clone_from(
ldns_rr_owner(rr),
ldns_dname_label_count(ldns_rr_owner(rr))
- (ldns_dname_label_count(closest_encloser) + 1)
);
hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
ldns_rr_list_rr(nsecs, 0),
next_closer
);
(void) ldns_dname_cat(hashed_next_closer, zone_name);
ldns_rdf_deep_free(next_closer);
}
/* Find the NSEC3 that covers the "next closer" */
for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
hashed_next_closer) &&
ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
result = LDNS_STATUS_OK;
if (match) {
*match = ldns_rr_list_rr(nsecs, i);
}
break;
}
}
ldns_rdf_deep_free(hashed_next_closer);
ldns_rdf_deep_free(closest_encloser);
}
done:
ldns_rdf_deep_free(zone_name);
return result;
}
ldns_status
ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
ldns_rr_list *nsecs,
ldns_rr_list *rrsigs,
ldns_pkt_rcode packet_rcode,
ldns_rr_type packet_qtype,
bool packet_nodata)
{
return ldns_dnssec_verify_denial_nsec3_match(
rr, nsecs, rrsigs, packet_rcode,
packet_qtype, packet_nodata, NULL
);
}
#ifdef USE_GOST
EVP_PKEY*
ldns_gost2pkey_raw(const unsigned char* key, size_t keylen)
{
/* prefix header for X509 encoding */
uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
unsigned char encoded[37+64];
const unsigned char* pp;
if(keylen != 64) {
/* key wrong size */
return NULL;
}
/* create evp_key */
memmove(encoded, asn, 37);
memmove(encoded+37, key, 64);
pp = (unsigned char*)&encoded[0];
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
}
static ldns_status
ldns_verify_rrsig_gost_raw(const unsigned char* sig, size_t siglen,
const ldns_buffer* rrset, const unsigned char* key, size_t keylen)
{
EVP_PKEY *evp_key;
ldns_status result;
(void) ldns_key_EVP_load_gost_id();
evp_key = ldns_gost2pkey_raw(key, keylen);
if(!evp_key) {
/* could not convert key */
return LDNS_STATUS_CRYPTO_BOGUS;
}
/* verify signature */
result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset,
evp_key, EVP_get_digestbyname("md_gost94"));
EVP_PKEY_free(evp_key);
return result;
}
#endif
#ifdef USE_ED25519
EVP_PKEY*
ldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x70, 0x03, 0x21, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 32 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
static ldns_status
ldns_verify_rrsig_ed25519_raw(unsigned char* sig, size_t siglen,
ldns_buffer* rrset, unsigned char* key, size_t keylen)
{
EVP_PKEY *evp_key;
ldns_status result;
evp_key = ldns_ed255192pkey_raw(key, keylen);
if(!evp_key) {
/* could not convert key */
return LDNS_STATUS_CRYPTO_BOGUS;
}
result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, NULL);
EVP_PKEY_free(evp_key);
return result;
}
#endif /* USE_ED25519 */
#ifdef USE_ED448
EVP_PKEY*
ldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
{
/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x71, 0x03, 0x3a, 0x00};
int pre_len = 12;
uint8_t buf[256];
EVP_PKEY *evp_key;
/* pp gets modified by d2i() */
const unsigned char* pp = (unsigned char*)buf;
if(keylen != 57 || keylen + pre_len > sizeof(buf))
return NULL; /* wrong length */
memmove(buf, pre, pre_len);
memmove(buf+pre_len, key, keylen);
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
return evp_key;
}
static ldns_status
ldns_verify_rrsig_ed448_raw(unsigned char* sig, size_t siglen,
ldns_buffer* rrset, unsigned char* key, size_t keylen)
{
EVP_PKEY *evp_key;
ldns_status result;
evp_key = ldns_ed4482pkey_raw(key, keylen);
if(!evp_key) {
/* could not convert key */
return LDNS_STATUS_CRYPTO_BOGUS;
}
result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, NULL);
EVP_PKEY_free(evp_key);
return result;
}
#endif /* USE_ED448 */
#ifdef USE_ECDSA
EVP_PKEY*
ldns_ecdsa2pkey_raw(const unsigned char* key, size_t keylen, uint8_t algo)
{
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
const unsigned char* pp = buf;
EVP_PKEY *evp_key;
EC_KEY *ec;
/* check length, which uncompressed must be 2 bignums */
if(algo == LDNS_ECDSAP256SHA256) {
if(keylen != 2*256/8) return NULL;
ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
} else if(algo == LDNS_ECDSAP384SHA384) {
if(keylen != 2*384/8) return NULL;
ec = EC_KEY_new_by_curve_name(NID_secp384r1);
} else ec = NULL;
if(!ec) return NULL;
if(keylen+1 > sizeof(buf))
return NULL; /* sanity check */
/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
* of openssl) for uncompressed data */
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
memmove(buf+1, key, keylen);
if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
EC_KEY_free(ec);
return NULL;
}
evp_key = EVP_PKEY_new();
if(!evp_key) {
EC_KEY_free(ec);
return NULL;
}
if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
EVP_PKEY_free(evp_key);
EC_KEY_free(ec);
return NULL;
}
return evp_key;
}
static ldns_status
ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen,
ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo)
{
EVP_PKEY *evp_key;
ldns_status result;
const EVP_MD *d;
evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo);
if(!evp_key) {
/* could not convert key */
return LDNS_STATUS_CRYPTO_BOGUS;
}
if(algo == LDNS_ECDSAP256SHA256)
d = EVP_sha256();
else d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */
result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d);
EVP_PKEY_free(evp_key);
return result;
}
#endif
ldns_status
ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf,
ldns_buffer *key_buf, uint8_t algo)
{
return ldns_verify_rrsig_buffers_raw(
(unsigned char*)ldns_buffer_begin(rawsig_buf),
ldns_buffer_position(rawsig_buf),
verify_buf,
(unsigned char*)ldns_buffer_begin(key_buf),
ldns_buffer_position(key_buf), algo);
}
ldns_status
ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
ldns_buffer *verify_buf, unsigned char* key, size_t keylen,
uint8_t algo)
{
/* check for right key */
switch(algo) {
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
return ldns_verify_rrsig_dsa_raw(sig,
siglen,
verify_buf,
key,
keylen);
break;
#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
return ldns_verify_rrsig_rsasha1_raw(sig,
siglen,
verify_buf,
key,
keylen);
break;
#ifdef USE_SHA2
case LDNS_RSASHA256:
return ldns_verify_rrsig_rsasha256_raw(sig,
siglen,
verify_buf,
key,
keylen);
break;
case LDNS_RSASHA512:
return ldns_verify_rrsig_rsasha512_raw(sig,
siglen,
verify_buf,
key,
keylen);
break;
#endif
#ifdef USE_GOST
case LDNS_ECC_GOST:
return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf,
key, keylen);
break;
#endif
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
key, keylen, algo);
break;
#endif
#ifdef USE_ED25519
case LDNS_ED25519:
return ldns_verify_rrsig_ed25519_raw(sig, siglen, verify_buf,
key, keylen);
break;
#endif
#ifdef USE_ED448
case LDNS_ED448:
return ldns_verify_rrsig_ed448_raw(sig, siglen, verify_buf,
key, keylen);
break;
#endif
case LDNS_RSAMD5:
return ldns_verify_rrsig_rsamd5_raw(sig,
siglen,
verify_buf,
key,
keylen);
break;
default:
/* do you know this alg?! */
return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
}
}
static void
ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, const ldns_rr* rrsig)
{
uint32_t orig_ttl;
uint16_t i;
uint8_t label_count;
ldns_rdf *wildcard_name;
ldns_rdf *wildcard_chopped;
ldns_rdf *wildcard_chopped_tmp;
if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) {
return;
}
orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
if (label_count <
ldns_dname_label_count(
ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
(void) ldns_str2rdf_dname(&wildcard_name, "*");
wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(
ldns_rr_list_rr(rrset_clone, i)));
while (label_count < ldns_dname_label_count(wildcard_chopped)) {
wildcard_chopped_tmp = ldns_dname_left_chop(
wildcard_chopped);
ldns_rdf_deep_free(wildcard_chopped);
wildcard_chopped = wildcard_chopped_tmp;
}
(void) ldns_dname_cat(wildcard_name, wildcard_chopped);
ldns_rdf_deep_free(wildcard_chopped);
ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(
rrset_clone, i)));
ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i),
wildcard_name);
}
ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
/* convert to lowercase */
ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
}
}
static ldns_status
ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, const ldns_rr* rrsig)
{
uint8_t sig_algo;
if (rrsig == NULL) {
return LDNS_STATUS_CRYPTO_NO_RRSIG;
}
if (ldns_rr_rdf(rrsig, 1) == NULL) {
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
}
sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
/* check for known and implemented algo's now (otherwise
* the function could return a wrong error
*/
/* create a buffer with signature rdata */
/* for some algorithms we need other data than for others... */
/* (the DSA API wants DER encoding for instance) */
switch(sig_algo) {
case LDNS_RSAMD5:
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
case LDNS_RSASHA256:
case LDNS_RSASHA512:
#endif
#ifdef USE_GOST
case LDNS_ECC_GOST:
#endif
#ifdef USE_ED25519
case LDNS_ED25519:
#endif
#ifdef USE_ED448
case LDNS_ED448:
#endif
if (ldns_rr_rdf(rrsig, 8) == NULL) {
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
}
if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8))
!= LDNS_STATUS_OK) {
return LDNS_STATUS_MEM_ERR;
}
break;
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
/* EVP takes rfc2459 format, which is a tad longer than dns format */
if (ldns_rr_rdf(rrsig, 8) == NULL) {
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
}
if (ldns_convert_dsa_rrsig_rdf2asn1(
rawsig_buf, ldns_rr_rdf(rrsig, 8))
!= LDNS_STATUS_OK) {
/*
if (ldns_rdf2buffer_wire(rawsig_buf,
ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
*/
return LDNS_STATUS_MEM_ERR;
}
break;
#endif
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
/* EVP produces an ASN prefix on the signature, which is
* not used in the DNS */
if (ldns_rr_rdf(rrsig, 8) == NULL) {
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
}
if (ldns_convert_ecdsa_rrsig_rdf2asn1(
rawsig_buf, ldns_rr_rdf(rrsig, 8))
!= LDNS_STATUS_OK) {
return LDNS_STATUS_MEM_ERR;
}
break;
#endif
case LDNS_DH:
case LDNS_ECC:
case LDNS_INDIRECT:
return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
default:
return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
}
return LDNS_STATUS_OK;
}
static ldns_status
ldns_rrsig_check_timestamps(const ldns_rr* rrsig, time_t now)
{
int32_t inception, expiration;
/* check the signature time stamps */
inception = (int32_t)ldns_rdf2native_time_t(
ldns_rr_rrsig_inception(rrsig));
expiration = (int32_t)ldns_rdf2native_time_t(
ldns_rr_rrsig_expiration(rrsig));
if (expiration - inception < 0) {
/* bad sig, expiration before inception?? Tsssg */
return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
}
if (((int32_t) now) - inception < 0) {
/* bad sig, inception date has not yet come to pass */
return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
}
if (expiration - ((int32_t) now) < 0) {
/* bad sig, expiration date has passed */
return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
}
return LDNS_STATUS_OK;
}
static ldns_status
ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
ldns_rr_list* rrset_clone, const ldns_rr* rrsig)
{
ldns_status result;
/* canonicalize the sig */
ldns_dname2canonical(ldns_rr_owner(rrsig));
/* check if the typecovered is equal to the type checked */
if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0)))
return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
/* create a buffer with b64 signature rdata */
result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig);
if(result != LDNS_STATUS_OK)
return result;
/* use TTL from signature. Use wildcard names for wildcards */
/* also canonicalizes rrset_clone */
ldns_rrset_use_signature_ttl(rrset_clone, rrsig);
/* sort the rrset in canonical order */
ldns_rr_list_sort(rrset_clone);
/* put the signature rr (without the b64) to the verify_buf */
if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK)
return LDNS_STATUS_MEM_ERR;
/* add the rrset in verify_buf */
if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone)
!= LDNS_STATUS_OK)
return LDNS_STATUS_MEM_ERR;
return LDNS_STATUS_OK;
}
static ldns_status
ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
const ldns_rr* rrsig, ldns_rr* key)
{
uint8_t sig_algo;
if (rrsig == NULL) {
return LDNS_STATUS_CRYPTO_NO_RRSIG;
}
if (ldns_rr_rdf(rrsig, 1) == NULL) {
return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
}
sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
/* before anything, check if the keytags match */
if (ldns_calc_keytag(key)
==
ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
) {
ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
ldns_status result = LDNS_STATUS_ERR;
/* put the key-data in a buffer, that's the third rdf, with
* the base64 encoded key data */
if (ldns_rr_rdf(key, 3) == NULL) {
ldns_buffer_free(key_buf);
return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
}
if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3))
!= LDNS_STATUS_OK) {
ldns_buffer_free(key_buf);
/* returning is bad might screw up
good keys later in the list
what to do? */
return LDNS_STATUS_ERR;
}
if (ldns_rr_rdf(key, 2) == NULL) {
result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
}
else if (sig_algo == ldns_rdf2native_int8(
ldns_rr_rdf(key, 2))) {
result = ldns_verify_rrsig_buffers(rawsig_buf,
verify_buf, key_buf, sig_algo);
} else {
/* No keys with the corresponding algorithm are found */
result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
}
ldns_buffer_free(key_buf);
return result;
}
else {
/* No keys with the corresponding keytag are found */
return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
}
}
/*
* to verify:
* - create the wire fmt of the b64 key rdata
* - create the wire fmt of the sorted rrset
* - create the wire fmt of the b64 sig rdata
* - create the wire fmt of the sig without the b64 rdata
* - cat the sig data (without b64 rdata) to the rrset
* - verify the rrset+sig, with the b64 data and the b64 key data
*/
ldns_status
ldns_verify_rrsig_keylist_time(
const ldns_rr_list *rrset,
const ldns_rr *rrsig,
const ldns_rr_list *keys,
time_t check_time,
ldns_rr_list *good_keys)
{
ldns_status result;
ldns_rr_list *valid;
if (!good_keys)
valid = NULL;
else if (!(valid = ldns_rr_list_new()))
return LDNS_STATUS_MEM_ERR;
result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid);
if(result != LDNS_STATUS_OK) {
ldns_rr_list_free(valid);
return result;
}
/* check timestamps last; its OK except time */
result = ldns_rrsig_check_timestamps(rrsig, check_time);
if(result != LDNS_STATUS_OK) {
ldns_rr_list_free(valid);
return result;
}
ldns_rr_list_cat(good_keys, valid);
ldns_rr_list_free(valid);
return LDNS_STATUS_OK;
}
/*
* to verify:
* - create the wire fmt of the b64 key rdata
* - create the wire fmt of the sorted rrset
* - create the wire fmt of the b64 sig rdata
* - create the wire fmt of the sig without the b64 rdata
* - cat the sig data (without b64 rdata) to the rrset
* - verify the rrset+sig, with the b64 data and the b64 key data
*/
ldns_status
ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
ldns_rr *rrsig,
const ldns_rr_list *keys,
ldns_rr_list *good_keys)
{
return ldns_verify_rrsig_keylist_time(
rrset, rrsig, keys, ldns_time(NULL), good_keys);
}
ldns_status
ldns_verify_rrsig_keylist_notime(const ldns_rr_list *rrset,
const ldns_rr *rrsig,
const ldns_rr_list *keys,
ldns_rr_list *good_keys)
{
ldns_buffer *rawsig_buf;
ldns_buffer *verify_buf;
uint16_t i;
ldns_status result, status;
ldns_rr_list *rrset_clone;
ldns_rr_list *validkeys;
if (!rrset) {
return LDNS_STATUS_ERR;
}
validkeys = ldns_rr_list_new();
if (!validkeys) {
return LDNS_STATUS_MEM_ERR;
}
/* clone the rrset so that we can fiddle with it */
rrset_clone = ldns_rr_list_clone(rrset);
/* create the buffers which will certainly hold the raw data */
rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
result = ldns_prepare_for_verify(rawsig_buf, verify_buf,
rrset_clone, rrsig);
if(result != LDNS_STATUS_OK) {
ldns_buffer_free(verify_buf);
ldns_buffer_free(rawsig_buf);
ldns_rr_list_deep_free(rrset_clone);
ldns_rr_list_free(validkeys);
return result;
}
result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
status = ldns_verify_test_sig_key(rawsig_buf, verify_buf,
rrsig, ldns_rr_list_rr(keys, i));
if (status == LDNS_STATUS_OK) {
/* one of the keys has matched, don't break
* here, instead put the 'winning' key in
* the validkey list and return the list
* later */
if (!ldns_rr_list_push_rr(validkeys,
ldns_rr_list_rr(keys,i))) {
/* couldn't push the key?? */
ldns_buffer_free(rawsig_buf);
ldns_buffer_free(verify_buf);
ldns_rr_list_deep_free(rrset_clone);
ldns_rr_list_free(validkeys);
return LDNS_STATUS_MEM_ERR;
}
result = status;
}
if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
result = status;
}
}
/* no longer needed */
ldns_rr_list_deep_free(rrset_clone);
ldns_buffer_free(rawsig_buf);
ldns_buffer_free(verify_buf);
if (ldns_rr_list_rr_count(validkeys) == 0) {
/* no keys were added, return last error */
ldns_rr_list_free(validkeys);
return result;
}
/* do not check timestamps */
ldns_rr_list_cat(good_keys, validkeys);
ldns_rr_list_free(validkeys);
return LDNS_STATUS_OK;
}
ldns_status
ldns_verify_rrsig_time(
ldns_rr_list *rrset,
ldns_rr *rrsig,
ldns_rr *key,
time_t check_time)
{
ldns_buffer *rawsig_buf;
ldns_buffer *verify_buf;
ldns_status result;
ldns_rr_list *rrset_clone;
if (!rrset) {
return LDNS_STATUS_NO_DATA;
}
/* clone the rrset so that we can fiddle with it */
rrset_clone = ldns_rr_list_clone(rrset);
/* create the buffers which will certainly hold the raw data */
rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
result = ldns_prepare_for_verify(rawsig_buf, verify_buf,
rrset_clone, rrsig);
if(result != LDNS_STATUS_OK) {
ldns_rr_list_deep_free(rrset_clone);
ldns_buffer_free(rawsig_buf);
ldns_buffer_free(verify_buf);
return result;
}
result = ldns_verify_test_sig_key(rawsig_buf, verify_buf,
rrsig, key);
/* no longer needed */
ldns_rr_list_deep_free(rrset_clone);
ldns_buffer_free(rawsig_buf);
ldns_buffer_free(verify_buf);
/* check timestamp last, apart from time its OK */
if(result == LDNS_STATUS_OK)
result = ldns_rrsig_check_timestamps(rrsig, check_time);
return result;
}
ldns_status
ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
{
return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
}
ldns_status
ldns_verify_rrsig_evp(ldns_buffer *sig,
ldns_buffer *rrset,
EVP_PKEY *key,
const EVP_MD *digest_type)
{
return ldns_verify_rrsig_evp_raw(
(unsigned char*)ldns_buffer_begin(sig),
ldns_buffer_position(sig),
rrset,
key,
digest_type);
}
ldns_status
ldns_verify_rrsig_evp_raw(const unsigned char *sig, size_t siglen,
const ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
{
EVP_MD_CTX *ctx;
int res;
#ifdef HAVE_EVP_MD_CTX_NEW
ctx = EVP_MD_CTX_new();
#else
ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
if(ctx) EVP_MD_CTX_init(ctx);
#endif
if(!ctx)
return LDNS_STATUS_MEM_ERR;
#if defined(USE_ED25519) || defined(USE_ED448)
if(!digest_type) {
res = EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, key);
if(res == 1) {
res = EVP_DigestVerify(ctx, sig, siglen,
ldns_buffer_begin(rrset),
ldns_buffer_position(rrset));
}
} else {
#else
res = 0;
if(digest_type) {
#endif
EVP_VerifyInit(ctx, digest_type);
EVP_VerifyUpdate(ctx,
ldns_buffer_begin(rrset),
ldns_buffer_position(rrset));
res = EVP_VerifyFinal(ctx, sig, (unsigned int) siglen, key);
}
EVP_MD_CTX_destroy(ctx);
if (res == 1) {
return LDNS_STATUS_OK;
} else if (res == 0) {
return LDNS_STATUS_CRYPTO_BOGUS;
}
/* TODO how to communicate internal SSL error?
let caller use ssl's get_error() */
return LDNS_STATUS_SSL_ERR;
}
ldns_status
ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
{
return ldns_verify_rrsig_dsa_raw(
(unsigned char*) ldns_buffer_begin(sig),
ldns_buffer_position(sig),
rrset,
(unsigned char*) ldns_buffer_begin(key),
ldns_buffer_position(key));
}
ldns_status
ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
{
return ldns_verify_rrsig_rsasha1_raw(
(unsigned char*)ldns_buffer_begin(sig),
ldns_buffer_position(sig),
rrset,
(unsigned char*) ldns_buffer_begin(key),
ldns_buffer_position(key));
}
ldns_status
ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
{
return ldns_verify_rrsig_rsamd5_raw(
(unsigned char*)ldns_buffer_begin(sig),
ldns_buffer_position(sig),
rrset,
(unsigned char*) ldns_buffer_begin(key),
ldns_buffer_position(key));
}
ldns_status
ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
ldns_buffer* rrset, unsigned char* key, size_t keylen)
{
#ifdef USE_DSA
EVP_PKEY *evp_key;
ldns_status result;
evp_key = EVP_PKEY_new();
if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) {
result = ldns_verify_rrsig_evp_raw(sig,
siglen,
rrset,
evp_key,
# ifdef HAVE_EVP_DSS1
EVP_dss1()
# else
EVP_sha1()
# endif
);
} else {
result = LDNS_STATUS_SSL_ERR;
}
EVP_PKEY_free(evp_key);
return result;
#else
(void)sig; (void)siglen; (void)rrset; (void)key; (void)keylen;
return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
#endif
}
ldns_status
ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
ldns_buffer* rrset, unsigned char* key, size_t keylen)
{
EVP_PKEY *evp_key;
ldns_status result;
evp_key = EVP_PKEY_new();
if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
result = ldns_verify_rrsig_evp_raw(sig,
siglen,
rrset,
evp_key,
EVP_sha1());
} else {
result = LDNS_STATUS_SSL_ERR;
}
EVP_PKEY_free(evp_key);
return result;
}
ldns_status
ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
size_t siglen,
ldns_buffer* rrset,
unsigned char* key,
size_t keylen)
{
#ifdef USE_SHA2
EVP_PKEY *evp_key;
ldns_status result;
evp_key = EVP_PKEY_new();
if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
result = ldns_verify_rrsig_evp_raw(sig,
siglen,
rrset,
evp_key,
EVP_sha256());
} else {
result = LDNS_STATUS_SSL_ERR;
}
EVP_PKEY_free(evp_key);
return result;
#else
/* touch these to prevent compiler warnings */
(void) sig;
(void) siglen;
(void) rrset;
(void) key;
(void) keylen;
return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
#endif
}
ldns_status
ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
size_t siglen,
ldns_buffer* rrset,
unsigned char* key,
size_t keylen)
{
#ifdef USE_SHA2
EVP_PKEY *evp_key;
ldns_status result;
evp_key = EVP_PKEY_new();
if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
result = ldns_verify_rrsig_evp_raw(sig,
siglen,
rrset,
evp_key,
EVP_sha512());
} else {
result = LDNS_STATUS_SSL_ERR;
}
EVP_PKEY_free(evp_key);
return result;
#else
/* touch these to prevent compiler warnings */
(void) sig;
(void) siglen;
(void) rrset;
(void) key;
(void) keylen;
return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
#endif
}
ldns_status
ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
size_t siglen,
ldns_buffer* rrset,
unsigned char* key,
size_t keylen)
{
EVP_PKEY *evp_key;
ldns_status result;
evp_key = EVP_PKEY_new();
if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
result = ldns_verify_rrsig_evp_raw(sig,
siglen,
rrset,
evp_key,
EVP_md5());
} else {
result = LDNS_STATUS_SSL_ERR;
}
EVP_PKEY_free(evp_key);
return result;
}
#endif
ldns_buffer_free
void ldns_buffer_free(ldns_buffer *buffer)
frees the buffer.
Definition buffer.c:137
ldns_buffer
struct ldns_struct_buffer ldns_buffer
Definition buffer.h:72
ldns_buffer_new
ldns_buffer * ldns_buffer_new(size_t capacity)
creates a new buffer with the specified capacity.
Definition buffer.c:16
ATTR_UNUSED
#define ATTR_UNUSED(x)
Definition common.h:72
config.h
ldns_dname_is_subdomain
signed char ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent)
test whether the name sub falls under parent (i.e.
Definition dname.c:296
ldns_dname_compare
int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
Compares the two dname rdf's according to the algorithm for ordering in RFC4034 Section 6.
Definition dname.c:359
ldns_dname_left_chop
ldns_rdf * ldns_dname_left_chop(const ldns_rdf *d)
chop one label off the left side of a dname.
Definition dname.c:189
ldns_dname_clone_from
ldns_rdf * ldns_dname_clone_from(const ldns_rdf *d, uint16_t n)
Clones the given dname from the nth label on.
Definition dname.c:160
ldns_dname2canonical
void ldns_dname2canonical(const ldns_rdf *rdf)
Put a dname into canonical fmt - ie.
Definition dname.c:280
ldns_dname_label_count
uint8_t ldns_dname_label_count(const ldns_rdf *r)
count the number of labels inside a LDNS_RDF_DNAME type rdf.
Definition dname.c:214
ldns_dname_cat
ldns_status ldns_dname_cat(ldns_rdf *rd1, const ldns_rdf *rd2)
concatenates rd2 after rd1 (rd2 is copied, rd1 is modified)
Definition dname.c:90
ldns_dname_new_frm_str
ldns_rdf * ldns_dname_new_frm_str(const char *str)
creates a new dname rdf from a string.
Definition dname.c:268
ldns_dnssec_pkt_get_rrsigs_for_type
ldns_rr_list * ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type)
Returns a ldns_rr_list containing the signatures covering the given type.
Definition dnssec.c:250
ldns_nsec_bitmap_covers_type
signed char ldns_nsec_bitmap_covers_type(const ldns_rdf *bitmap, ldns_rr_type type)
Check if RR type t is enumerated and set in the RR type bitmap rdf.
Definition dnssec.c:1393
ldns_gost2pkey_raw
EVP_PKEY * ldns_gost2pkey_raw(const unsigned char *key, size_t keylen)
Converts a holding buffer with key material to EVP PKEY in openssl.
ldns_dnssec_get_rrsig_for_name_and_type
ldns_rr * ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, const ldns_rr_type type, const ldns_rr_list *rrs)
Returns the first RRSIG rr that corresponds to the rrset with the given name and type.
Definition dnssec.c:34
ldns_convert_ecdsa_rrsig_rdf2asn1
ldns_status ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, const ldns_rdf *sig_rdf)
Converts the RRSIG signature RDF (from DNS) to a buffer with the signature in ASN1 format as openssl ...
Definition dnssec.c:1909
ldns_key_buf2dsa_raw
DSA * ldns_key_buf2dsa_raw(const unsigned char *key, size_t len)
Like ldns_key_buf2dsa, but uses raw buffer.
Definition dnssec.c:344
ldns_dnssec_pkt_get_rrsigs_for_name_and_type
ldns_rr_list * ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, const ldns_rdf *name, ldns_rr_type type)
Returns a ldns_rr_list containing the signatures covering the given name and type.
Definition dnssec.c:223
ldns_nsec_get_bitmap
ldns_rdf * ldns_nsec_get_bitmap(const ldns_rr *nsec)
Returns the rdata field that contains the bitmap of the covered types of the given NSEC record.
Definition dnssec.c:89
ldns_nsec_covers_name
signed char ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
Checks coverage of NSEC(3) RR name span Remember that nsec and name must both be in canonical form (i...
Definition dnssec.c:1508
ldns_dnssec_pkt_has_rrsigs
signed char ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt)
Checks whether the packet contains rrsigs.
Definition dnssec.c:204
ldns_calc_keytag
uint16_t ldns_calc_keytag(const ldns_rr *key)
calculates a keytag of a key for use in DNSSEC.
Definition dnssec.c:277
ldns_nsec3_hash_name_frm_nsec3
ldns_rdf * ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, const ldns_rdf *name)
Calculates the hashed name using the parameters of the given NSEC3 RR.
Definition dnssec.c:1368
ldns_key_buf2rsa_raw
RSA * ldns_key_buf2rsa_raw(const unsigned char *key, size_t len)
Like ldns_key_buf2rsa, but uses raw buffer.
Definition dnssec.c:421
ldns_convert_dsa_rrsig_rdf2asn1
ldns_status ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, const ldns_rdf *sig_rdf)
Converts the RRSIG signature RDF (in rfc2536 format) to a buffer with the signature in rfc2459 format...
Definition dnssec.c:1807
ldns_nsec3_optout
signed char ldns_nsec3_optout(const ldns_rr *nsec3_rr)
Returns true if the opt-out flag has been set in the given NSEC3 RR.
Definition dnssec.c:1286
ldns_nsec3_bitmap
ldns_rdf * ldns_nsec3_bitmap(const ldns_rr *nsec3_rr)
Returns the bitmap specifying the covered types of the given NSEC3 RR.
Definition dnssec.c:1358
ldns_dnssec_nsec3_closest_encloser
ldns_rdf * ldns_dnssec_nsec3_closest_encloser(const ldns_rdf *qname, ldns_rr_type qtype, const ldns_rr_list *nsec3s)
Returns the dname of the closest (provable) encloser.
ldns_ecdsa2pkey_raw
EVP_PKEY * ldns_ecdsa2pkey_raw(const unsigned char *key, size_t keylen, uint8_t algo)
Converts a holding buffer with key material to EVP PKEY in openssl.
Definition dnssec_verify.c:1948
ldns_dnssec_derive_trust_tree
ldns_dnssec_trust_tree * ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
Generates a dnssec_trust_tree for the given rr from the given data_chain.
Definition dnssec_verify.c:786
ldns_validate_domain_ds
ldns_rr_list * ldns_validate_domain_ds(const ldns_resolver *res, const ldns_rdf *domain, const ldns_rr_list *keys)
Validates the DS RRset for the given domain using the provided trusted keys.
Definition dnssec_verify.c:1418
ldns_verify_rrsig_buffers_raw
ldns_status ldns_verify_rrsig_buffers_raw(unsigned char *sig, size_t siglen, ldns_buffer *verify_buf, unsigned char *key, size_t keylen, uint8_t algo)
Like ldns_verify_rrsig_buffers, but uses raw data.
Definition dnssec_verify.c:2021
ldns_dnssec_verify_denial_nsec3_match
ldns_status ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr, ldns_rr_list *nsecs, ldns_rr_list *rrsigs __attribute__((unused)), ldns_pkt_rcode packet_rcode, ldns_rr_type packet_qtype, signed char packet_nodata, ldns_rr **match)
Definition dnssec_verify.c:1590
ldns_dnssec_data_chain_print
void ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
Prints the dnssec_data_chain to the given file stream.
Definition dnssec_verify.c:91
ldns_dnssec_derive_trust_tree_dnskey_rrset_time
void ldns_dnssec_derive_trust_tree_dnskey_rrset_time(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, ldns_rr *cur_rr, ldns_rr *cur_sig_rr, time_t check_time)
Sub function for derive_trust_tree that is used for DNSKEY rrsets.
Definition dnssec_verify.c:883
ldns_validate_domain_dnskey_time
ldns_rr_list * ldns_validate_domain_dnskey_time(const ldns_resolver *res, const ldns_rdf *domain, const ldns_rr_list *keys, time_t check_time)
Validates the DNSKEY RRset for the given domain using the provided trusted keys.
Definition dnssec_verify.c:1267
ldns_verify_rrsig_keylist_time
ldns_status ldns_verify_rrsig_keylist_time(const ldns_rr_list *rrset, const ldns_rr *rrsig, const ldns_rr_list *keys, time_t check_time, ldns_rr_list *good_keys)
Verifies an rrsig.
Definition dnssec_verify.c:2398
ldns_verify_notime
ldns_status ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys)
Verifies a list of signatures for one rrset, but disregard the time.
Definition dnssec_verify.c:1149
ldns_verify_rrsig_keylist
ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys)
Verifies an rrsig.
Definition dnssec_verify.c:2442
ldns_verify_rrsig_rsasha256_raw
ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char *sig, size_t siglen, ldns_buffer *rrset, unsigned char *key, size_t keylen)
Like ldns_verify_rrsig_rsasha256, but uses raw signature and key data.
Definition dnssec_verify.c:2735
ldns_fetch_valid_domain_keys_time
ldns_rr_list * ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, const ldns_rdf *domain, const ldns_rr_list *keys, time_t check_time, ldns_status *status)
Tries to build an authentication chain from the given keys down to the queried domain.
Definition dnssec_verify.c:1189
ldns_ed4482pkey_raw
EVP_PKEY * ldns_ed4482pkey_raw(const unsigned char *key, size_t keylen)
Converts a holding buffer with key material to EVP PKEY in openssl.
Definition dnssec_verify.c:1910
ldns_fetch_valid_domain_keys
ldns_rr_list * ldns_fetch_valid_domain_keys(const ldns_resolver *res, const ldns_rdf *domain, const ldns_rr_list *keys, ldns_status *status)
Tries to build an authentication chain from the given keys down to the queried domain.
Definition dnssec_verify.c:1257
ldns_verify_rrsig_rsasha1
ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
verifies a buffer with signature data (RSASHA1) for a buffer with rrset data with a buffer with key d...
Definition dnssec_verify.c:2660
ldns_dnssec_derive_trust_tree_dnskey_rrset
void ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, ldns_rr *cur_rr, ldns_rr *cur_sig_rr)
Sub function for derive_trust_tree that is used for DNSKEY rrsets.
Definition dnssec_verify.c:920
ldns_verify_rrsig_keylist_notime
ldns_status ldns_verify_rrsig_keylist_notime(const ldns_rr_list *rrset, const ldns_rr *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys)
Verifies an rrsig.
Definition dnssec_verify.c:2452
ldns_dnssec_verify_denial
ldns_status ldns_dnssec_verify_denial(ldns_rr *rr, ldns_rr_list *nsecs, ldns_rr_list *rrsigs)
denial is not just a river in egypt
Definition dnssec_verify.c:1501
ldns_dnssec_build_data_chain
ldns_dnssec_data_chain * ldns_dnssec_build_data_chain(ldns_resolver *res, uint16_t qflags, const ldns_rr_list *rrset, const ldns_pkt *pkt, ldns_rr *orig_rr)
Build an ldns_dnssec_data_chain, which contains all DNSSEC data that is needed to derive the trust tr...
Definition dnssec_verify.c:270
ldns_validate_domain_dnskey
ldns_rr_list * ldns_validate_domain_dnskey(const ldns_resolver *res, const ldns_rdf *domain, const ldns_rr_list *keys)
Validates the DNSKEY RRset for the given domain using the provided trusted keys.
Definition dnssec_verify.c:1361
ldns_verify_rrsig_dsa_raw
ldns_status ldns_verify_rrsig_dsa_raw(unsigned char *sig, size_t siglen, ldns_buffer *rrset, unsigned char *key, size_t keylen)
Like ldns_verify_rrsig_dsa, but uses raw signature and key data.
Definition dnssec_verify.c:2682
ldns_verify_trusted
ldns_status ldns_verify_trusted(ldns_resolver *res, ldns_rr_list *rrset, ldns_rr_list *rrsigs, ldns_rr_list *validating_keys)
Verifies a list of signatures for one RRset using a valid trust path.
Definition dnssec_verify.c:1489
ldns_verify_rrsig_rsamd5
ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
verifies a buffer with signature data (RSAMD5) for a buffer with rrset data with a buffer with key da...
Definition dnssec_verify.c:2671
ldns_verify_rrsig_buffers
ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, ldns_buffer *key_buf, uint8_t algo)
Verifies the already processed data in the buffers This function should probably not be used directly...
Definition dnssec_verify.c:2009
ldns_verify_rrsig
ldns_status ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
verify an rrsig with 1 key
Definition dnssec_verify.c:2579
ldns_dnssec_derive_trust_tree_no_sig
void ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain)
Sub function for derive_trust_tree that is used when there are no signatures.
Definition dnssec_verify.c:1036
ldns_dnssec_derive_trust_tree_no_sig_time
void ldns_dnssec_derive_trust_tree_no_sig_time(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, time_t check_time)
Sub function for derive_trust_tree that is used when there are no signatures.
Definition dnssec_verify.c:983
ldns_ed255192pkey_raw
EVP_PKEY * ldns_ed255192pkey_raw(const unsigned char *key, size_t keylen)
Converts a holding buffer with key material to EVP PKEY in openssl.
Definition dnssec_verify.c:1872
ldns_dnssec_data_chain_deep_free
void ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
Frees a dnssec_data_chain structure, and all data contained therein.
Definition dnssec_verify.c:45
ldns_dnssec_trust_tree_contains_keys
ldns_status ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, ldns_rr_list *trusted_keys)
Returns OK if there is a trusted path in the tree to one of the DNSKEY or DS RRs in the given list.
Definition dnssec_verify.c:1049
ldns_verify_rrsig_rsasha1_raw
ldns_status ldns_verify_rrsig_rsasha1_raw(unsigned char *sig, size_t siglen, ldns_buffer *rrset, unsigned char *key, size_t keylen)
Like ldns_verify_rrsig_rsasha1, but uses raw signature and key data.
Definition dnssec_verify.c:2713
ldns_verify_rrsig_rsasha512_raw
ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char *sig, size_t siglen, ldns_buffer *rrset, unsigned char *key, size_t keylen)
Like ldns_verify_rrsig_rsasha512, but uses raw signature and key data.
Definition dnssec_verify.c:2770
ldns_verify_trusted_time
ldns_status ldns_verify_trusted_time(ldns_resolver *res, ldns_rr_list *rrset, ldns_rr_list *rrsigs, time_t check_time, ldns_rr_list *validating_keys)
Verifies a list of signatures for one RRset using a valid trust path.
Definition dnssec_verify.c:1426
ldns_dnssec_verify_denial_nsec3
ldns_status ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, ldns_rr_list *nsecs, ldns_rr_list *rrsigs, ldns_pkt_rcode packet_rcode, ldns_rr_type packet_qtype, signed char packet_nodata)
Denial of existence using NSEC3 records Since NSEC3 is a bit more complicated than normal denial,...
Definition dnssec_verify.c:1810
ldns_verify_rrsig_dsa
ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
verifies a buffer with signature data (DSA) for a buffer with rrset data with a buffer with key data.
Definition dnssec_verify.c:2649
ldns_verify_rrsig_rsamd5_raw
ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char *sig, size_t siglen, ldns_buffer *rrset, unsigned char *key, size_t keylen)
Like ldns_verify_rrsig_rsamd5, but uses raw signature and key data.
Definition dnssec_verify.c:2806
ldns_validate_domain_ds_time
ldns_rr_list * ldns_validate_domain_ds_time(const ldns_resolver *res, const ldns_rdf *domain, const ldns_rr_list *keys, time_t check_time)
Validates the DS RRset for the given domain using the provided trusted keys.
Definition dnssec_verify.c:1370
ldns_dnssec_data_chain_print_fmt
void ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_dnssec_data_chain *chain)
Prints the dnssec_data_chain to the given file stream.
Definition dnssec_verify.c:56
ldns_verify_rrsig_evp_raw
ldns_status ldns_verify_rrsig_evp_raw(const unsigned char *sig, size_t siglen, const ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
Like ldns_verify_rrsig_evp, but uses raw signature data.
Definition dnssec_verify.c:2600
ldns_dnssec_trust_tree_new
ldns_dnssec_trust_tree * ldns_dnssec_trust_tree_new(void)
Creates a new (empty) dnssec_trust_tree structure.
Definition dnssec_verify.c:445
ldns_dnssec_data_chain_free
void ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
Frees a dnssec_data_chain structure.
Definition dnssec_verify.c:39
ldns_verify_rrsig_time
ldns_status ldns_verify_rrsig_time(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key, time_t check_time)
verify an rrsig with 1 key
Definition dnssec_verify.c:2536
ldns_dnssec_data_chain_new
ldns_dnssec_data_chain * ldns_dnssec_data_chain_new(void)
Creates a new dnssec_chain structure.
Definition dnssec_verify.c:19
ldns_verify_time
ldns_status ldns_verify_time(const ldns_rr_list *rrset, const ldns_rr_list *rrsig, const ldns_rr_list *keys, time_t check_time, ldns_rr_list *good_keys)
Verifies a list of signatures for one rrset.
Definition dnssec_verify.c:1098
ldns_dnssec_derive_trust_tree_ds_rrset
void ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, ldns_rr *cur_rr)
Sub function for derive_trust_tree that is used for DS rrsets.
Definition dnssec_verify.c:974
ldns_verify
ldns_status ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, ldns_rr_list *good_keys)
Verifies a list of signatures for one rrset.
Definition dnssec_verify.c:1142
ldns_dnssec_derive_trust_tree_normal_rrset
void ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, ldns_rr *cur_sig_rr)
Sub function for derive_trust_tree that is used for a 'normal' rrset.
Definition dnssec_verify.c:874
ldns_dnssec_trust_tree_add_parent
ldns_status ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, const ldns_dnssec_trust_tree *parent, const ldns_rr *signature, const ldns_status parent_status)
Adds a trust tree as a parent for the given trust tree.
Definition dnssec_verify.c:658
ldns_dnssec_trust_tree_depth
size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
returns the depth of the trust tree
Definition dnssec_verify.c:470
ldns_dnssec_derive_trust_tree_time
ldns_dnssec_trust_tree * ldns_dnssec_derive_trust_tree_time(ldns_dnssec_data_chain *data_chain, ldns_rr *rr, time_t check_time)
Generates a dnssec_trust_tree for the given rr from the given data_chain.
Definition dnssec_verify.c:685
ldns_dnssec_trust_tree_free
void ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
Frees the dnssec_trust_tree recursively.
Definition dnssec_verify.c:458
ldns_verify_rrsig_evp
ldns_status ldns_verify_rrsig_evp(ldns_buffer *sig, ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
verifies a buffer with signature data for a buffer with rrset data with an EVP_PKEY
Definition dnssec_verify.c:2586
ldns_dnssec_trust_tree_print_fmt
void ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_trust_tree *tree, size_t tabs, signed char extended)
Prints the dnssec_trust_tree structure to the given file stream.
Definition dnssec_verify.c:637
ldns_dnssec_derive_trust_tree_normal_rrset_time
void ldns_dnssec_derive_trust_tree_normal_rrset_time(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, ldns_rr *cur_sig_rr, time_t check_time)
Sub function for derive_trust_tree that is used for a 'normal' rrset.
Definition dnssec_verify.c:792
ldns_dnssec_derive_trust_tree_ds_rrset_time
void ldns_dnssec_derive_trust_tree_ds_rrset_time(ldns_dnssec_trust_tree *new_tree, ldns_dnssec_data_chain *data_chain, ldns_rr *cur_rr, time_t check_time)
Sub function for derive_trust_tree that is used for DS rrsets.
Definition dnssec_verify.c:930
ldns_dnssec_trust_tree_print
void ldns_dnssec_trust_tree_print(FILE *out, ldns_dnssec_trust_tree *tree, size_t tabs, signed char extended)
Prints the dnssec_trust_tree structure to the given file stream.
Definition dnssec_verify.c:647
ldns_dnssec_trust_tree
struct ldns_dnssec_trust_tree_struct ldns_dnssec_trust_tree
Tree structure that contains the relation of DNSSEC data, and their cryptographic status.
Definition dnssec_verify.h:121
ldns_dnssec_data_chain
struct ldns_dnssec_data_chain_struct ldns_dnssec_data_chain
Chain structure that contains all DNSSEC data needed to verify an rrset.
Definition dnssec_verify.h:19
LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS
#define LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS
dnssec_verify
Definition dnssec_verify.h:6
LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY
@ LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY
Definition error.h:56
LDNS_STATUS_NO_DATA
@ LDNS_STATUS_NO_DATA
Definition error.h:77
LDNS_STATUS_CRYPTO_NO_RRSIG
@ LDNS_STATUS_CRYPTO_NO_RRSIG
Definition error.h:54
LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR
@ LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR
Definition error.h:67
LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL
@ LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL
Definition error.h:53
LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED
@ LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED
Definition error.h:100
LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION
@ LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION
Definition error.h:66
LDNS_STATUS_CRYPTO_NO_DNSKEY
@ LDNS_STATUS_CRYPTO_NO_DNSKEY
Definition error.h:55
LDNS_STATUS_SSL_ERR
@ LDNS_STATUS_SSL_ERR
Definition error.h:36
LDNS_STATUS_CRYPTO_NO_TRUSTED_DS
@ LDNS_STATUS_CRYPTO_NO_TRUSTED_DS
Definition error.h:58
LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED
@ LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED
Definition error.h:99
LDNS_STATUS_CRYPTO_BOGUS
@ LDNS_STATUS_CRYPTO_BOGUS
Definition error.h:61
LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY
@ LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY
Definition error.h:59
LDNS_STATUS_NSEC3_ERR
@ LDNS_STATUS_NSEC3_ERR
Definition error.h:69
LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED
@ LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED
Definition error.h:63
LDNS_STATUS_ERR
@ LDNS_STATUS_ERR
Definition error.h:37
LDNS_STATUS_MEM_ERR
@ LDNS_STATUS_MEM_ERR
Definition error.h:34
LDNS_STATUS_DNSSEC_EXISTENCE_DENIED
@ LDNS_STATUS_DNSSEC_EXISTENCE_DENIED
Definition error.h:98
LDNS_STATUS_CRYPTO_SIG_EXPIRED
@ LDNS_STATUS_CRYPTO_SIG_EXPIRED
Definition error.h:62
LDNS_STATUS_CRYPTO_UNKNOWN_ALGO
@ LDNS_STATUS_CRYPTO_UNKNOWN_ALGO
Definition error.h:52
LDNS_STATUS_OK
@ LDNS_STATUS_OK
Definition error.h:26
LDNS_STATUS_MISSING_RDATA_FIELDS_KEY
@ LDNS_STATUS_MISSING_RDATA_FIELDS_KEY
Definition error.h:103
LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG
@ LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG
Definition error.h:102
ldns_status
enum ldns_enum_status ldns_status
Definition error.h:148
ldns_get_errorstr_by_id
const char * ldns_get_errorstr_by_id(ldns_status err)
look up a descriptive text by each error.
Definition error.c:196
ldns_rdf_print
void ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
Prints the data in the rdata field to the given file stream (in presentation format).
Definition host2str.c:3394
ldns_rr_list_print_fmt
void ldns_rr_list_print_fmt(FILE *output, const ldns_output_format *fmt, const ldns_rr_list *list)
print a rr_list to output
Definition host2str.c:3444
ldns_output_format_default
const ldns_output_format * ldns_output_format_default
The default output format record.
Definition host2str.c:142
ldns_output_format
struct ldns_struct_output_format ldns_output_format
Definition host2str.h:95
ldns_rr_print_fmt
void ldns_rr_print_fmt(FILE *output, const ldns_output_format *fmt, const ldns_rr *rr)
Prints the data in the resource record to the given file stream (in presentation format).
Definition host2str.c:3406
ldns_rrsig2buffer_wire
ldns_status ldns_rrsig2buffer_wire(ldns_buffer *output, const ldns_rr *sigrr)
Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata This is needed in DNSSEC verification.
Definition host2wire.c:294
ldns_rdf2buffer_wire
ldns_status ldns_rdf2buffer_wire(ldns_buffer *output, const ldns_rdf *rdf)
Copies the rdata data to the buffer in wire format.
Definition host2wire.c:109
ldns_rr_list2buffer_wire
ldns_status ldns_rr_list2buffer_wire(ldns_buffer *output, const ldns_rr_list *rrlist)
Copies the rr_list data to the buffer in wire format.
Definition host2wire.c:156
ldns_key_EVP_load_gost_id
int ldns_key_EVP_load_gost_id(void)
Get the PKEY id for GOST, loads GOST into openssl as a side effect.
LDNS_ED448
@ LDNS_ED448
Definition keys.h:59
LDNS_RSAMD5
@ LDNS_RSAMD5
Definition keys.h:46
LDNS_ECDSAP384SHA384
@ LDNS_ECDSAP384SHA384
Definition keys.h:57
LDNS_RSASHA1_NSEC3
@ LDNS_RSASHA1_NSEC3
Definition keys.h:52
LDNS_DSA_NSEC3
@ LDNS_DSA_NSEC3
Definition keys.h:51
LDNS_DSA
@ LDNS_DSA
Definition keys.h:48
LDNS_ECDSAP256SHA256
@ LDNS_ECDSAP256SHA256
Definition keys.h:56
LDNS_ECC_GOST
@ LDNS_ECC_GOST
Definition keys.h:55
LDNS_DH
@ LDNS_DH
Definition keys.h:47
LDNS_INDIRECT
@ LDNS_INDIRECT
Definition keys.h:60
LDNS_ECC
@ LDNS_ECC
Definition keys.h:49
LDNS_RSASHA1
@ LDNS_RSASHA1
Definition keys.h:50
LDNS_RSASHA512
@ LDNS_RSASHA512
Definition keys.h:54
LDNS_RSASHA256
@ LDNS_RSASHA256
Definition keys.h:53
LDNS_ED25519
@ LDNS_ED25519
Definition keys.h:58
ldns_rcodes
ldns_lookup_table ldns_rcodes[]
Response codes.
Definition host2str.c:109
LDNS_MAX_PACKETLEN
#define LDNS_MAX_PACKETLEN
Definition packet.h:24
ldns_pkt_free
void ldns_pkt_free(ldns_pkt *packet)
frees the packet structure and all data that it contains.
Definition packet.c:897
ldns_pkt_rr_list_by_type
ldns_rr_list * ldns_pkt_rr_list_by_type(const ldns_pkt *p, ldns_rr_type t, ldns_pkt_section s)
return all the rr with a specific type from a packet.
Definition packet.c:304
ldns_pkt_ancount
uint16_t ldns_pkt_ancount(const ldns_pkt *p)
Return the packet's an count.
Definition packet.c:106
ldns_pkt_rcode
enum ldns_enum_pkt_rcode ldns_pkt_rcode
Definition packet.h:69
ldns_pkt
struct ldns_struct_pkt ldns_pkt
Definition packet.h:272
LDNS_SECTION_ANSWER
@ LDNS_SECTION_ANSWER
Definition packet.h:279
LDNS_SECTION_ANY_NOQUESTION
@ LDNS_SECTION_ANY_NOQUESTION
used to get all non-question rrs from a packet
Definition packet.h:285
LDNS_RD
#define LDNS_RD
Definition packet.h:30
LDNS_RCODE_NXDOMAIN
@ LDNS_RCODE_NXDOMAIN
Definition packet.h:60
ldns_pkt_rr_list_by_name_and_type
ldns_rr_list * ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, const ldns_rdf *ownername, ldns_rr_type type, ldns_pkt_section sec)
return all the rr with a specific type and type from a packet.
Definition packet.c:340
ldns_pkt_get_rcode
ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *p)
Return the packet's response code.
Definition packet.c:94
ldns_rdf_data
uint8_t * ldns_rdf_data(const ldns_rdf *rd)
returns the data of the rdf.
Definition rdata.c:38
ldns_rdf_clone
ldns_rdf * ldns_rdf_clone(const ldns_rdf *rd)
clones a rdf structure.
Definition rdata.c:222
ldns_rdf_deep_free
void ldns_rdf_deep_free(ldns_rdf *rd)
frees a rdf structure and frees the data.
Definition rdata.c:230
ldns_rdf2native_int32
uint32_t ldns_rdf2native_int32(const ldns_rdf *rd)
returns the native uint32_t representation from the rdf.
Definition rdata.c:98
ldns_rdf2native_int16
uint16_t ldns_rdf2native_int16(const ldns_rdf *rd)
returns the native uint16_t representation from the rdf.
Definition rdata.c:84
ldns_rdf2native_int8
uint8_t ldns_rdf2native_int8(const ldns_rdf *rd)
returns the native uint8_t representation from the rdf.
Definition rdata.c:70
ldns_rdf_size
size_t ldns_rdf_size(const ldns_rdf *rd)
returns the size of the rdf.
Definition rdata.c:24
ldns_rdf2native_time_t
time_t ldns_rdf2native_time_t(const ldns_rdf *rd)
returns the native time_t representation from the rdf.
Definition rdata.c:112
ldns_rdf
struct ldns_struct_rdf ldns_rdf
Definition rdata.h:205
ldns_resolver_dnssec_anchors
ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r)
Get the resolver's DNSSEC anchors.
Definition resolver.c:132
ldns_resolver
struct ldns_struct_resolver ldns_resolver
Definition resolver.h:147
ldns_resolver_query
ldns_pkt * ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags)
Send a query to a nameserver.
Definition resolver.c:1129
ldns_rr_list_free
void ldns_rr_list_free(ldns_rr_list *rr_list)
frees an rr_list structure.
Definition rr.c:1015
ldns_rdf2rr_type
ldns_rr_type ldns_rdf2rr_type(const ldns_rdf *rd)
convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual LDNS_RR_TYPE.
Definition rr.c:2762
ldns_rr_list_deep_free
void ldns_rr_list_deep_free(ldns_rr_list *rr_list)
frees an rr_list structure and all rrs contained therein.
Definition rr.c:1024
ldns_rr_set_owner
void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner)
sets the owner in the rr structure.
Definition rr.c:808
ldns_rr
struct ldns_struct_rr ldns_rr
Definition rr.h:337
ldns_rr_list_new
ldns_rr_list * ldns_rr_list_new(void)
creates a new rr_list structure.
Definition rr.c:1004
ldns_rr_list_pop_rrset
ldns_rr_list * ldns_rr_list_pop_rrset(ldns_rr_list *rr_list)
pops the first rrset from the list, the list must be sorted, so that all rr's from each rrset are nex...
Definition rr.c:1352
ldns_rr_list_sort
void ldns_rr_list_sort(ldns_rr_list *unsorted)
sorts an rr_list (canonical wire format).
Definition rr.c:1520
ldns_rr_type
enum ldns_enum_rr_type ldns_rr_type
Definition rr.h:251
LDNS_RR_TYPE_RRSIG
@ LDNS_RR_TYPE_RRSIG
DNSSEC.
Definition rr.h:170
LDNS_RR_TYPE_DNSKEY
@ LDNS_RR_TYPE_DNSKEY
Definition rr.h:172
LDNS_RR_TYPE_NSEC
@ LDNS_RR_TYPE_NSEC
Definition rr.h:171
LDNS_RR_TYPE_DS
@ LDNS_RR_TYPE_DS
RFC4034, RFC3658.
Definition rr.h:164
LDNS_RR_TYPE_CNAME
@ LDNS_RR_TYPE_CNAME
the canonical name for an alias
Definition rr.h:88
LDNS_RR_TYPE_NSEC3
@ LDNS_RR_TYPE_NSEC3
Definition rr.h:176
LDNS_RR_TYPE_NS
@ LDNS_RR_TYPE_NS
an authoritative name server
Definition rr.h:82
ldns_rr_list_push_rr
signed char ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
pushes an rr to an rrlist.
Definition rr.c:1136
ldns_rr2canonical
void ldns_rr2canonical(ldns_rr *rr)
converts each dname in a rr to its canonical form.
Definition rr.c:1785
ldns_rr_rd_count
size_t ldns_rr_rd_count(const ldns_rr *rr)
returns the rd_count of an rr structure.
Definition rr.c:941
ldns_rr_rdf
ldns_rdf * ldns_rr_rdf(const ldns_rr *rr, size_t nr)
returns the rdata field member counter.
Definition rr.c:913
ldns_rr_list_rr_count
size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
returns the number of rr's in an rr_list.
Definition rr.c:961
ldns_rr_get_type
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition rr.c:947
ldns_rr_set_ttl
void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
sets the ttl in the rr structure.
Definition rr.c:820
ldns_rr_clone
ldns_rr * ldns_rr_clone(const ldns_rr *rr)
clones a rr and all its data
Definition rr.c:1404
ldns_rr_compare_ds
signed char ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2)
returns true of the given rr's are equal.
Definition rr.c:1714
ldns_rr_get_class
ldns_rr_class ldns_rr_get_class(const ldns_rr *rr)
returns the class of the rr.
Definition rr.c:953
ldns_rr_list
struct ldns_struct_rr_list ldns_rr_list
Definition rr.h:351
ldns_rr_class
enum ldns_enum_rr_class ldns_rr_class
Definition rr.h:61
ldns_rr_list_rr
ldns_rr * ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
returns a specific rr of an rrlist.
Definition rr.c:994
ldns_rr_list_cat
signed char ldns_rr_list_cat(ldns_rr_list *left, const ldns_rr_list *right)
concatenates two ldns_rr_lists together.
Definition rr.c:1040
ldns_rr_list_clone
ldns_rr_list * ldns_rr_list_clone(const ldns_rr_list *rrlist)
clones an rrlist.
Definition rr.c:1435
ldns_rr_owner
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
Definition rr.c:923
LDNS_RR_CLASS_IN
@ LDNS_RR_CLASS_IN
the Internet
Definition rr.h:47
ldns_rr_descript
const ldns_rr_descriptor * ldns_rr_descript(uint16_t type)
returns the resource record descriptor for the given rr type.
Definition rr.c:2644
ldns_rr_descriptor
struct ldns_struct_rr_descriptor ldns_rr_descriptor
Definition rr.h:377
ldns_rr_rrsig_expiration
ldns_rdf * ldns_rr_rrsig_expiration(const ldns_rr *r)
returns the expiration time of a LDNS_RR_TYPE_RRSIG RR
Definition rr_functions.c:159
ldns_rr_rrsig_inception
ldns_rdf * ldns_rr_rrsig_inception(const ldns_rr *r)
returns the inception time of a LDNS_RR_TYPE_RRSIG RR
Definition rr_functions.c:171
ldns_rr_rrsig_keytag
ldns_rdf * ldns_rr_rrsig_keytag(const ldns_rr *r)
returns the keytag of a LDNS_RR_TYPE_RRSIG RR
Definition rr_functions.c:183
ldns_rr_rrsig_typecovered
ldns_rdf * ldns_rr_rrsig_typecovered(const ldns_rr *r)
returns the type covered of a LDNS_RR_TYPE_RRSIG rr
Definition rr_functions.c:111
ldns_rr_rrsig_signame
ldns_rdf * ldns_rr_rrsig_signame(const ldns_rr *r)
returns the signers name of a LDNS_RR_TYPE_RRSIG RR
Definition rr_functions.c:195
ldns_rr_rrsig_labels
ldns_rdf * ldns_rr_rrsig_labels(const ldns_rr *r)
returns the number of labels of a LDNS_RR_TYPE_RRSIG RR
Definition rr_functions.c:135
ldns_str2rdf_dname
ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str)
convert a dname string into wireformat
Definition str2host.c:311
ldns_dnssec_data_chain_struct::packet_rcode
ldns_pkt_rcode packet_rcode
Definition dnssec_verify.h:26
ldns_dnssec_data_chain_struct::parent_type
ldns_rr_type parent_type
Definition dnssec_verify.h:24
ldns_dnssec_data_chain_struct::signatures
ldns_rr_list * signatures
Definition dnssec_verify.h:23
ldns_dnssec_data_chain_struct::packet_qtype
ldns_rr_type packet_qtype
Definition dnssec_verify.h:27
ldns_dnssec_data_chain_struct::packet_nodata
signed char packet_nodata
Definition dnssec_verify.h:28
ldns_dnssec_data_chain_struct::rrset
ldns_rr_list * rrset
Definition dnssec_verify.h:22
ldns_dnssec_data_chain_struct::parent
ldns_dnssec_data_chain * parent
Definition dnssec_verify.h:25
ldns_dnssec_trust_tree_struct::rrset
ldns_rr_list * rrset
Definition dnssec_verify.h:126
ldns_dnssec_trust_tree_struct::parent_count
size_t parent_count
Definition dnssec_verify.h:132
ldns_dnssec_trust_tree_struct::parents
ldns_dnssec_trust_tree * parents[10]
Definition dnssec_verify.h:127
ldns_dnssec_trust_tree_struct::parent_signature
ldns_rr * parent_signature[10]
for debugging, add signatures too (you might want those if they contain errors)
Definition dnssec_verify.h:131
ldns_dnssec_trust_tree_struct::rr
ldns_rr * rr
Definition dnssec_verify.h:124
ldns_dnssec_trust_tree_struct::parent_status
ldns_status parent_status[10]
Definition dnssec_verify.h:128
ldns_struct_lookup_table::name
const char * name
Definition util.h:158
ldns_struct_rr_descriptor::_name
const char * _name
Textual name of the RR type.
Definition rr.h:363
LDNS_FREE
#define LDNS_FREE(ptr)
Definition util.h:60
LDNS_CALLOC
#define LDNS_CALLOC(type, count)
Definition util.h:53
ldns_lookup_by_id
ldns_lookup_table * ldns_lookup_by_id(ldns_lookup_table table[], int id)
Looks up the table entry by id, returns NULL if not found.
LDNS_XMALLOC
#define LDNS_XMALLOC(type, count)
Definition util.h:51
ldns_lookup_table
struct ldns_struct_lookup_table ldns_lookup_table
Definition util.h:160