From ae1db39a33bd53cd2455e97b11d8c54d045dac0f Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 11 Jun 2015 15:40:44 +0200 Subject: [PATCH] Native stub validation --- aclocal.m4 | 4 +- configure | 17 +++-- configure.ac | 8 +-- src/config.h.in | 3 +- src/dnssec.c | 44 ++++--------- src/rr-dict.c | 162 +++++++++++++++++++----------------------------- src/rr-dict.h | 65 +++++++++---------- 7 files changed, 123 insertions(+), 180 deletions(-) diff --git a/aclocal.m4 b/aclocal.m4 index 95cd61e9..0cd56f0f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.14.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/configure b/configure index 7c6cca29..d197b17b 100755 --- a/configure +++ b/configure @@ -760,7 +760,7 @@ with_sysroot enable_libtool_lock enable_rpath enable_tcp_fastopen -enable_broken_native_stub_dnssec +enable_native_stub_dnssec with_ssl enable_draft_edns_cookies with_libidn @@ -1406,9 +1406,8 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --disable-rpath disable hardcoded rpath (default=enabled) --enable-tcp-fastopen Enable TCP Fast Open - --enable-broken-native-stub-dnssec - Enable very experimental and broken native stub - DNSSEC support + --disable-native-stub-dnssec + Disable native stub DNSSEC support --enable-draft-edns-cookies Enable experimental edns cookies @@ -11738,20 +11737,20 @@ _ACEOF ;; esac -# Check whether --enable-broken-native-stub-dnssec was given. -if test "${enable_broken_native_stub_dnssec+set}" = set; then : - enableval=$enable_broken_native_stub_dnssec; +# Check whether --enable-native-stub-dnssec was given. +if test "${enable_native_stub_dnssec+set}" = set; then : + enableval=$enable_native_stub_dnssec; fi case "$enable_broken_native_stub_dnssec" in - yes) + yes|*) cat >>confdefs.h <<_ACEOF #define STUB_NATIVE_DNSSEC 1 _ACEOF ;; - no|*) + no) ;; esac diff --git a/configure.ac b/configure.ac index 2c096722..f4811cc9 100644 --- a/configure.ac +++ b/configure.ac @@ -132,12 +132,12 @@ case "$enable_tcp_fastopen" in ;; esac -AC_ARG_ENABLE(broken-native-stub-dnssec, AC_HELP_STRING([--enable-broken-native-stub-dnssec], [Enable very experimental and broken native stub DNSSEC support])) +AC_ARG_ENABLE(native-stub-dnssec, AC_HELP_STRING([--disable-native-stub-dnssec], [Disable native stub DNSSEC support])) case "$enable_broken_native_stub_dnssec" in - yes) - AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1], [Define this to enable the very experimental and broken native stub DNSSEC support.]) + yes|*) + AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1], [Define this to enable native stub DNSSEC support.]) ;; - no|*) + no) ;; esac diff --git a/src/config.h.in b/src/config.h.in index e2405b25..ff26526c 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -192,8 +192,7 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS -/* Define this to enable the very experimental and broken native stub DNSSEC - support. */ +/* Define this to enable native stub DNSSEC support. */ #undef STUB_NATIVE_DNSSEC /* System configuration dir */ diff --git a/src/dnssec.c b/src/dnssec.c index c623d6df..486cf27a 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -475,36 +475,6 @@ priv_getdns_rr_list_from_list(struct getdns_list *list, ldns_rr_list **rr_list) return r; } -static int -priv_getdns_rr_dict_with_compressed_names(getdns_dict *rr_dict) -{ - uint32_t rr_type; - getdns_dict *rdata; - - if (getdns_dict_get_int(rr_dict, "type", &rr_type)) - return 0; - if (rr_type == GETDNS_RRTYPE_RRSIG) { - if (getdns_dict_get_dict(rr_dict, "rdata", &rdata)) - return 0; - if (getdns_dict_get_int(rdata, "type_covered", &rr_type)) - return 0; - } - switch (rr_type) { - case GETDNS_RRTYPE_NS: - case GETDNS_RRTYPE_MD: - case GETDNS_RRTYPE_CNAME: - case GETDNS_RRTYPE_SOA: - case GETDNS_RRTYPE_MG: - case GETDNS_RRTYPE_MR: - case GETDNS_RRTYPE_PTR: - case GETDNS_RRTYPE_MINFO: - case GETDNS_RRTYPE_MX: - return 1; - default: - return 0; - } -} - static int ldns_dname_compare_v(const void *a, const void *b) { return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); @@ -573,9 +543,6 @@ priv_getdns_dnssec_zone_from_list(struct getdns_list *list, if ((r = getdns_list_get_dict(list, i, &rr_dict))) break; - if (priv_getdns_rr_dict_with_compressed_names(rr_dict)) - continue; - if ((r = priv_getdns_create_rr_from_dict(rr_dict, &rr))) break; @@ -693,6 +660,17 @@ verify_rrset(ldns_dnssec_rrsets *rrset_and_sigs, ldns_rr_list *rrset = rrs2rr_list(rrset_and_sigs->rrs); ldns_rr_list *sigs = rrs2rr_list(rrset_and_sigs->signatures); s = ldns_verify(rrset, sigs, keys, good_keys); +#if 0 + if (s != 0) { + fprintf(stderr, "verify status %d\nrrset: ", s); + ldns_rr_list_print(stderr, rrset); + fprintf(stderr, "\nsigs: "); + ldns_rr_list_print(stderr, sigs); + fprintf(stderr, "\nkeys: "); + ldns_rr_list_print(stderr, keys); + fprintf(stderr, "\n\n"); + } +#endif ldns_rr_list_free(sigs); ldns_rr_list_free(rrset); return s; diff --git a/src/rr-dict.c b/src/rr-dict.c index d6dcea8c..85d779d8 100644 --- a/src/rr-dict.c +++ b/src/rr-dict.c @@ -255,9 +255,9 @@ static priv_getdns_rdata_def soa_rdata[] = { { "rname" , GETDNS_RDF_N_C }, { "serial" , GETDNS_RDF_I4 }, { "refresh" , GETDNS_RDF_I4 }, - { "refresh" , GETDNS_RDF_I4 }, { "retry" , GETDNS_RDF_I4 }, - { "expire" , GETDNS_RDF_I4 }}; + { "expire" , GETDNS_RDF_I4 }, + { "minimum" , GETDNS_RDF_I4 }}; static priv_getdns_rdata_def mg_rdata[] = { { "mgmname" , GETDNS_RDF_N_C }}; static priv_getdns_rdata_def mr_rdata[] = { @@ -742,9 +742,8 @@ static getdns_return_t priv_getdns_construct_wire_rdata_from_rdata( uint8_t **wire, size_t *wire_size) { getdns_return_t r = GETDNS_RETURN_GOOD; - const ldns_rr_descriptor *rr_descript; const priv_getdns_rr_def *def; - size_t i, size; + size_t i, j, size; struct getdns_bindata *bindata; uint32_t value; uint8_t *ptr; @@ -754,7 +753,6 @@ static getdns_return_t priv_getdns_construct_wire_rdata_from_rdata( assert(wire_size); def = priv_getdns_rr_def_lookup(rr_type); - rr_descript = ldns_rr_descript(rr_type); /* First calculate needed size */ size = 0; @@ -771,23 +769,7 @@ static getdns_return_t priv_getdns_construct_wire_rdata_from_rdata( r = GETDNS_RETURN_GENERIC_ERROR; break; } - switch (ldns_rr_descriptor_field_type(rr_descript, i)) { - - case LDNS_RDF_TYPE_CLASS: - case LDNS_RDF_TYPE_ALG : - case LDNS_RDF_TYPE_INT8 : size += 1; - break; - case LDNS_RDF_TYPE_TYPE : - case LDNS_RDF_TYPE_CERT_ALG: - case LDNS_RDF_TYPE_INT16: size += 2; - break; - case LDNS_RDF_TYPE_TIME : - case LDNS_RDF_TYPE_PERIOD: - case LDNS_RDF_TYPE_INT32: size += 4; - break; - default: r = GETDNS_RETURN_GENERIC_ERROR; - break; - } + size += def->rdata[i].type & GETDNS_RDF_FIXEDSZ; } *wire_size = size + 2; *wire = ptr = GETDNS_XMALLOC(rdata->mf, uint8_t, size + 2); @@ -815,64 +797,21 @@ static getdns_return_t priv_getdns_construct_wire_rdata_from_rdata( if ((r = getdns_dict_get_int( rdata, def->rdata[i].name, &value))) break; - - switch (ldns_rr_descriptor_field_type(rr_descript, i)) { - - case LDNS_RDF_TYPE_CLASS: - case LDNS_RDF_TYPE_ALG : - case LDNS_RDF_TYPE_INT8 : ptr[0] = (uint8_t) value & 0xff; - ptr += 1; - break; - case LDNS_RDF_TYPE_TYPE : - case LDNS_RDF_TYPE_CERT_ALG: - case LDNS_RDF_TYPE_INT16: ptr[0] = (uint8_t)(value>> 8) & 0xff; - ptr[1] = (uint8_t) value & 0xff; - ptr += 2; - break; - case LDNS_RDF_TYPE_TIME : - case LDNS_RDF_TYPE_PERIOD: - case LDNS_RDF_TYPE_INT32: ptr[0] = (uint8_t)(value>>24) & 0xff; - ptr[1] = (uint8_t)(value>>16) & 0xff; - ptr[2] = (uint8_t)(value>>8 ) & 0xff; - ptr[3] = (uint8_t) value & 0xff; - ptr += 4; - break; - default: r = GETDNS_RETURN_GENERIC_ERROR; - break; - } + + for (j = def->rdata[i].type & GETDNS_RDF_FIXEDSZ; j; j--) + *ptr++ = (uint8_t)(value >> (8 * (j - 1))) & 0xff; } if (r) GETDNS_FREE(rdata->mf, ptr); return r; } -static getdns_return_t -priv_getdns_dict_get_raw_rdata(struct getdns_dict *rdata, - uint8_t **wire, size_t *wire_size) -{ - getdns_return_t r; - struct getdns_bindata *bindata; - - if ((r = getdns_dict_get_bindata(rdata, "rdata_raw", &bindata))) - return r; - - *wire_size = bindata->size + 2; - *wire = GETDNS_XMALLOC(rdata->mf, uint8_t, *wire_size); - if (! *wire) - return GETDNS_RETURN_MEMORY_ERROR; - - (*wire)[0] = (uint8_t) (bindata->size >> 8) & 0xff; - (*wire)[1] = (uint8_t) bindata->size & 0xff; - - (void) memcpy(*wire + 2, bindata->data, bindata->size); - return GETDNS_RETURN_GOOD; -} - getdns_return_t priv_getdns_create_rr_from_dict(struct getdns_dict *rr_dict, ldns_rr **rr) { getdns_return_t r = GETDNS_RETURN_GOOD; struct getdns_bindata *name; + struct getdns_bindata *rdata_raw; struct getdns_dict *rdata; uint32_t rr_type; ldns_rdf *owner; @@ -887,41 +826,68 @@ priv_getdns_create_rr_from_dict(struct getdns_dict *rr_dict, ldns_rr **rr) *rr = ldns_rr_new(); if (! *rr) return GETDNS_RETURN_MEMORY_ERROR; - do { - r = getdns_dict_get_bindata(rr_dict, "name", &name); - if (r != GETDNS_RETURN_GOOD) + + if ((r = getdns_dict_get_bindata(rr_dict, "name", &name))) + goto error; + + owner = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_DNAME, name->size, name->data); + if (! owner) { + r = GETDNS_RETURN_MEMORY_ERROR; + goto error; + } + ldns_rr_set_owner(*rr, owner); + + if ((r = getdns_dict_get_int(rr_dict, "type", &rr_type))) + goto error; + ldns_rr_set_type(*rr, rr_type); + + if ((r = getdns_dict_get_dict(rr_dict, "rdata", &rdata))) + goto error; + + const priv_getdns_rr_def *rr_def = priv_getdns_rr_def_lookup(rr_type); + const priv_getdns_rdata_def *rd_def; + int n_rdata_fields; + + for ( rd_def = rr_def->rdata + , n_rdata_fields = rr_def->n_rdata_fields + ; n_rdata_fields + ; n_rdata_fields-- + , rd_def++ ) { + + if (rd_def->type & GETDNS_RDF_COMPRESSED) break; - owner = ldns_rdf_new_frm_data( - LDNS_RDF_TYPE_DNAME, name->size, name->data); - if (! owner) { + } + + if (n_rdata_fields == 0 && GETDNS_RETURN_GOOD == + (r = getdns_dict_get_bindata(rdata, "rdata_raw", &rdata_raw))) { + + wire_size = rdata_raw->size + 2; + wire = GETDNS_XMALLOC(rdata->mf, uint8_t, wire_size); + if (! wire) { r = GETDNS_RETURN_MEMORY_ERROR; - break; + goto error; } - ldns_rr_set_owner(*rr, owner); - r = getdns_dict_get_int(rr_dict, "type", &rr_type); - if (r != GETDNS_RETURN_GOOD) - break; - ldns_rr_set_type(*rr, rr_type); + wire[0] = (uint8_t) (rdata_raw->size >> 8) & 0xff; + wire[1] = (uint8_t) rdata_raw->size & 0xff; - r = getdns_dict_get_dict(rr_dict, "rdata", &rdata); - if (r != GETDNS_RETURN_GOOD) - break; + (void) memcpy(wire + 2, rdata_raw->data, rdata_raw->size); - r = priv_getdns_dict_get_raw_rdata(rdata, &wire, &wire_size); - if (r == GETDNS_RETURN_NO_SUCH_DICT_NAME) { - r = priv_getdns_construct_wire_rdata_from_rdata( - rdata, rr_type, &wire, &wire_size); - } - if (r != GETDNS_RETURN_GOOD) - break; - pos = 0; - s = ldns_wire2rdf(*rr, wire, wire_size, &pos); - GETDNS_FREE(rr_dict->mf, wire); - if (s == LDNS_STATUS_OK) - return r; - r = GETDNS_RETURN_GENERIC_ERROR; - } while (0); + } else if (n_rdata_fields || r == GETDNS_RETURN_NO_SUCH_DICT_NAME) { + + r = priv_getdns_construct_wire_rdata_from_rdata(rdata, rr_type, + &wire, &wire_size); + } + + pos = 0; + s = ldns_wire2rdf(*rr, wire, wire_size, &pos); + GETDNS_FREE(rr_dict->mf, wire); + if (s == LDNS_STATUS_OK) + return r; + + r = GETDNS_RETURN_GENERIC_ERROR; +error: ldns_rr_free(*rr); return r; } diff --git a/src/rr-dict.h b/src/rr-dict.h index 244f556b..cff4215a 100644 --- a/src/rr-dict.h +++ b/src/rr-dict.h @@ -51,56 +51,57 @@ typedef struct priv_getdns_rdf_special { /* draft-levine-dnsextlang'ish type rr and rdata definitions */ -#define GETDNS_RDF_INTEGER 0x010000 -#define GETDNS_RDF_BINDATA 0x020000 -#define GETDNS_RDF_DNAME 0x060000 -#define GETDNS_RDF_REPEAT 0x100000 +#define GETDNS_RDF_INTEGER 0x010000 +#define GETDNS_RDF_BINDATA 0x020000 +#define GETDNS_RDF_DNAME 0x060000 +#define GETDNS_RDF_COMPRESSED 0x080000 +#define GETDNS_RDF_REPEAT 0x100000 -#define GETDNS_RDF_FIXEDSZ 0x0000FF -#define GETDNS_RDF_LEN_VAL 0x00FF00 +#define GETDNS_RDF_FIXEDSZ 0x0000FF +#define GETDNS_RDF_LEN_VAL 0x00FF00 typedef enum priv_getdns_rdf_wf_type { - GETDNS_RDF_N = 0x060000, /* N */ - GETDNS_RDF_N_A = GETDNS_RDF_N, /* N[A] */ - GETDNS_RDF_N_A_C = GETDNS_RDF_N, /* N[A,C] */ - GETDNS_RDF_N_C = GETDNS_RDF_N, /* N[C] */ - GETDNS_RDF_N_M = 0x160000, /* N[M] */ + GETDNS_RDF_N = 0x060000, /* N */ + GETDNS_RDF_N_A = 0x060000, /* N[A] */ + GETDNS_RDF_N_C = 0x0E0000, /* N[C] */ + GETDNS_RDF_N_A_C = 0x0E0000, /* N[A,C] */ + GETDNS_RDF_N_M = 0x160000, /* N[M] */ - GETDNS_RDF_I1 = 0x010001, /* I1 */ - GETDNS_RDF_I2 = 0x010002, /* I2 */ - GETDNS_RDF_I4 = 0x010004, /* I4 */ + GETDNS_RDF_I1 = 0x010001, /* I1 */ + GETDNS_RDF_I2 = 0x010002, /* I2 */ + GETDNS_RDF_I4 = 0x010004, /* I4 */ - GETDNS_RDF_T = 0x010004, /* T */ + GETDNS_RDF_T = 0x010004, /* T */ /* Time values using ring arithmetics * (rfc1982) for TKEY['inception'], * TKEY['expiration'], * RRSIG['inception'] and * RRSIG['expiration'] */ - GETDNS_RDF_T6 = 0x020006, /* T6 */ + GETDNS_RDF_T6 = 0x020006, /* T6 */ /* Absolute time values (since epoch) * for TSIG['time_signed'] */ - GETDNS_RDF_A = 0x020004, /* A */ - GETDNS_RDF_AA = 0x020008, /* AA */ - GETDNS_RDF_AAAA = 0x020010, /* AAAA */ + GETDNS_RDF_A = 0x020004, /* A */ + GETDNS_RDF_AA = 0x020008, /* AA */ + GETDNS_RDF_AAAA = 0x020010, /* AAAA */ - GETDNS_RDF_S = 0x020100, /* S */ - GETDNS_RDF_S_L = 0x020000, /* S[L] */ - GETDNS_RDF_S_M = 0x120100, /* S[M] */ + GETDNS_RDF_S = 0x020100, /* S */ + GETDNS_RDF_S_L = 0x020000, /* S[L] */ + GETDNS_RDF_S_M = 0x120100, /* S[M] */ - GETDNS_RDF_B = 0x020000, /* B */ - GETDNS_RDF_B_C = 0x020100, /* B[C] */ + GETDNS_RDF_B = 0x020000, /* B */ + GETDNS_RDF_B_C = 0x020100, /* B[C] */ - GETDNS_RDF_B32_C = 0x020100, /* B32[C] */ + GETDNS_RDF_B32_C = 0x020100, /* B32[C] */ - GETDNS_RDF_X = 0x020000, /* X */ - GETDNS_RDF_X_C = 0x020100, /* X[C] */ + GETDNS_RDF_X = 0x020000, /* X */ + GETDNS_RDF_X_C = 0x020100, /* X[C] */ /* for NSEC3['salt'] and * NSEC3PARAM['salt']. */ - GETDNS_RDF_X_S = 0x020200, /* X[S] */ + GETDNS_RDF_X_S = 0x020200, /* X[S] */ /* for OPT['option_data'], * TKEY['key_data'], * TKEY['other_data'], @@ -109,12 +110,12 @@ typedef enum priv_getdns_rdf_wf_type { * Although those do not have an * official presentation format. */ - GETDNS_RDF_X6 = 0x020006, - GETDNS_RDF_X8 = 0x020008, + GETDNS_RDF_X6 = 0x020006, + GETDNS_RDF_X8 = 0x020008, - GETDNS_RDF_R = 0x100000, /* Repeat */ + GETDNS_RDF_R = 0x100000, /* Repeat */ - GETDNS_RDF_SPECIAL = 0x800000, + GETDNS_RDF_SPECIAL = 0x800000, } priv_getdns_rdf_type; typedef struct priv_getdns_rdata_def {