Commit 09e51b5e authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

dnssec: signing refactored using zone_update mechanizms

parent 225fd8d3
......@@ -24,6 +24,7 @@
#include "knot/ctl/commands.h"
#include "knot/dnssec/key-events.h"
#include "knot/events/handlers.h"
#include "knot/events/log.h"
#include "knot/nameserver/query_module.h"
#include "knot/updates/zone-update.h"
#include "knot/zone/timers.h"
......@@ -416,6 +417,22 @@ static int zone_txn_commit(zone_t *zone, ctl_args_t *args)
return KNOT_TXN_ENOTEXISTS;
}
// Sign update.
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name);
bool dnssec_enable = (zone->control_update->flags & UPDATE_SIGN) && conf_bool(&val);
if (dnssec_enable) {
zone_sign_reschedule_t resch = { 0 };
int ret = knot_dnssec_sign_update(zone->control_update, &resch);
if (ret != KNOT_EOK) {
zone_update_clear(zone->control_update);
free(zone->control_update);
zone->control_update = NULL;
return ret;
}
log_dnssec_next(zone->name, (time_t)resch.next_sign);
zone_events_schedule_at(zone, ZONE_EVENT_DNSSEC, (time_t)resch.next_sign);
}
int ret = zone_update_commit(conf(), zone->control_update);
if (ret != KNOT_EOK) {
/* Invalidate the transaction if aborted. */
......@@ -431,7 +448,7 @@ static int zone_txn_commit(zone_t *zone, ctl_args_t *args)
zone->control_update = NULL;
/* Sync zonefile immediately if configured. */
conf_val_t val = conf_zone_get(conf(), C_ZONEFILE_SYNC, zone->name);
val = conf_zone_get(conf(), C_ZONEFILE_SYNC, zone->name);
if (conf_int(&val) == 0) {
zone_events_schedule_now(zone, ZONE_EVENT_FLUSH);
}
......
......@@ -37,8 +37,6 @@ typedef struct {
char *kasp_zone_path;
uint32_t old_serial;
uint32_t new_serial;
bool rrsig_drop_existing;
} kdnssec_ctx_t;
......
......@@ -29,10 +29,9 @@
#include "knot/dnssec/zone-keys.h"
#include "knot/dnssec/zone-nsec.h"
#include "knot/dnssec/zone-sign.h"
#include "knot/zone/serial.h"
static int sign_init(const zone_contents_t *zone, int flags, kdnssec_ctx_t *ctx,
zone_sign_reschedule_t *reschedule)
static int sign_init(const zone_contents_t *zone, zone_sign_flags_t flags,
kdnssec_ctx_t *ctx, zone_sign_reschedule_t *reschedule)
{
assert(zone);
assert(ctx);
......@@ -61,28 +60,9 @@ static int sign_init(const zone_contents_t *zone, int flags, kdnssec_ctx_t *ctx,
ctx->rrsig_drop_existing = flags & ZONE_SIGN_DROP_SIGNATURES;
// SOA handling
ctx->old_serial = zone_contents_serial(zone);
if (flags & ZONE_SIGN_KEEP_SOA_SERIAL) {
ctx->new_serial = ctx->old_serial;
} else {
conf_val_t val = conf_zone_get(conf(), C_SERIAL_POLICY, zone_name);
ctx->new_serial = serial_next(ctx->old_serial, conf_opt(&val));
}
return KNOT_EOK;
}
static int sign_update_soa(const zone_contents_t *zone, changeset_t *chset,
kdnssec_ctx_t *ctx, zone_keyset_t *keyset)
{
knot_rrset_t soa = node_rrset(zone->apex, KNOT_RRTYPE_SOA);
knot_rrset_t rrsigs = node_rrset(zone->apex, KNOT_RRTYPE_RRSIG);
assert(!knot_rrset_empty(&soa));
return knot_zone_sign_update_soa(&soa, &rrsigs, keyset, ctx, chset);
}
static knot_time_t schedule_next(kdnssec_ctx_t *kctx, const zone_keyset_t *keyset,
knot_time_t zone_expire)
{
......@@ -155,21 +135,22 @@ int knot_dnssec_nsec3resalt(kdnssec_ctx_t *ctx, bool *salt_changed, knot_time_t
return ret;
}
int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
zone_sign_flags_t flags, zone_sign_reschedule_t *reschedule)
int knot_dnssec_zone_sign(zone_update_t *update,
zone_sign_flags_t flags,
zone_sign_reschedule_t *reschedule)
{
if (!zone || !out_ch || !reschedule) {
if (!update || !reschedule) {
return KNOT_EINVAL;
}
int result = KNOT_ERROR;
const knot_dname_t *zone_name = zone->apex->owner;
const knot_dname_t *zone_name = update->new_cont->apex->owner;
kdnssec_ctx_t ctx = { 0 };
zone_keyset_t keyset = { 0 };
// signing pipeline
result = sign_init(zone, flags, &ctx, reschedule);
result = sign_init(update->new_cont, flags, &ctx, reschedule);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to initialize (%s)",
knot_strerror(result));
......@@ -186,7 +167,7 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
log_zone_info(zone_name, "DNSSEC, signing started");
result = knot_zone_create_nsec_chain(zone, out_ch, &keyset, &ctx);
result = knot_zone_create_nsec_chain(update, &keyset, &ctx, false);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to create NSEC%s chain (%s)",
ctx.policy->nsec3_enabled ? "3" : "",
......@@ -195,7 +176,7 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
}
knot_time_t zone_expire = 0;
result = knot_zone_sign(zone, &keyset, &ctx, out_ch, &zone_expire);
result = knot_zone_sign(update, &keyset, &ctx, &zone_expire);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to sign zone content (%s)",
knot_strerror(result));
......@@ -204,13 +185,16 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
// SOA finishing
if (changeset_empty(out_ch) &&
!knot_zone_sign_soa_expired(zone, &keyset, &ctx)) {
if (zone_update_no_change(update) &&
!knot_zone_sign_soa_expired(update->new_cont, &keyset, &ctx)) {
log_zone_info(zone_name, "DNSSEC, zone is up-to-date");
goto done;
}
result = sign_update_soa(zone, out_ch, &ctx, &keyset);
result = zone_update_increment_soa(update, conf());
if (result == KNOT_EOK) {
result = knot_zone_sign_soa(update, &keyset, &ctx);
}
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to update SOA record (%s)",
knot_strerror(result));
......@@ -230,23 +214,20 @@ done:
return result;
}
int knot_dnssec_sign_changeset(const zone_contents_t *zone,
const changeset_t *in_ch,
changeset_t *out_ch,
zone_sign_reschedule_t *reschedule)
int knot_dnssec_sign_update(zone_update_t *update, zone_sign_reschedule_t *reschedule)
{
if (zone == NULL || in_ch == NULL || out_ch == NULL || reschedule == NULL) {
if (update == NULL || reschedule == NULL) {
return KNOT_EINVAL;
}
int result = KNOT_ERROR;
const knot_dname_t *zone_name = zone->apex->owner;
const knot_dname_t *zone_name = update->new_cont->apex->owner;
kdnssec_ctx_t ctx = { 0 };
zone_keyset_t keyset = { 0 };
// signing pipeline
result = sign_init(zone, ZONE_SIGN_KEEP_SOA_SERIAL, &ctx, reschedule);
result = sign_init(update->new_cont, 0, &ctx, reschedule);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to initialize (%s)",
knot_strerror(result));
......@@ -261,14 +242,15 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
goto done;
}
result = knot_zone_sign_changeset(zone, in_ch, out_ch, &keyset, &ctx);
knot_time_t expire_at = 0;
result = knot_zone_sign_update(update, &keyset, &ctx, &expire_at);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to sign changeset (%s)",
knot_strerror(result));
goto done;
}
result = knot_zone_create_nsec_chain(zone, out_ch, &keyset, &ctx);
result = knot_zone_create_nsec_chain(update, &keyset, &ctx, true);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to create NSEC%s chain (%s)",
ctx.policy->nsec3_enabled ? "3" : "",
......@@ -276,19 +258,36 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
goto done;
}
// update SOA
bool soa_changed = (knot_soa_serial(node_rdataset(update->zone->contents->apex, KNOT_RRTYPE_SOA)) !=
knot_soa_serial(node_rdataset(update->new_cont->apex, KNOT_RRTYPE_SOA)));
result = sign_update_soa(zone, out_ch, &ctx, &keyset);
if (zone_update_no_change(update) && !soa_changed &&
!knot_zone_sign_soa_expired(update->new_cont, &keyset, &ctx)) {
log_zone_info(zone_name, "DNSSEC, zone is up-to-date");
goto done;
}
if (!soa_changed) {
// incrementing SOA just of it has not been modified by the update
result = zone_update_increment_soa(update, conf());
}
if (result == KNOT_EOK) {
result = knot_zone_sign_soa(update, &keyset, &ctx);
}
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to update SOA record (%s)",
knot_strerror(result));
goto done;
}
// schedule next resigning (only new signatures are made)
log_zone_info(zone_name, "DNSSEC, successfully signed");
// schedule next resigning (only new signatures are made)
reschedule->next_sign = ctx.now + ctx.policy->rrsig_lifetime - ctx.policy->rrsig_refresh_before;
assert(reschedule->next_sign > 0);
(void)expire_at; // the result of expire_at is actually unused because we computed next_sign easily
// we can freely reschedule dnssec event to next_sign because if it's already scheduled
// to earlier time, it won't get postponed
done:
free_zone_keys(&keyset);
......
......@@ -20,12 +20,12 @@
#include "knot/zone/zone.h"
#include "knot/updates/changesets.h"
#include "knot/updates/zone-update.h"
#include "knot/dnssec/context.h"
enum zone_sign_flags {
ZONE_SIGN_NONE = 0,
ZONE_SIGN_DROP_SIGNATURES = (1 << 0),
ZONE_SIGN_KEEP_SOA_SERIAL = (1 << 1),
};
typedef enum zone_sign_flags zone_sign_flags_t;
......@@ -53,30 +53,25 @@ int knot_dnssec_sign_process_events(const kdnssec_ctx_t *kctx,
* \brief DNSSEC resign zone, store new records into changeset. Valid signatures
* and NSEC(3) records will not be changed.
*
* \param zone Zone contents to be signed.
* \param out_ch New records will be added to this changeset.
* \param update Zone Update structure with current zone contents to be updated by signing.
* \param flags Zone signing flags.
* \param refresh_at Signature refresh time of the oldest signature in zone.
* \param reschedule Signature refresh time of the oldest signature in zone.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
zone_sign_flags_t flags, zone_sign_reschedule_t *reschedule);
int knot_dnssec_zone_sign(zone_update_t *update,
zone_sign_flags_t flags,
zone_sign_reschedule_t *reschedule);
/*!
* \brief Sign changeset created by DDNS or zone-diff.
* \brief Sign changeset (inside incremental Zone Update) created by DDNS or so...
*
* \param zone Zone contents to be signed.
* \param in_ch Changeset created bvy DDNS or zone-diff
* \param out_ch New records will be added to this changeset.
* \param refresh_at Signature refresh time of the new signatures.
* \param update Zone Update structure with current zone contents, changes to be signed and to be updated with signatures.
* \param reschedule Signature refresh time of the new signatures.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_dnssec_sign_changeset(const zone_contents_t *zone,
const changeset_t *in_ch,
changeset_t *out_ch,
zone_sign_reschedule_t *reschedule);
int knot_dnssec_sign_update(zone_update_t *update, zone_sign_reschedule_t *reschedule);
/*!
* \brief Create new NCES3 salt if the old one is too old, and plan next resalt.
......@@ -90,7 +85,7 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
*
* \param ctx zone signing context
* \param salt_changed output if KNOT_EOK: was the salt changed ? (if so, please re-sign)
* \param next_resalt output: tmestamp when next resalt takes place
* \param when_resalt output: tmestamp when next resalt takes place
*
* \return KNOT_E*
*/
......
/* 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
......@@ -359,16 +359,16 @@ static dnssec_nsec3_params_t nsec3param_init(const knot_kasp_policy_t *policy,
return params;
}
int knot_zone_create_nsec_chain(const zone_contents_t *zone,
changeset_t *changeset,
int knot_zone_create_nsec_chain(zone_update_t *update,
const zone_keyset_t *zone_keys,
const kdnssec_ctx_t *ctx)
const kdnssec_ctx_t *ctx,
bool sign_nsec_chain)
{
if (zone == NULL || changeset == NULL || ctx == NULL) {
if (update == NULL || ctx == NULL) {
return KNOT_EINVAL;
}
const knot_rdataset_t *soa = node_rdataset(zone->apex, KNOT_RRTYPE_SOA);
const knot_rdataset_t *soa = node_rdataset(update->new_cont->apex, KNOT_RRTYPE_SOA);
if (soa == NULL) {
return KNOT_EINVAL;
}
......@@ -376,39 +376,54 @@ int knot_zone_create_nsec_chain(const zone_contents_t *zone,
uint32_t nsec_ttl = knot_soa_minimum(soa);
dnssec_nsec3_params_t params = nsec3param_init(ctx->policy, ctx->zone);
int ret = update_nsec3param(zone, changeset, &params);
changeset_t ch;
int ret = changeset_init(&ch, update->new_cont->apex->owner);
if (ret != KNOT_EOK) {
return ret;
}
ret = update_nsec3param(update->new_cont, &ch, &params);
if (ret != KNOT_EOK) {
goto cleanup;
}
// beware this is a hack: we need to guess correct apex type bitmap
// but it can change during zone signing.
bool apex_has_cds = zone_has_key_sbm(ctx);
if (ctx->policy->nsec3_enabled) {
int ret = knot_nsec3_create_chain(zone, &params, nsec_ttl,
apex_has_cds, changeset);
ret = knot_nsec3_create_chain(update->new_cont, &params, nsec_ttl,
apex_has_cds, &ch);
if (ret != KNOT_EOK) {
return ret;
goto cleanup;
}
} else {
int ret = knot_nsec_create_chain(zone, nsec_ttl, apex_has_cds, changeset);
int ret = knot_nsec_create_chain(update->new_cont, nsec_ttl, apex_has_cds, &ch);
if (ret != KNOT_EOK) {
return ret;
goto cleanup;
}
ret = delete_nsec3_chain(zone, changeset);
ret = delete_nsec3_chain(update->new_cont, &ch);
if (ret != KNOT_EOK) {
return ret;
goto cleanup;
}
// Mark removed NSEC3 nodes, so that they are not signed later.
ret = mark_removed_nsec3(zone, changeset);
ret = mark_removed_nsec3(update->new_cont, &ch);
if (ret != KNOT_EOK) {
return ret;
goto cleanup;
}
}
// Sign newly created records right away.
return knot_zone_sign_nsecs_in_changeset(zone_keys, ctx, changeset);
if (sign_nsec_chain) {
ret = knot_zone_sign_nsecs_in_changeset(zone_keys, ctx, &ch);
}
if (ret == KNOT_EOK) {
ret = zone_update_apply_changeset(update, &ch);
}
cleanup:
changeset_clear(&ch);
return ret;
}
/* 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
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief Interface for generating of NSEC/NSEC3 records in zone.
*
* \addtogroup dnssec
* @{
*/
#pragma once
......@@ -29,6 +21,7 @@
#include "knot/dnssec/context.h"
#include "knot/dnssec/zone-keys.h"
#include "knot/updates/changesets.h"
#include "knot/updates/zone-update.h"
#include "knot/zone/contents.h"
/*!
......@@ -68,16 +61,14 @@ knot_dname_t *knot_create_nsec3_owner(const knot_dname_t *owner,
/*!
* \brief Create NSEC or NSEC3 chain in the zone.
*
* \param zone Zone for which the NSEC(3) chain will be created.
* \param changeset Changeset into which the changes will be added.
* \param zone_keys Zone keys used for NSEC(3) creation.
* \param policy DNSSEC signing policy.
* \param update Zone Update with current zone contents and to be updated with NSEC chain.
* \param zone_keys Zone keys used for NSEC(3) creation.
* \param policy DNSSEC signing policy.
* \param sign_nsec_chain If true, the created NSEC(3) chain is signed at the end.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_create_nsec_chain(const zone_contents_t *zone,
changeset_t *changeset,
int knot_zone_create_nsec_chain(zone_update_t *update,
const zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx);
/*! @} */
const kdnssec_ctx_t *dnssec_ctx,
bool sign_nsec_chain);
This diff is collapsed.
/* Copyright (C) 2013 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
......@@ -13,67 +13,40 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file zone-sign.h
*
* \author Jan Vcelak <jan.vcelak@nic.cz>
* \author Lubos Slovak <lubos.slovak@nic.cz>
* \author Jan Kadlec <jan.kadlec@nic.cz>
*
* \brief Interface for DNSSEC signing of zones.
*
* \addtogroup dnssec
* @{
*/
#pragma once
#include "knot/updates/changesets.h"
#include "knot/updates/zone-update.h"
#include "knot/zone/zone.h"
#include "knot/zone/contents.h"
#include "knot/dnssec/context.h"
#include "knot/dnssec/zone-events.h"
#include "knot/dnssec/zone-keys.h"
/*!
* \brief Update zone signatures and store performed changes in changeset.
* \brief Update zone signatures and store performed changes in update.
*
* Updates RRSIGs, NSEC(3)s, and DNSKEYs.
*
* \param zone Zone to be signed.
* \param update Zone Update containing the zone and to be updated with new DNSKEYs and RRSIGs.
* \param zone_keys Zone keys.
* \param dnssec_ctx DNSSEC context.
* \param changeset Changeset to be updated.
* \param expire_at Time, when the oldest signature in the zone expires.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_sign(const zone_contents_t *zone,
int knot_zone_sign(zone_update_t *update,
zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx,
changeset_t *out_ch, knot_time_t *expire_at);
/*!
* \brief Update and sign SOA and store performed changes in changeset.
*
* \param zone Zone including SOA to be updated.
* \param zone_keys Zone keys.
* \param policy DNSSEC policy.
* \param changeset Changeset to be updated.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_sign_update_soa(const knot_rrset_t *soa, const knot_rrset_t *rrsigs,
const zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx,
changeset_t *changeset);
knot_time_t *expire_at);
/*!
* \brief Check if zone SOA signatures are expired.
*
* \param zone Zone to be signed.
* \param zone_keys Zone keys.
* \param policy DNSSEC policy.
* \param changeset Changeset to be updated.
* \param dnssec_ctx DNSSEC context.
*
* \return True if zone SOA signatures need update, false othewise.
*/
......@@ -81,23 +54,6 @@ bool knot_zone_sign_soa_expired(const zone_contents_t *zone,
const zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx);
/*!
* \brief Sign changeset created by DDNS or zone-diff.
*
* \param zone New zone contents.
* \param in_ch Changeset created bvy DDNS or zone-diff
* \param out_ch New records will be added to this changeset.
* \param zone_keys Keys to use for signing.
* \param policy DNSSEC signing policy.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_sign_changeset(const zone_contents_t *zone,
const changeset_t *in_ch,
changeset_t *out_ch,
const zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx);
/*!
* \brief Sign NSEC/NSEC3 nodes in changeset and update the changeset.
*
......@@ -118,13 +74,52 @@ int knot_zone_sign_nsecs_in_changeset(const zone_keyset_t *zone_keys,
*
* \param node Node containing the RRSet.
* \param rrset RRSet we are checking for.
* \param table Optional hat trie with already signed RRs.
*
* \retval true if should be signed.
*/
bool knot_zone_sign_rr_should_be_signed(const zone_node_t *node,
const knot_rrset_t *rrset);
bool knot_match_key_ds(zone_key_t *key, const knot_rdata_t *rdata);
/*!
* \brief Checks whether a DS record corresponds to a key.
*
* \param key A DNSSEC key in zone.
* \param rdata The DS record rdata.
*
* \return true if corresponds.
*/
bool knot_match_key_ds(zone_key_t *key,
const knot_rdata_t *rdata);
/*!
* \brief Sign updates of the zone, storing new RRSIGs in this update again.
*
* \param update Zone Update structure.
* \param zone_keys Zone keys.
* \param dnssec_ctx DNSSEC context.
* \param expire_at Time, when the oldest signature in the update expires.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_sign_update(zone_update_t *update,
zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx,
knot_time_t *expire_at);
/*! @} */
/*!
* \brief Sign the new SOA record in the Zone Update.
*
* The reason for having this separate is: not updating
* SOA if everything else is unchanged. So, the procedure is
* [refresh_DNSKEY_records]->[recreate_nsec]->[sign_zone]->
* ->[check_unchanged]->[update_soa]->[sign_soa]
*
* \param update Zone Update with new SOA and to be updated with SOA RRSIG.
* \param zone_keys Zone keys.
* \param dnssec_ctx DNSSEC context.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_sign_soa(zone_update_t *update,
const zone_keyset_t *zone_keys,
const kdnssec_ctx_t *dnssec_ctx);
/* 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
......@@ -60,12 +60,6 @@ int event_dnssec(conf_t *conf, zone_t *zone)
{
assert(zone);
changeset_t ch;
int ret = changeset_init(&ch, zone->name);
if (ret != KNOT_EOK) {
goto done;
}
zone_sign_reschedule_t resch = { 0 };
resch.allow_rollover = true;
int sign_flags = 0;
......@@ -80,47 +74,29 @@ int event_dnssec(conf_t *conf, zone_t *zone)
sign_flags = 0;
}
ret = knot_dnssec_zone_sign(zone->contents, &ch, sign_flags, &resch);
zone_update_t up;
int ret = zone_update_init(&up, zone, UPDATE_INCREMENTAL);
if (ret != KNOT_EOK) {
return ret;
}
ret = knot_dnssec_zone_sign(&up, sign_flags, &resch);
if (ret != KNOT_EOK) {
goto done;
}
bool zone_changed = !changeset_empty(&ch);
bool zone_changed = !zone_update_no_change(&up);
if (zone_changed) {
/* Apply change. */
apply_ctx_t a_ctx = { 0 };
apply_init_ctx(&a_ctx, NULL, APPLY_STRICT);
zone_contents_t *new_contents = NULL;
int ret = apply_changeset(&a_ctx, zone->contents, &ch, &new_contents);
ret = zone_update_commit(conf, &up);
if (ret != KNOT_EOK) {
log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)",
knot_strerror(ret));
goto done;
}
/* Write change to journal. */
ret = zone_change_store(conf, zone, &ch);
if (ret != KNOT_EOK) {
log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)",
knot_strerror(ret));
update_rollback(&a_ctx);
update_free_zone(&new_contents);
goto done;
}
/* Switch zone contents. */
zone_contents_t *old_contents = zone_switch_contents(zone, new_contents);
synchronize_rcu();
update_free_zone(&old_contents);
update_cleanup(&a_ctx);
}
// Schedule dependent events
event_dnssec_reschedule(conf, zone, &resch, zone_changed);
done:
changeset_clear(&ch);
zone_update_clear(&up);
return ret;
}
......@@ -78,7 +78,7 @@ int event_load(conf_t *conf, zone_t *zone)
load_post:
/* Post load actions - calculate delta, sign with DNSSEC... */
/*! \todo issue #242 dnssec signing should occur in the special event */
ret = zone_load_post(conf, zone, contents, &dnssec_refresh);
ret = zone_load_post(conf, zone, &contents, &dnssec_refresh);
if (ret != KNOT_EOK) {
goto fail;
}
......
/* Copyright (C) 2015 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
......@@ -18,6 +18,8 @@
#include "dnssec/random.h"
#include "knot/common/log.h"
#include "knot/dnssec/zone-events.h"
#include "knot/events/log.h"
#include "knot/query/capture.h"
#include "knot/query/requestor.h"
#include "knot/nameserver/update.h"
......@@ -154,6 +156,21 @@ static int process_normal(conf_t *conf, zone_t *zone, list_t *requests)
return ret;
}
// Sign update.
conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, zone->name);
bool dnssec_enable = (up.flags & UPDATE_SIGN) && conf_bool(&val);
if (dnssec_enable) {
zone_sign_reschedule_t resch = { 0 };
ret = knot_dnssec_sign_update(&up, &resch);
if (ret != KNOT_EOK) {
zone_update_clear(&up);
set_rcodes(requests, KNOT_RCODE_SERVFAIL);
return ret;
}
log_dnssec_next(zone->name, (time_t)resch.next_sign);
zone_events_schedule_at(zone, ZONE_EVENT_DNSSEC, (time_t)resch.next_sign);
}