mirror of https://github.com/getdnsapi/getdns.git
Sort RR's to validate
This commit is contained in:
parent
e47bd33ec0
commit
8b414c8570
128
src/dnssec.c
128
src/dnssec.c
|
@ -266,6 +266,20 @@ static uint8_t *_dname_label_copy(uint8_t *dst, const uint8_t *src, size_t dst_l
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static void _dname_canonicalize(uint8_t *dname)
|
||||||
|
{
|
||||||
|
uint8_t *next_label;
|
||||||
|
|
||||||
|
while (*dname) {
|
||||||
|
next_label = dname + *dname + 1;
|
||||||
|
dname += 1;
|
||||||
|
while (dname < next_label) {
|
||||||
|
*dname = (uint8_t)tolower((unsigned char)*dname);
|
||||||
|
dname++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fills the array pointed to by labels (of at least 128 uint8_t * pointers)
|
/* Fills the array pointed to by labels (of at least 128 uint8_t * pointers)
|
||||||
* with pointers to labels in given dname in reversed order. So that
|
* with pointers to labels in given dname in reversed order. So that
|
||||||
* labels[0] will point to the root.
|
* labels[0] will point to the root.
|
||||||
|
@ -1434,6 +1448,105 @@ static size_t _rr_rdata_size(rrtype_iter *rr)
|
||||||
return rr->rr_i.nxt - rr->rr_i.rr_type - 10;
|
return rr->rr_i.nxt - rr->rr_i.rr_type - 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Iterate byte by byte over rdata canonicalizing dname's */
|
||||||
|
typedef struct canon_rdata_iter {
|
||||||
|
_getdns_rdf_iter rdf_spc;
|
||||||
|
_getdns_rdf_iter *rdf;
|
||||||
|
uint8_t cdname[256]; /* Canonical dname */
|
||||||
|
uint8_t *pos;
|
||||||
|
size_t len;
|
||||||
|
} canon_rdata_iter;
|
||||||
|
|
||||||
|
inline static void canon_rdata_iter_field_init(canon_rdata_iter *i)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
if ((i->rdf->rdd_pos->type & GETDNS_RDF_N) == GETDNS_RDF_N) {
|
||||||
|
i->len = sizeof(i->cdname);
|
||||||
|
if ((i->pos = _getdns_rdf_if_or_as_decompressed(
|
||||||
|
i->rdf, i->cdname, &i->len)))
|
||||||
|
_dname_canonicalize(i->pos);
|
||||||
|
} else {
|
||||||
|
i->pos = i->rdf->pos;
|
||||||
|
i->len = i->rdf->nxt - i->rdf->pos;
|
||||||
|
}
|
||||||
|
if (i->len || !(i->rdf = _getdns_rdf_iter_next(i->rdf)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void canon_rdata_iter_init(canon_rdata_iter*i,_getdns_rr_iter*rr)
|
||||||
|
{
|
||||||
|
if ((i->rdf = _getdns_rdf_iter_init(&i->rdf_spc, rr)))
|
||||||
|
canon_rdata_iter_field_init(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static int canon_rdata_iter_data(canon_rdata_iter *i)
|
||||||
|
{
|
||||||
|
return i->rdf != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static uint8_t canon_rdata_iter_byte(canon_rdata_iter *i)
|
||||||
|
{
|
||||||
|
return *i->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void canon_rdata_iter_next(canon_rdata_iter *i)
|
||||||
|
{
|
||||||
|
if (--i->len == 0 && (i->rdf = _getdns_rdf_iter_next(i->rdf)))
|
||||||
|
canon_rdata_iter_field_init(i);
|
||||||
|
else
|
||||||
|
i->pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static int _dnssec_rdata_to_canonicalize(uint16_t rr_type)
|
||||||
|
{
|
||||||
|
return rr_type == LDNS_RR_TYPE_NS || rr_type == LDNS_RR_TYPE_MD
|
||||||
|
|| rr_type == LDNS_RR_TYPE_MF || rr_type == LDNS_RR_TYPE_CNAME
|
||||||
|
|| rr_type == LDNS_RR_TYPE_SOA || rr_type == LDNS_RR_TYPE_MB
|
||||||
|
|| rr_type == LDNS_RR_TYPE_MG || rr_type == LDNS_RR_TYPE_MR
|
||||||
|
|| rr_type == LDNS_RR_TYPE_PTR || rr_type == LDNS_RR_TYPE_MINFO
|
||||||
|
|| rr_type == LDNS_RR_TYPE_MX || rr_type == LDNS_RR_TYPE_RP
|
||||||
|
|| rr_type == LDNS_RR_TYPE_AFSDB || rr_type == LDNS_RR_TYPE_RT
|
||||||
|
|| rr_type == LDNS_RR_TYPE_SIG || rr_type == LDNS_RR_TYPE_PX
|
||||||
|
|| rr_type == LDNS_RR_TYPE_NXT || rr_type == LDNS_RR_TYPE_NAPTR
|
||||||
|
|| rr_type == LDNS_RR_TYPE_KX || rr_type == LDNS_RR_TYPE_SRV
|
||||||
|
|| rr_type == LDNS_RR_TYPE_DNAME || rr_type == LDNS_RR_TYPE_RRSIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _rr_iter_rdata_cmp(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
_getdns_rr_iter *x = (_getdns_rr_iter *)a;
|
||||||
|
_getdns_rr_iter *y = (_getdns_rr_iter *)b;
|
||||||
|
|
||||||
|
uint16_t rr_type = gldns_read_uint16(x->rr_type);
|
||||||
|
size_t x_rdata_len, y_rdata_len;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
canon_rdata_iter p, q;
|
||||||
|
|
||||||
|
assert(rr_type == gldns_read_uint16(y->rr_type));
|
||||||
|
|
||||||
|
if (!_dnssec_rdata_to_canonicalize(rr_type)) {
|
||||||
|
/* Memory compare of rdata */
|
||||||
|
x_rdata_len = x->nxt - x->rr_type - 10;
|
||||||
|
y_rdata_len = y->nxt - y->rr_type - 10;
|
||||||
|
if ((r = memcmp(x->rr_type + 10, y->rr_type + 10,
|
||||||
|
x_rdata_len < y_rdata_len ? x_rdata_len : y_rdata_len)))
|
||||||
|
return r;
|
||||||
|
return x_rdata_len < y_rdata_len ? -1 :
|
||||||
|
x_rdata_len > y_rdata_len ? 1 : 0;
|
||||||
|
}
|
||||||
|
for ( canon_rdata_iter_init(&p, x), canon_rdata_iter_init(&q, y)
|
||||||
|
; canon_rdata_iter_data(&p) && canon_rdata_iter_data(&q)
|
||||||
|
; canon_rdata_iter_next(&p) , canon_rdata_iter_next(&q) ) {
|
||||||
|
|
||||||
|
if (canon_rdata_iter_byte(&p) != canon_rdata_iter_byte(&q))
|
||||||
|
return canon_rdata_iter_byte(&p) >
|
||||||
|
canon_rdata_iter_byte(&q) ? 1 : -1;
|
||||||
|
}
|
||||||
|
return canon_rdata_iter_data(&p) ? 1
|
||||||
|
: canon_rdata_iter_data(&q) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Verifies the signature rrsig for rrset rrset with key key.
|
/* Verifies the signature rrsig for rrset rrset with key key.
|
||||||
* When the rrset was a wildcard expansion (rrsig labels < labels owner name),
|
* When the rrset was a wildcard expansion (rrsig labels < labels owner name),
|
||||||
|
@ -1458,12 +1571,12 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf,
|
||||||
assert(nc_name);
|
assert(nc_name);
|
||||||
assert(!*nc_name);
|
assert(!*nc_name);
|
||||||
|
|
||||||
if (!(rdf = _getdns_rdf_iter_init_at(&rdf_spc, &rrsig->rr_i, 7)))
|
if (!(rdf = _getdns_rdf_iter_init_at(&rdf_spc, &rrsig->rr_i, 8)))
|
||||||
return 0;
|
return 0;
|
||||||
valbuf_sz = rdf->nxt - rrsig->rr_i.rr_type - 10;
|
valbuf_sz = rdf->pos - rrsig->rr_i.rr_type - 10;
|
||||||
|
|
||||||
owner_len = _dname_len(rrset->name);
|
owner_len = _dname_len(rrset->name);
|
||||||
do {
|
for (;;) {
|
||||||
for ( rr = rrtype_iter_init(&rr_spc, rrset), i = 0
|
for ( rr = rrtype_iter_init(&rr_spc, rrset), i = 0
|
||||||
; rr
|
; rr
|
||||||
; rr = rrtype_iter_next(rr), i++) {
|
; rr = rrtype_iter_next(rr), i++) {
|
||||||
|
@ -1480,15 +1593,18 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf,
|
||||||
} else
|
} else
|
||||||
val_rrset[i] = rr->rr_i;
|
val_rrset[i] = rr->rr_i;
|
||||||
}
|
}
|
||||||
|
/* Did everything fit? Then break */
|
||||||
|
if (val_rrset != val_rrset_spc || i <= VAL_RRSET_SPC_SZ)
|
||||||
|
break;
|
||||||
|
|
||||||
/* More space needed for val_rrset */
|
/* More space needed for val_rrset */
|
||||||
if (val_rrset == val_rrset_spc && i > VAL_RRSET_SPC_SZ) {
|
|
||||||
val_rrset = GETDNS_XMALLOC(*mf, _getdns_rr_iter, i);
|
val_rrset = GETDNS_XMALLOC(*mf, _getdns_rr_iter, i);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
} while (0);
|
|
||||||
DEBUG_SEC( "sizes: %zu rrs, %zu bytes for validation buffer\n"
|
DEBUG_SEC( "sizes: %zu rrs, %zu bytes for validation buffer\n"
|
||||||
, i, valbuf_sz);
|
, i, valbuf_sz);
|
||||||
|
|
||||||
|
qsort(val_rrset, i, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp);
|
||||||
|
|
||||||
r = rrset_l && rrsig_l && key_l &&
|
r = rrset_l && rrsig_l && key_l &&
|
||||||
ldns_verify_rrsig(rrset_l, rrsig_l, key_l) == LDNS_STATUS_OK;
|
ldns_verify_rrsig(rrset_l, rrsig_l, key_l) == LDNS_STATUS_OK;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue