This commit is contained in:
David Vašek 2026-03-11 01:02:54 +01:00
parent 6dd8373def
commit 90e5caee07
5 changed files with 141 additions and 16 deletions

View file

@ -51,7 +51,7 @@ static int dnskey_guess_flags(dnssec_key_t *key, uint16_t keytag)
}
static int params2dnskey(const knot_dname_t *dname, key_params_t *params,
dnssec_key_t **key_ptr)
dnssec_key_t **key_ptr)
{
assert(dname);
assert(params);
@ -93,8 +93,8 @@ static int params2dnskey(const knot_dname_t *dname, key_params_t *params,
return KNOT_EOK;
}
static int params2kaspkey(const knot_dname_t *dname, key_params_t *params,
knot_kasp_key_t *key)
int params2kaspkey(const knot_dname_t *dname, key_params_t *params,
knot_kasp_key_t *key)
{
assert(dname != NULL);
assert(params != NULL);

View file

@ -19,6 +19,9 @@ typedef struct {
knot_time_t nsec3_salt_created;
} knot_kasp_zone_t;
int params2kaspkey(const knot_dname_t *dname, key_params_t *params,
knot_kasp_key_t *key);
int kasp_zone_load(knot_kasp_zone_t *zone,
const knot_dname_t *zone_name,
knot_lmdb_db_t *kdb,

View file

@ -23,6 +23,7 @@
#include "contrib/wire_ctx.h"
#include "libknot/dnssec/keyid.h"
#include "libknot/dnssec/shared/shared.h"
#include "knot/dnssec/kasp/kasp_zone.h"
#include "knot/dnssec/kasp/policy.h"
#include "knot/dnssec/key-events.h"
#include "knot/dnssec/rrset-sign.h"
@ -944,11 +945,18 @@ static const timer_ctx_t timers[] = {
{ NULL }
};
static const timer_ctx_t trash_timers[] = {
{ "discard", offsetof(knot_kasp_key_timing_t, remove) },
{ NULL }
};
typedef struct {
const char *ks_name;
size_t ks_count;
unsigned backend;
bool missing;
bool trash;
bool all_zones;
} key_info_t;
#define KS_TYPE(info) (info->backend == KEYSTORE_BACKEND_PEM) ? "PEM" : "PKCS11"
@ -992,9 +1000,10 @@ static void print_key_brief(const knot_kasp_key_t *key, key_info_t *info,
printf(" %s%s/%s%s", COL_YELW(c), KS_TYPE(info), info->ks_name, COL_RST(c));
}
static char buf[100];
static knot_dname_txt_storage_t buf;
knot_time_t now = knot_time();
for (const timer_ctx_t *t = &timers[0]; t->name != NULL; t++) {
for (const timer_ctx_t *t = info->trash ? &trash_timers[0] : &timers[0];
t->name != NULL; t++) {
knot_time_t *val = (void *)(&key->timing) + t->offset;
if (*val == 0) {
continue;
@ -1012,27 +1021,42 @@ static void print_key_brief(const knot_kasp_key_t *key, key_info_t *info,
(void)knot_time_print(params->format, *val, buf, sizeof(buf));
printf(" %s%s%s=%s%s%s", UNDR, t->name, COL_RST(c), BOLD, buf, COL_RST(c));
}
if (info->trash && info->all_zones) {
if (knot_dname_to_str(buf, dnssec_key_get_dname(key->key),
sizeof(buf)) != NULL) {
printf(" zone=%s", buf);
}
}
printf("\n");
}
static void print_key_full(const knot_kasp_key_t *key, key_info_t *info,
knot_time_print_t format)
keymgr_list_params_t *params)
{
printf("%s ksk=%s zsk=%s tag=%05d algorithm=%-2d size=%-4u public-only=%s for-later=%s missing=%s",
printf("%s ksk=%s zsk=%s tag=%05d algorithm=%-2d size=%-4u"
" public-only=%s for-later=%s missing=%s trash=%s",
key->id, (key->is_ksk ? "yes" : "no "), (key->is_zsk ? "yes" : "no "),
dnssec_key_get_keytag(key->key), (int)dnssec_key_get_algorithm(key->key),
dnssec_key_get_size(key->key), (key->is_pub_only ? "yes" : "no "),
(key->is_for_later ? "yes" : "no "), (info->missing ? "yes" : "no "));
(key->is_for_later ? "yes" : "no "), (info->missing ? "yes" : "no "),
(info->trash ? "yes" : "no "));
if (info->ks_name != NULL) {
printf(" keystore=%s/%s", KS_TYPE(info), info->ks_name);
}
static char buf[100];
for (const timer_ctx_t *t = &timers[0]; t->name != NULL; t++) {
static knot_dname_txt_storage_t buf;
for (const timer_ctx_t *t = info->trash ? &trash_timers[0] : &timers[0];
t->name != NULL; t++) {
knot_time_t *val = (void *)(&key->timing) + t->offset;
(void)knot_time_print(format, *val, buf, sizeof(buf));
(void)knot_time_print(params->format, *val, buf, sizeof(buf));
printf(" %s=%s", t->name, buf);
}
if (info->trash) {
if (knot_dname_to_str(buf, dnssec_key_get_dname(key->key),
sizeof(buf)) != NULL) {
printf(" zone=%s", buf);
}
}
printf("\n");
}
@ -1098,7 +1122,7 @@ int keymgr_list_keys(kdnssec_ctx_t *ctx, keymgr_list_params_t *params)
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
key_info_t info = key_missing(ctx, key);
print_key_full(key, &info, params->format);
print_key_full(key, &info, params);
}
} else if (params->json) {
jsonw_t *w = jsonw_new(stdout, " ");
@ -1140,6 +1164,77 @@ int keymgr_list_keys(kdnssec_ctx_t *ctx, keymgr_list_params_t *params)
return KNOT_EOK;
}
static int print_params_key(kdnssec_ctx_t *ctx, key_params_t *kparams,
keymgr_list_params_t *params,
void (*print_cb)(const knot_kasp_key_t *, key_info_t *,
keymgr_list_params_t *))
{
knot_kasp_key_t key;
int ret = params2kaspkey(kparams->dname, kparams, &key);
if (ret != KNOT_EOK) {
ERR2("failed to parse key metadata (%s)", knot_strerror(ret));
goto exit;
}
key_info_t info = key_missing(ctx, &key);
info.trash = true;
info.all_zones = ctx->validation_mode; // Abused parameter validation_mode.
print_cb(&key, &info, params);
exit:
free(key.id);
dnssec_key_free(key.key);
return ret;
}
int keymgr_list_trash(kdnssec_ctx_t *ctx, const knot_dname_t *zone_name,
keymgr_list_params_t *params)
{
list_t tlist;
init_list(&tlist);
int ret = kasp_db_list_keys(ctx->kasp_db, zone_name, &tlist, true);
if (ret != KNOT_EOK) {
ERR2("failed to initialize KASP (%s)", knot_strerror(ret));
return ret;
}
ptrnode_t *node;
if (params->extended) {
WALK_LIST(node, tlist) {
ret = print_params_key(ctx, node->d, params, print_key_full);
if (ret != KNOT_EOK) {
break;
}
}
} else if (params->json) {
// XXXXXXX
ERR2("JSON trash key listing not supported (yet)");
} else {
size_t tlist_size = list_size(&tlist);
key_sort_item_t items[tlist_size];
size_t i = 0;
WALK_LIST(node, tlist) {
items[i].val = node->d;
items[i].key = ((key_params_t *)node->d)->timing.remove;
i++;
}
qsort(&items, tlist_size, sizeof(items[0]), key_sort);
for (i = 0; i < tlist_size; i++) {
ret = print_params_key(ctx, items[i].val, params, print_key_brief);
if (ret != KNOT_EOK) {
break;
}
}
}
WALK_LIST(node, tlist) {
free_key_params(node->d);
}
ptrlist_deep_free(&tlist, NULL);
return ret;
}
static int print_ds(const knot_dname_t *dname, const dnssec_binary_t *rdata)
{
wire_ctx_t ctx = wire_ctx_init(rdata->data, rdata->size);

View file

@ -46,6 +46,8 @@ int keymgr_set_timing(knot_kasp_key_t *key, int argc, char *argv[]);
int keymgr_list_keys(kdnssec_ctx_t *ctx, keymgr_list_params_t *params);
int keymgr_list_trash(kdnssec_ctx_t *ctx, const knot_dname_t *zone_name, keymgr_list_params_t *params);
int keymgr_generate_ds(const knot_dname_t *dname, const knot_kasp_key_t *key);
int keymgr_generate_dnskey(const knot_dname_t *dname, const knot_kasp_key_t *key);

View file

@ -137,11 +137,27 @@ static int key_command(int argc, char *argv[], int opt_ind, knot_lmdb_db_t *kasp
knot_dname_to_lower(zone_name);
kdnssec_ctx_t kctx = { 0 };
int ret;
int ret = kdnssec_ctx_init(conf(), &kctx, zone_name, kaspdb, NULL);
if (ret != KNOT_EOK) {
ERR2("failed to initialize KASP (%s)", knot_strerror(ret));
goto main_end;
if (same_command(argv[1], "trash-list", false) ||
same_command(argv[1], "trash-delete", false)) {
kctx.kasp_db = kaspdb;
ret = init_all_keystores(conf(), &kctx.keystores);
if (ret != KNOT_EOK) {
ERR2("failed to initialize keystores (%s)", knot_strerror(ret));
goto main_end;
}
if (strncmp(id_str, "--", 3)) {
kctx.validation_mode = true; // Abused parameter validation_mode.
zone_name = NULL;
}
} else {
ret = kdnssec_ctx_init(conf(), &kctx, zone_name, kaspdb, NULL);
if (ret != KNOT_EOK) {
ERR2("failed to initialize KASP (%s)", knot_strerror(ret));
goto main_end;
}
}
#define CHECK_MISSING_ARG(msg) \
@ -211,6 +227,15 @@ static int key_command(int argc, char *argv[], int opt_ind, knot_lmdb_db_t *kasp
}
ret = keymgr_list_keys(&kctx, list_params);
print_ok_on_succes = false;
} else if (same_command(argv[1], "trash-list", false)) {
list_params->format = TIME_PRINT_UNIX;
if (argc > 2 && same_command(argv[2], "human", false)) {
list_params->format = TIME_PRINT_HUMAN_MIXED;
} else if (argc > 2 && same_command(argv[2], "iso", false)) {
list_params->format = TIME_PRINT_ISO8601;
}
ret = keymgr_list_trash(&kctx, zone_name, list_params);
print_ok_on_succes = false;
} else if (same_command(argv[1], "ds", false) || same_command(argv[1], "dnskey", false)) {
int (*generate_rr)(const knot_dname_t *, const knot_kasp_key_t *) = keymgr_generate_dnskey;
if (same_command(argv[1], "ds", false)) {