Skip to content
Snippets Groups Projects
Commit e2b10948 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman
Browse files

mod-online-sign: update to policy-based configuration

This is achieved by using more procedures from normal signing.
parent 7324bcfa
No related branches found
No related tags found
1 merge request!620dnssec: online signing can use both current and legacy keystore config
/* 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
......@@ -203,6 +203,12 @@ int kdnssec_kasp_init(kdnssec_ctx_t *ctx, const char *kasp_path, const char *zon
return r;
}
// Overide policy name if provided.
if (ctx->policy_name != NULL) {
free(ctx->zone->policy);
ctx->zone->policy = strdup(ctx->policy_name);
}
r = dnssec_kasp_policy_load(ctx->kasp, ctx->zone->policy, &ctx->policy);
if (r != DNSSEC_EOK) {
return r;
......@@ -218,6 +224,7 @@ void kdnssec_ctx_deinit(kdnssec_ctx_t *ctx)
return;
}
free(ctx->policy_name);
dnssec_keystore_deinit(ctx->keystore);
dnssec_kasp_policy_free(ctx->policy);
dnssec_kasp_zone_free(ctx->zone);
......@@ -226,26 +233,29 @@ void kdnssec_ctx_deinit(kdnssec_ctx_t *ctx)
memset(ctx, 0, sizeof(*ctx));
}
int kdnssec_ctx_init(kdnssec_ctx_t *ctx, const knot_dname_t *zone_name)
int kdnssec_ctx_init(kdnssec_ctx_t *ctx, const knot_dname_t *zone_name,
conf_val_t *policy, bool disable_legacy)
{
if (ctx == NULL || zone_name == NULL) {
return KNOT_EINVAL;
}
// Check for legacy configuration.
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_POLICY, zone_name);
bool legacy = val.code != KNOT_EOK;
kdnssec_ctx_t new_ctx = {
.legacy = legacy
};
char zone_str[KNOT_DNAME_TXT_MAXLEN + 1];
if (knot_dname_to_str(zone_str, zone_name, sizeof(zone_str)) == NULL) {
return KNOT_ENOMEM;
}
val = conf_zone_get(conf(), C_STORAGE, zone_name);
kdnssec_ctx_t new_ctx = { 0 };
if (!disable_legacy && policy->code != KNOT_EOK) {
new_ctx.legacy = true;
}
if (conf_str(policy) != NULL) {
new_ctx.policy_name = strdup(conf_str(policy));
}
conf_val_t val = conf_zone_get(conf(), C_STORAGE, zone_name);
char *storage = conf_abs_path(&val, NULL);
val = conf_zone_get(conf(), C_KASP_DB, zone_name);
char *kasp_path = conf_abs_path(&val, storage);
......
/* 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
......@@ -21,6 +21,7 @@
#include <dnssec/kasp.h>
#include <dnssec/keystore.h>
#include "knot/conf/conf.h"
#include "libknot/dname.h"
/*!
......@@ -30,6 +31,8 @@ struct kdnssec_ctx {
time_t now;
bool legacy;
char *policy_name;
dnssec_kasp_t *kasp;
dnssec_kasp_zone_t *zone;
dnssec_kasp_policy_t *policy;
......@@ -57,10 +60,13 @@ int kdnssec_kasp_init(kdnssec_ctx_t *ctx, const char *kasp_path, const char *zon
/*!
* \brief Initialize DNSSEC signing context.
*
* \param ctx Signing context to be initialized.
* \param zone_name Name of the zone.
* \param ctx Signing context to be initialized.
* \param zone_name Name of the zone.
* \param policy DNSSEC policy configuration reference.
* \param disable_legacy Disable legacy detection indication.
*/
int kdnssec_ctx_init(kdnssec_ctx_t *ctx, const knot_dname_t *zone_name);
int kdnssec_ctx_init(kdnssec_ctx_t *ctx, const knot_dname_t *zone_name,
conf_val_t *policy, bool disable_legacy);
/*!
* \brief Cleanup DNSSEC signing context.
......
/* 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
......@@ -38,7 +38,9 @@ static int sign_init(const zone_contents_t *zone, int flags, kdnssec_ctx_t *ctx)
const knot_dname_t *zone_name = zone->apex->owner;
int r = kdnssec_ctx_init(ctx, zone_name);
conf_val_t policy = conf_zone_get(conf(), C_DNSSEC_POLICY, zone_name);
int r = kdnssec_ctx_init(ctx, zone_name, &policy, false);
if (r != KNOT_EOK) {
return r;
}
......@@ -77,9 +79,13 @@ static dnssec_event_ctx_t kctx2ctx(const kdnssec_ctx_t *kctx)
return ctx;
}
static int sign_process_events(const knot_dname_t *zone_name,
const kdnssec_ctx_t *kctx)
int knot_dnssec_sign_process_events(const kdnssec_ctx_t *kctx,
const knot_dname_t *zone_name)
{
if (kctx == NULL || zone_name == NULL) {
return KNOT_EINVAL;
}
dnssec_event_t event = { 0 };
dnssec_event_ctx_t ctx = kctx2ctx(kctx);
......@@ -166,7 +172,7 @@ int knot_dnssec_zone_sign(zone_contents_t *zone, changeset_t *out_ch,
goto done;
}
result = sign_process_events(zone_name, &ctx);
result = knot_dnssec_sign_process_events(&ctx, zone_name);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to process events (%s)",
knot_strerror(result));
......
/* 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,23 +13,12 @@
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-events.h
*
* \author Jan Vcelak <jan.vcelak@nic.cz>
* \author Lubos Slovak <lubos.slovak@nic.cz>
* \author Jan Kadlec <jan.kadlec@nic.cz>
*
* \brief DNSSEC operations triggered on zone events.
*
* \addtogroup dnssec
* @{
*/
#pragma once
#include "knot/zone/zone.h"
#include "knot/updates/changesets.h"
#include "knot/dnssec/context.h"
enum zone_sign_flags {
ZONE_SIGN_NONE = 0,
......@@ -39,6 +28,17 @@ enum zone_sign_flags {
typedef enum zone_sign_flags zone_sign_flags_t;
/*!
* \brief Generate/rollover keys in keystore as needed.
*
* \param kctx Pointers to the keytore, policy, etc.
* \param zone_name Zone name.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_dnssec_sign_process_events(const kdnssec_ctx_t *kctx,
const knot_dname_t *zone_name);
/*!
* \brief DNSSEC resign zone, store new records into changeset. Valid signatures
* and NSEC(3) records will not be changed.
......@@ -67,5 +67,3 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
const changeset_t *in_ch,
changeset_t *out_ch,
uint32_t *refresh_at);
/*! @} */
/* 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
......@@ -15,16 +15,25 @@
*/
#include <assert.h>
#include <stddef.h>
#include "dnssec/error.h"
#include "dnssec/kasp.h"
#include "dnssec/sign.h"
#include "dnssec/nsec.h"
#include "contrib/string.h"
#include "knot/modules/online_sign/online_sign.h"
#include "knot/modules/online_sign/nsec_next.h"
#include "knot/dnssec/rrset-sign.h"
#include "knot/dnssec/zone-keys.h"
#include "knot/dnssec/zone-events.h"
#define MOD_POLICY C_POLICY
const yp_item_t scheme_mod_online_sign[] = {
{ C_ID, YP_TSTR, YP_VNONE },
{ MOD_POLICY, YP_TREF, YP_VREF = { C_POLICY }, YP_FNONE, { check_ref_dflt } },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
#define module_zone_error(zone, msg...) \
MODULE_ZONE_ERR(C_MOD_ONLINE_SIGN, zone, msg)
......@@ -66,13 +75,9 @@ static const uint16_t NSEC_FORCE_TYPES[] = {
0
};
const yp_item_t scheme_mod_online_sign[] = {
{ C_ID, YP_TSTR, YP_VNONE },
{ NULL }
};
typedef struct {
dnssec_key_t *key;
uint32_t rrsig_lifetime;
} online_sign_ctx_t;
static bool want_dnssec(struct query_data *qdata)
......@@ -247,7 +252,7 @@ static knot_rrset_t *sign_rrset(const knot_dname_t *owner,
// compatible context
dnssec_kasp_policy_t policy = {
.rrsig_lifetime = RRSIG_LIFETIME
.rrsig_lifetime = module_ctx->rrsig_lifetime
};
kdnssec_ctx_t ksign_ctx = {
......@@ -421,63 +426,26 @@ static int synth_answer(int state, knot_pkt_t *pkt, struct query_data *qdata, vo
return state;
}
static int get_online_key(dnssec_key_t **key_ptr, const knot_dname_t *zone_name,
const char *kasp_path)
static int get_online_key(dnssec_key_t **key_ptr, struct query_module *module)
{
dnssec_kasp_t *kasp = NULL;
dnssec_kasp_zone_t *zone = NULL;
dnssec_kasp_policy_t *policy = NULL;
dnssec_kasp_keystore_t *kasp_keystore = NULL;
dnssec_keystore_t *keystore = NULL;
// KASP database
int r = dnssec_kasp_init_dir(&kasp);
if (r != DNSSEC_EOK) {
goto fail;
}
r = dnssec_kasp_open(kasp, kasp_path);
if (r != DNSSEC_EOK) {
goto fail;
}
// KASP zone
char *zone_str = knot_dname_to_str_alloc(zone_name);
if (!zone_str) {
r = KNOT_ENOMEM;
goto fail;
}
r = dnssec_kasp_zone_load(kasp, zone_str, &zone);
free(zone_str);
if (r != DNSSEC_EOK) {
goto fail;
}
kdnssec_ctx_t kctx = { 0 };
// KASP keystore
conf_val_t policy = conf_mod_get(module->config, MOD_POLICY, module->id);
const char *policy_id = dnssec_kasp_zone_get_policy(zone);
r = dnssec_kasp_policy_load(kasp, policy_id, &policy);
int r = kdnssec_ctx_init(&kctx, module->zone, &policy, true);
if (r != DNSSEC_EOK) {
goto fail;
}
r = dnssec_kasp_keystore_load(kasp, policy->keystore, &kasp_keystore);
if (r != DNSSEC_EOK) {
goto fail;
}
// Force Singe-Type signing scheme.
kctx.policy->singe_type_signing = true;
r = dnssec_kasp_keystore_open(kasp, kasp_keystore->backend,
kasp_keystore->config, &keystore);
r = knot_dnssec_sign_process_events(&kctx, module->zone);
if (r != DNSSEC_EOK) {
goto fail;
}
// DNSSEC key
dnssec_list_t *list = dnssec_kasp_zone_get_keys(zone);
dnssec_list_t *list = dnssec_kasp_zone_get_keys(kctx.zone);
assert(list);
dnssec_item_t *item = dnssec_list_nth(list, 0);
if (!item) {
......@@ -494,7 +462,7 @@ static int get_online_key(dnssec_key_t **key_ptr, const knot_dname_t *zone_name,
goto fail;
}
r = dnssec_key_import_keystore(key, keystore, kasp_key->id);
r = dnssec_key_import_keystore(key, kctx.keystore, kasp_key->id);
if (r != DNSSEC_EOK) {
dnssec_key_free(key);
goto fail;
......@@ -503,11 +471,7 @@ static int get_online_key(dnssec_key_t **key_ptr, const knot_dname_t *zone_name,
*key_ptr = key;
fail:
dnssec_keystore_deinit(keystore);
dnssec_kasp_keystore_free(kasp_keystore);
dnssec_kasp_policy_free(policy);
dnssec_kasp_zone_free(zone);
dnssec_kasp_deinit(kasp);
kdnssec_ctx_deinit(&kctx);
return r;
}
......@@ -519,58 +483,46 @@ static void online_sign_ctx_free(online_sign_ctx_t *ctx)
free(ctx);
}
static int online_sign_ctx_new(online_sign_ctx_t **ctx_ptr,
const knot_dname_t *zone, const char *kasp_path)
static int online_sign_ctx_new(online_sign_ctx_t **ctx_ptr, struct query_module *module)
{
online_sign_ctx_t *ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
return KNOT_ENOMEM;
}
int r = get_online_key(&ctx->key, zone, kasp_path);
int r = get_online_key(&ctx->key, module);
if (r != KNOT_EOK) {
online_sign_ctx_free(ctx);
return r;
}
ctx->rrsig_lifetime = RRSIG_LIFETIME;
conf_val_t policy = conf_mod_get(module->config, MOD_POLICY, module->id);
if (policy.code == KNOT_EOK) {
conf_val_t val = conf_id_get(module->config, C_POLICY, C_RRSIG_LIFETIME, &policy);
if (val.code == KNOT_EOK) {
ctx->rrsig_lifetime = conf_int(&val);
}
}
*ctx_ptr = ctx;
return KNOT_EOK;
}
static char *conf_kasp_path(const knot_dname_t *zone)
{
conf_val_t val;
val = conf_zone_get(conf(), C_STORAGE, zone);
char *storage = conf_abs_path(&val, NULL);
val = conf_zone_get(conf(), C_KASP_DB, zone);
char *kasp_db = conf_abs_path(&val, storage);
free(storage);
return kasp_db;
}
int online_sign_load(struct query_module *module)
{
assert(module);
assert(module->zone);
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, module->zone);
conf_val_t val = conf_zone_get(module->config, C_DNSSEC_SIGNING, module->zone);
if (conf_bool(&val)) {
module_zone_error(module->zone, "incompatible with automatic signing");
return KNOT_ENOTSUP;
}
char *kasp_path = conf_kasp_path(module->zone);
if (!kasp_path) {
module_zone_error(module->zone, "KASP database is not configured");
return KNOT_ERROR;
}
online_sign_ctx_t *ctx = NULL;
int r = online_sign_ctx_new(&ctx, module->zone, kasp_path);
free(kasp_path);
int r = online_sign_ctx_new(&ctx, module);
if (r != KNOT_EOK) {
module_zone_error(module->zone, "failed to initialize signing key (%s)",
dnssec_strerror(r));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment