diff --git a/src/knot/dnssec/zone-keys.c b/src/knot/dnssec/zone-keys.c index 500724213d552847497fa28d1fc6cfd93c991151..9297a521a896189e654e8c6a08e38df360ddc69b 100644 --- a/src/knot/dnssec/zone-keys.c +++ b/src/knot/dnssec/zone-keys.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,9 @@ #include "knot/dnssec/zone-keys.h" #include "libknot/libknot.h" #include "libknot/rrtype/dnskey.h" +#include "contrib/dynarray.h" + +dynarray_define(keyptr, zone_key_t *, 1) /*! * \brief Get key feature flags from key parameters. @@ -319,22 +322,20 @@ void free_zone_keys(zone_keyset_t *keyset) } /*! - * \brief Get zone key by a keytag. + * \brief Get zone keys by keytag. */ -const zone_key_t *get_zone_key(const zone_keyset_t *keyset, uint16_t search) +struct keyptr_dynarray get_zone_keys(const zone_keyset_t *keyset, uint16_t search) { - if (!keyset) { - return NULL; - } + struct keyptr_dynarray res = { 0 }; - for (size_t i = 0; i < keyset->count; i++) { + for (size_t i = 0; keyset && i < keyset->count; i++) { zone_key_t *key = &keyset->keys[i]; - if (dnssec_key_get_keytag(key->key) == search) { - return key; + if (key != NULL && dnssec_key_get_keytag(key->key) == search) { + keyptr_dynarray_add(&res, &key); } } - return NULL; + return res; } /*! diff --git a/src/knot/dnssec/zone-keys.h b/src/knot/dnssec/zone-keys.h index dc0dd61fc53c2153eaaf7379c4adccd47c2e9146..5e306b69e098512a6930f97e69b17683331d6216 100644 --- a/src/knot/dnssec/zone-keys.h +++ b/src/knot/dnssec/zone-keys.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -72,14 +72,14 @@ int load_zone_keys(dnssec_kasp_zone_t *zone, dnssec_keystore_t *store, bool nsec3_enabled, time_t now, zone_keyset_t *keyset_ptr); /*! - * \brief Get zone key by a keytag. + * \brief Get zone keys by a keytag. * - * \param keys Zone keys. - * \param keytag Keytag to lookup a key for. + * \param keyset Zone keyset. + * \param search Keytag to lookup a key for. * - * \return Pointer to key or NULL if not found. + * \return Dynarray of pointers to keys. */ -const zone_key_t *get_zone_key(const zone_keyset_t *keyset, uint16_t keytag); +struct keyptr_dynarray get_zone_keys(const zone_keyset_t *keyset, uint16_t search); /*! * \brief Free structure with zone keys and associated DNSSEC contexts. diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c index 0f79051ab09a21bcccd8d80c6f4f038bc1444d1a..16f548ced052770855f9566a9215db49b6e4181b 100644 --- a/src/knot/dnssec/zone-sign.c +++ b/src/knot/dnssec/zone-sign.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,8 +35,11 @@ #include "libknot/rrset.h" #include "libknot/rrtype/rrsig.h" #include "libknot/rrtype/soa.h" +#include "contrib/dynarray.h" #include "contrib/macros.h" +dynarray_define(keyptr, zone_key_t *, 1) + typedef struct type_node { node_t n; uint16_t type; @@ -110,8 +113,10 @@ static bool valid_signature_exists(const knot_rrset_t *covered, continue; } - return knot_check_signature(covered, rrsigs, i, key, ctx, - dnssec_ctx) == KNOT_EOK; + if (knot_check_signature(covered, rrsigs, i, key, ctx, + dnssec_ctx) == KNOT_EOK) { + return true; + } } return false; @@ -182,18 +187,17 @@ static bool all_signatures_exist(const knot_rrset_t *covered, * \param pos Number of RR in RR set. * \param keys Zone keys. * - * \return Zone key or NULL if a that key does not exist. + * \return Dynarray of such keys. */ -static const zone_key_t *get_matching_zone_key(const knot_rrset_t *rrsigs, - size_t pos, - const zone_keyset_t *keys) +static struct keyptr_dynarray get_matching_zone_keys(const knot_rrset_t *rrsigs, + size_t pos, const zone_keyset_t *keys) { assert(rrsigs && rrsigs->type == KNOT_RRTYPE_RRSIG); assert(keys); uint16_t keytag = knot_rrsig_key_tag(&rrsigs->rrs, pos); - return get_zone_key(keys, keytag); + return get_zone_keys(keys, keytag); } /*! @@ -257,21 +261,30 @@ static int remove_expired_rrsigs(const knot_rrset_t *covered, uint16_t rrsig_rdata_count = synth_rrsig.rrs.rr_count; for (uint16_t i = 0; i < rrsig_rdata_count; i++) { - const zone_key_t *key; - key = get_matching_zone_key(&synth_rrsig, i, zone_keys); + struct keyptr_dynarray keys = get_matching_zone_keys(&synth_rrsig, i, zone_keys); + keyptr_dynarray_fix(&keys); + int endloop = 0; // 1 - continue; 2 - break - if (key && key->is_active) { + for (size_t j = 0; j < keys.size && endloop == 0; j++) { + if (!keys.arr[j]->is_active) { + continue; + } result = knot_check_signature(covered, &synth_rrsig, i, - key->key, key->ctx, dnssec_ctx); + keys.arr[j]->key, keys.arr[j]->ctx, dnssec_ctx); if (result == KNOT_EOK) { // valid signature note_earliest_expiration(&synth_rrsig, i, expires_at); - continue; + endloop = 1; + } else if (result != DNSSEC_INVALID_SIGNATURE) { + endloop = 2; } + } + keyptr_dynarray_free(&keys); - if (result != DNSSEC_INVALID_SIGNATURE) { - break; - } + if (endloop == 2) { + break; + } else if (endloop == 1) { + continue; } if (knot_rrset_empty(&to_remove)) { @@ -643,9 +656,20 @@ static bool dnskey_in_keyset(const zone_keyset_t *keyset, uint16_t tag = 0; dnssec_keytag(&rdata, &tag); - const zone_key_t *key = get_zone_key(keyset, tag); + bool found = false; + + struct keyptr_dynarray keys = get_zone_keys(keyset, tag); + keyptr_dynarray_fix(&keys); + + for (size_t i = 0; i < keys.size; i++) { + if (keys.arr[i]->is_public && dnskey_rdata_match(keys.arr[i], &rdata)) { + found = true; + break; + } + } + keyptr_dynarray_free(&keys); - return (key && key->is_public && dnskey_rdata_match(key, &rdata)); + return found; } /*!