Commit 573569a1 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'fix_offline_ksk' into 'master'

Fix offline ksk

See merge request !961
parents 8060b902 7da7c084
......@@ -130,8 +130,9 @@ owned by both zones equally.
\fBpregenerate\fP \fItimestamp\fP
Pre\-generate ZSKs for use with offline KSK, for the specified period starting from now.
.TP
\fBshow\-offline\fP \fItimestamp\fP
Print pre\-generated offline key\-related records for specified timestamp.
\fBshow\-offline\fP \fItimestamp\-from\fP [\fItimestamp\-to\fP]
Print pre\-generated offline key\-related records for specified time interval. If \fItimestamp_to\fP
is omitted, it will be to infinity.
.TP
\fBdel\-offline\fP \fItimestamp\-from\fP \fItimestamp\-to\fP
Delete pre\-generated offline key\-related records in specified time interval.
......@@ -139,7 +140,7 @@ Delete pre\-generated offline key\-related records in specified time interval.
\fBdel\-all\-old\fP
Delete old keys that are in state \(aqremoved\(aq.
.TP
\fBgenerate\-ksr\fP \fItimestamp\fP
\fBgenerate\-ksr\fP \fItimestamp\-from\fP \fItimestamp\-to\fP
Print to stdout KeySigningRequest based on pre\-generated ZSKs for specified period.
.TP
\fBsign\-ksr\fP \fIksr_file\fP
......@@ -147,7 +148,9 @@ Read KeySigingRequest from a text file, sign it using local keyset and print Sig
.TP
\fBimport\-skr\fP \fIskr_file\fP
Read SignedKeyResponse from a text file and import the signatures for later use in zone. (The signatures
are not at all checked at import time, but they will be ignored at signing time if invalid.)
are not checked at import time, but they will be ignored at signing time if invalid.) If some
signatures have already been imported, they will be deleted for the period from beginning of the SKR
to infinity.
.UNINDENT
.SS Generate arguments
.sp
......
......@@ -608,6 +608,7 @@ policy:
zsk\-size: SIZE
ksk\-shared: BOOL
dnskey\-ttl: TIME
zone\-max\-ttl: TIME
zsk\-lifetime: TIME
ksk\-lifetime: TIME
propagation\-delay: TIME
......@@ -704,6 +705,19 @@ A TTL value for DNSKEY records added into zone apex.
Has infuence over ZSK key lifetime.
.UNINDENT
.UNINDENT
.SS zone\-max\-ttl
.sp
Maximal TTL value among all the records in zone.
.sp
\fBNOTE:\fP
.INDENT 0.0
.INDENT 3.5
It\(aqs generally recommended to override the maximal TTL computation by setting this
explicitly whenever possible. It\(aqs required for DNSSEC Offline KSK\&.
.UNINDENT
.UNINDENT
.sp
\fIDefault:\fP computed after zone is loaded
.SS zsk\-lifetime
.sp
A period between ZSK publication and the next rollover initiation.
......
......@@ -107,8 +107,9 @@ Commands related to Offline KSK feature
**pregenerate** *timestamp*
Pre-generate ZSKs for use with offline KSK, for the specified period starting from now.
**show-offline** *timestamp*
Print pre-generated offline key-related records for specified timestamp.
**show-offline** *timestamp-from* [*timestamp-to*]
Print pre-generated offline key-related records for specified time interval. If *timestamp_to*
is omitted, it will be to infinity.
**del-offline** *timestamp-from* *timestamp-to*
Delete pre-generated offline key-related records in specified time interval.
......@@ -116,7 +117,7 @@ Commands related to Offline KSK feature
**del-all-old**
Delete old keys that are in state 'removed'.
**generate-ksr** *timestamp*
**generate-ksr** *timestamp-from* *timestamp-to*
Print to stdout KeySigningRequest based on pre-generated ZSKs for specified period.
**sign-ksr** *ksr_file*
......@@ -124,7 +125,9 @@ Commands related to Offline KSK feature
**import-skr** *skr_file*
Read SignedKeyResponse from a text file and import the signatures for later use in zone. (The signatures
are not at all checked at import time, but they will be ignored at signing time if invalid.)
are not checked at import time, but they will be ignored at signing time if invalid.) If some
signatures have already been imported, they will be deleted for the period from beginning of the SKR
to infinity.
Generate arguments
..................
......
......@@ -652,11 +652,14 @@ For the ZSK side (i.e. the operator of the DNS server), the pre-requisites are:
- properly configured :ref:`DNSSEC policy <Policy section>` (e.g. :ref:`zsk-lifetime <policy_zsk-lifetime>`),
- :ref:`manual <policy_manual>` set to `on`
- :ref:`offline-ksk <policy_offline-ksk>` set to `on`
- :ref:`dnskey-ttl <policy_dnskey-ttl>` and :ref:`zone-max-ttl <policy_zone-max-ttl>` set up explicitly
- a complete KASP DB with just ZSK(s)
For the KSK side (i.e. the operator of the KSK signer), the pre-requisites are:
- Knot configuration equal to the ZSK side (at least the :ref:`Policy section` must be identical)
- Knot configuration equal to the ZSK side (at least relevant parts of corresponding
:ref:`policy <Policy section>`, :ref:`zone <Zone section>`, and :ref:`template <Template section>`
sections must be identical)
- a KASP DB with the KSK(s)
Generating and signing future ZSKs
......@@ -673,15 +676,15 @@ Generating and signing future ZSKs
they would be generated in case of automatic key management.
2. Use the ``keymgr generate-ksr`` command on the ZSK side to export the public parts of the future ZSKs in a form
similar to DNSKEY records. Use the same time period as in the first step::
similar to DNSKEY records. You might use the same time period as in the first step::
$ keymgr -c /path/to/ZSK/side.conf example.com. generate-ksr +6mo
$ keymgr -c /path/to/ZSK/side.conf example.com. generate-ksr +0 +6mo > /path/to/ksr/file
Save the output of the command (called the Key Signing Request or KSR) to a file and transfer it to the KSK side e.g. via e-mail.
3. Use the ``keymgr sign-ksr`` command on the KSK side with the KSR file from the previous step as a parameter::
$ keymgr -c /path/to/KSK/side.conf example.com. sign-ksr /path/to/ksr/file
$ keymgr -c /path/to/KSK/side.conf example.com. sign-ksr /path/to/ksr/file > /path/to/skr/file
This creates all the future forms of the DNSKEY, CDNSKEY and CSK records and all the respective RRSIGs and prints them on output. Save
the output of the command (called the Signed Key Response or SKR) to a file and transfer it back to the ZSK side.
......@@ -697,7 +700,9 @@ Generating and signing future ZSKs
6. Now the future ZSKs and DNSKEY records with signatures are ready in KASP DB for later usage.
Knot automatically uses them in correct time intervals.
The entire procedure must to be repeated before the time period selected at the beginning passes.
The entire procedure must to be repeated before the time period selected at the beginning passes,
or whenever a configuration is changed significantly. Over-importing new SKR across some previously-imported
one leads to deleting the old offline records.
.. _DNSSEC Export Import KASP DB:
......
......@@ -672,6 +672,7 @@ DNSSEC policy configuration.
zsk-size: SIZE
ksk-shared: BOOL
dnskey-ttl: TIME
zone-max-ttl: TIME
zsk-lifetime: TIME
ksk-lifetime: TIME
propagation-delay: TIME
......@@ -773,6 +774,8 @@ If enabled, all zones with this policy assigned will share one KSK.
*Default:* off
.. _policy_dnskey-ttl:
dnskey-ttl
----------
......@@ -783,6 +786,19 @@ A TTL value for DNSKEY records added into zone apex.
.. NOTE::
Has infuence over ZSK key lifetime.
.. _policy_zone-max-ttl:
zone-max-ttl
------------
Maximal TTL value among all the records in zone.
.. NOTE::
It's generally recommended to override the maximal TTL computation by setting this
explicitly whenever possible. It's required for :ref:`DNSSEC Offline KSK`.
*Default:* computed after zone is loaded
.. _policy_zsk-lifetime:
zsk-lifetime
......
......@@ -389,7 +389,7 @@ int knot_time_print(knot_time_print_t format, knot_time_t time, char *dst, size_
struct tm lt;
time_t tt = (time_t)time;
ret = (localtime_r(&tt, &lt) == NULL ? -1 :
strftime(dst, dst_len, "%Y-%m-%dT%H:%M:%S", &lt));
strftime(dst, dst_len, "%Y-%m-%dT%H:%M:%SZ", &lt));
return (ret > 0 ? 0 : -1);
case TIME_PRINT_RELSEC:
ret = snprintf(dst, dst_len, "%+"KNOT_TIMEDIFF_PRINTF,
......
......@@ -249,6 +249,8 @@ static const yp_item_t desc_policy[] = {
CONF_IO_FRLD_ZONES },
{ C_DNSKEY_TTL, YP_TINT, YP_VINT = { 0, UINT32_MAX, YP_NIL, YP_STIME },
CONF_IO_FRLD_ZONES },
{ C_ZONE_MAX_TLL, YP_TINT, YP_VINT = { 0, UINT32_MAX, YP_NIL, YP_STIME },
CONF_IO_FRLD_ZONES },
{ C_ZSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, DAYS(30), YP_STIME },
CONF_IO_FRLD_ZONES },
{ C_KSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME },
......
......@@ -116,6 +116,7 @@
#define C_ZONE "\x04""zone"
#define C_ZONEFILE_LOAD "\x0D""zonefile-load"
#define C_ZONEFILE_SYNC "\x0D""zonefile-sync"
#define C_ZONE_MAX_TLL "\x0C""zone-max-ttl"
#define C_ZSK_LIFETIME "\x0C""zsk-lifetime"
#define C_ZSK_SIZE "\x08""zsk-size"
......
......@@ -58,6 +58,10 @@ static void policy_load(knot_kasp_policy_t *policy, conf_val_t *id)
int64_t ttl = conf_int(&val);
policy->dnskey_ttl = (ttl != YP_NIL) ? ttl : UINT32_MAX;
val = conf_id_get(conf(), C_POLICY, C_ZONE_MAX_TLL, id);
ttl = conf_int(&val);
policy->zone_maximal_ttl = (ttl != YP_NIL) ? ttl : UINT32_MAX;
val = conf_id_get(conf(), C_POLICY, C_ZSK_LIFETIME, id);
policy->zsk_lifetime = conf_int(&val);
......
......@@ -839,7 +839,7 @@ 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, r->rrsig.owner) != 0) {
knot_dname_cmp((const knot_dname_t *)key.data + 1, for_dname) != 0) {
ret = KNOT_ENOENT;
goto cleanup;
}
......
......@@ -107,8 +107,6 @@ typedef struct {
uint32_t nsec3_salt_lifetime;
uint16_t nsec3_iterations;
uint8_t nsec3_salt_length;
// SOA
uint32_t soa_minimal_ttl;
// zone
uint32_t zone_maximal_ttl;
// data propagation delay
......
......@@ -444,7 +444,7 @@ static roll_action_t next_action(kdnssec_ctx_t *ctx, zone_sign_roll_flags_t flag
} // else FALLTHROUGH
case DNSSEC_KEY_STATE_RETIRED:
keytime = knot_time_min(key->timing.retire, key->timing.remove);
keytime = ksk_remove_time(keytime, ctx);;
keytime = zsk_remove_time(keytime, ctx);
restype = REMOVE;
break;
case DNSSEC_KEY_STATE_READY:
......
......@@ -75,7 +75,7 @@ void key_records_clear_rdatasets(key_records_t *r)
knot_rdataset_clear(&r->rrsig.rrs, NULL);
}
int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r)
int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r, bool verbose)
{
if (*buf == NULL) {
if (*buf_size == 0) {
......@@ -86,26 +86,28 @@ int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r)
return KNOT_ENOMEM;
}
}
int ret = KNOT_EOK;
const knot_dump_style_t verb_style = {
.wrap = true,
.show_ttl = true,
.verbose = true,
.original_ttl = true,
.human_tmstamp = true
};
const knot_dump_style_t *style = verbose ? &verb_style : &KNOT_DUMP_STYLE_DEFAULT;
int ret = 0;
size_t total = 1;
const knot_rrset_t *all_rr[4] = { &r->dnskey, &r->cdnskey, &r->cds, &r->rrsig };
// 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;
for (int i = 0; i < 4; i++) {
if (ret >= 0 && !knot_rrset_empty(all_rr[i])) {
ret = knot_rrset_txt_dump(all_rr[i], buf, buf_size, style);
(void)buf;
total += ret;
}
}
if (ret >= 0 && total < *buf_size) {
if (ret >= 0 && total > *buf_size) {
free(*buf);
*buf_size = total;
*buf = malloc(*buf_size);
......@@ -116,21 +118,13 @@ int key_records_dump(char **buf, size_t *buf_size, const key_records_t *r)
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);
for (int i = 0; i < 4; i++) {
if (ret >= 0 && !knot_rrset_empty(all_rr[i])) {
ret = knot_rrset_txt_dump(all_rr[i], &fake_buf, &fake_size, style);
fake_buf += ret, fake_size -= ret;
}
}
assert(fake_buf - *buf == total - 1);
return ret >= 0 ? KNOT_EOK : ret;
}
......
......@@ -27,7 +27,7 @@ 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_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);
......
......@@ -19,12 +19,6 @@
#include "knot/dnssec/policy.h"
#include "libknot/rrtype/soa.h"
static uint32_t zone_soa_min_ttl(const zone_contents_t *zone)
{
knot_rrset_t soa = node_rrset(zone->apex, KNOT_RRTYPE_SOA);
return knot_soa_minimum(soa.rrs.rdata);
}
static uint32_t zone_soa_ttl(const zone_contents_t *zone)
{
knot_rrset_t soa = node_rrset(zone->apex, KNOT_RRTYPE_SOA);
......@@ -37,11 +31,11 @@ void update_policy_from_zone(knot_kasp_policy_t *policy,
assert(policy);
assert(zone);
// Use SOA TTL if not configured.
if (policy->dnskey_ttl == UINT32_MAX) {
policy->dnskey_ttl = zone_soa_ttl(zone);
}
policy->soa_minimal_ttl = zone_soa_min_ttl(zone);
policy->zone_maximal_ttl = zone->max_ttl;
if (policy->zone_maximal_ttl == UINT32_MAX) {
policy->zone_maximal_ttl = zone->max_ttl;
}
}
......@@ -205,6 +205,10 @@ int keymgr_generate_key(kdnssec_ctx_t *ctx, int argc, char *argv[])
return ret;
}
if ((flags & DNSKEY_GENERATE_KSK) && gen_timing.ready == infty) {
gen_timing.ready = gen_timing.active;
}
if (keysize > 0) {
if ((flags & DNSKEY_GENERATE_KSK)) {
ctx->policy->ksk_size = keysize;
......
......@@ -79,13 +79,13 @@ static void print_help(void)
" (syntax: pregenerate <timestamp>)\n"
" presign Pre-generate RRSIG signatures for pregenerated ZSKs.\n"
" (syntax: presign <timestamp>)\n"
" show-offline Print pre-generated offline key-related records for specified timestamp.\n"
" (syntax: show-offline <timestamp>)\n"
" show-offline Print pre-generated offline key-related records for specified time interval (possibly to infinity).\n"
" (syntax: show-offline <from> [<to>])\n"
" del-offline Delete pre-generated offline key-related records in specified time interval.\n"
" (syntax: del-offline <from> <to>)\n"
" del-all-old Delete old keys that are in state 'removed'.\n"
" generate-ksr Print to stdout KeySigningRequest based on pre-generated ZSKS.\n"
" (syntax: generate-ksr <timestamp>)\n"
" (syntax: generate-ksr <from> <to>)\n"
" sign-ksr Read KeySigningRequest from a file, sign it and print SignedKeyResponse to stdout.\n"
" (syntax: sign-ksr <ksr_file>)\n"
" import-skr Import DNSKEY record signatures from a SignedKeyResponse.\n"
......@@ -144,6 +144,13 @@ static int key_command(int argc, char *argv[], int opt_ind)
goto main_end; \
}
#define CHECK_MISSING_ARG2(msg) \
if (argc < 4) { \
printf("%s\n", (msg)); \
ret = KNOT_EINVAL; \
goto main_end; \
}
bool print_ok_on_succes = true;
if (strcmp(argv[1], "generate") == 0) {
ret = keymgr_generate_key(&kctx, argc - 2, argv + 2);
......@@ -227,19 +234,15 @@ static int key_command(int argc, char *argv[], int opt_ind)
ret = keymgr_pregenerate_zsks(&kctx, argv[2]);
} else if (strcmp(argv[1], "show-offline") == 0) {
CHECK_MISSING_ARG("Timestamp not specified");
ret = keymgr_print_offline_records(&kctx, argv[2]);
ret = keymgr_print_offline_records(&kctx, argv[2], argc > 3 ? argv[3] : NULL);
} else if (strcmp(argv[1], "del-offline") == 0) {
if (argc < 4) {
printf("Timestamps from-to not specified\n");
ret = KNOT_EINVAL;
goto main_end;
}
CHECK_MISSING_ARG2("Timestamps from-to not specified");
ret = keymgr_delete_offline_records(&kctx, argv[2], argv[3]);
} else if (strcmp(argv[1], "del-all-old") == 0) {
ret = keymgr_del_all_old(&kctx);
} else if (strcmp(argv[1], "generate-ksr") == 0) {
CHECK_MISSING_ARG("Timestamp not specified");
ret = keymgr_print_ksr(&kctx, argv[2]);
CHECK_MISSING_ARG2("Timestamps from-to not specified");
ret = keymgr_print_ksr(&kctx, argv[2], argv[3]);
print_ok_on_succes = false;
} else if (strcmp(argv[1], "sign-ksr") == 0) {
CHECK_MISSING_ARG("Input file not specified");
......
......@@ -93,9 +93,14 @@ int keymgr_pregenerate_zsks(kdnssec_ctx_t *ctx, char *arg)
ctx->keep_deleted_keys = true;
ctx->policy->manual = false;
if (ctx->policy->dnskey_ttl == UINT32_MAX ||
ctx->policy->zone_maximal_ttl == UINT32_MAX) {
printf("Error: dnskey-ttl and zone-max-ttl not configured.\n");
return KNOT_ESEMCHECK;
}
while (ret == KNOT_EOK && knot_time_cmp(next, upto) <= 0) {
ctx->now = next;
printf("pregenerate %"PRIu64"\n", ctx->now);
ret = pregenerate_once(ctx, &next);
}
......@@ -110,33 +115,53 @@ static int dump_rrset_to_buf(const knot_rrset_t *rrset, char **buf, size_t *buf_
return KNOT_ENOMEM;
}
}
return knot_rrset_txt_dump(rrset, buf, buf_size, &KNOT_DUMP_STYLE_DEFAULT);
knot_dump_style_t style = {
.wrap = true,
.show_ttl = true,
.verbose = true,
.original_ttl = true,
.human_tmstamp = true
};
return knot_rrset_txt_dump(rrset, buf, buf_size, &style);
}
int keymgr_print_offline_records(kdnssec_ctx_t *ctx, char *arg)
static void print_header(const char *of_what, knot_time_t timestamp, const char *contents)
{
knot_time_t when;
int ret = parse_timestamp(arg, &when);
char date[64] = { 0 };
(void)knot_time_print(TIME_PRINT_ISO8601, timestamp, date, sizeof(date));
printf(";; %s %"PRIu64" (%s) =========\n%s", of_what,
timestamp, date, contents);
}
int keymgr_print_offline_records(kdnssec_ctx_t *ctx, char *arg_from, char *arg_to)
{
knot_time_t from = 0, to = 0, next = 0;
int ret = parse_timestamp(arg_from, &from);
if (ret != KNOT_EOK) {
return ret;
}
knot_time_t next = 0;
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 = key_records_dump(&buf, &buf_size, &r);
if (arg_to != NULL) {
ret = parse_timestamp(arg_to, &to);
if (ret != KNOT_EOK) {
return ret;
}
}
char *buf = NULL;
size_t buf_size = 512;
for (knot_time_t i = from; ret == KNOT_EOK && i != 0 && (arg_to == NULL || knot_time_cmp(i, to) < 0); i = next) {
key_records_t r = { { 0 } };
ret = kasp_db_load_offline_records(*ctx->kasp_db, ctx->zone->dname, i, &next, &r);
if (ret == KNOT_EOK) {
printf("%s", buf);
ret = KNOT_EOK;
ret = key_records_dump(&buf, &buf_size, &r, true);
}
free(buf);
printf("; next %"PRIu64"\n", next);
if (ret == KNOT_EOK) {
print_header("Offline records for", i, buf);
}
key_records_clear(&r);
}
key_records_clear(&r);
free(buf);
return ret;
}
......@@ -170,7 +195,7 @@ static void print_generated_message(void)
{
char buf[64] = { 0 };
knot_time_print(TIME_PRINT_ISO8601, knot_time(), buf, sizeof(buf));
printf("generated on %s by KnotDNS %s\n", buf, VERSION);
printf("generated at %s by Knot DNS %s\n", buf, VERSION);
}
static int ksr_once(kdnssec_ctx_t *ctx, char **buf, size_t *buf_size, knot_time_t *next_ksr)
......@@ -183,8 +208,7 @@ static int ksr_once(kdnssec_ctx_t *ctx, char **buf, size_t *buf_size, knot_time_
}
ret = dump_rrset_to_buf(dnskey, buf, buf_size);
if (ret >= 0) {
printf(";; KeySigningRequest %s %"PRIu64" ===========\n%s",
KSR_SKR_VER, ctx->now, *buf);
print_header("KeySigningRequest "KSR_SKR_VER, ctx->now, *buf);
ret = KNOT_EOK;
}
......@@ -197,28 +221,29 @@ done:
return ret;
}
int keymgr_print_ksr(kdnssec_ctx_t *ctx, char *arg)
int keymgr_print_ksr(kdnssec_ctx_t *ctx, char *arg_from, char *arg_to)
{
knot_time_t upto;
int ret = parse_timestamp(arg, &upto);
knot_time_t from, to;
int ret = parse_timestamp(arg_from, &from);
if (ret != KNOT_EOK) {
return ret;
}
ret = parse_timestamp(arg_to, &to);
if (ret != KNOT_EOK) {
return ret;
}
knot_time_t next = ctx->now;
ret = KNOT_EOK;
char *buf = NULL;
size_t buf_size = 4096;
while (ret == KNOT_EOK && knot_time_cmp(next, upto) < 0) {
ctx->now = next;
ret = ksr_once(ctx, &buf, &buf_size, &next);
while (ret == KNOT_EOK && knot_time_cmp(from, to) < 0) {
ctx->now = from;
ret = ksr_once(ctx, &buf, &buf_size, &from);
}
if (ret != KNOT_EOK) {
free(buf);
return ret;
}
ctx->now = upto;
ctx->now = to;
// force end of period as a KSR timestamp
ret = ksr_once(ctx, &buf, &buf_size, NULL);
......@@ -269,10 +294,9 @@ static int ksr_sign_dnskey(kdnssec_ctx_t *ctx, knot_rrset_t *zsk, knot_time_t no
goto done;
}
}
ret = key_records_dump(&buf, &buf_size, &r);
ret = key_records_dump(&buf, &buf_size, &r, true);
if (ret == KNOT_EOK) {
printf(";; SignedKeyResponse %s %"PRIu64" ===========\n%s",
KSR_SKR_VER, ctx->now, buf);
print_header("SignedKeyResponse "KSR_SKR_VER, ctx->now, buf);
*next_sign = knot_get_next_zone_key_event(&keyset);
}
......@@ -346,8 +370,13 @@ static void skr_import_header(zs_scanner_t *sc)
}
(void)header_ver;
// delete possibly existing conflicting offline records
sc->error.code = kasp_db_delete_offline_records(
*ctx->kctx->kasp_db, ctx->kctx->zone->dname, next_timestamp, 0
);
// store previous SKR
if (ctx->timestamp > 0) {
if (ctx->timestamp > 0 && sc->error.code == KNOT_EOK) {
sc->error.code = kasp_db_store_offline_records(*ctx->kctx->kasp_db,
ctx->timestamp, &ctx->r);
key_records_clear_rdatasets(&ctx->r);
......
......@@ -20,13 +20,13 @@
int keymgr_pregenerate_zsks(kdnssec_ctx_t *ctx, char *arg);
int keymgr_print_offline_records(kdnssec_ctx_t *ctx, char *arg);
int keymgr_print_offline_records(kdnssec_ctx_t *ctx, char *arg_from, char *arg_to);
int keymgr_delete_offline_records(kdnssec_ctx_t *ctx, char *arg_from, char *arg_to);
int keymgr_del_all_old(kdnssec_ctx_t *ctx);
int keymgr_print_ksr(kdnssec_ctx_t *ctx, char *arg);
int keymgr_print_ksr(kdnssec_ctx_t *ctx, char *arg_from, char *arg_to);
int keymgr_sign_ksr(kdnssec_ctx_t *ctx, const char *ksr_file);
......
......@@ -91,6 +91,7 @@ knot.dnssec(zone).enable = True
knot.dnssec(zone).manual = True
knot.dnssec(zone).alg = "ECDSAP384SHA384"
knot.dnssec(zone).dnskey_ttl = 2
knot.dnssec(zone).zone_max_ttl = 3
knot.dnssec(zone).zsk_lifetime = STARTUP + 6*TICK # see ksk1 lifetime
knot.dnssec(zone).ksk_lifetime = 300 # this can be possibly left also infinity
knot.dnssec(zone).propagation_delay = TICK-2
......@@ -119,7 +120,7 @@ key_zsk1 = knot.key_gen(ZONE, ksk="false", created="+0", publish="+0", active="+
KSR = knot.keydir + "/ksr"
SKR = knot.keydir + "/skr"
Keymgr.run_check(knot.confile, ZONE, "pregenerate", "+" + str(FUTURE))
_, out, _ = Keymgr.run_check(knot.confile, ZONE, "generate-ksr", "+" + str(FUTURE))
_, out, _ = Keymgr.run_check(knot.confile, ZONE, "generate-ksr", "+0", "+" + str(FUTURE))
writef(KSR, out)
_, out, _ = Keymgr.run_check(signer.confile, ZONE, "sign-ksr", KSR)
writef(SKR, out)
......
......@@ -44,6 +44,7 @@ class ZoneDnssec(object):
self.ksk_size = None
self.zsk_size = None
self.dnskey_ttl = None
self.zone_max_ttl = None
self.ksk_lifetime = None
self.zsk_lifetime = None
self.propagation_delay = None
......@@ -1186,6 +1187,7 @@ class Knot(Server):
self._str(s, "ksk_size", z.dnssec.ksk_size)
self._str(s, "zsk_size", z.dnssec.zsk_size)
self._str(s, "dnskey-ttl", z.dnssec.dnskey_ttl)
self._str(s, "zone-max-ttl", z.dnssec.zone_max_ttl)
self._str(s, "ksk-lifetime", z.dnssec.ksk_lifetime)
self._str(s, "zsk-lifetime", z.dnssec.zsk_lifetime)
self._str(s, "propagation-delay", z.dnssec.propagation_delay)
......
......@@ -171,7 +171,7 @@ static void test_time_print(void)
ret = knot_time_print(TIME_PRINT_ISO8601, t, buff, bufl);
buff[11] = '0', buff[12] = '0'; // zeroing 'hours' field to avoid locality issues
test_time_print_expect(ret, buff, bufl, "1970-01-01T00:13:20", "iso");
test_time_print_expect(ret, buff, bufl, "1970-01-01T00:13:20Z", "iso");
t2 = knot_time_add(knot_time(), -10000);
ret = knot_time_print(TIME_PRINT_HUMAN_MIXED, t2, buff, bufl);
......
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