diff --git a/distro/pkg/deb/libknot12.symbols b/distro/pkg/deb/libknot12.symbols index 44859b3de830b8ae09157b455e77e6f1b3ba495f..55ed8c1dcfdddaf3ba0f19052ae68db8ebbf6ec8 100644 --- a/distro/pkg/deb/libknot12.symbols +++ b/distro/pkg/deb/libknot12.symbols @@ -116,6 +116,7 @@ libknot.so.12 libknot12 #MINVER# knot_rdataset_copy@Base 3.1.0 knot_rdataset_eq@Base 3.1.0 knot_rdataset_intersect@Base 3.1.0 + knot_rdataset_intersect2@Base 3.2.0 knot_rdataset_member@Base 3.1.0 knot_rdataset_merge@Base 3.1.0 knot_rdataset_subset@Base 3.2.0 diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in index 4a08769aeeb31f4944c452826e8e7bdfab1ef8e6..be80d3e53f35669f5a6d982e6039737ba97c72bc 100644 --- a/doc/man/knot.conf.5in +++ b/doc/man/knot.conf.5in @@ -1335,6 +1335,7 @@ policy: ds\-push: remote_id | remotes_id ... cds\-cdnskey\-publish: none | delete\-dnssec | rollover | always | double\-ds cds\-digest\-type: sha256 | sha384 + dnskey\-management: full | incremental offline\-ksk: BOOL unsafe\-operation: none | no\-check\-keyset | no\-update\-dnskey | no\-update\-nsec | no\-update\-expired ... .ft P @@ -1673,6 +1674,41 @@ more records depending on the keys available. Specify digest type for published CDS records. .sp \fIDefault:\fP sha256 +.SS dnskey\-management +.sp +Specify how the DNSKEY, CDNSKEY, and CDS RRSets at the zone apex are handled +when (re\-)signing the zone. +.sp +Possible values: +.INDENT 0.0 +.IP \(bu 2 +\fBfull\fP – Upon every zone (re\-)sign, delete all unknown DNSKEY, CDNSKEY, and CDS +records and keep just those that are related to the zone keys stored in the KASP database. +.IP \(bu 2 +\fBincremental\fP – Keep unknown DNSKEY, CDNSKEY, and CDS records in the zone, and +modify server\-managed records incrementally by employing changes in the KASP database. +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +Prerequisites for \fIincremental\fP: +.INDENT 0.0 +.IP \(bu 2 +The Offline KSK isn\(aqt supported. +.IP \(bu 2 +The \fI\%delete\-delay\fP is long enough to cover possible daemon +shutdown (e.g. due to server maintenance). +.IP \(bu 2 +Avoided manual deletion of keys with keymgr\&. +.UNINDENT +.sp +Otherwise there might remain some DNSKEY records in the zone, belonging to +deleted keys. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP full .SS offline\-ksk .sp Specifies if Offline KSK feature is enabled. diff --git a/doc/reference.rst b/doc/reference.rst index 4a110fa051a0915b0960188e7447158d641c8678..dbfa45e89e161a25515dc55cb8a977a5adfba807 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -1463,6 +1463,7 @@ DNSSEC policy configuration. ds-push: remote_id | remotes_id ... cds-cdnskey-publish: none | delete-dnssec | rollover | always | double-ds cds-digest-type: sha256 | sha384 + dnskey-management: full | incremental offline-ksk: BOOL unsafe-operation: none | no-check-keyset | no-update-dnskey | no-update-nsec | no-update-expired ... @@ -1835,6 +1836,34 @@ Specify digest type for published CDS records. *Default:* sha256 +.. _policy_dnskey-management: + +dnskey-management +----------------- + +Specify how the DNSKEY, CDNSKEY, and CDS RRSets at the zone apex are handled +when (re-)signing the zone. + +Possible values: + +- ``full`` – Upon every zone (re-)sign, delete all unknown DNSKEY, CDNSKEY, and CDS + records and keep just those that are related to the zone keys stored in the KASP database. +- ``incremental`` – Keep unknown DNSKEY, CDNSKEY, and CDS records in the zone, and + modify server-managed records incrementally by employing changes in the KASP database. + +.. NOTE:: + Prerequisites for *incremental*: + + - The :ref:`Offline KSK <DNSSEC Offline KSK>` isn't supported. + - The :ref:`policy_delete-delay` is long enough to cover possible daemon + shutdown (e.g. due to server maintenance). + - Avoided manual deletion of keys with :doc:`keymgr<man_keymgr>`. + + Otherwise there might remain some DNSKEY records in the zone, belonging to + deleted keys. + +*Default:* full + .. _policy_offline-ksk: offline-ksk diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index 7409abf5907effd99eb463fd21c57b120f2d8c78..7559301624ab188a8dd76f4c8c33098838ab419d 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -90,6 +90,12 @@ static const knot_lookup_t cds_cdnskey[] = { { 0, NULL } }; +static const knot_lookup_t dnskey_mgmt[] = { + { DNSKEY_MGMT_FULL, "full" }, + { DNSKEY_MGMT_INCREMENTAL, "incremental" }, + { 0, NULL } +}; + static const knot_lookup_t cds_digesttype[] = { { DNSSEC_KEY_DIGEST_SHA256, "sha256" }, { DNSSEC_KEY_DIGEST_SHA384, "sha384" }, @@ -414,6 +420,8 @@ static const yp_item_t desc_policy[] = { CONF_IO_FRLD_ZONES }, { C_CDS_DIGESTTYPE, YP_TOPT, YP_VOPT = { cds_digesttype, DNSSEC_KEY_DIGEST_SHA256 }, CONF_IO_FRLD_ZONES }, + { C_DNSKEY_MGMT, YP_TOPT, YP_VOPT = { dnskey_mgmt, DNSKEY_MGMT_FULL }, + CONF_IO_FRLD_ZONES }, { C_OFFLINE_KSK, YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES }, { C_UNSAFE_OPERATION, YP_TOPT, YP_VOPT = { unsafe_operation, UNSAFE_NONE }, YP_FMULTI }, { C_COMMENT, YP_TSTR, YP_VNONE }, diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h index 43ac1f9b243a116b252efacaa8afa57e5ba92475..9617c00c7b8775e18b531254bfd711f84d68ffc2 100644 --- a/src/knot/conf/schema.h +++ b/src/knot/conf/schema.h @@ -47,6 +47,7 @@ #define C_DBUS_EVENT "\x0A""dbus-event" #define C_DDNS_MASTER "\x0B""ddns-master" #define C_DENY "\x04""deny" +#define C_DNSKEY_MGMT "\x11""dnskey-management" #define C_DNSKEY_TTL "\x0A""dnskey-ttl" #define C_DNSSEC_POLICY "\x0D""dnssec-policy" #define C_DNSSEC_SIGNING "\x0E""dnssec-signing" @@ -202,6 +203,11 @@ enum { CDS_CDNSKEY_DOUBLE_DS = 4, }; +enum { + DNSKEY_MGMT_FULL = 0, + DNSKEY_MGMT_INCREMENTAL = 1, +}; + enum { SERIAL_POLICY_INCREMENT = 1, SERIAL_POLICY_UNIXTIME = 2, diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c index 4390ffaf9f40cccf636fc3e00b91b0f62ef6647c..0b423e28115dccd126fc570426bb4f9b7814f3ac 100644 --- a/src/knot/conf/tools.c +++ b/src/knot/conf/tools.c @@ -655,6 +655,23 @@ int check_policy( } } + conf_val_t dnskey_mgmt = conf_rawid_get_txn(args->extra->conf, args->extra->txn, C_POLICY, + C_DNSKEY_MGMT, args->id, args->id_len); + conf_val_t offline_ksk = conf_rawid_get_txn(args->extra->conf, args->extra->txn, C_POLICY, + C_OFFLINE_KSK, args->id, args->id_len); + conf_val_t delete_dely = conf_rawid_get_txn(args->extra->conf, args->extra->txn, C_POLICY, + C_DELETE_DELAY, args->id, args->id_len); + if (conf_opt(&dnskey_mgmt) != DNSKEY_MGMT_FULL) { + if (conf_bool(&offline_ksk)) { + args->err_str = "incremental DNSKEY management can't be used with offline-ksk"; + return KNOT_EINVAL; + } + if (conf_int(&delete_dely) <= 0) { + args->err_str = "incremental DNSKEY management requires configured delete-delay"; + return KNOT_EINVAL; + } + } + return KNOT_EOK; } diff --git a/src/knot/dnssec/context.c b/src/knot/dnssec/context.c index 132948fe339001130513b90e6f0626ee78bb7297..1e045b3760b81ee9ea22a76b8991f9b73c422de0 100644 --- a/src/knot/dnssec/context.c +++ b/src/knot/dnssec/context.c @@ -112,6 +112,9 @@ static void policy_load(knot_kasp_policy_t *policy, conf_t *conf, conf_val_t *id val = conf_id_get(conf, C_POLICY, C_CDS_DIGESTTYPE, id); policy->cds_dt = conf_opt(&val); + val = conf_id_get(conf, C_POLICY, C_DNSKEY_MGMT, id); + policy->incremental = (conf_opt(&val) == DNSKEY_MGMT_INCREMENTAL); + conf_val_t ksk_sbm = conf_id_get(conf, C_POLICY, C_KSK_SBM, id); if (ksk_sbm.code == KNOT_EOK) { val = conf_id_get(conf, C_SBM, C_CHK_INTERVAL, &ksk_sbm); diff --git a/src/knot/dnssec/kasp/policy.h b/src/knot/dnssec/kasp/policy.h index 5e6d110f39a2f3ee72598296c5f87b8d6e7b124e..a56bb8b0aeaeeb2b8f053727de902143ff626caf 100644 --- a/src/knot/dnssec/kasp/policy.h +++ b/src/knot/dnssec/kasp/policy.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -128,6 +128,7 @@ typedef struct { uint16_t signing_threads; bool ds_push; bool offline_ksk; + bool incremental; unsigned unsafe; } knot_kasp_policy_t; // TODO make the time parameters knot_timediff_t ?? diff --git a/src/knot/dnssec/key_records.c b/src/knot/dnssec/key_records.c index 88b102bd294219e2fbb750398bc35cb5cb8fc60b..14788c41dd6deea7bc59c4cdf8faaa80ac465f9a 100644 --- a/src/knot/dnssec/key_records.c +++ b/src/knot/dnssec/key_records.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -108,6 +108,34 @@ int key_records_to_changeset(const key_records_t *r, changeset_t *ch, return ret; } +static int subtract_one(knot_rrset_t *from, const knot_rrset_t *what, + int (*fcn)(knot_rdataset_t *, const knot_rdataset_t *, knot_mm_t *), + int ret) +{ + if (ret == KNOT_EOK && !knot_rrset_empty(from)) { + ret = fcn(&from->rrs, &what->rrs, NULL); + } + return ret; +} + +int key_records_subtract(key_records_t *r, const key_records_t *against) +{ + int ret = KNOT_EOK; + ret = subtract_one(&r->dnskey, &against->dnskey, knot_rdataset_subtract, ret); + ret = subtract_one(&r->cdnskey, &against->cdnskey, knot_rdataset_subtract, ret); + ret = subtract_one(&r->cds, &against->cds, knot_rdataset_subtract, ret); + return ret; +} + +int key_records_intersect(key_records_t *r, const key_records_t *against) +{ + int ret = KNOT_EOK; + ret = subtract_one(&r->dnskey, &against->dnskey, knot_rdataset_intersect2, ret); + ret = subtract_one(&r->cdnskey, &against->cdnskey, knot_rdataset_intersect2, ret); + ret = subtract_one(&r->cds, &against->cds, knot_rdataset_intersect2, ret); + return ret; +} + int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r, bool verbose) { if (*buf == NULL) { diff --git a/src/knot/dnssec/key_records.h b/src/knot/dnssec/key_records.h index 0d1c3516973db1cfd4346c7843bee23359c1a249..1f43467b057d267aa85406527353e54e9c870529 100644 --- a/src/knot/dnssec/key_records.h +++ b/src/knot/dnssec/key_records.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -33,6 +33,10 @@ void key_records_clear_rdatasets(key_records_t *r); int key_records_to_changeset(const key_records_t *r, changeset_t *ch, bool rem, changeset_flag_t chfl); +int key_records_subtract(key_records_t *r, const key_records_t *against); + +int key_records_intersect(key_records_t *r, const key_records_t *against); + int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r, bool verbose); int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx, knot_time_t *expires); diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c index 2822c4578eaddfe5fd735adfee6828f2d4c25177..e2cc164a5307ef13dd07b85f1c35bbd46de878be 100644 --- a/src/knot/dnssec/zone-sign.c +++ b/src/knot/dnssec/zone-sign.c @@ -775,26 +775,52 @@ keyptr_dynarray_t knot_zone_sign_get_cdnskeys(const kdnssec_ctx_t *ctx, } int knot_zone_sign_add_dnskeys(zone_keyset_t *zone_keys, const kdnssec_ctx_t *dnssec_ctx, - key_records_t *add_r) + key_records_t *add_r, key_records_t *rem_r, key_records_t *orig_r) { - if (add_r == NULL) { + if (add_r == NULL || (rem_r != NULL && orig_r == NULL)) { return KNOT_EINVAL; } + + bool incremental = (dnssec_ctx->policy->incremental && rem_r != NULL); + dnssec_key_digest_t cds_dt = dnssec_ctx->policy->cds_dt; int ret = KNOT_EOK; + for (int i = 0; i < zone_keys->count; i++) { zone_key_t *key = &zone_keys->keys[i]; if (key->is_public) { ret = rrset_add_zone_key(&add_r->dnskey, key); - if (ret != KNOT_EOK) { - return ret; - } + } else if (incremental) { + ret = rrset_add_zone_key(&rem_r->dnskey, key); + } + + // add all possible known CDNSKEYs and CDSs to removals. Sort it out later + if (incremental && ret == KNOT_EOK) { + ret = rrset_add_zone_key(&rem_r->cdnskey, key); + } + if (incremental && ret == KNOT_EOK) { + ret = rrset_add_zone_ds(&rem_r->cds, key, cds_dt); + } + + if (ret != KNOT_EOK) { + return ret; } } + keyptr_dynarray_t kcdnskeys = knot_zone_sign_get_cdnskeys(dnssec_ctx, zone_keys); knot_dynarray_foreach(keyptr, zone_key_t *, ksk_for_cds, kcdnskeys) { ret = rrset_add_zone_key(&add_r->cdnskey, *ksk_for_cds); if (ret == KNOT_EOK) { - ret = rrset_add_zone_ds(&add_r->cds, *ksk_for_cds, dnssec_ctx->policy->cds_dt); + ret = rrset_add_zone_ds(&add_r->cds, *ksk_for_cds, cds_dt); + } + } + + if (incremental && ret == KNOT_EOK) { // else rem_r is empty + ret = key_records_subtract(rem_r, add_r); + if (ret == KNOT_EOK) { + ret = key_records_intersect(rem_r, orig_r); + } + if (ret == KNOT_EOK) { + ret = key_records_subtract(add_r, orig_r); } } @@ -825,8 +851,9 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update, } const zone_node_t *apex = update->new_cont->apex; - key_records_t add_r, orig_r; + key_records_t add_r, rem_r, orig_r; memset(&add_r, 0, sizeof(add_r)); + memset(&rem_r, 0, sizeof(rem_r)); key_records_from_apex(apex, &orig_r); knot_rrset_t soa = node_rrset(apex, KNOT_RRTYPE_SOA); if (knot_rrset_empty(&soa)) { @@ -841,12 +868,14 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update, #define CHECK_RET if (ret != KNOT_EOK) goto cleanup - // remove all. This will cancel out with additions later - ret = key_records_to_changeset(&orig_r, &ch, true, 0); - CHECK_RET; + if (!dnssec_ctx->policy->incremental) { + // remove all. This will cancel out with additions later + ret = key_records_to_changeset(&orig_r, &ch, true, 0); + CHECK_RET; + } - // add DNSKEYs, CDNSKEYs and CDSs key_records_init(dnssec_ctx, &add_r); + key_records_init(dnssec_ctx, &rem_r); if (dnssec_ctx->policy->offline_ksk) { ret = kasp_db_load_offline_records(dnssec_ctx->kasp_db, apex->owner, dnssec_ctx->now, next_resign, &add_r); @@ -859,10 +888,12 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update, knot_strerror(ret)); } } else { - ret = knot_zone_sign_add_dnskeys(zone_keys, dnssec_ctx, &add_r); + ret = knot_zone_sign_add_dnskeys(zone_keys, dnssec_ctx, &add_r, &rem_r, &orig_r); } CHECK_RET; + ret = key_records_to_changeset(&rem_r, &ch, true, CHANGESET_CHECK); + CHECK_RET; ret = key_records_to_changeset(&add_r, &ch, false, CHANGESET_CHECK); CHECK_RET; if (dnssec_ctx->policy->ds_push && node_rrtype_exists(ch.add->apex, KNOT_RRTYPE_CDS)) { @@ -871,6 +902,7 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update, zone_events_schedule_at(update->zone, ZONE_EVENT_DS_PUSH, update->zone->timers.next_ds_push); } + assert(knot_rrset_empty(&rem_r.rrsig)); if (!knot_rrset_empty(&add_r.rrsig)) { dnssec_ctx->offline_rrsig = knot_rrset_copy(&add_r.rrsig, NULL); } @@ -881,6 +913,7 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update, cleanup: key_records_clear(&add_r); + key_records_clear(&rem_r); changeset_clear(&ch); return ret; } diff --git a/src/knot/dnssec/zone-sign.h b/src/knot/dnssec/zone-sign.h index 2f75d7a33473bc62fde29adbcb65169767244daa..c3990a52928a3051d389349d4cc1f190bf8a03b7 100644 --- a/src/knot/dnssec/zone-sign.h +++ b/src/knot/dnssec/zone-sign.h @@ -32,11 +32,13 @@ bool rrsig_covers_type(const knot_rrset_t *rrsig, uint16_t type); * \param zone_keys Zone keyset. * \param dnssec_ctx KASP context. * \param add_r RRSets to be added. + * \param rem_r RRSets to be removed (only for incremental policy). + * \param orig_r RRSets that was originally in zone (only for incremental policy). * * \return KNOT_E* */ int knot_zone_sign_add_dnskeys(zone_keyset_t *zone_keys, const kdnssec_ctx_t *dnssec_ctx, - key_records_t *add_r); + key_records_t *add_r, key_records_t *rem_r, key_records_t *orig_r); /*! * \brief Adds/removes DNSKEY (and CDNSKEY, CDS) records to zone according to zone keyset. diff --git a/src/libknot/rdataset.c b/src/libknot/rdataset.c index 0b9b4fd8c611358a74ad1f62e3733cf7965966b8..03e078486f27a6bb4a2ba6882f0df82d25d306b5 100644 --- a/src/libknot/rdataset.c +++ b/src/libknot/rdataset.c @@ -309,6 +309,38 @@ int knot_rdataset_intersect(const knot_rdataset_t *rrs1, const knot_rdataset_t * return KNOT_EOK; } +_public_ +int knot_rdataset_intersect2(knot_rdataset_t *from, const knot_rdataset_t *what, + knot_mm_t *mm) +{ + if (from == NULL || what == NULL) { + return KNOT_EINVAL; + } + + if (from->rdata == what->rdata) { + return KNOT_EOK; + } + + knot_rdata_t *rr1 = from->rdata; + for (uint16_t i = 0; i < from->count; ) { + if (!knot_rdataset_member(what, rr1)) { + int ret = remove_rr_at(from, i, mm); + if (ret != KNOT_EOK) { + return ret; + } + if (i < from->count) { + // Just to make sure rr1 remains valid if re-allocated. + rr1 = rr_seek(from, i); + } + } else { + i++; + rr1 = knot_rdataset_next(rr1); + } + } + + return KNOT_EOK; +} + _public_ int knot_rdataset_subtract(knot_rdataset_t *from, const knot_rdataset_t *what, knot_mm_t *mm) diff --git a/src/libknot/rdataset.h b/src/libknot/rdataset.h index f3e65a86e63b49277c1af3a6ddd1d4e9d49eeb0b..6d9808663e93a85e84a492e4835e5a976c83523b 100644 --- a/src/libknot/rdataset.h +++ b/src/libknot/rdataset.h @@ -171,6 +171,18 @@ int knot_rdataset_merge(knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2, int knot_rdataset_intersect(const knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2, knot_rdataset_t *out, knot_mm_t *mm); +/*! + * \brief Does set-like RRS intersection. \a from RRS is changed. + * + * \param from RRS to be modified by intersection. + * \param what RRS to intersect. + * \param mm Memory context use to reallocated \a from data. + * + * \return KNOT_E* + */ +int knot_rdataset_intersect2(knot_rdataset_t *from, const knot_rdataset_t *what, + knot_mm_t *mm); + /*! * \brief Does set-like RRS subtraction. \a from RRS is changed. * diff --git a/src/utils/keymgr/offline_ksk.c b/src/utils/keymgr/offline_ksk.c index 7eeca12a434dde65fb8b470fbd1f69c8a40b0b77..438230babbbffd973847fc70deee44e93db4cec3 100644 --- a/src/utils/keymgr/offline_ksk.c +++ b/src/utils/keymgr/offline_ksk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -297,7 +297,7 @@ static int ksr_sign_dnskey(kdnssec_ctx_t *ctx, knot_rrset_t *zsk, knot_time_t no key_records_t r; key_records_init(ctx, &r); - ret = knot_zone_sign_add_dnskeys(&keyset, ctx, &r); + ret = knot_zone_sign_add_dnskeys(&keyset, ctx, &r, NULL, NULL); if (ret != KNOT_EOK) { goto done; } diff --git a/tests-extra/tests/dnssec/key_rollovers/test.py b/tests-extra/tests/dnssec/key_rollovers/test.py index a102a3b40b621490dcc99e0a86a110f5c6b83f3f..51f4b2f23be8a825516b7eddf881cc62029a8f4d 100644 --- a/tests-extra/tests/dnssec/key_rollovers/test.py +++ b/tests-extra/tests/dnssec/key_rollovers/test.py @@ -16,16 +16,17 @@ from dnstest.utils import * from dnstest.keys import Keymgr from dnstest.test import Test -PUB_ONLY_SCENARIO = random.choice([0, 1, 2]) +PUB_ONLY_SCENARIO = random.choice([0, 0, 1, 2]) # Higher probability of zero to give INCREMENTAL a chance PUB_ONLY_KEYS = 1 if PUB_ONLY_SCENARIO > 0 else 0 PUB_ONLY_CDS = 1 if PUB_ONLY_SCENARIO > 1 else 0 PUB_ONLY_KEYID = "" DELETE_DELAY = random.choice([0, 2, 7, 17, 117]) +INCREMENTAL = random.choice([True, False]) if DELETE_DELAY > 0 and PUB_ONLY_KEYS == 0 else False DOUBLE_DS = random.choice([True, False]) CDS_DT = random.choice(["sha256", "sha384"]) -check_log("DOUBLE DS %s, cds dt %s, PUB_ONLY_KEYS %d, PUB_ONLY_CDS %d DELETE_DELAY %d" % \ - (str(DOUBLE_DS), CDS_DT, PUB_ONLY_KEYS, PUB_ONLY_CDS, DELETE_DELAY)) +check_log("DOUBLE DS %s, cds dt %s, PUB_ONLY_KEYS %d, PUB_ONLY_CDS %d, DELETE_DELAY %d, INCREMENTAL %s" % \ + (str(DOUBLE_DS), CDS_DT, PUB_ONLY_KEYS, PUB_ONLY_CDS, DELETE_DELAY, str(INCREMENTAL))) def generate_public_only(server, zone, alg): global PUB_ONLY_KEYID @@ -274,6 +275,7 @@ child.dnssec(child_zone).dnskey_ttl = 2 child.dnssec(child_zone).zsk_lifetime = 99999 child.dnssec(child_zone).ksk_lifetime = 300 # this can be possibly left also infinity child.dnssec(child_zone).delete_delay = DELETE_DELAY +child.dnssec(child_zone).dnskey_mgmt = "incremental" if INCREMENTAL else "full" child.dnssec(child_zone).propagation_delay = 11 child.dnssec(child_zone).ksk_sbm_check = [ parent ] child.dnssec(child_zone).ksk_sbm_check_interval = 2 diff --git a/tests-extra/tools/dnstest/server.py b/tests-extra/tools/dnstest/server.py index 4f3a9b7cc9982a3b21f197044dbce69ffd6912ef..fae1f3e6cf3a92929900b8e6d8425148664cd754 100644 --- a/tests-extra/tools/dnstest/server.py +++ b/tests-extra/tools/dnstest/server.py @@ -70,6 +70,7 @@ class ZoneDnssec(object): self.shared_policy_with = None self.cds_publish = None self.cds_digesttype = None + self.dnskey_mgmt = None self.offline_ksk = None class Zone(object): @@ -1447,6 +1448,7 @@ class Knot(Server): self._str(s, "cds-cdnskey-publish", z.dnssec.cds_publish) if z.dnssec.cds_digesttype: self._str(s, "cds-digest-type", z.dnssec.cds_digesttype) + self._str(s, "dnskey-management", z.dnssec.dnskey_mgmt) self._bool(s, "offline-ksk", z.dnssec.offline_ksk) self._str(s, "signing-threads", str(random.randint(1,4))) if have_policy: diff --git a/tests/libknot/test_rdataset.c b/tests/libknot/test_rdataset.c index 572cc49a1ecc71e60b29da7790f40c6ca20efa99..d364be3c3ca0a32f41c9439d4b8890d82de0a5c6 100644 --- a/tests/libknot/test_rdataset.c +++ b/tests/libknot/test_rdataset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2022 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 @@ -165,6 +165,28 @@ int main(int argc, char *argv[]) ok(intersect_ok, "rdataset: intersect normal."); knot_rdataset_clear(&intersection, NULL); + // Test intersect2 + ok(knot_rdataset_intersect2(NULL, NULL, NULL) == KNOT_EINVAL, + "rdataset: intersect2 NULL."); + + ret = knot_rdataset_intersect2(&rdataset, &rdataset, NULL); + intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(&rdataset, &rdataset); + ok(intersect_ok, "rdataset: intersect2 self."); + knot_rdataset_clear(&intersection, NULL); + + RDATASET_INIT_WITH(rdataset_lo, rdata_lo); + RDATASET_INIT_WITH(rdataset_gt, rdata_gt); + ret = knot_rdataset_intersect2(&rdataset_lo, &rdataset_gt, NULL); + intersect_ok = ret == KNOT_EOK && rdataset_lo.count == 0; + ok(intersect_ok, "rdataset: intersect2 no common."); + + ret = knot_rdataset_copy(©, &rdataset, NULL); + assert(ret == KNOT_EOK); + ret = knot_rdataset_intersect2(©, &rdataset_lo, NULL); + intersect_ok = ret == KNOT_EOK && knot_rdataset_eq(©, &rdataset_lo); + ok(intersect_ok, "rdataset: intersect2 normal."); + knot_rdataset_clear(©, NULL); + // Test subtract ok(knot_rdataset_subtract(NULL, NULL, NULL) == KNOT_EINVAL, "rdataset: subtract NULL.");