OpenDNSSEC-enforcer  1.3.9
enforcer.c
Go to the documentation of this file.
1 /*
2  * $Id: enforcer.c 6379 2012-06-05 08:52:37Z jerry $
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 
394  /* Find out how many ksk keys are needed for the POLICY */
395  status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, config->interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count);
396  if (status != 0) {
397  log_msg(NULL, LOG_ERR, "Could not predict ksk requirement for next interval for %s", policy->name);
398  /* TODO exit? continue with next policy? */
399  }
400  /* Find out how many suitable keys we have */
401  status = KsmKeyCountStillGood(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, config->interval, rightnow, &keys_in_queue, KSM_TYPE_KSK);
402  if (status != 0) {
403  log_msg(NULL, LOG_ERR, "Could not count current ksk numbers for policy %s", policy->name);
404  /* TODO exit? continue with next policy? */
405  }
406  /* Correct for shared keys */
407  if (policy->shared_keys == KSM_KEYS_SHARED) {
408  keys_in_queue /= zone_count;
409  }
410 
411  new_keys = ksks_needed - keys_in_queue;
412  /* fprintf(stderr, "keygen(ksk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, ksks_needed, keys_in_queue); */
413 
414  /* Check capacity of HSM will not be exceeded */
415  if (policy->ksk->sm_capacity != 0 && new_keys >= 0) {
416  current_count = hsm_count_keys_repository(ctx, policy->ksk->sm_name);
417  if (current_count >= policy->ksk->sm_capacity) {
418  log_msg(config, LOG_ERR, "Repository %s is full, cannot create more KSKs for policy %s\n", policy->ksk->sm_name, policy->name);
419  new_keys = 0;
420  }
421  else if (current_count + new_keys > policy->ksk->sm_capacity) {
422  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);
423  new_keys = policy->ksk->sm_capacity - current_count;
424  }
425  }
426 
427  /* Create the required keys */
428  for (i=new_keys ; i > 0 ; i--){
429  if (hsm_supported_algorithm(policy->ksk->algorithm) == 0) {
430  /* NOTE: for now we know that libhsm only supports RSA keys */
431  key = hsm_generate_rsa_key(ctx, policy->ksk->sm_name, policy->ksk->bits);
432  if (key) {
433  log_msg(config, LOG_DEBUG, "Created key in repository %s", policy->ksk->sm_name);
434  } else {
435  log_msg(config, LOG_ERR, "Error creating key in repository %s", policy->ksk->sm_name);
436  hsm_error_message = hsm_get_error(ctx);
437  if (hsm_error_message) {
438  log_msg(config, LOG_ERR, "%s", hsm_error_message);
439  free(hsm_error_message);
440  }
441  unlink(config->pidfile);
442  exit(1);
443  }
444  id = hsm_get_key_id(ctx, key);
445  hsm_key_free(key);
446  status = KsmKeyPairCreate(policy->id, id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, rightnow, &ignore);
447  if (status != 0) {
448  log_msg(config, LOG_ERR,"Error creating key in Database");
449  hsm_error_message = hsm_get_error(ctx);
450  if (hsm_error_message) {
451  log_msg(config, LOG_ERR, "%s", hsm_error_message);
452  free(hsm_error_message);
453  }
454  unlink(config->pidfile);
455  exit(1);
456  }
457  log_msg(config, LOG_INFO, "Created KSK size: %i, alg: %i with id: %s in repository: %s and database.", policy->ksk->bits,
458  policy->ksk->algorithm, id, policy->ksk->sm_name);
459  free(id);
460  } else {
461  log_msg(config, LOG_ERR, "Key algorithm %d unsupported by libhsm, exiting...", policy->ksk->algorithm);
462  unlink(config->pidfile);
463  exit(1);
464  }
465  }
466  ksks_created = new_keys;
467 
468  /* Find out how many zsk keys are needed */
469  keys_in_queue = 0;
470  new_keys = 0;
471  current_count = 0;
472 
473  /* Find out how many zsk keys are needed for the POLICY */
474  status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, config->interval, &zsks_needed, 0, zone_count);
475  if (status != 0) {
476  log_msg(NULL, LOG_ERR, "Could not predict zsk requirement for next intervalfor %s", policy->name);
477  /* TODO exit? continue with next policy? */
478  }
479  /* Find out how many suitable keys we have */
480  status = KsmKeyCountStillGood(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, config->interval, rightnow, &keys_in_queue, KSM_TYPE_ZSK);
481  if (status != 0) {
482  log_msg(NULL, LOG_ERR, "Could not count current zsk numbers for policy %s", policy->name);
483  /* TODO exit? continue with next policy? */
484  }
485  /* Correct for shared keys */
486  if (policy->shared_keys == KSM_KEYS_SHARED) {
487  keys_in_queue /= zone_count;
488  }
489  /* Might have to account for ksks */
490  if (same_keys) {
491  keys_in_queue -= ksks_needed;
492  }
493 
494  new_keys = zsks_needed - keys_in_queue;
495  /* fprintf(stderr, "keygen(zsk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, zsks_needed, keys_in_queue); */
496 
497  /* Check capacity of HSM will not be exceeded */
498  if (policy->zsk->sm_capacity != 0 && new_keys >= 0) {
499  current_count = hsm_count_keys_repository(ctx, policy->zsk->sm_name);
500  if (current_count >= policy->zsk->sm_capacity) {
501  log_msg(config, LOG_ERR, "Repository %s is full, cannot create more ZSKs for policy %s\n", policy->zsk->sm_name, policy->name);
502  new_keys = 0;
503  }
504  else if (current_count + new_keys > policy->zsk->sm_capacity) {
505  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);
506  new_keys = policy->zsk->sm_capacity - current_count;
507  }
508  }
509 
510  /* Create the required keys */
511  for (i = new_keys ; i > 0 ; i--) {
512  if (hsm_supported_algorithm(policy->zsk->algorithm) == 0) {
513  /* NOTE: for now we know that libhsm only supports RSA keys */
514  key = hsm_generate_rsa_key(ctx, policy->zsk->sm_name, policy->zsk->bits);
515  if (key) {
516  log_msg(config, LOG_DEBUG, "Created key in repository %s", policy->zsk->sm_name);
517  } else {
518  log_msg(config, LOG_ERR, "Error creating key in repository %s", policy->zsk->sm_name);
519  hsm_error_message = hsm_get_error(ctx);
520  if (hsm_error_message) {
521  log_msg(config, LOG_ERR, "%s", hsm_error_message);
522  free(hsm_error_message);
523  }
524  unlink(config->pidfile);
525  hsm_key_free(key);
526  exit(1);
527  }
528  id = hsm_get_key_id(ctx, key);
529  hsm_key_free(key);
530  status = KsmKeyPairCreate(policy->id, id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, rightnow, &ignore);
531  if (status != 0) {
532  log_msg(config, LOG_ERR,"Error creating key in Database");
533  hsm_error_message = hsm_get_error(ctx);
534  if (hsm_error_message) {
535  log_msg(config, LOG_ERR, "%s", hsm_error_message);
536  free(hsm_error_message);
537  }
538  unlink(config->pidfile);
539  exit(1);
540  }
541  log_msg(config, LOG_INFO, "Created ZSK size: %i, alg: %i with id: %s in repository: %s and database.", policy->zsk->bits,
542  policy->zsk->algorithm, id, policy->zsk->sm_name);
543  free(id);
544  } else {
545  log_msg(config, LOG_ERR, "Key algorithm %d unsupported by libhsm, exiting...", policy->zsk->algorithm);
546  unlink(config->pidfile);
547  exit(1);
548  }
549  }
550  StrFree(rightnow);
551 
552  /* Log if a backup needs to be run for these keys */
553  if (ksks_created && policy->ksk->require_backup) {
554  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);
555  }
556  if (new_keys && policy->zsk->require_backup && (policy->zsk->sm != policy->ksk->sm)) {
557  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);
558  }
559 
560  return status;
561 }
562 
564 {
565  int status = 0;
566  int status2 = 0;
567 
568  xmlTextReaderPtr reader = NULL;
569  xmlDocPtr doc = NULL;
570  xmlXPathContextPtr xpathCtx = NULL;
571  xmlXPathObjectPtr xpathObj = NULL;
572 
573  int ret = 0; /* status of the XML parsing */
574  char* zonelist_filename = NULL;
575  char* zone_name;
576  char* current_policy;
577  char* current_filename;
578  char *tag_name;
579  int zone_id = -1;
580  int signer_flag = 1; /* Is the signer responding? (1 == yes) */
581  char* ksk_expected = NULL; /* When is the next ksk rollover expected? */
582 
583  xmlChar *name_expr = (unsigned char*) "name";
584  xmlChar *policy_expr = (unsigned char*) "//Zone/Policy";
585  xmlChar *filename_expr = (unsigned char*) "//Zone/SignerConfiguration";
586 
587  char* temp_char = NULL;
588 
589  /* Stuff to see if we need to log an "impending rollover" warning */
590  char* datetime = NULL;
591  int roll_time = 0;
592 
593  /* Let's find our zonelist from the conf.xml */
594  if (config->configfile != NULL) {
595  status = read_zonelist_filename(config->configfile, &zonelist_filename);
596  } else {
597  status = read_zonelist_filename(OPENDNSSEC_CONFIG_FILE, &zonelist_filename);
598  }
599 
600  if (status != 0) {
601  log_msg(NULL, LOG_ERR, "couldn't read zonelist filename");
602  unlink(config->pidfile);
603  exit(1);
604  }
605 
606  /* In case zonelist is huge use the XmlTextReader API so that we don't hold the whole file in memory */
607  reader = xmlNewTextReaderFilename(zonelist_filename);
608  if (reader != NULL) {
609  ret = xmlTextReaderRead(reader);
610  while (ret == 1) {
611  tag_name = (char*) xmlTextReaderLocalName(reader);
612  /* Found <Zone> */
613  if (strncmp(tag_name, "Zone", 4) == 0
614  && strncmp(tag_name, "ZoneList", 8) != 0
615  && xmlTextReaderNodeType(reader) == 1) {
616  /* Get the zone name (TODO what if this is null?) */
617  zone_name = NULL;
618  temp_char = (char*) xmlTextReaderGetAttribute(reader, name_expr);
619  StrAppend(&zone_name, temp_char);
620  StrFree(temp_char);
621  /* Make sure that we got something */
622  if (zone_name == NULL) {
623  /* error */
624  log_msg(NULL, LOG_ERR, "Error extracting zone name from %s", zonelist_filename);
625  /* Don't return? try to parse the rest of the zones? */
626  ret = xmlTextReaderRead(reader);
627  StrFree(tag_name);
628  continue;
629  }
630 
631 
632  log_msg(config, LOG_INFO, "Zone %s found.", zone_name);
633 
634  /* Get zone ID from name (or skip if it doesn't exist) */
635  status = KsmZoneIdFromName(zone_name, &zone_id);
636  if (status != 0 || zone_id == -1)
637  {
638  /* error */
639  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);
640  /* Don't return? try to parse the rest of the zones? */
641  ret = xmlTextReaderRead(reader);
642  StrFree(tag_name);
643  StrFree(zone_name);
644  continue;
645  }
646 
647  /* Expand this node and get the rest of the info with XPath */
648  xmlTextReaderExpand(reader);
649  doc = xmlTextReaderCurrentDoc(reader);
650  if (doc == NULL) {
651  log_msg(config, LOG_ERR, "Error: can not read zone \"%s\"; skipping", zone_name);
652  /* Don't return? try to parse the rest of the zones? */
653  ret = xmlTextReaderRead(reader);
654  StrFree(tag_name);
655  StrFree(zone_name);
656  continue;
657  }
658 
659  /* TODO should we validate here? Or should we validate the whole document? */
660 
661  xpathCtx = xmlXPathNewContext(doc);
662  if(xpathCtx == NULL) {
663  log_msg(config, LOG_ERR,"Error: can not create XPath context for \"%s\"; skipping zone", zone_name);
664  /* Don't return? try to parse the rest of the zones? */
665  ret = xmlTextReaderRead(reader);
666  StrFree(tag_name);
667  StrFree(zone_name);
668  continue;
669  }
670 
671  /* Extract the Policy name and signer configuration filename for this zone */
672  /* Evaluate xpath expression for policy */
673  xpathObj = xmlXPathEvalExpression(policy_expr, xpathCtx);
674  if(xpathObj == NULL) {
675  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s; skipping zone", policy_expr);
676  /* Don't return? try to parse the rest of the zones? */
677  ret = xmlTextReaderRead(reader);
678  StrFree(tag_name);
679  StrFree(zone_name);
680  continue;
681  }
682  current_policy = NULL;
683  temp_char = (char*) xmlXPathCastToString(xpathObj);
684  StrAppend(&current_policy, temp_char);
685  StrFree(temp_char);
686  log_msg(config, LOG_INFO, "Policy for %s set to %s.", zone_name, current_policy);
687  xmlXPathFreeObject(xpathObj);
688 
689  if (strcmp(current_policy, policy->name) != 0) {
690 
691  /* Read new Policy */
692  kaspSetPolicyDefaults(policy, current_policy);
693 
694  status2 = KsmPolicyRead(policy);
695  if (status2 != 0) {
696  /* Don't return? try to parse the rest of the zones? */
697  log_msg(config, LOG_ERR, "Error reading policy");
698  ret = xmlTextReaderRead(reader);
699  StrFree(tag_name);
700  StrFree(zone_name);
701  continue;
702  }
703  log_msg(config, LOG_INFO, "Policy %s found in DB.", policy->name);
704 
705  } /* else */
706  /* Policy is same as previous zone, do not re-read */
707 
708  StrFree(current_policy);
709 
710  /* Evaluate xpath expression for signer configuration filename */
711  xpathObj = xmlXPathEvalExpression(filename_expr, xpathCtx);
712  xmlXPathFreeContext(xpathCtx);
713 
714  if(xpathObj == NULL) {
715  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s; skipping zone", filename_expr);
716  /* Don't return? try to parse the rest of the zones? */
717  ret = xmlTextReaderRead(reader);
718  StrFree(tag_name);
719  StrFree(zone_name);
720  continue;
721  }
722  current_filename = NULL;
723  temp_char = (char*)xmlXPathCastToString(xpathObj);
724  StrAppend(&current_filename, temp_char);
725  StrFree(temp_char);
726  log_msg(config, LOG_INFO, "Config will be output to %s.", current_filename);
727  xmlXPathFreeObject(xpathObj);
728  /* TODO should we check that we have not written to this file in this run?*/
729  /* Make sure that enough keys are allocated to this zone */
730  status2 = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, 0);
731  if (status2 != 0) {
732  log_msg(config, LOG_ERR, "Error allocating zsks to zone %s", zone_name);
733  /* Don't return? try to parse the rest of the zones? */
734  ret = xmlTextReaderRead(reader);
735  StrFree(tag_name);
736  StrFree(zone_name);
737  StrFree(current_filename);
738  continue;
739  }
740  status2 = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, policy->ksk->rollover_scheme);
741  if (status2 != 0) {
742  log_msg(config, LOG_ERR, "Error allocating ksks to zone %s", zone_name);
743  /* Don't return? try to parse the rest of the zones? */
744  ret = xmlTextReaderRead(reader);
745  StrFree(tag_name);
746  StrFree(zone_name);
747  StrFree(current_filename);
748  continue;
749  }
750 
751  /* turn this zone and policy into a file */
752  status2 = commGenSignConf(zone_name, zone_id, current_filename, policy, &signer_flag, config->interval, config->manualKeyGeneration, config->DSSubmitCmd);
753  if (status2 == -2) {
754  log_msg(config, LOG_ERR, "Signconf not written for %s", zone_name);
755  /* Don't return? try to parse the rest of the zones? */
756  ret = xmlTextReaderRead(reader);
757  StrFree(tag_name);
758  StrFree(zone_name);
759  StrFree(current_filename);
760  continue;
761  }
762  else if (status2 != 0) {
763  log_msg(config, LOG_ERR, "Error writing signconf 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 
772  /* See if we need to send a warning about an impending rollover */
773  if (config->rolloverNotify != -1) {
774  datetime = DtParseDateTimeString("now");
775 
776  /* Check datetime in case it came back NULL */
777  if (datetime == NULL) {
778  log_msg(config, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
779  unlink(config->pidfile);
780  exit(1);
781  }
782 
783  /* First the KSK */
784  status2 = KsmCheckNextRollover(KSM_TYPE_KSK, zone_id, &ksk_expected);
785  if (status2 == -1) {
786  log_msg(config, LOG_INFO, "No active KSKs yet for zone %s, can't check for impending rollover", zone_name);
787  }
788  else if (status2 != 0) {
789  log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
790  /* TODO should we quit or continue? */
791  } else {
792  status2 = DtDateDiff(ksk_expected, datetime, &roll_time);
793  if (status2 != 0) {
794  log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
795  } else {
796 
797  if (roll_time <= config->rolloverNotify) {
798  log_msg(config, LOG_INFO, "Rollover of KSK expected at %s for %s", ksk_expected, zone_name);
799  }
800  StrFree(ksk_expected);
801  }
802  }
803  StrFree(datetime);
804  }
805 
806  StrFree(current_filename);
807  StrFree(zone_name);
808  }
809  /* Read the next line */
810  ret = xmlTextReaderRead(reader);
811  StrFree(tag_name);
812  }
813  xmlFreeTextReader(reader);
814  if (ret != 0) {
815  log_msg(config, LOG_ERR, "%s : failed to parse", zonelist_filename);
816  }
817  } else {
818  log_msg(config, LOG_ERR, "Unable to open %s", zonelist_filename);
819  }
820 
821  xmlFreeDoc(doc);
822  StrFree(zonelist_filename);
823 
824  return status;
825 }
826 
827 /*
828  * generate the configuration file for the signer
829 
830  * returns 0 on success and -1 if something went wrong
831  * -2 if the RequestKeys call failed
832  */
833 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)
834 {
835  int status = 0;
836  int status2 = 0;
837  FILE *file, *file2;
838  int char1, char2; /* for the comparison between 2 files */
839  int same = 0;
840  char *temp_filename; /* In case this fails we write to a temp file and only overwrite
841  the current file when we are finished */
842  char *old_filename; /* Keep a copy of the previous version, just in case! (Also gets
843  round potentially different behaviour of rename over existing
844  file.) */
845  char *signer_command; /* how we will call the signer */
846  int gencnt; /* Number of keys in generate state */
847  int NewDS = 0; /* Did we change the DS Set in any way? */
848  char* datetime = DtParseDateTimeString("now");
849 
850  /* Check datetime in case it came back NULL */
851  if (datetime == NULL) {
852  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
853  exit(1);
854  }
855 
856  if (zone_name == NULL || current_filename == NULL || policy == NULL)
857  {
858  /* error */
859  log_msg(NULL, LOG_ERR, "commGenSignConf, NULL policy or zone provided");
860  MemFree(datetime);
861  return -1;
862  }
863 
864  old_filename = NULL;
865  StrAppend(&old_filename, current_filename);
866  StrAppend(&old_filename, ".OLD");
867 
868  temp_filename = NULL;
869  StrAppend(&temp_filename, current_filename);
870  StrAppend(&temp_filename, ".tmp");
871 
872  file = fopen(temp_filename, "w");
873 
874  if (file == NULL)
875  {
876  /* error */
877  log_msg(NULL, LOG_ERR, "Could not open: %s", temp_filename);
878  MemFree(datetime);
879  StrFree(temp_filename);
880  StrFree(old_filename);
881  return -1;
882  }
883 
884  fprintf(file, "<SignerConfiguration>\n");
885  fprintf(file, "\t<Zone name=\"%s\">\n", zone_name);
886 
887  fprintf(file, "\t\t<Signatures>\n");
888  fprintf(file, "\t\t\t<Resign>PT%dS</Resign>\n", policy->signature->resign);
889  fprintf(file, "\t\t\t<Refresh>PT%dS</Refresh>\n", policy->signer->refresh);
890  fprintf(file, "\t\t\t<Validity>\n");
891  fprintf(file, "\t\t\t\t<Default>PT%dS</Default>\n", policy->signature->valdefault);
892  fprintf(file, "\t\t\t\t<Denial>PT%dS</Denial>\n", policy->signature->valdenial);
893  fprintf(file, "\t\t\t</Validity>\n");
894  fprintf(file, "\t\t\t<Jitter>PT%dS</Jitter>\n", policy->signer->jitter);
895  fprintf(file, "\t\t\t<InceptionOffset>PT%dS</InceptionOffset>\n", policy->signature->clockskew);
896  fprintf(file, "\t\t</Signatures>\n");
897 
898  fprintf(file, "\n");
899 
900  fprintf(file, "\t\t<Denial>\n");
901  if (policy->denial->version == 3)
902  {
903  fprintf(file, "\t\t\t<NSEC3>\n");
904  if (policy->denial->optout == 1)
905  {
906  fprintf(file, "\t\t\t\t<OptOut />\n");
907  }
908  fprintf(file, "\t\t\t\t<Hash>\n");
909  fprintf(file, "\t\t\t\t\t<Algorithm>%d</Algorithm>\n", policy->denial->algorithm);
910  fprintf(file, "\t\t\t\t\t<Iterations>%d</Iterations>\n", policy->denial->iteration);
911  if (policy->denial->salt[0] == '\0') {
912  fprintf(file, "\t\t\t\t\t<Salt>-</Salt>\n");
913  } else {
914  fprintf(file, "\t\t\t\t\t<Salt>%s</Salt>\n", policy->denial->salt);
915  }
916  fprintf(file, "\t\t\t\t</Hash>\n");
917  fprintf(file, "\t\t\t</NSEC3>\n");
918  } else {
919  fprintf(file, "\t\t\t<NSEC />\n");
920  }
921 
922  fprintf(file, "\t\t</Denial>\n");
923 
924  fprintf(file, "\n");
925 
926  /* start of keys section */
927  fprintf(file, "\t\t<Keys>\n");
928  fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->ksk->ttl);
929 
930  /* get new keys _only_ if we don't have them from before */
931  status = KsmRequestKeys(0, 0, datetime, commKeyConfig, file, policy->id, zone_id, run_interval, &NewDS);
932  if (status != 0) {
933  /*
934  * Something went wrong (it should have been logged) stop this zone.
935  * Clean up the files, don't call the signer and move on to the next zone.
936  */
937  log_msg(NULL, LOG_ERR, "KsmRequestKeys returned: %d", status);
938 
939  /* check for the specific case of not having any keys
940  TODO check that this code can ever be executed after the restructure */
941  if (status == -1) {
942  status2 = KsmRequestGenerateCount(KSM_TYPE_KSK, &gencnt, zone_id);
943  if (status2 == 0 && gencnt == 0) {
944  if(man_key_gen == 1) {
945  log_msg(NULL, LOG_ERR, "There are no KSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
946  } else {
947  log_msg(NULL, LOG_WARNING, "There are no KSKs in the generate state; ods-enforcerd will create some on its next run.");
948  }
949  }
950  else if (status2 == 0) {
951  status2 = KsmRequestGenerateCount(KSM_TYPE_ZSK, &gencnt, zone_id);
952  if (status2 == 0 && gencnt == 0) {
953  if(man_key_gen == 1) {
954  log_msg(NULL, LOG_ERR, "There are no ZSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
955  } else {
956  log_msg(NULL, LOG_WARNING, "There are no ZSKs in the generate state; ods-enforcerd will create some on its next run.");
957  }
958  }
959  }
960  else {
961  log_msg(NULL, LOG_ERR, "KsmRequestGenerateCount returned: %d", status2);
962  }
963  }
964 
965  status = fclose(file);
966  unlink(temp_filename);
967  MemFree(datetime);
968  StrFree(temp_filename);
969  StrFree(old_filename);
970 
971  return -2;
972  }
973 
974  fprintf(file, "\t\t</Keys>\n");
975 
976  fprintf(file, "\n");
977 
978  fprintf(file, "\t\t<SOA>\n");
979  fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->signer->soattl);
980  fprintf(file, "\t\t\t<Minimum>PT%dS</Minimum>\n", policy->signer->soamin);
981  fprintf(file, "\t\t\t<Serial>%s</Serial>\n", KsmKeywordSerialValueToName( policy->signer->serial) );
982  fprintf(file, "\t\t</SOA>\n");
983 
984  if (strncmp(policy->audit, "NULL", 4) != 0) {
985  fprintf(file, "\n");
986  fprintf(file, "\t\t<Audit />\n");
987  fprintf(file, "\n");
988  }
989 
990  fprintf(file, "\t</Zone>\n");
991  fprintf(file, "</SignerConfiguration>\n");
992 
993  /* Force flush of stream to disc cache and then onto disc proper
994  * Do we need to do this? It might be significant on ext4
995  * NOTE though that there may be a significant overhead associated with it
996  * ALSO, if we do lose power maybe we should disregard any files when we come
997  * back as we won't know if they are now too old? */
998  /*
999  if (fflush(file) != 0) {
1000  MemFree(datetime);
1001  return -1;
1002  }
1003 
1004  if (fsync(fileno(file)) != 0) {
1005  MemFree(datetime);
1006  return -1;
1007  }
1008  */
1009 
1010  status = fclose(file);
1011  MemFree(datetime);
1012 
1013  if (status == EOF) /* close failed... do something? */
1014  {
1015  log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
1016  StrFree(temp_filename);
1017  StrFree(old_filename);
1018  return -1;
1019  }
1020 
1021  /* compare our temp file with the current one (if it exists) */
1022  file = fopen(temp_filename, "rb");
1023  if (file == NULL)
1024  {
1025  /* error */
1026  log_msg(NULL, LOG_ERR, "Could not reopen: %s", temp_filename);
1027  StrFree(temp_filename);
1028  StrFree(old_filename);
1029  return -1;
1030  }
1031 
1032  file2 = fopen(current_filename, "rb"); /* Might not exist */
1033 
1034  /* If current_filename exists then compare its contents to temp_filename */
1035  if (file2 != NULL) {
1036  same = 1;
1037  while(!feof(file)) {
1038  char1 = fgetc(file);
1039  if(ferror(file)) {
1040  log_msg(NULL, LOG_ERR, "Could not read: %s", temp_filename);
1041  fclose(file);
1042  fclose(file2);
1043  StrFree(temp_filename);
1044  StrFree(old_filename);
1045  return -1;
1046  }
1047  char2 = fgetc(file2);
1048  if(ferror(file2)) {
1049  log_msg(NULL, LOG_ERR, "Could not read: %s", current_filename);
1050  fclose(file);
1051  fclose(file2);
1052  StrFree(temp_filename);
1053  StrFree(old_filename);
1054  return -1;
1055  }
1056  if(char1 != char2) {
1057  same = 0;
1058  break;
1059  }
1060  }
1061 
1062  status = fclose(file2);
1063  if (status == EOF) /* close failed... do something? */
1064  {
1065  log_msg(NULL, LOG_ERR, "Could not close: %s", current_filename);
1066  fclose(file);
1067  StrFree(temp_filename);
1068  StrFree(old_filename);
1069  return -1;
1070  }
1071  }
1072 
1073  status = fclose(file);
1074  if (status == EOF) /* close failed... do something? */
1075  {
1076  log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
1077  StrFree(temp_filename);
1078  StrFree(old_filename);
1079  return -1;
1080  }
1081 
1082  /* If either current_filename does not exist, or if it is different to temp then same will == 0 */
1083 
1084  if (same == 0) {
1085 
1086  /* we now have a complete xml file. First move the old one out of the way */
1087  status = rename(current_filename, old_filename);
1088  if (status != 0 && status != -1)
1089  {
1090  /* cope with initial condition of files not existing */
1091  log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", current_filename, old_filename);
1092  StrFree(old_filename);
1093  StrFree(temp_filename);
1094  return -1;
1095  }
1096 
1097  /* Then copy our temp into place */
1098  if (rename(temp_filename, current_filename) != 0)
1099  {
1100  log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", temp_filename, current_filename);
1101  StrFree(old_filename);
1102  StrFree(temp_filename);
1103  return -1;
1104  }
1105 
1106  if (*signer_flag == 1) {
1107  /* call the signer engine to tell it that something changed */
1108  /* TODO for beta version connect straight to the socket
1109  should we make a blocking call on this?
1110  should we call it here or after we have written all of the files?
1111  have timeout if call is blocking */
1112  signer_command = NULL;
1113  StrAppend(&signer_command, SIGNER_CLI_UPDATE);
1114  StrAppend(&signer_command, " ");
1115  StrAppend(&signer_command, zone_name);
1116 
1117  status = system(signer_command);
1118  if (status != 0)
1119  {
1120  log_msg(NULL, LOG_ERR, "Could not call signer engine");
1121  log_msg(NULL, LOG_INFO, "Will continue: call 'ods-signer update' to manually update zones");
1122  *signer_flag = 0;
1123  }
1124 
1125  StrFree(signer_command);
1126  }
1127  }
1128  else {
1129  log_msg(NULL, LOG_INFO, "No change to: %s", current_filename);
1130  if (remove(temp_filename) != 0)
1131  {
1132  log_msg(NULL, LOG_ERR, "Could not remove: %s", temp_filename);
1133  StrFree(old_filename);
1134  StrFree(temp_filename);
1135  return -1;
1136  }
1137  }
1138 
1139  /* If the DS set changed then log/do something about it */
1140  if (NewDS == 1) {
1141  log_msg(NULL, LOG_INFO, "DSChanged");
1142  status = NewDSSet(zone_id, zone_name, DSSubmitCmd);
1143  }
1144 
1145  StrFree(old_filename);
1146  StrFree(temp_filename);
1147 
1148  return 0;
1149 }
1150 
1151 /*
1152  * CallBack to print key info in signerConfiguration
1153  */
1154 
1155 int commKeyConfig(void* context, KSM_KEYDATA* key_data)
1156 {
1157  FILE *file = (FILE *)context;
1158 
1159  fprintf(file, "\t\t\t<Key>\n");
1160  fprintf(file, "\t\t\t\t<Flags>%d</Flags>\n", key_data->keytype);
1161  fprintf(file, "\t\t\t\t<Algorithm>%d</Algorithm>\n", key_data->algorithm);
1162  fprintf(file, "\t\t\t\t<Locator>%s</Locator>\n", key_data->location);
1163 
1164  if (key_data->keytype == KSM_TYPE_KSK)
1165  {
1166  fprintf(file, "\t\t\t\t<KSK />\n");
1167  }
1168  if (key_data->keytype == KSM_TYPE_ZSK && key_data->state == KSM_STATE_ACTIVE)
1169  {
1170  fprintf(file, "\t\t\t\t<ZSK />\n");
1171  }
1172  if ((key_data->state > KSM_STATE_GENERATE && key_data->state < KSM_STATE_DEAD) || key_data->state == KSM_STATE_KEYPUBLISH)
1173  {
1174  fprintf(file, "\t\t\t\t<Publish />\n");
1175  }
1176  fprintf(file, "\t\t\t</Key>\n");
1177  fprintf(file, "\n");
1178 
1179  return 0;
1180 }
1181 
1182 /* allocateKeysToZone
1183  *
1184  * Description:
1185  * Allocates existing keys to zones
1186  *
1187  * Arguments:
1188  * policy
1189  * policy that the keys were created for
1190  * key_type
1191  * KSK or ZSK
1192  * zone_id
1193  * ID of zone in question
1194  * interval
1195  * time before next run
1196  * zone_name
1197  * just in case we need to log something
1198  * man_key_gen
1199  * lack of keys may be an issue for the user to fix
1200  * int rollover_scheme
1201  * KSK rollover scheme in use
1202  *
1203  * Returns:
1204  * int
1205  * Status return. 0=> Success, non-zero => error.
1206  * 1 == error with input
1207  * 2 == not enough keys to satisfy policy
1208  * 3 == database error
1209  -*/
1210 
1211 
1212 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)
1213 {
1214  int status = 0;
1215  int keys_needed = 0;
1216  int keys_in_queue = 0;
1217  int keys_pending_retirement = 0;
1218  int new_keys = 0;
1219  int key_pair_id = 0;
1220  int i = 0;
1221  DB_ID ignore = 0;
1222  KSM_PARCOLL collection; /* Parameters collection */
1223  char* datetime = DtParseDateTimeString("now");
1224 
1225  /* Check datetime in case it came back NULL */
1226  if (datetime == NULL) {
1227  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
1228  exit(1);
1229  }
1230 
1231  if (policy == NULL) {
1232  log_msg(NULL, LOG_ERR, "NULL policy sent to allocateKeysToZone");
1233  StrFree(datetime);
1234  return 1;
1235  }
1236 
1237  if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) {
1238  log_msg(NULL, LOG_ERR, "Unknown keytype: %i in allocateKeysToZone", key_type);
1239  StrFree(datetime);
1240  return 1;
1241  }
1242 
1243  /* Get list of parameters */
1244  status = KsmParameterCollection(&collection, policy->id);
1245  if (status != 0) {
1246  StrFree(datetime);
1247  return status;
1248  }
1249 
1250  /* Make sure that enough keys are allocated to this zone */
1251  /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */
1252  status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
1253  if (status != 0) {
1254  log_msg(NULL, LOG_ERR, "Could not predict key requirement for next interval for %s", zone_name);
1255  StrFree(datetime);
1256  return 3;
1257  }
1258 
1259  /* How many do we have ? TODO should this include the currently active key?*/
1260  status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id);
1261  if (status != 0) {
1262  log_msg(NULL, LOG_ERR, "Could not count current key numbers for zone %s", zone_name);
1263  StrFree(datetime);
1264  return 3;
1265  }
1266 
1267  /* or about to retire */
1268  status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval);
1269  if (status != 0) {
1270  log_msg(NULL, LOG_ERR, "Could not count keys which may retire before the next run (for zone %s)", zone_name);
1271  StrFree(datetime);
1272  return 3;
1273  }
1274 
1275  StrFree(datetime);
1276  new_keys = keys_needed - (keys_in_queue - keys_pending_retirement);
1277 
1278  /* 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); */
1279 
1280  /* Allocate keys */
1281  for (i=0 ; i < new_keys ; i++){
1282  key_pair_id = 0;
1283  if (key_type == KSM_TYPE_KSK) {
1284  status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
1285  if (status == -1 || key_pair_id == 0) {
1286  if (man_key_gen == 0) {
1287  log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
1288  log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
1289  }
1290  else {
1291  log_msg(NULL, LOG_ERR, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
1292  log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
1293  }
1294  return 2;
1295  }
1296  else if (status != 0) {
1297  log_msg(NULL, LOG_ERR, "Could not get an unallocated ksk for zone: %s", zone_name);
1298  return 3;
1299  }
1300  } else {
1301  status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
1302  if (status == -1 || key_pair_id == 0) {
1303  if (man_key_gen == 0) {
1304  log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
1305  log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
1306  }
1307  else {
1308  log_msg(NULL, LOG_ERR, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
1309  log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
1310  }
1311  return 2;
1312  }
1313  else if (status != 0) {
1314  log_msg(NULL, LOG_ERR, "Could not get an unallocated zsk for zone: %s", zone_name);
1315  return 3;
1316  }
1317  }
1318  if(key_pair_id > 0) {
1319  status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, NULL, &ignore);
1320  /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */
1321  } else {
1322  /* This shouldn't happen */
1323  log_msg(NULL, LOG_ERR, "KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name);
1324  exit(1);
1325  }
1326 
1327  }
1328 
1329  return status;
1330 }
1331 
1332 /*
1333  * Read the conf.xml file, extract the location of the zonelist.
1334  */
1335 int read_zonelist_filename(const char* filename, char** zone_list_filename)
1336 {
1337  xmlTextReaderPtr reader = NULL;
1338  xmlDocPtr doc = NULL;
1339  xmlXPathContextPtr xpathCtx = NULL;
1340  xmlXPathObjectPtr xpathObj = NULL;
1341  int ret = 0; /* status of the XML parsing */
1342  char* temp_char = NULL;
1343  char* tag_name = NULL;
1344 
1345  xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile";
1346 
1347  /* Start reading the file; we will be looking for "Common" tags */
1348  reader = xmlNewTextReaderFilename(filename);
1349  if (reader != NULL) {
1350  ret = xmlTextReaderRead(reader);
1351  while (ret == 1) {
1352  tag_name = (char*) xmlTextReaderLocalName(reader);
1353  /* Found <Common> */
1354  if (strncmp(tag_name, "Common", 6) == 0
1355  && xmlTextReaderNodeType(reader) == 1) {
1356 
1357  /* Expand this node and get the rest of the info with XPath */
1358  xmlTextReaderExpand(reader);
1359  doc = xmlTextReaderCurrentDoc(reader);
1360  if (doc == NULL) {
1361  log_msg(NULL, LOG_ERR, "Error: can not read Common section of %s", filename);
1362  /* Don't return? try to parse the rest of the file? */
1363  ret = xmlTextReaderRead(reader);
1364  continue;
1365  }
1366 
1367  xpathCtx = xmlXPathNewContext(doc);
1368  if(xpathCtx == NULL) {
1369  log_msg(NULL, LOG_ERR, "Error: can not create XPath context for Common section");
1370  /* Don't return? try to parse the rest of the file? */
1371  ret = xmlTextReaderRead(reader);
1372  continue;
1373  }
1374 
1375  /* Evaluate xpath expression for ZoneListFile */
1376  xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx);
1377  if(xpathObj == NULL) {
1378  log_msg(NULL, LOG_ERR, "Error: unable to evaluate xpath expression: %s", zonelist_expr);
1379  /* Don't return? try to parse the rest of the file? */
1380  ret = xmlTextReaderRead(reader);
1381  continue;
1382  }
1383  *zone_list_filename = NULL;
1384  temp_char = (char *)xmlXPathCastToString(xpathObj);
1385  StrAppend(zone_list_filename, temp_char);
1386  StrFree(temp_char);
1387  xmlXPathFreeObject(xpathObj);
1388  log_msg(NULL, LOG_INFO, "zonelist filename set to %s.", *zone_list_filename);
1389  }
1390  /* Read the next line */
1391  ret = xmlTextReaderRead(reader);
1392  StrFree(tag_name);
1393  }
1394  xmlFreeTextReader(reader);
1395  if (ret != 0) {
1396  log_msg(NULL, LOG_ERR, "%s : failed to parse", filename);
1397  return(1);
1398  }
1399  } else {
1400  log_msg(NULL, LOG_ERR, "Unable to open %s", filename);
1401  return(1);
1402  }
1403  if (xpathCtx) {
1404  xmlXPathFreeContext(xpathCtx);
1405  }
1406  if (doc) {
1407  xmlFreeDoc(doc);
1408  }
1409 
1410  return 0;
1411 }
1412 
1413 /*+
1414  * do_purge - Purge dead Keys
1415  *
1416  *
1417  * Arguments:
1418  *
1419  * int interval
1420  * how long a key needs to have been dead for before we purge it
1421  *
1422  * int policy_id
1423  * ID of the policy
1424  *
1425  * Returns:
1426  * int
1427  * Status return. 0 on success.
1428  * other on fail
1429  */
1430 
1431 int do_purge(int interval, int policy_id)
1432 {
1433  char* sql = NULL; /* SQL query */
1434  char* sql1 = NULL; /* SQL query */
1435  char* sql2 = NULL; /* SQL query */
1436  char* sql3 = NULL; /* SQL query */
1437  int status = 0; /* Status return */
1438  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
1439  DB_RESULT result; /* Result of the query */
1440  DB_ROW row = NULL; /* Row data */
1441 
1442  char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */
1443  unsigned int nchar; /* Number of characters converted */
1444 
1445  int temp_id = -1; /* place to store the key id returned */
1446  char* temp_loc = NULL; /* place to store location returned */
1447  int count = 0; /* How many keys don't match the purge */
1448 
1449  char *rightnow;
1450 
1451  /* Key information */
1452  hsm_key_t *key = NULL;
1453 
1454  log_msg(NULL, LOG_DEBUG, "Purging keys...");
1455 
1456  rightnow = DtParseDateTimeString("now");
1457 
1458  /* Check datetime in case it came back NULL */
1459  if (rightnow == NULL) {
1460  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
1461  exit(1);
1462  }
1463 
1464  /* Select rows */
1465  StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
1466 
1467  if (policy_id != -1) {
1468  StrAppend(&sql, "and policy_id = ");
1469  snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
1470  StrAppend(&sql, stringval);
1471  }
1472 
1473  DusEnd(&sql);
1474 
1475  status = DbExecuteSql(DbHandle(), sql, &result);
1476 
1477  if (status == 0) {
1478  status = DbFetchRow(result, &row);
1479  while (status == 0) {
1480  /* Got a row, check it */
1481  DbInt(row, 0, &temp_id);
1482  DbString(row, 1, &temp_loc);
1483 
1484  sql1 = DqsCountInit("dnsseckeys");
1485  DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
1486  DdsConditionInt(&sql1, "(state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
1487 
1488 #ifdef USE_MYSQL
1489  nchar = snprintf(buffer, sizeof(buffer),
1490  " or state = %d and DEAD > DATE_ADD('%s', INTERVAL -%d SECOND)) ", KSM_STATE_DEAD, rightnow, interval);
1491 #else
1492  nchar = snprintf(buffer, sizeof(buffer),
1493  " or state = %d and DEAD > DATETIME('%s', '-%d SECONDS')) ", KSM_STATE_DEAD, rightnow, interval);
1494 #endif /* USE_MYSQL */
1495 
1496  StrAppend(&sql1, buffer);
1497  DqsEnd(&sql1);
1498 
1499  status = DbIntQuery(DbHandle(), &count, sql1);
1500  DqsFree(sql1);
1501 
1502  if (status != 0) {
1503  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1504  DbStringFree(temp_loc);
1505  DbFreeRow(row);
1506  StrFree(rightnow);
1507  return status;
1508  }
1509 
1510  /* If the count is zero then there is no reason not to purge this key */
1511  if (count == 0) {
1512 
1513  /* Delete from dnsseckeys */
1514  sql2 = DdsInit("dnsseckeys");
1515  DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
1516  DdsEnd(&sql);
1517 
1518  status = DbExecuteSqlNoResult(DbHandle(), sql2);
1519  DdsFree(sql2);
1520  if (status != 0)
1521  {
1522  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1523  DbStringFree(temp_loc);
1524  DbFreeRow(row);
1525  StrFree(rightnow);
1526  return status;
1527  }
1528 
1529  /* Delete from keypairs */
1530  sql3 = DdsInit("keypairs");
1531  DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
1532  DdsEnd(&sql);
1533 
1534  status = DbExecuteSqlNoResult(DbHandle(), sql3);
1535  DdsFree(sql3);
1536  if (status != 0)
1537  {
1538  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1539  DbStringFree(temp_loc);
1540  DbFreeRow(row);
1541  StrFree(rightnow);
1542  return status;
1543  }
1544 
1545  /* Delete from the HSM */
1546  key = hsm_find_key_by_id(NULL, temp_loc);
1547 
1548  if (!key) {
1549  log_msg(NULL, LOG_ERR, "Key not found: %s\n", temp_loc);
1550  DbStringFree(temp_loc);
1551  DbFreeRow(row);
1552  StrFree(rightnow);
1553  return -1;
1554  }
1555 
1556  status = hsm_remove_key(NULL, key);
1557 
1558  hsm_key_free(key);
1559 
1560  if (!status) {
1561  log_msg(NULL, LOG_INFO, "Key remove successful.\n");
1562  } else {
1563  log_msg(NULL, LOG_ERR, "Key remove failed.\n");
1564  DbStringFree(temp_loc);
1565  DbFreeRow(row);
1566  StrFree(rightnow);
1567  return -1;
1568  }
1569  }
1570 
1571  /* NEXT! */
1572  status = DbFetchRow(result, &row);
1573  }
1574 
1575  /* Convert EOF status to success */
1576 
1577  if (status == -1) {
1578  status = 0;
1579  }
1580 
1581  DbFreeResult(result);
1582  }
1583 
1584  DusFree(sql);
1585  DbFreeRow(row);
1586 
1587  DbStringFree(temp_loc);
1588  StrFree(rightnow);
1589 
1590  return status;
1591 }
1592 
1593 int NewDSSet(int zone_id, const char* zone_name, const char* DSSubmitCmd) {
1594  int where = 0; /* for the SELECT statement */
1595  char* sql = NULL; /* SQL statement (when verifying) */
1596  char* sql2 = NULL; /* SQL statement (if getting DS) */
1597  int status = 0; /* Status return */
1598  int count = 0; /* How many keys fit our select? */
1599  int i = 0; /* A counter */
1600  int j = 0; /* Another counter */
1601  char* insql = NULL; /* SQL "IN" clause */
1602  int* keyids; /* List of IDs of keys to promote */
1603  DB_RESULT result; /* List result set */
1604  KSM_KEYDATA data; /* Data for this key */
1605  size_t nchar; /* Number of characters written */
1606  char buffer[256]; /* For constructing part of the command */
1607  char* count_clause = NULL;
1608  char* where_clause = NULL;
1609  int id = -1; /* ID of key which will retire */
1610  int active_count = -1; /* Number of currently active keys */
1611 
1612  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
1613  DB_RESULT result3; /* Result of DS query */
1614  KSM_KEYDATA data3; /* DS information */
1615  char* ds_buffer = NULL; /* Contents of DS records */
1616  char* ds_seen_buffer = NULL; /* Which keys have we promoted */
1617  char* temp_char = NULL; /* Contents of DS records */
1618 
1619  /* Key information */
1620  hsm_key_t *key = NULL;
1621  ldns_rr *dnskey_rr = NULL;
1622  hsm_sign_params_t *sign_params = NULL;
1623 
1624  FILE *fp;
1625  int bytes_written = -1;
1626 
1627  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d, %d, %d, %d, %d)",
1631  if (nchar >= sizeof(buffer)) {
1632  status = -1;
1633  return status;
1634  }
1635 
1636  /* Find the oldest active key, this is the one which will be retired
1637  NOTE; this may not match any keys */
1638 
1639  count_clause = DqsCountInit("KEYDATA_VIEW");
1640  DqsConditionInt(&count_clause, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1641  DqsConditionInt(&count_clause, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
1642  if (zone_id != -1) {
1643  DqsConditionInt(&count_clause, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1644  }
1645 
1646  status = DbIntQuery(DbHandle(), &active_count, count_clause);
1647  StrFree(count_clause);
1648  if (status != 0)
1649  {
1650  log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
1651  return status;
1652  }
1653 
1654  if (active_count > 0) {
1655 
1656  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
1657  StrAppend(&where_clause, "select id from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
1658  StrAppend(&where_clause, stringval);
1659  StrAppend(&where_clause, " and retire = (select min(retire) from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
1660  StrAppend(&where_clause, stringval);
1661  StrAppend(&where_clause, ")");
1662 
1663  /* Execute query and free up the query string */
1664  status = DbIntQuery(DbHandle(), &id, where_clause);
1665  StrFree(where_clause);
1666  if (status != 0)
1667  {
1668  log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
1669  return status;
1670  }
1671  }
1672 
1673  /* First up we need to count how many DSs we will have */
1674  where = 0;
1675  sql = DqsCountInit("KEYDATA_VIEW");
1676  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1677  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
1678  if (zone_id != -1) {
1679  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1680  }
1681  if (id != -1) {
1682  DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
1683  }
1684  DqsEnd(&sql);
1685 
1686  status = DbIntQuery(DbHandle(), &count, sql);
1687  DqsFree(sql);
1688 
1689  if (status != 0) {
1690  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1691  return status;
1692  }
1693 
1694  if (count == 0) {
1695  /* No KSKs in zone? */
1696  return status;
1697  }
1698 
1699  /* Allocate space for the list of key IDs */
1700  keyids = MemMalloc(count * sizeof(int));
1701 
1702  /* Get the list of IDs */
1703 
1704  where = 0;
1705  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1706  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1707  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
1708  if (zone_id != -1) {
1709  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1710  }
1711  if (id != -1) {
1712  DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
1713  }
1714  DqsEnd(&sql);
1715 
1716  status = KsmKeyInitSql(&result, sql);
1717  DqsFree(sql);
1718 
1719  if (status == 0) {
1720  while (status == 0) {
1721  status = KsmKey(result, &data);
1722  if (status == 0) {
1723  keyids[i] = data.keypair_id;
1724  i++;
1725  }
1726  }
1727 
1728  /* Convert EOF status to success */
1729 
1730  if (status == -1) {
1731  status = 0;
1732  } else {
1733  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1734  StrFree(keyids);
1735  return status;
1736  }
1737 
1738  KsmKeyEnd(result);
1739 
1740  } else {
1741  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1742  StrFree(keyids);
1743  return status;
1744  }
1745 
1746  /*
1747  * Now construct the "IN" statement listing the IDs of the keys we
1748  * are planning to change the state of.
1749  */
1750 
1751  StrAppend(&insql, "(");
1752  for (j = 0; j < i; ++j) {
1753  if (j != 0) {
1754  StrAppend(&insql, ",");
1755  }
1756  snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
1757  StrAppend(&insql, buffer);
1758  }
1759  StrAppend(&insql, ")");
1760 
1761  StrFree(keyids);
1762 
1763  /* Indicate that the DS record should now be submitted */
1764  sql2 = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1765  DqsConditionKeyword(&sql2, "ID", DQS_COMPARE_IN, insql, 0);
1766  DqsConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
1767  DqsEnd(&sql2);
1768 
1769  log_msg(NULL, LOG_INFO, "DS Record set has changed, the current set looks like:");
1770 
1771  status = KsmKeyInitSql(&result3, sql2);
1772  DqsFree(sql2);
1773  if (status == 0) {
1774  status = KsmKey(result3, &data3);
1775  while (status == 0) {
1776 
1777  /* Code to output the DNSKEY record (stolen from hsmutil) */
1778  key = hsm_find_key_by_id(NULL, data3.location);
1779 
1780  if (!key) {
1781  log_msg(NULL, LOG_ERR, "Key %s in DB but not repository.", data3.location);
1782  StrFree(insql);
1783  return status;
1784  }
1785 
1786  StrAppend(&ds_seen_buffer, ", ");
1787  StrAppend(&ds_seen_buffer, data3.location);
1788 
1789  sign_params = hsm_sign_params_new();
1790  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone_name);
1791  sign_params->algorithm = data3.algorithm;
1792  sign_params->flags = LDNS_KEY_ZONE_KEY;
1793  sign_params->flags += LDNS_KEY_SEP_KEY;
1794  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
1795 
1796  temp_char = ldns_rr2str(dnskey_rr);
1797  ldns_rr_free(dnskey_rr);
1798 
1799  /* Replace tab with white-space */
1800  for (i = 0; temp_char[i]; ++i) {
1801  if (temp_char[i] == '\t') {
1802  temp_char[i] = ' ';
1803  }
1804  }
1805  log_msg(NULL, LOG_INFO, "%s", temp_char);
1806 
1807  /* We need to strip off trailing comments before we send
1808  to any clients that might be listening */
1809  for (i = 0; temp_char[i]; ++i) {
1810  if (temp_char[i] == ';') {
1811  temp_char[i] = '\n';
1812  temp_char[i+1] = '\0';
1813  break;
1814  }
1815  }
1816  StrAppend(&ds_buffer, temp_char);
1817  StrFree(temp_char);
1818 
1819 /* StrAppend(&ds_buffer, "\n;KSK DS record (SHA1):\n");
1820  ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1);
1821  temp_char = ldns_rr2str(ds_sha1_rr);
1822  StrAppend(&ds_buffer, temp_char);
1823  StrFree(temp_char);
1824 
1825  StrAppend(&ds_buffer, "\n;KSK DS record (SHA256):\n");
1826  ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256);
1827  temp_char = ldns_rr2str(ds_sha256_rr);
1828  StrAppend(&ds_buffer, temp_char);
1829  StrFree(temp_char);
1830 */
1831 
1832  hsm_sign_params_free(sign_params);
1833  hsm_key_free(key);
1834  status = KsmKey(result3, &data3);
1835  }
1836  /* Convert EOF status to success */
1837  if (status == -1) {
1838  status = 0;
1839  }
1840 
1841  KsmKeyEnd(result3);
1842  }
1843 
1844  if (DSSubmitCmd[0] != '\0') {
1845  /* send records to the configured command */
1846  fp = popen(DSSubmitCmd, "w");
1847  if (fp == NULL) {
1848  log_msg(NULL, LOG_ERR, "Failed to run command: %s: %s", DSSubmitCmd, strerror(errno));
1849  return -1;
1850  }
1851  bytes_written = fprintf(fp, "%s", ds_buffer);
1852  if (bytes_written < 0) {
1853  log_msg(NULL, LOG_ERR, "Failed to write to %s: %s", DSSubmitCmd, strerror(errno));
1854  return -1;
1855  }
1856 
1857  if (pclose(fp) == -1) {
1858  log_msg(NULL, LOG_ERR, "Failed to close %s: %s", DSSubmitCmd, strerror(errno));
1859  return -1;
1860  }
1861  }
1862 
1863  StrFree(ds_buffer);
1864 
1865  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);
1866 
1867  StrFree(ds_seen_buffer);
1868 
1869  StrFree(insql);
1870 
1871  return status;
1872 }
1873 
1875 {
1876  int result = 0;
1877  char *hsm_error_message = NULL;
1878 
1879  result = hsm_check_context(*ctx);
1880 
1881  /* If we didn't get HSM_OK then close and reopen HSM */
1882  if (result != HSM_OK) {
1883 
1884  if (*ctx) {
1885  hsm_destroy_context(*ctx);
1886  }
1887 
1888  result = hsm_close();
1889 
1890  if (config->configfile != NULL) {
1891  result = hsm_open(config->configfile, hsm_prompt_pin, NULL);
1892  } else {
1893  result = hsm_open(OPENDNSSEC_CONFIG_FILE, hsm_prompt_pin, NULL);
1894  }
1895  if (result) {
1896  hsm_error_message = hsm_get_error(*ctx);
1897  if (hsm_error_message) {
1898  log_msg(config, LOG_ERR, hsm_error_message);
1899  free(hsm_error_message);
1900  } else {
1901  /* decode the error code ourselves
1902  TODO find if there is a better way to do this (and can all
1903  of these be returned? are there others?) */
1904  switch (result) {
1905  case HSM_ERROR:
1906  log_msg(config, LOG_ERR, "hsm_open() result: HSM error");
1907  break;
1908  case HSM_PIN_INCORRECT:
1909  log_msg(config, LOG_ERR, "hsm_open() result: incorrect PIN");
1910  break;
1911  case HSM_CONFIG_FILE_ERROR:
1912  log_msg(config, LOG_ERR, "hsm_open() result: config file error");
1913  break;
1914  case HSM_REPOSITORY_NOT_FOUND:
1915  log_msg(config, LOG_ERR, "hsm_open() result: repository not found");
1916  break;
1917  case HSM_NO_REPOSITORIES:
1918  log_msg(config, LOG_ERR, "hsm_open() result: no repositories");
1919  break;
1920  default:
1921  log_msg(config, LOG_ERR, "hsm_open() result: %d", result);
1922  }
1923  }
1924  unlink(config->pidfile);
1925  exit(1);
1926  }
1927  log_msg(config, LOG_INFO, "HSM reopened successfully.");
1928  *ctx = hsm_create_context();
1929  } else {
1930  log_msg(config, LOG_INFO, "HSM connection open.");
1931  }
1932 
1933 }
1934