OpenDNSSEC-enforcer 2.1.10
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
42#include "db/key_state.h"
43#include "db/hsm_key.h"
44#include "db/zone_db.h"
45
47
48static const char *module_str = "keystate_list_task";
49
50/* shorter defines to keep keystate table more readable */
51#define HID KEY_STATE_STATE_HIDDEN
52#define RUM KEY_STATE_STATE_RUMOURED
53#define OMN KEY_STATE_STATE_OMNIPRESENT
54#define UNR KEY_STATE_STATE_UNRETENTIVE
55#define NAV KEY_STATE_STATE_NA
56
58const char* statenames[] = {"generate", "publish", "ready",
59 "active", "retire", "unknown", "mixed", "dead"};
60
67static int
68keystate(int p, int c, int introducing, key_data_ds_at_parent_t dsstate)
69{
70 int dsseen = (dsstate == KEY_DATA_DS_AT_PARENT_SEEN);
71 int dsretract = (dsstate == KEY_DATA_DS_AT_PARENT_RETRACT);
72
73 if (p == OMN && c == OMN) return KS_ACT;
74 if (p == RUM && dsseen && c == OMN) return KS_ACT;
75 if (introducing) {
76 if (p == HID && c == HID) return KS_GEN;
77 if (p == HID || c == HID) return KS_PUB;
78 if (p == OMN || c == OMN) return KS_RDY;
79 if (p == RUM || c == RUM) return KS_RDY;
80 return KS_UNK;
81 } else {
82 /* retire conforms better to 1.4 terminology than dead. */
83 if (p == HID && c == HID) return KS_RET; /* dead */
84 if (p == UNR || c == UNR) return KS_RET;
85 if (p == OMN || c == OMN) return KS_RDY;
86 if (p == RUM || c == RUM) return KS_RDY;
87 return KS_RET;
88 }
89}
90
91static int
92zskstate(key_data_t *key)
93{
94 return keystate(key_state_state(key_data_cached_dnskey(key)),
97}
98
99static int
100kskstate(key_data_t *key)
101{
102 return keystate(key_state_state(key_data_cached_ds(key)),
106}
107
112const char*
114{
115 int z,k;
116 switch(key_data_role(key)) {
118 return statenames[kskstate(key)];
120 return statenames[zskstate(key)];
122 k = kskstate(key);
123 z = zskstate(key);
124 if (k != z) return statenames[KS_MIX];
125 return statenames[k];
126 default:
127 return statenames[KS_UNK];
128 }
129}
130
135static char*
136map_keytime(const zone_db_t *zone, const key_data_t *key)
137{
138 char ct[26];
139 struct tm srtm;
140 time_t t;
141
142 switch(key_data_ds_at_parent(key)) {
144 return strdup("waiting for ds-submit");
146 return strdup("waiting for ds-seen");
148 return strdup("waiting for ds-retract");
150 return strdup("waiting for ds-gone");
151 default:
152 break;
153 }
154 if (zone_db_next_change(zone) < 0)
155 return strdup("-");
156 else if (zone_db_next_change(zone) < time_now())
157 return strdup("now");
158
159 t = (time_t)zone_db_next_change(zone);
160 localtime_r(&t, &srtm);
161 strftime(ct, 26, "%Y-%m-%d %H:%M:%S", &srtm);
162 return strdup(ct);
163}
164
165static int
166perform_keystate_list(int sockfd, db_connection_t *dbconn,
167 const char* zonename, const char* keytype, const char* keystate,
168 void (printheader)(int sockfd),
169 void (printkey)(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmKey)) {
170 key_data_list_t* key_list;
171 key_data_t* key;
172 zone_db_t *zone = NULL;
173 char* tchange;
174 hsm_key_t *hsmkey;
175 int cmp;
176
177 if (!(key_list = key_data_list_new_get(dbconn))) {
178 client_printf_err(sockfd, "Unable to get list of keys, memory "
179 "allocation or database error!\n");
180 return 1;
181 }
182
183 if (printheader) {
184 (*printheader)(sockfd);
185 }
186
187 while ((key = key_data_list_get_next(key_list))) {
188 /* only refetches zone if different from previous */
189 if (zone
190 && (db_value_cmp(zone_db_id(zone), key_data_zone_id(key), &cmp)
191 || cmp)) {
192 zone_db_free(zone);
193 zone = NULL;
194 }
195 if (!zone) {
196 zone = key_data_get_zone(key);
197 }
198 hsmkey = key_data_get_hsm_key(key);
200 tchange = map_keytime(zone, key); /* allocs */
201 if ((printkey != NULL) && (!zonename || !strcmp(zone_db_name(zone), zonename)) && (!keytype || !strcasecmp(keytype,key_data_role_text(key))) && (!keystate || !strcasecmp(keystate, map_keystate(key))))
202 (*printkey)(sockfd, zone, key, tchange, hsmkey);
203 free(tchange);
204 hsm_key_free(hsmkey);
205 key_data_free(key);
206 }
207 zone_db_free(zone);
208 key_data_list_free(key_list);
209 return 0;
210}
211
212static void
213usage(int sockfd)
214{
215 client_printf(sockfd,
216 "key list\n"
217 " [--verbose] aka -v\n"
218 " [--debug] aka -d\n"
219 " [--full] aka -f\n"
220 " [--parsable] aka -p\n"
221 " [--zone] aka -z \n"
222 " [--keystate | --all] aka -k | -a \n"
223 );
224}
225
226static void
227help(int sockfd)
228{
229 client_printf(sockfd,
230 "List the keys in the enforcer database.\n"
231 "\nOptions:\n"
232 "verbose also show additional key parameters\n"
233 "debug print information about the keystate\n"
234 "full print information about the keystate and keytags\n"
235 "parsable output machine parsable list\n"
236 "zone limit the output to the specific zone\n"
237 "keytype limit the output to the given type, can be ZSK, KSK, or CSK\n"
238 "keystate limit the output to the given state\n"
239 "all print keys in all states (including generate) \n\n");
240}
241
242static void
243printcompatheader(int sockfd) {
244 client_printf(sockfd, "Keys:\n");
245 client_printf(sockfd, "%-31s %-8s %-9s %s\n", "Zone:", "Keytype:", "State:",
246 "Date of next transition:");
247}
248
249static void
250printcompatkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
251 (void)hsmkey;
252 client_printf(sockfd,
253 "%-31s %-8s %-9s %s\n",
254 zone_db_name(zone),
256 map_keystate(key),
257 tchange);
258}
259
260static void
261printverboseheader(int sockfd) {
262 client_printf(sockfd, "Keys:\n");
263 client_printf(sockfd, "%-31s %-8s %-9s %-24s %-5s %-10s %-32s %-11s %s\n", "Zone:", "Keytype:", "State:",
264 "Date of next transition:", "Size:", "Algorithm:", "CKA_ID:",
265 "Repository:", "KeyTag:");
266}
267
268static void
269printverbosekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
270 (void)tchange;
271 client_printf(sockfd,
272 "%-31s %-8s %-9s %-24s %-5d %-10d %-32s %-11s %d\n",
273 zone_db_name(zone),
275 map_keystate(key),
276 tchange,
277 hsm_key_bits(hsmkey),
278 hsm_key_algorithm(hsmkey),
279 hsm_key_locator(hsmkey),
280 hsm_key_repository(hsmkey),
281 key_data_keytag(key));
282}
283
284static void
285printFullkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
286 (void)tchange;
287 client_printf(sockfd,
288 "%-31s %-8s %-9s %d %s %-12s %-12s %-12s %-12s %d %4d %s\n",
289 zone_db_name(zone),
291 map_keystate(key),
292 key_data_keytag(key),
293 hsm_key_locator(hsmkey),
298 key_data_publish(key),
300 tchange);
301}
302
303static void
304printverboseparsablekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
305 client_printf(sockfd,
306 "%s;%s;%s;%s;%d;%d;%s;%s;%d\n",
307 zone_db_name(zone),
309 map_keystate(key),
310 tchange,
311 hsm_key_bits(hsmkey),
312 hsm_key_algorithm(hsmkey),
313 hsm_key_locator(hsmkey),
314 hsm_key_repository(hsmkey),
315 key_data_keytag(key));
316}
317
318static void
319printdebugheader(int sockfd) {
320 client_printf(sockfd,
321 "Keys:\nZone: Key role: "
322 "DS: DNSKEY: RRSIGDNSKEY: RRSIG: "
323 "Pub: Act: Id:\n");
324}
325
326static void
327printdebugkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
328 (void)tchange;
329 client_printf(sockfd,
330 "%-31s %-13s %-12s %-12s %-12s %-12s %d %4d %s\n",
331 zone_db_name(zone),
337 key_data_publish(key),
339 hsm_key_locator(hsmkey));
340}
341
342static void
343printdebugparsablekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
344 (void)tchange;
345 client_printf(sockfd,
346 "%s;%s;%s;%s;%s;%s;%d;%d;%s\n",
347 zone_db_name(zone),
353 key_data_publish(key),
355 hsm_key_locator(hsmkey));
356}
357
358static int
359run(int sockfd, cmdhandler_ctx_type* context, const char *cmd)
360{
361 char buf[ODS_SE_MAXLINE];
362 #define NARGV 12
363 const char *argv[NARGV];
364 int success, argIndex;
365 int argc = 0, 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 ods_log_debug("[%s] %s command", module_str, key_list_funcblock.cmdname);
385
386 /* Use buf as an intermediate buffer for the command. */
387 strncpy(buf, cmd, sizeof (buf));
388 buf[sizeof (buf) - 1] = '\0';
389
390 /* separate the arguments */
391 argc = ods_str_explode(buf, NARGV, argv);
392 if (argc == -1) {
393 ods_log_error("[%s] too many arguments for %s command",
394 module_str, key_list_funcblock.cmdname);
395 client_printf_err(sockfd, "too many arguments\n");
396 return -1;
397 }
398 optind = 0;
399 while ((opt = getopt_long(argc, (char* const*)argv, "vdfpz:t:e:a", long_options, &long_index) ) != -1) {
400 switch (opt) {
401 case 'v':
402 bVerbose = 1;
403 break;
404 case 'd':
405 bDebug = 1;
406 break;
407 case 'f':
408 bFull = 1;
409 break;
410 case 'p':
411 bParsable = 1;
412 break;
413 case 'z':
414 zonename = optarg;
415 break;
416 case 't':
417 keytype = optarg;
418 break;
419 case 'e':
420 keystate = optarg;
421 break;
422 case 'a':
423 bAll = 1;
424 break;
425 default:
426 client_printf_err(sockfd, "unknown arguments\n");
427 ods_log_error("[%s] unknown arguments for %s command",
428 module_str, key_list_funcblock.cmdname);
429 return -1;
430 }
431 }
432
433 if (keystate != NULL && bAll) {
434 client_printf(sockfd, "Error: --keystate and --all option cannot be given together\n");
435 return -1;
436 }
437
438 if (bFull) {
439 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printFullkey);
440 } else if (bDebug) {
441 if (bParsable) {
442 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printdebugparsablekey);
443 } else {
444 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printdebugheader, &printdebugkey);
445 }
446 } else if (bVerbose) {
447 if (bParsable) {
448 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printverboseparsablekey);
449 } else {
450 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printverboseheader, &printverbosekey);
451 }
452 } else {
453 if (bParsable)
454 client_printf_err(sockfd, "-p option only available in combination with -v and -d.\n");
455 success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printcompatheader, &printcompatkey);
456 }
457
458 return success;
459}
460
461struct cmd_func_block key_list_funcblock = {
462 "key list", &usage, &help, NULL, &run
463};
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
#define NARGV
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