OpenDNSSEC-enforcer  2.1.5
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  case KEY_DATA_DS_AT_PARENT_INVALID: return strdup("ds-invalid");
152  case KEY_DATA_DS_AT_PARENT_UNSUBMITTED: return strdup("ds-unsubmitted");
153  case KEY_DATA_DS_AT_PARENT_SEEN: return strdup("ds-seen");
154  default:
155  break;
156  }
157  if (zone_db_next_change(zone) < 0)
158  return strdup("-");
159  else if (zone_db_next_change(zone) < time_now())
160  return strdup("now");
161 
162  t = (time_t)zone_db_next_change(zone);
163  localtime_r(&t, &srtm);
164  strftime(ct, 26, "%Y-%m-%d %H:%M:%S", &srtm);
165  return strdup(ct);
166 }
167 
168 static int
169 perform_keystate_list(int sockfd, db_connection_t *dbconn,
170  const char* zonename, const char* keytype, const char* keystate,
171  void (printheader)(int sockfd),
172  void (printkey)(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmKey)) {
173  key_data_list_t* key_list;
174  key_data_t* key;
175  zone_db_t *zone = NULL;
176  char* tchange;
177  hsm_key_t *hsmkey;
178  int cmp;
179 
180  if (!(key_list = key_data_list_new_get(dbconn))) {
181  client_printf_err(sockfd, "Unable to get list of keys, memory "
182  "allocation or database error!\n");
183  return 1;
184  }
185 
186  if (printheader) {
187  (*printheader)(sockfd);
188  }
189 
190  while ((key = key_data_list_get_next(key_list))) {
191  /* only refetches zone if different from previous */
192  if (zone
193  && (db_value_cmp(zone_db_id(zone), key_data_zone_id(key), &cmp)
194  || cmp)) {
195  zone_db_free(zone);
196  zone = NULL;
197  }
198  if (!zone) {
199  zone = key_data_get_zone(key);
200  }
201  hsmkey = key_data_get_hsm_key(key);
203  tchange = map_keytime(zone, key); /* allocs */
204  if ((printkey != NULL) && (!zonename || !strcmp(zone_db_name(zone), zonename)) && (!keytype || !strcasecmp(keytype,key_data_role_text(key))) && (!keystate || !strcasecmp(keystate, map_keystate(key))))
205  (*printkey)(sockfd, zone, key, tchange, hsmkey);
206  free(tchange);
207  hsm_key_free(hsmkey);
208  key_data_free(key);
209  }
210  zone_db_free(zone);
211  key_data_list_free(key_list);
212  return 0;
213 }
214 
215 static void
216 usage(int sockfd)
217 {
218  client_printf(sockfd,
219  "key list\n"
220  " [--verbose] aka -v\n"
221  " [--debug] aka -d\n"
222  " [--full] aka -f\n"
223  " [--parsable] aka -p\n"
224  " [--zone] aka -z \n"
225  " [--keystate | --all] aka -k | -a \n"
226  );
227 }
228 
229 static void
230 help(int sockfd)
231 {
232  client_printf(sockfd,
233  "List the keys in the enforcer database.\n"
234  "\nOptions:\n"
235  "verbose also show additional key parameters\n"
236  "debug print information about the keystate\n"
237  "full print information about the keystate and keytags\n"
238  "parsable output machine parsable list\n"
239  "zone limit the output to the specific zone\n"
240  "keytype limit the output to the given type, can be ZSK, KSK, or CSK\n"
241  "keystate limit the output to the given state\n"
242  "all print keys in all states (including generate) \n\n");
243 }
244 
245 static void
246 printcompatheader(int sockfd) {
247  client_printf(sockfd, "Keys:\n");
248  client_printf(sockfd, "%-31s %-8s %-9s %s\n", "Zone:", "Keytype:", "State:",
249  "Date of next transition:");
250 }
251 
252 static void
253 printcompatkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
254  (void)hsmkey;
255  client_printf(sockfd,
256  "%-31s %-8s %-9s %s\n",
257  zone_db_name(zone),
258  key_data_role_text(key),
259  map_keystate(key),
260  tchange);
261 }
262 
263 static void
264 printverboseheader(int sockfd) {
265  client_printf(sockfd, "Keys:\n");
266  client_printf(sockfd, "%-31s %-8s %-9s %-24s %-5s %-10s %-32s %-11s %s\n", "Zone:", "Keytype:", "State:",
267  "Date of next transition:", "Size:", "Algorithm:", "CKA_ID:",
268  "Repository:", "KeyTag:");
269 }
270 
271 static void
272 printverbosekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
273  (void)tchange;
274  client_printf(sockfd,
275  "%-31s %-8s %-9s %-24s %-5d %-10d %-32s %-11s %d\n",
276  zone_db_name(zone),
277  key_data_role_text(key),
278  map_keystate(key),
279  tchange,
280  hsm_key_bits(hsmkey),
281  hsm_key_algorithm(hsmkey),
282  hsm_key_locator(hsmkey),
283  hsm_key_repository(hsmkey),
284  key_data_keytag(key));
285 }
286 
287 static void
288 printFullkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
289  (void)tchange;
290  client_printf(sockfd,
291  "%-31s %-8s %-9s %d %s %-12s %-12s %-12s %-12s %d %4d %s\n",
292  zone_db_name(zone),
293  key_data_role_text(key),
294  map_keystate(key),
295  key_data_keytag(key),
296  hsm_key_locator(hsmkey),
301  key_data_publish(key),
303  tchange);
304 }
305 
306 static void
307 printverboseparsablekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
308  client_printf(sockfd,
309  "%s;%s;%s;%s;%d;%d;%s;%s;%d\n",
310  zone_db_name(zone),
311  key_data_role_text(key),
312  map_keystate(key),
313  tchange,
314  hsm_key_bits(hsmkey),
315  hsm_key_algorithm(hsmkey),
316  hsm_key_locator(hsmkey),
317  hsm_key_repository(hsmkey),
318  key_data_keytag(key));
319 }
320 
321 static void
322 printdebugheader(int sockfd) {
323  client_printf(sockfd,
324  "Keys:\nZone: Key role: "
325  "DS: DNSKEY: RRSIGDNSKEY: RRSIG: "
326  "Pub: Act: Id:\n");
327 }
328 
329 static void
330 printdebugkey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
331  (void)tchange;
332  client_printf(sockfd,
333  "%-31s %-13s %-12s %-12s %-12s %-12s %d %4d %s\n",
334  zone_db_name(zone),
335  key_data_role_text(key),
340  key_data_publish(key),
342  hsm_key_locator(hsmkey));
343 }
344 
345 static void
346 printdebugparsablekey(int sockfd, zone_db_t* zone, key_data_t* key, char* tchange, hsm_key_t* hsmkey) {
347  (void)tchange;
348  client_printf(sockfd,
349  "%s;%s;%s;%s;%s;%s;%d;%d;%s\n",
350  zone_db_name(zone),
351  key_data_role_text(key),
356  key_data_publish(key),
358  hsm_key_locator(hsmkey));
359 }
360 
361 static int
362 run(int sockfd, cmdhandler_ctx_type* context, const char *cmd)
363 {
364  char buf[ODS_SE_MAXLINE];
365  #define NARGV 12
366  const char *argv[NARGV];
367  int success, argIndex;
368  int argc = 0, bVerbose = 0, bDebug = 0, bFull = 0, bParsable = 0, bAll = 0;
369  int long_index = 0, opt = 0;
370  const char* keytype = NULL;
371  const char* keystate = NULL;
372  const char* zonename = NULL;
373  db_connection_t* dbconn = getconnectioncontext(context);
374 
375  static struct option long_options[] = {
376  {"verbose", no_argument, 0, 'v'},
377  {"debug", no_argument, 0, 'd'},
378  {"full", no_argument, 0, 'f'},
379  {"parsable", no_argument, 0, 'p'},
380  {"zone", required_argument, 0, 'z'},
381  {"keytype", required_argument, 0, 't'},
382  {"keystate", required_argument, 0, 'e'},
383  {"all", no_argument, 0, 'a'},
384  {0, 0, 0, 0}
385  };
386 
387  ods_log_debug("[%s] %s command", module_str, key_list_funcblock.cmdname);
388 
389  /* Use buf as an intermediate buffer for the command. */
390  strncpy(buf, cmd, sizeof (buf));
391  buf[sizeof (buf) - 1] = '\0';
392 
393  /* separate the arguments */
394  argc = ods_str_explode(buf, NARGV, argv);
395  if (argc == -1) {
396  ods_log_error("[%s] too many arguments for %s command",
397  module_str, key_list_funcblock.cmdname);
398  client_printf_err(sockfd, "too many arguments\n");
399  return -1;
400  }
401  optind = 0;
402  while ((opt = getopt_long(argc, (char* const*)argv, "vdfpz:t:e:a", long_options, &long_index) ) != -1) {
403  switch (opt) {
404  case 'v':
405  bVerbose = 1;
406  break;
407  case 'd':
408  bDebug = 1;
409  break;
410  case 'f':
411  bFull = 1;
412  break;
413  case 'p':
414  bParsable = 1;
415  break;
416  case 'z':
417  zonename = optarg;
418  break;
419  case 't':
420  keytype = optarg;
421  break;
422  case 'e':
423  keystate = optarg;
424  break;
425  case 'a':
426  bAll = 1;
427  break;
428  default:
429  client_printf_err(sockfd, "unknown arguments\n");
430  ods_log_error("[%s] unknown arguments for %s command",
431  module_str, key_list_funcblock.cmdname);
432  return -1;
433  }
434  }
435 
436  if (keystate != NULL && bAll) {
437  client_printf(sockfd, "Error: --keystate and --all option cannot be given together\n");
438  return -1;
439  }
440 
441  if (bFull) {
442  success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printFullkey);
443  } else if (bDebug) {
444  if (bParsable) {
445  success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printdebugparsablekey);
446  } else {
447  success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printdebugheader, &printdebugkey);
448  }
449  } else if (bVerbose) {
450  if (bParsable) {
451  success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, NULL, &printverboseparsablekey);
452  } else {
453  success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printverboseheader, &printverbosekey);
454  }
455  } else {
456  if (bParsable)
457  client_printf_err(sockfd, "-p option only available in combination with -v and -d.\n");
458  success = perform_keystate_list(sockfd, dbconn, zonename, keytype, keystate, &printcompatheader, &printcompatkey);
459  }
460 
461  return success;
462 }
463 
464 struct cmd_func_block key_list_funcblock = {
465  "key list", &usage, &help, NULL, &run
466 };
key_data_list
Definition: key_data.h:477
KEY_DATA_DS_AT_PARENT_SEEN
Definition: key_data.h:53
RUM
#define RUM
Definition: keystate_list_cmd.c:52
zone_db_id
const db_value_t * zone_db_id(const zone_db_t *zone)
Definition: zone_db.c:728
hsm_key_bits
unsigned int hsm_key_bits(const hsm_key_t *hsm_key)
Definition: hsm_key.c:536
enforcercommands.h
KS_RDY
Definition: keystate_list_cmd.c:57
KEY_DATA_DS_AT_PARENT_INVALID
Definition: key_data.h:49
KEY_DATA_DS_AT_PARENT_SUBMITTED
Definition: key_data.h:52
key_list_funcblock
struct cmd_func_block key_list_funcblock
Definition: keystate_list_cmd.c:464
key_data_cached_ds
const key_state_t * key_data_cached_ds(key_data_t *key_data)
Definition: key_data_ext.c:60
key_state_state_text
const char * key_state_state_text(const key_state_t *key_state)
Definition: key_state.c:377
hsm_key_repository
const char * hsm_key_repository(const hsm_key_t *hsm_key)
Definition: hsm_key.c:568
zone_db_free
void zone_db_free(zone_db_t *zone)
Definition: zone_db.c:325
key_data_role_text
const char * key_data_role_text(const key_data_t *key_data)
Definition: key_data.c:711
key_data_cached_rrsigdnskey
const key_state_t * key_data_cached_rrsigdnskey(key_data_t *key_data)
Definition: key_data_ext.c:72
KEY_DATA_DS_AT_PARENT_RETRACTED
Definition: key_data.h:55
key_data_ds_at_parent_t
enum key_data_ds_at_parent key_data_ds_at_parent_t
key_data_get_zone
zone_db_t * key_data_get_zone(const key_data_t *key_data)
Definition: key_data.c:569
key_data_get_hsm_key
hsm_key_t * key_data_get_hsm_key(const key_data_t *key_data)
Definition: key_data.c:649
key_data_active_zsk
unsigned int key_data_active_zsk(const key_data_t *key_data)
Definition: key_data.c:735
keystate_list_cmd.h
zone_db.h
KS_GEN
Definition: keystate_list_cmd.c:57
zone_db_name
const char * zone_db_name(const zone_db_t *zone)
Definition: zone_db.c:782
KEY_DATA_ROLE_KSK
Definition: key_data.h:42
key_data_ds_at_parent
key_data_ds_at_parent
Definition: key_data.h:48
key_data_free
void key_data_free(key_data_t *key_data)
Definition: key_data.c:304
OMN
#define OMN
Definition: keystate_list_cmd.c:53
zone_db
Definition: zone_db.h:46
KS_MIX
Definition: keystate_list_cmd.c:57
key_data_cache_key_states
int key_data_cache_key_states(key_data_t *key_data)
Definition: key_data_ext.c:33
KEY_DATA_ROLE_ZSK
Definition: key_data.h:43
key_data_role
key_data_role
Definition: key_data.h:40
hsm_key
Definition: hsm_key.h:77
NARGV
#define NARGV
getconnectioncontext
db_connection_t * getconnectioncontext(cmdhandler_ctx_type *context)
Definition: enforcercommands.c:108
KS_PUB
Definition: keystate_list_cmd.c:57
key_data_list_free
void key_data_list_free(key_data_list_t *key_data_list)
Definition: key_data.c:1694
map_keystate
const char * map_keystate(key_data_t *key)
Definition: keystate_list_cmd.c:113
statenames
const char * statenames[]
Definition: keystate_list_cmd.c:58
key_data_publish
unsigned int key_data_publish(const key_data_t *key_data)
Definition: key_data.c:743
key_data_zone_id
const db_value_t * key_data_zone_id(const key_data_t *key_data)
Definition: key_data.c:561
key_state.h
UNR
#define UNR
Definition: keystate_list_cmd.c:54
key_state_state
key_state_state
Definition: key_state.h:49
KS_RET
Definition: keystate_list_cmd.c:57
KEY_DATA_DS_AT_PARENT_SUBMIT
Definition: key_data.h:51
zone_db_next_change
int zone_db_next_change(const zone_db_t *zone)
Definition: zone_db.c:806
KEY_DATA_ROLE_CSK
Definition: key_data.h:44
db_value_cmp
int db_value_cmp(const db_value_t *value_a, const db_value_t *value_b, int *result)
Definition: db_value.c:102
KS_UNK
Definition: keystate_list_cmd.c:57
KS_DEAD
Definition: keystate_list_cmd.c:57
key_data_cached_dnskey
const key_state_t * key_data_cached_dnskey(key_data_t *key_data)
Definition: key_data_ext.c:68
hsm_key_locator
const char * hsm_key_locator(const hsm_key_t *hsm_key)
Definition: hsm_key.c:520
engine.h
hsm_key.h
key_data_active_ksk
unsigned int key_data_active_ksk(const key_data_t *key_data)
Definition: key_data.c:751
KEY_DATA_DS_AT_PARENT_RETRACT
Definition: key_data.h:54
db_connection
Definition: db_connection.h:46
key_data_keytag
unsigned int key_data_keytag(const key_data_t *key_data)
Definition: key_data.c:767
key_data_introducing
unsigned int key_data_introducing(const key_data_t *key_data)
Definition: key_data.c:727
hsm_key_free
void hsm_key_free(hsm_key_t *hsm_key)
Definition: hsm_key.c:286
key_data_list_get_next
key_data_t * key_data_list_get_next(key_data_list_t *key_data_list)
Definition: key_data.c:2425
key_data_cached_rrsig
const key_state_t * key_data_cached_rrsig(key_data_t *key_data)
Definition: key_data_ext.c:64
HID
#define HID
Definition: keystate_list_cmd.c:51
KEY_DATA_DS_AT_PARENT_UNSUBMITTED
Definition: key_data.h:50
hsm_key_algorithm
unsigned int hsm_key_algorithm(const hsm_key_t *hsm_key)
Definition: hsm_key.c:544
key_data
Definition: key_data.h:66
KS_ACT
Definition: keystate_list_cmd.c:57
key_data_list_new_get
key_data_list_t * key_data_list_new_get(const db_connection_t *connection)
Definition: key_data.c:2102