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