OpenDNSSEC-enforcer  1.4.3
ksmutil.c
Go to the documentation of this file.
1 /*
2  * $Id: ksmutil.c 7416 2013-11-21 08:34:02Z matthijs $
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 #define _GNU_SOURCE
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <limits.h>
36 
37 #include "config.h"
38 
39 #include <getopt.h>
40 #include <string.h>
41 #include <syslog.h>
42 #include <sys/stat.h>
43 #include <pwd.h>
44 #include <grp.h>
45 
46 #include <ksm/ksmutil.h>
47 #include <ksm/ksm.h>
48 #include <ksm/database.h>
49 #include "ksm/database_statement.h"
50 #include "ksm/db_fields.h"
51 #include <ksm/datetime.h>
52 #include <ksm/string_util.h>
53 #include <ksm/string_util2.h>
54 #include "ksm/kmemsg.h"
55 #include "ksm/kmedef.h"
56 #include "ksm/dbsmsg.h"
57 #include "ksm/dbsdef.h"
58 #include "ksm/message.h"
59 
60 #include <libhsm.h>
61 #include <libhsmdns.h>
62 #include <ldns/ldns.h>
63 
64 #include <libxml/tree.h>
65 #include <libxml/parser.h>
66 #include <libxml/xpointer.h>
67 #include <libxml/xpath.h>
68 #include <libxml/xpathInternals.h>
69 #include <libxml/relaxng.h>
70 #include <libxml/xmlreader.h>
71 #include <libxml/xmlsave.h>
72 
73 #define MAX(a, b) ((a) > (b) ? (a) : (b))
74 
75 /* Some value type flags */
76 #define INT_TYPE 0
77 #define DURATION_TYPE 1
78 #define BOOL_TYPE 2
79 #define REPO_TYPE 3
80 #define SERIAL_TYPE 4
81 #define ROLLOVER_TYPE 5
82 #define INT_TYPE_NO_FREE 6
83 
84 #ifndef MAXPATHLEN
85 # define MAXPATHLEN 4096
86 #endif
87 
88 /* We write one log message to syslog */
89 #ifdef LOG_DAEMON
90 #define DEFAULT_LOG_FACILITY LOG_DAEMON
91 #else
92 #define DEFAULT_LOG_FACILITY LOG_USER
93 #endif /* LOG_DAEMON */
94 
95 extern char *optarg;
96 extern int optind;
97 const char *progname = NULL;
98 char *config = (char *) OPENDNSSEC_CONFIG_FILE;
99 
100 char *o_keystate = NULL;
101 char *o_algo = NULL;
102 char *o_input = NULL;
103 char *o_in_type = NULL;
104 char *o_cka_id = NULL;
105 char *o_size = NULL;
106 char *o_interval = NULL;
107 char *o_output = NULL;
108 char *o_out_type = NULL;
109 char *o_policy = NULL;
110 char *o_repository = NULL;
111 char *o_signerconf = NULL;
112 char *o_keytype = NULL;
113 char *o_time = NULL;
114 char *o_retire = NULL;
115 char *o_zone = NULL;
116 char *o_zonetotal = NULL;
117 char *o_keytag = NULL;
118 static int all_flag = 0;
119 static int auto_accept_flag = 0;
120 static int ds_flag = 0;
121 static int retire_flag = 1;
122 static int notify_flag = 1;
123 static int verbose_flag = 0;
124 static int xml_flag = 1;
125 static int td_flag = 0;
126 static int force_flag = 0;
127 static int hsm_flag = 1;
128 static int check_repository_flag = 0;
129 
130 static int restart_enforcerd(void);
131 
137 #if defined(HAVE_SYSLOG_R) && defined(HAVE_OPENLOG_R) && defined(HAVE_CLOSELOG_R)
138 struct syslog_data sdata = SYSLOG_DATA_INIT;
139 #else
140 #undef HAVE_SYSLOG_R
141 #undef HAVE_OPENLOG_R
142 #undef HAVE_CLOSELOG_R
143 #endif
144 
145  void
147 {
148  fprintf(stderr,
149  " help\n"
150  " --version aka -V\n");
151 }
152 
153  void
155 {
156  fprintf(stderr,
157  " setup\n"
158  "\tImport config into a database (deletes current contents)\n");
159 }
160 
161  void
163 {
164  fprintf(stderr,
165  " start|stop|notify\n"
166  "\tStart, stop or SIGHUP the ods-enforcerd\n");
167 }
168 
169  void
171 {
172  fprintf(stderr,
173  " update kasp\n"
174  " update zonelist\n"
175  " update conf\n"
176  " update all\n"
177  "\tUpdate database from config\n");
178 }
179 
180  void
182 {
183  fprintf(stderr,
184  " zone add\n"
185  "\t--zone <zone> aka -z\n"
186  "\t[--policy <policy>] aka -p\n"
187  "\t[--signerconf <signerconf.xml>] aka -s\n"
188  "\t[--input <input>] aka -i\n"
189  "\t[--in-type <input type>] aka -j\n"
190  "\t[--output <output>] aka -o\n"
191  "\t[--out-type <output type>] aka -q\n"
192  "\t[--no-xml] aka -m\n");
193 }
194 
195  void
197 {
198  fprintf(stderr,
199  " zone delete\n"
200  "\t--zone <zone> | --all aka -z / -a\n"
201  "\t[--no-xml] aka -m\n");
202 }
203 
204  void
206 {
207  fprintf(stderr,
208  " zone list\n");
209 }
210 
211  void
213 {
214  fprintf(stderr,
215  "usage: %s [-c <config> | --config <config>] zone \n\n",
216  progname);
217  usage_zoneadd ();
218  usage_zonedel ();
219  usage_zonelist ();
220 }
221 
222  void
224 {
225  fprintf(stderr,
226  " repository list\n");
227 }
228 
229  void
231 {
232  fprintf(stderr,
233  " policy export\n"
234  "\t--policy [policy_name] | --all aka -p / -a\n");
235 }
236 
237  void
239 {
240  fprintf(stderr,
241  " policy import\n");
242 }
243 
244  void
246 {
247  fprintf(stderr,
248  " policy list\n");
249 }
250 
251  void
253 {
254  fprintf(stderr,
255  " policy purge\n");
256 }
257 
258  void
260 {
261  fprintf(stderr,
262  "usage: %s [-c <config> | --config <config>] \n\n",
263  progname);
266  usage_policylist ();
268 }
269 
270  void
272 {
273  fprintf(stderr,
274  " key list\n"
275  "\t[--verbose]\n"
276  "\t--zone <zone> | --all aka -z / -a\n"
277 #if 0
278  "\t(will appear soon:\n"
279  "\t[--keystate <state>] aka -e\n"
280  "\t[--keytype <type>] aka -t\n"
281  "\t[--ds] aka -d)\n"
282 #endif
283  );
284 }
285 
286  void
288 {
289  fprintf(stderr,
290  " key export\n"
291  "\t--zone <zone> | --all aka -z / -a\n"
292  "\t[--keystate <state>] aka -e\n"
293  "\t[--keytype <type>] aka -t\n"
294  "\t[--ds] aka -d\n");
295 }
296 
297  void
299 {
300  fprintf(stderr,
301  " key import\n"
302  "\t--cka_id <CKA_ID> aka -k\n"
303  "\t--repository <repository> aka -r\n"
304  "\t--zone <zone> aka -z\n"
305  "\t--bits <size> aka -b\n"
306  "\t--algorithm <algorithm> aka -g\n"
307  "\t--keystate <state> aka -e\n"
308  "\t--keytype <type> aka -t\n"
309  "\t--time <time> aka -w\n"
310  "\t[--check-repository] aka -C\n"
311  "\t[--retire <retire>] aka -y\n");
312 }
313 
314  void
316 {
317  fprintf(stderr,
318  " key rollover\n"
319  "\t--zone zone aka -z\n"
320  "\t--keytype <type> | --all aka -t / -a\n"
321  " key rollover\n"
322  "\t--policy policy aka -p\n"
323  "\t--keytype <type> | --all aka -t / -a\n");
324 }
325 
326  void
328 {
329  fprintf(stderr,
330  " key purge\n"
331  "\t--zone <zone> aka -z\n"
332  " key purge\n"
333  "\t--policy <policy> aka -p\n");
334 }
335 
336  void
338 {
339  fprintf(stderr,
340  " key generate\n"
341  "\t--policy <policy> aka -p\n"
342  "\t--interval <interval> aka -n\n"
343  "\t[--zonetotal <total no. of zones>] aka -Z\n"
344  "\t--auto-accept aka -A\n");
345 }
346 
347  void
349 {
350  fprintf(stderr,
351  " key ksk-retire\n"
352  "\t--zone <zone> aka -z\n"
353  "\t--keytag <keytag> | --cka_id <CKA_ID> aka -x / -k\n");
354 }
355 
356  void
358 {
359  fprintf(stderr,
360  " key ds-seen\n"
361  /*"\t--zone <zone> (or --all) aka -z\n"*/
362  "\t--zone <zone> aka -z\n"
363  "\t--keytag <keytag> | --cka_id <CKA_ID> aka -x / -k\n"
364  "\t[--no-notify|-l] aka -l\n"
365  "\t[--no-retire|-f] aka -f\n");
366 }
367 
368  void
370 {
371  fprintf(stderr,
372  " key delete\n"
373  "\t--cka_id <CKA_ID> aka -k\n"
374  "\t--no-hsm\n");
375 }
376 
377  void
379 {
380  fprintf(stderr,
381  "usage: %s [-c <config> | --config <config>] \n\n",
382  progname);
383  usage_keylist ();
384  usage_keyexport ();
385  usage_keyimport ();
386  usage_keyroll ();
387  usage_keypurge ();
388  usage_keygen ();
390  usage_keydsseen ();
391  usage_keydelete ();
392 }
393 
394  void
396 {
397  fprintf(stderr,
398  " backup prepare\n"
399  "\t--repository <repository> aka -r\n"
400  " backup commit\n"
401  "\t--repository <repository> aka -r\n"
402  " backup rollback\n"
403  "\t--repository <repository> aka -r\n"
404  " backup list\n"
405  "\t--repository <repository> aka -r\n"
406  " backup done\n"
407  "\t--repository <repository> aka -r\n"
408  "\t--force\n"
409  "\t[NOTE: backup done is deprecated]\n");
410 }
411 
412  void
414 {
415  fprintf(stderr,
416  " rollover list\n"
417  "\t[--zone <zone>]\n");
418 }
419 
420  void
422 {
423  fprintf(stderr,
424  " database backup\n"
425  "\t[--output <output>] aka -o\n");
426 }
427 
428  void
430 {
431  fprintf(stderr,
432  " zonelist export\n"
433  " zonelist import\n");
434 }
435 
436  void
438 {
439  fprintf(stderr,
440  "usage: %s [-c <config> | --config <config>] command [options]\n\n",
441  progname);
442 
443  usage_general ();
444  usage_setup ();
445  usage_control ();
446  usage_update ();
447  usage_zoneadd ();
448  usage_zonedel ();
449  usage_zonelist ();
450  usage_repo ();
453  usage_policylist ();
455  usage_keylist ();
456  usage_keyexport ();
457  usage_keyimport ();
458  usage_keyroll ();
459  usage_keypurge ();
460  usage_keygen ();
462  usage_keydsseen ();
463  usage_backup ();
464  usage_rollover ();
465  usage_database ();
466  usage_zonelist2 ();
467 
468 }
469 
470  void
472 {
473  fprintf(stderr,
474  "\n\tAllowed date/time strings are of the form:\n"
475 
476  "\tYYYYMMDD[HH[MM[SS]]] (all numeric)\n"
477  "\n"
478  "\tor D-MMM-YYYY[:| ]HH[:MM[:SS]] (alphabetic month)\n"
479  "\tor DD-MMM-YYYY[:| ]HH[:MM[:SS]] (alphabetic month)\n"
480  "\tor YYYY-MMM-DD[:| ]HH[:MM[:SS]] (alphabetic month)\n"
481  "\n"
482  "\tD-MM-YYYY[:| ]HH[:MM[:SS]] (numeric month)\n"
483  "\tDD-MM-YYYY[:| ]HH[:MM[:SS]] (numeric month)\n"
484  "\tor YYYY-MM-DD[:| ]HH[:MM[:SS]] (numeric month)\n"
485  "\n"
486  "\t... and the distinction between them is given by the location of the\n"
487  "\thyphens.\n");
488 }
489 
490 void
492 {
493  fprintf(stderr,
494  "key states: GENERATE|PUBLISH|READY|ACTIVE|RETIRE|DEAD\n");
495 }
496 
497 void
499 {
500  fprintf(stderr,
501  "key types: KSK|ZSK\n");
502 }
503 
504 /*
505  * Check if the file exists.
506  * @param filename: name of file to be checked.
507  * @return: (int) 1 if file exist, 0 otherwise.
508  *
509  */
510 static int
511 exist_file(const char* filename) {
512  int status = 0;
513  FILE *file = fopen(filename, "r");
514  if(file != NULL){
515  fclose(file);
516  status = 1;
517  }
518  return status;
519 }
520 
521 /*
522  * Do initial import of config files into database
523  */
524 int
526 {
527  DB_HANDLE dbhandle;
528  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
529  char* zone_list_filename; /* Extracted from conf.xml */
530  char* kasp_filename; /* Extracted from conf.xml */
531  int status = 0;
532 
533  /* Database connection details */
534  char *dbschema = NULL;
535  char *host = NULL;
536  char *port = NULL;
537  char *user = NULL;
538  char *password = NULL;
539 
540  char quoted_user[KSM_NAME_LENGTH];
541  char quoted_password[KSM_NAME_LENGTH];
542 
543  char* setup_command = NULL;
544  char* lock_filename = NULL;
545 
546  int user_certain;
547  printf("*WARNING* This will erase all data in the database; are you sure? [y/N] ");
548 
549  user_certain = getchar();
550  if (user_certain != 'y' && user_certain != 'Y') {
551  printf("Okay, quitting...\n");
552  exit(0);
553  }
554 
555  /* Right then, they asked for it */
556 
557  /* Read the database details out of conf.xml */
558  status = get_db_details(&dbschema, &host, &port, &user, &password);
559  if (status != 0) {
560  StrFree(host);
561  StrFree(port);
562  StrFree(dbschema);
563  StrFree(user);
564  StrFree(password);
565  return(status);
566  }
567 
568  /* If we are in sqlite mode then take a lock out on a file to
569  prevent multiple access (not sure that we can be sure that sqlite is
570  safe for multiple processes to access). */
571  if (DbFlavour() == SQLITE_DB) {
572 
573  /* Make sure that nothing is happening to the DB */
574  StrAppend(&lock_filename, dbschema);
575  StrAppend(&lock_filename, ".our_lock");
576 
577  lock_fd = fopen(lock_filename, "w");
578  status = get_lite_lock(lock_filename, lock_fd);
579  if (status != 0) {
580  printf("Error getting db lock\n");
581  if (lock_fd != NULL) {
582  fclose(lock_fd);
583  }
584  StrFree(lock_filename);
585  StrFree(host);
586  StrFree(port);
587  StrFree(dbschema);
588  StrFree(user);
589  StrFree(password);
590  return(1);
591  }
592  StrFree(lock_filename);
593 
594  /* Run the setup script */
595  /* will look like: <SQL_BIN> <DBSCHEMA> < <SQL_SETUP> */
596  StrAppend(&setup_command, SQL_BIN);
597  StrAppend(&setup_command, " ");
598  StrAppend(&setup_command, dbschema);
599  StrAppend(&setup_command, " < ");
600  StrAppend(&setup_command, SQL_SETUP);
601 
602  if (system(setup_command) != 0)
603  {
604  printf("Could not call db setup command:\n\t%s\n", setup_command);
605  db_disconnect(lock_fd);
606  StrFree(host);
607  StrFree(port);
608  StrFree(dbschema);
609  StrFree(user);
610  StrFree(password);
611  StrFree(setup_command);
612  return(1);
613  }
614  StrFree(setup_command);
615 
616  /* If we are running as root then chmod the file so that the
617  final user/group can access it. */
618  if (fix_file_perms(dbschema) != 0)
619  {
620  printf("Couldn't fix permissions on file %s\n", dbschema);
621  printf("Will coninue with setup, but you may need to manually change ownership\n");
622  }
623  }
624  else {
625  /* MySQL setup */
626  /* will look like: <SQL_BIN> -u <USER> -h <HOST> -P <PORT> -p<PASSWORD> <DBSCHEMA> < <SQL_SETUP> */
627  /* Get a quoted version of the username */
628  status = ShellQuoteString(user, quoted_user, KSM_NAME_LENGTH);
629  if (status != 0) {
630  printf("Failed to connect to database, username too long.\n");
631  db_disconnect(lock_fd);
632  StrFree(host);
633  StrFree(port);
634  StrFree(dbschema);
635  StrFree(user);
636  StrFree(password);
637  return(1);
638  }
639 
640  /* Get a quoted version of the password */
641  if (password != NULL) {
642  status = ShellQuoteString(password, quoted_password, KSM_NAME_LENGTH);
643  if (status != 0) {
644  printf("Failed to connect to database, password too long.\n");
645  db_disconnect(lock_fd);
646  StrFree(host);
647  StrFree(port);
648  StrFree(dbschema);
649  StrFree(user);
650  StrFree(password);
651  return(1);
652  }
653  }
654 
655  StrAppend(&setup_command, SQL_BIN);
656  StrAppend(&setup_command, " -u '");
657  StrAppend(&setup_command, quoted_user);
658  StrAppend(&setup_command, "'");
659  if (host != NULL) {
660  StrAppend(&setup_command, " -h ");
661  StrAppend(&setup_command, host);
662  if (port != NULL) {
663  StrAppend(&setup_command, " -P ");
664  StrAppend(&setup_command, port);
665  }
666  }
667  if (password != NULL) {
668  StrAppend(&setup_command, " -p'");
669  StrAppend(&setup_command, quoted_password);
670  StrAppend(&setup_command, "'");
671  }
672  StrAppend(&setup_command, " ");
673  StrAppend(&setup_command, dbschema);
674  StrAppend(&setup_command, " < ");
675  StrAppend(&setup_command, SQL_SETUP);
676 
677  if (system(setup_command) != 0)
678  {
679  printf("Could not call db setup command:\n\t%s\n", setup_command);
680  StrFree(host);
681  StrFree(port);
682  StrFree(dbschema);
683  StrFree(user);
684  StrFree(password);
685  StrFree(setup_command);
686  return(1);
687  }
688  StrFree(setup_command);
689  }
690 
691  /* try to connect to the database */
692  status = DbConnect(&dbhandle, dbschema, host, password, user, port);
693  if (status != 0) {
694  printf("Failed to connect to database\n");
695  db_disconnect(lock_fd);
696  StrFree(host);
697  StrFree(port);
698  StrFree(dbschema);
699  StrFree(user);
700  StrFree(password);
701  return(1);
702  }
703 
704  /* Free these up early */
705  StrFree(host);
706  StrFree(port);
707  StrFree(dbschema);
708  StrFree(user);
709  StrFree(password);
710 
711  /*
712  * Now we will read the conf.xml file again, but this time we will not validate.
713  * Instead we just learn the location of the zonelist.xml and kasp.xml files.
714  */
715  status = read_filenames(&zone_list_filename, &kasp_filename);
716  if (status != 0) {
717  printf("Failed to read conf.xml\n");
718  db_disconnect(lock_fd);
719  return(1);
720  }
721 
722  /*
723  * Now we will read the conf.xml file again, but this time we will not validate.
724  * Instead we just extract the RepositoryList into the database
725  */
726  status = update_repositories();
727  if (status != 0) {
728  printf("Failed to update repositories\n");
729  db_disconnect(lock_fd);
730  StrFree(zone_list_filename);
731  StrFree(kasp_filename);
732  return(1);
733  }
734 
735  /*
736  * Now read the kasp.xml which should be in the same directory.
737  * This lists all of the policies.
738  */
739  status = update_policies(kasp_filename);
740  if (status != 0) {
741  printf("Failed to update policies\n");
742  printf("SETUP FAILED\n");
743  db_disconnect(lock_fd);
744  StrFree(zone_list_filename);
745  StrFree(kasp_filename);
746  return(1);
747  }
748 
749  StrFree(kasp_filename);
750 
751  /*
752  * Take the zonelist we learnt above and read it, updating or inserting zone
753  * records in the database as we go.
754  */
755  status = update_zones(zone_list_filename);
756  StrFree(zone_list_filename);
757  if (status != 0) {
758  printf("Failed to update zones\n");
759  db_disconnect(lock_fd);
760  return(1);
761  }
762 
763  /* Release sqlite lock file (if we have it) */
764  db_disconnect(lock_fd);
765 
766  DbDisconnect(dbhandle);
767 
768  return 0;
769 }
770 
771 /*
772  * Do incremental update of config files into database
773  *
774  * returns 0 on success
775  * 1 on error (and will have sent a message to stdout)
776  */
777  int
778 cmd_update (const char* qualifier)
779 {
780  DB_HANDLE dbhandle;
781  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
782  char* zone_list_filename = NULL; /* Extracted from conf.xml */
783  char* kasp_filename = NULL; /* Extracted from conf.xml */
784  int status = 0;
785  int done_something = 0;
786 
787  /* try to connect to the database */
788  status = db_connect(&dbhandle, &lock_fd, 1);
789  if (status != 0) {
790  printf("Failed to connect to database\n");
791  db_disconnect(lock_fd);
792  return(1);
793  }
794 
795  /*
796  * Now we will read the conf.xml file again, but this time we will not validate.
797  * Instead we just learn the location of the zonelist.xml and kasp.xml files.
798  */
799  if (strncmp(qualifier, "ZONELIST", 8) == 0 ||
800  strncmp(qualifier, "KASP", 4) == 0 ||
801  strncmp(qualifier, "ALL", 3) == 0) {
802  status = read_filenames(&zone_list_filename, &kasp_filename);
803  if (status != 0) {
804  printf("Failed to read conf.xml\n");
805  db_disconnect(lock_fd);
806  return(1);
807  }
808  }
809 
810  /*
811  * Read the conf.xml file yet again, but this time we will not validate.
812  * Instead we just extract the RepositoryList into the database.
813  */
814  if (strncmp(qualifier, "CONF", 4) == 0 ||
815  strncmp(qualifier, "ALL", 3) == 0) {
816  status = update_repositories();
817  if (status != 0) {
818  printf("Failed to update repositories\n");
819  db_disconnect(lock_fd);
820  if (strncmp(qualifier, "ALL", 3) == 0) {
821  StrFree(kasp_filename);
822  StrFree(zone_list_filename);
823  }
824  return(1);
825  }
826  done_something = 1;
827  }
828 
829  /*
830  * Now read the kasp.xml which should be in the same directory.
831  * This lists all of the policies.
832  */
833  if (strncmp(qualifier, "KASP", 4) == 0 ||
834  strncmp(qualifier, "ALL", 3) == 0) {
835  status = update_policies(kasp_filename);
836  if (status != 0) {
837  printf("Failed to update policies\n");
838  db_disconnect(lock_fd);
839  StrFree(kasp_filename);
840  StrFree(zone_list_filename);
841  return(1);
842  }
843  done_something = 1;
844  }
845 
846  /*
847  * Take the zonelist we learnt above and read it, updating or inserting zone
848  * records in the database as we go.
849  */
850  if (strncmp(qualifier, "ZONELIST", 8) == 0 ||
851  strncmp(qualifier, "ALL", 3) == 0) {
852  status = update_zones(zone_list_filename);
853  if (status != 0) {
854  printf("Failed to update zones\n");
855  db_disconnect(lock_fd);
856  StrFree(kasp_filename);
857  StrFree(zone_list_filename);
858  return(1);
859  }
860  done_something = 1;
861  }
862 
863  /*
864  * See if we did anything, otherwise log an error
865  */
866  if (done_something == 0) {
867  printf("Unrecognised command update %s. Please specify one of:\n", qualifier);
868  usage_update();
869  } else {
870  /* Need to poke the enforcer to wake it up */
871  if (restart_enforcerd() != 0)
872  {
873  fprintf(stderr, "Could not HUP ods-enforcerd\n");
874  }
875  }
876 
877  /* Release sqlite lock file (if we have it) */
878  db_disconnect(lock_fd);
879 
880  DbDisconnect(dbhandle);
881 
882  if (kasp_filename != NULL) {
883  StrFree(kasp_filename);
884  }
885  if (zone_list_filename != NULL) {
886  StrFree(zone_list_filename);
887  }
888 
889  return 0;
890 }
891 
892 /*
893  * Add a zone to the config and database.
894  *
895  * Use XMLwriter to update the zonelist.xml found in conf.xml.
896  * Then call update_zones to push these changes into the database.
897  * zonelist.xml will be backed up, as will the DB file if we are using sqlite
898  *
899  */
900  int
902 {
903  DB_HANDLE dbhandle;
904  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
905  char* zonelist_filename = NULL;
906  char* backup_filename = NULL;
907  /* The settings that we need for the zone */
908  char* sig_conf_name = NULL;
909  char* input_name = NULL;
910  char* output_name = NULL;
911  char* input_type = NULL;
912  char* output_type = NULL;
913  int policy_id = 0;
914  int new_zone; /* ignored */
915 
916  DB_RESULT result; /* Result of parameter query */
917  KSM_PARAMETER data; /* Parameter information */
918 
919  xmlDocPtr doc = NULL;
920 
921  int status = 0;
922 
923  char *path = getcwd(NULL, MAXPATHLEN);
924  if (path == NULL) {
925  printf("Couldn't malloc path: %s\n", strerror(errno));
926  exit(1);
927  }
928 
929  /* See what arguments we were passed (if any) otherwise set the defaults */
930  if (o_zone == NULL) {
931  printf("Please specify a zone with the --zone option\n");
932  usage_zone();
933  return(1);
934  }
935 
936  if (o_policy == NULL) {
937  o_policy = StrStrdup("default");
938  }
939  /*
940  * Set defaults and turn any relative paths into absolute
941  * (sort of, not the neatest output)
942  */
943  if (o_signerconf == NULL) {
944  StrAppend(&sig_conf_name, OPENDNSSEC_STATE_DIR);
945  StrAppend(&sig_conf_name, "/signconf/");
946  StrAppend(&sig_conf_name, o_zone);
947  StrAppend(&sig_conf_name, ".xml");
948  }
949  else if (*o_signerconf != '/') {
950  StrAppend(&sig_conf_name, path);
951  StrAppend(&sig_conf_name, "/");
952  StrAppend(&sig_conf_name, o_signerconf);
953  } else {
954  StrAppend(&sig_conf_name, o_signerconf);
955  }
956 
957  /* in the case of a 'DNS' adapter using a default path */
958  if (o_in_type == NULL) {
959  StrAppend(&input_type, "File");
960  } else {
961  StrAppend(&input_type, o_in_type);
962  }
963 
964  if (o_input == NULL) {
965  if(strcmp(input_type, "DNS")==0){
966  StrAppend(&input_name, OPENDNSSEC_CONFIG_DIR);
967  StrAppend(&input_name, "/addns.xml");
968  }else{
969  StrAppend(&input_name, OPENDNSSEC_STATE_DIR);
970  StrAppend(&input_name, "/unsigned/");
971  StrAppend(&input_name, o_zone);
972  }
973  }
974  else if (*o_input != '/') {
975  StrAppend(&input_name, path);
976  StrAppend(&input_name, "/");
977  StrAppend(&input_name, o_input);
978  } else {
979  StrAppend(&input_name, o_input);
980  }
981 
982  if (o_out_type == NULL) {
983  StrAppend(&output_type, "File");
984  } else {
985  StrAppend(&output_type, o_out_type);
986  }
987 
988  if (o_output == NULL) {
989  if(strcmp(output_type, "DNS") == 0){
990  StrAppend(&output_name, OPENDNSSEC_CONFIG_DIR);
991  StrAppend(&output_name, "/addns.xml");
992  }else{
993  StrAppend(&output_name, OPENDNSSEC_STATE_DIR);
994  StrAppend(&output_name, "/signed/");
995  StrAppend(&output_name, o_zone);
996  }
997 
998  }
999  else if (*o_output != '/') {
1000  StrAppend(&output_name, path);
1001  StrAppend(&output_name, "/");
1002  StrAppend(&output_name, o_output);
1003  } else {
1004  StrAppend(&output_name, o_output);
1005  }
1006 
1007 
1008  /* validate if the input file exist */
1009  if(!exist_file(input_name)){
1010  fprintf(stdout, "WARNING: The input file %s for zone %s does not currently exist. The zone will been added to the database anyway. \n",input_name, o_zone);
1011  }
1012 
1013  if(strcmp(output_type, "DNS") == 0 && !exist_file(output_name)){
1014  fprintf(stdout, "WARNING: The output file %s for zone %s does not currently exist. \n",output_name, o_zone);
1015  }
1016 
1017  free(path);
1018 
1019  /* Set zonelist from the conf.xml that we have got */
1020  status = read_zonelist_filename(&zonelist_filename);
1021  if (status != 0) {
1022  printf("couldn't read zonelist\n");
1023  StrFree(zonelist_filename);
1024  StrFree(sig_conf_name);
1025  StrFree(input_name);
1026  StrFree(output_name);
1027  StrFree(input_type);
1028  StrFree(output_type);
1029  return(1);
1030  }
1031 
1032  /*
1033  * Push this new zonelist into the database
1034  */
1035 
1036  /* try to connect to the database */
1037  status = db_connect(&dbhandle, &lock_fd, 1);
1038  if (status != 0) {
1039  printf("Failed to connect to database\n");
1040  db_disconnect(lock_fd);
1041  StrFree(zonelist_filename);
1042  StrFree(sig_conf_name);
1043  StrFree(input_name);
1044  StrFree(output_name);
1045  StrFree(input_type);
1046  StrFree(output_type);
1047  return(1);
1048  }
1049 
1050  /* Now stick this zone into the database */
1051  status = KsmPolicyIdFromName(o_policy, &policy_id);
1052  if (status != 0) {
1053  printf("Error, can't find policy : %s\n", o_policy);
1054  printf("Failed to update zones\n");
1055  db_disconnect(lock_fd);
1056  StrFree(zonelist_filename);
1057  StrFree(sig_conf_name);
1058  StrFree(input_name);
1059  StrFree(output_name);
1060  StrFree(input_type);
1061  StrFree(output_type);
1062  return(1);
1063  }
1064  status = KsmImportZone(o_zone, policy_id, 1, &new_zone, sig_conf_name, input_name, output_name, input_type, output_type);
1065  if (status != 0) {
1066  if (status == -2) {
1067  printf("Failed to Import zone %s; it already exists\n", o_zone);
1068  } else if (status == -3) {
1069  printf("Failed to Import zone %s; it already exists both with and without a trailing dot\n", o_zone);
1070  } else {
1071  printf("Failed to Import zone\n");
1072  }
1073  db_disconnect(lock_fd);
1074  StrFree(zonelist_filename);
1075  StrFree(sig_conf_name);
1076  StrFree(input_name);
1077  StrFree(output_name);
1078  StrFree(input_type);
1079  StrFree(output_type);
1080  return(1);
1081  }
1082 
1083  /* If need be (keys shared on policy) link existing keys to zone */
1084  /* First work out if the keys are shared on this policy */
1085  status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
1086  if (status != 0) {
1087  printf("Can't retrieve shared-keys parameter for policy\n");
1088  db_disconnect(lock_fd);
1089  StrFree(zonelist_filename);
1090  StrFree(sig_conf_name);
1091  StrFree(input_name);
1092  StrFree(output_name);
1093  StrFree(input_type);
1094  StrFree(output_type);
1095  return(1);
1096  }
1097  status = KsmParameter(result, &data);
1098  if (status != 0) {
1099  printf("Can't retrieve shared-keys parameter for policy\n");
1100  db_disconnect(lock_fd);
1101  StrFree(zonelist_filename);
1102  StrFree(sig_conf_name);
1103  StrFree(input_name);
1104  StrFree(output_name);
1105  StrFree(input_type);
1106  StrFree(output_type);
1107  return(1);
1108  }
1109  KsmParameterEnd(result);
1110 
1111  /* If the policy does not share keys then skip this */
1112  if (data.value == 1) {
1113  status = LinkKeys(o_zone, policy_id);
1114  if (status != 0) {
1115  printf("Failed to Link Keys to zone\n");
1116  /* Carry on and write the xml if the error code was 2
1117  (not enough keys) */
1118  if (status != 2) {
1119  db_disconnect(lock_fd);
1120  StrFree(zonelist_filename);
1121  StrFree(sig_conf_name);
1122  StrFree(input_name);
1123  StrFree(output_name);
1124  StrFree(input_type);
1125  StrFree(output_type);
1126  return(1);
1127  }
1128  }
1129  }
1130 
1131  /* Release sqlite lock file (if we have it) */
1132  db_disconnect(lock_fd);
1133  DbDisconnect(dbhandle);
1134 
1135  if (xml_flag == 1) {
1136  /* Read the file and add our new node in memory */
1137  /* TODO don't add if it already exists */
1138  xmlKeepBlanksDefault(0);
1139  xmlTreeIndentString = "\t";
1140  doc = add_zone_node(zonelist_filename, o_zone, o_policy, sig_conf_name, input_name, output_name, input_type, output_type);
1141 
1142  StrFree(sig_conf_name);
1143  StrFree(input_name);
1144  StrFree(output_name);
1145  StrFree(input_type);
1146  StrFree(output_type);
1147 
1148  if (doc == NULL) {
1149  StrFree(zonelist_filename);
1150  return(1);
1151  }
1152 
1153  /* Backup the current zonelist */
1154  StrAppend(&backup_filename, zonelist_filename);
1155  StrAppend(&backup_filename, ".backup");
1156  status = backup_file(zonelist_filename, backup_filename);
1157  StrFree(backup_filename);
1158  if (status != 0) {
1159  StrFree(zonelist_filename);
1160  return(status);
1161  }
1162 
1163  /* Save our new one over, TODO should we validate it first? */
1164  status = xmlSaveFormatFile(zonelist_filename, doc, 1);
1165  StrFree(zonelist_filename);
1166  xmlFreeDoc(doc);
1167 
1168  if (status == -1) {
1169  printf("couldn't save zonelist\n");
1170  return(1);
1171  }
1172  }
1173 
1174  /* TODO - KICK THE ENFORCER? */
1175  /* <matthijs> TODO - ods-signer update? */
1176 
1177  if (xml_flag == 0) {
1178  printf("Imported zone: %s into database only, please run \"ods-ksmutil zonelist export\" to update zonelist.xml\n", o_zone);
1179  } else {
1180  printf("Imported zone: %s\n", o_zone);
1181  }
1182 
1183  StrFree(sig_conf_name);
1184  StrFree(input_name);
1185  StrFree(output_name);
1186 
1187  return 0;
1188 }
1189 
1190 /*
1191  * Delete a zone from the config
1192  */
1193  int
1195 {
1196 
1197  char* zonelist_filename = NULL;
1198  char* backup_filename = NULL;
1199  /* The settings that we need for the zone */
1200  int zone_id = -1;
1201  int policy_id = -1;
1202 
1203  xmlDocPtr doc = NULL;
1204 
1205  int status = 0;
1206  int user_certain; /* Continue ? */
1207 
1208  /* Database connection details */
1209  DB_HANDLE dbhandle;
1210  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
1211 
1212  /* We should either have a policy name or --all but not both */
1213  if (all_flag && o_zone != NULL) {
1214  printf("can not use --all with --zone\n");
1215  return(1);
1216  }
1217  else if (!all_flag && o_zone == NULL) {
1218  printf("please specify either --zone <zone> or --all\n");
1219  return(1);
1220  }
1221 
1222  /* Warn and confirm if they have asked to delete all zones */
1223  if (all_flag == 1) {
1224  printf("*WARNING* This will remove all zones from OpenDNSSEC; are you sure? [y/N] ");
1225 
1226  user_certain = getchar();
1227  if (user_certain != 'y' && user_certain != 'Y') {
1228  printf("Okay, quitting...\n");
1229  exit(0);
1230  }
1231  }
1232 
1233  /* try to connect to the database */
1234  status = db_connect(&dbhandle, &lock_fd, 1);
1235  if (status != 0) {
1236  printf("Failed to connect to database\n");
1237  db_disconnect(lock_fd);
1238  return(1);
1239  }
1240 
1241  /* Put dot back in if we need to; delete zone is the only time we do this */
1242  if (td_flag == 1) {
1243  StrAppend(&o_zone, ".");
1244  }
1245  /*
1246  * DO XML STUFF FIRST
1247  */
1248 
1249  if (xml_flag == 1) {
1250  /* Set zonelist from the conf.xml that we have got */
1251  status = read_zonelist_filename(&zonelist_filename);
1252  if (status != 0) {
1253  printf("couldn't read zonelist\n");
1254  db_disconnect(lock_fd);
1255  StrFree(zonelist_filename);
1256  return(1);
1257  }
1258 
1259  /* Read the file and delete our zone node(s) in memory */
1260  /* N.B. This is deliberately _not_ trailing dot agnostic; the user will have to ask to delete the exact zone */
1261  doc = del_zone_node(zonelist_filename, o_zone);
1262  if (doc == NULL) {
1263  db_disconnect(lock_fd);
1264  StrFree(zonelist_filename);
1265  return(1);
1266  }
1267 
1268  /* rename the Signconf file so that if the zone is readded the old
1269  * file will not be used */
1270  status = rename_signconf(zonelist_filename, o_zone);
1271  if (status != 0) {
1272  StrFree(zonelist_filename);
1273  db_disconnect(lock_fd);
1274  return(status);
1275  }
1276 
1277  /* Backup the current zonelist */
1278  StrAppend(&backup_filename, zonelist_filename);
1279  StrAppend(&backup_filename, ".backup");
1280  status = backup_file(zonelist_filename, backup_filename);
1281  StrFree(backup_filename);
1282  if (status != 0) {
1283  StrFree(zonelist_filename);
1284  db_disconnect(lock_fd);
1285  return(status);
1286  }
1287 
1288  /* Save our new one over, TODO should we validate it first? */
1289  status = xmlSaveFormatFile(zonelist_filename, doc, 1);
1290  xmlFreeDoc(doc);
1291  StrFree(zonelist_filename);
1292  if (status == -1) {
1293  printf("Could not save %s\n", zonelist_filename);
1294  db_disconnect(lock_fd);
1295  return(1);
1296  }
1297  }
1298 
1299  /*
1300  * NOW SORT OUT THE DATABASE (zone_id will still be -1 if we are deleting all)
1301  */
1302 
1303  /* See if the zone exists and get its ID, assuming we are not deleting all */
1304  if (all_flag == 0) {
1305  status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id);
1306  if (status != 0) {
1307  printf("Couldn't find zone %s\n", o_zone);
1308  db_disconnect(lock_fd);
1309  return(1);
1310  }
1311  }
1312 
1313  /* Mark keys as dead */
1314  status = KsmMarkKeysAsDead(zone_id);
1315  if (status != 0) {
1316  printf("Error: failed to mark keys as dead in database\n");
1317  db_disconnect(lock_fd);
1318  return(status);
1319  }
1320 
1321  /* Finally, we can delete the zone */
1322  status = KsmDeleteZone(zone_id);
1323 
1324  if (status != 0) {
1325  printf("Error: failed to remove zone%s from database\n", (all_flag == 1) ? "s" : "");
1326  db_disconnect(lock_fd);
1327  return status;
1328  }
1329 
1330  /* Call the signer_engine_cli to tell it that the zonelist has changed */
1331  if (all_flag == 0) {
1332  if (system(SIGNER_CLI_UPDATE) != 0)
1333  {
1334  printf("Could not call signer engine\n");
1335  }
1336  }
1337 
1338  /* Release sqlite lock file (if we have it) */
1339  db_disconnect(lock_fd);
1340 
1341  if (xml_flag == 0) {
1342  printf("Deleted zone: %s from database only, please run \"ods-ksmutil zonelist export\" to update zonelist.xml\n", o_zone);
1343  }
1344 
1345  return 0;
1346 }
1347 
1348 /*
1349  * List a zone
1350  */
1351  int
1353 {
1354 
1355  DB_HANDLE dbhandle;
1356  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
1357 
1358  char* zonelist_filename = NULL;
1359  int* zone_ids; /* List of zone_ids seen from zonelist.xml */
1360 
1361  xmlTextReaderPtr reader = NULL;
1362  int ret = 0; /* status of the XML parsing */
1363  char* tag_name = NULL;
1364 
1365  int file_zone_count = 0; /* As a quick check we will compare the number of */
1366  int j = 0; /* Another counter */
1367  char buffer[256]; /* For constructing part of the command */
1368  char* sql = NULL; /* SQL "IN" query */
1369  DB_RESULT result; /* Result of the query */
1370  DB_ROW row = NULL; /* Row data */
1371  char* temp_name = NULL;
1372 
1373  int status = 0;
1374 
1375  /* Set zonelist from the conf.xml that we have got */
1376  status = read_zonelist_filename(&zonelist_filename);
1377  if (status != 0) {
1378  printf("couldn't read zonelist\n");
1379  if (zonelist_filename != NULL) {
1380  StrFree(zonelist_filename);
1381  }
1382  return(1);
1383  }
1384 
1385  /* try to connect to the database */
1386  status = db_connect(&dbhandle, &lock_fd, 1);
1387  if (status != 0) {
1388  printf("Failed to connect to database\n");
1389  db_disconnect(lock_fd);
1390  return(1);
1391  }
1392 
1393  /* Read through the file counting zones TODO better way to do this? */
1394  reader = xmlNewTextReaderFilename(zonelist_filename);
1395  if (reader != NULL) {
1396  ret = xmlTextReaderRead(reader);
1397  while (ret == 1) {
1398  tag_name = (char*) xmlTextReaderLocalName(reader);
1399  /* Found <Zone> */
1400  if (strncmp(tag_name, "Zone", 4) == 0
1401  && strncmp(tag_name, "ZoneList", 8) != 0
1402  && xmlTextReaderNodeType(reader) == 1) {
1403  file_zone_count++;
1404  }
1405  /* Read the next line */
1406  ret = xmlTextReaderRead(reader);
1407  StrFree(tag_name);
1408  }
1409  xmlFreeTextReader(reader);
1410  if (ret != 0) {
1411  printf("%s : failed to parse\n", zonelist_filename);
1412  }
1413  } else {
1414  printf("Unable to open %s\n", zonelist_filename);
1415  }
1416 
1417  /* Allocate space for the list of zone IDs */
1418  zone_ids = MemMalloc(file_zone_count * sizeof(int));
1419 
1420  /* Read the file and list the zones as we go */
1421  list_zone_node(zonelist_filename, zone_ids);
1422 
1423  /* Now see if there are any zones in the DB which are not in the file */
1424  if (file_zone_count != 0) {
1425  StrAppend(&sql, "select name from zones where id not in (");
1426  for (j = 0; j < file_zone_count; ++j) {
1427  if (j != 0) {
1428  StrAppend(&sql, ",");
1429  }
1430  snprintf(buffer, sizeof(buffer), "%d", zone_ids[j]);
1431  StrAppend(&sql, buffer);
1432  }
1433  StrAppend(&sql, ")");
1434  } else {
1435  StrAppend(&sql, "select name from zones");
1436  }
1437 
1438  status = DbExecuteSql(DbHandle(), sql, &result);
1439  if (status == 0) {
1440  status = DbFetchRow(result, &row);
1441  while (status == 0) {
1442  /* Got a row, print it */
1443  DbString(row, 0, &temp_name);
1444 
1445  printf("Found zone %s in DB but not zonelist.\n", temp_name);
1446  status = DbFetchRow(result, &row);
1447  file_zone_count++;
1448  }
1449 
1450  /* Convert EOF status to success */
1451 
1452  if (status == -1) {
1453  status = 0;
1454  }
1455 
1456  DbFreeResult(result);
1457  }
1458 
1459  db_disconnect(lock_fd);
1460  DbDisconnect(dbhandle);
1461 
1462  if (file_zone_count == 0) {
1463  printf("No zones in DB or zonelist.\n");
1464  }
1465 
1466  DbFreeRow(row);
1467  MemFree(zone_ids);
1468  StrFree(sql);
1469  StrFree(zonelist_filename);
1470  StrFree(temp_name);
1471 
1472  return 0;
1473 }
1474 
1475 /*
1476  * To export:
1477  * keys|ds for zone
1478  */
1479  int
1481 {
1482  int status = 0;
1483  /* Database connection details */
1484  DB_HANDLE dbhandle;
1485 
1486  int zone_id = -1;
1487  int state_id = -1;
1488  int keytype_id = KSM_TYPE_KSK;
1489  int red_seen = -1; /* Warn if no active or ready keys seen */
1490  int act_seen = -1; /* Also warn if it looks like a rollover is happening */
1491  int prev_zone_id = -1;
1492 
1493  char *case_keytype = NULL;
1494  char *case_keystate = NULL;
1495  char *zone_name = NULL;
1496 
1497  /* Key information */
1498  hsm_key_t *key = NULL;
1499  ldns_rr *dnskey_rr = NULL;
1500  ldns_rr *ds_sha1_rr = NULL;
1501  ldns_rr *ds_sha256_rr = NULL;
1502  hsm_sign_params_t *sign_params = NULL;
1503 
1504  /* To find the ttl of the DS */
1505  int policy_id = -1;
1506  int rrttl = -1;
1507  int param_id = -1; /* unused */
1508 
1509  char* sql = NULL;
1510  KSM_KEYDATA data; /* Data for each key */
1511  DB_RESULT result; /* Result set from query */
1512  size_t nchar; /* Number of characters written */
1513  char buffer[256]; /* For constructing part of the command */
1514 
1515  int done_something = 0; /* Have we exported any keys? */
1516 
1517  /* See what arguments we were passed (if any) otherwise set the defaults */
1518  /* Check keystate, can be state or keytype */
1519  if (o_keystate != NULL) {
1520  case_keystate = StrStrdup(o_keystate);
1521  (void) StrToUpper(case_keystate);
1522  if (strncmp(case_keystate, "KEYPUBLISH", 10) == 0 || strncmp(o_keystate, "10", 2) == 0) {
1523  state_id = KSM_STATE_KEYPUBLISH;
1524  }
1525  else if (strncmp(case_keystate, "GENERATE", 8) == 0 || strncmp(o_keystate, "1", 1) == 0) {
1526  state_id = KSM_STATE_GENERATE;
1527  }
1528  else if (strncmp(case_keystate, "PUBLISH", 7) == 0 || strncmp(o_keystate, "2", 1) == 0) {
1529  state_id = KSM_STATE_PUBLISH;
1530  }
1531  else if (strncmp(case_keystate, "READY", 5) == 0 || strncmp(o_keystate, "3", 1) == 0) {
1532  state_id = KSM_STATE_READY;
1533  }
1534  else if (strncmp(case_keystate, "ACTIVE", 6) == 0 || strncmp(o_keystate, "4", 1) == 0) {
1535  state_id = KSM_STATE_ACTIVE;
1536  }
1537  else if (strncmp(case_keystate, "RETIRE", 6) == 0 || strncmp(o_keystate, "5", 1) == 0) {
1538  state_id = KSM_STATE_RETIRE;
1539  }
1540  else if (strncmp(case_keystate, "DEAD", 4) == 0 || strncmp(o_keystate, "6", 1) == 0) {
1541  state_id = KSM_STATE_DEAD;
1542  }
1543  else if (strncmp(case_keystate, "DSSUB", 5) == 0 || strncmp(o_keystate, "7", 1) == 0) {
1544  state_id = KSM_STATE_DSSUB;
1545  }
1546  else if (strncmp(case_keystate, "DSPUBLISH", 9) == 0 || strncmp(o_keystate, "8", 1) == 0) {
1547  state_id = KSM_STATE_DSPUBLISH;
1548  }
1549  else if (strncmp(case_keystate, "DSREADY", 7) == 0 || strncmp(o_keystate, "9", 1) == 0) {
1550  state_id = KSM_STATE_DSREADY;
1551  }
1552  else {
1553  printf("Error: Unrecognised state %s; should be one of GENERATE, PUBLISH, READY, ACTIVE, RETIRE, DEAD, DSSUB, DSPUBLISH, DSREADY or KEYPUBLISH\n", o_keystate);
1554 
1555  StrFree(case_keystate);
1556  return(1);
1557  }
1558  StrFree(case_keystate);
1559  }
1560 
1561  /* Check keytype */
1562  if (o_keytype != NULL) {
1563  case_keytype = StrStrdup(o_keytype);
1564  (void) StrToUpper(case_keytype);
1565  if (strncmp(case_keytype, "KSK", 3) == 0 || strncmp(o_keytype, "257", 3) == 0) {
1566  keytype_id = KSM_TYPE_KSK;
1567  }
1568  else if (strncmp(case_keytype, "ZSK", 3) == 0 || strncmp(o_keytype, "256", 3) == 0) {
1569  keytype_id = KSM_TYPE_ZSK;
1570  }
1571  else {
1572  printf("Error: Unrecognised keytype %s; should be one of KSK or ZSK\n", o_keytype);
1573 
1574  StrFree(case_keytype);
1575  return(1);
1576  }
1577  StrFree(case_keytype);
1578  }
1579 
1580  /* try to connect to the database */
1581  status = db_connect(&dbhandle, NULL, 0);
1582  if (status != 0) {
1583  printf("Failed to connect to database\n");
1584  return(1);
1585  }
1586 
1587  /* check that the zone name is valid and use it to get some ids */
1588  if (o_zone != NULL) {
1589  status = KsmZoneIdFromName(o_zone, &zone_id);
1590  if (status != 0) {
1591  /* Try again with td */
1592  StrAppend(&o_zone, ".");
1593  status = KsmZoneIdFromName(o_zone, &zone_id);
1594  if (status != 0) {
1595  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
1596  return(status);
1597  }
1598  }
1599  }
1600 
1601  status = hsm_open(config, hsm_prompt_pin);
1602  if (status) {
1603  hsm_print_error(NULL);
1604  exit(-1);
1605  }
1606 
1607  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
1608  if (state_id != -1) {
1609  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, state_id, 0);
1610  } else {
1611  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d, %d, %d)",
1614  if (nchar >= sizeof(buffer)) {
1615  status = -1;
1616  hsm_close();
1617  return status;
1618  }
1619  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, 0);
1620 
1621  }
1622  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype_id, 1);
1623  if (zone_id != -1) {
1624  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 2);
1625  }
1626  DqsOrderBy(&sql, "STATE");
1627  DqsEnd(&sql);
1628 
1629  status = KsmKeyInitSql(&result, sql);
1630  if (status == 0) {
1631  status = KsmKey(result, &data);
1632  while (status == 0) {
1633 
1634  if (ds_flag == 1 && data.zone_id != prev_zone_id) {
1635  prev_zone_id = data.zone_id;
1636  if (red_seen == 0 && act_seen == 0) {
1637  printf("\nWARNING: No active or ready keys seen for this zone. Do not load any DS records to the parent unless you understand the possible consequences.\n");
1638  } else if (red_seen == 1 && act_seen == 1) {
1639  printf("\nWARNING: BOTH ready and active keys seen for this zone. Probably a key rollover is happening and you may only want the ready key to be submitted.\n");
1640  } else {
1641  red_seen = 0;
1642  act_seen = 0;
1643  }
1644  }
1645 
1646  if (data.state == KSM_STATE_READY) {
1647  red_seen = 1;
1648  } else if (data.state == KSM_STATE_ACTIVE) {
1649  act_seen = 1;
1650  }
1651 
1652  /* Code to output the DNSKEY record (stolen from hsmutil) */
1653  key = hsm_find_key_by_id(NULL, data.location);
1654 
1655  if (!key) {
1656  printf("Key %s in DB but not repository\n", data.location);
1657  hsm_close();
1658  return -1;
1659  }
1660 
1661  sign_params = hsm_sign_params_new();
1662  /* If zone_id == -1 then we need to work out the zone name from data.zone_id */
1663  if (zone_id == -1) {
1664  status = KsmZoneNameFromId(data.zone_id, &zone_name);
1665  if (status != 0) {
1666  printf("Error: unable to find zone name for id %d\n", zone_id);
1667  hsm_sign_params_free(sign_params);
1668  hsm_close();
1669  return(status);
1670  }
1671  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone_name);
1672  StrFree(zone_name);
1673  }
1674  else {
1675  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, o_zone);
1676  }
1677 
1678  sign_params->algorithm = data.algorithm;
1679  sign_params->flags = LDNS_KEY_ZONE_KEY;
1680  if (keytype_id == KSM_TYPE_KSK) {
1681  sign_params->flags += LDNS_KEY_SEP_KEY;
1682  }
1683  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
1684  sign_params->keytag = ldns_calc_keytag(dnskey_rr);
1685 
1686  if (ds_flag == 0) {
1687 
1688  /* Set TTL if we can find it; else leave it as the default */
1689  /* We need a policy id */
1690  status = KsmPolicyIdFromZoneId(data.zone_id, &policy_id);
1691  if (status == 0) {
1692 
1693  /* Use this to get the TTL parameter value */
1694  if (keytype_id == KSM_TYPE_KSK) {
1695  status = KsmParameterValue(KSM_PAR_KSKTTL_STRING, KSM_PAR_KSKTTL_CAT, &rrttl, policy_id, &param_id);
1696  } else {
1697  status = KsmParameterValue(KSM_PAR_ZSKTTL_STRING, KSM_PAR_ZSKTTL_CAT, &rrttl, policy_id, &param_id);
1698  }
1699  if (status == 0) {
1700  ldns_rr_set_ttl(dnskey_rr, rrttl);
1701  }
1702  }
1703 
1704  printf("\n;%s %s DNSKEY record:\n", KsmKeywordStateValueToName(data.state), (keytype_id == KSM_TYPE_KSK ? "KSK" : "ZSK"));
1705  ldns_rr_print(stdout, dnskey_rr);
1706  }
1707  else {
1708 
1709  /* Set TTL if we can find it; else leave it as the default */
1710  /* We need a policy id */
1711  status = KsmPolicyIdFromZoneId(data.zone_id, &policy_id);
1712  if (status == 0) {
1713 
1714  /* Use this to get the DSTTL parameter value */
1715  status = KsmParameterValue(KSM_PAR_DSTTL_STRING, KSM_PAR_DSTTL_CAT, &rrttl, policy_id, &param_id);
1716  if (status == 0) {
1717  ldns_rr_set_ttl(dnskey_rr, rrttl);
1718  }
1719  }
1720 
1721  printf("\n;%s %s DS record (SHA1):\n", KsmKeywordStateValueToName(data.state), (keytype_id == KSM_TYPE_KSK ? "KSK" : "ZSK"));
1722  ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1);
1723  ldns_rr_print(stdout, ds_sha1_rr);
1724 
1725  printf("\n;%s %s DS record (SHA256):\n", KsmKeywordStateValueToName(data.state), (keytype_id == KSM_TYPE_KSK ? "KSK" : "ZSK"));
1726  ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256);
1727  ldns_rr_print(stdout, ds_sha256_rr);
1728  }
1729 
1730  done_something = 1;
1731 
1732  hsm_sign_params_free(sign_params);
1733  hsm_key_free(key);
1734  status = KsmKey(result, &data);
1735 
1736  }
1737  /* Convert EOF status to success */
1738  if (status == -1) {
1739  status = 0;
1740  }
1741 
1742  KsmKeyEnd(result);
1743  }
1744  if (ds_flag == 1 && red_seen == 0 && act_seen == 0) {
1745  printf("\nWARNING: No active or ready keys seen for this zone. Do not load any DS records to the parent unless you understand the possible consequences.\n");
1746  } else if (ds_flag == 1 && red_seen == 1 && act_seen == 1) {
1747  printf("\nWARNING: BOTH ready and active keys seen for this zone. Probably a key rollover is happening and you may only want the ready key to be submitted.\n");
1748  }
1749 
1750  /* If we did nothing then explain why not */
1751  if (!done_something) {
1752  if (state_id != -1) {
1753  printf("No keys in %s state to export.\n", KsmKeywordStateValueToName(state_id) );
1754  } else {
1755  printf("No keys in READY state or higher to export.\n");
1756  }
1757  }
1758 
1759  /* TODO when the above is working then replicate it twice for the case where keytype == -1 */
1760 
1761  if (dnskey_rr != NULL) {
1762  ldns_rr_free(dnskey_rr);
1763  }
1764  if (ds_sha1_rr != NULL) {
1765  ldns_rr_free(ds_sha1_rr);
1766  }
1767  if (ds_sha256_rr != NULL) {
1768  ldns_rr_free(ds_sha256_rr);
1769  }
1770 
1771  hsm_close();
1772  DbDisconnect(dbhandle);
1773 
1774  return 0;
1775 }
1776 
1777 /*
1778  * To export:
1779  * policies (all, unless one is named) to xml
1780  */
1781  int
1783 {
1784  int status = 0;
1785  /* Database connection details */
1786  DB_HANDLE dbhandle;
1787 
1788  xmlDocPtr doc = xmlNewDoc((const xmlChar *)"1.0");
1789  xmlNodePtr root;
1790  KSM_POLICY *policy;
1791 
1792  DB_RESULT result; /* Result set from query */
1793 
1794  /* We should either have a policy name or --all but not both */
1795  if (all_flag && o_policy != NULL) {
1796  printf("can not use --all with --policy\n");
1797  return(1);
1798  }
1799  else if (!all_flag && o_policy == NULL) {
1800  printf("please specify either --policy <policy> or --all\n");
1801  return(1);
1802  }
1803 
1804  /* try to connect to the database */
1805  status = db_connect(&dbhandle, NULL, 0);
1806  if (status != 0) {
1807  printf("Failed to connect to database\n");
1808  return(1);
1809  }
1810 
1811  /* Make some space for the policy */
1812  policy = (KSM_POLICY *)malloc(sizeof(KSM_POLICY));
1813  if (policy == NULL) {
1814  fprintf(stderr, "Malloc for policy struct failed\n");
1815  exit(1);
1816  }
1817 
1818  policy->signer = (KSM_SIGNER_POLICY *)malloc(sizeof(KSM_SIGNER_POLICY));
1819  policy->signature = (KSM_SIGNATURE_POLICY *)malloc(sizeof(KSM_SIGNATURE_POLICY));
1820  policy->zone = (KSM_ZONE_POLICY *)malloc(sizeof(KSM_ZONE_POLICY));
1821  policy->parent = (KSM_PARENT_POLICY *)malloc(sizeof(KSM_PARENT_POLICY));
1822  policy->keys = (KSM_COMMON_KEY_POLICY *)malloc(sizeof(KSM_COMMON_KEY_POLICY));
1823  policy->ksk = (KSM_KEY_POLICY *)malloc(sizeof(KSM_KEY_POLICY));
1824  policy->zsk = (KSM_KEY_POLICY *)malloc(sizeof(KSM_KEY_POLICY));
1825  policy->denial = (KSM_DENIAL_POLICY *)malloc(sizeof(KSM_DENIAL_POLICY));
1826  policy->enforcer = (KSM_ENFORCER_POLICY *)malloc(sizeof(KSM_ENFORCER_POLICY));
1827  policy->description = (char *)calloc(KSM_POLICY_DESC_LENGTH, sizeof(char));
1828  if (policy->signer == NULL || policy->signature == NULL ||
1829  policy->zone == NULL || policy->parent == NULL ||
1830  policy->keys == NULL ||
1831  policy->ksk == NULL || policy->zsk == NULL ||
1832  policy->denial == NULL || policy->enforcer == NULL) {
1833  fprintf(stderr, "Malloc for policy struct failed\n");
1834  exit(1);
1835  }
1836 
1837  /* Setup doc with a root node of <KASP> */
1838  xmlKeepBlanksDefault(0);
1839  xmlTreeIndentString = " ";
1840  root = xmlNewDocNode(doc, NULL, (const xmlChar *)"KASP", NULL);
1841  (void) xmlDocSetRootElement(doc, root);
1842 
1843  /* Read policies (all if policy_name == NULL; else named policy only) */
1844  status = KsmPolicyInit(&result, o_policy);
1845  if (status == 0) {
1846  /* get the first policy */
1847  status = KsmPolicy(result, policy);
1848  KsmPolicyRead(policy);
1849 
1850  while (status == 0) {
1851  append_policy(doc, policy);
1852 
1853  /* get next policy */
1854  status = KsmPolicy(result, policy);
1855  KsmPolicyRead(policy);
1856 
1857  }
1858  }
1859 
1860  xmlSaveFormatFile("-", doc, 1);
1861 
1862  xmlFreeDoc(doc);
1863  KsmPolicyFree(policy);
1864 
1865  DbDisconnect(dbhandle);
1866 
1867  return 0;
1868 }
1869 
1870 /*
1871  * To export:
1872  * zonelist to xml
1873  */
1874  int
1876 {
1877  int status = 0;
1878  /* Database connection details */
1879  DB_HANDLE dbhandle;
1880 
1881  xmlDocPtr doc = xmlNewDoc((const xmlChar *)"1.0");
1882  xmlNodePtr root;
1883  KSM_ZONE *zone;
1884  int prev_policy_id = -1;
1885 
1886  DB_RESULT result; /* Result set from query */
1887 
1888  /* try to connect to the database */
1889  status = db_connect(&dbhandle, NULL, 0);
1890  if (status != 0) {
1891  printf("Failed to connect to database\n");
1892  return(1);
1893  }
1894 
1895  /* Make some space for the zone */
1896  zone = (KSM_ZONE *)malloc(sizeof(KSM_ZONE));
1897  if (zone == NULL) {
1898  fprintf(stderr, "Malloc for zone struct failed\n");
1899  exit(1);
1900  }
1901 
1902  /* Setup doc with a root node of <ZoneList> */
1903  xmlKeepBlanksDefault(0);
1904  xmlTreeIndentString = " ";
1905  root = xmlNewDocNode(doc, NULL, (const xmlChar *)"ZoneList", NULL);
1906  (void) xmlDocSetRootElement(doc, root);
1907 
1908  /* Read zones */
1909  status = KsmZoneInit(&result, -1);
1910  if (status == 0) {
1911  /* get the first zone */
1912  status = KsmZone(result, zone);
1913 
1914  while (status == 0) {
1915  if (zone->policy_id != prev_policy_id) {
1916  prev_policy_id = zone->policy_id;
1917  status = get_policy_name_from_id(zone);
1918  if (status != 0) {
1919  fprintf(stderr, "Couldn't get name for policy with ID: %d, exiting...\n", zone->policy_id);
1920  return(1);
1921  }
1922  }
1923  append_zone(doc, zone);
1924 
1925  /* get next zone */
1926  status = KsmZone(result, zone);
1927 
1928  }
1929  }
1930 
1931  xmlSaveFormatFile("-", doc, 1);
1932 
1933  xmlFreeDoc(doc);
1934  /*KsmZoneFree(zone);*/
1935 
1936  DbDisconnect(dbhandle);
1937 
1938  return 0;
1939 }
1940 
1941 /*
1942  * To rollover a zone (or all zones on a policy if keys are shared)
1943  */
1944  int
1946 {
1947  /* Database connection details */
1948  DB_HANDLE dbhandle;
1949  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
1950  DB_RESULT result; /* Result of parameter query */
1951  KSM_PARAMETER data; /* Parameter information */
1952 
1953  int key_type = -1;
1954  int zone_id = -1;
1955  int policy_id = -1;
1956 
1957  int status = 0;
1958  int user_certain;
1959 
1960  char logmsg[256]; /* For the message that we log when we are done here */
1961 
1962  /* If we were given a keytype, turn it into a number */
1963  if (o_keytype != NULL) {
1966  }
1967 
1968  /* try to connect to the database */
1969  status = db_connect(&dbhandle, &lock_fd, 1);
1970  if (status != 0) {
1971  printf("Failed to connect to database\n");
1972  db_disconnect(lock_fd);
1973  return(1);
1974  }
1975 
1976  status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id);
1977  if (status != 0) {
1978  /* Try again with td */
1979  StrAppend(&o_zone, ".");
1980  status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id);
1981  if (status != 0) {
1982  printf("Error, can't find zone : %s\n", o_zone);
1983  db_disconnect(lock_fd);
1984  return(status);
1985  }
1986  }
1987 
1988  /* Get the shared_keys parameter */
1989  status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
1990  if (status != 0) {
1991  db_disconnect(lock_fd);
1992  return(status);
1993  }
1994  status = KsmParameter(result, &data);
1995  if (status != 0) {
1996  db_disconnect(lock_fd);
1997  return(status);
1998  }
1999  KsmParameterEnd(result);
2000 
2001  /* Warn and confirm if this will roll more than one zone */
2002  if (data.value == 1) {
2003  printf("*WARNING* This zone shares keys with others, all instances of the active key on this zone will be retired; are you sure? [y/N] ");
2004 
2005  user_certain = getchar();
2006  if (user_certain != 'y' && user_certain != 'Y') {
2007  printf("Okay, quitting...\n");
2008  db_disconnect(lock_fd);
2009  exit(0);
2010  }
2011  }
2012 
2013  status = keyRoll(zone_id, -1, key_type);
2014  if (status != 0) {
2015  db_disconnect(lock_fd);
2016  return(status);
2017  }
2018 
2019  /* Let them know that it seemed to work */
2020  snprintf(logmsg, 256, "Manual key rollover for key type %s on zone %s initiated" , (o_keytype == NULL) ? "all" : o_keytype, o_zone);
2021  printf("\n%s\n", logmsg);
2022 
2023 /* send the msg to syslog */
2024 #ifdef HAVE_OPENLOG_R
2025  openlog_r("ods-ksmutil", 0, DEFAULT_LOG_FACILITY, &sdata);
2026 #else
2027  openlog("ods-ksmutil", 0, DEFAULT_LOG_FACILITY);
2028 #endif
2029 #ifdef HAVE_SYSLOG_R
2030  syslog_r(LOG_INFO, &sdata, "%s", logmsg);
2031 #else
2032  syslog(LOG_INFO, "%s", logmsg);
2033 #endif
2034 #ifdef HAVE_CLOSELOG_R
2035  closelog_r(&sdata);
2036 #else
2037  closelog();
2038 #endif
2039 
2040  /* Release sqlite lock file (if we have it) */
2041  db_disconnect(lock_fd);
2042 
2043  /* Need to poke the enforcer to wake it up */
2044  if (restart_enforcerd() != 0)
2045  {
2046  fprintf(stderr, "Could not HUP ods-enforcerd\n");
2047  }
2048 
2049  DbDisconnect(dbhandle);
2050 
2051  return 0;
2052 }
2053 
2054 /*
2055  * To rollover all zones on a policy
2056  */
2057  int
2059 {
2060  /* Database connection details */
2061  DB_HANDLE dbhandle;
2062  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2063 
2064  DB_RESULT result; /* To see if the policy shares keys or not */
2065 
2066  int zone_count = -1;
2067 
2068  int key_type = -1;
2069  int policy_id = 0;
2070 
2071  int status = 0;
2072  int user_certain;
2073 
2074  char logmsg[256]; /* For the message that we log when we are done here */
2075 
2076  /* If we were given a keytype, turn it into a number */
2077  if (o_keytype != NULL) {
2080  }
2081 
2082  /* try to connect to the database */
2083  status = db_connect(&dbhandle, &lock_fd, 1);
2084  if (status != 0) {
2085  printf("Failed to connect to database\n");
2086  db_disconnect(lock_fd);
2087  return(1);
2088  }
2089 
2090  status = KsmPolicyIdFromName(o_policy, &policy_id);
2091  if (status != 0) {
2092  printf("Error, can't find policy : %s\n", o_policy);
2093  db_disconnect(lock_fd);
2094  return(status);
2095  }
2096 
2097  /* Warn and confirm */
2098  printf("*WARNING* This will roll all keys on the policy; are you sure? [y/N] ");
2099 
2100  user_certain = getchar();
2101  if (user_certain != 'y' && user_certain != 'Y') {
2102  printf("Okay, quitting...\n");
2103  db_disconnect(lock_fd);
2104  exit(0);
2105  }
2106 
2107  /* Find out how many zones we will need to do */
2108  /* how many zones on this policy */
2109  status = KsmZoneCountInit(&result, policy_id);
2110  if (status == 0) {
2111  status = KsmZoneCount(result, &zone_count);
2112  }
2113  DbFreeResult(result);
2114 
2115  if (status == 0) {
2116  /* make sure that we have at least one zone */
2117  if (zone_count == 0) {
2118  printf("No zones on policy; nothing to roll\n");
2119  db_disconnect(lock_fd);
2120  return status;
2121  }
2122  } else {
2123  printf("Couldn't count zones on policy; quitting...\n");
2124  db_disconnect(lock_fd);
2125  exit(1);
2126  }
2127 
2128  status = keyRoll(-1, policy_id, key_type);
2129  if (status != 0) {
2130  db_disconnect(lock_fd);
2131  return(status);
2132  }
2133 
2134  /* Let them know that it seemed to work */
2135  snprintf(logmsg, 256, "Manual key rollover for key type %s on policy %s initiated" , (o_keytype == NULL) ? "all" : o_keytype, o_policy);
2136  printf("%s\n", logmsg);
2137 
2138 /* send the msg to syslog */
2139 #ifdef HAVE_OPENLOG_R
2140  openlog_r("ods-ksmutil", 0, DEFAULT_LOG_FACILITY, &sdata);
2141 #else
2142  openlog("ods-ksmutil", 0, DEFAULT_LOG_FACILITY);
2143 #endif
2144 #ifdef HAVE_SYSLOG_R
2145  syslog_r(LOG_INFO, &sdata, "%s", logmsg);
2146 #else
2147  syslog(LOG_INFO, "%s", logmsg);
2148 #endif
2149 #ifdef HAVE_CLOSELOG_R
2150  closelog_r(&sdata);
2151 #else
2152  closelog();
2153 #endif
2154 
2155  /* Release sqlite lock file (if we have it) */
2156  db_disconnect(lock_fd);
2157 
2158  /* Need to poke the enforcer to wake it up */
2159  if (restart_enforcerd() != 0)
2160  {
2161  fprintf(stderr, "Could not HUP ods-enforcerd\n");
2162  }
2163 
2164  DbDisconnect(dbhandle);
2165 
2166  return 0;
2167 }
2168 
2169 /*
2170  * purge dead keys from the database
2171  */
2172  int
2174 {
2175  int status = 0;
2176 
2177  int policy_id = -1;
2178  int zone_id = -1;
2179 
2180  /* Database connection details */
2181  DB_HANDLE dbhandle;
2182  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2183 
2184  /* try to connect to the database */
2185  status = db_connect(&dbhandle, &lock_fd, 1);
2186  if (status != 0) {
2187  printf("Failed to connect to database\n");
2188  db_disconnect(lock_fd);
2189  return(1);
2190  }
2191 
2192  /* Turn policy name into an id (if provided) */
2193  if (o_policy != NULL) {
2194  status = KsmPolicyIdFromName(o_policy, &policy_id);
2195  if (status != 0) {
2196  printf("Error: unable to find a policy named \"%s\" in database\n", o_policy);
2197  db_disconnect(lock_fd);
2198  return status;
2199  }
2200  }
2201 
2202  /* Turn zone name into an id (if provided) */
2203  if (o_zone != NULL) {
2204  status = KsmZoneIdFromName(o_zone, &zone_id);
2205  if (status != 0) {
2206  /* Try again with td */
2207  StrAppend(&o_zone, ".");
2208  status = KsmZoneIdFromName(o_zone, &zone_id);
2209  if (status != 0) {
2210  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
2211  db_disconnect(lock_fd);
2212  return(status);
2213  }
2214  }
2215  }
2216 
2217  status = PurgeKeys(zone_id, policy_id);
2218 
2219  if (status != 0) {
2220  printf("Error: failed to purge dead keys\n");
2221  db_disconnect(lock_fd);
2222  return status;
2223  }
2224 
2225  /* Release sqlite lock file (if we have it) */
2226  db_disconnect(lock_fd);
2227 
2228  DbDisconnect(dbhandle);
2229  return 0;
2230 }
2231 
2232 /*
2233  * note that fact that a backup has been performed
2234  */
2235  int
2236 cmd_backup (const char* qualifier)
2237 {
2238  int status = 0;
2239 
2240  int repo_id = -1;
2241 
2242  int user_certain; /* Continue ? */
2243 
2244  /* Database connection details */
2245  DB_HANDLE dbhandle;
2246  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2247 
2248  char* datetime = DtParseDateTimeString("now");
2249 
2250  /* Check datetime in case it came back NULL */
2251  if (datetime == NULL) {
2252  printf("Couldn't turn \"now\" into a date, quitting...\n");
2253  exit(1);
2254  }
2255 
2256  /* Warn about deprecation if we are doing the one-step backup */
2257  if ( strncmp(qualifier, "DONE", 4) == 0 ) {
2258  printf("*WARNING* One-step backups are deprecated in favour of a two-step process; see the documentation on key management for the explanation.\n");
2259 
2260  /* Allow force flag to override the question for scripts */
2261  if (force_flag == 0) {
2262  printf("Do you wish to continue? [y/N] ");
2263 
2264  user_certain = getchar();
2265  if (user_certain != 'y' && user_certain != 'Y') {
2266  printf("Okay, quitting...\n");
2267  exit(0);
2268  }
2269  }
2270  }
2271 
2272  /* try to connect to the database */
2273  status = db_connect(&dbhandle, &lock_fd, 1);
2274  if (status != 0) {
2275  printf("Failed to connect to database\n");
2276  db_disconnect(lock_fd);
2277  StrFree(datetime);
2278  return(1);
2279  }
2280 
2281  /* Turn repo name into an id (if provided) */
2282  if (o_repository != NULL) {
2283  status = KsmSmIdFromName(o_repository, &repo_id);
2284  if (status != 0) {
2285  printf("Error: unable to find a repository named \"%s\" in database\n", o_repository);
2286  db_disconnect(lock_fd);
2287  StrFree(datetime);
2288  return status;
2289  }
2290  }
2291 
2292  /* Do Pre first */
2293  if (strncmp(qualifier, "PREPARE", 7) == 0 ||
2294  strncmp(qualifier, "DONE", 4) == 0 ) {
2295  status = KsmMarkPreBackup(repo_id, datetime);
2296  if (status == -1) {
2297  printf("There were no keys to mark\n");
2298  }
2299  else if (status != 0) {
2300  printf("Error: failed to mark pre_backup as done\n");
2301  db_disconnect(lock_fd);
2302  StrFree(datetime);
2303  return status;
2304  } else {
2305  if (strncmp(qualifier, "PREPARE", 7) == 0) {
2306  if (o_repository != NULL) {
2307  printf("Marked repository %s as pre-backed up at %s\n", o_repository, datetime);
2308  } else {
2309  printf("Marked all repositories as pre-backed up at %s\n", datetime);
2310  }
2311  }
2312  }
2313  }
2314 
2315  /* Then commit */
2316  if (strncmp(qualifier, "COMMIT", 6) == 0 ||
2317  strncmp(qualifier, "DONE", 4) == 0 ) {
2318  status = KsmMarkBackup(repo_id, datetime);
2319  if (status == -1) {
2320  printf("There were no keys to mark\n");
2321  }
2322  else if (status != 0) {
2323  printf("Error: failed to mark backup as done\n");
2324  db_disconnect(lock_fd);
2325  StrFree(datetime);
2326  return status;
2327  } else {
2328  if (o_repository != NULL) {
2329  printf("Marked repository %s as backed up at %s\n", o_repository, datetime);
2330  } else {
2331  printf("Marked all repositories as backed up at %s\n", datetime);
2332  }
2333  }
2334  }
2335 
2336  /* Finally rollback */
2337  if (strncmp(qualifier, "ROLLBACK", 6) == 0 ) {
2338  status = KsmRollbackMarkPreBackup(repo_id);
2339  if (status == -1) {
2340  printf("There were no keys to rollback\n");
2341  }
2342  else if (status != 0) {
2343  printf("Error: failed to mark backup as done\n");
2344  db_disconnect(lock_fd);
2345  StrFree(datetime);
2346  return status;
2347  } else {
2348  if (o_repository != NULL) {
2349  printf("Rolled back pre-backup of repository %s\n", o_repository);
2350  } else {
2351  printf("Rolled back pre-backup of all repositories\n");
2352  }
2353  }
2354  }
2355 
2356  StrFree(datetime);
2357  /* Release sqlite lock file (if we have it) */
2358  db_disconnect(lock_fd);
2359 
2360  DbDisconnect(dbhandle);
2361  return 0;
2362 }
2363 
2364 /*
2365  * List rollovers
2366  */
2367  int
2369 {
2370  int status = 0;
2371  int ds_count = 0;
2372 
2373  int qualifier_id = -1; /* ID of qualifer (if given) */
2374 
2375  /* Database connection details */
2376  DB_HANDLE dbhandle;
2377  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2378 
2379  /* try to connect to the database */
2380  status = db_connect(&dbhandle, &lock_fd, 1);
2381  if (status != 0) {
2382  printf("Failed to connect to database\n");
2383  db_disconnect(lock_fd);
2384  return(1);
2385  }
2386 
2387  /* Turn zone name into an id (if provided) */
2388  if (o_zone != NULL) {
2389  status = KsmZoneIdFromName(o_zone, &qualifier_id);
2390  if (status != 0) {
2391  /* Try again with td */
2392  StrAppend(&o_zone, ".");
2393  status = KsmZoneIdFromName(o_zone, &qualifier_id);
2394  if (status != 0) {
2395  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
2396  db_disconnect(lock_fd);
2397  return(status);
2398  }
2399  }
2400  }
2401 
2402  printf("Rollovers:\n");
2403 
2404  status = KsmListRollovers(qualifier_id, &ds_count);
2405 
2406  if (status != 0) {
2407  printf("Error: failed to list rollovers\n");
2408  db_disconnect(lock_fd);
2409  return status;
2410  }
2411 
2412  printf("\n");
2413 
2414  /* If verbose flag set and some keys waiting for ds-seen then print some
2415  * helpful information for the user */
2416  if (verbose_flag && ds_count > 0) {
2417 
2418  status = ListDS(qualifier_id);
2419 
2420  if (status != 0) {
2421  printf("Error: failed to list DS records\n");
2422  db_disconnect(lock_fd);
2423  return status;
2424  }
2425  }
2426 
2427  /* Release sqlite lock file (if we have it) */
2428  db_disconnect(lock_fd);
2429 
2430  DbDisconnect(dbhandle);
2431  return 0;
2432 }
2433 
2434 /*
2435  * List backups
2436  */
2437  int
2439 {
2440  int status = 0;
2441 
2442  int qualifier_id = -1; /* ID of qualifer (if given) */
2443 
2444  /* Database connection details */
2445  DB_HANDLE dbhandle;
2446  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2447 
2448  /* try to connect to the database */
2449  status = db_connect(&dbhandle, &lock_fd, 0);
2450  if (status != 0) {
2451  printf("Failed to connect to database\n");
2452  db_disconnect(lock_fd);
2453  return(1);
2454  }
2455 
2456  /* Turn repo name into an id (if provided) */
2457  if (o_repository != NULL) {
2458  status = KsmSmIdFromName(o_repository, &qualifier_id);
2459  if (status != 0) {
2460  printf("Error: unable to find a repository named \"%s\" in database\n", o_repository);
2461  db_disconnect(lock_fd);
2462  return status;
2463  }
2464  }
2465 
2466  printf("Backups:\n");
2467  status = KsmListBackups(qualifier_id, verbose_flag);
2468 
2469  if (status != 0) {
2470  printf("Error: failed to list backups\n");
2471  db_disconnect(lock_fd);
2472  return status;
2473  }
2474  printf("\n");
2475 
2476  /* Release sqlite lock file (if we have it) */
2477  db_disconnect(lock_fd);
2478 
2479  DbDisconnect(dbhandle);
2480  return 0;
2481 }
2482 
2483 /*
2484  * List repos
2485  */
2486  int
2488 {
2489  int status = 0;
2490 
2491  /* Database connection details */
2492  DB_HANDLE dbhandle;
2493  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2494 
2495  /* try to connect to the database */
2496  status = db_connect(&dbhandle, &lock_fd, 0);
2497  if (status != 0) {
2498  printf("Failed to connect to database\n");
2499  db_disconnect(lock_fd);
2500  return(1);
2501  }
2502 
2503  printf("Repositories:\n");
2504 
2505  status = KsmListRepos();
2506 
2507  if (status != 0) {
2508  printf("Error: failed to list repositories\n");
2509  if (lock_fd != NULL) {
2510  fclose(lock_fd);
2511  }
2512  return status;
2513  }
2514 
2515  printf("\n");
2516 
2517  /* Release sqlite lock file (if we have it) */
2518  db_disconnect(lock_fd);
2519 
2520  DbDisconnect(dbhandle);
2521  return 0;
2522 }
2523 
2524 /*
2525  * List policy
2526  */
2527  int
2529 {
2530  int status = 0;
2531 
2532  /* Database connection details */
2533  DB_HANDLE dbhandle;
2534  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2535 
2536  /* try to connect to the database */
2537  status = db_connect(&dbhandle, &lock_fd, 0);
2538  if (status != 0) {
2539  printf("Failed to connect to database\n");
2540  db_disconnect(lock_fd);
2541  return(1);
2542  }
2543 
2544  printf("Policies:\n");
2545 
2546  status = KsmListPolicies();
2547 
2548  if (status != 0) {
2549  printf("Error: failed to list policies\n");
2550  db_disconnect(lock_fd);
2551  return status;
2552  }
2553 
2554  printf("\n");
2555 
2556  /* Release sqlite lock file (if we have it) */
2557  db_disconnect(lock_fd);
2558 
2559  DbDisconnect(dbhandle);
2560  return 0;
2561 }
2562 
2563 /*
2564  * List keys
2565  */
2566  int
2568 {
2569  int status = 0;
2570  int qualifier_id = -1;
2571 
2572  /* Database connection details */
2573  DB_HANDLE dbhandle;
2574  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2575 
2576  /* try to connect to the database */
2577  status = db_connect(&dbhandle, &lock_fd, 0);
2578  if (status != 0) {
2579  printf("Failed to connect to database\n");
2580  db_disconnect(lock_fd);
2581  return(1);
2582  }
2583 
2584  /* Turn zone name into an id (if provided) */
2585  if (o_zone != NULL) {
2586  status = KsmZoneIdFromName(o_zone, &qualifier_id);
2587  if (status != 0) {
2588  /* Try again with td */
2589  StrAppend(&o_zone, ".");
2590  status = KsmZoneIdFromName(o_zone, &qualifier_id);
2591  if (status != 0) {
2592  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
2593  db_disconnect(lock_fd);
2594  return(status);
2595  }
2596  }
2597  }
2598 
2599  printf("Keys:\n");
2600 
2601  status = ListKeys(qualifier_id);
2602 
2603  if (status != 0) {
2604  printf("Error: failed to list keys\n");
2605  db_disconnect(lock_fd);
2606  return status;
2607  }
2608 
2609  printf("\n");
2610 
2611  /* Release sqlite lock file (if we have it) */
2612  db_disconnect(lock_fd);
2613 
2614  DbDisconnect(dbhandle);
2615  return 0;
2616 }
2617 
2618 /*
2619  * KSKretire
2620  find key (either by details provided or oldest active),
2621  make sure that it is unique and in active state,
2622  retire key and set its dead time,
2623  */
2624  int
2626 {
2627  int status = 0;
2628  int zone_id = -1;
2629  int policy_id = -1;
2630  int key_count = -1;
2631  int keytag_int = -1;
2632  int temp_key_state = -1;
2633  int temp_keypair_id = -1;
2634  char* temp_cka_id = NULL; /* This will be set if we find a single matching key */
2635  int user_certain; /* Continue ? */
2636 
2637  /* Database connection details */
2638  DB_HANDLE dbhandle;
2639  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2640 
2641  char* datetime = DtParseDateTimeString("now");
2642 
2643  /* Check datetime in case it came back NULL */
2644  if (datetime == NULL) {
2645  printf("Couldn't turn \"now\" into a date, quitting...\n");
2646  StrFree(datetime);
2647  exit(1);
2648  }
2649 
2650  /* Warn and confirm that they realise this will retire the old key */
2651  printf("*WARNING* This will retire the currently active KSK; are you sure? [y/N] ");
2652 
2653  user_certain = getchar();
2654  if (user_certain != 'y' && user_certain != 'Y') {
2655  printf("Okay, quitting...\n");
2656  exit(0);
2657  }
2658 
2659  /* try to connect to the database */
2660  status = db_connect(&dbhandle, &lock_fd, 1);
2661  if (status != 0) {
2662  printf("Failed to connect to database\n");
2663  db_disconnect(lock_fd);
2664  StrFree(datetime);
2665  return(1);
2666  }
2667 
2668  /* Turn zone name into an id (if provided) */
2669  if (o_zone != NULL) {
2670  status = KsmZoneIdFromName(o_zone, &zone_id);
2671  if (status != 0) {
2672  /* Try again with td */
2673  StrAppend(&o_zone, ".");
2674  status = KsmZoneIdFromName(o_zone, &zone_id);
2675  if (status != 0) {
2676  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
2677  db_disconnect(lock_fd);
2678  StrFree(datetime);
2679  return(status);
2680  }
2681  }
2682  }
2683 
2684  /* Check the keytag is numeric */
2685  if (o_keytag != NULL) {
2686  if (StrIsDigits(o_keytag)) {
2687  status = StrStrtoi(o_keytag, &keytag_int);
2688  if (status != 0) {
2689  printf("Error: Unable to convert keytag \"%s\"; to an integer\n", o_keytag);
2690  db_disconnect(lock_fd);
2691  StrFree(datetime);
2692  return(status);
2693  }
2694  } else {
2695  printf("Error: keytag \"%s\"; should be numeric only\n", o_keytag);
2696  db_disconnect(lock_fd);
2697  StrFree(datetime);
2698  return(1);
2699  }
2700  }
2701 
2702  if (o_keytag == NULL && o_cka_id == NULL) {
2703  /* We will retire the oldest key if there are 2 or more active keys */
2704  if (o_zone == NULL) {
2705  printf("Please provide a zone or details of the key to roll\n");
2707  db_disconnect(lock_fd);
2708  StrFree(datetime);
2709  return(-1);
2710  }
2711 
2712  status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_ACTIVE, &key_count, zone_id);
2713  if (status != 0) {
2714  printf("Error: failed to count active keys\n");
2715  db_disconnect(lock_fd);
2716  StrFree(datetime);
2717  return status;
2718  }
2719 
2720  /* If there are not at least 2 active keys then quit */
2721  if (key_count < 2) {
2722  printf("Error: completing this action would leave no active keys on zone, quitting...\n");
2723  db_disconnect(lock_fd);
2724  StrFree(datetime);
2725  return -1;
2726  }
2727 
2728  /* We will need a policy id for the next bit */
2729  status = KsmPolicyIdFromZoneId(zone_id, &policy_id);
2730  if (status != 0) {
2731  printf("Error: failed to find policy for zone\n");
2732  db_disconnect(lock_fd);
2733  StrFree(datetime);
2734  return status;
2735  }
2736 
2737  status = RetireOldKey(zone_id, policy_id, datetime);
2738 
2739  if (status == 0) {
2740  printf("Old key retired\n");
2741  } else {
2742  printf("Old key NOT retired\n");
2743  }
2744  } else {
2745 
2746  /*
2747  * Get a count of keys that match our specifiers, will also print out
2748  * matching keys; note that zone_id may be overwritten
2749  */
2750  status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state, &temp_keypair_id);
2751  if (status != 0) {
2752  printf("Error: failed to count keys\n");
2753  db_disconnect(lock_fd);
2754  StrFree(datetime);
2755  return status;
2756  }
2757 
2758  /* If the keycount is more than 1 then display the cka_ids of the keys */
2759  if (key_count > 1) {
2760  printf("More than one key matched your parameters, please include more information from the above keys\n");
2761  db_disconnect(lock_fd);
2762  StrFree(datetime);
2763  return -1;
2764  }
2765 
2766  /* If the keycount is 0 or the key is not ACTIVE then write a message and exit */
2767  if (key_count == 0 || temp_key_state != KSM_STATE_ACTIVE) {
2768  printf("No keys in the ACTIVE state matched your parameters, please check the parameters\n");
2769  db_disconnect(lock_fd);
2770  StrFree(datetime);
2771  return -1;
2772  }
2773 
2774  status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_ACTIVE, &key_count, zone_id);
2775  if (status != 0) {
2776  printf("Error: failed to count active keys\n");
2777  db_disconnect(lock_fd);
2778  StrFree(datetime);
2779  return status;
2780  }
2781 
2782  /* If there are not at least 2 active keys then quit */
2783  if (key_count < 2) {
2784  printf("Error: completing this action would leave no active keys on zone, quitting...\n");
2785  db_disconnect(lock_fd);
2786  StrFree(datetime);
2787  return -1;
2788  }
2789 
2790  /* We will need a policy id for the next bit */
2791  status = KsmPolicyIdFromZoneId(zone_id, &policy_id);
2792  if (status != 0) {
2793  printf("Error: failed to find policy for zone\n");
2794  db_disconnect(lock_fd);
2795  StrFree(datetime);
2796  return status;
2797  }
2798 
2799  /* Retire the key */
2800  status = ChangeKeyState(KSM_TYPE_KSK, temp_cka_id, zone_id, policy_id, datetime, KSM_STATE_RETIRE);
2801 
2802  /* Let them know that it seemed to work */
2803  if (status == 0) {
2804  printf("Key %s retired\n", temp_cka_id);
2805  }
2806  }
2807 
2808  /* Release sqlite lock file (if we have it) */
2809  db_disconnect(lock_fd);
2810 
2811  DbDisconnect(dbhandle);
2812 
2813  StrFree(datetime);
2814 
2815  return status;
2816 }
2817 
2818 /*
2819  * DS Seen
2820  mark key as having had its DS published
2821  i.e. change its state to ACTIVE and set the time
2822  also set the time at which it will go to RETIRED
2823  */
2824  int
2826 {
2827  int status = 0;
2828  int zone_id = -1;
2829  int policy_id = -1;
2830  int key_count = -1;
2831  int retired_count = -1;
2832  int keytag_int = -1;
2833  int temp_key_state = -1;
2834  int temp_keypair_id = -1;
2835  char* temp_cka_id = NULL; /* This will be set if we find a single matching key */
2836  int user_certain; /* Continue ? */
2837 
2838  /* Database connection details */
2839  DB_HANDLE dbhandle;
2840  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
2841 
2842  char logmsg[256]; /* For the message that we log when a key moves */
2843 
2844  char* datetime = DtParseDateTimeString("now");
2845 
2846  /* Check datetime in case it came back NULL */
2847  if (datetime == NULL) {
2848  printf("Couldn't turn \"now\" into a date, quitting...\n");
2849  StrFree(datetime);
2850  exit(1);
2851  }
2852 
2853  /* Check that we have either a keytag or a cka_id */
2854  if (o_keytag == NULL && o_cka_id == NULL) {
2855  printf("Please provide a keytag or a CKA_ID for the key (CKA_ID will be used if both are provided\n");
2856  usage_keydsseen();
2857  StrFree(datetime);
2858  return(-1);
2859  }
2860 
2861  /* Warn and confirm that they realise this will retire the old key */
2862  if (0) {
2863  printf("*WARNING* This will retire the currently active KSK; are you sure? [y/N] ");
2864 
2865  user_certain = getchar();
2866  if (user_certain != 'y' && user_certain != 'Y') {
2867  printf("Okay, quitting...\n");
2868  exit(0);
2869  }
2870  }
2871  /* try to connect to the database */
2872  status = db_connect(&dbhandle, &lock_fd, 1);
2873  if (status != 0) {
2874  printf("Failed to connect to database\n");
2875  db_disconnect(lock_fd);
2876  StrFree(datetime);
2877  return(1);
2878  }
2879 
2880  /* Turn zone name into an id (if provided) */
2881  /* TODO sort out all flag */
2882  /*if (o_zone == NULL && !all_flag) {
2883  printf("Please specify a zone or use the --all flag to indicate all zones using this key\n");*/
2884  if (o_zone == NULL) {
2885  printf("Please specify a zone using the --zone flag\n");
2886  usage_keydsseen();
2887  StrFree(datetime);
2888  db_disconnect(lock_fd);
2889  return(-1);
2890  }
2891  else if (o_zone != NULL) {
2892  status = KsmZoneIdFromName(o_zone, &zone_id);
2893  if (status != 0) {
2894  /* Try again with td */
2895  StrAppend(&o_zone, ".");
2896  status = KsmZoneIdFromName(o_zone, &zone_id);
2897  if (status != 0) {
2898  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
2899  db_disconnect(lock_fd);
2900  StrFree(datetime);
2901  return(status);
2902  }
2903  }
2904  }
2905  else if (all_flag) {
2906  printf("*WARNING* This will act on every zone where this key is in use; are you sure? [y/N] ");
2907 
2908  user_certain = getchar();
2909  if (user_certain != 'y' && user_certain != 'Y') {
2910  printf("Okay, quitting...\n");
2911  exit(0);
2912  }
2913 
2914  zone_id = -1;
2915  }
2916 
2917  /* Check the keytag is numeric */
2918  if (o_keytag != NULL) {
2919  if (StrIsDigits(o_keytag)) {
2920  status = StrStrtoi(o_keytag, &keytag_int);
2921  if (status != 0) {
2922  printf("Error: Unable to convert keytag \"%s\"; to an integer\n", o_keytag);
2923  db_disconnect(lock_fd);
2924  StrFree(datetime);
2925  return(status);
2926  }
2927  } else {
2928  printf("Error: keytag \"%s\"; should be numeric only\n", o_keytag);
2929  db_disconnect(lock_fd);
2930  StrFree(datetime);
2931  return(1);
2932  }
2933  }
2934 
2935  /*
2936  * Get a count of keys that match our specifiers, will also print out
2937  * matching keys; note that zone_id may be overwritten
2938  */
2939  status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state, &temp_keypair_id);
2940  if (status != 0) {
2941  printf("Error: failed to count keys\n");
2942  db_disconnect(lock_fd);
2943  StrFree(datetime);
2944  return status;
2945  }
2946 
2947  /* If the keycount is more than 1 then display the cka_ids of the keys */
2948  if (key_count > 1) {
2949  printf("More than one key matched your parameters, please include more information from the above keys\n");
2950  db_disconnect(lock_fd);
2951  StrFree(datetime);
2952  return -1;
2953  }
2954 
2955  /* If the key is already active then write a message and exit */
2956  if (temp_key_state == KSM_STATE_ACTIVE) {
2957  printf("Key is already active\n");
2958  db_disconnect(lock_fd);
2959  StrFree(datetime);
2960  return -1;
2961  }
2962 
2963  /* If the keycount is 0 then write a message and exit */
2964  if (key_count == 0) {
2965  printf("No keys in the READY state matched your parameters, please check the parameters\n");
2966  db_disconnect(lock_fd);
2967  StrFree(datetime);
2968  return -1;
2969  }
2970 
2971  /* We will need a policy id for the next bit */
2972  status = KsmPolicyIdFromZoneId(zone_id, &policy_id);
2973  if (status != 0) {
2974  printf("Error: failed to find policy for zone\n");
2975  db_disconnect(lock_fd);
2976  StrFree(datetime);
2977  return status;
2978  }
2979 
2980  /* Do stuff */
2981  status = MarkDSSeen(temp_keypair_id, zone_id, policy_id, datetime, temp_key_state);
2982 
2983  /* Let them know that it seemed to work */
2984  if (status == 0) {
2985  snprintf(logmsg, 256, "Key %s made %s", temp_cka_id, (temp_key_state == KSM_STATE_READY) ? "active" : "into standby");
2986  printf("%s\n", logmsg);
2987 
2988  /* send the msg to syslog */
2989 #ifdef HAVE_OPENLOG_R
2990  openlog_r("ods-ksmutil", 0, DEFAULT_LOG_FACILITY, &sdata);
2991 #else
2992  openlog("ods-ksmutil", 0, DEFAULT_LOG_FACILITY);
2993 #endif
2994 #ifdef HAVE_SYSLOG_R
2995  syslog_r(LOG_INFO, &sdata, "%s", logmsg);
2996 #else
2997  syslog(LOG_INFO, "%s", logmsg);
2998 #endif
2999 #ifdef HAVE_CLOSELOG_R
3000  closelog_r(&sdata);
3001 #else
3002  closelog();
3003 #endif
3004 
3005  }
3006 
3007  /* Retire old key, unless asked not to */
3008  if (temp_key_state == KSM_STATE_READY) {
3009  if (retire_flag == 1) {
3010 
3011  /* We will retire the oldest key if there are 2 or more active keys */
3012  status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_ACTIVE, &key_count, zone_id);
3013  if (status != 0) {
3014  printf("Error: failed to count active keys\n");
3015  db_disconnect(lock_fd);
3016  StrFree(datetime);
3017  return status;
3018  }
3019 
3020  /* If there are not at least 2 active keys then quit */
3021  if (key_count < 2) {
3022  /* Count retired keys to work out if this is a new zone */
3023  status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_RETIRE, &retired_count, zone_id);
3024  if (status != 0) {
3025  printf("Error: failed to count retired keys\n");
3026  db_disconnect(lock_fd);
3027  StrFree(datetime);
3028  return status;
3029  }
3030 
3031  db_disconnect(lock_fd);
3032  StrFree(datetime);
3033  /* Cleanup and print an error message... */
3034  if (retired_count != 0) {
3035  printf("Error: retiring a key would leave no active keys on zone, skipping...\n");
3036  return -1;
3037  } else {
3038  /* ...Unless this looks like a new zone, in which case poke
3039  the enforcerd*/
3040  if (notify_flag == 1) {
3041  if (restart_enforcerd() != 0) {
3042  fprintf(stderr, "Could not HUP ods-enforcerd\n");
3043  } else {
3044  fprintf(stdout, "Performed a HUP ods-enforcerd\n");
3045  }
3046  } else {
3047  fprintf(stdout, "No HUP ods-enforcerd was performed as the '--no-notify' flag was specified.\n");
3048  fprintf(stdout, "Warning: The enforcer must be manually notified or the changes will not take full effect until the next scheduled enforcer run.\n");
3049  }
3050  return 0;
3051  }
3052  }
3053 
3054  status = RetireOldKey(zone_id, policy_id, datetime);
3055 
3056  /* Let them know that it seemed to work */
3057  if (status == 0) {
3058  printf("Old key retired\n");
3059  } else {
3060  printf("Old key NOT retired\n");
3061  }
3062  } else {
3063  printf("Old key NOT retired\n");
3064  }
3065  }
3066 
3067  if (notify_flag == 1) {
3068  if (restart_enforcerd() != 0) {
3069  fprintf(stderr, "Could not HUP ods-enforcerd\n");
3070  } else {
3071  fprintf(stdout, "Performed a HUP ods-enforcerd\n");
3072  }
3073  } else {
3074  fprintf(stdout, "No HUP ods-enforcerd was performed as the '--no-notify' flag was specified.\n");
3075  fprintf(stdout, "Warning: The enforcer must be manually notified or the changes will not take full effect until the next scheduled enforcer run.\n");
3076  }
3077 
3078  /* Release sqlite lock file (if we have it) */
3079  db_disconnect(lock_fd);
3080 
3081  DbDisconnect(dbhandle);
3082 
3083  StrFree(datetime);
3084 
3085  return status;
3086 }
3087 
3088 /*
3089  * import a key into the ksm and set its values as specified
3090  */
3091  int
3093 {
3094  int status = 0;
3095 
3096  /* some strings to hold upper case versions of arguments */
3097  char* case_keytype = NULL; /* KSK or ZSK */
3098  char* case_algorithm = NULL; /* RSASHA1 or RSASHA1-NSEC3-SHA1 (5 or 7) */
3099  char* case_state = NULL; /* GENERATE, PUBLISH, READY, ACTIVE or RETIRE */
3100 
3101  int repo_id = -1;
3102  int zone_id = -1;
3103  int policy_id = -1;
3104  int cka_id_exists = -1; /* do we already have this id in the HSM */
3105  int keytype_id = -1;
3106  int size_int = -1;
3107  int algo_id = -1;
3108  int state_id = -1;
3109  char form_time[KSM_TIME_LENGTH]; /* YYYY-MM-DD HH:MM:SS + NULL Time after we reformat it */
3110  char form_opt_time[KSM_TIME_LENGTH]; /* Opt_time after we reformat it */
3111 
3112  DB_ID keypair_id = 0; /* This will be set when we enter the keypair */
3113  DB_ID ignore = 0; /* This will be set when we enter the dnsseckey */
3114 
3115  struct tm datetime; /* Used for getting the date/time */
3116 
3117  int fix_time = 0; /* Will we be setting the retire time? */
3118 
3119  /* Database connection details */
3120  DB_HANDLE dbhandle;
3121  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
3122 
3123  DB_RESULT result; /* Result of parameter query */
3124  KSM_PARAMETER data; /* Parameter information */
3125 
3126  int user_certain; /* Continue ? */
3127 
3128  hsm_key_t *key = NULL;
3129 
3130  /* Chech that we got all arguments. */
3131 
3132  if (o_cka_id == NULL) {
3133  printf("Error: please specify a CKA_ID with the --cka_id <CKA_ID>\n");
3134  return(1);
3135  }
3136  if (o_repository == NULL) {
3137  printf("Error: please specify a repository with the --repository <repository>\n");
3138  return(1);
3139  }
3140  if (o_zone == NULL) {
3141  printf("Error: please specify a zone with the --zone <zone>\n");
3142  return(1);
3143  }
3144  if (o_size == NULL) {
3145  printf("Error: please specify the number of bits with the --bits <size>\n");
3146  return(1);
3147  }
3148  if (o_algo == NULL) {
3149  printf("Error: please specify the algorithm with the --algorithm <algorithm>\n");
3150  return(1);
3151  }
3152  if (o_keystate == NULL) {
3153  printf("Error: please specify the state with the --keystate <state>\n");
3154  return(1);
3155  }
3156  if (o_keytype == NULL) {
3157  printf("Error: please specify a keytype, KSK or ZSK, with the --keytype <type>\n");
3158  return(1);
3159  }
3160  if (o_time == NULL) {
3161  printf("Error: please specify the time of when the key entered the given state with the --time <time>\n");
3162  return(1);
3163  }
3164 
3165  /* Check the key does not exist in the specified HSM */
3166  status = hsm_open(config, hsm_prompt_pin);
3167  if (status) {
3168  hsm_print_error(NULL);
3169  return(1);
3170  }
3171  key = hsm_find_key_by_id(NULL, o_cka_id);
3172  hsm_close();
3173  if (!key) {
3174  if(check_repository_flag){
3175  fprintf(stderr, "Error: No key with the CKA_ID %-33s exists in the repository %s. When the option [--check-repository] is used the key MUST exist in the repository for the key to be imported. \n", o_cka_id,o_repository);
3176  return(1);
3177  }else{
3178  fprintf(stdout, "Warning: No key with the CKA_ID %-33s exists in the repository %s. The key will be imported into the database anyway. \n", o_cka_id,o_repository);
3179  }
3180  }else{
3181  hsm_key_free(key);
3182  }
3183 
3184  /* try to connect to the database */
3185  status = db_connect(&dbhandle, &lock_fd, 1);
3186  if (status != 0) {
3187  printf("Failed to connect to database\n");
3188  db_disconnect(lock_fd);
3189  return(1);
3190  }
3191 
3192  /* check that the repository exists */
3193  status = KsmSmIdFromName(o_repository, &repo_id);
3194  if (status != 0) {
3195  printf("Error: unable to find a repository named \"%s\" in database\n", o_repository);
3196  db_disconnect(lock_fd);
3197  return status;
3198  }
3199 
3200  /* check that the zone name is valid and use it to get some ids */
3201  status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id);
3202  if (status != 0) {
3203  /* Try again with td */
3204  StrAppend(&o_zone, ".");
3205  status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id);
3206  if (status != 0) {
3207  printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
3208  db_disconnect(lock_fd);
3209  return(status);
3210  }
3211  }
3212 
3213  /* Check that the cka_id does not exist (in the specified HSM) */
3214  status = (KsmCheckHSMkeyID(repo_id, o_cka_id, &cka_id_exists));
3215  if (status != 0) {
3216  db_disconnect(lock_fd);
3217  return(status);
3218  }
3219  if (cka_id_exists == 1) {
3220  printf("Error: key with CKA_ID \"%s\" already exists in database\n", o_cka_id);
3221  db_disconnect(lock_fd);
3222  return(1);
3223  }
3224 
3225  /* Check the Keytype */
3226  case_keytype = StrStrdup(o_keytype);
3227  (void) StrToUpper(case_keytype);
3228  if (strncmp(case_keytype, "KSK", 3) == 0 || strncmp(o_keytype, "257", 3) == 0) {
3229  keytype_id = 257;
3230  }
3231  else if (strncmp(case_keytype, "ZSK", 3) == 0 || strncmp(o_keytype, "256", 3) == 0) {
3232  keytype_id = 256;
3233  }
3234  else {
3235  printf("Error: Unrecognised keytype %s; should be one of KSK or ZSK\n", o_keytype);
3236 
3237  db_disconnect(lock_fd);
3238  StrFree(case_keytype);
3239  return(1);
3240  }
3241  StrFree(case_keytype);
3242 
3243  /* Check the size is numeric */
3244  if (StrIsDigits(o_size)) {
3245  status = StrStrtoi(o_size, &size_int);
3246  if (status != 0) {
3247  printf("Error: Unable to convert bits \"%s\"; to an integer\n", o_size);
3248  db_disconnect(lock_fd);
3249  return(status);
3250  }
3251  } else {
3252  printf("Error: Bits \"%s\"; should be numeric only\n", o_size);
3253  db_disconnect(lock_fd);
3254  return(1);
3255  }
3256 
3257  /* Check the algorithm */
3258  if (StrIsDigits(o_algo)) {
3259  /* Accept it as-is; The HSM will tell us if the number is not valid */
3260  status = StrStrtoi(o_algo, &algo_id);
3261  } else {
3262  /* Convert name to an id, we get 0 if it is unrecognised */
3263  case_algorithm = StrStrdup(o_algo);
3264  (void) StrToLower(case_algorithm);
3265 
3266  algo_id = KsmKeywordAlgorithmNameToValue(case_algorithm);
3267  StrFree(case_algorithm);
3268  }
3269 
3270  if (status != 0 || algo_id == 0 || hsm_supported_algorithm(algo_id) != 0) {
3271  printf("Error: Key algorithm %s not supported; try one of RSASHA1, RSASHA1-NSEC3-SHA1 or RSASHA256\n", o_algo);
3272  db_disconnect(lock_fd);
3273  return(status);
3274  }
3275 
3276  /* Check the state */
3277  case_state = StrStrdup(o_keystate);
3278  (void) StrToUpper(case_state);
3279  if (strncmp(case_state, "GENERATE", 8) == 0 || strncmp(o_keystate, "1", 1) == 0) {
3280  state_id = 1;
3281  }
3282  else if (strncmp(case_state, "PUBLISH", 7) == 0 || strncmp(o_keystate, "2", 1) == 0) {
3283  state_id = 2;
3284  }
3285  else if (strncmp(case_state, "READY", 5) == 0 || strncmp(o_keystate, "3", 1) == 0) {
3286  state_id = 3;
3287  }
3288  else if (strncmp(case_state, "ACTIVE", 6) == 0 || strncmp(o_keystate, "4", 1) == 0) {
3289  state_id = 4;
3290  }
3291  else if (strncmp(case_state, "RETIRE", 6) == 0 || strncmp(o_keystate, "5", 1) == 0) {
3292  state_id = 5;
3293  }
3294  else {
3295  printf("Error: Unrecognised state %s; should be one of GENERATE, PUBLISH, READY, ACTIVE or RETIRE\n", o_keystate);
3296 
3297  db_disconnect(lock_fd);
3298  StrFree(case_state);
3299  return(1);
3300  }
3301  StrFree(case_state);
3302 
3303  /* Check, and convert, the time(s) */
3304  status = DtGeneral(o_time, &datetime);
3305  if (status != 0) {
3306  printf("Error: unable to convert \"%s\" into a date\n", o_time);
3307  date_help();
3308 
3309  db_disconnect(lock_fd);
3310  return(status);
3311  }
3312  else {
3313  snprintf(form_time, KSM_TIME_LENGTH, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
3314  datetime.tm_year + 1900, datetime.tm_mon + 1, datetime.tm_mday,
3315  datetime.tm_hour, datetime.tm_min, datetime.tm_sec);
3316  }
3317 
3318  if (o_retire != NULL) {
3319  /* can only specify a retire time if the key is being inserted in the active state */
3320  if (state_id != KSM_STATE_ACTIVE) {
3321  printf("Error: unable to specify retire time for a key in state \"%s\"\n", o_keystate);
3322  db_disconnect(lock_fd);
3323  return(status);
3324  }
3325 
3326  status = DtGeneral(o_retire, &datetime);
3327  if (status != 0) {
3328  printf("Error: unable to convert retire time \"%s\" into a date\n", o_retire);
3329  date_help();
3330 
3331  db_disconnect(lock_fd);
3332  return(status);
3333  }
3334  else {
3335  snprintf(form_opt_time, KSM_TIME_LENGTH, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
3336  datetime.tm_year + 1900, datetime.tm_mon + 1, datetime.tm_mday,
3337  datetime.tm_hour, datetime.tm_min, datetime.tm_sec);
3338  fix_time = 1;
3339  }
3340  } else {
3341  form_opt_time[0] = '\0';
3342  }
3343 
3344  /* Find out if this zone has any others on a "shared keys" policy and warn */
3345  status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
3346  if (status != 0) {
3347  db_disconnect(lock_fd);
3348  return(status);
3349  }
3350  status = KsmParameter(result, &data);
3351  if (status != 0) {
3352  db_disconnect(lock_fd);
3353  return(status);
3354  }
3355  KsmParameterEnd(result);
3356 
3357  /* Warn and confirm if this will roll more than one zone */
3358  if (data.value == 1) {
3359  printf("*WARNING* This zone shares keys with others, the key will be added to all; are you sure? [y/N] ");
3360 
3361  user_certain = getchar();
3362  if (user_certain != 'y' && user_certain != 'Y') {
3363  printf("Okay, quitting...\n");
3364  db_disconnect(lock_fd);
3365  exit(0);
3366  }
3367  }
3368 
3369  /* create basic keypair */
3370  status = KsmImportKeyPair(policy_id, o_cka_id, repo_id, size_int, algo_id, state_id, form_time, fix_time, &keypair_id);
3371  if (status != 0) {
3372  printf("Error: couldn't import key\n");
3373  db_disconnect(lock_fd);
3374  return(status);
3375  }
3376 
3377  /* allocate key to zone(s) */
3378  /* TODO might not need this any more */
3379 /* if (data.value == 1) {
3380  status = KsmDnssecKeyCreateOnPolicy(policy_id, (int) keypair_id, keytype_id);
3381  } else {*/
3382  status = KsmDnssecKeyCreate(zone_id, (int) keypair_id, keytype_id, state_id, form_time, form_opt_time, &ignore);
3383 
3384  if (status != 0) {
3385  printf("Error: couldn't allocate key to zone(s)\n");
3386  db_disconnect(lock_fd);
3387  return(status);
3388  }
3389 
3390  printf("Key imported into zone(s)\n");
3391 
3392  /* Release sqlite lock file (if we have it) */
3393  db_disconnect(lock_fd);
3394 
3395  DbDisconnect(dbhandle);
3396  return 0;
3397 }
3398 
3399 /*
3400  * make a backup of a sqlite database
3401  */
3402  int
3404 {
3405  /* Database details */
3406  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
3407 
3408  /* what we will read from the file */
3409  char *dbschema = NULL;
3410  char *host = NULL;
3411  char *port = NULL;
3412  char *user = NULL;
3413  char *password = NULL;
3414 
3415  int status;
3416 
3417  char* backup_filename = NULL;
3418  char* lock_filename;
3419 
3420  char *path = getenv("PWD");
3421 
3422  if (DbFlavour() != SQLITE_DB) {
3423  printf("Sorry, currently this utility can only backup a sqlite database file\n");
3424  return -1;
3425  }
3426 
3427  /* Read the database details out of conf.xml */
3428  status = get_db_details(&dbschema, &host, &port, &user, &password);
3429  if (status != 0) {
3430  StrFree(host);
3431  StrFree(port);
3432  StrFree(dbschema);
3433  StrFree(user);
3434  StrFree(password);
3435  return(status);
3436  }
3437 
3438  /* set up DB lock */
3439  lock_filename = NULL;
3440  StrAppend(&lock_filename, dbschema);
3441  StrAppend(&lock_filename, ".our_lock");
3442 
3443  lock_fd = fopen(lock_filename, "w");
3444  status = get_lite_lock(lock_filename, lock_fd);
3445  if (status != 0) {
3446  printf("Error getting db lock\n");
3447  if (lock_fd != NULL) {
3448  fclose(lock_fd);
3449  }
3450  StrFree(host);
3451  StrFree(port);
3452  StrFree(dbschema);
3453  StrFree(user);
3454  StrFree(password);
3455  StrFree(lock_filename);
3456  return(1);
3457  }
3458  StrFree(lock_filename);
3459 
3460  /* Work out what file to output */
3461  if (o_output == NULL) {
3462  StrAppend(&backup_filename, dbschema);
3463  StrAppend(&backup_filename, ".backup");
3464  } else if (*o_output != '/') {
3465  StrAppend(&backup_filename, path);
3466  StrAppend(&backup_filename, "/");
3467  StrAppend(&backup_filename, o_output);
3468  } else {
3469  StrAppend(&backup_filename, o_output);
3470  }
3471 
3472  status = backup_file(dbschema, backup_filename);
3473 
3474  StrFree(backup_filename);
3475 
3476  /* Cleanup */
3477  StrFree(host);
3478  StrFree(port);
3479  StrFree(dbschema);
3480  StrFree(user);
3481  StrFree(password);
3482 
3483  /* Release sqlite lock */
3484  db_disconnect(lock_fd);
3485 
3486  return status;
3487 }
3488 
3489 /*
3490  * Delete any policies with no zones
3491  */
3492  int
3494 {
3495  int status = 0;
3496 
3497  char* kasp_filename = NULL;
3498  char* zonelist_filename = NULL;
3499  char* backup_filename = NULL;
3500 
3501  DB_HANDLE dbhandle;
3502  FILE* lock_fd = NULL;
3503  KSM_POLICY *policy;
3504  DB_RESULT result; /* Result set from policy query */
3505  DB_RESULT result2; /* Result set from zone count query */
3506  char sql[KSM_SQL_SIZE];
3507  int size = -1;
3508  char* sql2;
3509 
3510  FILE *test;
3511  int zone_count = -1;
3512 
3513  xmlDocPtr doc = NULL;
3514 
3515  int user_certain;
3516  printf("*WARNING* This feature is experimental and has not been fully tested; are you sure? [y/N] ");
3517 
3518  user_certain = getchar();
3519  if (user_certain != 'y' && user_certain != 'Y') {
3520  printf("Okay, quitting...\n");
3521  exit(0);
3522  }
3523 
3524  /* Read the conf.xml file to learn the location of the kasp.xml file. */
3525  status = read_filenames(&zonelist_filename, &kasp_filename);
3526  if (status != 0) {
3527  printf("Failed to read conf.xml\n");
3528  db_disconnect(lock_fd);
3529  return(1);
3530  }
3531 
3532  /* Backup the current kasp.xml */
3533  StrAppend(&backup_filename, kasp_filename);
3534  StrAppend(&backup_filename, ".backup");
3535  status = backup_file(kasp_filename, backup_filename);
3536  StrFree(backup_filename);
3537  if (status != 0) {
3538  StrFree(kasp_filename);
3539  StrFree(zonelist_filename);
3540  db_disconnect(lock_fd);
3541  return(status);
3542  }
3543 
3544  /* Check that we will be able to make the changes to kasp.xml */
3545  if ((test = fopen(kasp_filename, "ab"))==NULL) {
3546  printf("Cannot open kasp.xml for writing: %s\n", strerror(errno));
3547  StrFree(kasp_filename);
3548  StrFree(zonelist_filename);
3549  return(-1);
3550  } else {
3551  fclose(test);
3552  }
3553 
3554  /* try to connect to the database */
3555  status = db_connect(&dbhandle, &lock_fd, 1);
3556  if (status != 0) {
3557  printf("Failed to connect to database\n");
3558  db_disconnect(lock_fd);
3559  StrFree(kasp_filename);
3560  StrFree(zonelist_filename);
3561  return(1);
3562  }
3563 
3564  /* Start a transaction */
3565  status = DbBeginTransaction();
3566  if (status != 0) {
3567  /* Something went wrong */
3568 
3570  db_disconnect(lock_fd);
3571  StrFree(kasp_filename);
3572  StrFree(zonelist_filename);
3573  return status;
3574  }
3575 
3576  /* Loop through each policy */
3577  policy = KsmPolicyAlloc();
3578  if (policy == NULL) {
3579  printf("Malloc for policy struct failed\n");
3580  exit(1);
3581  }
3582 
3583  /* Read all policies */
3584  status = KsmPolicyInit(&result, NULL);
3585  if (status == 0) {
3586  /* get the first policy */
3587  status = KsmPolicy(result, policy);
3588  while (status == 0) {
3589  /* Count zones on this policy */
3590  status = KsmZoneCountInit(&result2, policy->id);
3591  if (status == 0) {
3592  status = KsmZoneCount(result2, &zone_count);
3593  }
3594  DbFreeResult(result2);
3595 
3596  if (status == 0) {
3597  /* Only carry on if we have no zones */
3598  if (zone_count == 0) {
3599  printf("No zones on policy %s; purging...\n", policy->name);
3600  /* set keystate to 6 across the board */
3601  size = snprintf(sql, KSM_SQL_SIZE, "update dnsseckeys set state = %d where keypair_id in (select id from keypairs where policy_id = %d)", KSM_STATE_DEAD, policy->id);
3602 
3603  /* Quick check that we didn't run out of space */
3604  if (size < 0 || size >= KSM_SQL_SIZE) {
3605  printf("Couldn't construct SQL to kill orphaned keys\n");
3606  db_disconnect(lock_fd);
3607  KsmPolicyFree(policy);
3608  StrFree(kasp_filename);
3609  StrFree(zonelist_filename);
3610  return -1;
3611  }
3612 
3613  status = DbExecuteSqlNoResult(DbHandle(), sql);
3614 
3615  /* Report any errors */
3616  if (status != 0) {
3617  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
3618  db_disconnect(lock_fd);
3619  KsmPolicyFree(policy);
3620  StrFree(kasp_filename);
3621  StrFree(zonelist_filename);
3622  return status;
3623  }
3624 
3625  /* call purge keys on that policy (all zones) */
3626  status = PurgeKeys(-1, policy->id);
3627  if (status != 0) {
3628  printf("Key purge failed for policy %s\n", policy->name);
3629  db_disconnect(lock_fd);
3630  KsmPolicyFree(policy);
3631  StrFree(kasp_filename);
3632  StrFree(zonelist_filename);
3633  return status;
3634  }
3635 
3636  /* Delete the policy from DB */
3637  sql2 = DdsInit("parameters_policies");
3638  DdsConditionInt(&sql2, "policy_id", DQS_COMPARE_EQ, policy->id, 0);
3639  DdsEnd(&sql2);
3640  status = DbExecuteSqlNoResult(DbHandle(), sql2);
3641  DdsFree(sql2);
3642 
3643  if (status != 0)
3644  {
3645  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
3646  db_disconnect(lock_fd);
3647  KsmPolicyFree(policy);
3648  StrFree(kasp_filename);
3649  StrFree(zonelist_filename);
3650  return status;
3651  }
3652 
3653  sql2 = DdsInit("policies");
3654  DdsConditionInt(&sql2, "id", DQS_COMPARE_EQ, policy->id, 0);
3655  DdsEnd(&sql2);
3656  status = DbExecuteSqlNoResult(DbHandle(), sql2);
3657  DdsFree(sql2);
3658 
3659  if (status != 0)
3660  {
3661  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
3662  db_disconnect(lock_fd);
3663  KsmPolicyFree(policy);
3664  StrFree(kasp_filename);
3665  StrFree(zonelist_filename);
3666  return status;
3667  }
3668 
3669  /* Delete the policy from the XML */
3670  /* Read the file and delete our policy node(s) in memory */
3671  doc = del_policy_node(kasp_filename, policy->name);
3672  if (doc == NULL) {
3673  db_disconnect(lock_fd);
3674  KsmPolicyFree(policy);
3675  StrFree(kasp_filename);
3676  StrFree(zonelist_filename);
3677  return(1);
3678  }
3679 
3680  /* Save our new file over the old, TODO should we validate it first? */
3681  status = xmlSaveFormatFile(kasp_filename, doc, 1);
3682  xmlFreeDoc(doc);
3683  if (status == -1) {
3684  printf("Could not save %s\n", kasp_filename);
3685  StrFree(kasp_filename);
3686  StrFree(zonelist_filename);
3687  db_disconnect(lock_fd);
3688  KsmPolicyFree(policy);
3689  return(1);
3690  }
3691 
3692  }
3693  } else {
3694  printf("Couldn't count zones on policy; quitting...\n");
3695  db_disconnect(lock_fd);
3696  exit(1);
3697  }
3698 
3699  /* get next policy */
3700  status = KsmPolicy(result, policy);
3701  }
3702  /* Reset EOF */
3703  if (status == -1) {
3704  status = 0;
3705  }
3706  DbFreeResult(result);
3707  }
3708 
3709  /* Commit or Rollback */
3710  if (status == 0) {
3711  /* Everything worked by the looks of it */
3712  DbCommit();
3713  } else {
3714  /* Whatever happened, it was not good */
3715  DbRollback();
3716  }
3717 
3718  StrFree(kasp_filename);
3719  StrFree(zonelist_filename);
3720  db_disconnect(lock_fd);
3721  KsmPolicyFree(policy);
3722  return status;
3723 }
3724 
3725 /*
3726  * Send command to ods-control
3727  */
3728  int
3729 cmd_control(char *command)
3730 {
3731  int status = 0;
3732  char* ods_control_cmd = NULL;
3733  char* ptr = command;
3734 
3735  /* We need the command in lower case */
3736  if (ptr) {
3737  while (*ptr) {
3738  *ptr = tolower((int) *ptr);
3739  ++ptr;
3740  }
3741  }
3742 
3743  /* Call "ods-control enforcer COMMAND" */
3744  StrAppend(&ods_control_cmd, ODS_EN_CONTROL);
3745  StrAppend(&ods_control_cmd, command);
3746 
3747  status = system(ods_control_cmd);
3748  if (status != 0)
3749  {
3750  fprintf(stderr, "Couldn't run %s\n", ods_control_cmd);
3751  }
3752 
3753  StrFree(ods_control_cmd);
3754 
3755  return(status);
3756 }
3757 
3758 /*
3759  * Fairly basic main, just pass most things through to their handlers
3760  */
3761  int
3762 main (int argc, char *argv[])
3763 {
3764  int result;
3765  int ch;
3766  char* case_command = NULL;
3767  char* case_verb = NULL;
3768 
3769  int option_index = 0;
3770  static struct option long_options[] =
3771  {
3772  {"all", no_argument, 0, 'a'},
3773  {"auto-accept", no_argument, 0, 'A'},
3774  {"bits", required_argument, 0, 'b'},
3775  {"config", required_argument, 0, 'c'},
3776  {"check-repository", no_argument, 0, 'C'},
3777  {"ds", no_argument, 0, 'd'},
3778  {"keystate", required_argument, 0, 'e'},
3779  {"no-retire", no_argument, 0, 'f'},
3780  {"force", no_argument, 0, 'F'},
3781  {"algorithm", required_argument, 0, 'g'},
3782  {"help", no_argument, 0, 'h'},
3783  {"input", required_argument, 0, 'i'},
3784  {"in-type", required_argument, 0, 'j'},
3785  {"cka_id", required_argument, 0, 'k'},
3786  {"no-notify", no_argument, 0, 'l'},
3787  {"no-xml", no_argument, 0, 'm'},
3788  {"no-hsm", no_argument, 0, 'M'},
3789  {"interval", required_argument, 0, 'n'},
3790  {"output", required_argument, 0, 'o'},
3791  {"policy", required_argument, 0, 'p'},
3792  {"out-type", required_argument, 0, 'q'},
3793  {"repository", required_argument, 0, 'r'},
3794  {"signerconf", required_argument, 0, 's'},
3795  {"keytype", required_argument, 0, 't'},
3796  {"time", required_argument, 0, 'w'},
3797  {"verbose", no_argument, 0, 'v'},
3798  {"version", no_argument, 0, 'V'},
3799  {"keytag", required_argument, 0, 'x'},
3800  {"retire", required_argument, 0, 'y'},
3801  {"zone", required_argument, 0, 'z'},
3802  {"zonetotal", required_argument, 0, 'Z'},
3803  {0,0,0,0}
3804  };
3805 
3806  progname = argv[0];
3807 
3808  while ((ch = getopt_long(argc, argv, "aAb:Cc:de:fFg:hi:j:k:mMln:o:p:q:r:s:t:vVw:x:y:z:Z:", long_options, &option_index)) != -1) {
3809  switch (ch) {
3810  case 'a':
3811  all_flag = 1;
3812  break;
3813  case 'A':
3814  auto_accept_flag = 1;
3815  break;
3816  case 'b':
3817  o_size = StrStrdup(optarg);
3818  break;
3819  case 'c':
3820  config = StrStrdup(optarg);
3821  break;
3822  case 'C':
3823  check_repository_flag = 1;
3824  break;
3825  case 'd':
3826  ds_flag = 1;
3827  break;
3828  case 'e':
3830  break;
3831  case 'f':
3832  retire_flag = 0;
3833  break;
3834  case 'F':
3835  force_flag = 1;
3836  break;
3837  case 'g':
3838  o_algo = StrStrdup(optarg);
3839  break;
3840  case 'h':
3841  usage();
3842  states_help();
3843  types_help();
3844  date_help();
3845  exit(0);
3846  break;
3847  case 'i':
3849  break;
3850  case 'j':
3852  break;
3853  case 'k':
3855  break;
3856  case 'l':
3857  notify_flag = 0;
3858  break;
3859  case 'm':
3860  xml_flag = 0;
3861  break;
3862  case 'M':
3863  hsm_flag = 0;
3864  break;
3865  case 'n':
3867  break;
3868  case 'o':
3870  break;
3871  case 'p':
3873  break;
3874  case 'q':
3876  break;
3877  case 'r':
3879  break;
3880  case 's':
3882  break;
3883  case 't':
3885  break;
3886  case 'V':
3887  printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
3888  exit(0);
3889  break;
3890  case 'v':
3891  verbose_flag = 1;
3892  break;
3893  case 'w':
3894  o_time = StrStrdup(optarg);
3895  break;
3896  case 'x':
3898  break;
3899  case 'y':
3901  break;
3902  case 'z':
3903  /* Remove trailing dot here */
3904  o_zone = StrStrdup(optarg);
3905  if (strlen(o_zone) > 1 && o_zone[strlen(o_zone)-1] == '.') {
3906  o_zone[strlen(o_zone)-1] = '\0';
3907  td_flag = 1;
3908  }
3909 
3910  break;
3911  case 'Z':
3913  break;
3914  default:
3915  usage();
3916  exit(1);
3917  }
3918  }
3919  argc -= optind;
3920  argv += optind;
3921 
3922  if (!argc) {
3923  usage();
3924  exit(1);
3925  }
3926 
3927 
3928  /*(void) KsmInit();*/
3929  MsgInit();
3932 
3933  /* command should be one of SETUP UPDATE ZONE REPOSITORY POLICY KEY BACKUP or ROLLOVER */
3934  case_command = StrStrdup(argv[0]);
3935  (void) StrToUpper(case_command);
3936  if (argc > 1) {
3937  /* verb should be stuff like ADD, LIST, DELETE, etc */
3938  case_verb = StrStrdup(argv[1]);
3939  (void) StrToUpper(case_verb);
3940  } else {
3941  case_verb = StrStrdup("NULL");
3942  }
3943 
3944 
3945  if (!strncmp(case_command, "SETUP", 5)) {
3946  argc --;
3947  argv ++;
3948  result = cmd_setup();
3949  } else if (!strncmp(case_command, "UPDATE", 6)) {
3950  argc --;
3951  argv ++;
3952  result = cmd_update(case_verb);
3953  } else if (!strncmp(case_command, "START", 5) ||
3954  !strncmp(case_command, "STOP", 4) ||
3955  !strncmp(case_command, "NOTIFY", 6)) {
3956  argc --;
3957  argv ++;
3958  result = cmd_control(case_command);
3959  } else if (!strncmp(case_command, "ZONE", 4) && strlen(case_command) == 4) {
3960  argc --; argc --;
3961  argv ++; argv ++;
3962 
3963  /* verb should be add, delete or list */
3964  if (!strncmp(case_verb, "ADD", 3)) {
3965  result = cmd_addzone();
3966  } else if (!strncmp(case_verb, "DELETE", 6)) {
3967  result = cmd_delzone();
3968  } else if (!strncmp(case_verb, "LIST", 4)) {
3969  result = cmd_listzone();
3970  } else {
3971  printf("Unknown command: zone %s\n", case_verb);
3972  usage_zone();
3973  result = -1;
3974  }
3975  } else if (!strncmp(case_command, "REPOSITORY", 10)) {
3976  argc --; argc --;
3977  argv ++; argv ++;
3978  /* verb should be list */
3979  if (!strncmp(case_verb, "LIST", 4)) {
3980  result = cmd_listrepo();
3981  } else {
3982  printf("Unknown command: repository %s\n", case_verb);
3983  usage_repo();
3984  result = -1;
3985  }
3986  } else if (!strncmp(case_command, "POLICY", 6)) {
3987  argc --; argc --;
3988  argv ++; argv ++;
3989  /* verb should be export, import, list or purge */
3990  if (!strncmp(case_verb, "EXPORT", 6)) {
3991  result = cmd_exportpolicy();
3992  } else if (!strncmp(case_verb, "IMPORT", 6)) {
3993  result = cmd_update("KASP");
3994  } else if (!strncmp(case_verb, "LIST", 4)) {
3995  result = cmd_listpolicy();
3996  } else if (!strncmp(case_verb, "PURGE", 5)) {
3997  result = cmd_purgepolicy();
3998  } else {
3999  printf("Unknown command: policy %s\n", case_verb);
4000  usage_policy();
4001  result = -1;
4002  }
4003  } else if (!strncmp(case_command, "KEY", 3)) {
4004  argc --; argc --;
4005  argv ++; argv ++;
4006  /* verb should be list, export import, rollover, purge, generate, ksk-retire or ds-seen */
4007  if (!strncmp(case_verb, "LIST", 4)) {
4008  result = cmd_listkeys();
4009  }
4010  else if (!strncmp(case_verb, "EXPORT", 6)) {
4011  result = cmd_exportkeys();
4012  }
4013  else if (!strncmp(case_verb, "IMPORT", 6)) {
4014  result = cmd_import();
4015  }
4016  else if (!strncmp(case_verb, "ROLLOVER", 8)) {
4017  /* Check that we have either a key type or the all flag */
4018  if (all_flag == 0 && o_keytype == NULL) {
4019  printf("Please specify either a keytype, KSK or ZSK, with the --keytype <type> option or use the --all option\n");
4020  usage_keyroll();
4021  result = -1;
4022  }
4023  else {
4024  /* Are we rolling a zone or a whole policy? */
4025  if (o_zone != NULL && o_policy == NULL) {
4026  result = cmd_rollzone();
4027  }
4028  else if (o_zone == NULL && o_policy != NULL) {
4029  result = cmd_rollpolicy();
4030  }
4031  else {
4032  printf("Please provide either a zone OR a policy to rollover\n");
4033  usage_keyroll();
4034  result = -1;
4035  }
4036  }
4037  }
4038  else if (!strncmp(case_verb, "PURGE", 5)) {
4039  if ((o_zone != NULL && o_policy == NULL) ||
4040  (o_zone == NULL && o_policy != NULL)){
4041  result = cmd_keypurge();
4042  }
4043  else {
4044  printf("Please provide either a zone OR a policy to key purge\n");
4045  usage_keypurge();
4046  result = -1;
4047  }
4048  }
4049  else if (!strncmp(case_verb, "GENERATE", 8)) {
4050  result = cmd_genkeys();
4051  }
4052  else if (!strncmp(case_verb, "KSK-RETIRE", 10)) {
4053  result = cmd_kskretire();
4054  }
4055  else if (!strncmp(case_verb, "DS-SEEN", 7)) {
4056  result = cmd_dsseen();
4057  } else if (!strncmp(case_verb, "DELETE", 6)) {
4058  result = cmd_delkey();
4059  } else {
4060  printf("Unknown command: key %s\n", case_verb);
4061  usage_key();
4062  result = -1;
4063  }
4064  } else if (!strncmp(case_command, "BACKUP", 6)) {
4065  argc --; argc --;
4066  argv ++; argv ++;
4067  /* verb should be done, prepare, commit, rollback or list */
4068  if (!strncmp(case_verb, "DONE", 4) ||
4069  !strncmp(case_verb, "PREPARE", 7) ||
4070  !strncmp(case_verb, "COMMIT", 6) ||
4071  !strncmp(case_verb, "ROLLBACK", 8)) {
4072  result = cmd_backup(case_verb);
4073  }
4074  else if (!strncmp(case_verb, "LIST", 4)) {
4075  result = cmd_listbackups();
4076  } else {
4077  printf("Unknown command: backup %s\n", case_verb);
4078  usage_backup();
4079  result = -1;
4080  }
4081  } else if (!strncmp(case_command, "ROLLOVER", 8)) {
4082  argc --; argc --;
4083  argv ++; argv ++;
4084  if (!strncmp(case_verb, "LIST", 4)) {
4085  result = cmd_listrolls();
4086  } else {
4087  printf("Unknown command: rollover %s\n", case_verb);
4088  usage_rollover();
4089  result = -1;
4090  }
4091  } else if (!strncmp(case_command, "DATABASE", 8)) {
4092  argc --; argc --;
4093  argv ++; argv ++;
4094  /* verb should be backup */
4095  if (!strncmp(case_verb, "BACKUP", 6)) {
4096  result = cmd_dbbackup();
4097  } else {
4098  printf("Unknown command: database %s\n", case_verb);
4099  usage_database();
4100  result = -1;
4101  }
4102  } else if (!strncmp(case_command, "ZONELIST", 8)) {
4103  argc --; argc --;
4104  argv ++; argv ++;
4105  /* verb should be import or export */
4106  if (!strncmp(case_verb, "EXPORT", 6)) {
4107  result = cmd_exportzonelist();
4108  }
4109  else if (!strncmp(case_verb, "IMPORT", 6)) {
4110  result = cmd_update("ZONELIST");
4111  } else {
4112  printf("Unknown command: zonelist %s\n", case_verb);
4113  usage_zonelist2();
4114  result = -1;
4115  }
4116  } else {
4117  printf("Unknown command: %s\n", argv[0]);
4118  usage();
4119  result = -1;
4120  }
4121 
4122  StrFree(case_command);
4123  StrFree(case_verb);
4124 
4125  /*(void) hsm_close();*/
4126  /*if (config) free(config);*/
4127 
4128  xmlCleanupParser();
4129  xmlCleanupGlobals();
4130  xmlCleanupThreads();
4131 
4132  exit(result);
4133 }
4134 
4135 
4136 /*
4137  * Given a conf.xml location connect to the database contained within it
4138  *
4139  * A lock will be taken out on the DB if it is SQLite; so it is important to release it
4140  * in the calling Fn when we are done with it.
4141  * If backup is set to 1 then a backup will be made (of a sqlite DB file)
4142  *
4143  * Returns 0 if a connection was made.
4144  * 1 if a connection could not be made.
4145  * -1 if any of the config files could not be read/parsed
4146  *
4147  */
4148  int
4149 db_connect(DB_HANDLE *dbhandle, FILE** lock_fd, int backup)
4150 {
4151  /* what we will read from the file */
4152  char *dbschema = NULL;
4153  char *host = NULL;
4154  char *port = NULL;
4155  char *user = NULL;
4156  char *password = NULL;
4157 
4158  int status;
4159 
4160  char* backup_filename = NULL;
4161  char* lock_filename;
4162 
4163  /* Read the database details out of conf.xml */
4164  status = get_db_details(&dbschema, &host, &port, &user, &password);
4165  if (status != 0) {
4166  StrFree(host);
4167  StrFree(port);
4168  StrFree(dbschema);
4169  StrFree(user);
4170  StrFree(password);
4171  return(status);
4172  }
4173 
4174  /* If we are in sqlite mode then take a lock out on a file to
4175  prevent multiple access (not sure that we can be sure that sqlite is
4176  safe for multiple processes to access). */
4177  if (DbFlavour() == SQLITE_DB) {
4178 
4179  /* set up lock filename (it may have changed?) */
4180  if (lock_fd != NULL) {
4181  lock_filename = NULL;
4182  StrAppend(&lock_filename, dbschema);
4183  StrAppend(&lock_filename, ".our_lock");
4184 
4185  *lock_fd = fopen(lock_filename, "w");
4186  status = get_lite_lock(lock_filename, *lock_fd);
4187  if (status != 0) {
4188  printf("Error getting db lock\n");
4189  if (*lock_fd != NULL) {
4190  fclose(*lock_fd);
4191  }
4192  StrFree(host);
4193  StrFree(port);
4194  StrFree(dbschema);
4195  StrFree(user);
4196  StrFree(password);
4197  StrFree(lock_filename);
4198  return(1);
4199  }
4200  StrFree(lock_filename);
4201  }
4202 
4203  /* Make a backup of the sqlite DB */
4204  if (backup == 1) {
4205  StrAppend(&backup_filename, dbschema);
4206  StrAppend(&backup_filename, ".backup");
4207 
4208  status = backup_file(dbschema, backup_filename);
4209 
4210  StrFree(backup_filename);
4211 
4212  if (status == 1) {
4213  if (lock_fd != NULL) {
4214  fclose(*lock_fd);
4215  }
4216  StrFree(host);
4217  StrFree(port);
4218  StrFree(dbschema);
4219  StrFree(user);
4220  StrFree(password);
4221  return(status);
4222  }
4223  }
4224 
4225  }
4226 
4227  /* Finally we can do what we came here to do, connect to the database */
4228  status = DbConnect(dbhandle, dbschema, host, password, user, port);
4229 
4230  /* Cleanup */
4231  StrFree(host);
4232  StrFree(port);
4233  StrFree(dbschema);
4234  StrFree(user);
4235  StrFree(password);
4236 
4237  return(status);
4238 }
4239 
4240 /*
4241  * Release the lock if the DB is SQLite
4242  *
4243  */
4244  void
4245 db_disconnect(FILE* lock_fd)
4246 {
4247  int status = 0;
4248 
4249  if (DbFlavour() == SQLITE_DB) {
4250  if (lock_fd != NULL) {
4251  status = release_lite_lock(lock_fd);
4252  if (status != 0) {
4253  printf("Error releasing db lock");
4254  /*fclose(lock_fd);*/
4255  return;
4256  }
4257  fclose(lock_fd);
4258  }
4259  }
4260  return;
4261 }
4262 
4263 /* To overcome the potential differences in sqlite compile flags assume that it is not
4264  happy with multiple connections.
4265 
4266  The following 2 functions take out a lock and release it
4267  */
4268 
4269 int get_lite_lock(char *lock_filename, FILE* lock_fd)
4270 {
4271  struct flock fl;
4272  struct timeval tv;
4273  int retry = 0;
4274 
4275  if (lock_fd == NULL) {
4276  printf("%s could not be opened\n", lock_filename);
4277  return 1;
4278  }
4279 
4280  memset(&fl, 0, sizeof(struct flock));
4281  fl.l_type = F_WRLCK;
4282  fl.l_whence = SEEK_SET;
4283  fl.l_pid = getpid();
4284 
4285  while (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
4286  if (retry >= 6) {
4287  printf("couldn't get lock on %s; %s\n", lock_filename, strerror(errno));
4288  return 1;
4289  }
4290  if (errno == EACCES || errno == EAGAIN) {
4291  printf("%s already locked, sleep\n", lock_filename);
4292 
4293  /* sleep for 10 seconds TODO make this configurable? */
4294  tv.tv_sec = 10;
4295  tv.tv_usec = 0;
4296  select(0, NULL, NULL, NULL, &tv);
4297 
4298  retry++;
4299 
4300  } else {
4301  printf("couldn't get lock on %s; %s\n", lock_filename, strerror(errno));
4302  return 1;
4303  }
4304  }
4305 
4306  return 0;
4307 
4308 }
4309 
4310 int release_lite_lock(FILE* lock_fd)
4311 {
4312  struct flock fl;
4313 
4314  if (lock_fd == NULL) {
4315  return 1;
4316  }
4317 
4318  memset(&fl, 0, sizeof(struct flock));
4319  fl.l_type = F_UNLCK;
4320  fl.l_whence = SEEK_SET;
4321 
4322  if (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
4323  return 1;
4324  }
4325 
4326  return 0;
4327 }
4328 
4329 /*
4330  * Now we will read the conf.xml file again, but this time we will not validate.
4331  * Instead we just learn the location of the zonelist.xml and kasp.xml files.
4332  */
4333 int read_filenames(char** zone_list_filename, char** kasp_filename)
4334 {
4335  xmlTextReaderPtr reader = NULL;
4336  xmlDocPtr doc = NULL;
4337  xmlXPathContextPtr xpathCtx = NULL;
4338  xmlXPathObjectPtr xpathObj = NULL;
4339  int ret = 0; /* status of the XML parsing */
4340  char* tag_name = NULL;
4341  char* temp_char = NULL;
4342 
4343  xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile";
4344  xmlChar *kaspfile_expr = (unsigned char*) "//Common/PolicyFile";
4345 
4346  /* Start reading the file; we will be looking for "Repository" tags */
4347  reader = xmlNewTextReaderFilename(config);
4348  if (reader != NULL) {
4349  ret = xmlTextReaderRead(reader);
4350  while (ret == 1) {
4351  tag_name = (char*) xmlTextReaderLocalName(reader);
4352  /* Found <Common> */
4353  if (strncmp(tag_name, "Common", 6) == 0
4354  && xmlTextReaderNodeType(reader) == 1) {
4355 
4356  /* Expand this node and get the rest of the info with XPath */
4357  xmlTextReaderExpand(reader);
4358  doc = xmlTextReaderCurrentDoc(reader);
4359  if (doc == NULL) {
4360  printf("Error: can not read Common section\n");
4361  /* Don't return? try to parse the rest of the file? */
4362  ret = xmlTextReaderRead(reader);
4363  continue;
4364  }
4365 
4366  xpathCtx = xmlXPathNewContext(doc);
4367  if(xpathCtx == NULL) {
4368  printf("Error: can not create XPath context for Common section\n");
4369  /* Don't return? try to parse the rest of the file? */
4370  ret = xmlTextReaderRead(reader);
4371  continue;
4372  }
4373 
4374  /* Evaluate xpath expression for ZoneListFile */
4375  xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx);
4376  if(xpathObj == NULL) {
4377  printf("Error: unable to evaluate xpath expression: %s\n", zonelist_expr);
4378  /* Don't return? try to parse the rest of the file? */
4379  ret = xmlTextReaderRead(reader);
4380  continue;
4381  }
4382  *zone_list_filename = NULL;
4383  temp_char = (char*) xmlXPathCastToString(xpathObj);
4384  StrAppend(zone_list_filename, temp_char);
4385  StrFree(temp_char);
4386  xmlXPathFreeObject(xpathObj);
4387  printf("zonelist filename set to %s.\n", *zone_list_filename);
4388 
4389  /* Evaluate xpath expression for KaspFile */
4390  xpathObj = xmlXPathEvalExpression(kaspfile_expr, xpathCtx);
4391  xmlXPathFreeContext(xpathCtx);
4392  if(xpathObj == NULL) {
4393  printf("Error: unable to evaluate xpath expression: %s\n", kaspfile_expr);
4394  /* Don't return? try to parse the rest of the file? */
4395  ret = xmlTextReaderRead(reader);
4396  continue;
4397  }
4398  *kasp_filename = NULL;
4399  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
4400  /*
4401  * Found Something, set it
4402  */
4403  temp_char = (char*) xmlXPathCastToString(xpathObj);
4404  StrAppend(kasp_filename, temp_char);
4405  StrFree(temp_char);
4406  } else {
4407  /*
4408  * Set a default
4409  */
4410  /* XXX this should be parse from the the main config */
4411  StrAppend(kasp_filename, OPENDNSSEC_CONFIG_DIR);
4412  StrAppend(kasp_filename, "/kasp.xml");
4413  }
4414  printf("kasp filename set to %s.\n", *kasp_filename);
4415 
4416  xmlXPathFreeObject(xpathObj);
4417  }
4418  /* Read the next line */
4419  ret = xmlTextReaderRead(reader);
4420 
4421  StrFree(tag_name);
4422  }
4423  xmlFreeTextReader(reader);
4424  if (ret != 0) {
4425  printf("%s : failed to parse\n", config);
4426  return(1);
4427  }
4428  } else {
4429  printf("Unable to open %s\n", config);
4430  return(1);
4431  }
4432  if (doc) {
4433  xmlFreeDoc(doc);
4434  }
4435 
4436  return 0;
4437 }
4438 
4439 /*
4440  * Read the conf.xml file yet again, but this time we will not validate.
4441  * Instead we just extract the RepositoryList into the database.
4442  */
4444 {
4445  int status = 0;
4446  xmlDocPtr doc = NULL;
4447  xmlXPathContextPtr xpathCtx = NULL;
4448  xmlXPathObjectPtr xpathObj = NULL;
4449  xmlNode *curNode;
4450  char* repo_name = NULL;
4451  char* repo_capacity = NULL;
4452  int require_backup = 0;
4453  int i = 0;
4454 
4455  xmlChar *node_expr = (unsigned char*) "//Configuration/RepositoryList/Repository";
4456 
4457  /* Start reading the file; we will be looking for "Repository" tags */
4458  /* Load XML document */
4459  doc = xmlParseFile(config);
4460  if (doc == NULL) {
4461  printf("Unable to open %s\n", config);
4462  return(1);
4463  }
4464 
4465  /* Create xpath evaluation context */
4466  xpathCtx = xmlXPathNewContext(doc);
4467  if(xpathCtx == NULL) {
4468  xmlFreeDoc(doc);
4469  return(1);
4470  }
4471 
4472  /* Evaluate xpath expression */
4473  xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx);
4474  if(xpathObj == NULL) {
4475  xmlXPathFreeContext(xpathCtx);
4476  xmlFreeDoc(doc);
4477  return(1);
4478  }
4479 
4480  if (xpathObj->nodesetval) {
4481  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
4482 
4483  require_backup = 0;
4484  StrAppend(&repo_capacity, "");
4485 
4486  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
4487  repo_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i],
4488  (const xmlChar *)"name");
4489  while (curNode) {
4490  if (xmlStrEqual(curNode->name, (const xmlChar *)"Capacity")) {
4491  repo_capacity = (char *) xmlNodeGetContent(curNode);
4492  }
4493  if (xmlStrEqual(curNode->name, (const xmlChar *)"RequireBackup")) {
4494  require_backup = 1;
4495  }
4496 
4497  curNode = curNode->next;
4498  }
4499 
4500  if (strlen(repo_name) != 0) {
4501  /* Log what we are about to do */
4502  printf("Repository %s found\n", repo_name);
4503  if (strlen(repo_capacity) == 0) {
4504  printf("No Maximum Capacity set.\n");
4505  /*
4506  * We have all the information, update/insert this repository
4507  */
4508  status = KsmImportRepository(repo_name, "0", require_backup);
4509  } else {
4510  printf("Capacity set to %s.\n", repo_capacity);
4511  /*
4512  * We have all the information, update/insert this repository
4513  */
4514  status = KsmImportRepository(repo_name, repo_capacity, require_backup);
4515  }
4516  if (require_backup == 0) {
4517  printf("RequireBackup NOT set; please make sure that you know the potential problems of using keys which are not recoverable\n");
4518  } else {
4519  printf("RequireBackup set.\n");
4520  }
4521 
4522  if (status != 0) {
4523  printf("Error Importing Repository %s", repo_name);
4524  /* Don't return? try to parse the rest of the zones? */
4525  }
4526  } else {
4527  printf("WARNING: Repository found with NULL name, skipping...\n");
4528  }
4529  StrFree(repo_name);
4530  StrFree(repo_capacity);
4531  }
4532  }
4533 
4534  if (xpathObj) {
4535  xmlXPathFreeObject(xpathObj);
4536  }
4537  if (xpathCtx) {
4538  xmlXPathFreeContext(xpathCtx);
4539  }
4540  if (doc) {
4541  xmlFreeDoc(doc);
4542  }
4543 
4544  return 0;
4545 }
4546 
4547 /* Read kasp.xml, validate it and grab each policy in it as we go. */
4548 int update_policies(char* kasp_filename)
4549 {
4550  int status;
4551 
4552  /* what we will read from the file */
4553  char *policy_name = NULL;
4554  char *policy_description = NULL;
4555 
4556  /* All of the XML stuff */
4557  xmlDocPtr doc = NULL;
4558  xmlDocPtr pol_doc = NULL;
4559  xmlDocPtr rngdoc = NULL;
4560  xmlNode *curNode;
4561  xmlNode *childNode;
4562  xmlNode *childNode2;
4563  xmlNode *childNode3;
4564  xmlChar *opt_out_flag = (xmlChar *)"N";
4565  xmlChar *nsec3param_ttl = NULL ;
4566  xmlChar *share_keys_flag = (xmlChar *)"N";
4567  xmlChar *man_roll_flag = (xmlChar *)"N";
4568  xmlChar *rfc5011_flag = (xmlChar *)"N";
4569  int standby_keys_flag = 0;
4570  xmlXPathContextPtr xpathCtx = NULL;
4571  xmlXPathObjectPtr xpathObj = NULL;
4572  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
4573  xmlRelaxNGValidCtxtPtr rngctx = NULL;
4574  xmlRelaxNGPtr schema = NULL;
4575  int i = 0;
4576 
4577  xmlChar *node_expr = (unsigned char*) "//Policy";
4578 
4579  KSM_POLICY *policy;
4580 
4581  /* Some stuff for the algorithm change check */
4582  int value = 0;
4583  int algo_change = 0;
4584  int user_certain;
4585  char* changes_made = NULL;
4586  int size = -1;
4587  char tmp_change[KSM_MSG_LENGTH];
4588 
4589  /* Some files, the xml and rng */
4590  const char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/kasp.rng";
4591  char* kaspcheck_cmd = NULL;
4592  char* kaspcheck_cmd_version = NULL;
4593 
4594  StrAppend(&kaspcheck_cmd, ODS_EN_KASPCHECK);
4595  StrAppend(&kaspcheck_cmd, " -c ");
4596  StrAppend(&kaspcheck_cmd, config);
4597 
4598  StrAppend(&kaspcheck_cmd_version, ODS_EN_KASPCHECK);
4599  StrAppend(&kaspcheck_cmd_version, " --version > /dev/null");
4600 
4601  /* Run kaspcheck */
4602  status = system(kaspcheck_cmd_version);
4603  if (status == 0)
4604  {
4605  status = system(kaspcheck_cmd);
4606  if (status != 0)
4607  {
4608  fprintf(stderr, "ods-kaspcheck returned an error, please check your policy\n");
4609  StrFree(kaspcheck_cmd);
4610  StrFree(kaspcheck_cmd_version);
4611  return(-1);
4612  }
4613  }
4614  else
4615  {
4616  fprintf(stderr, "Couldn't run ods-kaspcheck, will carry on\n");
4617  }
4618 
4619  StrFree(kaspcheck_cmd);
4620  StrFree(kaspcheck_cmd_version);
4621 
4622  /* Load XML document */
4623  doc = xmlParseFile(kasp_filename);
4624  if (doc == NULL) {
4625  printf("Error: unable to parse file \"%s\"\n", kasp_filename);
4626  return(-1);
4627  }
4628 
4629  /* Load rng document: TODO make the rng stuff optional? */
4630  rngdoc = xmlParseFile(rngfilename);
4631  if (rngdoc == NULL) {
4632  printf("Error: unable to parse file \"%s\"\n", rngfilename);
4633  return(-1);
4634  }
4635 
4636  /* Create an XML RelaxNGs parser context for the relax-ng document. */
4637  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
4638  if (rngpctx == NULL) {
4639  printf("Error: unable to create XML RelaxNGs parser context\n");
4640  return(-1);
4641  }
4642 
4643  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
4644  schema = xmlRelaxNGParse(rngpctx);
4645  if (schema == NULL) {
4646  printf("Error: unable to parse a schema definition resource\n");
4647  return(-1);
4648  }
4649 
4650  /* Create an XML RelaxNGs validation context based on the given schema */
4651  rngctx = xmlRelaxNGNewValidCtxt(schema);
4652  if (rngctx == NULL) {
4653  printf("Error: unable to create RelaxNGs validation context based on the schema\n");
4654  return(-1);
4655  }
4656 
4657  /* Validate a document tree in memory. */
4658  status = xmlRelaxNGValidateDoc(rngctx,doc);
4659  if (status != 0) {
4660  printf("Error validating file \"%s\"\n", kasp_filename);
4661  return(-1);
4662  }
4663 
4664  /* Allocate some space for our policy */
4665  policy = KsmPolicyAlloc();
4666  if (policy == NULL) {
4667  printf("Malloc for policy struct failed");
4668  exit(1);
4669  }
4670 
4671  /* Create xpath evaluation context */
4672  xpathCtx = xmlXPathNewContext(doc);
4673  if(xpathCtx == NULL) {
4674  xmlFreeDoc(doc);
4675  KsmPolicyFree(policy);
4676  return(1);
4677  }
4678 
4679  /* Evaluate xpath expression */
4680  xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx);
4681  if(xpathObj == NULL) {
4682  xmlXPathFreeContext(xpathCtx);
4683  xmlFreeDoc(doc);
4684  KsmPolicyFree(policy);
4685  return(1);
4686  }
4687 
4688  if (xpathObj->nodesetval) {
4689 
4690  /*
4691  * We will loop through twice, the first time to check on any algorithm
4692  * changes (which are not advised)
4693  */
4694  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) { /* foreach policy */
4695 
4696  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
4697  policy_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], (const xmlChar *)"name");
4698  if (strlen(policy_name) == 0) {
4699  /* error */
4700  printf("Error extracting policy name from %s\n", kasp_filename);
4701  break;
4702  }
4703 
4704  /*
4705  * Only carry on if this is an existing policy
4706  */
4707  SetPolicyDefaults(policy, policy_name);
4708  status = KsmPolicyExists(policy_name);
4709  if (status == 0) {
4710  /* Policy exists */
4711  status = KsmPolicyRead(policy);
4712  if(status != 0) {
4713  printf("Error: unable to read policy %s; skipping\n", policy_name);
4714  break;
4715  }
4716 
4717  while (curNode) {
4718  if (xmlStrEqual(curNode->name, (const xmlChar *)"Keys")) {
4719  childNode = curNode->children;
4720  while (childNode){
4721  if (xmlStrEqual(childNode->name, (const xmlChar *)"KSK")) {
4722  childNode2 = childNode->children;
4723  while (childNode2){
4724  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Algorithm")) {
4725  /* Compare with existing */
4726  value = 0;
4727  status = StrStrtoi((char *)xmlNodeGetContent(childNode2), &value);
4728  if (status != 0) {
4729  printf("Error extracting KSK algorithm for policy %s, exiting...", policy_name);
4730  return status;
4731  }
4732  if (value != policy->ksk->algorithm) {
4733  /* Changed */
4734  if (!algo_change) {
4735  printf("\n\nAlgorithm change attempted... details:\n");
4736  StrAppend(&changes_made, "Algorithm changes made, details:");
4737  algo_change = 1;
4738  }
4739  size = snprintf(tmp_change, KSM_MSG_LENGTH, "Policy: %s, KSK algorithm changed from %d to %d.", policy_name, policy->ksk->algorithm, value);
4740  /* Check overflow */
4741  if (size < 0 || size >= KSM_MSG_LENGTH) {
4742  printf("Error constructing log message for policy %s, exiting...", policy_name);
4743  return -1;
4744  }
4745  printf("%s\n", tmp_change);
4746  StrAppend(&changes_made, " ");
4747  StrAppend(&changes_made, tmp_change);
4748  }
4749 
4750  }
4751  childNode2 = childNode2->next;
4752  }
4753 
4754  } /* End of KSK */
4755  /* ZSK */
4756  else if (xmlStrEqual(childNode->name, (const xmlChar *)"ZSK")) {
4757  childNode2 = childNode->children;
4758  while (childNode2){
4759  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Algorithm")) {
4760  /* Compare with existing */
4761  value = 0;
4762  status = StrStrtoi((char *)xmlNodeGetContent(childNode2), &value);
4763  if (status != 0) {
4764  printf("Error extracting ZSK algorithm for policy %s, exiting...", policy_name);
4765  return status;
4766  }
4767  if (value != policy->zsk->algorithm) {
4768  /* Changed */
4769  if (!algo_change) {
4770  printf("\n\nAlgorithm change attempted... details:\n");
4771  StrAppend(&changes_made, "Algorithm changes made, details:");
4772  algo_change = 1;
4773  }
4774  size = snprintf(tmp_change, KSM_MSG_LENGTH, "Policy: %s, ZSK algorithm changed from %d to %d.", policy_name, policy->zsk->algorithm, value);
4775  /* Check overflow */
4776  if (size < 0 || size >= KSM_MSG_LENGTH) {
4777  printf("Error constructing log message for policy %s, exiting...", policy_name);
4778  return -1;
4779  }
4780  printf("%s\n", tmp_change);
4781  StrAppend(&changes_made, " ");
4782  StrAppend(&changes_made, tmp_change);
4783  }
4784 
4785  }
4786  childNode2 = childNode2->next;
4787  }
4788 
4789  } /* End of ZSK */
4790 
4791  childNode = childNode->next;
4792  }
4793  }
4794  curNode = curNode->next;
4795  }
4796  }
4797  /* Free up some stuff that we don't need any more */
4798  StrFree(policy_name);
4799 
4800  } /* End of <Policy> */
4801 
4802  /*
4803  * Did we see any changes? If so then warn and confirm before continuing
4804  */
4805 
4806  if (algo_change == 1 && force_flag == 0) {
4807  printf("*WARNING* This will change the algorithms used as noted above. Algorithm rollover is _not_ supported by OpenDNSSEC and zones may break. Are you sure? [y/N] ");
4808 
4809  user_certain = getchar();
4810  if (user_certain != 'y' && user_certain != 'Y') {
4811  printf("\nOkay, quitting...\n");
4812  xmlXPathFreeContext(xpathCtx);
4813  xmlFreeDoc(doc);
4814  KsmPolicyFree(policy);
4815 
4816  exit(0);
4817  }
4818 
4819  /* Newline for the output */
4820  printf("\n");
4821 
4822  /*
4823  * Log this change to syslog for posterity
4824  */
4825 #ifdef HAVE_OPENLOG_R
4826  openlog_r("ods-ksmutil", 0, DEFAULT_LOG_FACILITY, &sdata);
4827 #else
4828  openlog("ods-ksmutil", 0, DEFAULT_LOG_FACILITY);
4829 #endif
4830 #ifdef HAVE_SYSLOG_R
4831  syslog_r(LOG_INFO, &sdata, "%s", changes_made);
4832 #else
4833  syslog(LOG_INFO, "%s", changes_made);
4834 #endif
4835 #ifdef HAVE_CLOSELOG_R
4836  closelog_r(&sdata);
4837 #else
4838  closelog();
4839 #endif
4840 
4841  }
4842 
4843  /*
4844  * Then loop through to actually make the updates
4845  */
4846  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
4847 
4848  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
4849  policy_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], (const xmlChar *)"name");
4850  if (strlen(policy_name) == 0) {
4851  /* error */
4852  printf("Error extracting policy name from %s\n", kasp_filename);
4853  break;
4854  }
4855 
4856  printf("Policy %s found\n", policy_name);
4857  while (curNode) {
4858  if (xmlStrEqual(curNode->name, (const xmlChar *)"Description")) {
4859  policy_description = (char *) xmlNodeGetContent(curNode);
4860 
4861  /* Insert or update this policy with the description found,
4862  we will need the policy_id too */
4863  SetPolicyDefaults(policy, policy_name);
4864  status = KsmPolicyExists(policy_name);
4865  if (status == 0) {
4866  /* Policy exists; we will be updating it */
4867  status = KsmPolicyRead(policy);
4868  if(status != 0) {
4869  printf("Error: unable to read policy %s; skipping\n", policy_name);
4870  curNode = curNode->next;
4871  break;
4872  }
4873 
4874  /* Set description if it has changed */
4875  if (strncmp(policy_description, policy->description, KSM_POLICY_DESC_LENGTH) != 0) {
4876  status = KsmPolicyUpdateDesc(policy->id, policy_description);
4877  if(status != 0) {
4878  printf("Error: unable to update policy description for %s; skipping\n", policy_name);
4879  /* Don't return? try to parse the rest of the file? */
4880  curNode = curNode->next;
4881  continue;
4882  }
4883  }
4884  }
4885  else {
4886  /* New policy, insert it and get the new policy_id */
4887  status = KsmImportPolicy(policy_name, policy_description);
4888  if(status != 0) {
4889  printf("Error: unable to insert policy %s; skipping\n", policy_name);
4890  /* Don't return? try to parse the rest of the file? */
4891  curNode = curNode->next;
4892  continue;
4893  }
4894  status = KsmPolicySetIdFromName(policy);
4895 
4896  if (status != 0) {
4897  printf("Error: unable to get policy id for %s; skipping\n", policy_name);
4898  curNode = curNode->next;
4899  continue;
4900  }
4901  }
4902  }
4903  /* SIGNATURES */
4904  else if (xmlStrEqual(curNode->name, (const xmlChar *)"Signatures")) {
4905  childNode = curNode->children;
4906  while (childNode){
4907  if (xmlStrEqual(childNode->name, (const xmlChar *)"Resign")) {
4908  SetParamOnPolicy(xmlNodeGetContent(childNode), "resign", "signature", policy->signature->resign, policy->id, DURATION_TYPE);
4909  }
4910  else if (xmlStrEqual(childNode->name, (const xmlChar *)"Refresh")) {
4911  SetParamOnPolicy(xmlNodeGetContent(childNode), "refresh", "signature", policy->signer->refresh, policy->id, DURATION_TYPE);
4912  }
4913  else if (xmlStrEqual(childNode->name, (const xmlChar *)"Validity")) {
4914  childNode2 = childNode->children;
4915  while (childNode2){
4916  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Default")) {
4917  SetParamOnPolicy(xmlNodeGetContent(childNode2), "valdefault", "signature", policy->signature->valdefault, policy->id, DURATION_TYPE);
4918  }
4919  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Denial")) {
4920  SetParamOnPolicy(xmlNodeGetContent(childNode2), "valdenial", "signature", policy->signature->valdenial, policy->id, DURATION_TYPE);
4921  }
4922  childNode2 = childNode2->next;
4923  }
4924  }
4925  else if (xmlStrEqual(childNode->name, (const xmlChar *)"Jitter")) {
4926  SetParamOnPolicy(xmlNodeGetContent(childNode), "jitter", "signature", policy->signer->jitter, policy->id, DURATION_TYPE);
4927  }
4928  else if (xmlStrEqual(childNode->name, (const xmlChar *)"InceptionOffset")) {
4929  SetParamOnPolicy(xmlNodeGetContent(childNode), "clockskew", "signature", policy->signature->clockskew, policy->id, DURATION_TYPE);
4930  }
4931  childNode = childNode->next;
4932  }
4933  } /* End of Signatures */
4934  else if (xmlStrEqual(curNode->name, (const xmlChar *)"Denial")) {
4935  opt_out_flag = (xmlChar *)"N";
4936  childNode = curNode->children;
4937  while (childNode){
4938  if (xmlStrEqual(childNode->name, (const xmlChar *)"NSEC3")) {
4939  /* NSEC3 */
4940  status = KsmParameterSet("version", "denial", 3, policy->id);
4941  if (status != 0) {
4942  printf("Error: unable to insert/update %s for policy\n", "Denial version");
4943  }
4944  childNode2 = childNode->children;
4945  while (childNode2){
4946  if (xmlStrEqual(childNode2->name, (const xmlChar *)"OptOut")) {
4947  opt_out_flag = (xmlChar *)"Y";
4948  }
4949  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Resalt")) {
4950  SetParamOnPolicy(xmlNodeGetContent(childNode2), "resalt", "denial", policy->denial->resalt, policy->id, DURATION_TYPE);
4951  }
4952  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) {
4953  nsec3param_ttl = xmlNodeGetContent(childNode2);
4954  }
4955  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Hash")) {
4956  childNode3 = childNode2->children;
4957  while (childNode3){
4958  if (xmlStrEqual(childNode3->name, (const xmlChar *)"Algorithm")) {
4959  SetParamOnPolicy(xmlNodeGetContent(childNode3), "algorithm", "denial", policy->denial->algorithm, policy->id, INT_TYPE);
4960  }
4961  else if (xmlStrEqual(childNode3->name, (const xmlChar *)"Iterations")) {
4962  SetParamOnPolicy(xmlNodeGetContent(childNode3), "iterations", "denial", policy->denial->iteration, policy->id, INT_TYPE);
4963  }
4964  else if (xmlStrEqual(childNode3->name, (const xmlChar *)"Salt")) {
4965  SetParamOnPolicy(xmlGetProp(childNode3, (const xmlChar *)"length"), "saltlength", "denial", policy->denial->saltlength, policy->id, INT_TYPE);
4966  }
4967  childNode3 = childNode3->next;
4968  }
4969  }
4970 
4971  childNode2 = childNode2->next;
4972  }
4973  /* Set things that we flagged */
4974  SetParamOnPolicy(opt_out_flag, "optout", "denial", policy->denial->optout, policy->id, BOOL_TYPE);
4975  if (nsec3param_ttl == NULL)
4976  nsec3param_ttl = (xmlChar *) StrStrdup("PT0S");
4977  SetParamOnPolicy(nsec3param_ttl, "ttl", "denial", policy->denial->ttl, policy->id, DURATION_TYPE);
4978  nsec3param_ttl = NULL;
4979  } /* End of NSEC3 */
4980  else if (xmlStrEqual(childNode->name, (const xmlChar *)"NSEC")) {
4981  status = KsmParameterSet("version", "denial", 1, policy->id);
4982  if (status != 0) {
4983  printf("Error: unable to insert/update %s for policy\n", "Denial version");
4984  }
4985  }
4986  childNode = childNode->next;
4987  }
4988  } /* End of Denial */
4989  else if (xmlStrEqual(curNode->name, (const xmlChar *)"Keys")) {
4990  share_keys_flag = (xmlChar *)"N";
4991  childNode = curNode->children;
4992  while (childNode){
4993  if (xmlStrEqual(childNode->name, (const xmlChar *)"TTL")) {
4994  SetParamOnPolicy(xmlNodeGetContent(childNode), "ttl", "keys", policy->keys->ttl, policy->id, DURATION_TYPE);
4995  }
4996  else if (xmlStrEqual(childNode->name, (const xmlChar *)"RetireSafety")) {
4997  SetParamOnPolicy(xmlNodeGetContent(childNode), "retiresafety", "keys", policy->keys->retire_safety, policy->id, DURATION_TYPE);
4998  }
4999  else if (xmlStrEqual(childNode->name, (const xmlChar *)"PublishSafety")) {
5000  SetParamOnPolicy(xmlNodeGetContent(childNode), "publishsafety", "keys", policy->keys->publish_safety, policy->id, DURATION_TYPE);
5001  }
5002  else if (xmlStrEqual(childNode->name, (const xmlChar *)"ShareKeys")) {
5003  share_keys_flag = (xmlChar *)"Y";
5004  }
5005  else if (xmlStrEqual(childNode->name, (const xmlChar *)"Purge")) {
5006  SetParamOnPolicy(xmlNodeGetContent(childNode), "purge", "keys", policy->keys->purge, policy->id, DURATION_TYPE);
5007  }
5008  /* KSK */
5009  else if (xmlStrEqual(childNode->name, (const xmlChar *)"KSK")) {
5010  man_roll_flag = (xmlChar *)"N";
5011  rfc5011_flag = (xmlChar *)"N";
5012  childNode2 = childNode->children;
5013  while (childNode2){
5014  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Algorithm")) {
5015  SetParamOnPolicy(xmlNodeGetContent(childNode2), "algorithm", "ksk", policy->ksk->algorithm, policy->id, INT_TYPE);
5016  SetParamOnPolicy(xmlGetProp(childNode2, (const xmlChar *)"length"), "bits", "ksk", policy->ksk->bits, policy->id, INT_TYPE);
5017 
5018  }
5019  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Lifetime")) {
5020  SetParamOnPolicy(xmlNodeGetContent(childNode2), "lifetime", "ksk", policy->ksk->lifetime, policy->id, DURATION_TYPE);
5021  }
5022  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Repository")) {
5023  if (SetParamOnPolicy(xmlNodeGetContent(childNode2), "repository", "ksk", policy->ksk->sm, policy->id, REPO_TYPE) != 0) {
5024  printf("Please either add the repository to conf.xml or remove the reference to it from kasp.xml\n");
5025  /* return the error, we do not want to continue */
5026  xmlFreeDoc(pol_doc);
5027  xmlXPathFreeContext(xpathCtx);
5028  xmlRelaxNGFree(schema);
5029  xmlRelaxNGFreeValidCtxt(rngctx);
5030  xmlRelaxNGFreeParserCtxt(rngpctx);
5031  xmlFreeDoc(doc);
5032  xmlFreeDoc(rngdoc);
5033  KsmPolicyFree(policy);
5034 
5035  return(1);
5036  }
5037  }
5038  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Standby")) {
5039  SetParamOnPolicy(xmlNodeGetContent(childNode2), "standby", "ksk", policy->ksk->standby_keys, policy->id, INT_TYPE);
5040  standby_keys_flag = 1;
5041  }
5042  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"ManualRollover")) {
5043  man_roll_flag = (xmlChar *)"Y";
5044  }
5045  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"RFC5011")) {
5046  rfc5011_flag = (xmlChar *)"Y";
5047  }
5048  /*else if (xmlStrEqual(childNode2->name, (const xmlChar *)"RolloverScheme")) {
5049  SetParamOnPolicy(xmlNodeGetContent(childNode2), "rollover_scheme", "ksk", policy->ksk->rollover_scheme, policy->id, ROLLOVER_TYPE);
5050  }*/
5051  childNode2 = childNode2->next;
5052  }
5053  /* Set things that we flagged */
5054  SetParamOnPolicy(man_roll_flag, "manual_rollover", "ksk", policy->ksk->manual_rollover, policy->id, BOOL_TYPE);
5055  SetParamOnPolicy(rfc5011_flag, "rfc5011", "ksk", policy->ksk->rfc5011, policy->id, BOOL_TYPE);
5056  if (standby_keys_flag == 0) {
5057  SetParamOnPolicy((xmlChar *)"0", "standby", "ksk", policy->ksk->standby_keys, policy->id, INT_TYPE_NO_FREE);
5058  } else {
5059  standby_keys_flag = 0;
5060  }
5061  } /* End of KSK */
5062  /* ZSK */
5063  else if (xmlStrEqual(childNode->name, (const xmlChar *)"ZSK")) {
5064  man_roll_flag = (xmlChar *)"N";
5065  childNode2 = childNode->children;
5066  while (childNode2){
5067  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Algorithm")) {
5068  SetParamOnPolicy(xmlNodeGetContent(childNode2), "algorithm", "zsk", policy->zsk->algorithm, policy->id, INT_TYPE);
5069  SetParamOnPolicy(xmlGetProp(childNode2, (const xmlChar *)"length"), "bits", "zsk", policy->zsk->bits, policy->id, INT_TYPE);
5070 
5071  }
5072  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Lifetime")) {
5073  SetParamOnPolicy(xmlNodeGetContent(childNode2), "lifetime", "zsk", policy->zsk->lifetime, policy->id, DURATION_TYPE);
5074  }
5075  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Repository")) {
5076  if (SetParamOnPolicy(xmlNodeGetContent(childNode2), "repository", "zsk", policy->zsk->sm, policy->id, REPO_TYPE) != 0) {
5077  printf("Please either add the repository to conf.xml or remove the reference to it from kasp.xml\n");
5078  /* return the error, we do not want to continue */
5079  xmlFreeDoc(pol_doc);
5080  xmlXPathFreeContext(xpathCtx);
5081  xmlRelaxNGFree(schema);
5082  xmlRelaxNGFreeValidCtxt(rngctx);
5083  xmlRelaxNGFreeParserCtxt(rngpctx);
5084  xmlFreeDoc(doc);
5085  xmlFreeDoc(rngdoc);
5086  KsmPolicyFree(policy);
5087 
5088  return(1);
5089  }
5090  }
5091  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Standby")) {
5092  SetParamOnPolicy(xmlNodeGetContent(childNode2), "standby", "zsk", policy->zsk->standby_keys, policy->id, INT_TYPE);
5093  standby_keys_flag = 1;
5094  }
5095  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"ManualRollover")) {
5096  man_roll_flag = (xmlChar *)"Y";
5097  }
5098  childNode2 = childNode2->next;
5099  }
5100  /* Set things that we flagged */
5101  SetParamOnPolicy(man_roll_flag, "manual_rollover", "zsk", policy->zsk->manual_rollover, policy->id, BOOL_TYPE);
5102  } /* End of ZSK */
5103 
5104  childNode = childNode->next;
5105  }
5106  /* Set things that we flagged */
5107  SetParamOnPolicy(share_keys_flag, "zones_share_keys", "keys", policy->keys->share_keys, policy->id, BOOL_TYPE);
5108  if (standby_keys_flag == 0) {
5109  SetParamOnPolicy((xmlChar *)"0", "standby", "zsk", policy->zsk->standby_keys, policy->id, INT_TYPE_NO_FREE);
5110  } else {
5111  standby_keys_flag = 0;
5112  }
5113 
5114  } /* End of Keys */
5115  /* Zone */
5116  else if (xmlStrEqual(curNode->name, (const xmlChar *)"Zone")) {
5117  childNode = curNode->children;
5118  while (childNode){
5119  if (xmlStrEqual(childNode->name, (const xmlChar *)"PropagationDelay")) {
5120  SetParamOnPolicy(xmlNodeGetContent(childNode), "propagationdelay", "zone", policy->zone->propdelay, policy->id, DURATION_TYPE);
5121  }
5122  else if (xmlStrEqual(childNode->name, (const xmlChar *)"SOA")) {
5123  childNode2 = childNode->children;
5124  while (childNode2){
5125  if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) {
5126  SetParamOnPolicy(xmlNodeGetContent(childNode2), "ttl", "zone", policy->zone->soa_ttl, policy->id, DURATION_TYPE);
5127  }
5128  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Minimum")) {
5129  SetParamOnPolicy(xmlNodeGetContent(childNode2), "min", "zone", policy->zone->soa_min, policy->id, DURATION_TYPE);
5130  }
5131  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Serial")) {
5132  SetParamOnPolicy(xmlNodeGetContent(childNode2), "serial", "zone", policy->zone->serial, policy->id, SERIAL_TYPE);
5133  }
5134  childNode2 = childNode2->next;
5135  }
5136  }
5137  childNode = childNode->next;
5138  }
5139  } /* End of Zone */
5140  /* Parent */
5141  else if (xmlStrEqual(curNode->name, (const xmlChar *)"Parent")) {
5142  childNode = curNode->children;
5143  while (childNode){
5144  if (xmlStrEqual(childNode->name, (const xmlChar *)"PropagationDelay")) {
5145  SetParamOnPolicy(xmlNodeGetContent(childNode), "propagationdelay", "parent", policy->parent->propdelay, policy->id, DURATION_TYPE);
5146  }
5147  else if (xmlStrEqual(childNode->name, (const xmlChar *)"DS")) {
5148  childNode2 = childNode->children;
5149  while (childNode2){
5150  if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) {
5151  SetParamOnPolicy(xmlNodeGetContent(childNode2), "ttlds", "parent", policy->parent->ds_ttl, policy->id, DURATION_TYPE);
5152  }
5153  childNode2 = childNode2->next;
5154  }
5155  }
5156  else if (xmlStrEqual(childNode->name, (const xmlChar *)"SOA")) {
5157  childNode2 = childNode->children;
5158  while (childNode2){
5159  if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) {
5160  SetParamOnPolicy(xmlNodeGetContent(childNode2), "ttl", "parent", policy->parent->soa_ttl, policy->id, DURATION_TYPE);
5161  }
5162  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Minimum")) {
5163  SetParamOnPolicy(xmlNodeGetContent(childNode2), "min", "parent", policy->parent->soa_min, policy->id, DURATION_TYPE);
5164  }
5165  childNode2 = childNode2->next;
5166  }
5167  }
5168  childNode = childNode->next;
5169  }
5170  } /* End of Parent */
5171 
5172  curNode = curNode->next;
5173  }
5174 
5175  /* Free up some stuff that we don't need any more */
5176  StrFree(policy_name);
5177  StrFree(policy_description);
5178 
5179  } /* End of <Policy> */
5180  }
5181 
5182  /* Cleanup */
5183  xmlXPathFreeContext(xpathCtx);
5184  xmlRelaxNGFree(schema);
5185  xmlRelaxNGFreeValidCtxt(rngctx);
5186  xmlRelaxNGFreeParserCtxt(rngpctx);
5187  xmlFreeDoc(doc);
5188  xmlFreeDoc(rngdoc);
5189  KsmPolicyFree(policy);
5190 
5191  return(status);
5192 }
5193 
5194 /* Read zonelist (as passed in) and insert/update any zones seen */
5195 int update_zones(char* zone_list_filename)
5196 {
5197  int status = 0;
5198 
5199  /* All of the XML stuff */
5200  xmlDocPtr doc = NULL;
5201  xmlDocPtr rngdoc = NULL;
5202  xmlNode *curNode;
5203  xmlNode *childNode;
5204  xmlNode *childNode2;
5205  xmlXPathContextPtr xpathCtx = NULL;
5206  xmlXPathObjectPtr xpathObj = NULL;
5207  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
5208  xmlRelaxNGValidCtxtPtr rngctx = NULL;
5209  xmlRelaxNGPtr schema = NULL;
5210 
5211  char* zone_name = NULL;
5212  char* policy_name = NULL;
5213  char* current_policy = NULL;
5214  char* current_signconf = NULL;
5215  char* current_input = NULL;
5216  char* current_output = NULL;
5217  char* current_in_type = NULL;
5218  char* current_out_type = NULL;
5219  int policy_id = 0;
5220  int new_zone = 0; /* flag to say if the zone is new or not */
5221  int file_zone_count = 0; /* As a quick check we will compare the number of */
5222  int db_zone_count = 0; /* zones in the file to the number in the database */
5223  int* zone_ids; /* List of zone_ids seen from zonelist.xml */
5224  int temp_id;
5225 
5226  char* sql = NULL;
5227  DB_RESULT result; /* Result of the query */
5228  DB_RESULT result2; /* Result of the query */
5229  DB_RESULT result3; /* Result of the query */
5230  DB_ROW row = NULL; /* Row data */
5231  KSM_PARAMETER shared; /* Parameter information */
5232  int seen_zone = 0;
5233  int temp_count = 0;
5234  int i = 0;
5235 
5236  xmlChar *node_expr = (unsigned char*) "//Zone";
5237  const char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/zonelist.rng";
5238 
5239  /* Load XML document */
5240  doc = xmlParseFile(zone_list_filename);
5241  if (doc == NULL) {
5242  printf("Error: unable to parse file \"%s\"\n", zone_list_filename);
5243  return(-1);
5244  }
5245 
5246  /* Load rng document: TODO make the rng stuff optional? */
5247  rngdoc = xmlParseFile(rngfilename);
5248  if (rngdoc == NULL) {
5249  printf("Error: unable to parse file \"%s\"\n", rngfilename);
5250  return(-1);
5251  }
5252 
5253  /* Create an XML RelaxNGs parser context for the relax-ng document. */
5254  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
5255  if (rngpctx == NULL) {
5256  printf("Error: unable to create XML RelaxNGs parser context\n");
5257  return(-1);
5258  }
5259 
5260  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
5261  schema = xmlRelaxNGParse(rngpctx);
5262  if (schema == NULL) {
5263  printf("Error: unable to parse a schema definition resource\n");
5264  return(-1);
5265  }
5266 
5267  /* Create an XML RelaxNGs validation context based on the given schema */
5268  rngctx = xmlRelaxNGNewValidCtxt(schema);
5269  if (rngctx == NULL) {
5270  printf("Error: unable to create RelaxNGs validation context based on the schema\n");
5271  return(-1);
5272  }
5273 
5274  /* Validate a document tree in memory. */
5275  status = xmlRelaxNGValidateDoc(rngctx,doc);
5276  if (status != 0) {
5277  printf("Error validating file \"%s\"\n", zone_list_filename);
5278  return(-1);
5279  }
5280 
5281  /* Create xpath evaluation context */
5282  xpathCtx = xmlXPathNewContext(doc);
5283  if(xpathCtx == NULL) {
5284  xmlFreeDoc(doc);
5285  return(1);
5286  }
5287 
5288  /* Evaluate xpath expression */
5289  xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx);
5290  if(xpathObj == NULL) {
5291  xmlXPathFreeContext(xpathCtx);
5292  xmlFreeDoc(doc);
5293  return(1);
5294  }
5295 
5296  if (xpathObj->nodesetval) {
5297  file_zone_count = xpathObj->nodesetval->nodeNr;
5298  } else {
5299  printf("Error extracting zone count from %s\n", zone_list_filename);
5300  xmlXPathFreeContext(xpathCtx);
5301  xmlFreeDoc(doc);
5302  return(1);
5303  }
5304 
5305  /* Allocate space for the list of zone IDs */
5306  zone_ids = MemMalloc(file_zone_count * sizeof(int));
5307 
5308  if (xpathObj->nodesetval) {
5309  for (i = 0; i < file_zone_count; i++) {
5310 
5311  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
5312  zone_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], (const xmlChar *)"name");
5313  if (strlen(zone_name) == 0) {
5314  /* error */
5315  printf("Error extracting zone name from %s\n", zone_list_filename);
5316  return(1);
5317  }
5318 
5319  /*
5320  It is tempting to remove the trailing dot here; however I am
5321  not sure that it is the right thing to do... It trashed my
5322  test setup by deleting the zone sion. and replacing it with
5323  sion (but of course none of the keys were moved). I think
5324  that allowing people to edit zonelist.xml means that we must
5325  allow them to add the td if they want to.
5326  */
5327 
5328  printf("Zone %s found; ", zone_name);
5329  while (curNode) {
5330  /* POLICY */
5331  if (xmlStrEqual(curNode->name, (const xmlChar *)"Policy")) {
5332  current_policy = (char *) xmlNodeGetContent(curNode);
5333 
5334  printf("policy set to %s\n", current_policy);
5335 
5336  /* If we have a different policy to last time get its ID */
5337  if (policy_name == NULL || strcmp(current_policy, policy_name) != 0) {
5338  StrFree(policy_name);
5339  StrAppend(&policy_name, current_policy);
5340 
5341  status = KsmPolicyIdFromName(policy_name, &policy_id);
5342  if (status != 0) {
5343  printf("ERROR, can't find policy %s.\n", policy_name);
5344  StrFree(zone_ids);
5345  return(1);
5346  }
5347  }
5348  }
5349  /* SIGNERCONFIGURATION */
5350  else if (xmlStrEqual(curNode->name, (const xmlChar *)"SignerConfiguration")) {
5351  current_signconf = (char *) xmlNodeGetContent(curNode);
5352  }
5353  /* ADAPTERS */
5354  else if (xmlStrEqual(curNode->name, (const xmlChar *)"Adapters")) {
5355  childNode = curNode->children;
5356  while (childNode){
5357  /* INPUT */
5358  if (xmlStrEqual(childNode->name, (const xmlChar *)"Input")) {
5359  childNode2 = childNode->children;
5360  while (childNode2){
5361  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Adapter")) {
5362  current_input = (char *) xmlNodeGetContent(childNode2);
5363  current_in_type = (char *) xmlGetProp(childNode2, (const xmlChar *)"type");
5364  }
5365  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"File")) {
5366  current_input = (char *) xmlNodeGetContent(childNode2);
5367  current_in_type = (char *) childNode2->name;
5368  }
5369  childNode2 = childNode2->next;
5370  }
5371  }
5372  /* OUTPUT */
5373  else if (xmlStrEqual(childNode->name, (const xmlChar *)"Output")) {
5374  childNode2 = childNode->children;
5375  while (childNode2){
5376  if (xmlStrEqual(childNode2->name, (const xmlChar *)"Adapter")) {
5377  current_output = (char *) xmlNodeGetContent(childNode2);
5378  current_out_type = (char *) xmlGetProp(childNode2, (const xmlChar *)"type");
5379  }
5380  else if (xmlStrEqual(childNode2->name, (const xmlChar *)"File")) {
5381  current_output = (char *) xmlNodeGetContent(childNode2);
5382  current_out_type = (char *) childNode2->name;
5383  }
5384  childNode2 = childNode2->next;
5385  }
5386  }
5387  childNode = childNode->next;
5388  }
5389  }
5390  curNode = curNode->next;
5391  }
5392 
5393  /*
5394  * Now we have all the information update/insert this repository
5395  */
5396  status = KsmImportZone(zone_name, policy_id, 0, &new_zone, current_signconf, current_input, current_output, current_in_type, current_out_type);
5397  if (status != 0) {
5398  if (status == -3) {
5399  printf("Error Importing zone %s; it already exists both with and without a trailing dot\n", zone_name);
5400  } else {
5401  printf("Error Importing Zone %s\n", zone_name);
5402  }
5403  StrFree(zone_ids);
5404  return(1);
5405  }
5406 
5407  if (new_zone == 1) {
5408  printf("Added zone %s to database\n", zone_name);
5409  }
5410 
5411  /* make a note of the zone_id */
5412  status = KsmZoneIdFromName(zone_name, &temp_id);
5413  if (status != 0) {
5414  printf("Error: unable to find a zone named \"%s\" in database\n", zone_name);
5415  printf("Error: Possibly two domains differ only by having a trailing dot or not?\n");
5416  StrFree(zone_ids);
5417  return(status);
5418  }
5419 
5420  /* We malloc'd this above */
5421  zone_ids[i] = temp_id;
5422 
5423  new_zone = 0;
5424  } /* End of <Zone> */
5425 
5426  }
5427 
5428  /* Cleanup */
5429  xmlXPathFreeContext(xpathCtx);
5430  xmlRelaxNGFree(schema);
5431  xmlRelaxNGFreeValidCtxt(rngctx);
5432  xmlRelaxNGFreeParserCtxt(rngpctx);
5433  xmlFreeDoc(doc);
5434  xmlFreeDoc(rngdoc);
5435 
5436  /* Now see how many zones are in the database */
5437  sql = DqsCountInit(DB_ZONE_TABLE);
5438  DqsEnd(&sql);
5439 
5440  /* Execute query and free up the query string */
5441  status = DbIntQuery(DbHandle(), &db_zone_count, sql);
5442  DqsFree(sql);
5443 
5444  /* If the 2 numbers match then our work is done */
5445  if (file_zone_count == db_zone_count) {
5446  StrFree(zone_ids);
5447  return 0;
5448  }
5449  /* If the file count is larger then something went wrong */
5450  else if (file_zone_count > db_zone_count) {
5451  printf("Failed to add all zones from zonelist\n");
5452  StrFree(zone_ids);
5453  return(1);
5454  }
5455 
5456  /* If we get here we need to do some deleting, get each zone in the db
5457  * and see if it is in the zone_list that we built earlier */
5458  /* In case there are thousands of zones we don't use an "IN" clause*/
5459  sql = DqsSpecifyInit(DB_ZONE_TABLE, "id, name, policy_id");
5460  DqsOrderBy(&sql, "ID");
5461  DqsEnd(&sql);
5462 
5463  status = DbExecuteSql(DbHandle(), sql, &result);
5464 
5465  if (status == 0) {
5466  status = DbFetchRow(result, &row);
5467  while (status == 0) {
5468  DbInt(row, 0, &temp_id);
5469  DbString(row, 1, &zone_name);
5470  DbInt(row, 2, &policy_id);
5471 
5472  seen_zone = 0;
5473  for (i = 0; i < db_zone_count; ++i) {
5474  if (temp_id == zone_ids[i]) {
5475  seen_zone = 1;
5476  break;
5477  }
5478  }
5479 
5480  if (seen_zone == 0) {
5481  /* We need to delete this zone */
5482  /* Get the shared_keys parameter */
5483  printf("Removing zone %s from database\n", zone_name);
5484 
5485  status = KsmParameterInit(&result2, "zones_share_keys", "keys", policy_id);
5486  if (status != 0) {
5487  DbFreeRow(row);
5488  DbStringFree(zone_name);
5489  StrFree(zone_ids);
5490  DusFree(sql);
5491  return(status);
5492  }
5493  status = KsmParameter(result2, &shared);
5494  if (status != 0) {
5495  DbFreeRow(row);
5496  DbStringFree(zone_name);
5497  StrFree(zone_ids);
5498  DusFree(sql);
5499  return(status);
5500  }
5501  KsmParameterEnd(result2);
5502 
5503  /* how many zones on this policy (needed to unlink keys) */
5504  status = KsmZoneCountInit(&result3, policy_id);
5505  if (status == 0) {
5506  status = KsmZoneCount(result3, &temp_count);
5507  }
5508  DbFreeResult(result3);
5509 
5510  /* Mark keys as dead if appropriate */
5511  if ((shared.value == 1 && temp_count == 1) || shared.value == 0) {
5512  status = KsmMarkKeysAsDead(temp_id);
5513  if (status != 0) {
5514  printf("Error: failed to mark keys as dead in database\n");
5515  StrFree(zone_ids);
5516  DusFree(sql);
5517  return(status);
5518  }
5519  }
5520 
5521  /* Finally, we can delete the zone (and any dnsseckeys entries) */
5522  status = KsmDeleteZone(temp_id);
5523  }
5524 
5525  status = DbFetchRow(result, &row);
5526  }
5527  /* Convert EOF status to success */
5528 
5529  if (status == -1) {
5530  status = 0;
5531  }
5532  DbFreeResult(result);
5533  }
5534 
5535  DusFree(sql);
5536  DbFreeRow(row);
5537  DbStringFree(zone_name);
5538  StrFree(zone_ids);
5539 
5540  return 0;
5541 }
5542 
5543 /*
5544  * This encapsulates all of the steps needed to insert/update a parameter value
5545  * try to update the policy value, if it has changed
5546  * TODO possible bug where parmeters which have a value of 0 are not written (because we
5547  * only write what looks like it has changed
5548  */
5549 int SetParamOnPolicy(const xmlChar* new_value, const char* name, const char* category, int current_value, int policy_id, int value_type)
5550 {
5551  int status = 0;
5552  int value = 0;
5553  char* temp_char = (char *)new_value;
5554 
5555  /* extract the value into an int */
5556  if (value_type == DURATION_TYPE) {
5557  if (strlen(temp_char) != 0) {
5558  status = DtXMLIntervalSeconds(temp_char, &value);
5559  if (status > 0) {
5560  printf("Error: unable to convert interval %s to seconds, error: %i\n", temp_char, status);
5561  StrFree(temp_char);
5562  return status;
5563  }
5564  else if (status == -1) {
5565  printf("Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days\n", temp_char);
5566  }
5567  StrFree(temp_char);
5568  } else {
5569  value = -1;
5570  }
5571  }
5572  else if (value_type == BOOL_TYPE) {
5573  /* Do we have an empty tag or no tag? */
5574  if (strncmp(temp_char, "Y", 1) == 0) {
5575  value = 1;
5576  } else {
5577  value = 0;
5578  }
5579  }
5580  else if (value_type == REPO_TYPE) {
5581  /* We need to convert the repository name into an id */
5582  status = KsmSmIdFromName(temp_char, &value);
5583  if (status != 0) {
5584  printf("Error: unable to find repository %s\n", temp_char);
5585  StrFree(temp_char);
5586  return status;
5587  }
5588  StrFree(temp_char);
5589  }
5590  else if (value_type == SERIAL_TYPE) {
5591  /* We need to convert the serial name into an id */
5592  status = KsmSerialIdFromName(temp_char, &value);
5593  if (status != 0) {
5594  printf("Error: unable to find serial type %s\n", temp_char);
5595  StrFree(temp_char);
5596  return status;
5597  }
5598  StrFree(temp_char);
5599  }
5600  else if (value_type == ROLLOVER_TYPE) {
5601  /* We need to convert the rollover scheme name into an id */
5602  value = KsmKeywordRollNameToValue(temp_char);
5603  if (value == 0) {
5604  printf("Error: unable to find rollover scheme %s\n", temp_char);
5605  StrFree(temp_char);
5606  return status;
5607  }
5608  StrFree(temp_char);
5609  }
5610  else {
5611  status = StrStrtoi(temp_char, &value);
5612  if (status != 0) {
5613  printf("Error: unable to convert %s to int\n", temp_char);
5614  StrFree(temp_char);
5615  return status;
5616  }
5617  if (value_type != INT_TYPE_NO_FREE) {
5618  StrFree(temp_char);
5619  }
5620  }
5621 
5622  /* Now update the policy with what we found, if it is different */
5623  if (value != current_value || current_value == 0) {
5624  status = KsmParameterSet(name, category, value, policy_id);
5625  if (status != 0) {
5626  printf("Error: unable to insert/update %s for policy\n", name);
5627  printf("Error: Is your database schema up to date?\n");
5628  return status;
5629  }
5630 
5631  /* Special step if salt length changed make sure that the salt is
5632  regenerated when the enforcer runs next */
5633  if (strncmp(name, "saltlength", 10) == 0) {
5634  status = KsmPolicyNullSaltStamp(policy_id);
5635  if (status != 0) {
5636  printf("Error: unable to insert/update %s for policy\n", name);
5637  printf("Error: Is your database schema up to date?\n");
5638  return status;
5639  }
5640  }
5641  }
5642 
5643  return 0;
5644 }
5645 
5646 void SetPolicyDefaults(KSM_POLICY *policy, char *name)
5647 {
5648  if (policy == NULL) {
5649  printf("Error, no policy provided");
5650  return;
5651  }
5652 
5653  if (name) {
5654  snprintf(policy->name, KSM_NAME_LENGTH, "%s", name);
5655  }
5656 
5657  policy->signer->refresh = 0;
5658  policy->signer->jitter = 0;
5659  policy->signer->propdelay = 0;
5660  policy->signer->soamin = 0;
5661  policy->signer->soattl = 0;
5662  policy->signer->serial = 0;
5663 
5664  policy->signature->clockskew = 0;
5665  policy->signature->resign = 0;
5666  policy->signature->valdefault = 0;
5667  policy->signature->valdenial = 0;
5668 
5669  policy->denial->version = 0;
5670  policy->denial->resalt = 0;
5671  policy->denial->algorithm = 0;
5672  policy->denial->iteration = 0;
5673  policy->denial->optout = 0;
5674  policy->denial->ttl = 0;
5675  policy->denial->saltlength = 0;
5676 
5677  policy->keys->ttl = 0;
5678  policy->keys->retire_safety = 0;
5679  policy->keys->publish_safety = 0;
5680  policy->keys->share_keys = 0;
5681  policy->keys->purge = -1;
5682 
5683  policy->ksk->algorithm = 0;
5684  policy->ksk->bits = 0;
5685  policy->ksk->lifetime = 0;
5686  policy->ksk->sm = 0;
5687  policy->ksk->overlap = 0;
5688  policy->ksk->ttl = 0;
5689  policy->ksk->rfc5011 = 0;
5690  policy->ksk->type = KSM_TYPE_KSK;
5691  policy->ksk->standby_keys = 0;
5692  policy->ksk->manual_rollover = 0;
5694 
5695  policy->zsk->algorithm = 0;
5696  policy->zsk->bits = 0;
5697  policy->zsk->lifetime = 0;
5698  policy->zsk->sm = 0;
5699  policy->zsk->overlap = 0;
5700  policy->zsk->ttl = 0;
5701  policy->zsk->rfc5011 = 0;
5702  policy->zsk->type = KSM_TYPE_ZSK;
5703  policy->zsk->standby_keys = 0;
5704  policy->zsk->manual_rollover = 0;
5705  policy->zsk->rollover_scheme = 0;
5706 
5707  policy->enforcer->keycreate = 0;
5708  policy->enforcer->backup_interval = 0;
5709  policy->enforcer->keygeninterval = 0;
5710 
5711  policy->zone->propdelay = 0;
5712  policy->zone->soa_ttl = 0;
5713  policy->zone->soa_min = 0;
5714  policy->zone->serial = 0;
5715 
5716  policy->parent->propdelay = 0;
5717  policy->parent->ds_ttl = 0;
5718  policy->parent->soa_ttl = 0;
5719  policy->parent->soa_min = 0;
5720 
5721 }
5722 
5723 /* make a backup of a file
5724  * Returns 0 on success
5725  * 1 on error
5726  * -1 if it could read the original but not open the backup
5727  */
5728 int backup_file(const char* orig_file, const char* backup_file)
5729 {
5730  FILE *from, *to;
5731  int ch;
5732 
5733  errno = 0;
5734  /* open source file */
5735  if((from = fopen( orig_file, "rb"))==NULL) {
5736  if (errno == ENOENT) {
5737  printf("File %s does not exist, nothing to backup\n", orig_file);
5738  return(0);
5739  }
5740  else {
5741  printf("Cannot open source file.\n");
5742  return(1); /* No point in trying to connect */
5743  }
5744  }
5745 
5746  /* open destination file */
5747  if((to = fopen(backup_file, "wb"))==NULL) {
5748  printf("Cannot open destination file, will not make backup.\n");
5749  fclose(from);
5750  return(-1);
5751  }
5752  else {
5753  /* copy the file */
5754  while(!feof(from)) {
5755  ch = fgetc(from);
5756  if(ferror(from)) {
5757  printf("Error reading source file.\n");
5758  fclose(from);
5759  fclose(to);
5760  return(1);
5761  }
5762  if(!feof(from)) fputc(ch, to);
5763  if(ferror(to)) {
5764  printf("Error writing destination file.\n");
5765  fclose(from);
5766  fclose(to);
5767  return(1);
5768  }
5769  }
5770 
5771  if(fclose(from)==EOF) {
5772  printf("Error closing source file.\n");
5773  fclose(to);
5774  return(1);
5775  }
5776 
5777  if(fclose(to)==EOF) {
5778  printf("Error closing destination file.\n");
5779  return(1);
5780  }
5781  }
5782  return(0);
5783 }
5784 
5785 /*
5786  * Given a conf.xml location extract the database details contained within it
5787  *
5788  * The caller will need to StrFree the char**s passed in
5789  *
5790  * Returns 0 if a full set of details was found
5791  * 1 if something didn't look right
5792  * -1 if any of the config files could not be read/parsed
5793  *
5794  */
5795  int
5796 get_db_details(char** dbschema, char** host, char** port, char** user, char** password)
5797 {
5798  /* All of the XML stuff */
5799  xmlDocPtr doc;
5800  xmlDocPtr rngdoc;
5801  xmlXPathContextPtr xpathCtx;
5802  xmlXPathObjectPtr xpathObj;
5803  xmlRelaxNGParserCtxtPtr rngpctx;
5804  xmlRelaxNGValidCtxtPtr rngctx;
5805  xmlRelaxNGPtr schema;
5806  xmlChar *litexpr = (unsigned char*) "//Configuration/Enforcer/Datastore/SQLite";
5807  xmlChar *mysql_host = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host";
5808  xmlChar *mysql_port = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host/@port";
5809  xmlChar *mysql_db = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Database";
5810  xmlChar *mysql_user = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Username";
5811  xmlChar *mysql_pass = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Password";
5812 
5813  int status;
5814  int db_found = 0;
5815  char* temp_char = NULL;
5816 
5817  /* Some files, the xml and rng */
5818  const char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng";
5819 
5820  /* Load XML document */
5821  doc = xmlParseFile(config);
5822  if (doc == NULL) {
5823  printf("Error: unable to parse file \"%s\"\n", config);
5824  return(-1);
5825  }
5826 
5827  /* Load rng document: TODO make the rng stuff optional? */
5828  rngdoc = xmlParseFile(rngfilename);
5829  if (rngdoc == NULL) {
5830  printf("Error: unable to parse file \"%s\"\n", rngfilename);
5831  xmlFreeDoc(doc);
5832  return(-1);
5833  }
5834 
5835  /* Create an XML RelaxNGs parser context for the relax-ng document. */
5836  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
5837  xmlFreeDoc(rngdoc);
5838  if (rngpctx == NULL) {
5839  printf("Error: unable to create XML RelaxNGs parser context\n");
5840  xmlFreeDoc(doc);
5841  return(-1);
5842  }
5843 
5844  /* parse a schema definition resource and build an internal XML Schema structure which can be used to validate instances. */
5845  schema = xmlRelaxNGParse(rngpctx);
5846  xmlRelaxNGFreeParserCtxt(rngpctx);
5847  if (schema == NULL) {
5848  printf("Error: unable to parse a schema definition resource\n");
5849  xmlFreeDoc(doc);
5850  return(-1);
5851  }
5852 
5853  /* Create an XML RelaxNGs validation context based on the given schema */
5854  rngctx = xmlRelaxNGNewValidCtxt(schema);
5855  if (rngctx == NULL) {
5856  printf("Error: unable to create RelaxNGs validation context based on the schema\n");
5857  xmlRelaxNGFree(schema);
5858  xmlFreeDoc(doc);
5859  return(-1);
5860  }
5861 
5862  /* Validate a document tree in memory. */
5863  status = xmlRelaxNGValidateDoc(rngctx,doc);
5864  xmlRelaxNGFreeValidCtxt(rngctx);
5865  xmlRelaxNGFree(schema);
5866  if (status != 0) {
5867  printf("Error validating file \"%s\"\n", config);
5868  xmlFreeDoc(doc);
5869  return(-1);
5870  }
5871 
5872  /* Now parse a value out of the conf */
5873  /* Create xpath evaluation context */
5874  xpathCtx = xmlXPathNewContext(doc);
5875  if(xpathCtx == NULL) {
5876  printf("Error: unable to create new XPath context\n");
5877  xmlFreeDoc(doc);
5878  return(-1);
5879  }
5880 
5881  /* Evaluate xpath expression for SQLite file location */
5882  xpathObj = xmlXPathEvalExpression(litexpr, xpathCtx);
5883  if(xpathObj == NULL) {
5884  printf("Error: unable to evaluate xpath expression: %s\n", litexpr);
5885  xmlXPathFreeContext(xpathCtx);
5886  xmlFreeDoc(doc);
5887  return(-1);
5888  }
5889  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
5890  db_found = SQLITE_DB;
5891  temp_char = (char *)xmlXPathCastToString(xpathObj);
5892  StrAppend(dbschema, temp_char);
5893  StrFree(temp_char);
5894  if (verbose_flag) {
5895  fprintf(stderr, "SQLite database set to: %s\n", *dbschema);
5896  }
5897  }
5898  xmlXPathFreeObject(xpathObj);
5899 
5900  if (db_found == 0) {
5901  db_found = MYSQL_DB;
5902 
5903  /* Get all of the MySQL stuff read in too */
5904  /* HOST, optional */
5905  xpathObj = xmlXPathEvalExpression(mysql_host, xpathCtx);
5906  if(xpathObj == NULL) {
5907  printf("Error: unable to evaluate xpath expression: %s\n", mysql_host);
5908  xmlXPathFreeContext(xpathCtx);
5909  xmlFreeDoc(doc);
5910  return(-1);
5911  }
5912  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
5913  temp_char = (char *)xmlXPathCastToString(xpathObj);
5914  StrAppend(host, temp_char);
5915  StrFree(temp_char);
5916  if (verbose_flag) {
5917  fprintf(stderr, "MySQL database host set to: %s\n", *host);
5918  }
5919  }
5920  xmlXPathFreeObject(xpathObj);
5921 
5922  /* PORT, optional */
5923  xpathObj = xmlXPathEvalExpression(mysql_port, xpathCtx);
5924  if(xpathObj == NULL) {
5925  printf("Error: unable to evaluate xpath expression: %s\n", mysql_port);
5926  xmlXPathFreeContext(xpathCtx);
5927  xmlFreeDoc(doc);
5928  return(-1);
5929  }
5930  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
5931  temp_char = (char *)xmlXPathCastToString(xpathObj);
5932  StrAppend(port, temp_char);
5933  StrFree(temp_char);
5934  if (verbose_flag) {
5935  fprintf(stderr, "MySQL database port set to: %s\n", *port);
5936  }
5937  }
5938  xmlXPathFreeObject(xpathObj);
5939 
5940  /* SCHEMA */
5941  xpathObj = xmlXPathEvalExpression(mysql_db, xpathCtx);
5942  if(xpathObj == NULL) {
5943  printf("Error: unable to evaluate xpath expression: %s\n", mysql_db);
5944  xmlXPathFreeContext(xpathCtx);
5945  xmlFreeDoc(doc);
5946  return(-1);
5947  }
5948  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
5949  temp_char = (char *)xmlXPathCastToString(xpathObj);
5950  StrAppend(dbschema, temp_char);
5951  StrFree(temp_char);
5952  if (verbose_flag) {
5953  fprintf(stderr, "MySQL database schema set to: %s\n", *dbschema);
5954  }
5955  } else {
5956  db_found = 0;
5957  }
5958  xmlXPathFreeObject(xpathObj);
5959 
5960  /* DB USER */
5961  xpathObj = xmlXPathEvalExpression(mysql_user, xpathCtx);
5962  if(xpathObj == NULL) {
5963  printf("Error: unable to evaluate xpath expression: %s\n", mysql_user);
5964  xmlXPathFreeContext(xpathCtx);
5965  xmlFreeDoc(doc);
5966  return(-1);
5967  }
5968  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
5969  temp_char = (char *)xmlXPathCastToString(xpathObj);
5970  StrAppend(user, temp_char);
5971  StrFree(temp_char);
5972  if (verbose_flag) {
5973  fprintf(stderr, "MySQL database user set to: %s\n", *user);
5974  }
5975  } else {
5976  db_found = 0;
5977  }
5978  xmlXPathFreeObject(xpathObj);
5979 
5980  /* DB PASSWORD */
5981  xpathObj = xmlXPathEvalExpression(mysql_pass, xpathCtx);
5982  if(xpathObj == NULL) {
5983  printf("Error: unable to evaluate xpath expression: %s\n", mysql_pass);
5984  xmlXPathFreeContext(xpathCtx);
5985  xmlFreeDoc(doc);
5986  return(-1);
5987  }
5988  /* password may be blank */
5989  temp_char = (char *)xmlXPathCastToString(xpathObj);
5990  StrAppend(password, temp_char);
5991  StrFree(temp_char);
5992  xmlXPathFreeObject(xpathObj);
5993 
5994  if (verbose_flag) {
5995  fprintf(stderr, "MySQL database password set\n");
5996  }
5997 
5998  }
5999 
6000  xmlXPathFreeContext(xpathCtx);
6001  xmlFreeDoc(doc);
6002 
6003  /* Check that we found one or the other database */
6004  if(db_found == 0) {
6005  printf("Error: unable to find complete database connection expression\n");
6006  return(-1);
6007  }
6008 
6009  /* Check that we found the right database type */
6010  if (db_found != DbFlavour()) {
6011  printf("Error: Config file %s specifies database type %s but system is compiled to use %s\n", config, (db_found==1) ? "MySQL" : "sqlite3", (db_found==2) ? "MySQL" : "sqlite3");
6012  return(-1);
6013  }
6014 
6015  return(status);
6016 }
6017 
6018 /*
6019  * Read the conf.xml file, we will not validate as that was done as we read the database.
6020  * Instead we just extract the RepositoryList into the database and also learn the
6021  * location of the zonelist.
6022  */
6023 int read_zonelist_filename(char** zone_list_filename)
6024 {
6025  xmlTextReaderPtr reader = NULL;
6026  xmlDocPtr doc = NULL;
6027  xmlXPathContextPtr xpathCtx = NULL;
6028  xmlXPathObjectPtr xpathObj = NULL;
6029  int ret = 0; /* status of the XML parsing */
6030  char* temp_char = NULL;
6031  char* tag_name = NULL;
6032 
6033  xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile";
6034 
6035  /* Start reading the file; we will be looking for "Common" tags */
6036  reader = xmlNewTextReaderFilename(config);
6037  if (reader != NULL) {
6038  ret = xmlTextReaderRead(reader);
6039  while (ret == 1) {
6040  tag_name = (char*) xmlTextReaderLocalName(reader);
6041  /* Found <Common> */
6042  if (strncmp(tag_name, "Common", 6) == 0
6043  && xmlTextReaderNodeType(reader) == 1) {
6044 
6045  /* Expand this node and get the rest of the info with XPath */
6046  xmlTextReaderExpand(reader);
6047  doc = xmlTextReaderCurrentDoc(reader);
6048  if (doc == NULL) {
6049  printf("Error: can not read Common section\n");
6050  /* Don't return? try to parse the rest of the file? */
6051  ret = xmlTextReaderRead(reader);
6052  continue;
6053  }
6054 
6055  xpathCtx = xmlXPathNewContext(doc);
6056  if(xpathCtx == NULL) {
6057  printf("Error: can not create XPath context for Common section\n");
6058  /* Don't return? try to parse the rest of the file? */
6059  ret = xmlTextReaderRead(reader);
6060  continue;
6061  }
6062 
6063  /* Evaluate xpath expression for ZoneListFile */
6064  xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx);
6065  if(xpathObj == NULL) {
6066  printf("Error: unable to evaluate xpath expression: %s\n", zonelist_expr);
6067  /* Don't return? try to parse the rest of the file? */
6068  ret = xmlTextReaderRead(reader);
6069  continue;
6070  }
6071  *zone_list_filename = NULL;
6072  temp_char = (char *)xmlXPathCastToString(xpathObj);
6073  xmlXPathFreeObject(xpathObj);
6074  StrAppend(zone_list_filename, temp_char);
6075  StrFree(temp_char);
6076  printf("zonelist filename set to %s.\n", *zone_list_filename);
6077  }
6078  /* Read the next line */
6079  ret = xmlTextReaderRead(reader);
6080  StrFree(tag_name);
6081  }
6082  xmlFreeTextReader(reader);
6083  if (ret != 0) {
6084  printf("%s : failed to parse\n", config);
6085  return(1);
6086  }
6087  } else {
6088  printf("Unable to open %s\n", config);
6089  return(1);
6090  }
6091  if (xpathCtx) {
6092  xmlXPathFreeContext(xpathCtx);
6093  }
6094  if (doc) {
6095  xmlFreeDoc(doc);
6096  }
6097 
6098  return 0;
6099 }
6100 
6101 xmlDocPtr add_zone_node(const char *docname,
6102  const char *zone_name,
6103  const char *policy_name,
6104  const char *sig_conf_name,
6105  const char *input_name,
6106  const char *output_name,
6107  const char *input_type,
6108  const char *output_type)
6109 {
6110  xmlDocPtr doc;
6111  xmlNodePtr cur;
6112  xmlNodePtr newzonenode;
6113  xmlNodePtr newadaptnode;
6114  xmlNodePtr newinputnode;
6115  xmlNodePtr newinadnode;
6116  xmlNodePtr newoutputnode;
6117  xmlNodePtr newoutadnode;
6118  doc = xmlParseFile(docname);
6119  if (doc == NULL ) {
6120  fprintf(stderr,"Document not parsed successfully. \n");
6121  return (NULL);
6122  }
6123  cur = xmlDocGetRootElement(doc);
6124  if (cur == NULL) {
6125  fprintf(stderr,"empty document\n");
6126  xmlFreeDoc(doc);
6127  return (NULL);
6128  }
6129  if (xmlStrcmp(cur->name, (const xmlChar *) "ZoneList")) {
6130  fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList");
6131  xmlFreeDoc(doc);
6132  return (NULL);
6133  }
6134  newzonenode = xmlNewTextChild(cur, NULL, (const xmlChar *)"Zone", NULL);
6135  (void) xmlNewProp(newzonenode, (const xmlChar *)"name", (const xmlChar *)zone_name);
6136 
6137  (void) xmlNewTextChild (newzonenode, NULL, (const xmlChar *)"Policy", (const xmlChar *)policy_name);
6138 
6139  (void) xmlNewTextChild (newzonenode, NULL, (const xmlChar *)"SignerConfiguration", (const xmlChar *)sig_conf_name);
6140 
6141  newadaptnode = xmlNewChild (newzonenode, NULL, (const xmlChar *)"Adapters", NULL);
6142 
6143  newinputnode = xmlNewChild (newadaptnode, NULL, (const xmlChar *)"Input", NULL);
6144 
6145  newinadnode = xmlNewTextChild (newinputnode, NULL, (const xmlChar *)"Adapter", (const xmlChar *)input_name);
6146  (void) xmlNewProp(newinadnode, (const xmlChar *)"type", (const xmlChar *)input_type);
6147 
6148  newoutputnode = xmlNewChild (newadaptnode, NULL, (const xmlChar *)"Output", NULL);
6149 
6150  newoutadnode = xmlNewTextChild (newoutputnode, NULL, (const xmlChar *)"Adapter", (const xmlChar *)output_name);
6151  (void) xmlNewProp(newoutadnode, (const xmlChar *)"type", (const xmlChar *)output_type);
6152 
6153  return(doc);
6154 }
6155 
6156 xmlDocPtr del_zone_node(const char *docname,
6157  const char *zone_name)
6158 {
6159  xmlDocPtr doc;
6160  xmlNodePtr root;
6161  xmlNodePtr cur;
6162 
6163  doc = xmlParseFile(docname);
6164  if (doc == NULL ) {
6165  fprintf(stderr,"Document not parsed successfully. \n");
6166  return (NULL);
6167  }
6168  root = xmlDocGetRootElement(doc);
6169  if (root == NULL) {
6170  fprintf(stderr,"empty document\n");
6171  xmlFreeDoc(doc);
6172  return (NULL);
6173  }
6174  if (xmlStrcmp(root->name, (const xmlChar *) "ZoneList")) {
6175  fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList");
6176  xmlFreeDoc(doc);
6177  return (NULL);
6178  }
6179 
6180  /* If we are removing all zones then just replace the root node with an empty one */
6181  if (all_flag == 1) {
6182  cur = root->children;
6183  while (cur != NULL)
6184  {
6185  xmlUnlinkNode(cur);
6186  xmlFreeNode(cur);
6187 
6188  cur = root->children;
6189  }
6190  }
6191  else {
6192 
6193  /* Zone nodes are children of the root */
6194  for(cur = root->children; cur != NULL; cur = cur->next)
6195  {
6196  /* is this the zone we are looking for? */
6197  if (xmlStrcmp( xmlGetProp(cur, (xmlChar *) "name"), (const xmlChar *) zone_name) == 0)
6198  {
6199  xmlUnlinkNode(cur);
6200 
6201  cur = root->children; /* May pass through multiple times, but will remove all instances of the zone */
6202  }
6203  }
6204  xmlFreeNode(cur);
6205  }
6206 
6207  return(doc);
6208 }
6209 
6210 void list_zone_node(const char *docname, int *zone_ids)
6211 {
6212  xmlDocPtr doc;
6213  xmlNodePtr root;
6214  xmlNodePtr cur;
6215  xmlNodePtr pol;
6216  xmlChar *polChar = NULL;
6217  xmlChar *propChar = NULL;
6218 
6219  int temp_id;
6220  int i = 0;
6221  int status = 0;
6222 
6223  doc = xmlParseFile(docname);
6224  if (doc == NULL ) {
6225  fprintf(stderr,"Document not parsed successfully. \n");
6226  return;
6227  }
6228  root = xmlDocGetRootElement(doc);
6229  if (root == NULL) {
6230  fprintf(stderr,"empty document\n");
6231  xmlFreeDoc(doc);
6232  return;
6233  }
6234  if (xmlStrcmp(root->name, (const xmlChar *) "ZoneList")) {
6235  fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList");
6236  xmlFreeDoc(doc);
6237  return;
6238  }
6239 
6240  /* Zone nodes are children of the root */
6241  for(cur = root->children; cur != NULL; cur = cur->next)
6242  {
6243  if (xmlStrcmp( cur->name, (const xmlChar *)"Zone") == 0) {
6244  propChar = xmlGetProp(cur, (xmlChar *) "name");
6245  printf("Found Zone: %s", propChar);
6246 
6247  /* make a note of the zone_id */
6248  status = KsmZoneIdFromName((char *) propChar, &temp_id);
6249  xmlFree(propChar);
6250  if (status != 0) {
6251  printf(" (zone not in database)");
6252  zone_ids[i] = 0;
6253  } else {
6254  zone_ids[i] = temp_id;
6255  i++;
6256  }
6257 
6258  /* Print the policy name for this zone */
6259  for(pol = cur->children; pol != NULL; pol = pol->next)
6260  {
6261  if (xmlStrcmp( pol->name, (const xmlChar *)"Policy") == 0)
6262  {
6263  polChar = xmlNodeGetContent(pol);
6264  printf("; on policy %s\n", polChar);
6265  xmlFree(polChar);
6266  }
6267  }
6268  }
6269  }
6270 
6271  xmlFreeDoc(doc);
6272 
6273  return;
6274 }
6275 
6276 /*
6277  * Given a doc that has the start of the kasp-like xml and a policy structure
6278  * create the policy tag and contents in that doc
6279  */
6280 int append_policy(xmlDocPtr doc, KSM_POLICY *policy)
6281 {
6282  xmlNodePtr root;
6283  xmlNodePtr policy_node;
6284  xmlNodePtr signatures_node;
6285  xmlNodePtr validity_node;
6286  xmlNodePtr denial_node;
6287  xmlNodePtr nsec_node;
6288  xmlNodePtr hash_node;
6289  xmlNodePtr salt_node;
6290  xmlNodePtr keys_node;
6291  xmlNodePtr ksk_node;
6292  xmlNodePtr ksk_alg_node;
6293  xmlNodePtr zsk_node;
6294  xmlNodePtr zsk_alg_node;
6295  xmlNodePtr zone_node;
6296  xmlNodePtr zone_soa_node;
6297  xmlNodePtr parent_node;
6298  xmlNodePtr parent_ds_node;
6299  xmlNodePtr parent_soa_node;
6300 
6301  char temp_time[32];
6302 
6303  root = xmlDocGetRootElement(doc);
6304  if (root == NULL) {
6305  fprintf(stderr,"empty document\n");
6306  return(1);
6307  }
6308  if (xmlStrcmp(root->name, (const xmlChar *) "KASP")) {
6309  fprintf(stderr,"document of the wrong type, root node != %s", "KASP");
6310  return(1);
6311  }
6312 
6313  policy_node = xmlNewTextChild(root, NULL, (const xmlChar *)"Policy", NULL);
6314  (void) xmlNewProp(policy_node, (const xmlChar *)"name", (const xmlChar *)policy->name);
6315  (void) xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Description", (const xmlChar *)policy->description);
6316 
6317  /* SIGNATURES */
6318  signatures_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Signatures", NULL);
6319  snprintf(temp_time, 32, "PT%dS", policy->signature->resign);
6320  (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Resign", (const xmlChar *)temp_time);
6321  snprintf(temp_time, 32, "PT%dS", policy->signer->refresh);
6322  (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Refresh", (const xmlChar *)temp_time);
6323  validity_node = xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Validity", NULL);
6324  snprintf(temp_time, 32, "PT%dS", policy->signature->valdefault);
6325  (void) xmlNewTextChild(validity_node, NULL, (const xmlChar *)"Default", (const xmlChar *)temp_time);
6326  snprintf(temp_time, 32, "PT%dS", policy->signature->valdenial);
6327  (void) xmlNewTextChild(validity_node, NULL, (const xmlChar *)"Denial", (const xmlChar *)temp_time);
6328  snprintf(temp_time, 32, "PT%dS", policy->signer->jitter);
6329  (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Jitter", (const xmlChar *)temp_time);
6330  snprintf(temp_time, 32, "PT%dS", policy->signature->clockskew);
6331  (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"InceptionOffset", (const xmlChar *)temp_time);
6332 
6333  /* DENIAL */
6334  denial_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Denial", NULL);
6335  if (policy->denial->version == 1) /* NSEC */
6336  {
6337  (void) xmlNewTextChild(denial_node, NULL, (const xmlChar *)"NSEC", NULL);
6338  }
6339  else /* NSEC3 */
6340  {
6341  nsec_node = xmlNewTextChild(denial_node, NULL, (const xmlChar *)"NSEC3", NULL);
6342  if (policy->denial->ttl != 0) {
6343  snprintf(temp_time, 32, "PT%dS", policy->denial->ttl);
6344  (void) xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time);
6345  }
6346  if (policy->denial->optout == 1)
6347  {
6348  (void) xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"OptOut", NULL);
6349  }
6350  snprintf(temp_time, 32, "PT%dS", policy->denial->resalt);
6351  (void) xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"Resalt", (const xmlChar *)temp_time);
6352  hash_node = xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"Hash", NULL);
6353  snprintf(temp_time, 32, "%d", policy->denial->algorithm);
6354  (void) xmlNewTextChild(hash_node, NULL, (const xmlChar *)"Algorithm", (const xmlChar *)temp_time);
6355  snprintf(temp_time, 32, "%d", policy->denial->iteration);
6356  (void) xmlNewTextChild(hash_node, NULL, (const xmlChar *)"Iterations", (const xmlChar *)temp_time);
6357  snprintf(temp_time, 32, "%d", policy->denial->saltlength);
6358  salt_node = xmlNewTextChild(hash_node, NULL, (const xmlChar *)"Salt", NULL);
6359  (void) xmlNewProp(salt_node, (const xmlChar *)"length", (const xmlChar *)temp_time);
6360  }
6361 
6362  /* KEYS */
6363  keys_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Keys", NULL);
6364  snprintf(temp_time, 32, "PT%dS", policy->keys->ttl);
6365  (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time);
6366  snprintf(temp_time, 32, "PT%dS", policy->keys->retire_safety);
6367  (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"RetireSafety", (const xmlChar *)temp_time);
6368  snprintf(temp_time, 32, "PT%dS", policy->keys->publish_safety);
6369  (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"PublishSafety", (const xmlChar *)temp_time);
6370  if (policy->keys->share_keys == 1)
6371  {
6372  (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"ShareKeys", NULL);
6373  }
6374  if (policy->keys->purge != -1) {
6375  snprintf(temp_time, 32, "PT%dS", policy->keys->purge);
6376  (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"Purge", (const xmlChar *)temp_time);
6377  }
6378  /*(void) xmlNewDocComment(doc, (const xmlChar *)"Parameters that are different for zsks and ksks");*/
6379  /* KSK */
6380  ksk_node = xmlNewTextChild(keys_node, NULL, (const xmlChar *)"KSK", NULL);
6381  snprintf(temp_time, 32, "%d", policy->ksk->algorithm);
6382  ksk_alg_node = xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Algorithm", (const xmlChar *)temp_time);
6383  snprintf(temp_time, 32, "%d", policy->ksk->bits);
6384  (void) xmlNewProp(ksk_alg_node, (const xmlChar *)"length", (const xmlChar *)temp_time);
6385  snprintf(temp_time, 32, "PT%dS", policy->ksk->lifetime);
6386  (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Lifetime", (const xmlChar *)temp_time);
6387  (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Repository", (const xmlChar *)policy->ksk->sm_name);
6388  snprintf(temp_time, 32, "%d", policy->ksk->standby_keys);
6389  (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Standby", (const xmlChar *)temp_time);
6390  if (policy->ksk->manual_rollover == 1)
6391  {
6392  (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"ManualRollover", NULL);
6393  }
6394  if (policy->ksk->rfc5011 == 1)
6395  {
6396  (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"RFC5011", NULL);
6397  }
6398 /* if (policy->ksk->rollover_scheme != 0)
6399  {
6400  (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"RolloverScheme", (const xmlChar *) KsmKeywordRollValueToName(policy->ksk->rollover_scheme));
6401  }*/
6402 
6403  /* ZSK */
6404  zsk_node = xmlNewTextChild(keys_node, NULL, (const xmlChar *)"ZSK", NULL);
6405  snprintf(temp_time, 32, "%d", policy->zsk->algorithm);
6406  zsk_alg_node = xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Algorithm", (const xmlChar *)temp_time);
6407  snprintf(temp_time, 32, "%d", policy->zsk->bits);
6408  (void) xmlNewProp(zsk_alg_node, (const xmlChar *)"length", (const xmlChar *)temp_time);
6409  snprintf(temp_time, 32, "PT%dS", policy->zsk->lifetime);
6410  (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Lifetime", (const xmlChar *)temp_time);
6411  (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Repository", (const xmlChar *)policy->zsk->sm_name);
6412  snprintf(temp_time, 32, "%d", policy->zsk->standby_keys);
6413  (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Standby", (const xmlChar *)temp_time);
6414  if (policy->zsk->manual_rollover == 1)
6415  {
6416  (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"ManualRollover", NULL);
6417  }
6418 
6419  /* ZONE */
6420  zone_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Zone", NULL);
6421  snprintf(temp_time, 32, "PT%dS", policy->zone->propdelay);
6422  (void) xmlNewTextChild(zone_node, NULL, (const xmlChar *)"PropagationDelay", (const xmlChar *)temp_time);
6423  zone_soa_node = xmlNewTextChild(zone_node, NULL, (const xmlChar *)"SOA", NULL);
6424  snprintf(temp_time, 32, "PT%dS", policy->zone->soa_ttl);
6425  (void) xmlNewTextChild(zone_soa_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time);
6426  snprintf(temp_time, 32, "PT%dS", policy->zone->soa_min);
6427  (void) xmlNewTextChild(zone_soa_node, NULL, (const xmlChar *)"Minimum", (const xmlChar *)temp_time);
6428  (void) xmlNewTextChild(zone_soa_node, NULL, (const xmlChar *)"Serial", (const xmlChar *) KsmKeywordSerialValueToName(policy->zone->serial));
6429 
6430  /* PARENT */
6431  parent_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Parent", NULL);
6432  snprintf(temp_time, 32, "PT%dS", policy->parent->propdelay);
6433  (void) xmlNewTextChild(parent_node, NULL, (const xmlChar *)"PropagationDelay", (const xmlChar *)temp_time);
6434  parent_ds_node = xmlNewTextChild(parent_node, NULL, (const xmlChar *)"DS", NULL);
6435  snprintf(temp_time, 32, "PT%dS", policy->parent->ds_ttl);
6436  (void) xmlNewTextChild(parent_ds_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time);
6437  parent_soa_node = xmlNewTextChild(parent_node, NULL, (const xmlChar *)"SOA", NULL);
6438  snprintf(temp_time, 32, "PT%dS", policy->parent->soa_ttl);
6439  (void) xmlNewTextChild(parent_soa_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time);
6440  snprintf(temp_time, 32, "PT%dS", policy->parent->soa_min);
6441  (void) xmlNewTextChild(parent_soa_node, NULL, (const xmlChar *)"Minimum", (const xmlChar *)temp_time);
6442 
6443  return(0);
6444 }
6445 
6446 /*
6447  * Delete a policy node from kasp.xml
6448  */
6449 xmlDocPtr del_policy_node(const char *docname,
6450  const char *policy_name)
6451 {
6452  xmlDocPtr doc;
6453  xmlNodePtr root;
6454  xmlNodePtr cur;
6455 
6456  doc = xmlParseFile(docname);
6457  if (doc == NULL ) {
6458  fprintf(stderr,"Document not parsed successfully. \n");
6459  return (NULL);
6460  }
6461  root = xmlDocGetRootElement(doc);
6462  if (root == NULL) {
6463  fprintf(stderr,"empty document\n");
6464  xmlFreeDoc(doc);
6465  return (NULL);
6466  }
6467  if (xmlStrcmp(root->name, (const xmlChar *) "KASP")) {
6468  fprintf(stderr,"document of the wrong type, root node != %s", "KASP");
6469  xmlFreeDoc(doc);
6470  return (NULL);
6471  }
6472 
6473 
6474  /* Policy nodes are children of the root */
6475  for(cur = root->children; cur != NULL; cur = cur->next)
6476  {
6477  /* is this the zone we are looking for? */
6478  if (xmlStrcmp( xmlGetProp(cur, (xmlChar *) "name"), (const xmlChar *) policy_name) == 0)
6479  {
6480  xmlUnlinkNode(cur);
6481 
6482  cur = root->children; /* May pass through multiple times, but will remove all instances of the policy */
6483  }
6484  }
6485  xmlFreeNode(cur);
6486 
6487  return(doc);
6488 }
6489 
6490 /*
6491  * CallBack to print key info to stdout
6492  */
6493 int printKey(void* context, KSM_KEYDATA* key_data)
6494 {
6495  if (key_data->state == KSM_STATE_RETIRE && strcasecmp(key_data->retire, (char *)context) == 0) {
6496  if (key_data->keytype == KSM_TYPE_KSK)
6497  {
6498  fprintf(stdout, "KSK:");
6499  }
6500  if (key_data->keytype == KSM_TYPE_ZSK)
6501  {
6502  fprintf(stdout, "ZSK:");
6503  }
6504  fprintf(stdout, " %s Retired\n", key_data->location);
6505  }
6506 
6507  return 0;
6508 }
6509 
6510 /*
6511  * log function suitable for libksm callback
6512  */
6513  void
6514 ksm_log_msg(const char *format)
6515 {
6516  fprintf(stderr, "%s\n", format);
6517 }
6518 
6519 /*+
6520  * ListKeys - Output a list of Keys
6521  *
6522  *
6523  * Arguments:
6524  *
6525  * int zone_id
6526  * ID of the zone (-1 for all)
6527  *
6528  * Returns:
6529  * int
6530  * Status return. 0 on success.
6531  * other on fail
6532  */
6533 
6534 int ListKeys(int zone_id)
6535 {
6536  char* sql = NULL; /* SQL query */
6537  int status = 0; /* Status return */
6538  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
6539  DB_RESULT result; /* Result of the query */
6540  DB_ROW row = NULL; /* Row data */
6541  int done_row = 0; /* Have we printed a row this loop? */
6542 
6543  char* temp_zone = NULL; /* place to store zone name returned */
6544  int temp_type = 0; /* place to store key type returned */
6545  int temp_state = 0; /* place to store key state returned */
6546  char* temp_ready = NULL; /* place to store ready date returned */
6547  char* temp_active = NULL; /* place to store active date returned */
6548  char* temp_retire = NULL; /* place to store retire date returned */
6549  char* temp_dead = NULL; /* place to store dead date returned */
6550  char* temp_loc = NULL; /* place to store location returned */
6551  char* temp_hsm = NULL; /* place to store hsm returned */
6552  int temp_alg = 0; /* place to store algorithm returned */
6553  int temp_size = 0; /* place to store size returned */
6554 
6555  /* Key information */
6556  hsm_key_t *key = NULL;
6557  ldns_rr *dnskey_rr = NULL;
6558  hsm_sign_params_t *sign_params = NULL;
6559 
6560  if (verbose_flag) {
6561  /* connect to the HSM */
6562  status = hsm_open(config, hsm_prompt_pin);
6563  if (status) {
6564  hsm_print_error(NULL);
6565  return(-1);
6566  }
6567  }
6568 
6569  /* Select rows */
6570  StrAppend(&sql, "select z.name, k.keytype, k.state, k.ready, k.active, k.retire, k.dead, k.location, s.name, k.algorithm, k.size from securitymodules s, zones z, KEYDATA_VIEW k where z.id = k.zone_id and s.id = k.securitymodule_id and state != 6 and zone_id is not null ");
6571  if (zone_id != -1) {
6572  StrAppend(&sql, "and zone_id = ");
6573  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
6574  StrAppend(&sql, stringval);
6575  }
6576  StrAppend(&sql, " order by zone_id");
6577 
6578  DusEnd(&sql);
6579 
6580  status = DbExecuteSql(DbHandle(), sql, &result);
6581 
6582  if (status == 0) {
6583  status = DbFetchRow(result, &row);
6584  if (verbose_flag == 1) {
6585  printf("Zone: Keytype: State: Date of next transition (to): Size: Algorithm: CKA_ID: Repository: Keytag:\n");
6586  }
6587  else {
6588  printf("Zone: Keytype: State: Date of next transition:\n");
6589  }
6590  while (status == 0) {
6591  /* Got a row, print it */
6592  DbString(row, 0, &temp_zone);
6593  DbInt(row, 1, &temp_type);
6594  DbInt(row, 2, &temp_state);
6595  DbString(row, 3, &temp_ready);
6596  DbString(row, 4, &temp_active);
6597  DbString(row, 5, &temp_retire);
6598  DbString(row, 6, &temp_dead);
6599  DbString(row, 7, &temp_loc);
6600  DbString(row, 8, &temp_hsm);
6601  DbInt(row, 9, &temp_alg);
6602  DbInt(row, 10, &temp_size);
6603  done_row = 0;
6604 
6605  if (temp_state == KSM_STATE_PUBLISH) {
6606  printf("%-31s %-13s %-9s %-20s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_ready == NULL) ? "(not scheduled)" : temp_ready);
6607  if (verbose_flag) {
6608  printf("(ready) ");
6609  }
6610  done_row = 1;
6611  }
6612  else if (temp_state == KSM_STATE_READY) {
6613  printf("%-31s %-13s %-9s %-20s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_type == KSM_TYPE_KSK) ? "waiting for ds-seen" : "next rollover");
6614  if (verbose_flag) {
6615  printf("(active) ");
6616  }
6617  done_row = 1;
6618  }
6619  else if (temp_state == KSM_STATE_ACTIVE) {
6620  printf("%-31s %-13s %-9s %-20s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_retire == NULL) ? "(not scheduled)" : temp_retire);
6621  if (verbose_flag) {
6622  printf("(retire) ");
6623  }
6624  done_row = 1;
6625  }
6626  else if (temp_state == KSM_STATE_RETIRE) {
6627  printf("%-31s %-13s %-9s %-20s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_dead == NULL) ? "(not scheduled)" : temp_dead);
6628  if (verbose_flag) {
6629  printf("(dead) ");
6630  }
6631  done_row = 1;
6632  }
6633  else if (temp_state == KSM_STATE_DSSUB) {
6634  printf("%-31s %-13s %-9s %-20s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), "waiting for ds-seen");
6635  if (verbose_flag) {
6636  printf("(dspub) ");
6637  }
6638  done_row = 1;
6639  }
6640  else if (temp_state == KSM_STATE_DSPUBLISH) {
6641  printf("%-31s %-13s %-9s %-20s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), (temp_ready == NULL) ? "(not scheduled)" : temp_ready);
6642  if (verbose_flag) {
6643  printf("(dsready) ");
6644  }
6645  done_row = 1;
6646  }
6647  else if (temp_state == KSM_STATE_DSREADY) {
6648  printf("%-31s %-13s %-9s %-20s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), "When required");
6649  if (verbose_flag) {
6650  printf("(keypub) ");
6651  }
6652  done_row = 1;
6653  }
6654  else if (temp_state == KSM_STATE_KEYPUBLISH) {
6655  printf("%-31s %-13s %-9s %-20s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), (temp_active == NULL) ? "(not scheduled)" : temp_active);
6656  if (verbose_flag) {
6657  printf("(active) ");
6658  }
6659  done_row = 1;
6660  }
6661 
6662  if (done_row == 1 && verbose_flag == 1) {
6663  printf("%-7d %-12d", temp_size, temp_alg);
6664  key = hsm_find_key_by_id(NULL, temp_loc);
6665  if (!key) {
6666  printf("%-33s %s NOT IN repository\n", temp_loc, temp_hsm);
6667  } else {
6668  sign_params = hsm_sign_params_new();
6669  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, temp_zone);
6670  sign_params->algorithm = temp_alg;
6671  sign_params->flags = LDNS_KEY_ZONE_KEY;
6672  if (temp_type == KSM_TYPE_KSK) {
6673  sign_params->flags += LDNS_KEY_SEP_KEY;
6674  }
6675  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
6676  sign_params->keytag = ldns_calc_keytag(dnskey_rr);
6677 
6678  printf("%-33s %-33s %d\n", temp_loc, temp_hsm, sign_params->keytag);
6679 
6680  hsm_sign_params_free(sign_params);
6681  hsm_key_free(key);
6682  }
6683  }
6684  else if (done_row == 1) {
6685  printf("\n");
6686  }
6687 
6688  status = DbFetchRow(result, &row);
6689  }
6690 
6691  /* Convert EOF status to success */
6692 
6693  if (status == -1) {
6694  status = 0;
6695  }
6696 
6697  DbFreeResult(result);
6698  }
6699 
6700  DusFree(sql);
6701  DbFreeRow(row);
6702 
6703  DbStringFree(temp_zone);
6704  DbStringFree(temp_ready);
6705  DbStringFree(temp_active);
6706  DbStringFree(temp_retire);
6707  DbStringFree(temp_dead);
6708  DbStringFree(temp_loc);
6709  DbStringFree(temp_hsm);
6710 
6711  if (dnskey_rr != NULL) {
6712  ldns_rr_free(dnskey_rr);
6713  }
6714 
6715  if (verbose_flag) {
6716  hsm_close();
6717  }
6718 
6719  return status;
6720 }
6721 
6722 /*+
6723  * PurgeKeys - Purge dead Keys
6724  *
6725  *
6726  * Arguments:
6727  *
6728  * int zone_id
6729  * ID of the zone
6730  *
6731  * int policy_id
6732  * ID of the policy
6733  *
6734  * N.B. Only one of the arguments should be set, the other should be -1
6735  *
6736  * Returns:
6737  * int
6738  * Status return. 0 on success.
6739  * other on fail
6740  */
6741 
6742 int PurgeKeys(int zone_id, int policy_id)
6743 {
6744  char* sql = NULL; /* SQL query */
6745  char* sql1 = NULL; /* SQL query */
6746  char* sql2 = NULL; /* SQL query */
6747  char* sql3 = NULL; /* SQL query */
6748  int status = 0; /* Status return */
6749  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
6750  DB_RESULT result; /* Result of the query */
6751  DB_ROW row = NULL; /* Row data */
6752 
6753  int temp_id = -1; /* place to store the key id returned */
6754  char* temp_loc = NULL; /* place to store location returned */
6755  int count = 0; /* How many keys don't match the purge */
6756 
6757  int done_something = 0; /* have we done anything? */
6758 
6759  /* Key information */
6760  hsm_key_t *key = NULL;
6761 
6762  if ((zone_id == -1 && policy_id == -1) ||
6763  (zone_id != -1 && policy_id != -1)){
6764  printf("Please provide either a zone OR a policy to key purge\n");
6765  usage_keypurge();
6766  return(1);
6767  }
6768 
6769  /* connect to the HSM */
6770  status = hsm_open(config, hsm_prompt_pin);
6771  if (status) {
6772  hsm_print_error(NULL);
6773  return(-1);
6774  }
6775 
6776  /* Select rows */
6777  StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
6778  if (zone_id != -1) {
6779  StrAppend(&sql, "and zone_id = ");
6780  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
6781  StrAppend(&sql, stringval);
6782  }
6783  if (policy_id != -1) {
6784  StrAppend(&sql, "and policy_id = ");
6785  snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
6786  StrAppend(&sql, stringval);
6787  }
6788  DusEnd(&sql);
6789 
6790  status = DbExecuteSql(DbHandle(), sql, &result);
6791 
6792  if (status == 0) {
6793  status = DbFetchRow(result, &row);
6794  while (status == 0) {
6795  /* Got a row, check it */
6796  DbInt(row, 0, &temp_id);
6797  DbString(row, 1, &temp_loc);
6798 
6799  sql1 = DqsCountInit("dnsseckeys");
6800  DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
6801  DdsConditionInt(&sql1, "state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
6802  DqsEnd(&sql1);
6803 
6804  status = DbIntQuery(DbHandle(), &count, sql1);
6805  DqsFree(sql1);
6806 
6807  if (status != 0) {
6808  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
6809  DbStringFree(temp_loc);
6810  DbFreeRow(row);
6811  DusFree(sql);
6812  hsm_close();
6813  return status;
6814  }
6815 
6816  /* If the count is zero then there is no reason not to purge this key */
6817  if (count == 0) {
6818 
6819  done_something = 1;
6820 
6821  /* Delete from dnsseckeys */
6822  sql2 = DdsInit("dnsseckeys");
6823  DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
6824  DdsEnd(&sql2);
6825 
6826  status = DbExecuteSqlNoResult(DbHandle(), sql2);
6827  DdsFree(sql2);
6828  if (status != 0)
6829  {
6830  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
6831  DbStringFree(temp_loc);
6832  DbFreeRow(row);
6833  DusFree(sql);
6834  hsm_close();
6835  return status;
6836  }
6837 
6838  /* Delete from keypairs */
6839  sql3 = DdsInit("keypairs");
6840  DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
6841  DdsEnd(&sql3);
6842 
6843  status = DbExecuteSqlNoResult(DbHandle(), sql3);
6844  DdsFree(sql3);
6845  if (status != 0)
6846  {
6847  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
6848  DbStringFree(temp_loc);
6849  DbFreeRow(row);
6850  DusFree(sql);
6851  hsm_close();
6852  return status;
6853  }
6854 
6855  /* Delete from the HSM */
6856  key = hsm_find_key_by_id(NULL, temp_loc);
6857 
6858  if (!key) {
6859  printf("Key not found: %s\n", temp_loc);
6860  DbStringFree(temp_loc);
6861  DbFreeRow(row);
6862  DusFree(sql);
6863  hsm_close();
6864  return -1;
6865  }
6866 
6867  status = hsm_remove_key(NULL, key);
6868 
6869  hsm_key_free(key);
6870 
6871  if (!status) {
6872  printf("Key remove successful: %s\n", temp_loc);
6873  } else {
6874  printf("Key remove failed: %s\n", temp_loc);
6875  DbStringFree(temp_loc);
6876  DbFreeRow(row);
6877  DusFree(sql);
6878  hsm_close();
6879  return -1;
6880  }
6881  }
6882 
6883  /* NEXT! */
6884  status = DbFetchRow(result, &row);
6885  }
6886 
6887  /* Convert EOF status to success */
6888 
6889  if (status == -1) {
6890  status = 0;
6891  }
6892 
6893  DbFreeResult(result);
6894  }
6895 
6896  if (done_something == 0) {
6897  printf("No keys to purge.\n");
6898  }
6899 
6900  DusFree(sql);
6901  DbFreeRow(row);
6902 
6903  DbStringFree(temp_loc);
6904 
6905  hsm_close();
6906 
6907  return status;
6908 }
6909 
6911 {
6912  int status = 0;
6913 
6914  int interval = -1;
6915 
6916  KSM_POLICY* policy;
6917  hsm_ctx_t *ctx = NULL;
6918 
6919  char *rightnow;
6920  int i = 0;
6921  char *id;
6922  hsm_key_t *key = NULL;
6923  char *hsm_error_message = NULL;
6924  DB_ID ignore = 0;
6925  int ksks_needed = 0; /* Total No of ksks needed before next generation run */
6926  int zsks_needed = 0; /* Total No of zsks needed before next generation run */
6927  int ksks_in_queue = 0; /* number of unused keys */
6928  int zsks_in_queue = 0; /* number of unused keys */
6929  int new_ksks = 0; /* number of keys required */
6930  int new_zsks = 0; /* number of keys required */
6931  unsigned int current_count = 0; /* number of keys already in HSM */
6932 
6933  DB_RESULT result;
6934  int zone_count = 0; /* Number of zones on policy */
6935 
6936  int same_keys = 0; /* Do ksks and zsks look the same ? */
6937  int ksks_created = 0; /* Were any KSKs created? */
6938 
6939  /* Database connection details */
6940  DB_HANDLE dbhandle;
6941  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
6942 
6943  /* We will ask if the user is sure once we have counted keys */
6944  int user_certain;
6945 
6946  /* try to connect to the database */
6947  status = db_connect(&dbhandle, &lock_fd, 1);
6948  if (status != 0) {
6949  printf("Failed to connect to database\n");
6950  db_disconnect(lock_fd);
6951  return(1);
6952  }
6953 
6954  policy = KsmPolicyAlloc();
6955  if (policy == NULL) {
6956  printf("Malloc for policy struct failed\n");
6957  db_disconnect(lock_fd);
6958  exit(1);
6959  }
6960 
6961  if (o_policy == NULL) {
6962  printf("Please provide a policy name with the --policy option\n");
6963  db_disconnect(lock_fd);
6964  KsmPolicyFree(policy);
6965  return(1);
6966  }
6967  if (o_interval == NULL) {
6968  printf("Please provide an interval with the --interval option\n");
6969  db_disconnect(lock_fd);
6970  KsmPolicyFree(policy);
6971  return(1);
6972  }
6973 
6974  SetPolicyDefaults(policy, o_policy);
6975 
6976  status = KsmPolicyExists(o_policy);
6977  if (status == 0) {
6978  /* Policy exists */
6979  status = KsmPolicyRead(policy);
6980  if(status != 0) {
6981  printf("Error: unable to read policy %s from database\n", o_policy);
6982  db_disconnect(lock_fd);
6983  KsmPolicyFree(policy);
6984  return status;
6985  }
6986  } else {
6987  printf("Error: policy %s doesn't exist in database\n", o_policy);
6988  db_disconnect(lock_fd);
6989  KsmPolicyFree(policy);
6990  return status;
6991  }
6992 
6993  if (policy->shared_keys == 1 ) {
6994  printf("Key sharing is On\n");
6995  } else {
6996  printf("Key sharing is Off\n");
6997  }
6998 
6999  status = DtXMLIntervalSeconds(o_interval, &interval);
7000  if (status > 0) {
7001  printf("Error: unable to convert Interval %s to seconds, error: ", o_interval);
7002  switch (status) {
7003  case 1: /* This has gone away, will now return 2 */
7004  printf("invalid interval-type.\n");
7005  break;
7006  case 2:
7007  printf("unable to translate string.\n");
7008  break;
7009  case 3:
7010  printf("interval too long to be an int. E.g. Maximum is ~68 years on a system with 32-bit integers.\n");
7011  break;
7012  case 4:
7013  printf("invalid pointers or text string NULL.\n");
7014  break;
7015  default:
7016  printf("unknown\n");
7017  }
7018  db_disconnect(lock_fd);
7019  KsmPolicyFree(policy);
7020  return status;
7021  }
7022  else if (status == -1) {
7023  printf("Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days\n", o_interval);
7024  }
7025 
7026  /* Connect to the hsm */
7027  status = hsm_open(config, hsm_prompt_pin);
7028  if (status) {
7029  hsm_error_message = hsm_get_error(ctx);
7030  if (hsm_error_message) {
7031  printf("%s\n", hsm_error_message);
7032  free(hsm_error_message);
7033  } else {
7034  /* decode the error code ourselves
7035  TODO find if there is a better way to do this (and can all of these be returned? are there others?) */
7036  switch (status) {
7037  case HSM_ERROR:
7038  printf("hsm_open() result: HSM error\n");
7039  break;
7040  case HSM_PIN_INCORRECT:
7041  printf("hsm_open() result: incorrect PIN\n");
7042  break;
7043  case HSM_CONFIG_FILE_ERROR:
7044  printf("hsm_open() result: config file error\n");
7045  break;
7046  case HSM_REPOSITORY_NOT_FOUND:
7047  printf("hsm_open() result: repository not found\n");
7048  break;
7049  case HSM_NO_REPOSITORIES:
7050  printf("hsm_open() result: no repositories\n");
7051  break;
7052  default:
7053  printf("hsm_open() result: %d", status);
7054  }
7055  }
7056  db_disconnect(lock_fd);
7057  KsmPolicyFree(policy);
7058  exit(1);
7059  }
7060  printf("HSM opened successfully.\n");
7061  ctx = hsm_create_context();
7062 
7063  rightnow = DtParseDateTimeString("now");
7064 
7065  /* Check datetime in case it came back NULL */
7066  if (rightnow == NULL) {
7067  printf("Couldn't turn \"now\" into a date, quitting...\n");
7068  db_disconnect(lock_fd);
7069  KsmPolicyFree(policy);
7070  hsm_close();
7071  exit(1);
7072  }
7073 
7074  if (policy->ksk->sm == policy->zsk->sm && policy->ksk->bits == policy->zsk->bits && policy->ksk->algorithm == policy->zsk->algorithm) {
7075  same_keys = 1;
7076  } else {
7077  same_keys = 0;
7078  }
7079 
7080  /* How many zones on this policy */
7081  status = KsmZoneCountInit(&result, policy->id);
7082  if (status == 0) {
7083  status = KsmZoneCount(result, &zone_count);
7084  }
7085  DbFreeResult(result);
7086 
7087  if (status != 0) {
7088  printf("Could not count zones on policy %s\n", policy->name);
7089  db_disconnect(lock_fd);
7090  if (ctx) {
7091  hsm_destroy_context(ctx);
7092  }
7093  hsm_close();
7094  KsmPolicyFree(policy);
7095  return status;
7096  }
7097  printf("Info: %d zone(s) found on policy \"%s\"\n", zone_count, policy->name);
7098 
7099  /* If the zone total has been specified manually then use this
7100  instead but report how it differs from the actual number of zones*/
7101  if (o_zonetotal) {
7102  /* Check the value is numeric*/
7103  if (StrIsDigits(o_zonetotal)) {
7104  status = StrStrtoi(o_zonetotal, &zone_count);
7105  if (status != 0) {
7106  printf("Error: Unable to convert zonetotal \"%s\"; to an integer\n", o_zonetotal);
7107  db_disconnect(lock_fd);
7108  KsmPolicyFree(policy);
7109  hsm_close();
7110  exit(1);
7111  }
7112  } else {
7113  printf("Error: zonetotal \"%s\"; should be numeric only\n", o_zonetotal);
7114  db_disconnect(lock_fd);
7115  KsmPolicyFree(policy);
7116  hsm_close();
7117  exit(1);
7118  }
7119  /* Check the value is greater than 0*/
7120  if (zone_count < 1) {
7121  printf("Error: zonetotal parameter value of %d is invalid - the value must be greater than 0\n", zone_count);
7122  db_disconnect(lock_fd);
7123  KsmPolicyFree(policy);
7124  hsm_close();
7125  exit(1);
7126  }
7127  printf("Info: Keys will actually be generated for a total of %d zone(s) as specified by zone total parameter\n", zone_count);
7128  }
7129  else {
7130  /* make sure that we have at least one zone */
7131  if (zone_count == 0) {
7132  printf("No zones on policy %s, skipping...\n", policy->name);
7133  db_disconnect(lock_fd);
7134  if (ctx) {
7135  hsm_destroy_context(ctx);
7136  }
7137  hsm_close();
7138  KsmPolicyFree(policy);
7139  return status;
7140  }
7141  }
7142 
7143  /* Find out how many ksk keys are needed for the POLICY */
7144  status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count);
7145  if (status != 0) {
7146  printf("Could not predict ksk requirement for next interval for %s\n", policy->name);
7147  hsm_close();
7148  db_disconnect(lock_fd);
7149  KsmPolicyFree(policy);
7150  return(1);
7151  }
7152  /* Find out how many suitable keys we have */
7153  status = KsmKeyCountStillGood(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, interval, rightnow, &ksks_in_queue, KSM_TYPE_KSK);
7154  if (status != 0) {
7155  printf("Could not count current ksk numbers for policy %s\n", policy->name);
7156  hsm_close();
7157  db_disconnect(lock_fd);
7158  KsmPolicyFree(policy);
7159  return(1);
7160  }
7161  /* Don't have to adjust the queue for shared keys as the prediction has already taken care of that.*/
7162 
7163  new_ksks = ksks_needed - ksks_in_queue;
7164  /* fprintf(stderr, "keygen(ksk): new_ksks(%d) = ksks_needed(%d) - ksks_in_queue(%d)\n", new_ksks, ksks_needed, ksks_in_queue); */
7165 
7166  /* Find out how many ZSKs are needed for the POLICY */
7167  status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, interval, &zsks_needed, 0, zone_count);
7168  if (status != 0) {
7169  printf("Could not predict zsk requirement for next interval for %s\n", policy->name);
7170  hsm_close();
7171  db_disconnect(lock_fd);
7172  KsmPolicyFree(policy);
7173  return(1);
7174  }
7175  /* Find out how many suitable keys we have */
7176  status = KsmKeyCountStillGood(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, interval, rightnow, &zsks_in_queue, KSM_TYPE_ZSK);
7177  if (status != 0) {
7178  printf("Could not count current zsk numbers for policy %s\n", policy->name);
7179  hsm_close();
7180  db_disconnect(lock_fd);
7181  KsmPolicyFree(policy);
7182  return(1);
7183  }
7184  /* Don't have to adjust the queue for shared keys as the prediction has already taken care of that.*/
7185  /* Need to account for how many ksks will be taken from the queue*/
7186  if (same_keys) {
7187  /* If we need to generate any new ksks then there aren't enough keys on the queue to meet the demand for ksks.
7188  So we can't use any keys in the queue for zsks therefore we set the number available to 0 */
7189  if (new_ksks >= 0) {
7190  zsks_in_queue = 0;
7191  } else {
7192  /* Otherwise we can use any _not_ required for the ksks as zsk.
7193  So we set the number availble to equal those left over after we have taken all the ksk. */
7194  zsks_in_queue -= ksks_needed;
7195  }
7196  }
7197 
7198  new_zsks = zsks_needed - zsks_in_queue;
7199  /* fprintf(stderr, "keygen(zsk): new_zsks(%d) = zsks_needed(%d) - zsks_in_queue(%d)\n", new_zsks, zsks_needed, zsks_in_queue); */
7200 
7201  /* Check capacity of HSM will not be exceeded */
7202  if (policy->ksk->sm == policy->zsk->sm) {
7203  /* One HSM, One check */
7204  if (policy->ksk->sm_capacity != 0 && (new_ksks + new_zsks) > 0) {
7205  current_count = hsm_count_keys_repository(ctx, policy->ksk->sm_name);
7206  if (current_count >= policy->ksk->sm_capacity) {
7207  printf("Repository %s is full, cannot create more keys for policy %s\n", policy->ksk->sm_name, policy->name);
7208  return (1);
7209  }
7210  else if (current_count + new_ksks > policy->ksk->sm_capacity) {
7211  printf("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_ksks);
7212  new_ksks = policy->ksk->sm_capacity - current_count;
7213  }
7214  else if (current_count + new_ksks + new_zsks > policy->ksk->sm_capacity) {
7215  printf("Repository %s is nearly full, will create %lu ZSKs for policy %s (reduced from %d)\n", policy->ksk->sm_name, policy->ksk->sm_capacity - current_count, policy->name, new_ksks);
7216  new_zsks = policy->ksk->sm_capacity - current_count - new_ksks;
7217  }
7218 
7219  }
7220  } else {
7221  /* Two HSMs, Two checks */
7222  /* KSKs */
7223  if (policy->ksk->sm_capacity != 0 && new_ksks > 0) {
7224  current_count = hsm_count_keys_repository(ctx, policy->ksk->sm_name);
7225  if (current_count >= policy->ksk->sm_capacity) {
7226  printf("Repository %s is full, cannot create more KSKs for policy %s\n", policy->ksk->sm_name, policy->name);
7227  new_ksks = 0;
7228  }
7229  else if (current_count + new_ksks > policy->ksk->sm_capacity) {
7230  printf("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_ksks);
7231  new_ksks = policy->ksk->sm_capacity - current_count;
7232  }
7233  }
7234 
7235  /* ZSKs */
7236  if (policy->zsk->sm_capacity != 0 && new_zsks > 0) {
7237  current_count = hsm_count_keys_repository(ctx, policy->zsk->sm_name);
7238  if (current_count >= policy->zsk->sm_capacity) {
7239  printf("Repository %s is full, cannot create more ZSKs for policy %s\n", policy->zsk->sm_name, policy->name);
7240  new_zsks = 0;
7241  }
7242  else if (current_count + new_zsks > policy->zsk->sm_capacity) {
7243  printf("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_zsks);
7244  new_zsks = policy->zsk->sm_capacity - current_count;
7245  }
7246  }
7247  }
7248 
7249  /* If there is no work to do exit here */
7250  if (new_ksks <= 0 && new_zsks <= 0) {
7251  printf("No keys need to be created, quitting...\n");
7252 
7253  if (ctx) {
7254  hsm_destroy_context(ctx);
7255  }
7256  status = hsm_close();
7257  printf("all done! hsm_close result: %d\n", status);
7258  db_disconnect(lock_fd);
7259  KsmPolicyFree(policy);
7260  return(status);
7261  }
7262 
7263  /* Make sure that the user is happy */
7264  if (!auto_accept_flag) {
7265  printf("*WARNING* This will create %d KSKs (%d bits) and %d ZSKs (%d bits)\nAre you sure? [y/N] \n", new_ksks >= 0 ? new_ksks : 0, policy->ksk->bits, new_zsks >= 0 ? new_zsks : 0, policy->zsk->bits);
7266 
7267  user_certain = getchar();
7268  if (user_certain != 'y' && user_certain != 'Y') {
7269  printf("Okay, quitting...\n");
7270 
7271  if (ctx) {
7272  hsm_destroy_context(ctx);
7273  }
7274  status = hsm_close();
7275  printf("all done! hsm_close result: %d\n", status);
7276  db_disconnect(lock_fd);
7277  KsmPolicyFree(policy);
7278  return(status);
7279  }
7280  }
7281 
7282  /* Create the required keys */
7283  for (i=new_ksks ; i > 0 ; i--){
7284  if (hsm_supported_algorithm(policy->ksk->algorithm) == 0) {
7285  /* NOTE: for now we know that libhsm only supports RSA keys */
7286  key = hsm_generate_rsa_key(ctx, policy->ksk->sm_name, policy->ksk->bits);
7287  if (key) {
7288  if (verbose_flag) {
7289  printf("Created key in repository %s\n", policy->ksk->sm_name);
7290  }
7291  } else {
7292  printf("Error creating key in repository %s\n", policy->ksk->sm_name);
7293  hsm_error_message = hsm_get_error(ctx);
7294  if (hsm_error_message) {
7295  printf("%s\n", hsm_error_message);
7296  free(hsm_error_message);
7297  }
7298  db_disconnect(lock_fd);
7299  KsmPolicyFree(policy);
7300  hsm_close();
7301  exit(1);
7302  }
7303  id = hsm_get_key_id(ctx, key);
7304  hsm_key_free(key);
7305  status = KsmKeyPairCreate(policy->id, id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, rightnow, &ignore);
7306  if (status != 0) {
7307  printf("Error creating key in Database\n");
7308  hsm_error_message = hsm_get_error(ctx);
7309  if (hsm_error_message) {
7310  printf("%s\n", hsm_error_message);
7311  free(hsm_error_message);
7312  }
7313  db_disconnect(lock_fd);
7314  KsmPolicyFree(policy);
7315  hsm_close();
7316  exit(1);
7317  }
7318  printf("Created KSK size: %i, alg: %i with id: %s in repository: %s and database.\n", policy->ksk->bits,
7319  policy->ksk->algorithm, id, policy->ksk->sm_name);
7320  free(id);
7321  } else {
7322  printf("Key algorithm %d unsupported by libhsm.\n", policy->ksk->algorithm);
7323  db_disconnect(lock_fd);
7324  KsmPolicyFree(policy);
7325  hsm_close();
7326  exit(1);
7327  }
7328  }
7329  ksks_created = new_ksks;
7330 
7331  /* Create the required ZSKs */
7332  for (i = new_zsks ; i > 0 ; i--) {
7333  if (hsm_supported_algorithm(policy->zsk->algorithm) == 0) {
7334  /* NOTE: for now we know that libhsm only supports RSA keys */
7335  key = hsm_generate_rsa_key(ctx, policy->zsk->sm_name, policy->zsk->bits);
7336  if (key) {
7337  if (verbose_flag) {
7338  printf("Created key in repository %s\n", policy->zsk->sm_name);
7339  }
7340  } else {
7341  printf("Error creating key in repository %s\n", policy->zsk->sm_name);
7342  hsm_error_message = hsm_get_error(ctx);
7343  if (hsm_error_message) {
7344  printf("%s\n", hsm_error_message);
7345  free(hsm_error_message);
7346  }
7347  db_disconnect(lock_fd);
7348  KsmPolicyFree(policy);
7349  hsm_close();
7350  exit(1);
7351  }
7352  id = hsm_get_key_id(ctx, key);
7353  hsm_key_free(key);
7354  status = KsmKeyPairCreate(policy->id, id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, rightnow, &ignore);
7355  if (status != 0) {
7356  printf("Error creating key in Database\n");
7357  hsm_error_message = hsm_get_error(ctx);
7358  if (hsm_error_message) {
7359  printf("%s\n", hsm_error_message);
7360  free(hsm_error_message);
7361  }
7362  db_disconnect(lock_fd);
7363  KsmPolicyFree(policy);
7364  hsm_close();
7365  exit(1);
7366  }
7367  printf("Created ZSK size: %i, alg: %i with id: %s in repository: %s and database.\n", policy->zsk->bits,
7368  policy->zsk->algorithm, id, policy->zsk->sm_name);
7369  free(id);
7370  } else {
7371  printf("Key algorithm %d unsupported by libhsm.\n", policy->zsk->algorithm);
7372  db_disconnect(lock_fd);
7373  KsmPolicyFree(policy);
7374  hsm_close();
7375  exit(1);
7376  }
7377  }
7378  StrFree(rightnow);
7379 
7380  /* Log if a backup needs to be run for these keys */
7381  if (ksks_created && policy->ksk->require_backup) {
7382  printf("NOTE: keys generated in repository %s will not become active until they have been backed up\n", policy->ksk->sm_name);
7383  }
7384  if (new_ksks && policy->zsk->require_backup && (policy->zsk->sm != policy->ksk->sm)) {
7385  printf("NOTE: keys generated in repository %s will not become active until they have been backed up\n", policy->zsk->sm_name);
7386  }
7387 
7388  /*
7389  * Destroy HSM context
7390  */
7391  if (ctx) {
7392  hsm_destroy_context(ctx);
7393  }
7394  status = hsm_close();
7395  printf("all done! hsm_close result: %d\n", status);
7396 
7397  KsmPolicyFree(policy);
7398 
7399  /* Release sqlite lock file (if we have it) */
7400  db_disconnect(lock_fd);
7401 
7402  return status;
7403 }
7404 
7406 {
7407  int status = 0;
7408  int user_certain; /* Continue ? */
7409  int key_state = -1;
7410  int keypair_id = -1;
7411 
7412  /* Database connection details */
7413  DB_HANDLE dbhandle;
7414  FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */
7415  char* sql = NULL; /* SQL query */
7416  char* sql2 = NULL; /* SQL query */
7417 
7418  /* Key information */
7419  hsm_key_t *key = NULL;
7420 
7421  /* Check that we have either a keytag or a cka_id */
7422  if (o_cka_id == NULL) {
7423  printf("Please provide a CKA_ID for the key to delete\n");
7424  usage_keydelete();
7425  return(-1);
7426  }
7427 
7428  /* try to connect to the database */
7429  status = db_connect(&dbhandle, &lock_fd, 1);
7430  if (status != 0) {
7431  printf("Failed to connect to database\n");
7432  db_disconnect(lock_fd);
7433  return(1);
7434  }
7435 
7436 
7437  /* Find the key and check its state */
7438  status = GetKeyState(o_cka_id, &key_state, &keypair_id);
7439  if (status != 0 || key_state == -1) {
7440  printf("Failed to determine the state of the key\n");
7441  db_disconnect(lock_fd);
7442  return(1);
7443  }
7444 
7445  /* If state == GENERATE or force_flag == 1 Remove the key from the database */
7446  if (key_state != KSM_STATE_GENERATE && key_state != KSM_STATE_DEAD) {
7447  if (force_flag == 1) {
7448  printf("*WARNING* This will delete a key that the enforcer believes is in use; are you really sure? [y/N] ");
7449 
7450  user_certain = getchar();
7451  if (user_certain != 'y' && user_certain != 'Y') {
7452  printf("Okay, quitting...\n");
7453  exit(0);
7454  }
7455  }
7456  else {
7457  printf("The enforcer believes that this key is in use, quitting...\n");
7458  exit(0);
7459  }
7460  }
7461 
7462  /* Okay, do it */
7463  /* Delete from dnsseckeys */
7464  sql = DdsInit("dnsseckeys");
7465  DdsConditionInt(&sql, "keypair_id", DQS_COMPARE_EQ, keypair_id, 0);
7466  DdsEnd(&sql);
7467 
7468  status = DbExecuteSqlNoResult(DbHandle(), sql);
7469  DdsFree(sql);
7470  if (status != 0)
7471  {
7472  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
7473  return status;
7474  }
7475 
7476  /* Delete from keypairs */
7477  sql2 = DdsInit("keypairs");
7478  DdsConditionInt(&sql2, "id", DQS_COMPARE_EQ, keypair_id, 0);
7479  DdsEnd(&sql2);
7480 
7481  status = DbExecuteSqlNoResult(DbHandle(), sql2);
7482  DdsFree(sql2);
7483  if (status != 0)
7484  {
7485  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
7486  return status;
7487  }
7488 
7489  /* If hsm_flag == 1 Remove from the HSM */
7490  if (hsm_flag == 1) {
7491  /* connect to the HSM */
7492  status = hsm_open(config, hsm_prompt_pin);
7493  if (status) {
7494  hsm_print_error(NULL);
7495  return(-1);
7496  }
7497 
7498  /* Delete from the HSM */
7499  key = hsm_find_key_by_id(NULL, o_cka_id);
7500 
7501  if (!key) {
7502  printf("Key not found in HSM: %s\n", o_cka_id);
7503  hsm_close();
7504  return -1;
7505  }
7506 
7507  status = hsm_remove_key(NULL, key);
7508 
7509  hsm_key_free(key);
7510  hsm_close();
7511  }
7512 
7513  if (!status) {
7514  printf("Key delete successful: %s\n", o_cka_id);
7515  } else {
7516  printf("Key delete failed: %s\n", o_cka_id);
7517  return -1;
7518  }
7519 
7520  return status;
7521 }
7522 
7523 /* Make sure (if we can) that the permissions on a file are correct for the user/group in conf.xml */
7524 
7525 int fix_file_perms(const char *dbschema)
7526 {
7527  struct stat stat_ret;
7528 
7529  int status = 0;
7530 
7531  xmlDocPtr doc = NULL;
7532  xmlDocPtr rngdoc = NULL;
7533  xmlXPathContextPtr xpathCtx = NULL;
7534  xmlXPathObjectPtr xpathObj = NULL;
7535  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
7536  xmlRelaxNGValidCtxtPtr rngctx = NULL;
7537  xmlRelaxNGPtr schema = NULL;
7538  xmlChar *user_expr = (unsigned char*) "//Configuration/Enforcer/Privileges/User";
7539  xmlChar *group_expr = (unsigned char*) "//Configuration/Enforcer/Privileges/Group";
7540 
7541  char* filename = OPENDNSSEC_CONFIG_FILE;
7542  char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng";
7543  char* temp_char = NULL;
7544 
7545  struct passwd *pwd;
7546  struct group *grp;
7547 
7548  int uid = -1;
7549  int gid = -1;
7550  char *username = NULL;
7551  char *groupname = NULL;
7552 
7553  printf("fixing permissions on file %s\n", dbschema);
7554  /* First see if we are running as root, if not then return */
7555  if (geteuid() != 0) {
7556  return 0;
7557  }
7558 
7559  /* Now see if the file exists, if it does not then return */
7560  if (stat(dbschema, &stat_ret) != 0) {
7561  printf("cannot stat file %s: %s", dbschema, strerror(errno));
7562  return -1;
7563  }
7564 
7565  /* OKAY... read conf.xml for the user and group */
7566  /* Load XML document */
7567  doc = xmlParseFile(filename);
7568  if (doc == NULL) {
7569  printf("Error: unable to parse file \"%s\"", filename);
7570  return(-1);
7571  }
7572 
7573  /* Load rng document */
7574  rngdoc = xmlParseFile(rngfilename);
7575  if (rngdoc == NULL) {
7576  printf("Error: unable to parse file \"%s\"", rngfilename);
7577  return(-1);
7578  }
7579 
7580  /* Create an XML RelaxNGs parser context for the relax-ng document. */
7581  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
7582  if (rngpctx == NULL) {
7583  printf("Error: unable to create XML RelaxNGs parser context");
7584  return(-1);
7585  }
7586 
7587  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
7588  schema = xmlRelaxNGParse(rngpctx);
7589  if (schema == NULL) {
7590  printf("Error: unable to parse a schema definition resource");
7591  return(-1);
7592  }
7593 
7594  /* Create an XML RelaxNGs validation context based on the given schema */
7595  rngctx = xmlRelaxNGNewValidCtxt(schema);
7596  if (rngctx == NULL) {
7597  printf("Error: unable to create RelaxNGs validation context based on the schema");
7598  return(-1);
7599  }
7600 
7601  /* Validate a document tree in memory. */
7602  status = xmlRelaxNGValidateDoc(rngctx,doc);
7603  if (status != 0) {
7604  printf("Error validating file \"%s\"", filename);
7605  return(-1);
7606  }
7607 
7608  /* Now parse a value out of the conf */
7609  /* Create xpath evaluation context */
7610  xpathCtx = xmlXPathNewContext(doc);
7611  if(xpathCtx == NULL) {
7612  printf("Error: unable to create new XPath context");
7613  xmlFreeDoc(doc);
7614  return(-1);
7615  }
7616 
7617  /* Set the group if specified */
7618  xpathObj = xmlXPathEvalExpression(group_expr, xpathCtx);
7619  if(xpathObj == NULL) {
7620  printf("Error: unable to evaluate xpath expression: %s", group_expr);
7621  xmlXPathFreeContext(xpathCtx);
7622  xmlFreeDoc(doc);
7623  return(-1);
7624  }
7625  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
7626  temp_char = (char*) xmlXPathCastToString(xpathObj);
7627  StrAppend(&groupname, temp_char);
7628  StrFree(temp_char);
7629  xmlXPathFreeObject(xpathObj);
7630  } else {
7631  groupname = NULL;
7632  }
7633 
7634  /* Set the user to drop to if specified */
7635  xpathObj = xmlXPathEvalExpression(user_expr, xpathCtx);
7636  if(xpathObj == NULL) {
7637  printf("Error: unable to evaluate xpath expression: %s", user_expr);
7638  xmlXPathFreeContext(xpathCtx);
7639  xmlFreeDoc(doc);
7640  return(-1);
7641  }
7642  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
7643  temp_char = (char*) xmlXPathCastToString(xpathObj);
7644  StrAppend(&username, temp_char);
7645  StrFree(temp_char);
7646  xmlXPathFreeObject(xpathObj);
7647  } else {
7648  username = NULL;
7649  }
7650 
7651  /* Free up the xml stuff, we are done with it */
7652  xmlXPathFreeContext(xpathCtx);
7653  xmlRelaxNGFree(schema);
7654  xmlRelaxNGFreeValidCtxt(rngctx);
7655  xmlRelaxNGFreeParserCtxt(rngpctx);
7656  xmlFreeDoc(doc);
7657  xmlFreeDoc(rngdoc);
7658 
7659  /* Set uid and gid if required */
7660  if (username != NULL) {
7661  /* Lookup the user id in /etc/passwd */
7662  if ((pwd = getpwnam(username)) == NULL) {
7663  printf("user '%s' does not exist. cannot chown %s...\n", username, dbschema);
7664  return(1);
7665  } else {
7666  uid = pwd->pw_uid;
7667  }
7668  endpwent();
7669  }
7670  if (groupname) {
7671  /* Lookup the group id in /etc/groups */
7672  if ((grp = getgrnam(groupname)) == NULL) {
7673  printf("group '%s' does not exist. cannot chown %s...\n", groupname, dbschema);
7674  exit(1);
7675  } else {
7676  gid = grp->gr_gid;
7677  }
7678  endgrent();
7679  }
7680 
7681  /* Change ownership of the db file */
7682  if (chown(dbschema, uid, gid) == -1) {
7683  printf("cannot chown(%u,%u) %s: %s",
7684  (unsigned) uid, (unsigned) gid, dbschema, strerror(errno));
7685  return -1;
7686  }
7687 
7688  /* and change ownership of the lock file */
7689  temp_char = NULL;
7690  StrAppend(&temp_char, dbschema);
7691  StrAppend(&temp_char, ".our_lock");
7692 
7693  if (chown(temp_char, uid, gid) == -1) {
7694  printf("cannot chown(%u,%u) %s: %s",
7695  (unsigned) uid, (unsigned) gid, temp_char, strerror(errno));
7696  StrFree(temp_char);
7697  return -1;
7698  }
7699 
7700  StrFree(temp_char);
7701 
7702  return 0;
7703 }
7704 
7705 /*+
7706  * CountKeys - Find how many Keys match our criteria
7707  *
7708  *
7709  * Arguments:
7710  *
7711  * int zone_id
7712  * ID of the zone (-1 for all)
7713  *
7714  * int keytag
7715  * keytag provided (-1 if not specified)
7716  *
7717  * const char * cka_id
7718  * cka_id provided (NULL if not)
7719  *
7720  * int * key_count (returned)
7721  * count of keys matching the information specified
7722  *
7723  * char ** temp_cka_id (returned)
7724  * cka_id of key found
7725  *
7726  * int * temp_key_state (returned)
7727  * What state is the key in (only used if _one_ key returned)
7728  *
7729  * int * temp_keypair_id (returned)
7730  * ID of the key found (only used if _one_ key returned)
7731  * Returns:
7732  * int
7733  * Status return. 0 on success.
7734  * other on fail
7735  */
7736 
7737 int CountKeys(int *zone_id, int keytag, const char *cka_id, int *key_count, char **temp_cka_id, int *temp_key_state, int *temp_keypair_id)
7738 {
7739  char* sql = NULL; /* SQL query */
7740  int status = 0; /* Status return */
7741  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
7742  DB_RESULT result; /* Result of the query */
7743  DB_ROW row = NULL; /* Row data */
7744 
7745  char buffer[256]; /* For constructing part of the command */
7746  size_t nchar; /* Number of characters written */
7747 
7748  int done_row = 0; /* Have we found a key this loop? */
7749 
7750  int temp_zone_id = 0; /* place to store zone_id returned */
7751  char* temp_loc = NULL; /* place to store location returned */
7752  int temp_alg = 0; /* place to store algorithm returned */
7753  int temp_state = 0; /* place to store state returned */
7754  int temp_keypair = 0; /* place to store id returned */
7755 
7756  int temp_count = 0; /* Count of keys found */
7757 
7758  /* Key information */
7759  hsm_key_t *key = NULL;
7760  ldns_rr *dnskey_rr = NULL;
7761  hsm_sign_params_t *sign_params = NULL;
7762 
7763  /* connect to the HSM */
7764  status = hsm_open(config, hsm_prompt_pin);
7765  if (status) {
7766  hsm_print_error(NULL);
7767  return(-1);
7768  }
7769 
7770  /* Select rows */
7771  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d)",
7773  if (nchar >= sizeof(buffer)) {
7774  printf("Error: Overran buffer in CountKeys\n");
7775  hsm_close();
7776  return(-1);
7777  }
7778 
7779  /* TODO do I need to use the view */
7780  StrAppend(&sql, "select k.zone_id, k.location, k.algorithm, k.state, k.id from KEYDATA_VIEW k where state in ");
7781  StrAppend(&sql, buffer);
7782  StrAppend(&sql, " and zone_id is not null and k.keytype = 257");
7783 
7784  if (*zone_id != -1) {
7785  StrAppend(&sql, " and zone_id = ");
7786  snprintf(stringval, KSM_INT_STR_SIZE, "%d", *zone_id);
7787  StrAppend(&sql, stringval);
7788  }
7789  if (cka_id != NULL) {
7790  StrAppend(&sql, " and k.location = '");
7791  StrAppend(&sql, cka_id);
7792  StrAppend(&sql, "'");
7793  }
7794  /* where location is unique? */
7795  StrAppend(&sql, " group by location");
7796 
7797  DusEnd(&sql);
7798 
7799  status = DbExecuteSql(DbHandle(), sql, &result);
7800 
7801  /* loop round printing out the cka_id of any key that matches
7802  * if only one does then we are good, if not then we will write a
7803  * message asking for further clarification */
7804  /* Note that we only need to do each key, not each instance of a key */
7805  if (status == 0) {
7806  status = DbFetchRow(result, &row);
7807  while (status == 0) {
7808  /* Got a row, process it */
7809  DbInt(row, 0, &temp_zone_id);
7810  DbString(row, 1, &temp_loc);
7811  DbInt(row, 2, &temp_alg);
7812  DbInt(row, 3, &temp_state);
7813  DbInt(row, 4, &temp_keypair);
7814 
7815  done_row = 0;
7816 
7817  if (keytag == -1 && cka_id == NULL)
7818  {
7819  *temp_key_state = temp_state;
7820  }
7821 
7822  key = hsm_find_key_by_id(NULL, temp_loc);
7823  if (!key) {
7824  printf("cka_id %-33s in DB but NOT IN repository\n", temp_loc);
7825  } else if (keytag != -1) {
7826  sign_params = hsm_sign_params_new();
7827  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "temp_zone");
7828  sign_params->algorithm = temp_alg;
7829  sign_params->flags = LDNS_KEY_ZONE_KEY;
7830  sign_params->flags += LDNS_KEY_SEP_KEY;
7831 
7832  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
7833  sign_params->keytag = ldns_calc_keytag(dnskey_rr);
7834 
7835  /* Have we matched our keytag? */
7836  if (keytag == sign_params->keytag) {
7837  temp_count++;
7838  done_row = 1;
7839  *temp_cka_id = NULL;
7840  StrAppend(temp_cka_id, temp_loc);
7841  *zone_id = temp_zone_id;
7842  *temp_key_state = temp_state;
7843  *temp_keypair_id = temp_keypair;
7844  printf("Found key with CKA_ID %s\n", temp_loc);
7845  }
7846 
7847  hsm_sign_params_free(sign_params);
7848  }
7849  if (key && cka_id != NULL && strncmp(cka_id, temp_loc, strlen(temp_loc)) == 0) {
7850  /* Or have we matched a provided cka_id */
7851  if (done_row == 0) {
7852  temp_count++;
7853  *temp_cka_id = NULL;
7854  StrAppend(temp_cka_id, temp_loc);
7855  *zone_id = temp_zone_id;
7856  *temp_key_state = temp_state;
7857  *temp_keypair_id = temp_keypair;
7858  printf("Found key with CKA_ID %s\n", temp_loc);
7859  }
7860  }
7861 
7862  if (key) {
7863  hsm_key_free(key);
7864  }
7865 
7866  status = DbFetchRow(result, &row);
7867  }
7868 
7869  /* Convert EOF status to success */
7870 
7871  if (status == -1) {
7872  status = 0;
7873  }
7874 
7875  DbFreeResult(result);
7876  }
7877 
7878  *key_count = temp_count;
7879 
7880  DusFree(sql);
7881  DbFreeRow(row);
7882 
7883  DbStringFree(temp_loc);
7884 
7885  if (dnskey_rr != NULL) {
7886  ldns_rr_free(dnskey_rr);
7887  }
7888 
7889  hsm_close();
7890 
7891  return status;
7892 }
7893 
7894 /* Simpler version of the above function */
7895 int GetKeyState(const char *cka_id, int *temp_key_state, int *temp_keypair_id) {
7896  int status = 0;
7897  char sql[256]; /* For constructing the command */
7898  size_t nchar; /* Number of characters written */
7899 
7900  DB_RESULT result; /* Result of the query */
7901  DB_ROW row = NULL; /* Row data */
7902  int temp_state = 0; /* place to store state returned */
7903  int temp_keypair = 0; /* place to store id returned */
7904 
7905  nchar = snprintf(sql, sizeof(sql), "select k.id, k.state from KEYDATA_VIEW k where k.location = '%s'", cka_id);
7906  if (nchar >= sizeof(sql)) {
7907  printf("Error: Overran buffer in CountKeys\n");
7908  return(-1);
7909  }
7910 
7911  status = DbExecuteSql(DbHandle(), sql, &result);
7912 
7913  /* loop round until we find a key not in the GENERATE or DEAD state */
7914  if (status == 0) {
7915  status = DbFetchRow(result, &row);
7916  while (status == 0) {
7917  /* Got a row, process it */
7918  DbInt(row, 0, &temp_keypair);
7919  DbInt(row, 1, &temp_state);
7920 
7921  /* Note that GENERATE == {null} in this view so state will be 0 */
7922  if (temp_state == 0) {
7923  temp_state = KSM_STATE_GENERATE;
7924  }
7925 
7926  *temp_key_state = temp_state;
7927  *temp_keypair_id = temp_keypair;
7928 
7929  if (temp_state != KSM_STATE_GENERATE && temp_state != KSM_STATE_DEAD) {
7930  DbFreeRow(row);
7931  return(0);
7932  }
7933 
7934  status = DbFetchRow(result, &row);
7935  }
7936  }
7937 
7938  DbFreeRow(row);
7939  return(0);
7940 }
7941 
7942 /*+
7943  * MarkDSSeen - Indicate that the DS record has been observed:
7944  * Change the state of the key to ACTIVE
7945  *
7946  * Arguments:
7947  *
7948  * const char * cka_id
7949  * cka_id of key to make active
7950  *
7951  * int zone_id
7952  * ID of the zone
7953  *
7954  * int policy_id
7955  * ID of the policy
7956  *
7957  * const char * datetime
7958  * when this is happening
7959  *
7960  * int key_state
7961  * state that the key is in
7962  *
7963  * Returns:
7964  * int
7965  * Status return. 0 on success.
7966  * other on fail
7967  */
7968 
7969 int MarkDSSeen(int keypair_id, int zone_id, int policy_id, const char *datetime, int key_state)
7970 {
7971  char* sql1 = NULL; /* SQL query */
7972  int status = 0; /* Status return */
7973 
7974  char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */
7975 
7976  KSM_PARCOLL collection; /* Collection of parameters for zone */
7977  int deltat; /* Time interval */
7978 
7979  (void) zone_id;
7980 
7981  /* Set collection defaults */
7982  KsmCollectionInit(&collection);
7983 
7984  /* Get the values of the parameters */
7985  status = KsmParameterCollection(&collection, policy_id);
7986  if (status != 0) {
7987  printf("Error: failed to read policy\n");
7988  return status;
7989  }
7990 
7991 /* 0) Start a transaction */
7992  status = DbBeginTransaction();
7993  if (status != 0) {
7994  /* Something went wrong */
7995 
7997  return status;
7998  }
7999 
8000  /* 1) Change the state of the selected Key */
8001  if (key_state == KSM_STATE_READY) {
8002  /* We are making a key active */
8003 
8004  /* Set the interval until Retire */
8005  deltat = collection.ksklife;
8006 
8007  /* Generate the SQL to express this interval */
8008  status = DbDateDiff(datetime, deltat, 1, buffer, KSM_SQL_SIZE);
8009  if (status != 0) {
8010  printf("DbDateDiff failed\n");
8011  return status;
8012  }
8013 
8014  sql1 = DusInit("dnsseckeys");
8015  DusSetInt(&sql1, "STATE", KSM_STATE_ACTIVE, 0);
8017  StrAppend(&sql1, ", RETIRE = ");
8018  StrAppend(&sql1, buffer);
8019  StrAppend(&sql1, " ");
8020 
8021  DusConditionInt(&sql1, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0);
8022  DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
8023  DusEnd(&sql1);
8024  }
8025  else {
8026  /* We are making a standby key DSpublish */
8027 
8028  /* Set the interval until DSReady */
8029  deltat = collection.kskttl + collection.kskpropdelay +
8030  collection.pub_safety;
8031 
8032  /* Generate the SQL to express this interval */
8033  status = DbDateDiff(datetime, deltat, 1, buffer, KSM_SQL_SIZE);
8034  if (status != 0) {
8035  printf("DbDateDiff failed\n");
8036  return status;
8037  }
8038 
8039  sql1 = DusInit("dnsseckeys");
8040  DusSetInt(&sql1, "STATE", KSM_STATE_DSPUBLISH, 0);
8042  StrAppend(&sql1, ", READY = ");
8043  StrAppend(&sql1, buffer);
8044  StrAppend(&sql1, " ");
8045 
8046  DusConditionInt(&sql1, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0);
8047  DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
8048  DusEnd(&sql1);
8049  }
8050 
8051  status = DbExecuteSqlNoResult(DbHandle(), sql1);
8052  DusFree(sql1);
8053 
8054  /* Report any errors */
8055  if (status != 0) {
8056  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
8057  DbRollback();
8058  return status;
8059  }
8060 
8061  /* 3) Commit or Rollback */
8062  if (status == 0) { /* It actually can't be anything else */
8063  /* Everything worked by the looks of it */
8064  DbCommit();
8065  } else {
8066  /* Whatever happened, it was not good */
8067  DbRollback();
8068  }
8069 
8070  return status;
8071 }
8072 
8073 /*+
8074  * RetireOldKey - Retire the old KSK
8075  *
8076  *
8077  * Arguments:
8078  *
8079  * int zone_id
8080  * ID of the zone
8081  *
8082  * int policy_id
8083  * ID of the policy
8084  *
8085  * const char * datetime
8086  * when this is happening
8087  *
8088  * Returns:
8089  * int
8090  * Status return. 0 on success.
8091  * other on fail
8092  */
8093 
8094 int RetireOldKey(int zone_id, int policy_id, const char *datetime)
8095 {
8096  char* sql2 = NULL; /* SQL query */
8097  int status = 0; /* Status return */
8098  char* where_clause = NULL;
8099  int id = -1; /* ID of key to retire */
8100 
8101  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
8102  char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */
8103 
8104  KSM_PARCOLL collection; /* Collection of parameters for zone */
8105  int deltat; /* Time interval */
8106 
8107  /* Set collection defaults */
8108  KsmCollectionInit(&collection);
8109 
8110  /* Get the values of the parameters */
8111  status = KsmParameterCollection(&collection, policy_id);
8112  if (status != 0) {
8113  printf("Error: failed to read policy\n");
8114  return status;
8115  }
8116 
8117 /* 0) Start a transaction */
8118  status = DbBeginTransaction();
8119  if (status != 0) {
8120  /* Something went wrong */
8121 
8123  return status;
8124  }
8125 
8126  /* 1) Retire the oldest active key, and set its deadtime */
8127  /* work out which key */
8128  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
8129  StrAppend(&where_clause, "select id from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
8130  StrAppend(&where_clause, stringval);
8131  StrAppend(&where_clause, " and retire = (select min(retire) from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
8132  StrAppend(&where_clause, stringval);
8133  StrAppend(&where_clause, ")");
8134 
8135  /* Execute query and free up the query string */
8136  status = DbIntQuery(DbHandle(), &id, where_clause);
8137  StrFree(where_clause);
8138  if (status != 0)
8139  {
8140  printf("Error: failed to find ID of key to retire\n");
8141  DbRollback();
8142  return status;
8143  }
8144 
8145  /* work out what its deadtime should become */
8146  deltat = collection.dsttl + collection.kskpropdelay + collection.ret_safety;
8147 
8148  /* Generate the SQL to express this interval */
8149  status = DbDateDiff(datetime, deltat, 1, buffer, KSM_SQL_SIZE);
8150  if (status != 0) {
8151  printf("DbDateDiff failed\n");
8152  DbRollback();
8153  return status;
8154  }
8155 
8156  sql2 = DusInit("dnsseckeys");
8157  DusSetInt(&sql2, "STATE", KSM_STATE_RETIRE, 0);
8159  StrAppend(&sql2, ", DEAD = ");
8160  StrAppend(&sql2, buffer);
8161  DusConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, id, 0);
8162  DusConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
8163 
8164  status = DbExecuteSqlNoResult(DbHandle(), sql2);
8165  DusFree(sql2);
8166 
8167  /* Report any errors */
8168  if (status != 0) {
8169  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
8170  DbRollback();
8171  return status;
8172  }
8173 
8174  /* 2) Commit or Rollback */
8175  if (status == 0) { /* It actually can't be anything else */
8176  /* Everything worked by the looks of it */
8177  DbCommit();
8178  } else {
8179  /* Whatever happened, it was not good */
8180  DbRollback();
8181  }
8182 
8183  return status;
8184 }
8185 
8186 /*
8187  * CountKeysInState - Count Keys in given state
8188  *
8189  * Description:
8190  * Counts the number of keys in the given state.
8191  *
8192  * Arguments:
8193  * int keytype
8194  * Either KSK or ZSK, depending on the key type
8195  *
8196  * int keystate
8197  * State of keys to count
8198  *
8199  * int* count
8200  * Number of keys meeting the condition.
8201  *
8202  * int zone_id
8203  * ID of zone that we are looking at (-1 == all zones)
8204  *
8205  * Returns:
8206  * int
8207  * Status return. 0 => success, Other => error, in which case a message
8208  * will have been output.
8209 -*/
8210 
8211 int CountKeysInState(int keytype, int keystate, int* count, int zone_id)
8212 {
8213  int clause = 0; /* Clause counter */
8214  char* sql = NULL; /* SQL command */
8215  int status; /* Status return */
8216 
8217  sql = DqsCountInit("KEYDATA_VIEW");
8218  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
8219  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, keystate, clause++);
8220  if (zone_id != -1) {
8221  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
8222  }
8223  DqsEnd(&sql);
8224 
8225  status = DbIntQuery(DbHandle(), count, sql);
8226  DqsFree(sql);
8227 
8228  if (status != 0) {
8229  printf("Error in CountKeysInState\n");
8230  }
8231 
8232  return status;
8233 }
8234 
8235 /*+
8236  * ChangeKeyState - Change the state of the specified key
8237  *
8238  * Arguments:
8239  *
8240  * int keytype
8241  * type of key we are dealing with
8242  *
8243  * const char * cka_id
8244  * cka_id of key to change
8245  *
8246  * int zone_id
8247  * ID of the zone
8248  *
8249  * int policy_id
8250  * ID of the policy
8251  *
8252  * const char * datetime
8253  * when this is happening
8254  *
8255  * int keystate
8256  * state that the key should be moved to
8257  *
8258  * Returns:
8259  * int
8260  * Status return. 0 on success.
8261  * other on fail
8262  *
8263  * TODO take keytimings out of here
8264  */
8265 
8266 int ChangeKeyState(int keytype, const char *cka_id, int zone_id, int policy_id, const char *datetime, int keystate)
8267 {
8268  char* sql1 = NULL; /* SQL query */
8269  int status = 0; /* Status return */
8270 
8271  int count = 0; /* Count of keys whose date will be set */
8272  char* sql = NULL; /* For creating the SQL command */
8273  int where = 0; /* For the SQL selection */
8274  int i = 0; /* A counter */
8275  int j = 0; /* Another counter */
8276  char* insql = NULL; /* SQL "IN" clause */
8277  int* keyids; /* List of IDs of keys to promote */
8278  DB_RESULT result; /* List result set */
8279  KSM_KEYDATA data; /* Data for this key */
8280 
8281  char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */
8282 
8283  KSM_PARCOLL collection; /* Collection of parameters for zone */
8284  int deltat = 0; /* Time interval */
8285 
8286  (void) zone_id;
8287 
8288  /* Set collection defaults */
8289  KsmCollectionInit(&collection);
8290 
8291  /* Get the values of the parameters */
8292  status = KsmParameterCollection(&collection, policy_id);
8293  if (status != 0) {
8294  printf("Error: failed to read policy\n");
8295  return status;
8296  }
8297 
8298  /* Count how many keys will have their state changed */
8299 
8300  sql = DqsCountInit("KEYDATA_VIEW");
8301  DqsConditionString(&sql, "location", DQS_COMPARE_EQ, cka_id, where++);
8302  if (zone_id != -1) {
8303  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
8304  }
8305  DqsEnd(&sql);
8306 
8307  status = DbIntQuery(DbHandle(), &count, sql);
8308  DqsFree(sql);
8309 
8310  if (status != 0) {
8311  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
8312  return status;
8313  }
8314 
8315  if (count == 0) {
8316  /* Nothing to do, error? */
8317  return status;
8318  }
8319 
8320  /* Allocate space for the list of key IDs */
8321  keyids = MemMalloc(count * sizeof(int));
8322 
8323  /* Get the list of IDs */
8324 
8325  where = 0;
8326  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
8327  DqsConditionString(&sql, "location", DQS_COMPARE_EQ, cka_id, where++);
8328  if (zone_id != -1) {
8329  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
8330  }
8331  DqsEnd(&sql);
8332 
8333  status = KsmKeyInitSql(&result, sql);
8334  DqsFree(sql);
8335 
8336  if (status == 0) {
8337  while (status == 0) {
8338  status = KsmKey(result, &data);
8339  if (status == 0) {
8340  keyids[i] = data.keypair_id;
8341  i++;
8342  }
8343  }
8344 
8345  /* Convert EOF status to success */
8346 
8347  if (status == -1) {
8348  status = 0;
8349  } else {
8350  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
8351  StrFree(keyids);
8352  return status;
8353  }
8354 
8355  KsmKeyEnd(result);
8356 
8357  } else {
8358  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
8359  StrFree(keyids);
8360  return status;
8361  }
8362 
8363  /*
8364  * Now construct the "IN" statement listing the IDs of the keys we
8365  * are planning to change the state of.
8366  */
8367 
8368  StrAppend(&insql, "(");
8369  for (j = 0; j < i; ++j) {
8370  if (j != 0) {
8371  StrAppend(&insql, ",");
8372  }
8373  snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
8374  StrAppend(&insql, buffer);
8375  }
8376  StrAppend(&insql, ")");
8377 
8378 /* 0) Start a transaction */
8379  status = DbBeginTransaction();
8380  if (status != 0) {
8381  /* Something went wrong */
8382 
8384  StrFree(keyids);
8385  return status;
8386  }
8387 
8388  /* 1) Change the state of the selected Key */
8389  if (keystate == KSM_STATE_ACTIVE) {
8390  /* We are making a key active */
8391 
8392  /* Set the interval until Retire */
8393  deltat = collection.ksklife;
8394 
8395  /* Generate the SQL to express this interval */
8396  status = DbDateDiff(datetime, deltat, 1, buffer, KSM_SQL_SIZE);
8397  if (status != 0) {
8398  printf("DbDateDiff failed\n");
8399  StrFree(keyids);
8400  return status;
8401  }
8402 
8403  sql1 = DusInit("dnsseckeys");
8404  DusSetInt(&sql1, "STATE", KSM_STATE_ACTIVE, 0);
8406  StrAppend(&sql1, ", RETIRE = ");
8407  StrAppend(&sql1, buffer);
8408 
8409  DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
8410  if (zone_id != -1) {
8411  DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
8412  }
8413  DusEnd(&sql1);
8414  }
8415  else if (keystate == KSM_STATE_RETIRE) {
8416  /* We are making a key retired */
8417 
8418  /* Set the interval until Dead */
8419  if (keytype == KSM_TYPE_ZSK) {
8420  deltat = collection.zsksiglife + collection.propdelay + collection.ret_safety;
8421  }
8422  else if (keytype == KSM_TYPE_KSK) {
8423  deltat = collection.kskttl + collection.kskpropdelay +
8424  collection.ret_safety; /* Ipp */
8425  }
8426 
8427  /* Generate the SQL to express this interval */
8428  status = DbDateDiff(datetime, deltat, 1, buffer, KSM_SQL_SIZE);
8429  if (status != 0) {
8430  printf("DbDateDiff failed\n");
8431  StrFree(keyids);
8432  return status;
8433  }
8434 
8435  sql1 = DusInit("dnsseckeys");
8436  DusSetInt(&sql1, "STATE", KSM_STATE_RETIRE, 0);
8438  StrAppend(&sql1, ", DEAD = ");
8439  StrAppend(&sql1, buffer);
8440 
8441  DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
8442  if (zone_id != -1) {
8443  DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
8444  }
8445  DusEnd(&sql1);
8446  }
8447  else if (keystate == KSM_STATE_DSPUBLISH) {
8448  /* Set the interval until DSReady */
8449  deltat = collection.kskttl + collection.kskpropdelay +
8450  collection.pub_safety;
8451 
8452  /* Generate the SQL to express this interval */
8453  status = DbDateDiff(datetime, deltat, 1, buffer, KSM_SQL_SIZE);
8454  if (status != 0) {
8455  printf("DbDateDiff failed\n");
8456  StrFree(keyids);
8457  return status;
8458  }
8459 
8460  sql1 = DusInit("dnsseckeys");
8461  DusSetInt(&sql1, "STATE", KSM_STATE_DSPUBLISH, 0);
8463  StrAppend(&sql1, ", READY = ");
8464  StrAppend(&sql1, buffer);
8465 
8466  DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
8467  if (zone_id != -1) {
8468  DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
8469  }
8470  DusEnd(&sql1);
8471  }
8472  else {
8473  printf("Moving to keystate %s not implemented yet\n", KsmKeywordStateValueToName(keystate));
8474  StrFree(keyids);
8475  return -1;
8476  }
8477 
8478  status = DbExecuteSqlNoResult(DbHandle(), sql1);
8479  DusFree(sql1);
8480 
8481  StrFree(insql);
8482  StrFree(keyids);
8483 
8484  /* Report any errors */
8485  if (status != 0) {
8486  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
8487  DbRollback();
8488  return status;
8489  }
8490 
8491  /* 3) Commit or Rollback */
8492  if (status == 0) { /* It actually can't be anything else */
8493  /* Everything worked by the looks of it */
8494  DbCommit();
8495  } else {
8496  /* Whatever happened, it was not good */
8497  DbRollback();
8498  }
8499 
8500  return status;
8501 }
8502 
8503 static int restart_enforcerd()
8504 {
8505  /* ToDo: This should really be rewritten so that it will read
8506  OPENDNSSEC_ENFORCER_PIDFILE and send a SIGHUP itself */
8507  return system(ODS_EN_NOTIFY);
8508 }
8509 
8510 /*
8511  * Read the conf.xml file, we will not validate as that was done as we read the database.
8512  * Instead we just extract the RepositoryList into the database and also learn the
8513  * location of the zonelist.
8514  */
8515 int get_conf_key_info(int* interval, int* man_key_gen)
8516 {
8517  int status = 0;
8518  int mysec = 0;
8519  xmlDocPtr doc = NULL;
8520  xmlXPathContextPtr xpathCtx = NULL;
8521  xmlXPathObjectPtr xpathObj = NULL;
8522  char* temp_char = NULL;
8523 
8524  xmlChar *iv_expr = (unsigned char*) "//Configuration/Enforcer/Interval";
8525  xmlChar *mk_expr = (unsigned char*) "//Configuration/Enforcer/ManualKeyGeneration";
8526 
8527  /* Load XML document */
8528  doc = xmlParseFile(config);
8529  if (doc == NULL) {
8530  printf("Error: unable to parse file \"%s\"\n", config);
8531  return(-1);
8532  }
8533 
8534  /* Create xpath evaluation context */
8535  xpathCtx = xmlXPathNewContext(doc);
8536  if(xpathCtx == NULL) {
8537  printf("Error: unable to create new XPath context\n");
8538  xmlFreeDoc(doc);
8539  return(-1);
8540  }
8541 
8542  /* Evaluate xpath expression for interval */
8543  xpathObj = xmlXPathEvalExpression(iv_expr, xpathCtx);
8544  if(xpathObj == NULL) {
8545  printf("Error: unable to evaluate xpath expression: %s", iv_expr);
8546  xmlXPathFreeContext(xpathCtx);
8547  xmlFreeDoc(doc);
8548  return(-1);
8549  }
8550 
8551  temp_char = (char *)xmlXPathCastToString(xpathObj);
8552  status = DtXMLIntervalSeconds(temp_char, &mysec);
8553  if (status > 0) {
8554  printf("Error: unable to convert Interval %s to seconds, error: %i\n", temp_char, status);
8555  StrFree(temp_char);
8556  return status;
8557  }
8558  else if (status == -1) {
8559  printf("Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days\n", temp_char);
8560  }
8561  *interval = mysec;
8562  StrFree(temp_char);
8563  xmlXPathFreeObject(xpathObj);
8564 
8565  /* Evaluate xpath expression for Manual key generation */
8566  xpathObj = xmlXPathEvalExpression(mk_expr, xpathCtx);
8567  if(xpathObj == NULL) {
8568  printf("Error: unable to evaluate xpath expression: %s\n", mk_expr);
8569  xmlXPathFreeContext(xpathCtx);
8570  xmlFreeDoc(doc);
8571  return(-1);
8572  }
8573 
8574  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
8575  /* Manual key generation tag is present */
8576  *man_key_gen = 1;
8577  }
8578  else {
8579  /* Tag absent */
8580  *man_key_gen = 0;
8581  }
8582  xmlXPathFreeObject(xpathObj);
8583 
8584  if (xpathCtx) {
8585  xmlXPathFreeContext(xpathCtx);
8586  }
8587  if (doc) {
8588  xmlFreeDoc(doc);
8589  }
8590 
8591  return 0;
8592 }
8593 
8594 /* TODO put this fn and the one below somewhere that we can call it from here and the enforcer */
8595  /*+
8596  * LinkKeys - Create required entries in Dnsseckeys table for zones added to policies
8597  * (i.e. when keysharing is turned on)
8598  *
8599  * Description:
8600  * Allocates a key in the database.
8601  *
8602  * Arguments:
8603  * const char* zone_name
8604  * name of zone
8605  *
8606  * int policy_id
8607  * ID of policy which the zone is on
8608  *
8609  * int interval
8610  * Enforcer run interval
8611  *
8612  * int man_key_gen
8613  * Manual Key Generation flag
8614  *
8615  * Returns:
8616  * int
8617  * Status return. 0=> Success, non-zero => error.
8618 -*/
8619 
8620 int LinkKeys(const char* zone_name, int policy_id)
8621 {
8622  int status = 0;
8623 
8624  int interval = -1; /* Enforcer interval */
8625  int man_key_gen = -1; /* Manual key generation flag */
8626 
8627  int zone_id = 0; /* id of zone supplied */
8628  KSM_POLICY* policy;
8629 
8630  /* Unused parameter */
8631  (void)policy_id;
8632 
8633  /* Get some info from conf.xml */
8634  status = get_conf_key_info(&interval, &man_key_gen);
8635  if (status != 0) {
8636  printf("Failed to Link Keys to zone\n");
8637  return(1);
8638  }
8639 
8640  status = KsmZoneIdFromName(zone_name, &zone_id);
8641  if (status != 0) {
8642  return(status);
8643  }
8644 
8645  policy = KsmPolicyAlloc();
8646  if (policy == NULL) {
8647  printf("Malloc for policy struct failed\n");
8648  exit(1);
8649  }
8650  SetPolicyDefaults(policy, o_policy);
8651 
8652  status = KsmPolicyExists(o_policy);
8653  if (status == 0) {
8654  /* Policy exists */
8655  status = KsmPolicyRead(policy);
8656  if(status != 0) {
8657  printf("Error: unable to read policy %s from database\n", o_policy);
8658  KsmPolicyFree(policy);
8659  return status;
8660  }
8661  } else {
8662  printf("Error: policy %s doesn't exist in database\n", o_policy);
8663  KsmPolicyFree(policy);
8664  return status;
8665  }
8666 
8667  /* Make sure that enough keys are allocated to this zone */
8668  status = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, interval, zone_name, man_key_gen, 0);
8669  if (status != 0) {
8670  printf("Error allocating zsks to zone %s", zone_name);
8671  KsmPolicyFree(policy);
8672  return(status);
8673  }
8674  status = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, interval, zone_name, man_key_gen, policy->ksk->rollover_scheme);
8675  if (status != 0) {
8676  printf("Error allocating ksks to zone %s", zone_name);
8677  KsmPolicyFree(policy);
8678  return(status);
8679  }
8680 
8681  KsmPolicyFree(policy);
8682  return 0;
8683 }
8684 
8685 /* allocateKeysToZone
8686  *
8687  * Description:
8688  * Allocates existing keys to zones
8689  *
8690  * Arguments:
8691  * policy
8692  * policy that the keys were created for
8693  * key_type
8694  * KSK or ZSK
8695  * zone_id
8696  * ID of zone in question
8697  * interval
8698  * time before next run
8699  * zone_name
8700  * just in case we need to log something
8701  * man_key_gen
8702  * lack of keys may be an issue for the user to fix
8703  * int rollover_scheme
8704  * KSK rollover scheme in use
8705  *
8706  * Returns:
8707  * int
8708  * Status return. 0=> Success, non-zero => error.
8709  * 1 == error with input
8710  * 2 == not enough keys to satisfy policy
8711  * 3 == database error
8712  -*/
8713 
8714 
8715 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)
8716 {
8717  int status = 0;
8718  int keys_needed = 0;
8719  int keys_in_queue = 0;
8720  int keys_pending_retirement = 0;
8721  int new_keys = 0;
8722  int key_pair_id = 0;
8723  int i = 0;
8724  DB_ID ignore = 0;
8725  KSM_PARCOLL collection; /* Parameters collection */
8726  char* datetime = DtParseDateTimeString("now");
8727 
8728  /* Check datetime in case it came back NULL */
8729  if (datetime == NULL) {
8730  printf("Couldn't turn \"now\" into a date, quitting...");
8731  exit(1);
8732  }
8733 
8734  if (policy == NULL) {
8735  printf("NULL policy sent to allocateKeysToZone");
8736  StrFree(datetime);
8737  return 1;
8738  }
8739 
8740  if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) {
8741  printf("Unknown keytype: %i in allocateKeysToZone", key_type);
8742  StrFree(datetime);
8743  return 1;
8744  }
8745 
8746  /* Get list of parameters */
8747  status = KsmParameterCollection(&collection, policy->id);
8748  if (status != 0) {
8749  StrFree(datetime);
8750  return status;
8751  }
8752 
8753  /* Make sure that enough keys are allocated to this zone */
8754  /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */
8755  status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
8756  if (status != 0) {
8757  printf("Could not predict key requirement for next interval for %s", zone_name);
8758  StrFree(datetime);
8759  return 3;
8760  }
8761 
8762  /* How many do we have ? TODO should this include the currently active key?*/
8763  status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id);
8764  if (status != 0) {
8765  printf("Could not count current key numbers for zone %s", zone_name);
8766  StrFree(datetime);
8767  return 3;
8768  }
8769 
8770  /* or about to retire */
8771  status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval);
8772  if (status != 0) {
8773  printf("Could not count keys which may retire before the next run (for zone %s)", zone_name);
8774  StrFree(datetime);
8775  return 3;
8776  }
8777 
8778  StrFree(datetime);
8779  new_keys = keys_needed - (keys_in_queue - keys_pending_retirement);
8780 
8781  /* 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); */
8782 
8783  /* Allocate keys */
8784  for (i=0 ; i < new_keys ; i++){
8785  key_pair_id = 0;
8786  if (key_type == KSM_TYPE_KSK) {
8787  status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
8788  if (status == -1 || key_pair_id == 0) {
8789  if (man_key_gen == 0) {
8790  printf("Not enough keys to satisfy ksk policy for zone: %s", zone_name);
8791  printf("ods-enforcerd will create some more keys on its next run");
8792  }
8793  else {
8794  printf("Not enough keys to satisfy ksk policy for zone: %s", zone_name);
8795  printf("please use \"ods-ksmutil key generate\" to create some more keys.");
8796  }
8797  return 2;
8798  }
8799  else if (status != 0) {
8800  printf("Could not get an unallocated ksk for zone: %s", zone_name);
8801  return 3;
8802  }
8803  } else {
8804  status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
8805  if (status == -1 || key_pair_id == 0) {
8806  if (man_key_gen == 0) {
8807  printf("Not enough keys to satisfy zsk policy for zone: %s", zone_name);
8808  printf("ods-enforcerd will create some more keys on its next run");
8809  }
8810  else {
8811  printf("Not enough keys to satisfy zsk policy for zone: %s", zone_name);
8812  printf("please use \"ods-ksmutil key generate\" to create some more keys.");
8813  }
8814  return 2;
8815  }
8816  else if (status != 0) {
8817  printf("Could not get an unallocated zsk for zone: %s", zone_name);
8818  return 3;
8819  }
8820  }
8821  if(key_pair_id > 0) {
8822  status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, NULL, &ignore);
8823  /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */
8824  } else {
8825  /* This shouldn't happen */
8826  printf("KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name);
8827  exit(1);
8828  }
8829 
8830  }
8831 
8832  return status;
8833 }
8834 
8835 
8836 /* keyRoll
8837  *
8838  * Description:
8839  * Rolls keys far enough for the enforcer to take over
8840  *
8841  * Arguments:
8842  * zone_id
8843  * ID of zone in question (-1 == all)
8844  * policy_id
8845  * policy that should be rolled (-1 == all)
8846  * key_type
8847  * KSK or ZSK (-1 == all)
8848  *
8849  * Returns:
8850  * int
8851  * Status return. 0=> Success, non-zero => error.
8852  -*/
8853 
8854 int keyRoll(int zone_id, int policy_id, int key_type)
8855 {
8856 
8857  int status = 0;
8858  int size = -1;
8859 
8860  char* sql = NULL; /* SQL query */
8861  char* sql1 = NULL; /* SQL query */
8862  char sql2[KSM_SQL_SIZE];
8863  DB_RESULT result1; /* Result of the query */
8864  DB_ROW row = NULL; /* Row data */
8865  int temp_id = -1; /* place to store the key id returned */
8866  int temp_type = -1; /* place to store the key type returned */
8867  int temp_zone_id = -1; /* place to store the zone id returned */
8868  int where = 0;
8869  int j = 0;
8870  DB_RESULT result2; /* Result of the query */
8871  DB_RESULT result3; /* Result of the query */
8872  DB_ROW row2 = NULL; /* Row data */
8873  char* insql1 = NULL; /* SQL query */
8874  char* insql2 = NULL; /* SQL query */
8875  char buffer[32]; /* For integer conversion */
8876 
8877  char* datetime = DtParseDateTimeString("now");
8878 
8879  /* Check datetime in case it came back NULL */
8880  if (datetime == NULL) {
8881  printf("Couldn't turn \"now\" into a date, quitting...\n");
8882  StrFree(datetime);
8883  exit(1);
8884  }
8885 
8886  /* retire the active key(s) */
8887  /* Find the key ID */
8888  sql = DqsSpecifyInit("KEYDATA_VIEW","id, keytype");
8889  if (zone_id != -1) {
8890  DqsConditionInt(&sql, "zone_id", DQS_COMPARE_EQ, zone_id, where++);
8891  }
8892  if (policy_id != -1) {
8893  DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
8894  }
8895  DqsConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
8896  if (key_type != -1) {
8897  DqsConditionInt(&sql, "keytype", DQS_COMPARE_EQ, key_type, where++);
8898  }
8899  DqsEnd(&sql);
8900 
8901  status = DbExecuteSql(DbHandle(), sql, &result1);
8902 
8903  if (status == 0) {
8904  status = DbFetchRow(result1, &row);
8905  while (status == 0) {
8906  /* Got a row, deal with it */
8907  DbInt(row, 0, &temp_id);
8908  DbInt(row, 1, &temp_type);
8909 
8910  sql1 = DusInit("keypairs");
8911  DusSetInt(&sql1, "fixedDate", 1, 0);
8912  DusSetInt(&sql1, "compromisedflag", 1, 1);
8913 
8914  DusConditionInt(&sql1, "id", DQS_COMPARE_EQ, temp_id, 0);
8915  DusEnd(&sql1);
8916  status = DbExecuteSqlNoResult(DbHandle(), sql1);
8917  DusFree(sql1);
8918 
8919  /* Report any errors */
8920  if (status != 0) {
8921  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
8922  DbFreeRow(row);
8923  return status;
8924  }
8925 
8926  /* Loop over instances of this key: */
8927  /* active-> set retire time */
8928  sql1 = DusInit("dnsseckeys");
8929  DusSetString(&sql1, "RETIRE", datetime, 0);
8930 
8931  DusConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
8932  DusConditionInt(&sql1, "state", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, 1);
8933  DusEnd(&sql1);
8934  status = DbExecuteSqlNoResult(DbHandle(), sql1);
8935  DusFree(sql1);
8936 
8937  /* Report any errors */
8938  if (status != 0) {
8939  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
8940  DbFreeRow(row);
8941  return status;
8942  }
8943 
8944  /* other-> move to dead */
8945  sql1 = DusInit("dnsseckeys");
8946  DusSetString(&sql1, "DEAD", datetime, 0);
8947  DusSetInt(&sql1, "state", KSM_STATE_DEAD, 1);
8948 
8949  DusConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
8950  DusConditionInt(&sql1, "state", DQS_COMPARE_NE, KSM_STATE_ACTIVE, 1);
8951  DusEnd(&sql1);
8952  status = DbExecuteSqlNoResult(DbHandle(), sql1);
8953  DusFree(sql1);
8954 
8955  /* Report any errors */
8956  if (status != 0) {
8957  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
8958  DbFreeRow(row);
8959  return status;
8960  }
8961 
8962  /* Promote any standby keys if we need to, i.e. we retired a KSK
8963  and there is nothing able to take over from it */
8964  if (temp_type == KSM_TYPE_KSK) {
8965  /* find each zone in turn */
8966  /* Depressingly MySQL can't run the following sql; so we need
8967  to build it by parts... There has to be a better way to do
8968  this.
8969  size = snprintf(sql2, KSM_SQL_SIZE, "update dnsseckeys set state = %d where state = %d and zone_id in (select zone_id from dnsseckeys where retire = \"%s\" and keypair_id = %d) and zone_id not in (select zone_id from KEYDATA_VIEW where policy_id = %d and keytype = %d and state in (%d,%d))", KSM_STATE_KEYPUBLISH, KSM_STATE_DSREADY, datetime, temp_id, policy_id, KSM_TYPE_KSK, KSM_STATE_PUBLISH, KSM_STATE_READY); */
8970 
8971  /* First INSQL: select zone_id from dnsseckeys where retire = "DATETIME" and keypair_id = temp_id*/
8972 
8973  size = snprintf(sql2, KSM_SQL_SIZE, "select zone_id from dnsseckeys where retire = \"%s\" and keypair_id = %d", datetime, temp_id);
8974  status = DbExecuteSql(DbHandle(), sql2, &result2);
8975  if (status == 0) {
8976  status = DbFetchRow(result2, &row2);
8977  while (status == 0) {
8978  /* Got a row, print it */
8979  DbInt(row2, 0, &temp_zone_id);
8980 
8981  if (j != 0) {
8982  StrAppend(&insql1, ",");
8983  }
8984  snprintf(buffer, sizeof(buffer), "%d", temp_zone_id);
8985  StrAppend(&insql1, buffer);
8986  j++;
8987 
8988  status = DbFetchRow(result2, &row2);
8989  }
8990 
8991  /* Convert EOF status to success */
8992 
8993  if (status == -1) {
8994  status = 0;
8995  }
8996 
8997  DbFreeResult(result2);
8998  }
8999 
9000  /* Second INSQL: select zone_id from KEYDATA_VIEW where policy_id = policy_id and keytype = KSK and state in (publish,ready) */
9001 
9002  size = snprintf(sql2, KSM_SQL_SIZE, "select zone_id from KEYDATA_VIEW where policy_id = %d and keytype = %d and state in (%d,%d)", policy_id, KSM_TYPE_KSK, KSM_STATE_PUBLISH, KSM_STATE_READY);
9003  j=0;
9004  status = DbExecuteSql(DbHandle(), sql2, &result3);
9005  if (status == 0) {
9006  status = DbFetchRow(result3, &row2);
9007  while (status == 0) {
9008  /* Got a row, print it */
9009  DbInt(row2, 0, &temp_zone_id);
9010 
9011  if (j != 0) {
9012  StrAppend(&insql2, ",");
9013  }
9014  snprintf(buffer, sizeof(buffer), "%d", temp_zone_id);
9015  StrAppend(&insql2, buffer);
9016  j++;
9017 
9018  status = DbFetchRow(result3, &row2);
9019  }
9020 
9021  /* Convert EOF status to success */
9022 
9023  if (status == -1) {
9024  status = 0;
9025  }
9026 
9027  DbFreeResult(result3);
9028  }
9029  DbFreeRow(row2);
9030 
9031  /* Finally we can do the update */
9032  size = snprintf(sql2, KSM_SQL_SIZE, "update dnsseckeys set state = %d where state = %d and zone_id in (%s) and zone_id not in (%s)", KSM_STATE_KEYPUBLISH, KSM_STATE_DSREADY, insql1, insql2);
9033 
9034  /* Quick check that we didn't run out of space */
9035  if (size < 0 || size >= KSM_SQL_SIZE) {
9036  printf("Couldn't construct SQL to promote standby key\n");
9037  StrFree(datetime);
9038  DbFreeRow(row);
9039  DqsFree(sql);
9040  DqsFree(insql1);
9041  DqsFree(insql2);
9042  return -1;
9043  }
9044 
9045  status = DbExecuteSqlNoResult(DbHandle(), sql2);
9046 
9047  /* Report any errors */
9048  if (status != 0) {
9049  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
9050  StrFree(datetime);
9051  DbFreeRow(row);
9052  DqsFree(sql);
9053  DqsFree(insql1);
9054  DqsFree(insql2);
9055  return status;
9056  }
9057  }
9058 
9059  /* NEXT KEY */
9060  status = DbFetchRow(result1, &row);
9061  }
9062 
9063  /* Convert EOF status to success */
9064  if (status == -1) {
9065  status = 0;
9066  }
9067  DbFreeResult(result1);
9068  }
9069  DqsFree(sql);
9070  DbFreeRow(row);
9071 
9072  StrFree(datetime);
9073 
9074  return status;
9075 }
9076 
9078 {
9079  int where = 0; /* WHERE clause value */
9080  char* sql = NULL; /* SQL query */
9081  DB_RESULT result; /* Handle converted to a result object */
9082  DB_ROW row = NULL; /* Row data */
9083  int status = 0; /* Status return */
9084 
9085  /* Construct the query */
9086 
9087  sql = DqsSpecifyInit("policies","id, name");
9088  DqsConditionInt(&sql, "ID", DQS_COMPARE_EQ, zone->policy_id, where++);
9089  DqsOrderBy(&sql, "id");
9090 
9091  /* Execute query and free up the query string */
9092  status = DbExecuteSql(DbHandle(), sql, &result);
9093  DqsFree(sql);
9094 
9095  if (status != 0)
9096  {
9097  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
9098  DbFreeResult(result);
9099  return status;
9100  }
9101 
9102  /* Get the next row from the data */
9103  status = DbFetchRow(result, &row);
9104  if (status == 0) {
9105  DbStringBuffer(row, DB_POLICY_NAME, zone->policy_name, KSM_NAME_LENGTH*sizeof(char));
9106  }
9107  else if (status == -1) {}
9108  /* No rows to return (but no error) */
9109  else {
9110  printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
9111  return status;
9112  }
9113 
9114  DbFreeRow(row);
9115  DbFreeResult(result);
9116  return status;
9117 }
9118 
9119 int append_zone(xmlDocPtr doc, KSM_ZONE *zone)
9120 {
9121  xmlNodePtr root;
9122  xmlNodePtr zone_node;
9123  xmlNodePtr adapters_node;
9124  xmlNodePtr input_node;
9125  xmlNodePtr in_ad_node;
9126  xmlNodePtr output_node;
9127  xmlNodePtr out_ad_node;
9128 
9129  root = xmlDocGetRootElement(doc);
9130  if (root == NULL) {
9131  fprintf(stderr,"empty document\n");
9132  return(1);
9133  }
9134  if (xmlStrcmp(root->name, (const xmlChar *) "ZoneList")) {
9135  fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList");
9136  return(1);
9137  }
9138 
9139  zone_node = xmlNewTextChild(root, NULL, (const xmlChar *)"Zone", NULL);
9140  (void) xmlNewProp(zone_node, (const xmlChar *)"name", (const xmlChar *)zone->name);
9141 
9142  /* Policy */
9143  (void) xmlNewTextChild(zone_node, NULL, (const xmlChar *)"Policy", (const xmlChar *)zone->policy_name);
9144 
9145  /* SignConf */
9146  (void) xmlNewTextChild(zone_node, NULL, (const xmlChar *)"SignerConfiguration", (const xmlChar *)zone->signconf);
9147 
9148  /* Adapters */
9149  adapters_node = xmlNewTextChild(zone_node, NULL, (const xmlChar *)"Adapters", NULL);
9150  /* Input */
9151  input_node = xmlNewTextChild(adapters_node, NULL, (const xmlChar *)"Input", NULL);
9152  in_ad_node = xmlNewTextChild (input_node, NULL, (const xmlChar *)"Adapter", (const xmlChar *)zone->input);
9153  /* Default type is "File" */
9154  if (zone->in_type[0] == '\0') { /* Default to "File" */
9155  (void) xmlNewProp(in_ad_node, (const xmlChar *)"type", (const xmlChar *)"File");
9156  } else {
9157  (void) xmlNewProp(in_ad_node, (const xmlChar *)"type", (const xmlChar *)zone->in_type);
9158  }
9159 
9160  /* Output */
9161  output_node = xmlNewTextChild(adapters_node, NULL, (const xmlChar *)"Output", NULL);
9162  out_ad_node = xmlNewTextChild (output_node, NULL, (const xmlChar *)"Adapter", (const xmlChar *)zone->output);
9163  /* Default type is "File" */
9164  if (zone->out_type[0] == '\0') {
9165  (void) xmlNewProp(out_ad_node, (const xmlChar *)"type", (const xmlChar *)"File");
9166  } else {
9167  (void) xmlNewProp(out_ad_node, (const xmlChar *)"type", (const xmlChar *)zone->out_type);
9168  }
9169 
9170  return(0);
9171 }
9172 
9173 int ShellQuoteString(const char* string, char* buffer, size_t buflen)
9174 {
9175  size_t i; /* Loop counter */
9176  size_t j = 0; /* Counter for new string */
9177 
9178  size_t len = 0;
9179 
9180  if (string) {
9181  len = strlen(string);
9182 
9183  for (i = 0; i < len; ++i) {
9184  if (string[i] == '\'') {
9185  buffer[j++] = '\'';
9186  buffer[j++] = '\\';
9187  buffer[j++] = '\'';
9188  }
9189  buffer[j++] = string[i];
9190  }
9191  }
9192  buffer[j] = '\0';
9193  return ( (j <= buflen) ? 0 : 1);
9194 }
9195 
9196 int rename_signconf(const char* zonelist_filename, const char* o_zone) {
9197  int status = 0;
9198  char* signconf = NULL;
9199  char* moved_signconf = NULL;
9200  char* zone_name = NULL;
9201  int i = 0;
9202 
9203  /* All of the XML stuff */
9204  xmlDocPtr doc = NULL;
9205  xmlNode *curNode;
9206  xmlXPathContextPtr xpathCtx = NULL;
9207  xmlXPathObjectPtr xpathObj = NULL;
9208 
9209  xmlChar *node_expr = (unsigned char*) "//Zone";
9210 /* Load XML document */
9211  doc = xmlParseFile(zonelist_filename);
9212  if (doc == NULL) {
9213  printf("Error: unable to parse file \"%s\"\n", zonelist_filename);
9214  return(-1);
9215  }
9216 /* Create xpath evaluation context */
9217  xpathCtx = xmlXPathNewContext(doc);
9218  if(xpathCtx == NULL) {
9219  xmlFreeDoc(doc);
9220  return(1);
9221  }
9222 
9223  /* Evaluate xpath expression */
9224  xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx);
9225  if(xpathObj == NULL) {
9226  xmlXPathFreeContext(xpathCtx);
9227  xmlFreeDoc(doc);
9228  return(1);
9229  }
9230 
9231  if (xpathObj->nodesetval) {
9232  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
9233 
9234  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
9235  zone_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], (const xmlChar *)"name");
9236 
9237  if (all_flag || (strlen(zone_name) == strlen(o_zone) &&
9238  strncmp(zone_name, o_zone, strlen(zone_name)) == 0)) {
9239 
9240  while (curNode) {
9241 
9242  if (xmlStrEqual(curNode->name, (const xmlChar *)"SignerConfiguration")) {
9243  StrAppend(&signconf, (char *) xmlNodeGetContent(curNode));
9244  StrAppend(&moved_signconf, signconf);
9245  StrAppend(&moved_signconf, ".ZONE_DELETED");
9246  /* Do the move */
9247  status = rename(signconf, moved_signconf);
9248  if (status != 0 && errno != ENOENT)
9249  {
9250  /* cope with initial condition of files not existing */
9251  printf("Could not rename: %s -> %s", signconf, moved_signconf);
9252  StrFree(signconf);
9253  StrFree(moved_signconf);
9254  return(1);
9255  }
9256  StrFree(signconf);
9257  StrFree(moved_signconf);
9258  break;
9259  }
9260 
9261  curNode = curNode->next;
9262  }
9263 
9264  if (!all_flag) {
9265  break;
9266  }
9267  }
9268  }
9269  }
9270 
9271  return 0;
9272 }
9273 
9274 /*+
9275  * ListDS - List DS records currently involved with rollovers
9276  *
9277  *
9278  * Arguments:
9279  *
9280  * int zone_id
9281  * -1 for all zones
9282  *
9283  * Returns:
9284  * int
9285  * Status return. 0 on success.
9286  * other on fail
9287  */
9288 
9289 int ListDS(int zone_id) {
9290 
9291  int status = 0;
9292  char* sql = NULL;
9293  char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */
9294  DB_RESULT result; /* Result of the query */
9295  DB_ROW row = NULL; /* Row data */
9296 
9297  char* temp_zone = NULL; /* place to store zone name returned */
9298  int temp_policy = 0; /* place to store policy id returned */
9299  char* temp_location = NULL; /* place to store location returned */
9300  int temp_algo = 0; /* place to store algorithm returned */
9301 
9302  int rrttl = -1; /* TTL to put into DS record */
9303  int param_id = -1; /* unused */
9304 
9305  /* Key information */
9306  hsm_key_t *key = NULL;
9307  ldns_rr *dnskey_rr = NULL;
9308  hsm_sign_params_t *sign_params = NULL;
9309  int i = 0;
9310 
9311  /* Output strings */
9312  char* ds_buffer = NULL; /* Contents of DS records */
9313 
9314  /* connect to the HSM */
9315  status = hsm_open(config, hsm_prompt_pin);
9316  if (status) {
9317  hsm_print_error(NULL);
9318  return(1);
9319  }
9320 
9321  StrAppend(&sql,
9322  "select name, kv.policy_id, location, algorithm from KEYDATA_VIEW kv, zones z where keytype = 257 and state in (3,7) and zone_id = z.id ");
9323  if (zone_id != -1) {
9324  StrAppend(&sql, "and zone_id = ");
9325  snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
9326  StrAppend(&sql, stringval);
9327  }
9328  StrAppend(&sql, " order by zone_id");
9329 
9330  DusEnd(&sql);
9331 
9332  status = DbExecuteSql(DbHandle(), sql, &result);
9333 
9334  if (status == 0) {
9335  status = DbFetchRow(result, &row);
9336  while (status == 0) {
9337  /* Got a row, print it */
9338  DbString(row, 0, &temp_zone);
9339  DbInt(row, 1, &temp_policy);
9340  DbString(row, 2, &temp_location);
9341  DbInt(row, 3, &temp_algo);
9342 
9343  /* Code to output the DNSKEY record (stolen from hsmutil) */
9344  key = hsm_find_key_by_id(NULL, temp_location);
9345 
9346  if (!key) {
9347  printf("Key %s in DB but not repository.", temp_location);
9348  DbFreeRow(row);
9349  DbStringFree(temp_location);
9350  DbStringFree(temp_zone);
9351  StrFree(sql);
9352  hsm_close();
9353  return status;
9354  }
9355 
9356  printf("\n*** Found DNSKEY RECORD involved with rollover:\n");
9357 
9358  sign_params = hsm_sign_params_new();
9359  sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, temp_zone);
9360  sign_params->algorithm = temp_algo;
9361  sign_params->flags = LDNS_KEY_ZONE_KEY;
9362  sign_params->flags += LDNS_KEY_SEP_KEY;
9363  dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
9364 
9365  /* Use this to get the TTL parameter value */
9366  status = KsmParameterValue(KSM_PAR_KSKTTL_STRING, KSM_PAR_KSKTTL_CAT, &rrttl, temp_policy, &param_id);
9367  if (status == 0) {
9368  ldns_rr_set_ttl(dnskey_rr, rrttl);
9369  }
9370 
9371  ds_buffer = ldns_rr2str(dnskey_rr);
9372  ldns_rr_free(dnskey_rr);
9373 
9374  /* Replace tab with white-space */
9375  for (i = 0; ds_buffer[i]; ++i) {
9376  if (ds_buffer[i] == '\t') {
9377  ds_buffer[i] = ' ';
9378  }
9379  }
9380 
9381  /* Print it */
9382  printf("%s", ds_buffer);
9383  printf("\nOnce the DS record for this DNSKEY is seen in DNS you can issue the ds-seen command for zone %s with the cka_id %s\n", temp_zone, temp_location);
9384 
9385  StrFree(ds_buffer);
9386  DbStringFree(temp_location);
9387  DbStringFree(temp_zone);
9388 
9389  hsm_sign_params_free(sign_params);
9390  hsm_key_free(key);
9391 
9392  status = DbFetchRow(result, &row);
9393  }
9394  /* Convert EOF status to success */
9395  if (status == -1) {
9396  status = 0;
9397  }
9398 
9399  }
9400 
9401  DbFreeRow(row);
9402  StrFree(sql);
9403  hsm_close();
9404 
9405  return status;
9406 }
#define BOOL_TYPE
Definition: ksmutil.c:78
int cmd_listzone()
Definition: ksmutil.c:1352
void DbFreeResult(DB_RESULT result)
int KsmCheckHSMkeyID(int repo_id, const char *cka_id, int *exists)
Definition: ksm_import.c:725
#define KSM_MSG_LENGTH
Definition: ksm.h:60
void usage_keyroll()
Definition: ksmutil.c:315
int LinkKeys(const char *zone_name, int policy_id)
Definition: ksmutil.c:8620
int cmd_rollpolicy()
Definition: ksmutil.c:2058
int KsmPolicyInit(DB_RESULT *handle, const char *name)
Definition: ksm_policy.c:69
char name[KSM_NAME_LENGTH]
Definition: ksm.h:244
unsigned long sm_capacity
Definition: ksm.h:211
int update_policies(char *kasp_filename)
Definition: ksmutil.c:4548
int zone_id
Definition: ksm.h:117
sqlite3 * DB_HANDLE
Definition: database.h:79
void db_disconnect(FILE *lock_fd)
Definition: ksmutil.c:4245
char name[KSM_ZONE_NAME_LENGTH]
Definition: ksm.h:286
#define KSM_TYPE_ZSK
Definition: ksm.h:359
int release_lite_lock(FILE *lock_fd)
Definition: ksmutil.c:4310
int KsmZoneIdAndPolicyFromName(const char *zone_name, int *policy_id, int *zone_id)
Definition: ksm_zone.c:312
#define StrFree(x)
Definition: string_util.h:68
int StrIsDigits(const char *string)
Definition: string_util2.c:590
void DusConditionKeyword(char **query, const char *field, DQS_COMPARISON compare, const char *value, int clause)
Definition: du_string.c:184
int overlap
Definition: ksm.h:213
xmlDocPtr add_zone_node(const char *docname, const char *zone_name, const char *policy_name, const char *sig_conf_name, const char *input_name, const char *output_name, const char *input_type, const char *output_type)
Definition: ksmutil.c:6101
#define INT_TYPE_NO_FREE
Definition: ksmutil.c:82
int DbRollback(void)
void usage_update()
Definition: ksmutil.c:170
char signconf[KSM_PATH_LENGTH]
Definition: ksm.h:287
int DbFlavour(void)
int rfc5011
Definition: ksm.h:215
int DbFetchRow(DB_RESULT result, DB_ROW *row)
void usage_keydelete()
Definition: ksmutil.c:369
void SetPolicyDefaults(KSM_POLICY *policy, char *name)
Definition: ksmutil.c:5646
#define KSM_STATE_DEAD
Definition: ksm.h:372
int backup_interval
Definition: ksm.h:224
int KsmPolicy(DB_RESULT handle, KSM_POLICY *data)
Definition: ksm_policy.c:191
int cmd_listrepo()
Definition: ksmutil.c:2487
void usage_setup()
Definition: ksmutil.c:154
char * o_retire
Definition: ksmutil.c:114
int serial
Definition: ksm.h:232
char * o_out_type
Definition: ksmutil.c:108
int cmd_listkeys()
Definition: ksmutil.c:2567
#define INT_TYPE
Definition: ksmutil.c:76
char * DqsSpecifyInit(const char *table, const char *fields)
Definition: dq_string.c:119
#define KSM_STATE_ACTIVE
Definition: ksm.h:368
int kskttl
Definition: ksm.h:481
#define REPO_TYPE
Definition: ksmutil.c:79
char location[KSM_NAME_LENGTH]
Definition: ksm.h:111
char * optarg
char * o_time
Definition: ksmutil.c:113
int KsmKeywordTypeNameToValue(const char *name)
Definition: ksm_keyword.c:229
int soa_min
Definition: ksm.h:231
void usage_policyimport()
Definition: ksmutil.c:238
#define SERIAL_TYPE
Definition: ksmutil.c:80
int KsmMarkPreBackup(int repo_id, const char *datetime)
Definition: ksm_import.c:519
int KsmKeyCountQueue(int keytype, int *count, int zone_id)
Definition: ksm_key.c:655
int pub_safety
Definition: ksm.h:484
KSM_POLICY * KsmPolicyAlloc()
Definition: ksm_policy.c:949
#define KSM_STATE_READY
Definition: ksm.h:366
#define KSM_PAR_ZSKTTL_CAT
Definition: ksm.h:440
int KsmParameter(DB_RESULT result, KSM_PARAMETER *data)
KSM_COMMON_KEY_POLICY * keys
Definition: ksm.h:249
void usage_policylist()
Definition: ksmutil.c:245
int ShellQuoteString(const char *string, char *buffer, size_t buflen)
Definition: ksmutil.c:9173
int KsmZoneInit(DB_RESULT *handle, int policy_id)
Definition: ksm_zone.c:68
int ListKeys(int zone_id)
Definition: ksmutil.c:6534
int state
Definition: ksm.h:101
int KsmParameterCollection(KSM_PARCOLL *data, int policy_id)
int cmd_listrolls()
Definition: ksmutil.c:2368
void usage_keyimport()
Definition: ksmutil.c:298
int soa_ttl
Definition: ksm.h:230
int cmd_setup()
Definition: ksmutil.c:525
void DusFree(char *sql)
Definition: du_string.c:225
#define KSM_TIME_LENGTH
Definition: ksm.h:63
int KsmSerialIdFromName(const char *name, int *id)
Definition: ksm_import.c:429
int main(int argc, char *argv[])
Definition: ksmutil.c:3762
int ListDS(int zone_id)
Definition: ksmutil.c:9289
int cmd_listpolicy()
Definition: ksmutil.c:2528
KSM_KEY_POLICY * zsk
Definition: ksm.h:251
void usage_backup()
Definition: ksmutil.c:395
char * o_keytag
Definition: ksmutil.c:117
char retire[KSM_TIME_LENGTH]
Definition: ksm.h:110
int bits
Definition: ksm.h:207
int KsmPolicySetIdFromName(KSM_POLICY *policy)
Definition: ksm_policy.c:807
char * o_output
Definition: ksmutil.c:107
int get_db_details(char **dbschema, char **host, char **port, char **user, char **password)
Definition: ksmutil.c:5796
#define DURATION_TYPE
Definition: ksmutil.c:77
xmlDocPtr del_zone_node(const char *docname, const char *zone_name)
Definition: ksmutil.c:6156
void DqsConditionKeyword(char **query, const char *field, DQS_COMPARISON compare, const char *value, int index)
Definition: dq_string.c:253
int dsttl
Definition: ksm.h:488
int cmd_purgepolicy()
Definition: ksmutil.c:3493
int get_policy_name_from_id(KSM_ZONE *zone)
Definition: ksmutil.c:9077
int zsksiglife
Definition: ksm.h:478
#define KSM_ROLL_DEFAULT
Definition: ksm.h:395
int cmd_kskretire()
Definition: ksmutil.c:2625
void usage_zonelist2()
Definition: ksmutil.c:429
int KsmKeyPairCreate(int policy_id, const char *HSMKeyID, int smID, int size, int alg, const char *generate, DB_ID *id)
Definition: ksm_key.c:86
int KsmImportZone(const char *zone_name, int policy_id, int fail_if_exists, int *new_zone, const char *signconf, const char *input, const char *output, const char *input_type, const char *output_type)
Definition: ksm_import.c:220
int KsmZone(DB_RESULT handle, KSM_ZONE *data)
Definition: ksm_zone.c:152
int KsmKeywordRollNameToValue(const char *name)
Definition: ksm_keyword.c:259
int manual_rollover
Definition: ksm.h:218
void list_zone_node(const char *docname, int *zone_ids)
Definition: ksmutil.c:6210
void DqsOrderBy(char **query, const char *field)
Definition: dq_string.c:279
int cmd_delkey()
Definition: ksmutil.c:7405
int KsmZoneCount(DB_RESULT handle, int *count)
Definition: ksm_zone.c:208
void usage_keypurge()
Definition: ksmutil.c:327
int value
Definition: ksm.h:156
char sm_name[KSM_NAME_LENGTH]
Definition: ksm.h:210
int MsgLog(int status,...)
Definition: message.c:337
int get_conf_key_info(int *interval, int *man_key_gen)
Definition: ksmutil.c:8515
int KsmRollbackMarkPreBackup(int repo_id)
Definition: ksm_import.c:582
#define DBS_MIN_VALUE
Definition: dbsmsg.h:6
char * o_cka_id
Definition: ksmutil.c:104
int shared_keys
Definition: ksm.h:255
int KsmListPolicies()
Definition: ksm_list.c:308
int cmd_genkeys()
Definition: ksmutil.c:6910
int KsmPolicyRead(KSM_POLICY *policy)
Definition: ksm_policy.c:232
int cmd_control(char *command)
Definition: ksmutil.c:3729
int ret_safety
Definition: ksm.h:485
char * o_interval
Definition: ksmutil.c:106
void usage_policyexport()
Definition: ksmutil.c:230
int cmd_addzone()
Definition: ksmutil.c:901
void DusSetInt(char **sql, const char *field, int data, int clause)
Definition: du_string.c:99
int append_policy(xmlDocPtr doc, KSM_POLICY *policy)
Definition: ksmutil.c:6280
void DqsFree(char *query)
Definition: dq_string.c:322
int keyRoll(int zone_id, int policy_id, int key_type)
Definition: ksmutil.c:8854
int ksklife
Definition: ksm.h:471
#define KSM_STATE_KEYPUBLISH
Definition: ksm.h:380
void DdsFree(char *query)
Definition: dd_string.c:117
int algorithm
Definition: ksm.h:206
void DusConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int clause)
Definition: du_string.c:172
#define MemFree(ptr)
Definition: memory.h:50
const char * KsmKeywordStateValueToName(int value)
Definition: ksm_keyword.c:244
char * DqsCountInit(const char *table)
Definition: dq_string.c:92
void usage_repo()
Definition: ksmutil.c:223
#define MAXPATHLEN
Definition: ksmutil.c:85
int cmd_exportpolicy()
Definition: ksmutil.c:1782
void usage_keydsseen()
Definition: ksmutil.c:357
void usage_policy()
Definition: ksmutil.c:259
int KsmPolicyIdFromName(const char *name, int *id)
Definition: ksm_import.c:472
#define KSM_NAME_LENGTH
Definition: ksm.h:59
int cmd_exportzonelist()
Definition: ksmutil.c:1875
void usage_rollover()
Definition: ksmutil.c:413
DB_HANDLE DbHandle(void)
int DbString(DB_ROW row, int field_index, char **result)
#define KSM_PAR_DSTTL_CAT
Definition: ksm.h:464
void types_help()
Definition: ksmutil.c:498
int KsmSmIdFromName(const char *name, int *id)
Definition: ksm_import.c:400
char * StrStrdup(const char *string)
Definition: string_util.c:126
int keygeninterval
Definition: ksm.h:225
void DqsConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int index)
Definition: dq_string.c:226
void DdsConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int index)
Definition: dd_string.c:90
#define KSM_PAR_ZSKTTL_STRING
Definition: ksm.h:439
int saltlength
Definition: ksm.h:192
int policy_id
Definition: ksm.h:285
int KsmPolicyIdFromZoneId(int zone_id, int *policy_id)
Definition: ksm_policy.c:856
int DbCommit(void)
int SetParamOnPolicy(const xmlChar *new_value, const char *name, const char *category, int current_value, int policy_id, int value_type)
Definition: ksmutil.c:5549
void states_help()
Definition: ksmutil.c:491
char * DdsInit(const char *table)
Definition: dd_string.c:62
char * config
Definition: ksmutil.c:98
void date_help()
Definition: ksmutil.c:471
int DtGeneral(const char *string, struct tm *datetime)
Definition: datetime.c:329
char * DtParseDateTimeString(const char *string)
Definition: datetime.c:617
#define KSM_STATE_DSPUBLISH
Definition: ksm.h:376
KSM_PARENT_POLICY * parent
Definition: ksm.h:254
char output[KSM_PATH_LENGTH]
Definition: ksm.h:289
void ksm_log_msg(const char *format)
Definition: ksmutil.c:6514
int cmd_dsseen()
Definition: ksmutil.c:2825
KSM_DENIAL_POLICY * denial
Definition: ksm.h:248
int backup_file(const char *orig_file, const char *backup_file)
Definition: ksmutil.c:5728
int printKey(void *context, KSM_KEYDATA *key_data)
Definition: ksmutil.c:6493
int KsmZoneIdFromName(const char *zone_name, int *zone_id)
Definition: ksm_zone.c:249
KSM_KEY_POLICY * ksk
Definition: ksm.h:250
void usage_control()
Definition: ksmutil.c:162
int KsmListRollovers(int zone_id, int *ds_count)
Definition: ksm_list.c:371
unsigned long DB_ID
Definition: database.h:80
KSM_ZONE_POLICY * zone
Definition: ksm.h:253
int KsmParameterValue(const char *name, const char *category, int *value, int policy_id, int *parameter_id)
void usage_keylist()
Definition: ksmutil.c:271
int KsmListRepos()
Definition: ksm_list.c:244
int KsmKeyInitSql(DB_RESULT *result, const char *sql)
Definition: ksm_key.c:219
int cmd_listbackups()
Definition: ksmutil.c:2438
int GetKeyState(const char *cka_id, int *temp_key_state, int *temp_keypair_id)
Definition: ksmutil.c:7895
#define SQLITE_DB
Definition: database.h:48
int propdelay
Definition: ksm.h:229
int KsmCollectionInit(KSM_PARCOLL *data)
int update_repositories()
Definition: ksmutil.c:4443
#define DB_KEYDATA_FIELDS
Definition: db_fields.h:58
const char * DbErrmsg(DB_HANDLE handle)
int type
Definition: ksm.h:216
int KsmImportPolicy(const char *policy_name, const char *policy_description)
Definition: ksm_import.c:149
char policy_name[KSM_NAME_LENGTH]
Definition: ksm.h:290
int propdelay
Definition: ksm.h:474
void KsmPolicyFree(KSM_POLICY *policy)
Definition: ksm_policy.c:987
void DbFreeRow(DB_ROW row)
int KsmKey(DB_RESULT result, KSM_KEYDATA *data)
Definition: ksm_key.c:368
void MsgRegister(int min, int max, const char **message, MSG_OUTPUT_FUNCTION output)
Definition: message.c:143
KSM_SIGNER_POLICY * signer
Definition: ksm.h:246
size_t StrToLower(char *text)
Definition: string_util.c:325
int cmd_update(const char *qualifier)
Definition: ksmutil.c:778
char input[KSM_PATH_LENGTH]
Definition: ksm.h:288
int DbDisconnect(DB_HANDLE dbhandle)
void usage_zoneadd()
Definition: ksmutil.c:181
int standby_keys
Definition: ksm.h:217
int KsmPolicyUpdateDesc(int policy_id, const char *policy_description)
Definition: ksm_policy.c:919
int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme, int zone_count)
Definition: ksm_key.c:564
int KsmMarkKeysAsDead(int zone_id)
Definition: ksm_key.c:948
int read_zonelist_filename(char **zone_list_filename)
Definition: ksmutil.c:6023
void usage_database()
Definition: ksmutil.c:421
const char * KsmKeywordSerialValueToName(int value)
Definition: ksm_keyword.c:254
#define KME_MAX_VALUE
Definition: kmemsg.h:7
int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, int state, const char *time, const char *retTime, DB_ID *id)
Definition: ksm_key.c:143
#define DBS_MAX_VALUE
Definition: dbsmsg.h:7
int KsmPolicyNullSaltStamp(int policy_id)
Definition: ksm_policy.c:673
int DbExecuteSql(DB_HANDLE handle, const char *stmt_str, DB_RESULT *result)
int keytype
Definition: ksm.h:102
int cmd_dbbackup()
Definition: ksmutil.c:3403
#define KSM_SQL_SIZE
Definition: ksm.h:65
#define KSM_POLICY_DESC_LENGTH
Definition: ksm.h:62
char * o_keytype
Definition: ksmutil.c:112
int DbStringBuffer(DB_ROW row, int field_index, char *buffer, size_t buflen)
void usage_keygen()
Definition: ksmutil.c:337
int PurgeKeys(int zone_id, int policy_id)
Definition: ksmutil.c:6742
#define KME_SQLFAIL
Definition: kmedef.h:69
int cmd_delzone()
Definition: ksmutil.c:1194
void StrAppend(char **str1, const char *str2)
Definition: string_util2.c:78
int propdelay
Definition: ksm.h:236
char * o_zone
Definition: ksmutil.c:115
int StrStrtoi(const char *string, int *value)
Definition: string_util2.c:508
int ChangeKeyState(int keytype, const char *cka_id, int zone_id, int policy_id, const char *datetime, int keystate)
Definition: ksmutil.c:8266
char * description
Definition: ksm.h:245
int algorithm
Definition: ksm.h:103
void DusEnd(char **sql)
Definition: du_string.c:204
int propdelay
Definition: ksm.h:172
int DbIntQuery(DB_HANDLE handle, int *value, const char *query)
void usage_keykskretire()
Definition: ksmutil.c:348
#define KSM_PAR_KSKTTL_CAT
Definition: ksm.h:443
void usage_keyexport()
Definition: ksmutil.c:287
#define KSM_STATE_RETIRE
Definition: ksm.h:370
#define KSM_STATE_PUBLISH
Definition: ksm.h:364
#define KME_MIN_VALUE
Definition: kmemsg.h:6
int DbDateDiff(const char *start, int delta, int sign, char *buffer, size_t buflen)
#define KSM_PAR_DSTTL_STRING
Definition: ksm.h:463
void usage_zonedel()
Definition: ksmutil.c:196
int KsmDeleteZone(int zone_id)
Definition: ksm_zone.c:374
char * o_zonetotal
Definition: ksmutil.c:116
#define MYSQL_DB
Definition: database.h:47
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)
Definition: ksmutil.c:8715
int KsmZoneNameFromId(int zone_id, char **zone_name)
Definition: ksm_zone.c:414
char * DusInit(const char *table)
Definition: du_string.c:62
#define DEFAULT_LOG_FACILITY
Definition: ksmutil.c:92
int read_filenames(char **zone_list_filename, char **kasp_filename)
Definition: ksmutil.c:4333
int CountKeysInState(int keytype, int keystate, int *count, int zone_id)
Definition: ksmutil.c:8211
DB_ID keypair_id
Definition: ksm.h:100
void KsmParameterEnd(DB_RESULT result)
int KsmImportKeyPair(int policy_id, const char *HSMKeyID, int smID, int size, int alg, int state, const char *time, int fixDate, DB_ID *id)
Definition: ksm_import.c:346
int cmd_backup(const char *qualifier)
Definition: ksmutil.c:2236
char * o_input
Definition: ksmutil.c:102
int sm
Definition: ksm.h:209
void usage()
Definition: ksmutil.c:437
int RetireOldKey(int zone_id, int policy_id, const char *datetime)
Definition: ksmutil.c:8094
int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int zone_id, int share_keys, int *keypair_id)
Definition: ksm_key.c:872
int db_connect(DB_HANDLE *dbhandle, FILE **lock_fd, int backup)
Definition: ksmutil.c:4149
int append_zone(xmlDocPtr doc, KSM_ZONE *zone)
Definition: ksmutil.c:9119
#define ROLLOVER_TYPE
Definition: ksmutil.c:81
#define DB_ZONE_TABLE
Definition: db_fields.h:99
void usage_zone()
Definition: ksmutil.c:212
int KsmParameterInit(DB_RESULT *result, const char *name, const char *category, int policy_id)
Definition: ksm_parameter.c:85
xmlDocPtr del_policy_node(const char *docname, const char *policy_name)
Definition: ksmutil.c:6449
char * o_repository
Definition: ksmutil.c:110
void usage_zonelist()
Definition: ksmutil.c:205
int kskpropdelay
Definition: ksm.h:482
#define KSM_INT_STR_SIZE
Definition: ksm.h:66
int KsmPolicyExists(const char *name)
Definition: ksm_policy.c:151
int fix_file_perms(const char *dbschema)
Definition: ksmutil.c:7525
char * o_keystate
Definition: ksmutil.c:100
int optind
int id
Definition: ksm.h:243
void usage_policypurge()
Definition: ksmutil.c:252
int ttl
Definition: ksm.h:214
int cmd_exportkeys()
Definition: ksmutil.c:1480
#define KSM_PAR_KSKTTL_STRING
Definition: ksm.h:442
int require_backup
Definition: ksm.h:212
int rename_signconf(const char *zonelist_filename, const char *o_zone)
Definition: ksmutil.c:9196
int KsmRequestPendingRetireCount(int keytype, const char *datetime, KSM_PARCOLL *parameters, int *count, int zone_id, int interval)
Definition: ksm_request.c:1482
#define KSM_STATE_DSSUB
Definition: ksm.h:374
int KsmZoneCountInit(DB_RESULT *handle, int id)
Definition: ksm_zone.c:109
void DdsEnd(char **query)
Definition: dd_string.c:111
#define KSM_TYPE_KSK
Definition: ksm.h:357
int KsmParameterSet(const char *name, const char *category, int value, int policy_id)
KSM_ENFORCER_POLICY * enforcer
Definition: ksm.h:252
int KsmImportRepository(const char *repo_name, const char *repo_capacity, int require_backup)
Definition: ksm_import.c:72
int KsmKeywordAlgorithmNameToValue(const char *name)
Definition: ksm_keyword.c:209
char in_type[KSM_ADAPTER_NAME_LENGTH]
Definition: ksm.h:291
int cmd_keypurge()
Definition: ksmutil.c:2173
int DbInt(DB_ROW row, int field_index, int *value)
void * MemMalloc(size_t size)
Definition: memory.c:59
int cmd_rollzone()
Definition: ksmutil.c:1945
int algorithm
Definition: ksm.h:188
char out_type[KSM_ADAPTER_NAME_LENGTH]
Definition: ksm.h:292
int KsmListBackups(int repo_id, int verbose_flag)
Definition: ksm_list.c:66
#define KSM_STATE_DSREADY
Definition: ksm.h:378
int rollover_scheme
Definition: ksm.h:219
int DtXMLIntervalSeconds(const char *text, int *interval)
Definition: datetime.c:928
size_t StrToUpper(char *text)
Definition: string_util.c:355
void KsmKeyEnd(DB_RESULT result)
Definition: ksm_key.c:471
int get_lite_lock(char *lock_filename, FILE *lock_fd)
Definition: ksmutil.c:4269
int cmd_import()
Definition: ksmutil.c:3092
void MsgInit(void)
Definition: message.c:65
char * o_size
Definition: ksmutil.c:105
int lifetime
Definition: ksm.h:208
int KsmMarkBackup(int repo_id, const char *datetime)
Definition: ksm_import.c:652
int iteration
Definition: ksm.h:189
#define KSM_STATE_GENERATE
Definition: ksm.h:362
void DusSetString(char **sql, const char *field, const char *data, int clause)
Definition: du_string.c:115
int MarkDSSeen(int keypair_id, int zone_id, int policy_id, const char *datetime, int key_state)
Definition: ksmutil.c:7969
void DqsEnd(char **query)
Definition: dq_string.c:301
void usage_general()
Definition: ksmutil.c:146
Definition: ksm.h:283
int DbBeginTransaction(void)
char * o_algo
Definition: ksmutil.c:101
int DbExecuteSqlNoResult(DB_HANDLE handle, const char *stmt_str)
void DqsConditionString(char **query, const char *field, DQS_COMPARISON compare, const char *value, int index)
Definition: dq_string.c:240
char * o_in_type
Definition: ksmutil.c:103
int KsmKeyCountStillGood(int policy_id, int sm, int bits, int algorithm, int interval, const char *datetime, int *count, int keytype)
Definition: ksm_key.c:734
int update_zones(char *zone_list_filename)
Definition: ksmutil.c:5195
void usage_key()
Definition: ksmutil.c:378
#define DB_POLICY_NAME
Definition: db_fields.h:112
int CountKeys(int *zone_id, int keytag, const char *cka_id, int *key_count, char **temp_cka_id, int *temp_key_state, int *temp_keypair_id)
Definition: ksmutil.c:7737
KSM_SIGNATURE_POLICY * signature
Definition: ksm.h:247
char * o_signerconf
Definition: ksmutil.c:111
const char * progname
Definition: ksmutil.c:97
char * o_policy
Definition: ksmutil.c:109
int DbConnect(DB_HANDLE *dbhandle, const char *database,...)
void DbStringFree(char *string)