mirror of https://github.com/getdnsapi/getdns.git
parent
102d55d4a5
commit
e1126c9cf8
18
src/dict.c
18
src/dict.c
|
@ -601,6 +601,24 @@ getdns_dict_set_list(
|
|||
|
||||
|
||||
/*---------------------------------------- getdns_dict_set_bindata */
|
||||
getdns_return_t
|
||||
_getdns_dict_set_this_bindata(
|
||||
getdns_dict *dict, const char *name, getdns_bindata *bindata)
|
||||
{
|
||||
getdns_item *item;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!dict || !name || !bindata)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if ((r = _getdns_dict_find_and_add(dict, name, &item)))
|
||||
return r;
|
||||
|
||||
item->dtype = t_bindata;
|
||||
item->data.bindata = bindata;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
_getdns_dict_set_const_bindata(
|
||||
getdns_dict *dict, const char *name, size_t size, const void *data)
|
||||
|
|
121
src/dnssec.c
121
src/dnssec.c
|
@ -268,23 +268,6 @@ static uint8_t *_dname_label_copy(uint8_t *dst, const uint8_t *src, size_t dst_l
|
|||
return r;
|
||||
}
|
||||
|
||||
inline static void _dname_canonicalize(const uint8_t *src, uint8_t *dst)
|
||||
{
|
||||
const uint8_t *next_label;
|
||||
|
||||
while (*src) {
|
||||
next_label = src + *src + 1;
|
||||
*dst++ = *src++;
|
||||
while (src < next_label)
|
||||
*dst++ = (uint8_t)tolower((unsigned char)*src++);
|
||||
}
|
||||
}
|
||||
|
||||
inline static void _dname_canonicalize2(uint8_t *dname)
|
||||
{
|
||||
_dname_canonicalize(dname, dname);
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
|
@ -1528,21 +1511,6 @@ inline static void canon_rdata_iter_next(canon_rdata_iter *i)
|
|||
i->pos++;
|
||||
}
|
||||
|
||||
inline static int _dnssec_rdata_to_canonicalize(uint16_t rr_type)
|
||||
{
|
||||
return rr_type == GLDNS_RR_TYPE_NS || rr_type == GLDNS_RR_TYPE_MD
|
||||
|| rr_type == GLDNS_RR_TYPE_MF || rr_type == GLDNS_RR_TYPE_CNAME
|
||||
|| rr_type == GLDNS_RR_TYPE_SOA || rr_type == GLDNS_RR_TYPE_MB
|
||||
|| rr_type == GLDNS_RR_TYPE_MG || rr_type == GLDNS_RR_TYPE_MR
|
||||
|| rr_type == GLDNS_RR_TYPE_PTR || rr_type == GLDNS_RR_TYPE_MINFO
|
||||
|| rr_type == GLDNS_RR_TYPE_MX || rr_type == GLDNS_RR_TYPE_RP
|
||||
|| rr_type == GLDNS_RR_TYPE_AFSDB || rr_type == GLDNS_RR_TYPE_RT
|
||||
|| rr_type == GLDNS_RR_TYPE_SIG || rr_type == GLDNS_RR_TYPE_PX
|
||||
|| rr_type == GLDNS_RR_TYPE_NXT || rr_type == GLDNS_RR_TYPE_NAPTR
|
||||
|| rr_type == GLDNS_RR_TYPE_KX || rr_type == GLDNS_RR_TYPE_SRV
|
||||
|| rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG;
|
||||
}
|
||||
|
||||
static int _rr_iter_rdata_cmp(const void *a, const void *b)
|
||||
{
|
||||
_getdns_rr_iter *x = (_getdns_rr_iter *)a;
|
||||
|
@ -1656,6 +1624,7 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf,
|
|||
|
||||
if (!_dnssec_rdata_to_canonicalize(rrset->rr_type))
|
||||
for (i = 0; i < n_rrs; i++) {
|
||||
/* Get rid of doubles */
|
||||
if (i && !_rr_iter_rdata_cmp(
|
||||
&val_rrset[i], &val_rrset[i-1]))
|
||||
continue;
|
||||
|
@ -3047,6 +3016,62 @@ static int rrset_in_list(getdns_rrset *rrset, getdns_list *list)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void append_canonical_rrset2val_chain_list(
|
||||
getdns_list *val_chain_list, getdns_rrset *rrset, rrsig_iter *rrsig)
|
||||
{
|
||||
_getdns_rr_iter val_rrset_spc[VAL_RRSET_SPC_SZ];
|
||||
_getdns_rr_iter *val_rrset = val_rrset_spc;
|
||||
rrtype_iter rr_spc, *rr;
|
||||
size_t n_rrs, i;
|
||||
uint32_t orig_ttl;
|
||||
getdns_dict *rr_dict;
|
||||
|
||||
assert(val_chain_list && rrset && rrsig);
|
||||
|
||||
/* keytag was already read, so orig_ttl should cause no problem */
|
||||
assert(rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 18);
|
||||
|
||||
orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
|
||||
|
||||
for (;;) {
|
||||
for ( rr = rrtype_iter_init(&rr_spc, rrset), n_rrs = 0
|
||||
; rr
|
||||
; rr = rrtype_iter_next(rr), n_rrs++) {
|
||||
|
||||
if (n_rrs < VAL_RRSET_SPC_SZ ||
|
||||
val_rrset != val_rrset_spc)
|
||||
val_rrset[n_rrs] = rr->rr_i;
|
||||
}
|
||||
/* Did everything fit? Then break */
|
||||
if (val_rrset != val_rrset_spc || n_rrs <= VAL_RRSET_SPC_SZ)
|
||||
break;
|
||||
|
||||
/* More space needed for val_rrset */
|
||||
val_rrset = GETDNS_XMALLOC(
|
||||
val_chain_list->mf, _getdns_rr_iter, n_rrs);
|
||||
}
|
||||
qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp);
|
||||
for (i = 0; i < n_rrs; i++) {
|
||||
/* Get rid of doubles */
|
||||
if (i && !_rr_iter_rdata_cmp(&val_rrset[i], &val_rrset[i-1]))
|
||||
continue;
|
||||
|
||||
if (!(rr_dict = _getdns_rr_iter2rr_dict_canonical(
|
||||
&val_chain_list->mf, &val_rrset[i], &orig_ttl)))
|
||||
continue;
|
||||
|
||||
if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
|
||||
getdns_dict_destroy(rr_dict);
|
||||
}
|
||||
if ((rr_dict = _getdns_rr_iter2rr_dict_canonical(
|
||||
&val_chain_list->mf, &rrsig->rr_i, &orig_ttl)) &&
|
||||
_getdns_list_append_this_dict(val_chain_list, rr_dict))
|
||||
getdns_dict_destroy(rr_dict);
|
||||
|
||||
if (val_rrset != val_rrset_spc)
|
||||
GETDNS_FREE(val_chain_list->mf, val_rrset);
|
||||
}
|
||||
|
||||
static void append_rrs2val_chain_list(getdns_context *ctxt,
|
||||
getdns_list *val_chain_list, getdns_network_req *netreq, int signer)
|
||||
{
|
||||
|
@ -3072,6 +3097,27 @@ static void append_rrs2val_chain_list(getdns_context *ctxt,
|
|||
rrset->rr_type != GETDNS_RRTYPE_DS)
|
||||
continue;
|
||||
|
||||
if ((signer & 0xFFFF)) {
|
||||
/* We have a signer! Return RRset in canonical
|
||||
* form and order with only the RRSIG that signed
|
||||
* the RRset.
|
||||
*/
|
||||
for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset)
|
||||
; rrsig &&
|
||||
( rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28
|
||||
|| gldns_read_uint16(rrsig->rr_i.rr_type + 26)
|
||||
!= (signer & 0xFFFF))
|
||||
; rrsig = rrsig_iter_next(rrsig))
|
||||
; /* pass */
|
||||
|
||||
if (!rrsig) {
|
||||
/* Signer not found, try next RR set */
|
||||
continue;
|
||||
}
|
||||
append_canonical_rrset2val_chain_list(
|
||||
val_chain_list, rrset, rrsig);
|
||||
continue;
|
||||
}
|
||||
for ( rr = rrtype_iter_init(&rr_spc, rrset)
|
||||
; rr; rr = rrtype_iter_next(rr)) {
|
||||
|
||||
|
@ -3085,16 +3131,7 @@ static void append_rrs2val_chain_list(getdns_context *ctxt,
|
|||
for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset)
|
||||
; rrsig; rrsig = rrsig_iter_next(rrsig)) {
|
||||
|
||||
if (/* No space for keytag & signer in rrsig rdata? */
|
||||
rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28
|
||||
|
||||
/* We have a signer and it doesn't match? */
|
||||
|| ((signer & 0xFFFF) &&
|
||||
gldns_read_uint16(rrsig->rr_i.rr_type + 26)
|
||||
!= (signer & 0xFFFF))
|
||||
|
||||
/* Could not convert to rr_dict */
|
||||
|| !(rr_dict = _getdns_rr_iter2rr_dict(
|
||||
if (!(rr_dict = _getdns_rr_iter2rr_dict(
|
||||
&ctxt->mf, &rrsig->rr_i)))
|
||||
continue;
|
||||
|
||||
|
|
16
src/dnssec.h
16
src/dnssec.h
|
@ -41,6 +41,7 @@
|
|||
#include "getdns/getdns.h"
|
||||
#include "config.h"
|
||||
#include "gldns/gbuffer.h"
|
||||
#include "gldns/rrdef.h"
|
||||
#include "types-internal.h"
|
||||
|
||||
/* Do some additional requests to fetch the complete validation chain */
|
||||
|
@ -48,6 +49,21 @@ void _getdns_get_validation_chain(getdns_dns_req *dns_req);
|
|||
|
||||
uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf);
|
||||
|
||||
inline static int _dnssec_rdata_to_canonicalize(uint16_t rr_type)
|
||||
{
|
||||
return rr_type == GLDNS_RR_TYPE_NS || rr_type == GLDNS_RR_TYPE_MD
|
||||
|| rr_type == GLDNS_RR_TYPE_MF || rr_type == GLDNS_RR_TYPE_CNAME
|
||||
|| rr_type == GLDNS_RR_TYPE_SOA || rr_type == GLDNS_RR_TYPE_MB
|
||||
|| rr_type == GLDNS_RR_TYPE_MG || rr_type == GLDNS_RR_TYPE_MR
|
||||
|| rr_type == GLDNS_RR_TYPE_PTR || rr_type == GLDNS_RR_TYPE_MINFO
|
||||
|| rr_type == GLDNS_RR_TYPE_MX || rr_type == GLDNS_RR_TYPE_RP
|
||||
|| rr_type == GLDNS_RR_TYPE_AFSDB || rr_type == GLDNS_RR_TYPE_RT
|
||||
|| rr_type == GLDNS_RR_TYPE_SIG || rr_type == GLDNS_RR_TYPE_PX
|
||||
|| rr_type == GLDNS_RR_TYPE_NXT || rr_type == GLDNS_RR_TYPE_NAPTR
|
||||
|| rr_type == GLDNS_RR_TYPE_KX || rr_type == GLDNS_RR_TYPE_SRV
|
||||
|| rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* dnssec.h */
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "gldns/str2wire.h"
|
||||
#include "gldns/gbuffer.h"
|
||||
#include "gldns/pkthdr.h"
|
||||
#include "dnssec.h"
|
||||
|
||||
|
||||
getdns_return_t
|
||||
|
@ -145,11 +146,12 @@ _getdns_sockaddr_to_dict(struct getdns_context *context, struct sockaddr_storage
|
|||
}
|
||||
|
||||
getdns_dict *
|
||||
_getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
||||
_getdns_rr_iter2rr_dict_canonical(
|
||||
struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl)
|
||||
{
|
||||
getdns_dict *rr_dict, *rdata_dict;
|
||||
const uint8_t *bin_data;
|
||||
size_t bin_size;
|
||||
size_t bin_size, owner_len = 0, rdata_sz;
|
||||
uint32_t int_val = 0;
|
||||
enum wf_data_type { wf_int, wf_bindata, wf_special } val_type;
|
||||
_getdns_rdf_iter rdf_storage, *rdf;
|
||||
|
@ -157,6 +159,7 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
getdns_dict *repeat_dict = NULL;
|
||||
uint8_t ff_bytes[256];
|
||||
uint16_t rr_type;
|
||||
int canonicalize;
|
||||
|
||||
assert(i);
|
||||
if (!(rr_dict = _getdns_dict_create_with_mf(mf)))
|
||||
|
@ -165,6 +168,12 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
bin_data = _getdns_owner_if_or_as_decompressed(
|
||||
i, ff_bytes, &bin_size);
|
||||
|
||||
if (orig_ttl) {
|
||||
if (bin_data != ff_bytes)
|
||||
bin_data = memcpy(ff_bytes, bin_data, bin_size);
|
||||
_dname_canonicalize2(ff_bytes);
|
||||
owner_len = bin_size;
|
||||
}
|
||||
/* question */
|
||||
if (_getdns_rr_iter_section(i) == GLDNS_SECTION_QUESTION) {
|
||||
|
||||
|
@ -186,6 +195,9 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
|
||||
goto error;
|
||||
}
|
||||
canonicalize = orig_ttl && _dnssec_rdata_to_canonicalize(rr_type)
|
||||
&& (i->rr_type + 12 <= i->nxt) /* To estimate rdata size */;
|
||||
|
||||
if (rr_type == GETDNS_RRTYPE_OPT) {
|
||||
int_val = gldns_read_uint16(i->rr_type + 6);
|
||||
|
||||
|
@ -210,7 +222,8 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
(uint32_t) gldns_read_uint16(i->rr_type + 2)) ||
|
||||
|
||||
getdns_dict_set_int(rr_dict, "ttl",
|
||||
(uint32_t) gldns_read_uint32(i->rr_type + 4)) ||
|
||||
( orig_ttl && rr_type != GETDNS_RRTYPE_RRSIG
|
||||
? *orig_ttl : (uint32_t) gldns_read_uint32(i->rr_type + 4))) ||
|
||||
|
||||
_getdns_dict_set_const_bindata(
|
||||
rr_dict, "name", bin_size, bin_data)) {
|
||||
|
@ -220,15 +233,21 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
if (!(rdata_dict = _getdns_dict_create_with_mf(mf)))
|
||||
return NULL;
|
||||
|
||||
if (i->rr_type + 10 <= i->nxt) {
|
||||
if (i->rr_type + 10 <= i->nxt && !canonicalize) {
|
||||
bin_size = i->nxt - (i->rr_type + 10);
|
||||
bin_data = i->rr_type + 10;
|
||||
if (_getdns_dict_set_const_bindata(
|
||||
rdata_dict, "rdata_raw", bin_size, bin_data))
|
||||
goto rdata_error;
|
||||
}
|
||||
if (canonicalize)
|
||||
rdata_sz = 0;
|
||||
|
||||
for ( rdf = _getdns_rdf_iter_init(&rdf_storage, i)
|
||||
; rdf; rdf = _getdns_rdf_iter_next(rdf)) {
|
||||
if (canonicalize && !(rdf->rdd_pos->type & GETDNS_RDF_DNAME)) {
|
||||
rdata_sz += rdf->nxt - rdf->pos;
|
||||
}
|
||||
if (rdf->rdd_pos->type & GETDNS_RDF_INTEGER) {
|
||||
val_type = wf_int;
|
||||
switch (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
|
||||
|
@ -247,6 +266,12 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
bin_data = _getdns_rdf_if_or_as_decompressed(
|
||||
rdf, ff_bytes, &bin_size);
|
||||
|
||||
if (canonicalize) {
|
||||
if (bin_data != ff_bytes)
|
||||
bin_data = memcpy(ff_bytes, bin_data, bin_size);
|
||||
_dname_canonicalize2(ff_bytes);
|
||||
rdata_sz += bin_size;
|
||||
}
|
||||
} else if (rdf->rdd_pos->type & GETDNS_RDF_BINDATA) {
|
||||
val_type = wf_bindata;
|
||||
if (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
|
||||
|
@ -376,6 +401,29 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
|||
if (_getdns_dict_set_this_dict(rr_dict, "rdata", rdata_dict))
|
||||
goto rdata_error;
|
||||
|
||||
if (canonicalize && rdata_sz) {
|
||||
fprintf(stderr, "XXXXXXXXXX: owner_len: %zu, rdata_len: %zu\n", owner_len, rdata_sz);
|
||||
|
||||
gldns_buffer gbuf;
|
||||
getdns_bindata *bindata;
|
||||
uint8_t *data = GETDNS_XMALLOC(
|
||||
*mf, uint8_t, owner_len + 10 + rdata_sz);
|
||||
|
||||
if (!data)
|
||||
return rr_dict;
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, data, owner_len+10+rdata_sz);
|
||||
if (_getdns_rr_dict2wire(rr_dict, &gbuf) ||
|
||||
gldns_buffer_position(&gbuf) != owner_len + 10 + rdata_sz ||
|
||||
!(bindata = GETDNS_MALLOC(*mf, struct getdns_bindata))) {
|
||||
GETDNS_FREE(*mf, data);
|
||||
return rr_dict;
|
||||
}
|
||||
bindata->size = rdata_sz;
|
||||
bindata->data = memmove(data, data + owner_len + 10, rdata_sz);
|
||||
(void) _getdns_dict_set_this_bindata(rr_dict,
|
||||
"/rdata/rdata_raw", bindata);
|
||||
}
|
||||
return rr_dict;
|
||||
|
||||
rdata_error:
|
||||
|
@ -387,6 +435,12 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
getdns_dict *
|
||||
_getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
|
||||
{
|
||||
return _getdns_rr_iter2rr_dict_canonical(mf, i, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
_getdns_dname_equal(const uint8_t *s1, const uint8_t *s2)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "config.h"
|
||||
#include "context.h"
|
||||
#include "rr-iter.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define UNCONST_UINT8_p uint8_t *
|
||||
|
||||
|
@ -95,6 +96,9 @@ getdns_return_t _getdns_dict_set_this_list(getdns_dict *dict,
|
|||
getdns_return_t _getdns_dict_set_const_bindata(getdns_dict *dict,
|
||||
const char *name, size_t size, const void *data);
|
||||
|
||||
getdns_return_t _getdns_dict_set_this_bindata(getdns_dict *dict,
|
||||
const char *name, getdns_bindata *child_bindata);
|
||||
|
||||
/**
|
||||
* private function (API users should not be calling this), this uses library
|
||||
* routines to make a copy of the list - would be faster to make the copy directly
|
||||
|
@ -138,6 +142,10 @@ getdns_return_t _getdns_sockaddr_to_dict(struct getdns_context *context,
|
|||
getdns_dict *
|
||||
_getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i);
|
||||
|
||||
getdns_dict *
|
||||
_getdns_rr_iter2rr_dict_canonical(
|
||||
struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl);
|
||||
|
||||
struct getdns_dns_req;
|
||||
struct getdns_dict *_getdns_create_getdns_response(struct getdns_dns_req *completed_request);
|
||||
|
||||
|
@ -178,5 +186,22 @@ INLINE getdns_eventloop_event *getdns_eventloop_event_init(
|
|||
#define GETDNS_SCHEDULE_EVENT(loop, fd, timeout, event) \
|
||||
do { (loop)->vmt->schedule((loop),(fd),(timeout),(event)); } while(0)
|
||||
|
||||
INLINE void _dname_canonicalize(const uint8_t *src, uint8_t *dst)
|
||||
{
|
||||
const uint8_t *next_label;
|
||||
|
||||
while (*src) {
|
||||
next_label = src + *src + 1;
|
||||
*dst++ = *src++;
|
||||
while (src < next_label)
|
||||
*dst++ = (uint8_t)tolower((unsigned char)*src++);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void _dname_canonicalize2(uint8_t *dname)
|
||||
{
|
||||
_dname_canonicalize(dname, dname);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* util-internal.h */
|
||||
|
|
Loading…
Reference in New Issue