OpenDNSSEC-enforcer  1.4.1
enforcer.c
Go to the documentation of this file.
1 /*
2  * $Id: enforcer.c 7028 2013-02-13 11:41:17Z sion $
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 "config.h"
37 
38 #include <stdlib.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <syslog.h>
43 #include <sys/stat.h>
44 
45 #include <libxml/xmlreader.h>
46 #include <libxml/xpath.h>
47 
48 #include "daemon.h"
49 #include "daemon_util.h"
50 #include "enforcer.h"
51 #include "kaspaccess.h"
52 
53 #include "ksm/ksm.h"
54 #include "ksm/memory.h"
55 #include "ksm/string_util.h"
56 #include "ksm/string_util2.h"
57 #include "ksm/datetime.h"
58 #include "ksm/db_fields.h"
59 
60 #include "libhsm.h"
61 #include "libhsmdns.h"
62 
63 int
65 {
66  if (config == NULL) {
67  log_msg(NULL, LOG_ERR, "Error in server_init, no config provided");
68  exit(1);
69  }
70 
71  /* set the default pidfile if nothing was provided on the command line*/
72  if (config->pidfile == NULL) {
73  config->pidfile = OPENDNSSEC_ENFORCER_PIDFILE;
74  }
75 
76  return 0;
77 }
78 
79 /*
80  * Main loop of enforcerd server
81  */
82 void
84 {
85  DB_RESULT handle;
86  DB_HANDLE dbhandle;
87  int status = 0;
88  struct timeval tv;
89  KSM_POLICY *policy;
90  int result;
91  hsm_ctx_t *ctx = NULL;
92  char *hsm_error_message = NULL;
93 
94  FILE *lock_fd = NULL; /* for sqlite file locking */
95  char *lock_filename = NULL;
96 
97  if (config == NULL) {
98  log_msg(NULL, LOG_ERR, "Error in server_main, no config provided");
99  exit(1);
100  }
101 
102  policy = KsmPolicyAlloc();
103  if (policy == NULL) {
104  log_msg(config, LOG_ERR, "Malloc for policy struct failed");
105  exit(1);
106  }
107  kaspSetPolicyDefaults(policy, NULL);
108 
109  /* Read the config file */
110  status = ReadConfig(config , 0);
111  if (status != 0) {
112  log_msg(config, LOG_ERR, "Error reading config");
113  exit(1);
114  }
115 
116  /* If we are doing key generation then connect to the hsm */
117 /* if (config->manualKeyGeneration == 0) {*/
118  /* We keep the HSM connection open for the lifetime of the daemon */
119  if (config->configfile != NULL) {
120  result = hsm_open(config->configfile, hsm_check_pin);
121  } else {
122  result = hsm_open(OPENDNSSEC_CONFIG_FILE, hsm_check_pin);
123  }
124  if (result) {
125  hsm_error_message = hsm_get_error(ctx);
126  if (hsm_error_message) {
127  log_msg(config, LOG_ERR, "%s", hsm_error_message);
128  free(hsm_error_message);
129  } else {
130  /* decode the error code ourselves
131  TODO find if there is a better way to do this (and can all of these be returned? are there others?) */
132  switch (result) {
133  case HSM_ERROR:
134  log_msg(config, LOG_ERR, "hsm_open() result: HSM error");
135  break;
136  case HSM_PIN_INCORRECT:
137  log_msg(config, LOG_ERR, "hsm_open() result: incorrect PIN");
138  break;
139  case HSM_CONFIG_FILE_ERROR:
140  log_msg(config, LOG_ERR, "hsm_open() result: config file error");
141  break;
142  case HSM_REPOSITORY_NOT_FOUND:
143  log_msg(config, LOG_ERR, "hsm_open() result: repository not found");
144  break;
145  case HSM_NO_REPOSITORIES:
146  log_msg(config, LOG_ERR, "hsm_open() result: no repositories");
147  break;
148  default:
149  log_msg(config, LOG_ERR, "hsm_open() result: %d", result);
150  }
151  }
152  exit(1);
153  }
154  log_msg(config, LOG_INFO, "HSM opened successfully.");
155  ctx = hsm_create_context();
156  /*}*/
157 
158  log_msg(config, LOG_INFO, "Checking database connection...");
159  if (kaspTryConnect(config, &dbhandle)) {
160  log_msg(config, LOG_ERR, "Database connection failed");
161  exit(1);
162  }
163  log_msg(config, LOG_INFO, "Database connection ok.");
164 
165  /* Create pidfile as late as possible to report start up error */
166  if (writepid(config) == -1) {
167  log_msg(config, LOG_ERR, "cannot write the pidfile %s: %s",
168  config->pidfile, strerror(errno));
169  exit(1);
170  }
171 
172  while (1) {
173 
174  /* Read the config file */
175  status = ReadConfig(config, 1);
176  if (status != 0) {
177  log_msg(config, LOG_ERR, "Error reading config");
178  unlink(config->pidfile);
179  exit(1);
180  }
181  /* If we are in sqlite mode then take a lock out on a file to
182  prevent multiple access (not sure that we can be sure that sqlite is
183  safe for multiple processes to access). */
184  if (DbFlavour() == SQLITE_DB) {
185 
186  /* set up lock filename (it may have changed?) */
187  lock_filename = NULL;
188  StrAppend(&lock_filename, (char *)config->schema);
189  StrAppend(&lock_filename, ".our_lock");
190 
191  lock_fd = fopen(lock_filename, "w");
192  status = get_lite_lock(lock_filename, lock_fd);
193  StrFree(lock_filename);
194  if (status != 0) {
195  log_msg(config, LOG_ERR, "Error getting db lock");
196  unlink(config->pidfile);
197  exit(1);
198  }
199  }
200 
201  log_msg(config, LOG_INFO, "Connecting to Database...");
202  kaspConnect(config, &dbhandle);
203 
204  /* Read all policies */
205  status = KsmPolicyInit(&handle, NULL);
206  if (status == 0) {
207  /* get the first policy */
208  status = KsmPolicy(handle, policy);
209  while (status == 0) {
210  log_msg(config, LOG_INFO, "Policy %s found.", policy->name);
211  /* Clear the policy struct */
212  kaspSetPolicyDefaults(policy, NULL);
213 
214  /* Read the parameters for that policy */
215  status = kaspReadPolicy(policy);
216 
217  /* Update the salt if it is not up to date */
218  if (policy->denial->version == 3)
219  {
220  status = KsmPolicyUpdateSalt(policy);
221  if (status != 0) {
222  /* Don't return? */
223  log_msg(config, LOG_ERR, "Error (%d) updating salt for %s", status, policy->name);
224  }
225  }
226 
227  /* Do keygen stuff if required */
228  if (config->manualKeyGeneration == 0) {
229  status = do_keygen(config, policy, ctx);
230  }
231 
232  /* TODO move communicated stuff here eventually */
233  /* Find all zones and do communication stuff */
234 
235  /* Purge dead keys if we are asked to in this policy */
236  if (policy->keys->purge != -1) {
237  status = do_purge(policy->keys->purge, policy->id);
238  }
239 
240  /* get next policy */
241  status = KsmPolicy(handle, policy);
242  }
243  } else {
244  log_msg(config, LOG_ERR, "Error querying KASP DB for policies.");
245  unlink(config->pidfile);
246  exit(1);
247  }
248 
249  /* Communicate zones to the signer */
250  KsmParameterCollectionCache(1); /* Enable caching of policy parameters while in do_communication() */
251  do_communication(config, policy);
253 
254  DbFreeResult(handle);
255 
256  /* Disconnect from DB in case we are asleep for a long time */
257  log_msg(config, LOG_INFO, "Disconnecting from Database...");
258  kaspDisconnect(&dbhandle);
259 
260  /* Release sqlite lock file (if we have it) */
261  if (DbFlavour() == SQLITE_DB) {
262  status = release_lite_lock(lock_fd);
263  if (status != 0) {
264  log_msg(config, LOG_ERR, "Error releasing db lock");
265  unlink(config->pidfile);
266  exit(1);
267  }
268  fclose(lock_fd);
269  }
270 
271  if (config->once == true ){
272  log_msg(config, LOG_INFO, "Running once only, exiting...");
273  break;
274  }
275 
276  /* If we have been sent a SIGTERM then it is time to exit */
277  if (config->term == 1 ){
278  log_msg(config, LOG_INFO, "Received SIGTERM, exiting...");
279  break;
280  }
281  /* Or SIGINT */
282  if (config->term == 2 ){
283  log_msg(config, LOG_INFO, "Received SIGINT, exiting...");
284  break;
285  }
286 
287  /* sleep for the interval */
288  tv.tv_sec = config->interval;
289  tv.tv_usec = 0;
290  log_msg(config, LOG_INFO, "Sleeping for %i seconds.",config->interval);
291  select(0, NULL, NULL, NULL, &tv);
292 
293  /* If we have been sent a SIGTERM then it is time to exit */
294  if (config->term == 1 ){
295  log_msg(config, LOG_INFO, "Received SIGTERM, exiting...");
296  break;
297  }
298  /* Or SIGINT */
299  if (config->term == 2 ){
300  log_msg(config, LOG_INFO, "Received SIGINT, exiting...");
301  break;
302  }
303 
304  /* Make sure that we can still talk to the HSM; this call exits if
305  we can not (after trying to reconnect) */
306  check_hsm_connection(&ctx, config);
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_ERR, "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 = NULL;
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 
731  status2 = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, 0);
732  if (status2 != 0) {
733  log_msg(config, LOG_ERR, "Error allocating zsks to zone %s", zone_name);
734  /* Don't return? try to parse the rest of the zones? */
735  ret = xmlTextReaderRead(reader);
736  StrFree(tag_name);
737  StrFree(zone_name);
738  StrFree(current_filename);
739  continue;
740  }
741  status2 = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, policy->ksk->rollover_scheme);
742  if (status2 != 0) {
743  log_msg(config, LOG_ERR, "Error allocating ksks to zone %s", zone_name);
744  /* Don't return? try to parse the rest of the zones? */
745  ret = xmlTextReaderRead(reader);
746  StrFree(tag_name);
747  StrFree(zone_name);
748  StrFree(current_filename);
749  continue;
750  }
751 
752  /* turn this zone and policy into a file */
753  status2 = commGenSignConf(zone_name, zone_id, current_filename, policy, &signer_flag, config->interval, config->manualKeyGeneration, config->DSSubmitCmd, config->DSSubCKA_ID);
754  if (status2 == -2) {
755  log_msg(config, LOG_ERR, "Signconf not written for %s", zone_name);
756  /* Don't return? try to parse the rest of the zones? */
757  ret = xmlTextReaderRead(reader);
758  StrFree(tag_name);
759  StrFree(zone_name);
760  StrFree(current_filename);
761  continue;
762  }
763  else if (status2 != 0) {
764  log_msg(config, LOG_ERR, "Error writing signconf for %s", zone_name);
765  /* Don't return? try to parse the rest of the zones? */
766  ret = xmlTextReaderRead(reader);
767  StrFree(tag_name);
768  StrFree(zone_name);
769  StrFree(current_filename);
770  continue;
771  }
772 
773  /* See if we need to send a warning about an impending rollover */
774  if (config->rolloverNotify != -1) {
775  datetime = DtParseDateTimeString("now");
776 
777  /* Check datetime in case it came back NULL */
778  if (datetime == NULL) {
779  log_msg(config, LOG_ERR, "Couldn't turn \"now\" into a date, quiting...");
780  unlink(config->pidfile);
781  exit(1);
782  }
783 
784  /* First the KSK */
785  status2 = KsmCheckNextRollover(KSM_TYPE_KSK, zone_id, &ksk_expected);
786  if (status2 == -1) {
787  log_msg(config, LOG_INFO, "No active KSKs yet for zone %s, can't check for impending rollover", zone_name);
788  }
789  else if (status2 != 0) {
790  log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
791  /* TODO should we quit or continue? */
792  } else {
793  status2 = DtDateDiff(ksk_expected, datetime, &roll_time);
794  if (status2 != 0) {
795  log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
796  } else {
797 
798  if (roll_time <= config->rolloverNotify) {
799  log_msg(config, LOG_INFO, "Rollover of KSK expected at %s for %s", ksk_expected, zone_name);
800  }
801  }
802  StrFree(ksk_expected);
803  }
804  StrFree(datetime);
805  }
806 
807  StrFree(current_filename);
808  StrFree(zone_name);
809  }
810  /* Read the next line */
811  ret = xmlTextReaderRead(reader);
812  StrFree(tag_name);
813  }
814  xmlFreeTextReader(reader);
815  if (ret != 0) {
816  log_msg(config, LOG_ERR, "%s : failed to parse", zonelist_filename);
817  }
818  } else {
819  log_msg(config, LOG_ERR, "Unable to open %s", zonelist_filename);
820  }
821 
822  xmlFreeDoc(doc);
823  StrFree(zonelist_filename);
824 
825  return status;
826 }
827 
828 /*
829  * generate the configuration file for the signer
830 
831  * returns 0 on success and -1 if something went wrong
832  * -2 if the RequestKeys call failed
833  */
834 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, int DSSubCKA_ID)
835 {
836  int status = 0;
837  int status2 = 0;
838  FILE *file, *file2;
839  int char1, char2; /* for the comparison between 2 files */
840  int same = 0;
841  char *temp_filename; /* In case this fails we write to a temp file and only overwrite
842  the current file when we are finished */
843  char *old_filename; /* Keep a copy of the previous version, just in case! (Also gets
844  round potentially different behaviour of rename over existing
845  file.) */
846  int gencnt; /* Number of keys in generate state */
847  char *signer_command; /* how we will call the signer */
848  int NewDS = 0; /* Did we change the DS Set in any way? */
849  char* datetime = DtParseDateTimeString("now");
850 
851  /* Check datetime in case it came back NULL */
852  if (datetime == NULL) {
853  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
854  return -1;
855  }
856 
857  if (zone_name == NULL || current_filename == NULL || policy == NULL)
858  {
859  /* error */
860  log_msg(NULL, LOG_ERR, "commGenSignConf, NULL policy or zone provided");
861  MemFree(datetime);
862  return -1;
863  }
864 
865  old_filename = NULL;
866  StrAppend(&old_filename, current_filename);
867  StrAppend(&old_filename, ".OLD");
868 
869  temp_filename = NULL;
870  StrAppend(&temp_filename, current_filename);
871  StrAppend(&temp_filename, ".tmp");
872 
873  file = fopen(temp_filename, "w");
874 
875  if (file == NULL)
876  {
877  /* error */
878  log_msg(NULL, LOG_ERR, "Could not open: %s (%s)", temp_filename,
879  strerror(errno));
880  MemFree(datetime);
881  StrFree(temp_filename);
882  StrFree(old_filename);
883  return -1;
884  }
885 
886  fprintf(file, "<SignerConfiguration>\n");
887  fprintf(file, "\t<Zone name=\"%s\">\n", zone_name);
888 
889  fprintf(file, "\t\t<Signatures>\n");
890  fprintf(file, "\t\t\t<Resign>PT%dS</Resign>\n", policy->signature->resign);
891  fprintf(file, "\t\t\t<Refresh>PT%dS</Refresh>\n", policy->signer->refresh);
892  fprintf(file, "\t\t\t<Validity>\n");
893  fprintf(file, "\t\t\t\t<Default>PT%dS</Default>\n", policy->signature->valdefault);
894  fprintf(file, "\t\t\t\t<Denial>PT%dS</Denial>\n", policy->signature->valdenial);
895  fprintf(file, "\t\t\t</Validity>\n");
896  fprintf(file, "\t\t\t<Jitter>PT%dS</Jitter>\n", policy->signer->jitter);
897  fprintf(file, "\t\t\t<InceptionOffset>PT%dS</InceptionOffset>\n", policy->signature->clockskew);
898  fprintf(file, "\t\t</Signatures>\n");
899 
900  fprintf(file, "\n");
901 
902  fprintf(file, "\t\t<Denial>\n");
903  if (policy->denial->version == 3)
904  {
905  fprintf(file, "\t\t\t<NSEC3>\n");
906  if (policy->denial->optout == 1)
907  {
908  fprintf(file, "\t\t\t\t<OptOut />\n");
909  }
910  fprintf(file, "\t\t\t\t<Hash>\n");
911  fprintf(file, "\t\t\t\t\t<Algorithm>%d</Algorithm>\n", policy->denial->algorithm);
912  fprintf(file, "\t\t\t\t\t<Iterations>%d</Iterations>\n", policy->denial->iteration);
913  if (policy->denial->salt[0] == '\0') {
914  fprintf(file, "\t\t\t\t\t<Salt>-</Salt>\n");
915  } else {
916  fprintf(file, "\t\t\t\t\t<Salt>%s</Salt>\n", policy->denial->salt);
917  }
918  fprintf(file, "\t\t\t\t</Hash>\n");
919  fprintf(file, "\t\t\t</NSEC3>\n");
920  } else {
921  fprintf(file, "\t\t\t<NSEC />\n");
922  }
923 
924  fprintf(file, "\t\t</Denial>\n");
925 
926  fprintf(file, "\n");
927 
928  /* start of keys section */
929  fprintf(file, "\t\t<Keys>\n");
930  fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->ksk->ttl);
931 
932  /* get new keys _only_ if we don't have them from before */
933  status = KsmRequestKeys(0, 0, datetime, commKeyConfig, file, policy->id, zone_id, run_interval, &NewDS);
934  if (status != 0) {
935  /*
936  * Something went wrong (it should have been logged) stop this zone.
937  * Clean up the files, don't call the signer and move on to the next zone.
938  */
939  log_msg(NULL, LOG_ERR, "KsmRequestKeys returned: %d", status);
940 
941  /* check for the specific case of not having any keys
942  TODO check that this code can ever be executed after the restructure */
943  if (status == -1) {
944  status2 = KsmRequestGenerateCount(KSM_TYPE_KSK, &gencnt, zone_id);
945  if (status2 == 0 && gencnt == 0) {
946  if(man_key_gen == 1) {
947  log_msg(NULL, LOG_ERR, "There are no KSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
948  } else {
949  log_msg(NULL, LOG_WARNING, "There are no KSKs in the generate state; ods-enforcerd will create some on its next run.");
950  }
951  }
952  else if (status2 == 0) {
953  status2 = KsmRequestGenerateCount(KSM_TYPE_ZSK, &gencnt, zone_id);
954  if (status2 == 0 && gencnt == 0) {
955  if(man_key_gen == 1) {
956  log_msg(NULL, LOG_ERR, "There are no ZSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
957  } else {
958  log_msg(NULL, LOG_WARNING, "There are no ZSKs in the generate state; ods-enforcerd will create some on its next run.");
959  }
960  }
961  }
962  else {
963  log_msg(NULL, LOG_ERR, "KsmRequestGenerateCount returned: %d", status2);
964  }
965  }
966 
967  status = fclose(file);
968  unlink(temp_filename);
969  MemFree(datetime);
970  StrFree(temp_filename);
971  StrFree(old_filename);
972 
973  return -2;
974  }
975 
976  fprintf(file, "\t\t</Keys>\n");
977 
978  fprintf(file, "\n");
979 
980  fprintf(file, "\t\t<SOA>\n");
981  fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->signer->soattl);
982  fprintf(file, "\t\t\t<Minimum>PT%dS</Minimum>\n", policy->signer->soamin);
983  fprintf(file, "\t\t\t<Serial>%s</Serial>\n", KsmKeywordSerialValueToName( policy->signer->serial) );
984  fprintf(file, "\t\t</SOA>\n");
985 
986  fprintf(file, "\t</Zone>\n");
987  fprintf(file, "</SignerConfiguration>\n");
988 
989  /* Force flush of stream to disc cache and then onto disc proper
990  * Do we need to do this? It might be significant on ext4
991  * NOTE though that there may be a significant overhead associated with it
992  * ALSO, if we do lose power maybe we should disregard any files when we come
993  * back as we won't know if they are now too old? */
994  /*
995  if (fflush(file) != 0) {
996  MemFree(datetime);
997  return -1;
998  }
999 
1000  if (fsync(fileno(file)) != 0) {
1001  MemFree(datetime);
1002  return -1;
1003  }
1004  */
1005 
1006  status = fclose(file);
1007  MemFree(datetime);
1008 
1009  if (status == EOF) /* close failed... do something? */
1010  {
1011  log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
1012  StrFree(temp_filename);
1013  StrFree(old_filename);
1014  return -1;
1015  }
1016 
1017  /* compare our temp file with the current one (if it exists) */
1018  file = fopen(temp_filename, "rb");
1019  if (file == NULL)
1020  {
1021  /* error */
1022  log_msg(NULL, LOG_ERR, "Could not reopen: %s", temp_filename);
1023  StrFree(temp_filename);
1024  StrFree(old_filename);
1025  return -1;
1026  }
1027 
1028  file2 = fopen(current_filename, "rb"); /* Might not exist */
1029 
1030  /* If current_filename exists then compare its contents to temp_filename */
1031  if (file2 != NULL) {
1032  same = 1;
1033  while(!feof(file)) {
1034  char1 = fgetc(file);
1035  if(ferror(file)) {
1036  log_msg(NULL, LOG_ERR, "Could not read: %s", temp_filename);
1037  fclose(file);
1038  fclose(file2);
1039  StrFree(temp_filename);
1040  StrFree(old_filename);
1041  return -1;
1042  }
1043  char2 = fgetc(file2);
1044  if(ferror(file2)) {
1045  log_msg(NULL, LOG_ERR, "Could not read: %s", current_filename);
1046  fclose(file);
1047  fclose(file2);
1048  StrFree(temp_filename);
1049  StrFree(old_filename);
1050  return -1;
1051  }
1052  if(char1 != char2) {
1053  same = 0;
1054  break;
1055  }
1056  }
1057 
1058  status = fclose(file2);
1059  if (status == EOF) /* close failed... do something? */
1060  {
1061  log_msg(NULL, LOG_ERR, "Could not close: %s", current_filename);
1062  fclose(file);
1063  StrFree(temp_filename);
1064  StrFree(old_filename);
1065  return -1;
1066  }
1067  }
1068 
1069  status = fclose(file);
1070  if (status == EOF) /* close failed... do something? */
1071  {
1072  log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
1073  StrFree(temp_filename);
1074  StrFree(old_filename);
1075  return -1;
1076  }
1077 
1078  /* If either current_filename does not exist, or if it is different to temp then same will == 0 */
1079 
1080  if (same == 0) {
1081 
1082  /* we now have a complete xml file. First move the old one out of the way */
1083  status = rename(current_filename, old_filename);
1084  if (status != 0 && status != -1)
1085  {
1086  /* cope with initial condition of files not existing */
1087  log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", current_filename, old_filename);
1088  StrFree(old_filename);
1089  StrFree(temp_filename);
1090  return -1;
1091  }
1092 
1093  /* Then copy our temp into place */
1094  if (rename(temp_filename, current_filename) != 0)
1095  {
1096  log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", temp_filename, current_filename);
1097  StrFree(old_filename);
1098  StrFree(temp_filename);
1099  return -1;
1100  }
1101 
1102  if (*signer_flag == 1) {
1103  /* call the signer engine to tell it that something changed */
1104  /* TODO for beta version connect straight to the socket
1105  should we make a blocking call on this?
1106  should we call it here or after we have written all of the files?
1107  have timeout if call is blocking */
1108  signer_command = NULL;
1109  StrAppend(&signer_command, SIGNER_CLI_UPDATE);
1110  StrAppend(&signer_command, " ");
1111  StrAppend(&signer_command, zone_name);
1112 
1113  status = system(signer_command);
1114  if (status != 0)
1115  {
1116  log_msg(NULL, LOG_ERR, "Could not call signer engine");
1117  log_msg(NULL, LOG_INFO, "Will continue: call '%s' to manually update the zone", signer_command);
1118  *signer_flag = 0;
1119  }
1120  else {
1121  log_msg(NULL, LOG_INFO, "Called signer engine: %s", signer_command);
1122  }
1123 
1124  StrFree(signer_command);
1125  }
1126  }
1127  else {
1128  log_msg(NULL, LOG_INFO, "No change to: %s", current_filename);
1129  if (remove(temp_filename) != 0)
1130  {
1131  log_msg(NULL, LOG_ERR, "Could not remove: %s", temp_filename);
1132  StrFree(old_filename);
1133  StrFree(temp_filename);
1134  return -1;
1135  }
1136  }
1137 
1138  /* If the DS set changed then log/do something about it */
1139  if (NewDS == 1) {
1140  log_msg(NULL, LOG_INFO, "DSChanged");
1141  status = NewDSSet(zone_id, zone_name, DSSubmitCmd, DSSubCKA_ID);
1142  }
1143 
1144  StrFree(old_filename);
1145  StrFree(temp_filename);
1146 
1147  return 0;
1148 }
1149 
1150 /*
1151  * CallBack to print key info in signerConfiguration
1152  */
1153 
1154 int commKeyConfig(void* context, KSM_KEYDATA* key_data)
1155 {
1156  FILE *file = (FILE *)context;
1157 
1158  fprintf(file, "\t\t\t<Key>\n");
1159  fprintf(file, "\t\t\t\t<Flags>%d</Flags>\n", key_data->keytype);
1160  fprintf(file, "\t\t\t\t<Algorithm>%d</Algorithm>\n", key_data->algorithm);
1161  fprintf(file, "\t\t\t\t<Locator>%s</Locator>\n", key_data->location);
1162 
1163  if (key_data->keytype == KSM_TYPE_KSK)
1164  {
1165  fprintf(file, "\t\t\t\t<KSK />\n");
1166  }
1167  if (key_data->keytype == KSM_TYPE_ZSK && key_data->state == KSM_STATE_ACTIVE)
1168  {
1169  fprintf(file, "\t\t\t\t<ZSK />\n");
1170  }
1171  if ((key_data->state > KSM_STATE_GENERATE && key_data->state < KSM_STATE_DEAD) || key_data->state == KSM_STATE_KEYPUBLISH)
1172  {
1173  fprintf(file, "\t\t\t\t<Publish />\n");
1174  }
1175  fprintf(file, "\t\t\t</Key>\n");
1176  fprintf(file, "\n");
1177 
1178  return 0;
1179 }
1180 
1181 /* allocateKeysToZone
1182  *
1183  * Description:
1184  * Allocates existing keys to zones
1185  *
1186  * Arguments:
1187  * policy
1188  * policy that the keys were created for
1189  * key_type
1190  * KSK or ZSK
1191  * zone_id
1192  * ID of zone in question
1193  * interval
1194  * time before next run
1195  * zone_name
1196  * just in case we need to log something
1197  * man_key_gen
1198  * lack of keys may be an issue for the user to fix
1199  * int rollover_scheme
1200  * KSK rollover scheme in use
1201  *
1202  * Returns:
1203  * int
1204  * Status return. 0=> Success, non-zero => error.
1205  * 1 == error with input
1206  * 2 == not enough keys to satisfy policy
1207  * 3 == database error
1208  -*/
1209 
1210 
1211 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)
1212 {
1213  int status = 0;
1214  int keys_needed = 0;
1215  int keys_in_queue = 0;
1216  int keys_pending_retirement = 0;
1217  int new_keys = 0;
1218  int key_pair_id = 0;
1219  int i = 0;
1220  DB_ID ignore = 0;
1221  KSM_PARCOLL collection; /* Parameters collection */
1222  char* datetime = DtParseDateTimeString("now");
1223 
1224  /* Check datetime in case it came back NULL */
1225  if (datetime == NULL) {
1226  log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
1227  return -1;
1228  }
1229 
1230  if (policy == NULL) {
1231  log_msg(NULL, LOG_ERR, "NULL policy sent to allocateKeysToZone");
1232  StrFree(datetime);
1233  return 1;
1234  }
1235 
1236  if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) {
1237  log_msg(NULL, LOG_ERR, "Unknown keytype: %i in allocateKeysToZone", key_type);
1238  StrFree(datetime);
1239  return 1;
1240  }
1241 
1242  /* Get list of parameters */
1243  status = KsmParameterCollection(&collection, policy->id);
1244  if (status != 0) {
1245  StrFree(datetime);
1246  return status;
1247  }
1248 
1249  /* Make sure that enough keys are allocated to this zone */
1250  /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */
1251  status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
1252  if (status != 0) {
1253  log_msg(NULL, LOG_ERR, "Could not predict key requirement for next interval for %s", zone_name);
1254  StrFree(datetime);
1255  return 3;
1256  }
1257 
1258  /* How many do we have ? TODO should this include the currently active key?*/
1259  status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id);
1260  if (status != 0) {
1261  log_msg(NULL, LOG_ERR, "Could not count current key numbers for zone %s", zone_name);
1262  StrFree(datetime);
1263  return 3;
1264  }
1265 
1266  /* or about to retire */
1267  status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval);
1268  if (status != 0) {
1269  log_msg(NULL, LOG_ERR, "Could not count keys which may retire before the next run (for zone %s)", zone_name);
1270  StrFree(datetime);
1271  return 3;
1272  }
1273 
1274  StrFree(datetime);
1275  new_keys = keys_needed - (keys_in_queue - keys_pending_retirement);
1276 
1277  /* 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); */
1278 
1279  /* Allocate keys */
1280  for (i=0 ; i < new_keys ; i++){
1281  key_pair_id = 0;
1282  if (key_type == KSM_TYPE_KSK) {
1283  status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
1284  if (status == -1 || key_pair_id == 0) {
1285  if (man_key_gen == 0) {
1286  log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
1287  log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
1288  }
1289  else {
1290  log_msg(NULL, LOG_ERR, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
1291  log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
1292  }
1293  return 2;
1294  }
1295  else if (status != 0) {
1296  log_msg(NULL, LOG_ERR, "Could not get an unallocated ksk for zone: %s", zone_name);
1297  return 3;
1298  }
1299  } else {
1300  status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
1301  if (status == -1 || key_pair_id == 0) {
1302  if (man_key_gen == 0) {
1303  log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
1304  log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
1305  }
1306  else {
1307  log_msg(NULL, LOG_ERR, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
1308  log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
1309  }
1310  return 2;
1311  }
1312  else if (status != 0) {
1313  log_msg(NULL, LOG_ERR, "Could not get an unallocated zsk for zone: %s", zone_name);
1314  return 3;
1315  }
1316  }
1317  if(key_pair_id > 0) {
1318  status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, NULL, &ignore);
1319  /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */
1320  } else {
1321  /* This shouldn't happen */
1322  log_msg(NULL, LOG_ERR, "KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name);
1323  return -1;
1324  }
1325 
1326  }
1327 
1328  return status;
1329 }
1330 
1331 /*
1332  * Read the conf.xml file, extract the location of the zonelist.
1333  */
1334 int read_zonelist_filename(const char* filename, char** zone_list_filename)
1335 {
1336  xmlTextReaderPtr reader = NULL;
1337  xmlDocPtr doc = NULL;
1338  xmlXPathContextPtr xpathCtx = NULL;
1339  xmlXPathObjectPtr xpathObj = NULL;
1340  int ret = 0; /* status of the XML parsing */
1341  char* temp_char = NULL;
1342  char* tag_name = NULL;
1343 
1344  xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile";
1345 
1346  /* Start reading the file; we will be looking for "Common" tags */
1347  reader = xmlNewTextReaderFilename(filename);
1348  if (reader != NULL) {
1349  ret = xmlTextReaderRead(reader);
1350  while (ret == 1) {
1351  tag_name = (char*) xmlTextReaderLocalName(reader);
1352  /* Found <Common> */
1353  if (strncmp(tag_name, "Common", 6) == 0
1354  && xmlTextReaderNodeType(reader) == 1) {
1355 
1356  /* Expand this node and get the rest of the info with XPath */
1357  xmlTextReaderExpand(reader);
1358  doc = xmlTextReaderCurrentDoc(reader);
1359  if (doc == NULL) {
1360  log_msg(NULL, LOG_ERR, "Error: can not read Common section of %s", filename);
1361  /* Don't return? try to parse the rest of the file? */
1362  ret = xmlTextReaderRead(reader);
1363  continue;
1364  }
1365 
1366  xpathCtx = xmlXPathNewContext(doc);
1367  if(xpathCtx == NULL) {
1368  log_msg(NULL, LOG_ERR, "Error: can not create XPath context for Common section");
1369  /* Don't return? try to parse the rest of the file? */
1370  ret = xmlTextReaderRead(reader);
1371  continue;
1372  }
1373 
1374  /* Evaluate xpath expression for ZoneListFile */
1375  xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx);
1376  if(xpathObj == NULL) {
1377  log_msg(NULL, LOG_ERR, "Error: unable to evaluate xpath expression: %s", zonelist_expr);
1378  /* Don't return? try to parse the rest of the file? */
1379  ret = xmlTextReaderRead(reader);
1380  continue;
1381  }
1382  *zone_list_filename = NULL;
1383  temp_char = (char *)xmlXPathCastToString(xpathObj);
1384  StrAppend(zone_list_filename, temp_char);
1385  StrFree(temp_char);
1386  xmlXPathFreeObject(xpathObj);
1387  log_msg(NULL, LOG_INFO, "zonelist filename set to %s.", *zone_list_filename);
1388  }
1389  /* Read the next line */
1390  ret = xmlTextReaderRead(reader);
1391  StrFree(tag_name);
1392  }
1393  xmlFreeTextReader(reader);
1394  if (ret != 0) {
1395  log_msg(NULL, LOG_ERR, "%s : failed to parse", filename);
1396  return(1);
1397  }
1398  } else {
1399  log_msg(NULL, LOG_ERR, "Unable to open %s", filename);
1400  return(1);
1401  }
1402  if (xpathCtx) {
1403  xmlXPathFreeContext(xpathCtx);
1404  }
1405  if (doc) {
1406  xmlFreeDoc(doc);
1407  }
1408 
1409  return 0;
1410 }
1411 
1412 /*+
1413  * do_purge - Purge dead Keys
1414  *
1415  *
1416  * Arguments:
1417  *
1418  * int interval
1419  * how long a key needs to have been dead for before we purge it
1420  *
1421  * int policy_id
1422  * ID of the policy
1423  *
1424  * Returns:
1425  * int
1426  * Status return. 0 on success.
1427  * other on fail
1428  */
1429 
1430 int do_purge(int interval, int policy_id)
1431 {
1432  char* sql = NULL; /* SQL query */
1433  char* sql1 = NULL; /* SQL query */
1434  char* sql2 = NULL; /* SQL query */
1435  char* sql3 = NULL; /* SQL query */
1436  int status = 0; /* Status return */
1437  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
1438  DB_RESULT result; /* Result of the query */
1439  DB_ROW row = NULL; /* Row data */
1440 
1441  char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */
1442 
1443  int temp_id = -1; /* place to store the key id returned */
1444  char* temp_loc = NULL; /* place to store location returned */
1445  int count = 0; /* How many keys don't match the purge */
1446 
1447  char *rightnow;
1448 
1449  /* Key information */
1450  hsm_key_t *key = NULL;
1451 
1452  log_msg(NULL, LOG_DEBUG, "Purging keys...");
1453 
1454  rightnow = DtParseDateTimeString("now");
1455 
1456  /* Check datetime in case it came back NULL */
1457  if (rightnow == NULL) {
1458  log_msg(NULL, LOG_ERR, "Couldn't turn \"now\" into a date, quitting...");
1459  exit(1);
1460  }
1461 
1462  /* Select rows */
1463  StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
1464 
1465  if (policy_id != -1) {
1466  StrAppend(&sql, "and policy_id = ");
1467  snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
1468  StrAppend(&sql, stringval);
1469  }
1470 
1471  DusEnd(&sql);
1472 
1473  status = DbExecuteSql(DbHandle(), sql, &result);
1474 
1475  if (status == 0) {
1476  status = DbFetchRow(result, &row);
1477  while (status == 0) {
1478  /* Got a row, check it */
1479  DbInt(row, 0, &temp_id);
1480  DbString(row, 1, &temp_loc);
1481 
1482  sql1 = DqsCountInit("dnsseckeys");
1483  DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
1484  DdsConditionInt(&sql1, "(state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
1485 
1486  status = DbDateDiff(rightnow, interval, -1, buffer, KSM_SQL_SIZE);
1487  if (status != 0) {
1488  log_msg(NULL, LOG_ERR, "DbDateDiff failed\n");
1489  DbStringFree(temp_loc);
1490  DbFreeRow(row);
1491  StrFree(rightnow);
1492  DusFree(sql);
1493  DqsFree(sql1);
1494  return status;
1495  }
1496 
1497  StrAppend(&sql1, " or state = 6 and DEAD > ");
1498  StrAppend(&sql1, buffer);
1499  StrAppend(&sql1, ")");
1500  DqsEnd(&sql1);
1501 
1502  status = DbIntQuery(DbHandle(), &count, sql1);
1503  DqsFree(sql1);
1504 
1505  if (status != 0) {
1506  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1507  DbStringFree(temp_loc);
1508  DbFreeRow(row);
1509  StrFree(rightnow);
1510  DusFree(sql);
1511  return status;
1512  }
1513 
1514  /* If the count is zero then there is no reason not to purge this key */
1515  if (count == 0) {
1516 
1517  /* Delete from dnsseckeys */
1518  sql2 = DdsInit("dnsseckeys");
1519  DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
1520  DdsEnd(&sql2);
1521 
1522  status = DbExecuteSqlNoResult(DbHandle(), sql2);
1523  DdsFree(sql2);
1524  if (status != 0)
1525  {
1526  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1527  DbStringFree(temp_loc);
1528  DbFreeRow(row);
1529  StrFree(rightnow);
1530  DusFree(sql);
1531  return status;
1532  }
1533 
1534  /* Delete from keypairs */
1535  sql3 = DdsInit("keypairs");
1536  DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
1537  DdsEnd(&sql);
1538 
1539  status = DbExecuteSqlNoResult(DbHandle(), sql3);
1540  DdsFree(sql3);
1541  if (status != 0)
1542  {
1543  log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
1544  DbStringFree(temp_loc);
1545  DbFreeRow(row);
1546  StrFree(rightnow);
1547  DusFree(sql);
1548  return status;
1549  }
1550 
1551  /* Delete from the HSM */
1552  key = hsm_find_key_by_id(NULL, temp_loc);
1553 
1554  if (!key) {
1555  log_msg(NULL, LOG_ERR, "Key not found: %s\n", temp_loc);
1556  DbStringFree(temp_loc);
1557  DbFreeRow(row);
1558  StrFree(rightnow);
1559  DusFree(sql);
1560  return -1;
1561  }
1562 
1563  status = hsm_remove_key(NULL, key);
1564 
1565  hsm_key_free(key);
1566 
1567  if (!status) {
1568  log_msg(NULL, LOG_INFO, "Key remove successful: %s\n", temp_loc);
1569  } else {
1570  log_msg(NULL, LOG_ERR, "Key remove failed: %s\n", temp_loc);
1571  DbStringFree(temp_loc);
1572  DbFreeRow(row);
1573  StrFree(rightnow);
1574  DusFree(sql);
1575  return -1;
1576  }
1577  }
1578 
1579  /* NEXT! */
1580  status = DbFetchRow(result, &row);
1581  }
1582 
1583  /* Convert EOF status to success */
1584 
1585  if (status == -1) {
1586  status = 0;
1587  }
1588 
1589  DbFreeResult(result);
1590  }
1591 
1592  DusFree(sql);
1593  DbFreeRow(row);
1594 
1595  DbStringFree(temp_loc);
1596  StrFree(rightnow);
1597 
1598  return status;
1599 }
1600 
1601 int NewDSSet(int zone_id, const char* zone_name, const char* DSSubmitCmd, int DSSubCKA_ID) {
1602  int where = 0; /* for the SELECT statement */
1603  char* sql = NULL; /* SQL statement (when verifying) */
1604  char* sql2 = NULL; /* SQL statement (if getting DS) */
1605  int status = 0; /* Status return */
1606  int count = 0; /* How many keys fit our select? */
1607  int i = 0; /* A counter */
1608  int j = 0; /* Another counter */
1609  char* insql = NULL; /* SQL "IN" clause */
1610  int* keyids; /* List of IDs of keys to promote */
1611  DB_RESULT result; /* List result set */
1612  KSM_KEYDATA data; /* Data for this key */
1613  size_t nchar; /* Number of characters written */
1614  char buffer[256]; /* For constructing part of the command */
1615  char* count_clause = NULL;
1616  char* where_clause = NULL;
1617  int id = -1; /* ID of key which will retire */
1618  int active_count = -1; /* Number of currently active keys */
1619 
1620  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
1621  DB_RESULT result3; /* Result of DS query */
1622  KSM_KEYDATA data3; /* DS information */
1623  char* ds_buffer = NULL; /* Contents of DS records */
1624  char* ds_seen_buffer = NULL; /* Which keys have we promoted */
1625  char* temp_char = NULL; /* Contents of DS records */
1626 
1627  /* To find the ttl of the DS */
1628  int policy_id = -1;
1629  int rrttl = -1;
1630  int param_id = -1; /* unused */
1631 
1632  /* Key information */
1633  hsm_key_t *key = NULL;
1634  ldns_rr *dnskey_rr = NULL;
1635  hsm_sign_params_t *sign_params = NULL;
1636 
1637  FILE *fp;
1638  int bytes_written = -1;
1639 
1640  struct stat stat_ret; /* we will test the DSSubmitCmd */
1641 
1642  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d, %d, %d, %d, %d)",
1646  if (nchar >= sizeof(buffer)) {
1647  status = -1;
1648  return status;
1649  }
1650 
1651  /* Find the oldest active key, this is the one which will be retired
1652  NOTE; this may not match any keys */
1653 
1654  count_clause = DqsCountInit("KEYDATA_VIEW");
1655  DqsConditionInt(&count_clause, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1656  DqsConditionInt(&count_clause, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
1657  if (zone_id != -1) {
1658  DqsConditionInt(&count_clause, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1659  }
1660 
1661  status = DbIntQuery(DbHandle(), &active_count, count_clause);
1662  StrFree(count_clause);
1663  if (status != 0)
1664  {
1665  log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
1666  return status;
1667  }
1668 
1669  if (active_count > 0) {
1670 
1671  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
1672  StrAppend(&where_clause, "select id from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
1673  StrAppend(&where_clause, stringval);
1674  StrAppend(&where_clause, " and retire = (select min(retire) from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
1675  StrAppend(&where_clause, stringval);
1676  StrAppend(&where_clause, ")");
1677 
1678  /* Execute query and free up the query string */
1679  status = DbIntQuery(DbHandle(), &id, where_clause);
1680  StrFree(where_clause);
1681  if (status != 0)
1682  {
1683  log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
1684  return status;
1685  }
1686  }
1687 
1688  /* First up we need to count how many DSs we will have */
1689  where = 0;
1690  sql = DqsCountInit("KEYDATA_VIEW");
1691  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1692  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
1693  if (zone_id != -1) {
1694  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1695  }
1696  if (id != -1) {
1697  DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
1698  }
1699  DqsEnd(&sql);
1700 
1701  status = DbIntQuery(DbHandle(), &count, sql);
1702  DqsFree(sql);
1703 
1704  if (status != 0) {
1705  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1706  return status;
1707  }
1708 
1709  if (count == 0) {
1710  /* No KSKs in zone? */
1711  return status;
1712  }
1713 
1714  /* Allocate space for the list of key IDs */
1715  keyids = MemMalloc(count * sizeof(int));
1716 
1717  /* Get the list of IDs */
1718 
1719  where = 0;
1720  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1721  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
1722  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
1723  if (zone_id != -1) {
1724  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
1725  }
1726  if (id != -1) {
1727  DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
1728  }
1729  DqsEnd(&sql);
1730 
1731  status = KsmKeyInitSql(&result, sql);
1732  DqsFree(sql);
1733 
1734  if (status == 0) {
1735  while (status == 0) {
1736  status = KsmKey(result, &data);
1737  if (status == 0) {
1738  keyids[i] = data.keypair_id;
1739  i++;
1740  }
1741  }
1742 
1743  /* Convert EOF status to success */
1744 
1745  if (status == -1) {
1746  status = 0;
1747  } else {
1748  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1749  StrFree(keyids);
1750  return status;
1751  }
1752 
1753  KsmKeyEnd(result);
1754 
1755  } else {
1756  /*status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));*/
1757  StrFree(keyids);
1758  return status;
1759  }
1760 
1761  /*
1762  * Now construct the "IN" statement listing the IDs of the keys we
1763  * are planning to change the state of.
1764  */
1765 
1766  StrAppend(&insql, "(");
1767  for (j = 0; j < i; ++j) {
1768  if (j != 0) {
1769  StrAppend(&insql, ",");
1770  }
1771  snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
1772  StrAppend(&insql, buffer);
1773  }
1774  StrAppend(&insql, ")");
1775 
1776  StrFree(keyids);
1777 
1778  /* Indicate that the DS record should now be submitted */
1779  sql2 = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1780  DqsConditionKeyword(&sql2, "ID", DQS_COMPARE_IN, insql, 0);
1781  DqsConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
1782  DqsEnd(&sql2);
1783 
1784  log_msg(NULL, LOG_INFO, "DS Record set has changed, the current set looks like:");
1785 
1786  status = KsmKeyInitSql(&result3, sql2);
1787  DqsFree(sql2);
1788  if (status == 0) {
1789  status = KsmKey(result3, &data3);
1790  while (status == 0) {
1791 
1792  /* Code to output the DNSKEY record (stolen from hsmutil) */
1793  key = hsm_find_key_by_id(NULL, data3.location);
1794 
1795  if (!key) {
1796  log_msg(NULL, LOG_ERR, "Key %s in DB but not repository.", data3.location);
1797  StrFree(insql);
1798  return status;
1799  }
1800 
1801  StrAppend(&ds_seen_buffer, ", ");
1802  StrAppend(&ds_seen_buffer, data3.location);
1803 
1804  sign_params = hsm_sign_params_new();
1805  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone_name);
1806  sign_params->algorithm = data3.algorithm;
1807  sign_params->flags = LDNS_KEY_ZONE_KEY;
1808  sign_params->flags += LDNS_KEY_SEP_KEY;
1809  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
1810 
1811  /* Set TTL if we can find it; else leave it as the default */
1812  /* We need a policy id */
1813  status = KsmPolicyIdFromZoneId(zone_id, &policy_id);
1814  if (status == 0) {
1815 
1816  /* Use this to get the TTL parameter value */
1817  status = KsmParameterValue(KSM_PAR_KSKTTL_STRING, KSM_PAR_KSKTTL_CAT, &rrttl, policy_id, &param_id);
1818  if (status == 0) {
1819  ldns_rr_set_ttl(dnskey_rr, rrttl);
1820  }
1821  }
1822 
1823  temp_char = ldns_rr2str(dnskey_rr);
1824  ldns_rr_free(dnskey_rr);
1825 
1826  /* Replace tab with white-space */
1827  for (i = 0; temp_char[i]; ++i) {
1828  if (temp_char[i] == '\t') {
1829  temp_char[i] = ' ';
1830  }
1831  }
1832  log_msg(NULL, LOG_INFO, "%s", temp_char);
1833 
1834  /* We need to strip off trailing comments before we send
1835  to any clients that might be listening */
1836  for (i = 0; temp_char[i]; ++i) {
1837  if (temp_char[i] == ';') {
1838  temp_char[i] = '\n';
1839  temp_char[i+1] = '\0';
1840  break;
1841  }
1842  }
1843  StrAppend(&ds_buffer, temp_char);
1844 
1845  /* Add the CKA_ID if asked */
1846  if (DSSubCKA_ID) {
1847  StrAppend(&ds_buffer, "; {cka_id = ");
1848  StrAppend(&ds_buffer, data3.location);
1849  StrAppend(&ds_buffer, "}");
1850  }
1851 
1852  StrFree(temp_char);
1853 
1854 /* StrAppend(&ds_buffer, "\n;KSK DS record (SHA1):\n");
1855  ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1);
1856  temp_char = ldns_rr2str(ds_sha1_rr);
1857  StrAppend(&ds_buffer, temp_char);
1858  StrFree(temp_char);
1859 
1860  StrAppend(&ds_buffer, "\n;KSK DS record (SHA256):\n");
1861  ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256);
1862  temp_char = ldns_rr2str(ds_sha256_rr);
1863  StrAppend(&ds_buffer, temp_char);
1864  StrFree(temp_char);
1865 */
1866 
1867  hsm_sign_params_free(sign_params);
1868  hsm_key_free(key);
1869  status = KsmKey(result3, &data3);
1870  }
1871  /* Convert EOF status to success */
1872  if (status == -1) {
1873  status = 0;
1874  }
1875 
1876  KsmKeyEnd(result3);
1877  }
1878 
1879  if (DSSubmitCmd[0] != '\0') {
1880  /* First check that the command exists */
1881  if (stat(DSSubmitCmd, &stat_ret) != 0) {
1882  log_msg(NULL, LOG_WARNING, "Cannot stat file %s: %s", DSSubmitCmd, strerror(errno));
1883  }
1884  /* Then see if it is a regular file, then if usr, grp or all have execute set */
1885  else if (S_ISREG(stat_ret.st_mode) && !(stat_ret.st_mode & S_IXUSR || stat_ret.st_mode & S_IXGRP || stat_ret.st_mode & S_IXOTH)) {
1886  log_msg(NULL, LOG_WARNING, "File %s is not executable", DSSubmitCmd);
1887  }
1888  else {
1889 
1890  /* send records to the configured command */
1891  fp = popen(DSSubmitCmd, "w");
1892  if (fp == NULL) {
1893  log_msg(NULL, LOG_ERR, "Failed to run command: %s: %s", DSSubmitCmd, strerror(errno));
1894  StrFree(insql);
1895  return -1;
1896  }
1897  bytes_written = fprintf(fp, "%s", ds_buffer);
1898  if (bytes_written < 0) {
1899  log_msg(NULL, LOG_ERR, "Failed to write to %s: %s", DSSubmitCmd, strerror(errno));
1900  return -1;
1901  }
1902 
1903  if (pclose(fp) == -1) {
1904  log_msg(NULL, LOG_ERR, "Failed to close %s: %s", DSSubmitCmd, strerror(errno));
1905  StrFree(ds_buffer);
1906  StrFree(ds_seen_buffer);
1907  StrFree(insql);
1908  return -1;
1909  }
1910  }
1911  }
1912 
1913  StrFree(ds_buffer);
1914 
1915  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);
1916 
1917  StrFree(ds_seen_buffer);
1918 
1919  StrFree(insql);
1920 
1921  return status;
1922 }
1923 
1925 {
1926  int result = 0;
1927  char *hsm_error_message = NULL;
1928 
1929  result = hsm_check_context(*ctx);
1930 
1931  /* If we didn't get HSM_OK then close and reopen HSM */
1932  if (result != HSM_OK) {
1933 
1934  if (*ctx) {
1935  hsm_destroy_context(*ctx);
1936  }
1937 
1938  result = hsm_close();
1939 
1940  if (config->configfile != NULL) {
1941  result = hsm_open(config->configfile, hsm_check_pin);
1942  } else {
1943  result = hsm_open(OPENDNSSEC_CONFIG_FILE, hsm_check_pin);
1944  }
1945  if (result) {
1946  hsm_error_message = hsm_get_error(*ctx);
1947  if (hsm_error_message) {
1948  log_msg(config, LOG_ERR, hsm_error_message);
1949  free(hsm_error_message);
1950  } else {
1951  /* decode the error code ourselves
1952  TODO find if there is a better way to do this (and can all
1953  of these be returned? are there others?) */
1954  switch (result) {
1955  case HSM_ERROR:
1956  log_msg(config, LOG_ERR, "hsm_open() result: HSM error");
1957  break;
1958  case HSM_PIN_INCORRECT:
1959  log_msg(config, LOG_ERR, "hsm_open() result: incorrect PIN");
1960  break;
1961  case HSM_CONFIG_FILE_ERROR:
1962  log_msg(config, LOG_ERR, "hsm_open() result: config file error");
1963  break;
1964  case HSM_REPOSITORY_NOT_FOUND:
1965  log_msg(config, LOG_ERR, "hsm_open() result: repository not found");
1966  break;
1967  case HSM_NO_REPOSITORIES:
1968  log_msg(config, LOG_ERR, "hsm_open() result: no repositories");
1969  break;
1970  default:
1971  log_msg(config, LOG_ERR, "hsm_open() result: %d", result);
1972  }
1973  }
1974  unlink(config->pidfile);
1975  exit(1);
1976  }
1977  log_msg(config, LOG_INFO, "HSM reopened successfully.");
1978  *ctx = hsm_create_context();
1979  } else {
1980  log_msg(config, LOG_INFO, "HSM connection open.");
1981  }
1982 
1983 }