OpenDNSSEC-enforcer  2.1.7
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 
48 static 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 
58 const char* statenames[] = {"generate", "publish", "ready",
59  "active", "retire", "unknown", "mixed", "dead"};
60 
67 static int
68 keystate(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 
91 static int
92 zskstate(key_data_t *key)
93 {
94  return keystate(key_state_state(key_data_cached_dnskey(key)),
97 }
98 
99 static int
100 kskstate(key_data_t *key)
101 {
102  return keystate(key_state_state(key_data_cached_ds(key)),
105  key_data_ds_at_parent(key));
106 }
107 
112 const char*
114 {
115  int z,k;
116  switch(key_data_role(key)) {
117  case KEY_DATA_ROLE_KSK:
118  return statenames[kskstate(key)];
119  case KEY_DATA_ROLE_ZSK:
120  return statenames[zskstate(key)];
121  case KEY_DATA_ROLE_CSK:
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 
135 static char*
136 map_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 
165 static int
166 perform_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 
212 static void
213 usage(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 
226 static void
227 help(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 
242 static void
243 printcompatheader(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 
249 static void
250 printcompatkey(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),
255  key_data_role_text(key),
256  map_keystate(key),
257  tchange);
258 }
259 
260 static void
261 printverboseheader(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 
268 static void
269 printverbosekey(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),
274  key_data_role_text(key),
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 
284 static void
285 printFullkey(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),
290  key_data_role_text(key),
291  map_keystate(key),
292  key_data_keytag(key),
293  hsm_key_locator(hsmkey),
298  key_data_publish(key),
300  tchange);
301 }
302 
303 static void
304 printverboseparsablekey(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),
308  key_data_role_text(key),
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 
318 static void
319 printdebugheader(int sockfd) {
320  client_printf(sockfd,
321  "Keys:\nZone: Key role: "
322  "DS: DNSKEY: RRSIGDNSKEY: RRSIG: "
323  "Pub: Act: Id:\n");
324 }
325 
326 static void
327 printdebugkey(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),
332  key_data_role_text(key),
337  key_data_publish(key),
339  hsm_key_locator(hsmkey));
340 }
341 
342 static void
343 printdebugparsablekey(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),
348  key_data_role_text(key),
353  key_data_publish(key),
355  hsm_key_locator(hsmkey));
356 }
357 
358 static int
359 run(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 
461 struct 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
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
const char * hsm_key_locator(const hsm_key_t *hsm_key)
Definition: hsm_key.c:520
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_t * key_data_list_get_next(key_data_list_t *key_data_list)
Definition: key_data.c:2425
const char * key_data_role_text(const key_data_t *key_data)
Definition: key_data.c:711
zone_db_t * key_data_get_zone(const key_data_t *key_data)
Definition: key_data.c:569
unsigned int key_data_keytag(const key_data_t *key_data)
Definition: key_data.c:767
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
const db_value_t * key_data_zone_id(const key_data_t *key_data)
Definition: key_data.c:561
unsigned int key_data_active_zsk(const key_data_t *key_data)
Definition: key_data.c:735
hsm_key_t * key_data_get_hsm_key(const key_data_t *key_data)
Definition: key_data.c:649
key_data_list_t * key_data_list_new_get(const db_connection_t *connection)
Definition: key_data.c:2102
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
int key_data_cache_key_states(key_data_t *key_data)
Definition: key_data_ext.c:33
const key_state_t * key_data_cached_rrsigdnskey(key_data_t *key_data)
Definition: key_data_ext.c:72
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_rrsig(key_data_t *key_data)
Definition: key_data_ext.c:64
const key_state_t * key_data_cached_ds(key_data_t *key_data)
Definition: key_data_ext.c:60
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
const char * map_keystate(key_data_t *key)
#define UNR
const char * statenames[]
#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