OpenDNSSEC-enforcer 2.1.13
keystate_list_cmd.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Surfnet
3 * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation).
4 * Copyright (c) 2011 OpenDNSSEC AB (svb)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#include <getopt.h>
31#include "config.h"
32
33#include "cmdhandler.h"
35#include "daemon/engine.h"
36#include "file.h"
37#include "duration.h"
38#include "log.h"
39#include "str.h"
40#include "clientpipe.h"
41#include "longgetopt.h"
42
43#include "db/key_state.h"
44#include "db/hsm_key.h"
45#include "db/zone_db.h"
46
48
49static const char *module_str = "keystate_list_task";
50
51/* shorter defines to keep keystate table more readable */
52#define HID KEY_STATE_STATE_HIDDEN
53#define RUM KEY_STATE_STATE_RUMOURED
54#define OMN KEY_STATE_STATE_OMNIPRESENT
55#define UNR KEY_STATE_STATE_UNRETENTIVE
56#define NAV KEY_STATE_STATE_NA
57
59const char* statenames[] = {"generate", "publish", "ready",
60 "active", "retire", "unknown", "mixed", "dead"};
61
68static int
69keystate(int p, int c, int introducing, key_data_ds_at_parent_t dsstate)
70{
71 int dsseen = (dsstate == KEY_DATA_DS_AT_PARENT_SEEN);
72 int dsretract = (dsstate == KEY_DATA_DS_AT_PARENT_RETRACT);
73
74 if (p == OMN && c == OMN) return KS_ACT;
75 if (p == RUM && dsseen && c == OMN) return KS_ACT;
76 if (introducing) {
77 if (p == HID && c == HID) return KS_GEN;
78 if (p == HID || c == HID) return KS_PUB;
79 if (p == OMN || c == OMN) return KS_RDY;
80 if (p == RUM || c == RUM) return KS_RDY;
81 return KS_UNK;
82 } else {
83 /* retire conforms better to 1.4 terminology than dead. */
84 if (p == HID && c == HID) return KS_RET; /* dead */
85 if (p == UNR || c == UNR) return KS_RET;
86 if (p == OMN || c == OMN) return KS_RDY;
87 if (p == RUM || c == RUM) return KS_RDY;
88 return KS_RET;
89 }
90}
91
92static int
93zskstate(key_data_t *key)
94{
95 return keystate(key_state_state(key_data_cached_dnskey(key)),
98}
99
100static int
101kskstate(key_data_t *key)
102{
103 return keystate(key_state_state(key_data_cached_ds(key)),
107}
108
113const char*
115{
116 int z,k;
117 switch(key_data_role(key)) {
119 return statenames[kskstate(key)];
121 return statenames[zskstate(key)];
123 k = kskstate(key);
124 z = zskstate(key);
125 if (k != z) return statenames[KS_MIX];
126 return statenames[k];
127 default:
128 return statenames[KS_UNK];
129 }
130}
131
136static char*
137map_keytime(const zone_db_t *zone, const key_data_t *key)
138{
139 char ct[26];
140 struct tm srtm;
141 time_t t;
142
143 switch(key_data_ds_at_parent(key)) {
145 return strdup("waiting for ds-submit");
147 return strdup("waiting for ds-seen");
149 return strdup("waiting for ds-retract");
151 return strdup("waiting for ds-gone");
152 default:
153 break;
154 }
155 if (zone_db_next_change(zone) < 0)
156 return strdup("-");
157 else if (zone_db_next_change(zone) < time_now())
158 return strdup("now");
159
160 t = (time_t)zone_db_next_change(zone);
161 localtime_r(&t, &srtm);
162 strftime(ct, 26, "%Y-%m-%d %H:%M:%S", &srtm);
163 return strdup(ct);
164}
165
166static int
167perform_keystate_list(int sockfd, db_connection_t *dbconn,
168 const char* zonename, const char* keytype, const char* keystate,
169 void (printheader)(int sockfd),
170 void (printkey)(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmKey)) {
171 key_data_list_t* key_list;
172 key_data_t* key;
173 zone_db_t *zone = NULL;
174 char* tchange;
175 hsm_key_t *hsmkey;
176 int cmp;
177
178 if (!(key_list = key_data_list_new_get(dbconn))) {
179 client_printf_err(sockfd, "Unable to get list of keys, memory "
180 "allocation or database error!\n");
181 return 1;
182 }
183
184 if (printheader) {
185 (*printheader)(sockfd);
186 }
187
188 while ((key = key_data_list_get_next(key_list))) {
189 /* only refetches zone if different from previous */
190 if (zone
191 && (db_value_cmp(zone_db_id(zone), key_data_zone_id(key), &cmp)
192 || cmp)) {
193 zone_db_free(zone);
194 zone = NULL;
195 }
196 if (!zone) {
197 zone = key_data_get_zone(key);
198 }
199 hsmkey = key_data_get_hsm_key(key);
201 tchange = map_keytime(zone, key); /* allocs */
202 if ((printkey != NULL) && (!zonename || !strcmp(zone_db_name(zone), zonename)) && (!keytype || !strcasecmp(keytype,key_data_role_text(key))) && (!keystate || !strcasecmp(keystate, map_keystate(key))))
203 (*printkey)(sockfd, zone, key, tchange, hsmkey);
204 free(tchange);
205 hsm_key_free(hsmkey);
206 key_data_free(key);
207 }
208 zone_db_free(zone);
209 key_data_list_free(key_list);
210 return 0;
211}
212
213static void
214usage(int sockfd)
215{
216 client_printf(sockfd,
217 "key list\n"
218 " [--verbose] aka -v\n"
219 " [--debug] aka -d\n"
220 " [--full] aka -f\n"
221 " [--parsable] aka -p\n"
222 " [--zone] aka -z \n"
223 " [--keystate | --all] aka -k | -a \n"
224 );
225}
226
227static void
228help(int sockfd)
229{
230 client_printf(sockfd,
231 "List the keys in the enforcer database.\n"
232 "\nOptions:\n"
233 "verbose also show additional key parameters\n"
234 "debug print information about the keystate\n"
235 "full print information about the keystate and keytags\n"
236 "parsable output machine parsable list\n"
237 "zone limit the output to the specific zone\n"
238 "keytype limit the output to the given type, can be ZSK, KSK, or CSK\n"
239 "keystate limit the output to the given state\n"
240 "all print keys in all states (including generate) \n\n");
241}
242
243static void
244printcompatheader(int sockfd) {
245 client_printf(sockfd, "Keys:\n");
246 client_printf(sockfd, "%-31s %-8s %-9s %s\n", "Zone:", "Keytype:", "State:",
247 "Date of next transition:");
248}
249
250static void
251printcompatkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
252 (void)hsmkey;
253 client_printf(sockfd,
254 "%-31s %-8s %-9s %s\n",
255 zone_db_name(zone),
257 map_keystate(key),
258 tchange);
259}
260
261static void
262printverboseheader(int sockfd) {
263 client_printf(sockfd, "Keys:\n");
264 client_printf(sockfd, "%-31s %-8s %-9s %-24s %-5s %-10s %-32s %-11s %s\n", "Zone:", "Keytype:", "State:",
265 "Date of next transition:", "Size:", "Algorithm:", "CKA_ID:",
266 "Repository:", "KeyTag:");
267}
268
269static void
270printverbosekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
271 (void)tchange;
272 client_printf(sockfd,
273 "%-31s %-8s %-9s %-24s %-5d %-10d %-32s %-11s %d\n",
274 zone_db_name(zone),
276 map_keystate(key),
277 tchange,
278 hsm_key_bits(hsmkey),
279 hsm_key_algorithm(hsmkey),
280 hsm_key_locator(hsmkey),
281 hsm_key_repository(hsmkey),
282 key_data_keytag(key));
283}
284
285static void
286printFullkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
287 (void)tchange;
288 client_printf(sockfd,
289 "%-31s %-8s %-9s %d %s %-12s %-12s %-12s %-12s %d %4d %s\n",
290 zone_db_name(zone),
292 map_keystate(key),
293 key_data_keytag(key),
294 hsm_key_locator(hsmkey),
299 key_data_publish(key),
301 tchange);
302}
303
304static void
305printverboseparsablekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
306 client_printf(sockfd,
307 "%s;%s;%s;%s;%d;%d;%s;%s;%d\n",
308 zone_db_name(zone),
310 map_keystate(key),
311 tchange,
312 hsm_key_bits(hsmkey),
313 hsm_key_algorithm(hsmkey),
314 hsm_key_locator(hsmkey),
315 hsm_key_repository(hsmkey),
316 key_data_keytag(key));
317}
318
319static void
320printdebugheader(int sockfd) {
321 client_printf(sockfd,
322 "Keys:\nZone: Key role: "
323 "DS: DNSKEY: RRSIGDNSKEY: RRSIG: "
324 "Pub: Act: Id:\n");
325}
326
327static void
328printdebugkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
329 (void)tchange;
330 client_printf(sockfd,
331 "%-31s %-13s %-12s %-12s %-12s %-12s %d %4d %s\n",
332 zone_db_name(zone),
338 key_data_publish(key),
340 hsm_key_locator(hsmkey));
341}
342
343static void
344printdebugparsablekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
345 (void)tchange;
346 client_printf(sockfd,
347 "%s;%s;%s;%s;%s;%s;%d;%d;%s\n",
348 zone_db_name(zone),
354 key_data_publish(key),
356 hsm_key_locator(hsmkey));
357}
358
359static int
360run(cmdhandler_ctx_type* context, int argc, char* argv[])
361{
362 int sockfd = context->sockfd;
363 struct longgetopt optctx;
364 int success;
365 int bVerbose = 0, bDebug = 0, bFull = 0, bParsable = 0, bAll = 0;
366 int long_index = 0, opt = 0;
367 const char* keytype = NULL;
368 const char* keystate = NULL;
369 const char* zonename = NULL;
370 db_connection_t* dbconn = getconnectioncontext(context);
371
372 static struct option long_options[] = {
373 {"verbose", no_argument, 0, 'v'},
374 {"debug", no_argument, 0, 'd'},
375 {"full", no_argument, 0, 'f'},
376 {"parsable", no_argument, 0, 'p'},
377 {"zone", required_argument, 0, 'z'},
378 {"keytype", required_argument, 0, 't'},
379 {"keystate", required_argument, 0, 'e'},
380 {"all", no_argument, 0, 'a'},
381 {0, 0, 0, 0}
382 };
383
384 for(opt = longgetopt(argc, argv, "vdfpz:t:e:a", long_options, &long_index, &optctx); opt != -1;
385 opt = longgetopt(argc, argv, NULL, long_options, &long_index, &optctx)) {
386 switch (opt) {
387 case 'v':
388 bVerbose = 1;
389 break;
390 case 'd':
391 bDebug = 1;
392 break;
393 case 'f':
394 bFull = 1;
395 break;
396 case 'p':
397 bParsable = 1;
398 break;
399 case 'z':
400 zonename = optctx.optarg;
401 break;
402 case 't':
403 keytype = optctx.optarg;
404 break;
405 case 'e':
406 keystate = optctx.optarg;
407 break;
408 case 'a':
409 bAll = 1;
410 break;
411 default:
412 client_printf_err(sockfd, "unknown arguments\n");
413 ods_log_error("[%s] unknown arguments for key list command", module_str);
414 return -1;
415 }
416 }
417
418 if (keystate != NULL && bAll) {
419 client_printf(sockfd, "Error: --keystate and --all option cannot be given together\n");
420 return -1;
421 }
422
423 if (bFull) {
424 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printFullkey);
425 } else if (bDebug) {
426 if (bParsable) {
427 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printdebugparsablekey);
428 } else {
429 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printdebugheader, &printdebugkey);
430 }
431 } else if (bVerbose) {
432 if (bParsable) {
433 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printverboseparsablekey);
434 } else {
435 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printverboseheader, &printverbosekey);
436 }
437 } else {
438 if (bParsable)
439 client_printf_err(sockfd, "-p option only available in combination with -v and -d.\n");
440 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printcompatheader, &printcompatkey);
441 }
442 return success;
443}
444
445struct cmd_func_block key_list_funcblock = {
446 "key list", &usage, &help, NULL, NULL, &run, NULL
447};
int db_value_cmp(const db_value_t *value_a, const db_value_t *value_b, int *result)
Definition: db_value.c:102
db_connection_t * getconnectioncontext(cmdhandler_ctx_type *context)
void hsm_key_free(hsm_key_t *hsm_key)
Definition: hsm_key.c:286
const char * hsm_key_repository(const hsm_key_t *hsm_key)
Definition: hsm_key.c:568
const char * hsm_key_locator(const hsm_key_t *hsm_key)
Definition: hsm_key.c:520
unsigned int hsm_key_algorithm(const hsm_key_t *hsm_key)
Definition: hsm_key.c:544
unsigned int hsm_key_bits(const hsm_key_t *hsm_key)
Definition: hsm_key.c:536
zone_db_t * key_data_get_zone(const key_data_t *key_data)
Definition: key_data.c:569
unsigned int key_data_active_ksk(const key_data_t *key_data)
Definition: key_data.c:751
void key_data_free(key_data_t *key_data)
Definition: key_data.c:304
key_data_list_t * key_data_list_new_get(const db_connection_t *connection)
Definition: key_data.c:2102
hsm_key_t * key_data_get_hsm_key(const key_data_t *key_data)
Definition: key_data.c:649
unsigned int key_data_keytag(const key_data_t *key_data)
Definition: key_data.c:767
const char * key_data_role_text(const key_data_t *key_data)
Definition: key_data.c:711
unsigned int key_data_publish(const key_data_t *key_data)
Definition: key_data.c:743
void key_data_list_free(key_data_list_t *key_data_list)
Definition: key_data.c:1694
unsigned int key_data_introducing(const key_data_t *key_data)
Definition: key_data.c:727
unsigned int key_data_active_zsk(const key_data_t *key_data)
Definition: key_data.c:735
key_data_t * key_data_list_get_next(key_data_list_t *key_data_list)
Definition: key_data.c:2425
const db_value_t * key_data_zone_id(const key_data_t *key_data)
Definition: key_data.c:561
key_data_role
Definition: key_data.h:40
@ KEY_DATA_ROLE_ZSK
Definition: key_data.h:43
@ KEY_DATA_ROLE_KSK
Definition: key_data.h:42
@ KEY_DATA_ROLE_CSK
Definition: key_data.h:44
enum key_data_ds_at_parent key_data_ds_at_parent_t
key_data_ds_at_parent
Definition: key_data.h:50
@ KEY_DATA_DS_AT_PARENT_SUBMITTED
Definition: key_data.h:54
@ KEY_DATA_DS_AT_PARENT_RETRACT
Definition: key_data.h:56
@ KEY_DATA_DS_AT_PARENT_SEEN
Definition: key_data.h:55
@ KEY_DATA_DS_AT_PARENT_INVALID
Definition: key_data.h:51
@ KEY_DATA_DS_AT_PARENT_SUBMIT
Definition: key_data.h:53
@ KEY_DATA_DS_AT_PARENT_RETRACTED
Definition: key_data.h:57
const key_state_t * key_data_cached_rrsig(key_data_t *key_data)
Definition: key_data_ext.c:64
int key_data_cache_key_states(key_data_t *key_data)
Definition: key_data_ext.c:33
const key_state_t * key_data_cached_dnskey(key_data_t *key_data)
Definition: key_data_ext.c:68
const key_state_t * key_data_cached_ds(key_data_t *key_data)
Definition: key_data_ext.c:60
const key_state_t * key_data_cached_rrsigdnskey(key_data_t *key_data)
Definition: key_data_ext.c:72
const char * key_state_state_text(const key_state_t *key_state)
Definition: key_state.c:377
key_state_state
Definition: key_state.h:49
struct cmd_func_block key_list_funcblock
#define RUM
#define UNR
const char * statenames[]
const char * map_keystate(key_data_t *key)
#define HID
@ KS_ACT
@ KS_DEAD
@ KS_GEN
@ KS_PUB
@ KS_MIX
@ KS_RET
@ KS_UNK
@ KS_RDY
#define OMN
void zone_db_free(zone_db_t *zone)
Definition: zone_db.c:325
const char * zone_db_name(const zone_db_t *zone)
Definition: zone_db.c:782
const db_value_t * zone_db_id(const zone_db_t *zone)
Definition: zone_db.c:728
int zone_db_next_change(const zone_db_t *zone)
Definition: zone_db.c:806