Commit af3a9826 authored by Libor Peltan's avatar Libor Peltan

dnssec: structure for manipulating DNSKEY/CDS/RRSIG at once

parent 4bf3dd22
......@@ -103,6 +103,8 @@ src/knot/dnssec/kasp/keystore.h
src/knot/dnssec/kasp/policy.h
src/knot/dnssec/key-events.c
src/knot/dnssec/key-events.h
src/knot/dnssec/key_records.c
src/knot/dnssec/key_records.h
src/knot/dnssec/nsec-chain.c
src/knot/dnssec/nsec-chain.h
src/knot/dnssec/nsec3-chain.c
......
......@@ -44,6 +44,8 @@ libknotd_la_SOURCES = \
knot/dnssec/kasp/policy.h \
knot/dnssec/key-events.c \
knot/dnssec/key-events.h \
knot/dnssec/key_records.c \
knot/dnssec/key_records.h \
knot/dnssec/nsec-chain.c \
knot/dnssec/nsec-chain.h \
knot/dnssec/nsec3-chain.c \
......
......@@ -23,6 +23,7 @@
#include "contrib/files.h"
#include "contrib/wire_ctx.h"
#include "knot/dnssec/key_records.h"
#include "knot/journal/serialization.h"
struct kasp_db {
......@@ -775,22 +776,16 @@ static void for_time2string(char str[TIME_STRLEN + 1], knot_time_t t)
(void)snprintf(str, TIME_STRLEN + 1, "%0.*"PRIu64, TIME_STRLEN, t);
}
int kasp_db_store_offline_records(kasp_db_t *db, knot_time_t for_time, const knot_rrset_t *rrsig,
const knot_rrset_t *dnskey, const knot_rrset_t *cdnskey,
const knot_rrset_t *cds)
int kasp_db_store_offline_records(kasp_db_t *db, knot_time_t for_time, const key_records_t *r)
{
if (db == NULL || rrsig == NULL || rrsig->type != KNOT_RRTYPE_RRSIG ||
dnskey == NULL || dnskey->type != KNOT_RRTYPE_DNSKEY ||
cdnskey == NULL || cdnskey->type != KNOT_RRTYPE_CDNSKEY ||
cds == NULL || cds->type != KNOT_RRTYPE_CDS) {
if (db == NULL || r == NULL) {
return KNOT_EINVAL;
}
char for_time_str[TIME_STRLEN + 1];
for_time2string(for_time_str, for_time);
knot_db_val_t key = make_key(KASPDBKEY_OFFLINE_RECORDS, rrsig->owner, for_time_str), val;
val.len = rrset_serialized_size(rrsig) + rrset_serialized_size(dnskey) +
rrset_serialized_size(cdnskey) + rrset_serialized_size(cds);
knot_db_val_t key = make_key(KASPDBKEY_OFFLINE_RECORDS, r->rrsig.owner, for_time_str), val;
val.len = key_records_serialized_size(r);
val.data = malloc(val.len);
if (val.data == NULL) {
free_key(&key);
......@@ -798,16 +793,7 @@ int kasp_db_store_offline_records(kasp_db_t *db, knot_time_t for_time, const kno
}
with_txn(KEYS_RW, key.data, val.data, NULL);
wire_ctx_t wire = wire_ctx_init(val.data, val.len);
ret = serialize_rrset(&wire, rrsig);
if (ret == KNOT_EOK) {
ret = serialize_rrset(&wire, dnskey);
}
if (ret == KNOT_EOK) {
ret = serialize_rrset(&wire, cdnskey);
}
if (ret == KNOT_EOK) {
ret = serialize_rrset(&wire, cds);
}
ret = key_records_serialize(&wire, r);
if (ret == KNOT_EOK) {
ret = db_api->insert(txn, &key, &val, 0);
}
......@@ -819,10 +805,9 @@ int kasp_db_store_offline_records(kasp_db_t *db, knot_time_t for_time, const kno
int kasp_db_load_offline_records(kasp_db_t *db, const knot_dname_t *for_dname,
knot_time_t for_time, knot_time_t *next_time,
knot_rrset_t *rrsig, knot_rrset_t *dnskey,
knot_rrset_t *cdnskey, knot_rrset_t *cds)
key_records_t *r)
{
if (db == NULL || rrsig == NULL || dnskey == NULL || cdnskey == NULL || cds == NULL) {
if (db == NULL || r == NULL) {
return KNOT_EINVAL;
}
......@@ -845,25 +830,19 @@ int kasp_db_load_offline_records(kasp_db_t *db, const knot_dname_t *for_dname,
goto cleanup;
}
if (key_class(&key) != KASPDBKEY_OFFLINE_RECORDS ||
knot_dname_cmp((const knot_dname_t *)key.data + 1, rrsig->owner) != 0) {
knot_dname_cmp((const knot_dname_t *)key.data + 1, r->rrsig.owner) != 0) {
ret = KNOT_ENOENT;
goto cleanup;
}
wire_ctx_t wire = wire_ctx_init(val.data, val.len);
#define CHK_RET if (ret != KNOT_EOK) goto cleanup;
ret = deserialize_rrset(&wire, rrsig);
CHK_RET
ret = deserialize_rrset(&wire, dnskey);
CHK_RET
ret = deserialize_rrset(&wire, cdnskey);
CHK_RET
ret = deserialize_rrset(&wire, cds);
CHK_RET
#undef CHK_RET
ret = key_records_deserialize(&wire, r);
if (ret != KNOT_EOK) {
goto cleanup;
}
*next_time = 0;
if ((it = db_api->iter_next(it)) != NULL && db_api->iter_key(it, &key) == KNOT_EOK) {
if (key_class(&key) == KASPDBKEY_OFFLINE_RECORDS &&
knot_dname_cmp(key_dname(&key), rrsig->owner) == 0) {
knot_dname_cmp(key_dname(&key), r->rrsig.owner) == 0) {
*next_time = atol(key_str(&key));
}
}
......
......@@ -236,42 +236,33 @@ int kasp_db_set_policy_last(kasp_db_t *db, const char *policy_string, const char
int kasp_db_list_zones(kasp_db_t *db, list_t *dst);
/*!
* \brief Store pre-generated RRSIG for offline KSK usage.
* \brief Store pre-generated records for offline KSK usage.
*
* \param db KASP db.
* \param for_time Timestamp in future in which the RRSIG shall be used.
* \param rrsig The RRSIG to be stored.
* \param dnskey The DNSKEY rrset to be stored.
* \param cdnskey The CDNSKEY rrset to be stored.
* \param cds The CDS rrset to be stored.
* \param r Records to be stored.
*
* \return KNOT_E*
*/
int kasp_db_store_offline_records(kasp_db_t *db, knot_time_t for_time, const knot_rrset_t *rrsig,
const knot_rrset_t *dnskey, const knot_rrset_t *cdnskey,
const knot_rrset_t *cds);
int kasp_db_store_offline_records(kasp_db_t *db, knot_time_t for_time, const key_records_t *r);
/*!
* \brief Load pregenerated RRSIG.
* \brief Load pregenerated records for offline signing.
*
* \param db KASP db.
* \param for_dname Name of the related zone.
* \param for_time Now. Closest RRSIG (timestamp equals or is closest lower).
* \param next_time Out: timestamp of next saved RRSIG (for easy "iteration").
* \param rrsig Out: the RRSIG rrset.
* \param dnskey Out: the DNSKEY rrset.
* \param cdnskey Out: the CDNSKEY rrset.
* \param cds Out: the CDS rrset.
* \param r Out: offline records.
*
* \return KNOT_E*
*/
int kasp_db_load_offline_records(kasp_db_t *db, const knot_dname_t *for_dname,
knot_time_t for_time, knot_time_t *next_time,
knot_rrset_t *rrsig, knot_rrset_t *dnskey,
knot_rrset_t *cdnskey, knot_rrset_t *cds);
key_records_t *r);
/*!
* \brief Delete pregenerated RRSIGs for specified time interval.
* \brief Delete pregenerated records for specified time interval.
*
* \param db KASP db.
* \param zone Zone in question.
......
......@@ -73,6 +73,16 @@ typedef struct {
dynarray_declare(parent, knot_kasp_parent_t, DYNARRAY_VISIBILITY_PUBLIC, 3)
/*!
* Set of DNSSEC key related records.
*/
typedef struct {
knot_rrset_t dnskey;
knot_rrset_t cdnskey;
knot_rrset_t cds;
knot_rrset_t rrsig;
} key_records_t;
/*!
* Key and signature policy.
*/
......
/* Copyright (C) 2018 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "knot/dnssec/key_records.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-sign.h"
#include "knot/journal/serialization.h"
void key_records_init(const kdnssec_ctx_t *ctx, key_records_t *r)
{
knot_rrset_init(&r->dnskey, knot_dname_copy(ctx->zone->dname, NULL),
KNOT_RRTYPE_DNSKEY, KNOT_CLASS_IN, ctx->policy->dnskey_ttl);
knot_rrset_init(&r->cdnskey, knot_dname_copy(ctx->zone->dname, NULL),
KNOT_RRTYPE_CDNSKEY, KNOT_CLASS_IN, 0);
knot_rrset_init(&r->cds, knot_dname_copy(ctx->zone->dname, NULL),
KNOT_RRTYPE_CDS, KNOT_CLASS_IN, 0);
knot_rrset_init(&r->rrsig, knot_dname_copy(ctx->zone->dname, NULL),
KNOT_RRTYPE_RRSIG, KNOT_CLASS_IN, ctx->policy->dnskey_ttl);
}
int key_records_add_rdata(key_records_t *r, uint16_t rrtype, uint8_t *rdata, uint16_t rdlen, uint32_t ttl)
{
knot_rrset_t *to_add;
switch(rrtype) {
case KNOT_RRTYPE_DNSKEY:
to_add = &r->dnskey;
break;
case KNOT_RRTYPE_CDNSKEY:
to_add = &r->cdnskey;
break;
case KNOT_RRTYPE_CDS:
to_add = &r->cds;
break;
case KNOT_RRTYPE_RRSIG:
to_add = &r->rrsig;
break;
default:
return KNOT_EINVAL;
}
int ret = knot_rrset_add_rdata(to_add, rdata, rdlen, NULL);
if (ret == KNOT_EOK) {
to_add->ttl = ttl;
}
return ret;
}
void key_records_clear(key_records_t *r)
{
knot_rrset_clear(&r->dnskey, NULL);
knot_rrset_clear(&r->cdnskey, NULL);
knot_rrset_clear(&r->cds, NULL);
knot_rrset_clear(&r->rrsig, NULL);
}
void key_records_clear_rdatasets(key_records_t *r)
{
knot_rdataset_clear(&r->dnskey.rrs, NULL);
knot_rdataset_clear(&r->cdnskey.rrs, NULL);
knot_rdataset_clear(&r->cds.rrs, NULL);
knot_rdataset_clear(&r->rrsig.rrs, NULL);
}
int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r)
{
if (*buf == NULL) {
if (*buf_size == 0) {
*buf_size = 512;
}
*buf = malloc(*buf_size);
if (*buf == NULL) {
return KNOT_ENOMEM;
}
}
int ret = KNOT_EOK;
size_t total = 1;
// first go: just detect the size
if (!knot_rrset_empty(&r->dnskey)) {
ret = knot_rrset_txt_dump(&r->dnskey, buf, buf_size, &KNOT_DUMP_STYLE_DEFAULT);
total += ret;
}
if (ret >= 0 && !knot_rrset_empty(&r->cdnskey)) {
ret = knot_rrset_txt_dump(&r->cdnskey, buf, buf_size, &KNOT_DUMP_STYLE_DEFAULT);
total += ret;
}
if (ret >= 0 && !knot_rrset_empty(&r->cds)) {
ret = knot_rrset_txt_dump(&r->cds, buf, buf_size, &KNOT_DUMP_STYLE_DEFAULT);
total += ret;
}
if (ret >= 0 && !knot_rrset_empty(&r->rrsig)) {
ret = knot_rrset_txt_dump(&r->rrsig, buf, buf_size, &KNOT_DUMP_STYLE_DEFAULT);
total += ret;
}
if (ret >= 0 && total < *buf_size) {
free(*buf);
*buf_size = total;
*buf = malloc(*buf_size);
if (*buf == NULL) {
return KNOT_ENOMEM;
}
}
char *fake_buf = *buf;
size_t fake_size = *buf_size;
//second go: do it
if (ret >= 0 && !knot_rrset_empty(&r->dnskey)) {
ret = knot_rrset_txt_dump(&r->dnskey, &fake_buf, &fake_size, &KNOT_DUMP_STYLE_DEFAULT);
fake_buf += ret, fake_size -= ret;
}
if (ret >= 0 && !knot_rrset_empty(&r->cdnskey)) {
ret = knot_rrset_txt_dump(&r->cdnskey, &fake_buf, &fake_size, &KNOT_DUMP_STYLE_DEFAULT);
fake_buf += ret, fake_size -= ret;
}
if (ret >= 0 && !knot_rrset_empty(&r->cds)) {
ret = knot_rrset_txt_dump(&r->cds, &fake_buf, &fake_size, &KNOT_DUMP_STYLE_DEFAULT);
fake_buf += ret, fake_size -= ret;
}
if (ret >= 0 && !knot_rrset_empty(&r->rrsig)) {
ret = knot_rrset_txt_dump(&r->rrsig, &fake_buf, &fake_size, &KNOT_DUMP_STYLE_DEFAULT);
}
return ret >= 0 ? KNOT_EOK : ret;
}
int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx)
{
if (!key->is_active) {
return KNOT_EOK;
}
int ret = KNOT_EOK;
if (!knot_rrset_empty(&r->dnskey) && knot_zone_sign_use_key(key, &r->dnskey)) {
ret = knot_sign_rrset(&r->rrsig, &r->dnskey, key->key, key->ctx, kctx, NULL, NULL);
}
if (ret == KNOT_EOK && !knot_rrset_empty(&r->cdnskey) && knot_zone_sign_use_key(key, &r->cdnskey)) {
ret = knot_sign_rrset(&r->rrsig, &r->cdnskey, key->key, key->ctx, kctx, NULL, NULL);
}
if (ret == KNOT_EOK && !knot_rrset_empty(&r->cds) && knot_zone_sign_use_key(key, &r->cds)) {
ret = knot_sign_rrset(&r->rrsig, &r->cds, key->key, key->ctx, kctx, NULL, NULL);
}
return ret;
}
size_t key_records_serialized_size(const key_records_t *r)
{
return rrset_serialized_size(&r->dnskey) + rrset_serialized_size(&r->cdnskey) +
rrset_serialized_size(&r->cds) + rrset_serialized_size(&r->rrsig);
}
int key_records_serialize(wire_ctx_t *wire, const key_records_t *r)
{
int ret = serialize_rrset(wire, &r->dnskey);
if (ret == KNOT_EOK) {
ret = serialize_rrset(wire, &r->cdnskey);
}
if (ret == KNOT_EOK) {
ret = serialize_rrset(wire, &r->cds);
}
if (ret == KNOT_EOK) {
ret = serialize_rrset(wire, &r->rrsig);
}
return ret;
}
int key_records_deserialize(wire_ctx_t *wire, key_records_t *r)
{
int ret = deserialize_rrset(wire, &r->dnskey);
if (ret == KNOT_EOK) {
ret = deserialize_rrset(wire, &r->cdnskey);
}
if (ret == KNOT_EOK) {
ret = deserialize_rrset(wire, &r->cds);
}
if (ret == KNOT_EOK) {
ret = deserialize_rrset(wire, &r->rrsig);
}
return ret;
}
/* Copyright (C) 2018 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "contrib/wire_ctx.h"
#include "knot/dnssec/zone-keys.h"
void key_records_init(const kdnssec_ctx_t *ctx, key_records_t *r);
int key_records_add_rdata(key_records_t *r, uint16_t rrtype, uint8_t *rdata, uint16_t rdlen, uint32_t ttl);
void key_records_clear(key_records_t *r);
void key_records_clear_rdatasets(key_records_t *r);
int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r);
int key_records_sign(const zone_key_t *key, key_records_t *r, const kdnssec_ctx_t *kctx);
size_t key_records_serialized_size(const key_records_t *r);
int key_records_serialize(wire_ctx_t *wire, const key_records_t *r);
int key_records_deserialize(wire_ctx_t *wire, key_records_t *r);
......@@ -23,6 +23,7 @@
#include "libdnssec/sign.h"
#include "knot/common/log.h"
#include "knot/dnssec/key-events.h"
#include "knot/dnssec/key_records.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-sign.h"
#include "libknot/libknot.h"
......@@ -904,16 +905,16 @@ 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,
knot_rrset_t *add_dnskeys, knot_rrset_t *add_cdnskeys, knot_rrset_t *add_cdss)
key_records_t *add_r)
{
if (add_dnskeys == NULL || add_cdnskeys == NULL || add_cdss == NULL) {
if (add_r == NULL) {
return KNOT_EINVAL;
}
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_dnskeys, key);
ret = rrset_add_zone_key(&add_r->dnskey, key);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -921,18 +922,18 @@ int knot_zone_sign_add_dnskeys(zone_keyset_t *zone_keys, const kdnssec_ctx_t *dn
}
keyptr_dynarray_t kcdnskeys = knot_zone_sign_get_cdnskeys(dnssec_ctx, zone_keys);
dynarray_foreach(keyptr, zone_key_t *, ksk_for_cds, kcdnskeys) {
ret = rrset_add_zone_key(add_cdnskeys, *ksk_for_cds);
ret = rrset_add_zone_key(&add_r->cdnskey, *ksk_for_cds);
if (ret == KNOT_EOK) {
ret = rrset_add_zone_ds(add_cdss, *ksk_for_cds);
ret = rrset_add_zone_ds(&add_r->cds, *ksk_for_cds);
}
}
if (dnssec_ctx->policy->child_records_publish == CHILD_RECORDS_EMPTY && ret == KNOT_EOK) {
const uint8_t cdnskey_empty[5] = { 0, 0, 3, 0, 0 };
const uint8_t cds_empty[5] = { 0, 0, 0, 0, 0 };
ret = knot_rrset_add_rdata(add_cdnskeys, cdnskey_empty, sizeof(cdnskey_empty), NULL);
ret = knot_rrset_add_rdata(&add_r->cdnskey, cdnskey_empty, sizeof(cdnskey_empty), NULL);
if (ret == KNOT_EOK) {
ret = knot_rrset_add_rdata(add_cdss, cds_empty, sizeof(cds_empty), NULL);
ret = knot_rrset_add_rdata(&add_r->cds, cds_empty, sizeof(cds_empty), NULL);
}
}
......@@ -953,11 +954,8 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update,
knot_rrset_t dnskeys = node_rrset(apex, KNOT_RRTYPE_DNSKEY);
knot_rrset_t cdnskeys = node_rrset(apex, KNOT_RRTYPE_CDNSKEY);
knot_rrset_t cdss = node_rrset(apex, KNOT_RRTYPE_CDS);
knot_rrset_t *add_dnskeys = NULL;
knot_rrset_t *add_cdnskeys = NULL;
knot_rrset_t *add_cdss = NULL;
knot_rrset_t *add_rrsigs = NULL;
uint32_t dnskey_ttl = dnssec_ctx->policy->dnskey_ttl;
key_records_t add_r;
memset(&add_r, 0, sizeof(add_r));
knot_rrset_t soa = node_rrset(apex, KNOT_RRTYPE_SOA);
if (knot_rrset_empty(&soa)) {
return KNOT_EINVAL;
......@@ -980,22 +978,10 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update,
CHECK_RET;
// add DNSKEYs, CDNSKEYs and CDSs
add_dnskeys = knot_rrset_new(apex->owner, KNOT_RRTYPE_DNSKEY, soa.rclass,
dnskey_ttl, NULL);
add_cdnskeys = knot_rrset_new(apex->owner, KNOT_RRTYPE_CDNSKEY, soa.rclass,
0, NULL);
add_cdss = knot_rrset_new(apex->owner, KNOT_RRTYPE_CDS, soa.rclass,
0, NULL);
add_rrsigs = knot_rrset_new(apex->owner, KNOT_RRTYPE_RRSIG, soa.rclass,
dnskey_ttl, NULL);
if (add_dnskeys == NULL || add_cdnskeys == NULL || add_cdss == NULL || add_rrsigs == NULL) {
ret = KNOT_ENOMEM;
CHECK_RET;
}
key_records_init(dnssec_ctx, &add_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_rrsigs, add_dnskeys, add_cdnskeys, add_cdss);
ret = kasp_db_load_offline_records(*dnssec_ctx->kasp_db, apex->owner, dnssec_ctx->now, next_resign, &add_r);
if (ret == KNOT_EOK) {
log_zone_info(dnssec_ctx->zone->dname, "DNSSEC, using offline DNSKEY RRSIG");
} else {
......@@ -1003,31 +989,30 @@ 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_dnskeys, add_cdnskeys, add_cdss);
ret = knot_zone_sign_add_dnskeys(zone_keys, dnssec_ctx, &add_r);
}
CHECK_RET;
if (!knot_rrset_empty(add_cdnskeys)) {
ret = changeset_add_addition(&ch, add_cdnskeys, CHANGESET_CHECK |
CHANGESET_CHECK_CANCELOUT);
if (!knot_rrset_empty(&add_r.cdnskey)) {
ret = changeset_add_addition(&ch, &add_r.cdnskey,
CHANGESET_CHECK | CHANGESET_CHECK_CANCELOUT);
CHECK_RET;
}
if (!knot_rrset_empty(add_cdss)) {
ret = changeset_add_addition(&ch, add_cdss, CHANGESET_CHECK |
CHANGESET_CHECK_CANCELOUT);
if (!knot_rrset_empty(&add_r.cds)) {
ret = changeset_add_addition(&ch, &add_r.cds,
CHANGESET_CHECK | CHANGESET_CHECK_CANCELOUT);
CHECK_RET;
}
if (!knot_rrset_empty(add_dnskeys)) {
ret = changeset_add_addition(&ch, add_dnskeys, CHANGESET_CHECK |
CHANGESET_CHECK_CANCELOUT);
if (!knot_rrset_empty(&add_r.dnskey)) {
ret = changeset_add_addition(&ch, &add_r.dnskey,
CHANGESET_CHECK | CHANGESET_CHECK_CANCELOUT);
CHECK_RET;
}
if (!knot_rrset_empty(add_rrsigs)) {
dnssec_ctx->offline_rrsig = add_rrsigs;
add_rrsigs = NULL; // prevent free
if (!knot_rrset_empty(&add_r.rrsig)) {
dnssec_ctx->offline_rrsig = knot_rrset_copy(&add_r.rrsig, NULL);
}
ret = zone_update_apply_changeset(update, &ch);
......@@ -1035,10 +1020,7 @@ int knot_zone_sign_update_dnskeys(zone_update_t *update,
#undef CHECK_RET
cleanup:
knot_rrset_free(add_dnskeys, NULL);
knot_rrset_free(add_cdnskeys, NULL);
knot_rrset_free(add_cdss, NULL);
knot_rrset_free(add_rrsigs, NULL);
key_records_clear(&add_r);
changeset_clear(&ch);
return ret;
}
......
......@@ -29,14 +29,12 @@ int rrset_add_zone_key(knot_rrset_t *rrset, zone_key_t *zone_key);
*
* \param zone_keys Zone keyset.
* \param dnssec_ctx KASP context.
* \param add_dnskeys RRSet for DNSKEYs.
* \param add_cdnskeys RRSet for CDNSKEYs.
* \param add_cdss RRSet for CDSs.
* \param add_r RRSets to be added.
*
* \return KNOT_E*
*/
int knot_zone_sign_add_dnskeys(zone_keyset_t *zone_keys, const kdnssec_ctx_t *dnssec_ctx,
knot_rrset_t *add_dnskeys, knot_rrset_t *add_cdnskeys, knot_rrset_t *add_cdss);
key_records_t *add_r);
/*!
* \brief Adds/removes DNSKEY (and CDNSKEY, CDS) records to zone according to zone keyset.
......
......@@ -21,6 +21,7 @@
#include "utils/keymgr/offline_ksk.h"
#include "knot/dnssec/kasp/policy.h"
#include "knot/dnssec/key-events.h"
#include "knot/dnssec/key_records.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-events.h"
#include "knot/dnssec/zone-keys.h"
......@@ -118,41 +119,21 @@ int keymgr_print_offline_records(kdnssec_ctx_t *ctx, char *arg)
}
knot_time_t next = 0;
knot_rrset_t rrsig = { 0 }, dnskey = { 0 }, cdnskey = { 0 }, cds = { 0 };
knot_rrset_init(&rrsig, knot_dname_copy(ctx->zone->dname, NULL),
KNOT_RRTYPE_RRSIG, KNOT_CLASS_IN, ctx->policy->dnskey_ttl);
knot_rrset_init_empty(&dnskey);
knot_rrset_init_empty(&cdnskey);
knot_rrset_init_empty(&cds);
ret = kasp_db_load_offline_records(*ctx->kasp_db, ctx->zone->dname, when, &next,
&rrsig, &dnskey, &cdnskey, &cds);
key_records_t r;
memset(&r, 0, sizeof(r));
ret = kasp_db_load_offline_records(*ctx->kasp_db, ctx->zone->dname, when, &next, &r);
if (ret == KNOT_EOK) {
char *buf = NULL;
size_t buf_size = 512;
ret = dump_rrset_to_buf(&rrsig, &buf, &buf_size);
if (ret >= 0) {
printf("%s", buf);
ret = dump_rrset_to_buf(&dnskey, &buf, &buf_size);
}
if (ret >= 0) {
printf("%s", buf);
ret = dump_rrset_to_buf(&cdnskey, &buf, &buf_size);
}
if (ret >= 0) {
printf("%s", buf);
ret = dump_rrset_to_buf(&cds, &buf, &buf_size);
}
if (ret >= 0) {
ret = key_records_dump(&buf, &buf_size, &r);
if (ret == KNOT_EOK) {
printf("%s", buf);
ret = KNOT_EOK;
}
free(buf);
printf("; next %lu\n", next);
}
knot_rrset_clear(&rrsig, NULL);
knot_rrset_clear(&dnskey, NULL);
knot_rrset_clear(&cdnskey, NULL);
knot_rrset_clear(&cds, NULL);
key_records_clear(&r);
return ret;
}
......@@ -246,11 +227,8 @@ int keymgr_print_ksr(kdnssec_ctx_t *ctx, char *arg)
}
typedef struct {
knot_rrset_t *dnskey;
key_records_t r;
knot_rrset_t *dnskey_prev;
knot_rrset_t *cdnskey;
knot_rrset_t *cds;
knot_rrset_t *rrsig;
kdnssec_ctx_t *kctx;
} ksr_sign_ctx_t;
......@@ -263,65 +241,38 @@ static int ksr_sign_dnskey(kdnssec_ctx_t *ctx, knot_rrset_t *zsk, knot_time_t *n
if (ret != KNOT_EOK) {
return ret;
}
knot_rrset_t *dnskey = knot_rrset_copy(zsk, NULL);
knot_rrset_t *cdnskey = knot_rrset_new(zsk->owner, KNOT_RRTYPE_CDNSKEY, zsk->rclass, 0, NULL);
knot_rrset_t *cds = knot_rrset_new(zsk->owner, KNOT_RRTYPE_CDS, zsk->rclass, 0, NULL);
knot_rrset_t *rrsig = knot_rrset_new(zsk->owner, KNOT_RRTYPE_RRSIG, zsk->rclass, zsk->ttl, NULL);
if (dnskey == NULL || cdnskey == NULL || cds == NULL || rrsig == NULL) {
ret = KNOT_ENOMEM;
key_records_t r;
key_records_init(ctx, &r);
ret = knot_zone_sign_add_dnskeys(&keyset, ctx, &r);
if (ret != KNOT_EOK) {
goto done;
}
ret = knot_zone_sign_add_dnskeys(&keyset, ctx, dnskey, cdnskey, cds);
ret = knot_rdataset_merge(&r.dnskey.rrs, &zsk->rrs, NULL);
if (ret != KNOT_EOK) {
goto done;
}
// no check if the KSK used for signing (in keyset) is contained in DNSKEY record being signed (in KSR) !
for (int i = 0; i < keyset.count; i++) {
zone_key_t *key = &keyset.keys[i];
if (key->is_active && key->is_ksk) {
ret = knot_sign_rrset(rrsig, dnskey, key->key, key->ctx, ctx, NULL, NULL);
if (ret == KNOT_EOK && !knot_rrset_empty(cdnskey) && knot_zone_sign_use_key(key, cdnskey)) {
ret = knot_sign_rrset(rrsig, cdnskey, key->key, key->ctx, ctx, NULL, NULL);
}
if (ret == KNOT_EOK && !knot_rrset_empty(cds) && knot_zone_sign_use_key(key, cds)) {
ret = knot_sign_rrset(rrsig, cds, key->key, key->ctx, ctx, NULL, NULL);
}
if (ret != KNOT_EOK) {
goto done;
}
ret = key_records_sign(&keyset.keys[i], &r, ctx);
if (ret != KNOT_EOK) {
goto done;
}
}
printf(";;SKR ver 1.0 ===========\n");
ret = dump_rrset_to_buf(dnskey, &buf, &buf_size);
if (ret >= 0) {
printf("%s", buf);
ret = dump_rrset_to_buf(cdnskey, &buf, &buf_size);
}
if (ret >= 0) {
printf("%s", buf);
ret = dump_rrset_to_buf(cds, &buf, &buf_size);
}
if (ret >= 0) {
printf("%s", buf);
ret = dump_rrset_to_buf(rrsig, &buf, &buf_size);
}
if (ret >= 0) {
ret = key_records_dump(&buf, &buf_size, &r);
if (ret == KNOT_EOK) {
buf[strlen(buf) - 1] = '\0'; // remove trailing newline
printf("%s ; end SKR %lu\n", buf, ctx->now);