Commit 459dab34 authored by Jan Včelák's avatar Jan Včelák 🚀

DNSSEC: extract policy and zone keys to separate files

parent 3c8654a3
......@@ -168,10 +168,13 @@ libknot_la_SOURCES = \
libknot/dnssec/nsec-bitmap.h \
libknot/dnssec/nsec3.c \
libknot/dnssec/nsec3.h \
libknot/dnssec/policy.h \
libknot/dnssec/sig0.c \
libknot/dnssec/sig0.h \
libknot/dnssec/sign.c \
libknot/dnssec/sign.h \
libknot/dnssec/zone-keys.c \
libknot/dnssec/zone-keys.h \
libknot/dnssec/zone-nsec.c \
libknot/dnssec/zone-nsec.h \
libknot/dnssec/zone-sign.c \
......
/* Copyright (C) 2011 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/>.
*/
/*!
* \file policy.h
*
* \author Jan Vcelak <jan.vcelak@nic.cz>
*
* \brief Policy for handling of DNSSEC signatures and keys.
*
* \addtogroup dnssec
* @{
*/
#ifndef _KNOT_DNSSEC_POLICY_H_
#define _KNOT_DNSSEC_POLICY_H_
typedef struct {
uint32_t now; //! Current time.
uint32_t sign_lifetime; //! Signature life time.
uint32_t sign_refresh; //! Signature refresh time before expiration.
} knot_dnssec_policy_t;
#define DEFAULT_DNSSEC_POLICY { .now = time_now(), .sign_lifetime = 2592000, \
.sign_refresh = 7200 }
#endif // _KNOT_DNSSEC_POLICY_H_
/*! @} */
/* Copyright (C) 2011 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 <config.h>
#include <assert.h>
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h> // TMP
#include "common/errcode.h"
#include "libknot/dname.h"
#include "libknot/dnssec/sign.h"
#include "libknot/dnssec/zone-keys.h"
/*!
* \brief Check if the key is in active period.
*/
static bool is_current_key(const knot_key_params_t *key)
{
time_t now = time(NULL);
if (now < key->time_activate)
return false;
if (key->time_inactive && now > key->time_inactive)
return false;
return true;
}
/*!
* \brief Load zone keys from a key directory.
*
* \todo Remove fprintf()
* \todo Check for duplicate key tags
* \todo Maybe use dynamic list instead of fixed size array.
*/
int load_zone_keys(const char *keydir_name, const knot_dname_t *zone_name,
knot_zone_keys_t *keys)
{
assert(keydir_name);
assert(zone_name);
assert(keys);
DIR *keydir = opendir(keydir_name);
if (!keydir)
return KNOT_DNSSEC_EINVALID_KEY;
struct dirent entry_buf = { 0 };
struct dirent *entry = NULL;
while (keys->count < KNOT_MAX_ZONE_KEYS &&
readdir_r(keydir, &entry_buf, &entry) == 0 &&
entry != NULL
) {
if (entry->d_name[0] != 'K')
continue;
char *suffix = strrchr(entry->d_name, '.');
if (!suffix)
continue;
if (strcmp(suffix, ".private") != 0)
continue;
size_t path_len = strlen(keydir_name) + 1
+ strlen(entry->d_name) + 1;
char *path = malloc(path_len * sizeof(char));
if (!path) {
fprintf(stderr, "failed to alloc key path\n");
continue;
}
snprintf(path, path_len, "%s/%s", keydir_name, entry->d_name);
fprintf(stderr, "reading key '%s'\n", path);
knot_key_params_t params = { 0 };
int result = knot_load_key_params(path, &params);
free(path);
if (result != KNOT_EOK) {
fprintf(stderr, "failed to load key params\n");
continue;
}
if (knot_dname_compare(zone_name, params.name) != 0) {
fprintf(stderr, "key for other zone\n");
continue;
}
if (!is_current_key(&params)) {
fprintf(stderr, "key is not active\n");
continue;
}
if (knot_get_key_type(&params) != KNOT_KEY_DNSSEC) {
fprintf(stderr, "not a DNSSEC key\n");
continue;
}
result = knot_dnssec_key_from_params(&params, &keys->keys[keys->count]);
if (result != KNOT_EOK) {
fprintf(stderr, "cannot create the dnssec key\n");
continue;
}
fprintf(stderr, "key is valid\n");
fprintf(stderr, "key is %s\n", params.flags & 1 ? "ksk" : "zsk");
keys->is_ksk[keys->count] = params.flags & 1;
keys->count += 1;
}
closedir(keydir);
return keys->count > 0 ? KNOT_EOK : KNOT_DNSSEC_EINVALID_KEY;
}
/* Copyright (C) 2011 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/>.
*/
/*!
* \file zone-keys.h
*
* \author Jan Vcelak <jan.vcelak@nic.cz>
*
* \brief Loading of zone keys.
*
* \addtogroup dnssec
* @{
*/
#ifndef _KNOT_DNSSEC_ZONE_KEYS_H_
#define _KNOT_DNSSEC_ZONE_KEYS_H_
#include <stdbool.h>
#include "libknot/dname.h"
#include "libknot/dnssec/sign.h"
/*!
* Maximal count of active keys for one zone.
*/
#define KNOT_MAX_ZONE_KEYS 8
/*!
* \brief Keys used for zone signing.
*/
typedef struct {
int count;
knot_dnssec_key_t keys[KNOT_MAX_ZONE_KEYS];
knot_dnssec_sign_context_t *contexts[KNOT_MAX_ZONE_KEYS];
bool is_ksk[KNOT_MAX_ZONE_KEYS];
} knot_zone_keys_t;
/*!
* \brief Load zone keys from a key directory.
*
* \param keydir_name Name of the directory with DNSSEC keys.
* \param zone_name Domain name of the zone.
* \param keys Structure with loaded keys.
*
* \return Error code, KNOT_EOK if successful.
*/
int load_zone_keys(const char *keydir_name, const knot_dname_t *zone_name,
knot_zone_keys_t *keys);
#endif // _KNOT_DNSSEC_ZONE_KEYS_H_
/*! @} */
......@@ -16,7 +16,6 @@
#include <config.h>
#include <assert.h>
#include <dirent.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h> // TMP
......@@ -27,29 +26,16 @@
#include "common/hattrie/hat-trie.h"
#include "libknot/dname.h"
#include "libknot/dnssec/key.h"
#include "libknot/dnssec/policy.h"
#include "libknot/dnssec/sign.h"
#include "libknot/dnssec/zone-keys.h"
#include "libknot/rrset.h"
#include "libknot/updates/changesets.h"
#include "libknot/zone/node.h"
#include "libknot/zone/zone-contents.h"
//! \todo Check if defined elsewhere.
#define MAX_RR_WIREFORMAT_SIZE (64 * 1024 * sizeof(uint8_t))
#define MAX_ZONE_KEYS 8
typedef struct {
int count;
knot_dnssec_key_t keys[MAX_ZONE_KEYS];
knot_dnssec_sign_context_t *contexts[MAX_ZONE_KEYS];
bool is_ksk[MAX_ZONE_KEYS];
} knot_zone_keys_t;
typedef struct {
uint32_t now; //! Current time.
uint32_t sign_lifetime; //! Signature life time.
uint32_t sign_refresh; //! Signature refresh time before expiration.
} knot_dnssec_policy_t;
#define DEFAULT_DNSSEC_POLICY { .now = time_now(), .sign_lifetime = 2592000, .sign_refresh = 7200 }
static uint32_t time_now(void)
{
......@@ -316,7 +302,7 @@ static int add_missing_rrsigs(const knot_rrset_t *covered,
return KNOT_EOK;
}
static int sign_rrsets(const knot_rrset_t **rrsets, size_t rrset_count,
static int sign_rrsets(knot_rrset_t **rrsets, size_t rrset_count,
knot_zone_keys_t *zone_keys,
const knot_dnssec_policy_t *policy,
knot_changeset_t *changeset)
......@@ -387,100 +373,6 @@ static int zone_tree_sign(knot_zone_tree_t *tree, knot_zone_keys_t *zone_keys,
return result;
}
static bool is_current_key(const knot_key_params_t *key)
{
time_t now = time(NULL);
if (now < key->time_activate)
return false;
if (key->time_inactive && now > key->time_inactive)
return false;
return true;
}
static int load_zone_keys(const char *keydir_name,
const knot_dname_t *zone_name,
knot_zone_keys_t *keys)
{
assert(keydir_name);
assert(zone_name);
assert(keys);
DIR *keydir = opendir(keydir_name);
if (!keydir)
return KNOT_DNSSEC_EINVALID_KEY;
struct dirent entry_buf = { 0 };
struct dirent *entry = NULL;
while (keys->count < MAX_ZONE_KEYS &&
readdir_r(keydir, &entry_buf, &entry) == 0 &&
entry != NULL
) {
if (entry->d_name[0] != 'K')
continue;
char *suffix = strrchr(entry->d_name, '.');
if (!suffix)
continue;
if (strcmp(suffix, ".private") != 0)
continue;
size_t path_len = strlen(keydir_name) + 1
+ strlen(entry->d_name) + 1;
char *path = malloc(path_len * sizeof(char));
if (!path) {
fprintf(stderr, "failed to alloc key path\n");
continue;
}
snprintf(path, path_len, "%s/%s", keydir_name, entry->d_name);
fprintf(stderr, "reading key '%s'\n", path);
knot_key_params_t params = { 0 };
int result = knot_load_key_params(path, &params);
free(path);
if (result != KNOT_EOK) {
fprintf(stderr, "failed to load key params\n");
continue;
}
if (knot_dname_compare(zone_name, params.name) != 0) {
fprintf(stderr, "key for other zone\n");
continue;
}
if (!is_current_key(&params)) {
fprintf(stderr, "key is not active\n");
continue;
}
if (knot_get_key_type(&params) != KNOT_KEY_DNSSEC) {
fprintf(stderr, "not a DNSSEC key\n");
continue;
}
result = knot_dnssec_key_from_params(&params, &keys->keys[keys->count]);
if (result != KNOT_EOK) {
fprintf(stderr, "cannot create the dnssec key\n");
continue;
}
fprintf(stderr, "key is valid\n");
fprintf(stderr, "key is %s\n", params.flags & 1 ? "ksk" : "zsk");
keys->is_ksk[keys->count] = params.flags & 1;
keys->count += 1;
}
closedir(keydir);
return keys->count > 0 ? KNOT_EOK : KNOT_DNSSEC_EINVALID_KEY;
}
static void free_sign_contexts(knot_zone_keys_t *keys)
{
for (int i = 0; i < keys->count; i++) {
......@@ -516,8 +408,7 @@ int knot_zone_sign(const knot_zone_contents_t *zone, const char *keydir,
knot_dnssec_policy_t policy = DEFAULT_DNSSEC_POLICY;
knot_zone_keys_t zone_keys;
memset(&zone_keys, '\0', sizeof(zone_keys));
knot_zone_keys_t zone_keys = { '\0' };
result = load_zone_keys(keydir, zone->apex->owner, &zone_keys);
if (result != KNOT_EOK) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment