OpenDNSSEC-enforcer  1.3.15
enforcer.c
Go to the documentation of this file.
1 /*
2  * $Id: enforcer.c 7213 2013-08-09 14:11:22Z sara $
3  *
4  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
29 /*
30  * enforcer.c code implements the server_main
31  * function needed by daemon.c
32  *
33  * The bit that makes the daemon do something useful
34  */
35 
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <syslog.h>
41 
42 #include <libxml/xmlreader.h>
43 #include <libxml/xpath.h>
44 
45 #include "config.h"
46 
47 #include "daemon.h"
48 #include "daemon_util.h"
49 #include "enforcer.h"
50 #include "kaspaccess.h"
51 
52 #include "ksm/ksm.h"
53 #include "ksm/memory.h"
54 #include "ksm/string_util.h"
55 #include "ksm/string_util2.h"
56 #include "ksm/datetime.h"
57 #include "ksm/db_fields.h"
58 
59 #include "libhsm.h"
60 #include "libhsmdns.h"
61 
62  int
64 {
65  if (config == NULL) {
66  log_msg(NULL, LOG_ERR, "Error in server_init, no config provided");
67  exit(1);
68  }
69 
70  /* set the default pidfile if nothing was provided on the command line*/
71  if (config->pidfile == NULL) {
72  config->pidfile = OPENDNSSEC_ENFORCER_PIDFILE;
73  }
74 
75  return 0;
76 }
77 
78 /*
79  * Main loop of enforcerd server
80  */
81  void
83 {
84  DB_RESULT handle;
85  DB_HANDLE dbhandle;
86  int status = 0;
87  struct timeval tv;
88  KSM_POLICY *policy;
89  int result;
90  hsm_ctx_t *ctx = NULL;
91  char *hsm_error_message = NULL;
92 
93  FILE *lock_fd = NULL; /* for sqlite file locking */
94  char *lock_filename = NULL;
95 
96  if (config == NULL) {
97  log_msg(NULL, LOG_ERR, "Error in server_main, no config provided");
98  exit(1);
99  }
100 
101  policy = KsmPolicyAlloc();
102  if (policy == NULL) {
103  log_msg(config, LOG_ERR, "Malloc for policy struct failed");
104  exit(1);
105  }
106  kaspSetPolicyDefaults(policy, NULL);
107 
108  /* Read the config file */
109  status = ReadConfig(config , 0);
110  if (status != 0) {
111  log_msg(config, LOG_ERR, "Error reading config");
112  exit(1);
113  }
114 
115  /* If we are doing key generation then connect to the hsm */
116 /* if (config->manualKeyGeneration == 0) {*/
117  /* We keep the HSM connection open for the lifetime of the daemon */
118  if (config->configfile != NULL) {
119  result = hsm_open(config->configfile, hsm_prompt_pin, NULL);
120  } else {
121  result = hsm_open(OPENDNSSEC_CONFIG_FILE, hsm_prompt_pin, NULL);
122  }
123  if (result) {
124  hsm_error_message = hsm_get_error(ctx);
125  if (hsm_error_message) {
126  log_msg(config, LOG_ERR, "%s", hsm_error_message);
127  free(hsm_error_message);
128  } else {
129  /* decode the error code ourselves
130  TODO find if there is a better way to do this (and can all of these be returned? are there others?) */
131  switch (result) {
132  case HSM_ERROR:
133  log_msg(config, LOG_ERR, "hsm_open() result: HSM error");
134  break;
135  case HSM_PIN_INCORRECT:
136  log_msg(config, LOG_ERR, "hsm_open() result: incorrect PIN");
137  break;
138  case HSM_CONFIG_FILE_ERROR:
139  log_msg(config, LOG_ERR, "hsm_open() result: config file error");
140  break;
141  case HSM_REPOSITORY_NOT_FOUND:
142  log_msg(config, LOG_ERR, "hsm_open() result: repository not found");
143  break;
144  case HSM_NO_REPOSITORIES:
145  log_msg(config, LOG_ERR, "hsm_open() result: no repositories");
146  break;
147  default:
148  log_msg(config, LOG_ERR, "hsm_open() result: %d", result);
149  }
150  }
151  exit(1);
152  }
153  log_msg(config, LOG_INFO, "HSM opened successfully.");
154  ctx = hsm_create_context();
155  /*}*/
156 
157  log_msg(config, LOG_INFO, "Checking database connection...");
158  if (kaspTryConnect(config, &dbhandle)) {
159  log_msg(config, LOG_ERR, "Database connection failed");
160  exit(1);
161  }
162  log_msg(config, LOG_INFO, "Database connection ok.");
163 
164  /* Create pidfile as late as possible to report start up error */
165  if (writepid(config) == -1) {
166  log_msg(config, LOG_ERR, "cannot write the pidfile %s: %s",
167  config->pidfile, strerror(errno));
168  exit(1);
169  }
170 
171  while (1) {
172 
173  /* Read the config file */
174  status = ReadConfig(config, 1);
175  if (status != 0) {
176  log_msg(config, LOG_ERR, "Error reading config");
177  unlink(config->pidfile);
178  exit(1);
179  }
180  /* If we are in sqlite mode then take a lock out on a file to
181  prevent multiple access (not sure that we can be sure that sqlite is
182  safe for multiple processes to access). */
183  if (DbFlavour() == SQLITE_DB) {
184 
185  /* set up lock filename (it may have changed?) */
186  lock_filename = NULL;
187  StrAppend(&lock_filename, (char *)config->schema);
188  StrAppend(&lock_filename, ".our_lock");
189 
190  lock_fd = fopen(lock_filename, "w");
191  status = get_lite_lock(lock_filename, lock_fd);
192  StrFree(lock_filename);
193  if (status != 0) {
194  log_msg(config, LOG_ERR, "Error getting db lock");
195  unlink(config->pidfile);
196  exit(1);
197  }
198  }
199 
200  log_msg(config, LOG_INFO, "Connecting to Database...");
201  kaspConnect(config, &dbhandle);
202 
203  /* Read all policies */
204  status = KsmPolicyInit(&handle, NULL);
205  if (status == 0) {
206  /* get the first policy */
207  status = KsmPolicy(handle, policy);
208  while (status == 0) {
209  log_msg(config, LOG_INFO, "Policy %s found.", policy->name);
210  /* Clear the policy struct */
211  kaspSetPolicyDefaults(policy, NULL);
212 
213  /* Read the parameters for that policy */
214  status = kaspReadPolicy(policy);
215 
216  /* Update the salt if it is not up to date */
217  if (policy->denial->version == 3)
218  {
219  status = KsmPolicyUpdateSalt(policy);
220  if (status != 0) {
221  /* Don't return? */
222  log_msg(config, LOG_ERR, "Error (%d) updating salt for %s", status, policy->name);
223  }
224  }
225 
226  /* Do keygen stuff if required */
227  if (config->manualKeyGeneration == 0) {
228  status = do_keygen(config, policy, ctx);
229  }
230 
231  /* TODO move communicated stuff here eventually */
232  /* Find all zones and do communication stuff */
233 
234  /* Purge dead keys if we are asked to in this policy */
235  if (policy->keys->purge != -1) {
236  status = do_purge(policy->keys->purge, policy->id);
237  }
238 
239  /* get next policy */
240  status = KsmPolicy(handle, policy);
241  }
242  } else {
243  log_msg(config, LOG_ERR, "Error querying KASP DB for policies.");
244  unlink(config->pidfile);
245  exit(1);
246  }
247 
248  /* Communicate zones to the signer */
249  KsmParameterCollectionCache(1); /* Enable caching of policy parameters while in do_communication() */
250  do_communication(config, policy);
252 
253  DbFreeResult(handle);
254 
255  /* Disconnect from DB in case we are asleep for a long time */
256  log_msg(config, LOG_INFO, "Disconnecting from Database...");
257  kaspDisconnect(&dbhandle);
258 
259  /* Release sqlite lock file (if we have it) */
260  if (DbFlavour() == SQLITE_DB) {
261  status = release_lite_lock(lock_fd);
262  if (status != 0) {
263  log_msg(config, LOG_ERR, "Error releasing db lock");
264  unlink(config->pidfile);
265  exit(1);
266  }
267  fclose(lock_fd);
268  }
269 
270  if (config->once == true ){
271  log_msg(config, LOG_INFO, "Running once only, exiting...");
272  break;
273  }
274 
275  /* If we have been sent a SIGTERM then it is time to exit */
276  if (config->term == 1 ){
277  log_msg(config, LOG_INFO, "Received SIGTERM, exiting...");
278  break;
279  }
280  /* Or SIGINT */
281  if (config->term == 2 ){
282  log_msg(config, LOG_INFO, "Received SIGINT, exiting...");
283  break;
284  }
285 
286  /* sleep for the interval */
287  tv.tv_sec = config->interval;
288  tv.tv_usec = 0;
289  log_msg(config, LOG_INFO, "Sleeping for %i seconds.",config->interval);
290  select(0, NULL, NULL, NULL, &tv);
291 
292  /* If we have been sent a SIGTERM then it is time to exit */
293  if (config->term == 1 ){
294  log_msg(config, LOG_INFO, "Received SIGTERM, exiting...");
295  break;
296  }
297  /* Or SIGINT */
298  if (config->term == 2 ){
299  log_msg(config, LOG_INFO, "Received SIGINT, exiting...");
300  break;
301  }
302 
303  /* Make sure that we can still talk to the HSM; this call exits if
304  we can not (after trying to reconnect) */
305  check_hsm_connection(&ctx, config);
306 
307  }
308 
309  /*
310  * Destroy HSM context
311  */
312  if (ctx) {
313  hsm_destroy_context(ctx);
314  }
315 
316  result = hsm_close();
317  log_msg(config, LOG_INFO, "all done! hsm_close result: %d", result);
318 
319  KsmPolicyFree(policy);
320 
321  if (unlink(config->pidfile) == -1) {
322  log_msg(config, LOG_ERR, "unlink pidfile %s failed: %s",
323  config->pidfile?config->pidfile:"(null)",
324  strerror(errno));
325  }
326 
327  xmlCleanupParser();
328 
329 }
330 
331 int do_keygen(DAEMONCONFIG *config, KSM_POLICY* policy, hsm_ctx_t *ctx)
332 {
333  int status = 0;
334 
335  char *rightnow;
336  int i = 0;
337  char *id;
338  hsm_key_t *key = NULL;
339  char *hsm_error_message = NULL;
340  DB_ID ignore = 0;
341  int ksks_needed = 0; /* Total No of ksks needed before next generation run */
342  int zsks_needed = 0; /* Total No of zsks needed before next generation run */
343  int keys_in_queue = 0; /* number of unused keys */
344  int new_keys = 0; /* number of keys required */
345  unsigned int current_count = 0; /* number of keys already in HSM */
346 
347  int same_keys = 0; /* Do ksks and zsks look the same ? */
348  int ksks_created = 0; /* Were any KSKs created? */
349 
350  DB_RESULT result;
351  int zone_count = 0; /* Number of zones on policy */
352 
353  if (policy->shared_keys == 1 ) {
354  log_msg(config, LOG_INFO, "Key sharing is On");
355  } else {
356  log_msg(config, LOG_INFO, "Key sharing is Off.");
357  }
358 
359  rightnow = DtParseDateTimeString("now");
360 
361  /* Check datetime in case it came back NULL */
362  if (rightnow == NULL) {
363  log_msg(config, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
364  exit(1);
365  }
366 
367  /* See if our ZSKs and KSKs look the same */
368  if (policy->ksk->sm == policy->zsk->sm && policy->ksk->bits == policy->zsk->bits && policy->ksk->algorithm == policy->zsk->algorithm) {
369  same_keys = 1;
370  } else {
371  same_keys = 0;
372  }
373 
374  /* How many zones on this policy */
375  status = KsmZoneCountInit(&result, policy->id);
376  if (status == 0) {
377  status = KsmZoneCount(result, &zone_count);
378  }
379  DbFreeResult(result);
380 
381  if (status == 0) {
382  /* make sure that we have at least one zone */
383  if (zone_count == 0) {
384  log_msg(config, LOG_INFO, "No zones on policy %s, skipping...", policy->name);
385  StrFree(rightnow);
386  return status;
387  }
388  } else {
389  log_msg(NULL, LOG_ERR, "Could not count zones on policy %s", policy->name);
390  StrFree(rightnow);
391  return status;
392  }
393  log_msg(config, LOG_INFO, "%d zone(s) found on policy \"%s\"\n", zone_count, policy->name);
394 
395  /* Find out how many ksk keys are needed for the POLICY */
396  status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, config->interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count);
397  if (status != 0) {
398  log_msg(NULL, LOG_ERR, "Could not predict ksk requirement for next interval for %s", policy->name);
399  /* TODO exit? continue with next policy? */
400  }
401  /* Find out how many suitable keys we have */
402  status = KsmKeyCountStillGood(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, config->interval, rightnow, &keys_in_queue, KSM_TYPE_KSK);
403  if (status != 0) {
404  log_msg(NULL, LOG_ERR, "Could not count current ksk numbers for policy %s", policy->name);
405  /* TODO exit? continue with next policy? */
406  }
407  /* Don't have to adjust the queue for shared keys as the prediction has already taken care of that.*/
408 
409  new_keys = ksks_needed - keys_in_queue;
410  /* fprintf(stderr, "keygen(ksk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, ksks_needed, keys_in_queue); */
411 
412  /* Check capacity of HSM will not be exceeded */
413  if (policy->ksk->sm_capacity != 0 && new_keys >= 0) {
414  current_count = hsm_count_keys_repository(ctx, policy->ksk->sm_name);
415  if (current_count >= policy->ksk->sm_capacity) {
416  log_msg(config, LOG_ERR, "Repository %s is full, cannot create more KSKs for policy %s\n", policy->ksk->sm_name, policy->name);
417  new_keys = 0;
418  }
419  else if (current_count + new_keys > policy->ksk->sm_capacity) {
420  log_msg(config, LOG_WARNING, "Repository %s is nearly full, will create %lu KSKs for policy %s (reduced from %d)\n", policy->ksk->sm_name, policy->ksk->sm_capacity - current_count, policy->name, new_keys);
421  new_keys = policy->ksk->sm_capacity - current_count;
422  }
423  }
424  if (new_keys <= 0 ) {
425  log_msg(config, LOG_INFO,"No new KSKs need to be created.\n");
426  }
427  else {
428  log_msg(config, LOG_INFO,"%d new KSK(s) (%d bits) need to be created.\n", new_keys, policy->ksk->bits);
429  }
430 
431  /* Create the required keys */
432  for (i=new_keys ; i > 0 ; i--){
433  if (hsm_supported_algorithm(policy->ksk->algorithm) == 0) {
434  /* NOTE: for now we know that libhsm only supports RSA keys */
435  key = hsm_generate_rsa_key(ctx, policy->ksk->sm_name, policy->ksk->bits);
436  if (key) {
437  log_msg(config, LOG_DEBUG, "Created key in repository %s", policy->ksk->sm_name);
438  } else {
439  log_msg(config, LOG_ERR, "Error creating key in repository %s", policy->ksk->sm_name);
440  hsm_error_message = hsm_get_error(ctx);
441  if (hsm_error_message) {
442  log_msg(config, LOG_ERR, "%s", hsm_error_message);
443  free(hsm_error_message);
444  }
445  unlink(config->pidfile);
446  exit(1);
447  }
448  id = hsm_get_key_id(ctx, key);
449  hsm_key_free(key);
450  status = KsmKeyPairCreate(policy->id, id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, rightnow, &ignore);
451  if (status != 0) {
452  log_msg(config, LOG_ERR,"Error creating key in Database");
453  hsm_error_message = hsm_get_error(ctx);
454  if (hsm_error_message) {
455  log_msg(config, LOG_ERR, "%s", hsm_error_message);
456  free(hsm_error_message);
457  }
458  unlink(config->pidfile);
459  exit(1);
460  }
461  log_msg(config, LOG_INFO, "Created KSK size: %i, alg: %i with id: %s in repository: %s and database.", policy->ksk->bits,
462  policy->ksk->algorithm, id, policy->ksk->sm_name);
463  free(id);
464  } else {
465  log_msg(config, LOG_ERR, "Key algorithm %d unsupported by libhsm, exiting...", policy->ksk->algorithm);
466  unlink(config->pidfile);
467  exit(1);
468  }
469  }
470  ksks_created = new_keys;
471 
472  /* Find out how many zsk keys are needed */
473  keys_in_queue = 0;
474  new_keys = 0;
475  current_count = 0;
476 
477  /* Find out how many zsk keys are needed for the POLICY */
478  status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, config->interval, &zsks_needed, 0, zone_count);
479  if (status != 0) {
480  log_msg(NULL, LOG_ERR, "Could not predict zsk requirement for next intervalfor %s", policy->name);
481  /* TODO exit? continue with next policy? */
482  }
483  /* Find out how many suitable keys we have */
484  status = KsmKeyCountStillGood(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, config->interval, rightnow, &keys_in_queue, KSM_TYPE_ZSK);
485  if (status != 0) {
486  log_msg(NULL, LOG_ERR, "Could not count current zsk numbers for policy %s", policy->name);
487  /* TODO exit? continue with next policy? */
488  }
489  /* Don't have to adjust the queue for shared keys as the prediction has already taken care of that.*/
490  /* Might have to account for ksks */
491  if (same_keys) {
492  keys_in_queue -= ksks_needed;
493  }
494 
495  new_keys = zsks_needed - keys_in_queue;
496  /* fprintf(stderr, "keygen(zsk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, zsks_needed, keys_in_queue); */
497 
498  /* Check capacity of HSM will not be exceeded */
499  if (policy->zsk->sm_capacity != 0 && new_keys >= 0) {
500  current_count = hsm_count_keys_repository(ctx, policy->zsk->sm_name);
501  if (current_count >= policy->zsk->sm_capacity) {
502  log_msg(config, LOG_ERR, "Repository %s is full, cannot create more ZSKs for policy %s\n", policy->zsk->sm_name, policy->name);
503  new_keys = 0;
504  }
505  else if (current_count + new_keys > policy->zsk->sm_capacity) {
506  log_msg(config, LOG_WARNING, "Repository %s is nearly full, will create %lu ZSKs for policy %s (reduced from %d)\n", policy->zsk->sm_name, policy->zsk->sm_capacity - current_count, policy->name, new_keys);
507  new_keys = policy->zsk->sm_capacity - current_count;
508  }
509  }
510 
511  if (new_keys <= 0 ) {
512  /* Don't exit here, just fall through to the end */
513  log_msg(config, LOG_INFO, "No new ZSKs need to be created.\n");
514  }
515  else {
516  log_msg(config, LOG_INFO, "%d new ZSK(s) (%d bits) need to be created.\n", new_keys, policy->zsk->bits);
517  }
518 
519  /* Create the required keys */
520  for (i = new_keys ; i > 0 ; i--) {
521  if (hsm_supported_algorithm(policy->zsk->algorithm) == 0) {
522  /* NOTE: for now we know that libhsm only supports RSA keys */
523  key = hsm_generate_rsa_key(ctx, policy->zsk->sm_name, policy->zsk->bits);
524  if (key) {
525  log_msg(config, LOG_DEBUG, "Created key in repository %s", policy->zsk->sm_name);
526  } else {
527  log_msg(config, LOG_ERR, "Error creating key in repository %s", policy->zsk->sm_name);
528  hsm_error_message = hsm_get_error(ctx);
529  if (hsm_error_message) {
530  log_msg(config, LOG_ERR, "%s", hsm_error_message);
531  free(hsm_error_message);
532  }
533  unlink(config->pidfile);
534  hsm_key_free(key);
535  exit(1);
536  }
537  id = hsm_get_key_id(ctx, key);
538  hsm_key_free(key);
539  status = KsmKeyPairCreate(policy->id, id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, rightnow, &ignore);
540  if (status != 0) {
541  log_msg(config, LOG_ERR,"Error creating key in Database");
542  hsm_error_message = hsm_get_error(ctx);
543  if (hsm_error_message) {
544  log_msg(config, LOG_ERR, "%s", hsm_error_message);
545  free(hsm_error_message);
546  }
547  unlink(config->pidfile);
548  exit(1);
549  }
550  log_msg(config, LOG_INFO, "Created ZSK size: %i, alg: %i with id: %s in repository: %s and database.", policy->zsk->bits,
551  policy->zsk->algorithm, id, policy->zsk->sm_name);
552  free(id);
553  } else {
554  log_msg(config, LOG_ERR, "Key algorithm %d unsupported by libhsm, exiting...", policy->zsk->algorithm);
555  unlink(config->pidfile);
556  exit(1);
557  }
558  }
559  StrFree(rightnow);
560 
561  /* Log if a backup needs to be run for these keys */
562  if (ksks_created && policy->ksk->require_backup) {
563  log_msg(config, LOG_INFO, "NOTE: keys generated in repository %s will not become active until they have been backed up", policy->ksk->sm_name);
564  }
565  if (new_keys && policy->zsk->require_backup && (policy->zsk->sm != policy->ksk->sm)) {
566  log_msg(config, LOG_INFO, "NOTE: keys generated in repository %s will not become active until they have been backed up", policy->zsk->sm_name);
567  }
568 
569  return status;
570 }
571 
573 {
574  int status = 0;
575  int status2 = 0;
576 
577  xmlTextReaderPtr reader = NULL;
578  xmlDocPtr doc = NULL;
579  xmlXPathContextPtr xpathCtx = NULL;
580  xmlXPathObjectPtr xpathObj = NULL;
581 
582  int ret = 0; /* status of the XML parsing */
583  char* zonelist_filename = NULL;
584  char* zone_name;
585  char* current_policy;
586  char* current_filename;
587  char *tag_name;
588  int zone_id = -1;
589  int signer_flag = 1; /* Is the signer responding? (1 == yes) */
590  char* ksk_expected = NULL; /* When is the next ksk rollover expected? */
591 
592  xmlChar *name_expr = (unsigned char*) "name";
593  xmlChar *policy_expr = (unsigned char*) "//Zone/Policy";
594  xmlChar *filename_expr = (unsigned char*) "//Zone/SignerConfiguration";
595 
596  char* temp_char = NULL;
597 
598  /* Stuff to see if we need to log an "impending rollover" warning */
599  char* datetime = NULL;
600  int roll_time = 0;
601 
602  /* Let's find our zonelist from the conf.xml */
603  if (config->configfile != NULL) {
604  status = read_zonelist_filename(config->configfile, &zonelist_filename);
605  } else {
606  status = read_zonelist_filename(OPENDNSSEC_CONFIG_FILE, &zonelist_filename);
607  }
608 
609  if (status != 0) {
610  log_msg(NULL, LOG_ERR, "couldn't read zonelist filename");
611  unlink(config->pidfile);
612  exit(1);
613  }
614 
615  /* In case zonelist is huge use the XmlTextReader API so that we don't hold the whole file in memory */
616  reader = xmlNewTextReaderFilename(zonelist_filename);
617  if (reader != NULL) {
618  ret = xmlTextReaderRead(reader);
619  while (ret == 1) {
620  tag_name = (char*) xmlTextReaderLocalName(reader);
621  /* Found <Zone> */
622  if (strncmp(tag_name, "Zone", 4) == 0
623  && strncmp(tag_name, "ZoneList", 8) != 0
624  && xmlTextReaderNodeType(reader) == 1) {
625  /* Get the zone name (TODO what if this is null?) */
626  zone_name = NULL;
627  temp_char = (char*) xmlTextReaderGetAttribute(reader, name_expr);
628  StrAppend(&zone_name, temp_char);
629  StrFree(temp_char);
630  /* Make sure that we got something */
631  if (zone_name == NULL) {
632  /* error */
633  log_msg(NULL, LOG_ERR, "Error extracting zone name from %s", zonelist_filename);
634  /* Don't return? try to parse the rest of the zones? */
635  ret = xmlTextReaderRead(reader);
636  StrFree(tag_name);
637  continue;
638  }
639 
640 
641  log_msg(config, LOG_INFO, "Zone %s found.", zone_name);
642 
643  /* Get zone ID from name (or skip if it doesn't exist) */
644  status = KsmZoneIdFromName(zone_name, &zone_id);
645  if (status != 0 || zone_id == -1)
646  {
647  /* error */
648  log_msg(NULL, LOG_ERR, "Error looking up zone \"%s\" in database (please make sure that the zonelist file is up to date)", zone_name);
649  /* Don't return? try to parse the rest of the zones? */
650  ret = xmlTextReaderRead(reader);
651  StrFree(tag_name);
652  StrFree(zone_name);
653  continue;
654  }
655 
656  /* Expand this node and get the rest of the info with XPath */
657  xmlTextReaderExpand(reader);
658  doc = xmlTextReaderCurrentDoc(reader);
659  if (doc == NULL) {
660  log_msg(config, LOG_ERR, "Error: can not read zone \"%s\"; skipping", zone_name);
661  /* Don't return? try to parse the rest of the zones? */
662  ret = xmlTextReaderRead(reader);
663  StrFree(tag_name);
664  StrFree(zone_name);
665  continue;
666  }
667 
668  /* TODO should we validate here? Or should we validate the whole document? */
669 
670  xpathCtx = xmlXPathNewContext(doc);
671  if(xpathCtx == NULL) {
672  log_msg(config, LOG_ERR,"Error: can not create XPath context for \"%s\"; skipping zone", zone_name);
673  /* Don't return? try to parse the rest of the zones? */
674  ret = xmlTextReaderRead(reader);
675  StrFree(tag_name);
676  StrFree(zone_name);
677  continue;
678  }
679 
680  /* Extract the Policy name and signer configuration filename for this zone */
681  /* Evaluate xpath expression for policy */
682  xpathObj = xmlXPathEvalExpression(policy_expr, xpathCtx);
683  if(xpathObj == NULL) {
684  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s; skipping zone", policy_expr);
685  /* Don't return? try to parse the rest of the zones? */
686  ret = xmlTextReaderRead(reader);
687  StrFree(tag_name);
688  StrFree(zone_name);
689  continue;
690  }
691  current_policy = NULL;
692  temp_char = (char*) xmlXPathCastToString(xpathObj);
693  StrAppend(&current_policy, temp_char);
694  StrFree(temp_char);
695  log_msg(config, LOG_INFO, "Policy for %s set to %s.", zone_name, current_policy);
696  xmlXPathFreeObject(xpathObj);
697 
698  if (strcmp(current_policy, policy->name) != 0) {
699 
700  /* Read new Policy */
701  kaspSetPolicyDefaults(policy, current_policy);
702 
703  status2 = KsmPolicyRead(policy);
704  if (status2 != 0) {
705  /* Don't return? try to parse the rest of the zones? */
706  log_msg(config, LOG_ERR, "Error reading policy");
707  ret = xmlTextReaderRead(reader);
708  StrFree(tag_name);
709  StrFree(zone_name);
710  continue;
711  }
712  log_msg(config, LOG_INFO, "Policy %s found in DB.", policy->name);
713 
714  } /* else */
715  /* Policy is same as previous zone, do not re-read */
716 
717  StrFree(current_policy);
718 
719  /* Evaluate xpath expression for signer configuration filename */
720  xpathObj = xmlXPathEvalExpression(filename_expr, xpathCtx);
721  xmlXPathFreeContext(xpathCtx);
722 
723  if(xpathObj == NULL) {
724  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s; skipping zone", filename_expr);
725  /* Don't return? try to parse the rest of the zones? */
726  ret = xmlTextReaderRead(reader);
727  StrFree(tag_name);
728  StrFree(zone_name);
729  continue;
730  }
731  current_filename = NULL;
732  temp_char = (char*)xmlXPathCastToString(xpathObj);
733  StrAppend(&current_filename, temp_char);
734  StrFree(temp_char);
735  log_msg(config, LOG_INFO, "Config will be output to %s.", current_filename);
736  xmlXPathFreeObject(xpathObj);
737  /* TODO should we check that we have not written to this file in this run?*/
738  /* Make sure that enough keys are allocated to this zone */
739  status2 = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, 0);
740  if (status2 != 0) {
741  log_msg(config, LOG_ERR, "Error allocating zsks to zone %s", zone_name);
742  /* Don't return? try to parse the rest of the zones? */
743  ret = xmlTextReaderRead(reader);
744  StrFree(tag_name);
745  StrFree(zone_name);
746  StrFree(current_filename);
747  continue;
748  }
749  status2 = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, policy->ksk->rollover_scheme);
750  if (status2 != 0) {
751  log_msg(config, LOG_ERR, "Error allocating ksks to zone %s", zone_name);
752  /* Don't return? try to parse the rest of the zones? */
753  ret = xmlTextReaderRead(reader);
754  StrFree(tag_name);
755  StrFree(zone_name);
756  StrFree(current_filename);
757  continue;
758  }
759 
760  /* turn this zone and policy into a file */
761  status2 = commGenSignConf(zone_name, zone_id, current_filename, policy, &signer_flag, config->interval, config->manualKeyGeneration, config->DSSubmitCmd);
762  if (status2 == -2) {
763  log_msg(config, LOG_ERR, "Signconf not written for %s", zone_name);
764  /* Don't return? try to parse the rest of the zones? */
765  ret = xmlTextReaderRead(reader);
766  StrFree(tag_name);
767  StrFree(zone_name);
768  StrFree(current_filename);
769  continue;
770  }
771  else if (status2 != 0) {
772  log_msg(config, LOG_ERR, "Error writing signconf for %s", zone_name);
773  /* Don't return? try to parse the rest of the zones? */
774  ret = xmlTextReaderRead(reader);
775  StrFree(tag_name);
776  StrFree(zone_name);
777  StrFree(current_filename);
778  continue;
779  }
780 
781  /* See if we need to send a warning about an impending rollover */
782  if (config->rolloverNotify != -1) {
783  datetime = DtParseDateTimeString("now");
784 
785  /* Check datetime in case it came back NULL */
786  if (datetime == NULL) {
787  log_msg(config, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
788  unlink(config->pidfile);
789  exit(1);
790  }
791 
792  /* First the KSK */
793  status2 = KsmCheckNextRollover(KSM_TYPE_KSK, zone_id, &ksk_expected);
794  if (status2 == -1) {
795  log_msg(config, LOG_INFO, "No active KSKs yet for zone %s, can't check for impending rollover", zone_name);
796  }
797  else if (status2 != 0) {
798  log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
799  /* TODO should we quit or continue? */
800  } else {
801  status2 = DtDateDiff(ksk_expected, datetime, &roll_time);
802  if (status2 != 0) {
803  log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
804  } else {
805 
806  if (roll_time <= config->rolloverNotify) {
807  log_msg(config, LOG_INFO, "Rollover of KSK expected at %s for %s", ksk_expected, zone_name);
808  }
809  StrFree(ksk_expected);
810  }
811  }
812  StrFree(datetime);
813  }
814 
815  StrFree(current_filename);
816  StrFree(zone_name);
817  }
818  /* Read the next line */
819  ret = xmlTextReaderRead(reader);
820  StrFree(tag_name);
821  }
822  xmlFreeTextReader(reader);
823  if (ret != 0) {
824  log_msg(config, LOG_ERR, "%s : failed to parse", zonelist_filename);
825  }
826  } else {
827  log_msg(config, LOG_ERR, "Unable to open %s", zonelist_filename);
828  }
829 
830  xmlFreeDoc(doc);
831  StrFree(zonelist_filename);
832 
833  return status;
834 }
835 
836 /*
837  * generate the configuration file for the signer
838 
839  * returns 0 on success and -1 if something went wrong
840  * -2 if the RequestKeys call failed
841  */
842 int commGenSignConf(char* zone_name, int zone_id, char* current_filename, KSM_POLICY *policy, int* signer_flag, int run_interval, int man_key_gen, const char* DSSubmitCmd)
843 {
844  int status = 0;
845  int status2 = 0;
846  FILE *file, *file2;
847  int char1, char2; /* for the comparison between 2 files */
848  int same = 0;
849  char *temp_filename; /* In case this fails we write to a temp file and only overwrite
850  the current file when we are finished */
851  char *old_filename; /* Keep a copy of the previous version, just in case! (Also gets
852  round potentially different behaviour of rename over existing
853  file.) */
854  char *signer_command; /* how we will call the signer */
855  int gencnt; /* Number of keys in generate state */
856  int NewDS = 0; /* Did we change the DS Set in any way? */
857  char* datetime = DtParseDateTimeString("now");
858 
859  /* Check datetime in case it came back NULL */
860  if (datetime == NULL) {
861  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
862  exit(1);
863  }
864 
865  if (zone_name == NULL || current_filename == NULL || policy == NULL)
866  {
867  /* error */
868  log_msg(NULL, LOG_ERR, "commGenSignConf, NULL policy or zone provided");
869  MemFree(datetime);
870  return -1;
871  }
872 
873  old_filename = NULL;
874  StrAppend(&old_filename, current_filename);
875  StrAppend(&old_filename, ".OLD");
876 
877  temp_filename = NULL;
878  StrAppend(&temp_filename, current_filename);
879  StrAppend(&temp_filename, ".tmp");
880 
881  file = fopen(temp_filename, "w");
882 
883  if (file == NULL)
884  {
885  /* error */
886  log_msg(NULL, LOG_ERR, "Could not open: %s", temp_filename);
887  MemFree(datetime);
888  StrFree(temp_filename);
889  StrFree(old_filename);
890  return -1;
891  }
892 
893  fprintf(file, "<SignerConfiguration>\n");
894  fprintf(file, "\t<Zone name=\"%s\">\n", zone_name);
895 
896  fprintf(file, "\t\t<Signatures>\n");
897  fprintf(file, "\t\t\t<Resign>PT%dS</Resign>\n", policy->signature->resign);
898  fprintf(file, "\t\t\t<Refresh>PT%dS</Refresh>\n", policy->signer->refresh);
899  fprintf(file, "\t\t\t<Validity>\n");
900  fprintf(file, "\t\t\t\t<Default>PT%dS</Default>\n", policy->signature->valdefault);
901  fprintf(file, "\t\t\t\t<Denial>PT%dS</Denial>\n", policy->signature->valdenial);
902  fprintf(file, "\t\t\t</Validity>\n");
903  fprintf(file, "\t\t\t<Jitter>PT%dS</Jitter>\n", policy->signer->jitter);
904  fprintf(file, "\t\t\t<InceptionOffset>PT%dS</InceptionOffset>\n", policy->signature->clockskew);
905  fprintf(file, "\t\t</Signatures>\n");
906 
907  fprintf(file, "\n");
908 
909  fprintf(file, "\t\t<Denial>\n");
910  if (policy->denial->version == 3)
911  {
912  fprintf(file, "\t\t\t<NSEC3>\n");
913  if (policy->denial->optout == 1)
914  {
915  fprintf(file, "\t\t\t\t<OptOut />\n");
916  }
917  fprintf(file, "\t\t\t\t<Hash>\n");
918  fprintf(file, "\t\t\t\t\t<Algorithm>%d</Algorithm>\n", policy->denial->algorithm);
919  fprintf(file, "\t\t\t\t\t<Iterations>%d</Iterations>\n", policy->denial->iteration);
920  if (policy->denial->salt[0] == '\0') {
921  fprintf(file, "\t\t\t\t\t<Salt>-</Salt>\n");
922  } else {
923  fprintf(file, "\t\t\t\t\t<Salt>%s</Salt>\n", policy->denial->salt);
924  }
925  fprintf(file, "\t\t\t\t</Hash>\n");
926  fprintf(file, "\t\t\t</NSEC3>\n");
927  } else {
928  fprintf(file, "\t\t\t<NSEC />\n");
929  }
930 
931  fprintf(file, "\t\t</Denial>\n");
932 
933  fprintf(file, "\n");
934 
935  /* start of keys section */
936  fprintf(file, "\t\t<Keys>\n");
937  fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->ksk->ttl);
938 
939  /* get new keys _only_ if we don't have them from before */
940  status = KsmRequestKeys(0, 0, datetime, commKeyConfig, file, policy->id, zone_id, run_interval, &NewDS);
941  if (status != 0) {
942  /*
943  * Something went wrong (it should have been logged) stop this zone.
944  * Clean up the files, don't call the signer and move on to the next zone.
945  */
946  log_msg(NULL, LOG_ERR, "KsmRequestKeys returned: %d", status);
947 
948  /* check for the specific case of not having any keys
949  TODO check that this code can ever be executed after the restructure */
950  if (status == -1) {
951  status2 = KsmRequestGenerateCount(KSM_TYPE_KSK, &gencnt, zone_id);
952  if (status2 == 0 && gencnt == 0) {
953  if(man_key_gen == 1) {
954  log_msg(NULL, LOG_ERR, "There are no KSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
955  } else {
956  log_msg(NULL, LOG_WARNING, "There are no KSKs in the generate state; ods-enforcerd will create some on its next run.");
957  }
958  }
959  else if (status2 == 0) {
960  status2 = KsmRequestGenerateCount(KSM_TYPE_ZSK, &gencnt, zone_id);
961  if (status2 == 0 && gencnt == 0) {
962  if(man_key_gen == 1) {
963  log_msg(NULL, LOG_ERR, "There are no ZSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
964  } else {
965  log_msg(NULL, LOG_WARNING, "There are no ZSKs in the generate state; ods-enforcerd will create some on its next run.");
966  }
967  }
968  }
969  else {
970  log_msg(NULL, LOG_ERR, "KsmRequestGenerateCount returned: %d", status2);
971  }
972  }
973 
974  status = fclose(file);
975  unlink(temp_filename);
976  MemFree(datetime);
977  StrFree(temp_filename);
978  StrFree(old_filename);
979 
980  return -2;
981  }
982 
983  fprintf(file, "\t\t</Keys>\n");
984 
985  fprintf(file, "\n");
986 
987  fprintf(file, "\t\t<SOA>\n");
988  fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->signer->soattl);
989  fprintf(file, "\t\t\t<Minimum>PT%dS</Minimum>\n", policy->signer->soamin);
990  fprintf(file, "\t\t\t<Serial>%s</Serial>\n", KsmKeywordSerialValueToName( policy->signer->serial) );
991  fprintf(file, "\t\t</SOA>\n");
992 
993  if (strncmp(policy->audit, "NULL", 4) != 0) {
994  fprintf(file, "\n");
995  fprintf(file, "\t\t<Audit />\n");
996  fprintf(file, "\n");
997  }
998 
999  fprintf(file, "\t</Zone>\n");
1000  fprintf(file, "</SignerConfiguration>\n");
1001 
1002  /* Force flush of stream to disc cache and then onto disc proper
1003  * Do we need to do this? It might be significant on ext4
1004  * NOTE though that there may be a significant overhead associated with it
1005  * ALSO, if we do lose power maybe we should disregard any files when we come
1006  * back as we won't know if they are now too old? */
1007  /*
1008  if (fflush(file) != 0) {
1009  MemFree(datetime);
1010  return -1;
1011  }
1012 
1013  if (fsync(fileno(file)) != 0) {
1014  MemFree(datetime);
1015  return -1;
1016  }
1017  */
1018 
1019  status = fclose(file);
1020  MemFree(datetime);
1021 
1022  if (status == EOF) /* close failed... do something? */
1023  {
1024  log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
1025  StrFree(temp_filename);
1026  StrFree(old_filename);
1027  return -1;
1028  }
1029 
1030  /* compare our temp file with the current one (if it exists) */
1031  file = fopen(temp_filename, "rb");
1032  if (file == NULL)
1033  {
1034  /* error */
1035  log_msg(NULL, LOG_ERR, "Could not reopen: %s", temp_filename);
1036  StrFree(temp_filename);
1037  StrFree(old_filename);
1038  return -1;
1039  }
1040 
1041  file2 = fopen(current_filename, "rb"); /* Might not exist */
1042 
1043  /* If current_filename exists then compare its contents to temp_filename */
1044  if (file2 != NULL) {
1045  same = 1;
1046  while(!feof(file)) {
1047  char1 = fgetc(file);
1048  if(ferror(file)) {
1049  log_msg(NULL, LOG_ERR, "Could not read: %s", temp_filename);
1050  fclose(file);
1051  fclose(file2);
1052  StrFree(temp_filename);
1053  StrFree(old_filename);
1054  return -1;
1055  }
1056  char2 = fgetc(file2);
1057  if(ferror(file2)) {
1058  log_msg(NULL, LOG_ERR, "Could not read: %s", current_filename);
1059  fclose(file);
1060  fclose(file2);
1061  StrFree(temp_filename);
1062  StrFree(old_filename);
1063  return -1;
1064  }
1065  if(char1 != char2) {
1066  same = 0;
1067  break;
1068  }
1069  }
1070 
1071  status = fclose(file2);
1072  if (status == EOF) /* close failed... do something? */
1073  {
1074  log_msg(NULL, LOG_ERR, "Could not close: %s", current_filename);
1075  fclose(file);
1076  StrFree(temp_filename);
1077  StrFree(old_filename);
1078  return -1;
1079  }
1080  }
1081 
1082  status = fclose(file);
1083  if (status == EOF) /* close failed... do something? */
1084  {
1085  log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
1086  StrFree(temp_filename);
1087  StrFree(old_filename);
1088  return -1;
1089  }
1090 
1091  /* If either current_filename does not exist, or if it is different to temp then same will == 0 */
1092 
1093  if (same == 0) {
1094 
1095  /* we now have a complete xml file. First move the old one out of the way */
1096  status = rename(current_filename, old_filename);
1097  if (status != 0 && status != -1)
1098  {
1099  /* cope with initial condition of files not existing */
1100  log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", current_filename, old_filename);
1101  StrFree(old_filename);
1102  StrFree(temp_filename);
1103  return -1;
1104  }
1105 
1106  /* Then copy our temp into place */
1107  if (rename(temp_filename, current_filename) != 0)
1108  {
1109  log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", temp_filename, current_filename);
1110  StrFree(old_filename);
1111  StrFree(temp_filename);
1112  return -1;
1113  }
1114 
1115  if (*signer_flag == 1) {
1116  /* call the signer engine to tell it that something changed */
1117  /* TODO for beta version connect straight to the socket
1118  should we make a blocking call on this?
1119  should we call it here or after we have written all of the files?
1120  have timeout if call is blocking */
1121  signer_command = NULL;
1122  StrAppend(&signer_command, SIGNER_CLI_UPDATE);
1123  StrAppend(&signer_command, " ");
1124  StrAppend(&signer_command, zone_name);
1125 
1126  status = system(signer_command);
1127  if (status != 0)
1128  {
1129  log_msg(NULL, LOG_ERR, "Could not call signer engine");
1130  log_msg(NULL, LOG_INFO, "Will continue: call 'ods-signer update' to manually update zones");
1131  *signer_flag = 0;
1132  }
1133 
1134  StrFree(signer_command);
1135  }
1136  }
1137  else {
1138  log_msg(NULL, LOG_INFO, "No change to: %s", current_filename);
1139  if (remove(temp_filename) != 0)
1140  {
1141  log_msg(NULL, LOG_ERR, "Could not remove: %s", temp_filename);
1142  StrFree(old_filename);
1143  StrFree(temp_filename);
1144  return -1;
1145  }
1146  }
1147 
1148  /* If the DS set changed then log/do something about it */
1149  if (NewDS == 1) {
1150  log_msg(NULL, LOG_INFO, "DSChanged");
1151  status = NewDSSet(zone_id, zone_name, DSSubmitCmd);
1152  }
1153 
1154  StrFree(old_filename);
1155  StrFree(temp_filename);
1156 
1157  return 0;
1158 }
1159 
1160 /*
1161  * CallBack to print key info in signerConfiguration
1162  */
1163 
1164 int commKeyConfig(void* context, KSM_KEYDATA* key_data)
1165 {
1166  FILE *file = (FILE *)context;
1167 
1168  fprintf(file, "\t\t\t<Key>\n");
1169  fprintf(file, "\t\t\t\t<Flags>%d</Flags>\n", key_data->keytype);
1170  fprintf(file, "\t\t\t\t<Algorithm>%d</Algorithm>\n", key_data->algorithm);
1171  fprintf(file, "\t\t\t\t<Locator>%s</Locator>\n", key_data->location);
1172 
1173  if (key_data->keytype == KSM_TYPE_KSK)
1174  {
1175  fprintf(file, "\t\t\t\t<KSK />\n");
1176  }
1177  if (key_data->keytype == KSM_TYPE_ZSK && key_data->state == KSM_STATE_ACTIVE)
1178  {
1179  fprintf(file, "\t\t\t\t<ZSK />\n");
1180  }
1181  if ((key_data->state > KSM_STATE_GENERATE && key_data->state < KSM_STATE_DEAD) || key_data->state == KSM_STATE_KEYPUBLISH)
1182  {
1183  fprintf(file, "\t\t\t\t<Publish />\n");
1184  }
1185  fprintf(file, "\t\t\t</Key>\n");
1186  fprintf(file, "\n");
1187 
1188  return 0;
1189 }
1190 
1191 /* allocateKeysToZone
1192  *
1193  * Description:
1194  * Allocates existing keys to zones
1195  *
1196  * Arguments:
1197  * policy
1198  * policy that the keys were created for
1199  * key_type
1200  * KSK or ZSK
1201  * zone_id
1202  * ID of zone in question
1203  * interval
1204  * time before next run
1205  * zone_name
1206  * just in case we need to log something
1207  * man_key_gen
1208  * lack of keys may be an issue for the user to fix
1209  * int rollover_scheme
1210  * KSK rollover scheme in use
1211  *
1212  * Returns:
1213  * int
1214  * Status return. 0=> Success, non-zero => error.
1215  * 1 == error with input
1216  * 2 == not enough keys to satisfy policy
1217  * 3 == database error
1218  -*/
1219 
1220 
1221 int allocateKeysToZone(KSM_POLICY *policy, int key_type, int zone_id, uint16_t interval, const char* zone_name, int man_key_gen, int rollover_scheme)
1222 {
1223  int status = 0;
1224  int keys_needed = 0;
1225  int keys_in_queue = 0;
1226  int keys_pending_retirement = 0;
1227  int new_keys = 0;
1228  int key_pair_id = 0;
1229  int i = 0;
1230  DB_ID ignore = 0;
1231  KSM_PARCOLL collection; /* Parameters collection */
1232  char* datetime = DtParseDateTimeString("now");
1233 
1234  /* Check datetime in case it came back NULL */
1235  if (datetime == NULL) {
1236  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
1237  exit(1);
1238  }
1239 
1240  if (policy == NULL) {
1241  log_msg(NULL, LOG_ERR, "NULL policy sent to allocateKeysToZone");
1242  StrFree(datetime);
1243  return 1;
1244  }
1245 
1246  if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) {
1247  log_msg(NULL, LOG_ERR, "Unknown keytype: %i in allocateKeysToZone", key_type);
1248  StrFree(datetime);
1249  return 1;
1250  }
1251 
1252  /* Get list of parameters */
1253  status = KsmParameterCollection(&collection, policy->id);
1254  if (status != 0) {
1255  StrFree(datetime);
1256  return status;
1257  }
1258 
1259  /* Make sure that enough keys are allocated to this zone */
1260  /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */
1261  status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
1262  if (status != 0) {
1263  log_msg(NULL, LOG_ERR, "Could not predict key requirement for next interval for %s", zone_name);
1264  StrFree(datetime);
1265  return 3;
1266  }
1267 
1268  /* How many do we have ? TODO should this include the currently active key?*/
1269  status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id);
1270  if (status != 0) {
1271  log_msg(NULL, LOG_ERR, "Could not count current key numbers for zone %s", zone_name);
1272  StrFree(datetime);
1273  return 3;
1274  }
1275 
1276  /* or about to retire */
1277  status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval);
1278  if (status != 0) {
1279  log_msg(NULL, LOG_ERR, "Could not count keys which may retire before the next run (for zone %s)", zone_name);
1280  StrFree(datetime);
1281  return 3;
1282  }
1283 
1284  StrFree(datetime);
1285  new_keys = keys_needed - (keys_in_queue - keys_pending_retirement);
1286 
1287  /* fprintf(stderr, "comm(%d) %s: new_keys(%d) = keys_needed(%d) - (keys_in_queue(%d) - keys_pending_retirement(%d))\n", key_type, zone_name, new_keys, keys_needed, keys_in_queue, keys_pending_retirement); */
1288 
1289  /* Allocate keys */
1290  for (i=0 ; i < new_keys ; i++){
1291  key_pair_id = 0;
1292  if (key_type == KSM_TYPE_KSK) {
1293  status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
1294  if (status == -1 || key_pair_id == 0) {
1295  if (man_key_gen == 0) {
1296  log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
1297  log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
1298  }
1299  else {
1300  log_msg(NULL, LOG_ERR, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
1301  log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
1302  }
1303  return 2;
1304  }
1305  else if (status != 0) {
1306  log_msg(NULL, LOG_ERR, "Could not get an unallocated ksk for zone: %s", zone_name);
1307  return 3;
1308  }
1309  } else {
1310  status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
1311  if (status == -1 || key_pair_id == 0) {
1312  if (man_key_gen == 0) {
1313  log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
1314  log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
1315  }
1316  else {
1317  log_msg(NULL, LOG_ERR, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
1318  log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
1319  }
1320  return 2;
1321  }
1322  else if (status != 0) {
1323  log_msg(NULL, LOG_ERR, "Could not get an unallocated zsk for zone: %s", zone_name);
1324  return 3;
1325  }
1326  }
1327  if(key_pair_id > 0) {
1328  status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, NULL, &ignore);
1329  /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */
1330  } else {
1331  /* This shouldn't happen */
1332  log_msg(NULL, LOG_ERR, "KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name);
1333  exit(1);
1334  }
1335 
1336  }
1337 
1338  return status;
1339 }
1340 
1341 /*
1342  * Read the conf.xml file, extract the location of the zonelist.
1343  */
1344 int read_zonelist_filename(const char* filename, char** zone_list_filename)
1345 {
1346  xmlTextReaderPtr reader = NULL;
1347  xmlDocPtr doc = NULL;
1348  xmlXPathContextPtr xpathCtx = NULL;
1349  xmlXPathObjectPtr xpathObj = NULL;
1350  int ret = 0; /* status of the XML parsing */
1351  char* temp_char = NULL;
1352  char* tag_name = NULL;
1353 
1354  xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile";
1355 
1356  /* Start reading the file; we will be looking for "Common" tags */
1357  reader = xmlNewTextReaderFilename(filename);
1358  if (reader != NULL) {
1359  ret = xmlTextReaderRead(reader);
1360  while (ret == 1) {
1361  tag_name = (char*) xmlTextReaderLocalName(reader);
1362  /* Found <Common> */
1363  if (strncmp(tag_name, "Common", 6) == 0
1364  && xmlTextReaderNodeType(reader) == 1) {
1365 
1366  /* Expand this node and get the rest of the info with XPath */
1367  xmlTextReaderExpand(reader);
1368  doc = xmlTextReaderCurrentDoc(reader);
1369  if (doc == NULL) {
1370  log_msg(NULL, LOG_ERR, "Error: can not read Common section of %s", filename);
1371  /* Don't return? try to parse the rest of the file? */
1372  ret = xmlTextReaderRead(reader);
1373  continue;
1374  }
1375 
1376  xpathCtx = xmlXPathNewContext(doc);
1377  if(xpathCtx == NULL) {
1378  log_msg(NULL, LOG_ERR, "Error: can not create XPath context for Common section");
1379  /* Don't return? try to parse the rest of the file? */
1380  ret = xmlTextReaderRead(reader);
1381  continue;
1382  }
1383 
1384  /* Evaluate xpath expression for ZoneListFile */
1385  xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx);
1386  if(xpathObj == NULL) {
1387  log_msg(NULL, LOG_ERR, "Error: unable to evaluate xpath expression: %s", zonelist_expr);
1388  /* Don't return? try to parse the rest of the file? */
1389  ret = xmlTextReaderRead(reader);
1390  continue;
1391  }
1392  *zone_list_filename = NULL;
1393  temp_char = (char *)xmlXPathCastToString(xpathObj);
1394  StrAppend(zone_list_filename, temp_char);
1395  StrFree(temp_char);
1396  xmlXPathFreeObject(xpathObj);
1397  log_msg(NULL, LOG_INFO, "zonelist filename set to %s.", *zone_list_filename);
1398  }
1399  /* Read the next line */
1400  ret = xmlTextReaderRead(reader);
1401  StrFree(tag_name);
1402  }
1403  xmlFreeTextReader(reader);
1404  if (ret != 0) {
1405  log_msg(NULL, LOG_ERR, "%s : failed to parse", filename);
1406  return(1);
1407  }
1408  } else {
1409  log_msg(NULL, LOG_ERR, "Unable to open %s", filename);
1410  return(1);
1411  }
1412  if (xpathCtx) {
1413  xmlXPathFreeContext(xpathCtx);
1414  }
1415  if (doc) {
1416  xmlFreeDoc(doc);
1417  }
1418 
1419  return 0;
1420 }
1421 
1422 /*+
1423  * do_purge - Purge dead Keys
1424  *
1425  *
1426  * Arguments:
1427  *
1428  * int interval
1429  * how long a key needs to have been dead for before we purge it
1430  *
1431  * int policy_id
1432  * ID of the policy
1433  *
1434  * Returns:
1435  * int
1436  * Status return. 0 on success.
1437  * other on fail
1438  */
1439 
1440 int do_purge(int interval, int policy_id)
1441 {
1442  char* sql = NULL; /* SQL query */
1443  char* sql1 = NULL; /* SQL query */
1444  char* sql2 = NULL; /* SQL query */
1445  char* sql3 = NULL; /* SQL query */
1446  int status = 0; /* Status return */
1447  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
1448  DB_RESULT result; /* Result of the query */
1449  DB_ROW row = NULL; /* Row data */
1450 
1451  char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */
1452  unsigned int nchar; /* Number of characters converted */
1453 
1454  int temp_id = -1; /* place to store the key id returned */
1455  char* temp_loc = NULL; /* place to store location returned */
1456  int count = 0; /* How many keys don't match the purge */
1457 
1458  char *rightnow;
1459 
1460  /* Key information */
1461  hsm_key_t *key = NULL;
1462 
1463  log_msg(NULL, LOG_DEBUG, "Purging keys...");
1464 
1465  rightnow = DtParseDateTimeString("now");
1466 
1467  /* Check datetime in case it came back NULL */
1468  if (rightnow == NULL) {
1469  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
1470  exit(1);
1471  }
1472 
1473  /* Select rows */
1474  StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
1475 
1476  if (policy_id != -1) {
1477  StrAppend(&sql, "and policy_id = ");
1478  snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
1479  StrAppend(&sql, stringval);
1480  }
1481 
1482  DusEnd(&sql);
1483 
1484  status = DbExecuteSql(DbHandle(), sql, &result);
1485 
1486  if (status == 0) {
1487  status = DbFetchRow(result, &row);
1488  while (status == 0) {
1489  /* Got a row, check it */
1490  DbInt(row, 0, &temp_id);
1491  DbString(row, 1, &temp_loc);
1492 
1493  sql1 = DqsCountInit("dnsseckeys");
1494  DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
1495  DdsConditionInt(&sql1, "(state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
1496 
1497 #ifdef USE_MYSQL
1498  nchar = snprintf(buffer, sizeof(buffer),
1499  " or state = %d and DEAD > DATE_ADD('%s', INTERVAL -%d SECOND)) ", KSM_STATE_DEAD, rightnow, interval);
1500 #else
1501  nchar = snprintf(buffer, sizeof(buffer),
1502  " or state = %d and DEAD > DATETIME('%s', '-%d SECONDS')) ", KSM_STATE_DEAD, rightnow, interval);
1503 #endif /* USE_MYSQL */
1504 
1505  if (nchar >= sizeof(buffer)) {
1506  log_msg(NULL, LOG_ERR, "Error: failed to create SQL statement to purge keys\n");
1507  DbStringFree(temp_loc);
1508  DbFreeRow(row);
1509  StrFree(rightnow);
1510  return(-1);
1511  }
1512 
1513  StrAppend(&sql1, buffer);
1514  DqsEnd(&sql1);
1515 
1516  status = DbIntQuery(DbHandle(), &count, sql1);
1517  DqsFree(sql1);
1518 
1519  if (status != 0) {
1520  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1521  DbStringFree(temp_loc);
1522  DbFreeRow(row);
1523  StrFree(rightnow);
1524  return status;
1525  }
1526 
1527  /* If the count is zero then there is no reason not to purge this key */
1528  if (count == 0) {
1529 
1530  /* Delete from dnsseckeys */
1531  sql2 = DdsInit("dnsseckeys");
1532  DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
1533  DdsEnd(&sql);
1534 
1535  status = DbExecuteSqlNoResult(DbHandle(), sql2);
1536  DdsFree(sql2);
1537  if (status != 0)
1538  {
1539  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1540  DbStringFree(temp_loc);
1541  DbFreeRow(row);
1542  StrFree(rightnow);
1543  return status;
1544  }
1545 
1546  /* Delete from keypairs */
1547  sql3 = DdsInit("keypairs");
1548  DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
1549  DdsEnd(&sql);
1550 
1551  status = DbExecuteSqlNoResult(DbHandle(), sql3);
1552  DdsFree(sql3);
1553  if (status != 0)
1554  {
1555  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1556  DbStringFree(temp_loc);
1557  DbFreeRow(row);
1558  StrFree(rightnow);
1559  return status;
1560  }
1561 
1562  /* Delete from the HSM */
1563  key = hsm_find_key_by_id(NULL, temp_loc);
1564 
1565  if (!key) {
1566  log_msg(NULL, LOG_ERR, "Key not found: %s\n", temp_loc);
1567  DbStringFree(temp_loc);
1568  DbFreeRow(row);
1569  StrFree(rightnow);
1570  return -1;
1571  }
1572 
1573  status = hsm_remove_key(NULL, key);
1574 
1575  hsm_key_free(key);
1576 
1577  if (!status) {
1578  log_msg(NULL, LOG_INFO, "Key remove successful.\n");
1579  } else {
1580  log_msg(NULL, LOG_ERR, "Key remove failed.\n");
1581  DbStringFree(temp_loc);
1582  DbFreeRow(row);
1583  StrFree(rightnow);
1584  return -1;
1585  }
1586  }
1587 
1588  /* NEXT! */
1589  status = DbFetchRow(result, &row);
1590  }
1591 
1592  /* Convert EOF status to success */
1593 
1594  if (status == -1) {
1595  status = 0;
1596  }
1597 
1598  DbFreeResult(result);
1599  }
1600 
1601  DusFree(sql);
1602  DbFreeRow(row);
1603 
1604  DbStringFree(temp_loc);
1605  StrFree(rightnow);
1606 
1607  return status;
1608 }
1609 
1610 int NewDSSet(int zone_id, const char* zone_name, const char* DSSubmitCmd) {
1611  int where = 0; /* for the SELECT statement */
1612  char* sql = NULL; /* SQL statement (when verifying) */
1613  char* sql2 = NULL; /* SQL statement (if getting DS) */
1614  int status = 0; /* Status return */
1615  int count = 0; /* How many keys fit our select? */
1616  int i = 0; /* A counter */
1617  int j = 0; /* Another counter */
1618  char* insql = NULL; /* SQL "IN" clause */
1619  int* keyids; /* List of IDs of keys to promote */
1620  DB_RESULT result; /* List result set */
1621  KSM_KEYDATA data; /* Data for this key */
1622  size_t nchar; /* Number of characters written */
1623  char buffer[256]; /* For constructing part of the command */
1624  char* count_clause = NULL;
1625  char* where_clause = NULL;
1626  int id = -1; /* ID of key which will retire */
1627  int active_count = -1; /* Number of currently active keys */
1628 
1629  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
1630  DB_RESULT result3; /* Result of DS query */
1631  KSM_KEYDATA data3; /* DS information */
1632  char* ds_buffer = NULL; /* Contents of DS records */
1633  char* ds_seen_buffer = NULL; /* Which keys have we promoted */
1634  char* temp_char = NULL; /* Contents of DS records */
1635 
1636  /* To find the ttl of the DS */
1637  int policy_id = -1;
1638  int rrttl = -1;
1639  int param_id = -1; /* unused */
1640 
1641  /* Key information */
1642  hsm_key_t *key = NULL;
1643  ldns_rr *dnskey_rr = NULL;
1644  hsm_sign_params_t *sign_params = NULL;
1645 
1646  FILE *fp;
1647  int bytes_written = -1;
1648 
1649  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d, %d, %d, %d, %d)",
1653  if (nchar >= sizeof(buffer)) {
1654  status = -1;
1655  return status;
1656  }
1657 
1658  /* Find the oldest active key, this is the one which will be retired
1659  NOTE; this may not match any keys */
1660 
1661  count_clause = DqsCountInit("KEYDATA_VIEW");
1662  DqsConditionInt(&count_clause, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1663  DqsConditionInt(&count_clause, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
1664  if (zone_id != -1) {
1665  DqsConditionInt(&count_clause, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1666  }
1667 
1668  status = DbIntQuery(DbHandle(), &active_count, count_clause);
1669  StrFree(count_clause);
1670  if (status != 0)
1671  {
1672  log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
1673  return status;
1674  }
1675 
1676  if (active_count > 0) {
1677 
1678  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
1679  StrAppend(&where_clause, "select id from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
1680  StrAppend(&where_clause, stringval);
1681  StrAppend(&where_clause, " and retire = (select min(retire) from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
1682  StrAppend(&where_clause, stringval);
1683  StrAppend(&where_clause, ")");
1684 
1685  /* Execute query and free up the query string */
1686  status = DbIntQuery(DbHandle(), &id, where_clause);
1687  StrFree(where_clause);
1688  if (status != 0)
1689  {
1690  log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
1691  return status;
1692  }
1693  }
1694 
1695  /* First up we need to count how many DSs we will have */
1696  where = 0;
1697  sql = DqsCountInit("KEYDATA_VIEW");
1698  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1699  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
1700  if (zone_id != -1) {
1701  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1702  }
1703  if (id != -1) {
1704  DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
1705  }
1706  DqsEnd(&sql);
1707 
1708  status = DbIntQuery(DbHandle(), &count, sql);
1709  DqsFree(sql);
1710 
1711  if (status != 0) {
1712  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1713  return status;
1714  }
1715 
1716  if (count == 0) {
1717  /* No KSKs in zone? */
1718  return status;
1719  }
1720 
1721  /* Allocate space for the list of key IDs */
1722  keyids = MemMalloc(count * sizeof(int));
1723 
1724  /* Get the list of IDs */
1725 
1726  where = 0;
1727  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1728  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1729  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
1730  if (zone_id != -1) {
1731  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1732  }
1733  if (id != -1) {
1734  DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
1735  }
1736  DqsEnd(&sql);
1737 
1738  status = KsmKeyInitSql(&result, sql);
1739  DqsFree(sql);
1740 
1741  if (status == 0) {
1742  while (status == 0) {
1743  status = KsmKey(result, &data);
1744  if (status == 0) {
1745  keyids[i] = data.keypair_id;
1746  i++;
1747  }
1748  }
1749 
1750  /* Convert EOF status to success */
1751 
1752  if (status == -1) {
1753  status = 0;
1754  } else {
1755  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1756  StrFree(keyids);
1757  return status;
1758  }
1759 
1760  KsmKeyEnd(result);
1761 
1762  } else {
1763  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1764  StrFree(keyids);
1765  return status;
1766  }
1767 
1768  /*
1769  * Now construct the "IN" statement listing the IDs of the keys we
1770  * are planning to change the state of.
1771  */
1772 
1773  StrAppend(&insql, "(");
1774  for (j = 0; j < i; ++j) {
1775  if (j != 0) {
1776  StrAppend(&insql, ",");
1777  }
1778  snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
1779  StrAppend(&insql, buffer);
1780  }
1781  StrAppend(&insql, ")");
1782 
1783  StrFree(keyids);
1784 
1785  /* Indicate that the DS record should now be submitted */
1786  sql2 = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1787  DqsConditionKeyword(&sql2, "ID", DQS_COMPARE_IN, insql, 0);
1788  DqsConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
1789  DqsEnd(&sql2);
1790 
1791  log_msg(NULL, LOG_INFO, "DS Record set has changed, the current set looks like:");
1792 
1793  status = KsmKeyInitSql(&result3, sql2);
1794  DqsFree(sql2);
1795  if (status == 0) {
1796  status = KsmKey(result3, &data3);
1797  while (status == 0) {
1798 
1799  /* Code to output the DNSKEY record (stolen from hsmutil) */
1800  key = hsm_find_key_by_id(NULL, data3.location);
1801 
1802  if (!key) {
1803  log_msg(NULL, LOG_ERR, "Key %s in DB but not repository.", data3.location);
1804  StrFree(insql);
1805  return status;
1806  }
1807 
1808  StrAppend(&ds_seen_buffer, ", ");
1809  StrAppend(&ds_seen_buffer, data3.location);
1810 
1811  sign_params = hsm_sign_params_new();
1812  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone_name);
1813  sign_params->algorithm = data3.algorithm;
1814  sign_params->flags = LDNS_KEY_ZONE_KEY;
1815  sign_params->flags += LDNS_KEY_SEP_KEY;
1816  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
1817 
1818  /* Set TTL if we can find it; else leave it as the default */
1819  /* We need a policy id */
1820  status = KsmPolicyIdFromZoneId(zone_id, &policy_id);
1821  if (status == 0) {
1822 
1823  /* Use this to get the TTL parameter value */
1824  status = KsmParameterValue(KSM_PAR_KSKTTL_STRING, KSM_PAR_KSKTTL_CAT, &rrttl, policy_id, &param_id);
1825  if (status == 0) {
1826  ldns_rr_set_ttl(dnskey_rr, rrttl);
1827  }
1828  }
1829 
1830  temp_char = ldns_rr2str(dnskey_rr);
1831  ldns_rr_free(dnskey_rr);
1832 
1833  /* Replace tab with white-space */
1834  for (i = 0; temp_char[i]; ++i) {
1835  if (temp_char[i] == '\t') {
1836  temp_char[i] = ' ';
1837  }
1838  }
1839  log_msg(NULL, LOG_INFO, "%s", temp_char);
1840 
1841  /* We need to strip off trailing comments before we send
1842  to any clients that might be listening */
1843  for (i = 0; temp_char[i]; ++i) {
1844  if (temp_char[i] == ';') {
1845  temp_char[i] = '\n';
1846  temp_char[i+1] = '\0';
1847  break;
1848  }
1849  }
1850  StrAppend(&ds_buffer, temp_char);
1851  StrFree(temp_char);
1852 
1853 /* StrAppend(&ds_buffer, "\n;KSK DS record (SHA1):\n");
1854  ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1);
1855  temp_char = ldns_rr2str(ds_sha1_rr);
1856  StrAppend(&ds_buffer, temp_char);
1857  StrFree(temp_char);
1858 
1859  StrAppend(&ds_buffer, "\n;KSK DS record (SHA256):\n");
1860  ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256);
1861  temp_char = ldns_rr2str(ds_sha256_rr);
1862  StrAppend(&ds_buffer, temp_char);
1863  StrFree(temp_char);
1864 */
1865 
1866  hsm_sign_params_free(sign_params);
1867  hsm_key_free(key);
1868  status = KsmKey(result3, &data3);
1869  }
1870  /* Convert EOF status to success */
1871  if (status == -1) {
1872  status = 0;
1873  }
1874 
1875  KsmKeyEnd(result3);
1876  }
1877 
1878  if (DSSubmitCmd[0] != '\0') {
1879  /* send records to the configured command */
1880  fp = popen(DSSubmitCmd, "w");
1881  if (fp == NULL) {
1882  log_msg(NULL, LOG_ERR, "Failed to run command: %s: %s", DSSubmitCmd, strerror(errno));
1883  return -1;
1884  }
1885  bytes_written = fprintf(fp, "%s", ds_buffer);
1886  if (bytes_written < 0) {
1887  log_msg(NULL, LOG_ERR, "Failed to write to %s: %s", DSSubmitCmd, strerror(errno));
1888  return -1;
1889  }
1890 
1891  if (pclose(fp) == -1) {
1892  log_msg(NULL, LOG_ERR, "Failed to close %s: %s", DSSubmitCmd, strerror(errno));
1893  return -1;
1894  }
1895  }
1896 
1897  StrFree(ds_buffer);
1898 
1899  log_msg(NULL, LOG_INFO, "Once the new DS records are seen in DNS please issue the ds-seen command for zone %s with the following cka_ids%s", zone_name, ds_seen_buffer);
1900 
1901  StrFree(ds_seen_buffer);
1902 
1903  StrFree(insql);
1904 
1905  return status;
1906 }
1907 
1909 {
1910  int result = 0;
1911  char *hsm_error_message = NULL;
1912 
1913  result = hsm_check_context(*ctx);
1914 
1915  /* If we didn't get HSM_OK then close and reopen HSM */
1916  if (result != HSM_OK) {
1917 
1918  if (*ctx) {
1919  hsm_destroy_context(*ctx);
1920  }
1921 
1922  result = hsm_close();
1923 
1924  if (config->configfile != NULL) {
1925  result = hsm_open(config->configfile, hsm_prompt_pin, NULL);
1926  } else {
1927  result = hsm_open(OPENDNSSEC_CONFIG_FILE, hsm_prompt_pin, NULL);
1928  }
1929  if (result) {
1930  hsm_error_message = hsm_get_error(*ctx);
1931  if (hsm_error_message) {
1932  log_msg(config, LOG_ERR, hsm_error_message);
1933  free(hsm_error_message);
1934  } else {
1935  /* decode the error code ourselves
1936  TODO find if there is a better way to do this (and can all
1937  of these be returned? are there others?) */
1938  switch (result) {
1939  case HSM_ERROR:
1940  log_msg(config, LOG_ERR, "hsm_open() result: HSM error");
1941  break;
1942  case HSM_PIN_INCORRECT:
1943  log_msg(config, LOG_ERR, "hsm_open() result: incorrect PIN");
1944  break;
1945  case HSM_CONFIG_FILE_ERROR:
1946  log_msg(config, LOG_ERR, "hsm_open() result: config file error");
1947  break;
1948  case HSM_REPOSITORY_NOT_FOUND:
1949  log_msg(config, LOG_ERR, "hsm_open() result: repository not found");
1950  break;
1951  case HSM_NO_REPOSITORIES:
1952  log_msg(config, LOG_ERR, "hsm_open() result: no repositories");
1953  break;
1954  default:
1955  log_msg(config, LOG_ERR, "hsm_open() result: %d", result);
1956  }
1957  }
1958  unlink(config->pidfile);
1959  exit(1);
1960  }
1961  log_msg(config, LOG_INFO, "HSM reopened successfully.");
1962  *ctx = hsm_create_context();
1963  } else {
1964  log_msg(config, LOG_INFO, "HSM connection open.");
1965  }
1966 
1967 }
1968