OpenDNSSEC-enforcer
1.3.8
|
00001 /* 00002 * $Id: ksmutil.c 6295 2012-05-01 10:43:29Z sion $ 00003 * 00004 * Copyright (c) 2008-2009 Nominet UK. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #define _GNU_SOURCE 00029 #include <stdio.h> 00030 #include <string.h> 00031 #include <stdlib.h> 00032 #include <unistd.h> 00033 #include <errno.h> 00034 #include <fcntl.h> 00035 #include <limits.h> 00036 00037 #include "config.h" 00038 00039 #include <getopt.h> 00040 #include <string.h> 00041 #include <syslog.h> 00042 #include <sys/stat.h> 00043 #include <pwd.h> 00044 #include <grp.h> 00045 00046 #include <ksm/ksmutil.h> 00047 #include <ksm/ksm.h> 00048 #include <ksm/database.h> 00049 #include "ksm/database_statement.h" 00050 #include "ksm/db_fields.h" 00051 #include <ksm/datetime.h> 00052 #include <ksm/string_util.h> 00053 #include <ksm/string_util2.h> 00054 #include "ksm/kmemsg.h" 00055 #include "ksm/kmedef.h" 00056 #include "ksm/dbsmsg.h" 00057 #include "ksm/dbsdef.h" 00058 #include "ksm/message.h" 00059 00060 #include <libhsm.h> 00061 #include <libhsmdns.h> 00062 #include <ldns/ldns.h> 00063 00064 #include <libxml/tree.h> 00065 #include <libxml/parser.h> 00066 #include <libxml/xpointer.h> 00067 #include <libxml/xpath.h> 00068 #include <libxml/xpathInternals.h> 00069 #include <libxml/relaxng.h> 00070 #include <libxml/xmlreader.h> 00071 #include <libxml/xmlsave.h> 00072 00073 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 00074 00075 /* Some value type flags */ 00076 #define INT_TYPE 0 00077 #define DURATION_TYPE 1 00078 #define BOOL_TYPE 2 00079 #define REPO_TYPE 3 00080 #define SERIAL_TYPE 4 00081 #define ROLLOVER_TYPE 5 00082 #define INT_TYPE_NO_FREE 6 00083 00084 #ifndef MAXPATHLEN 00085 # define MAXPATHLEN 4096 00086 #endif 00087 00088 /* We write one log message to syslog */ 00089 #ifdef LOG_DAEMON 00090 #define DEFAULT_LOG_FACILITY LOG_DAEMON 00091 #else 00092 #define DEFAULT_LOG_FACILITY LOG_USER 00093 #endif /* LOG_DAEMON */ 00094 00095 extern char *optarg; 00096 extern int optind; 00097 const char *progname = NULL; 00098 char *config = (char *) OPENDNSSEC_CONFIG_FILE; 00099 00100 char *o_keystate = NULL; 00101 char *o_algo = NULL; 00102 char *o_input = NULL; 00103 char *o_cka_id = NULL; 00104 char *o_size = NULL; 00105 char *o_interval = NULL; 00106 char *o_output = NULL; 00107 char *o_policy = NULL; 00108 char *o_repository = NULL; 00109 char *o_signerconf = NULL; 00110 char *o_keytype = NULL; 00111 char *o_time = NULL; 00112 char *o_retire = NULL; 00113 char *o_zone = NULL; 00114 char *o_keytag = NULL; 00115 static int all_flag = 0; 00116 static int ds_flag = 0; 00117 static int retire_flag = 1; 00118 static int verbose_flag = 0; 00119 static int xml_flag = 1; 00120 static int td_flag = 0; 00121 00122 static int restart_enforcerd(void); 00123 00124 void 00125 usage_general () 00126 { 00127 fprintf(stderr, 00128 " help\n" 00129 " --version aka -V\n"); 00130 } 00131 00132 void 00133 usage_setup () 00134 { 00135 fprintf(stderr, 00136 " setup\n" 00137 "\tImport config into a database (deletes current contents)\n"); 00138 } 00139 00140 void 00141 usage_control () 00142 { 00143 fprintf(stderr, 00144 " start|stop|notify\n" 00145 "\tStart, stop or SIGHUP the ods-enforcerd\n"); 00146 } 00147 00148 void 00149 usage_update () 00150 { 00151 fprintf(stderr, 00152 " update kasp\n" 00153 " update zonelist\n" 00154 " update conf\n" 00155 " update all\n" 00156 "\tUpdate database from config\n"); 00157 } 00158 00159 void 00160 usage_zoneadd () 00161 { 00162 fprintf(stderr, 00163 " zone add\n" 00164 "\t--zone <zone> aka -z\n" 00165 "\t[--policy <policy>] aka -p\n" 00166 "\t[--signerconf <signerconf.xml>] aka -s\n" 00167 "\t[--input <input>] aka -i\n" 00168 "\t[--output <output>] aka -o\n" 00169 "\t[--no-xml] aka -m\n"); 00170 } 00171 00172 void 00173 usage_zonedel () 00174 { 00175 fprintf(stderr, 00176 " zone delete\n" 00177 "\t--zone <zone> | --all aka -z / -a\n" 00178 "\t[--no-xml] aka -m\n"); 00179 } 00180 00181 void 00182 usage_zonelist () 00183 { 00184 fprintf(stderr, 00185 " zone list\n"); 00186 } 00187 00188 void 00189 usage_zone () 00190 { 00191 fprintf(stderr, 00192 "usage: %s [-c <config> | --config <config>] zone \n\n", 00193 progname); 00194 usage_zoneadd (); 00195 usage_zonedel (); 00196 usage_zonelist (); 00197 } 00198 00199 void 00200 usage_repo () 00201 { 00202 fprintf(stderr, 00203 " repository list\n"); 00204 } 00205 00206 void 00207 usage_policyexport () 00208 { 00209 fprintf(stderr, 00210 " policy export\n" 00211 "\t--policy [policy_name] | --all aka -p / -a\n"); 00212 } 00213 00214 void 00215 usage_policyimport () 00216 { 00217 fprintf(stderr, 00218 " policy import\n"); 00219 } 00220 00221 void 00222 usage_policylist () 00223 { 00224 fprintf(stderr, 00225 " policy list\n"); 00226 } 00227 00228 void 00229 usage_policypurge () 00230 { 00231 fprintf(stderr, 00232 " policy purge\n"); 00233 } 00234 00235 void 00236 usage_policy () 00237 { 00238 fprintf(stderr, 00239 "usage: %s [-c <config> | --config <config>] \n\n", 00240 progname); 00241 usage_policyexport (); 00242 usage_policyimport (); 00243 usage_policylist (); 00244 usage_policypurge (); 00245 } 00246 00247 void 00248 usage_keylist () 00249 { 00250 fprintf(stderr, 00251 " key list\n" 00252 "\t[--verbose]\n" 00253 "\t--zone <zone> | --all aka -z / -a\n" 00254 #if 0 00255 "\t(will appear soon:\n" 00256 "\t[--keystate <state>] aka -e\n" 00257 "\t[--keytype <type>] aka -t\n" 00258 "\t[--ds] aka -d)\n" 00259 #endif 00260 ); 00261 } 00262 00263 void 00264 usage_keyexport () 00265 { 00266 fprintf(stderr, 00267 " key export\n" 00268 "\t--zone <zone> | --all aka -z / -a\n" 00269 "\t[--keystate <state>] aka -e\n" 00270 "\t[--keytype <type>] aka -t\n" 00271 "\t[--ds] aka -d\n"); 00272 } 00273 00274 void 00275 usage_keyimport () 00276 { 00277 fprintf(stderr, 00278 " key import\n" 00279 "\t--cka_id <CKA_ID> aka -k\n" 00280 "\t--repository <repository> aka -r\n" 00281 "\t--zone <zone> aka -z\n" 00282 "\t--bits <size> aka -b\n" 00283 "\t--algorithm <algorithm> aka -g\n" 00284 "\t--keystate <state> aka -e\n" 00285 "\t--keytype <type> aka -t\n" 00286 "\t--time <time> aka -w\n" 00287 "\t[--retire <retire>] aka -y\n"); 00288 } 00289 00290 void 00291 usage_keyroll () 00292 { 00293 fprintf(stderr, 00294 " key rollover\n" 00295 "\t--zone zone [--keytype <type>] aka -z\n" 00296 " key rollover\n" 00297 "\t--policy policy [--keytype <type>] aka -p\n"); 00298 } 00299 00300 void 00301 usage_keypurge () 00302 { 00303 fprintf(stderr, 00304 " key purge\n" 00305 "\t--zone <zone> aka -z\n" 00306 " key purge\n" 00307 "\t--policy <policy> aka -p\n"); 00308 } 00309 00310 void 00311 usage_keygen () 00312 { 00313 fprintf(stderr, 00314 " key generate\n" 00315 "\t--policy <policy>\n" 00316 "\t--interval <interval>\n"); 00317 } 00318 00319 void 00320 usage_keykskretire () 00321 { 00322 fprintf(stderr, 00323 " key ksk-retire\n" 00324 "\t--zone <zone> aka -z\n" 00325 "\t--keytag <keytag> | --cka_id <CKA_ID> aka -x / -k\n"); 00326 } 00327 00328 void 00329 usage_keydsseen () 00330 { 00331 fprintf(stderr, 00332 " key ds-seen\n" 00333 /*"\t--zone <zone> (or --all) aka -z\n"*/ 00334 "\t--zone <zone> aka -z\n" 00335 "\t--keytag <keytag> | --cka_id <CKA_ID> aka -x / -k\n" 00336 "\t--no-retire\n"); 00337 } 00338 00339 void 00340 usage_key () 00341 { 00342 fprintf(stderr, 00343 "usage: %s [-c <config> | --config <config>] \n\n", 00344 progname); 00345 usage_keylist (); 00346 usage_keyexport (); 00347 usage_keyimport (); 00348 usage_keyroll (); 00349 usage_keypurge (); 00350 usage_keygen (); 00351 usage_keykskretire (); 00352 usage_keydsseen (); 00353 } 00354 00355 void 00356 usage_backup () 00357 { 00358 fprintf(stderr, 00359 " backup prepare\n" 00360 "\t--repository <repository> aka -r\n" 00361 " backup commit\n" 00362 "\t--repository <repository> aka -r\n" 00363 " backup rollback\n" 00364 "\t--repository <repository> aka -r\n" 00365 " backup list\n" 00366 "\t--repository <repository> aka -r\n" 00367 " backup done\n" 00368 "\t--repository <repository> aka -r\n"); 00369 } 00370 00371 void 00372 usage_rollover () 00373 { 00374 fprintf(stderr, 00375 " rollover list\n" 00376 "\t[--zone <zone>]\n"); 00377 } 00378 00379 void 00380 usage_database () 00381 { 00382 fprintf(stderr, 00383 " database backup\n" 00384 "\t[--output <output>] aka -o\n"); 00385 } 00386 00387 void 00388 usage_zonelist2 () 00389 { 00390 fprintf(stderr, 00391 " zonelist export\n" 00392 " zonelist import\n"); 00393 } 00394 00395 void 00396 usage () 00397 { 00398 fprintf(stderr, 00399 "usage: %s [-c <config> | --config <config>] command [options]\n\n", 00400 progname); 00401 00402 usage_general (); 00403 usage_setup (); 00404 usage_control (); 00405 usage_update (); 00406 usage_zoneadd (); 00407 usage_zonedel (); 00408 usage_zonelist (); 00409 usage_repo (); 00410 usage_policyexport (); 00411 usage_policylist (); 00412 usage_policypurge (); 00413 usage_keylist (); 00414 usage_keyexport (); 00415 usage_keyimport (); 00416 usage_keyroll (); 00417 usage_keypurge (); 00418 usage_keygen (); 00419 usage_keykskretire (); 00420 usage_keydsseen (); 00421 usage_backup (); 00422 usage_rollover (); 00423 usage_database (); 00424 usage_zonelist2 (); 00425 00426 } 00427 00428 void 00429 date_help() 00430 { 00431 fprintf(stderr, 00432 "\n\tAllowed date/time strings are of the form:\n" 00433 00434 "\tYYYYMMDD[HH[MM[SS]]] (all numeric)\n" 00435 "\n" 00436 "\tor D-MMM-YYYY[:| ]HH[:MM[:SS]] (alphabetic month)\n" 00437 "\tor DD-MMM-YYYY[:| ]HH[:MM[:SS]] (alphabetic month)\n" 00438 "\tor YYYY-MMM-DD[:| ]HH[:MM[:SS]] (alphabetic month)\n" 00439 "\n" 00440 "\tD-MM-YYYY[:| ]HH[:MM[:SS]] (numeric month)\n" 00441 "\tDD-MM-YYYY[:| ]HH[:MM[:SS]] (numeric month)\n" 00442 "\tor YYYY-MM-DD[:| ]HH[:MM[:SS]] (numeric month)\n" 00443 "\n" 00444 "\t... and the distinction between them is given by the location of the\n" 00445 "\thyphens.\n"); 00446 } 00447 00448 void 00449 states_help() 00450 { 00451 fprintf(stderr, 00452 "key states: GENERATE|PUBLISH|READY|ACTIVE|RETIRE|DEAD\n"); 00453 } 00454 00455 void 00456 types_help() 00457 { 00458 fprintf(stderr, 00459 "key types: KSK|ZSK\n"); 00460 } 00461 00462 /* 00463 * Do initial import of config files into database 00464 */ 00465 int 00466 cmd_setup () 00467 { 00468 DB_HANDLE dbhandle; 00469 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 00470 char* zone_list_filename; /* Extracted from conf.xml */ 00471 char* kasp_filename; /* Extracted from conf.xml */ 00472 int status = 0; 00473 00474 /* Database connection details */ 00475 char *dbschema = NULL; 00476 char *host = NULL; 00477 char *port = NULL; 00478 char *user = NULL; 00479 char *password = NULL; 00480 00481 char quoted_user[KSM_NAME_LENGTH]; 00482 char quoted_password[KSM_NAME_LENGTH]; 00483 00484 char* setup_command = NULL; 00485 char* lock_filename = NULL; 00486 00487 int user_certain; 00488 printf("*WARNING* This will erase all data in the database; are you sure? [y/N] "); 00489 00490 user_certain = getchar(); 00491 if (user_certain != 'y' && user_certain != 'Y') { 00492 printf("Okay, quitting...\n"); 00493 exit(0); 00494 } 00495 00496 /* Right then, they asked for it */ 00497 00498 /* Read the database details out of conf.xml */ 00499 status = get_db_details(&dbschema, &host, &port, &user, &password); 00500 if (status != 0) { 00501 StrFree(host); 00502 StrFree(port); 00503 StrFree(dbschema); 00504 StrFree(user); 00505 StrFree(password); 00506 return(status); 00507 } 00508 00509 /* If we are in sqlite mode then take a lock out on a file to 00510 prevent multiple access (not sure that we can be sure that sqlite is 00511 safe for multiple processes to access). */ 00512 if (DbFlavour() == SQLITE_DB) { 00513 00514 /* Make sure that nothing is happening to the DB */ 00515 StrAppend(&lock_filename, dbschema); 00516 StrAppend(&lock_filename, ".our_lock"); 00517 00518 lock_fd = fopen(lock_filename, "w"); 00519 status = get_lite_lock(lock_filename, lock_fd); 00520 if (status != 0) { 00521 printf("Error getting db lock\n"); 00522 if (lock_fd != NULL) { 00523 fclose(lock_fd); 00524 } 00525 StrFree(lock_filename); 00526 StrFree(host); 00527 StrFree(port); 00528 StrFree(dbschema); 00529 StrFree(user); 00530 StrFree(password); 00531 return(1); 00532 } 00533 StrFree(lock_filename); 00534 00535 /* Run the setup script */ 00536 /* will look like: <SQL_BIN> <DBSCHEMA> < <SQL_SETUP> */ 00537 StrAppend(&setup_command, SQL_BIN); 00538 StrAppend(&setup_command, " "); 00539 StrAppend(&setup_command, dbschema); 00540 StrAppend(&setup_command, " < "); 00541 StrAppend(&setup_command, SQL_SETUP); 00542 00543 if (system(setup_command) != 0) 00544 { 00545 printf("Could not call db setup command:\n\t%s\n", setup_command); 00546 db_disconnect(lock_fd); 00547 StrFree(host); 00548 StrFree(port); 00549 StrFree(dbschema); 00550 StrFree(user); 00551 StrFree(password); 00552 StrFree(setup_command); 00553 return(1); 00554 } 00555 StrFree(setup_command); 00556 00557 /* If we are running as root then chmod the file so that the 00558 final user/group can access it. */ 00559 if (fix_file_perms(dbschema) != 0) 00560 { 00561 printf("Couldn't fix permissions on file %s\n", dbschema); 00562 printf("Will coninue with setup, but you may need to manually change ownership\n"); 00563 } 00564 } 00565 else { 00566 /* MySQL setup */ 00567 /* will look like: <SQL_BIN> -u <USER> -h <HOST> -P <PORT> -p<PASSWORD> <DBSCHEMA> < <SQL_SETUP> */ 00568 00569 /* Get a quoted version of the username */ 00570 status = ShellQuoteString(user, quoted_user, KSM_NAME_LENGTH); 00571 if (status != 0) { 00572 printf("Failed to connect to database, username too long.\n"); 00573 db_disconnect(lock_fd); 00574 StrFree(host); 00575 StrFree(port); 00576 StrFree(dbschema); 00577 StrFree(user); 00578 StrFree(password); 00579 return(1); 00580 } 00581 00582 /* Get a quoted version of the password */ 00583 status = ShellQuoteString(password, quoted_password, KSM_NAME_LENGTH); 00584 if (status != 0) { 00585 printf("Failed to connect to database, password too long.\n"); 00586 db_disconnect(lock_fd); 00587 StrFree(host); 00588 StrFree(port); 00589 StrFree(dbschema); 00590 StrFree(user); 00591 StrFree(password); 00592 return(1); 00593 } 00594 00595 StrAppend(&setup_command, SQL_BIN); 00596 StrAppend(&setup_command, " -u '"); 00597 StrAppend(&setup_command, quoted_user); 00598 StrAppend(&setup_command, "'"); 00599 if (host != NULL) { 00600 StrAppend(&setup_command, " -h "); 00601 StrAppend(&setup_command, host); 00602 if (port != NULL) { 00603 StrAppend(&setup_command, " -P "); 00604 StrAppend(&setup_command, port); 00605 } 00606 } 00607 if (password != NULL) { 00608 StrAppend(&setup_command, " -p'"); 00609 StrAppend(&setup_command, quoted_password); 00610 StrAppend(&setup_command, "'"); 00611 } 00612 StrAppend(&setup_command, " "); 00613 StrAppend(&setup_command, dbschema); 00614 StrAppend(&setup_command, " < "); 00615 StrAppend(&setup_command, SQL_SETUP); 00616 00617 if (system(setup_command) != 0) 00618 { 00619 printf("Could not call db setup command:\n\t%s\n", setup_command); 00620 StrFree(host); 00621 StrFree(port); 00622 StrFree(dbschema); 00623 StrFree(user); 00624 StrFree(password); 00625 StrFree(setup_command); 00626 return(1); 00627 } 00628 StrFree(setup_command); 00629 } 00630 00631 /* try to connect to the database */ 00632 status = DbConnect(&dbhandle, dbschema, host, password, user, port); 00633 if (status != 0) { 00634 printf("Failed to connect to database\n"); 00635 db_disconnect(lock_fd); 00636 StrFree(host); 00637 StrFree(port); 00638 StrFree(dbschema); 00639 StrFree(user); 00640 StrFree(password); 00641 return(1); 00642 } 00643 00644 /* Free these up early */ 00645 StrFree(host); 00646 StrFree(port); 00647 StrFree(dbschema); 00648 StrFree(user); 00649 StrFree(password); 00650 00651 /* 00652 * Now we will read the conf.xml file again, but this time we will not validate. 00653 * Instead we just learn the location of the zonelist.xml and kasp.xml files. 00654 */ 00655 status = read_filenames(&zone_list_filename, &kasp_filename); 00656 if (status != 0) { 00657 printf("Failed to read conf.xml\n"); 00658 db_disconnect(lock_fd); 00659 return(1); 00660 } 00661 00662 /* 00663 * Now we will read the conf.xml file again, but this time we will not validate. 00664 * Instead we just extract the RepositoryList into the database 00665 */ 00666 status = update_repositories(); 00667 if (status != 0) { 00668 printf("Failed to update repositories\n"); 00669 db_disconnect(lock_fd); 00670 StrFree(zone_list_filename); 00671 return(1); 00672 } 00673 00674 /* 00675 * Now read the kasp.xml which should be in the same directory. 00676 * This lists all of the policies. 00677 */ 00678 status = update_policies(kasp_filename); 00679 if (status != 0) { 00680 printf("Failed to update policies\n"); 00681 printf("SETUP FAILED\n"); 00682 db_disconnect(lock_fd); 00683 StrFree(zone_list_filename); 00684 return(1); 00685 } 00686 00687 StrFree(kasp_filename); 00688 00689 /* 00690 * Take the zonelist we learnt above and read it, updating or inserting zone 00691 * records in the database as we go. 00692 */ 00693 status = update_zones(zone_list_filename); 00694 StrFree(zone_list_filename); 00695 if (status != 0) { 00696 printf("Failed to update zones\n"); 00697 db_disconnect(lock_fd); 00698 return(1); 00699 } 00700 00701 /* Release sqlite lock file (if we have it) */ 00702 db_disconnect(lock_fd); 00703 00704 DbDisconnect(dbhandle); 00705 00706 return 0; 00707 } 00708 00709 /* 00710 * Do incremental update of config files into database 00711 * 00712 * returns 0 on success 00713 * 1 on error (and will have sent a message to stdout) 00714 */ 00715 int 00716 cmd_update (const char* qualifier) 00717 { 00718 DB_HANDLE dbhandle; 00719 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 00720 char* zone_list_filename = NULL; /* Extracted from conf.xml */ 00721 char* kasp_filename = NULL; /* Extracted from conf.xml */ 00722 int status = 0; 00723 int done_something = 0; 00724 00725 /* try to connect to the database */ 00726 status = db_connect(&dbhandle, &lock_fd, 1); 00727 if (status != 0) { 00728 printf("Failed to connect to database\n"); 00729 db_disconnect(lock_fd); 00730 return(1); 00731 } 00732 00733 /* 00734 * Now we will read the conf.xml file again, but this time we will not validate. 00735 * Instead we just learn the location of the zonelist.xml and kasp.xml files. 00736 */ 00737 if (strncmp(qualifier, "ZONELIST", 8) == 0 || 00738 strncmp(qualifier, "KASP", 4) == 0 || 00739 strncmp(qualifier, "ALL", 3) == 0) { 00740 status = read_filenames(&zone_list_filename, &kasp_filename); 00741 if (status != 0) { 00742 printf("Failed to read conf.xml\n"); 00743 db_disconnect(lock_fd); 00744 return(1); 00745 } 00746 } 00747 00748 /* 00749 * Read the conf.xml file yet again, but this time we will not validate. 00750 * Instead we just extract the RepositoryList into the database. 00751 */ 00752 if (strncmp(qualifier, "CONF", 4) == 0 || 00753 strncmp(qualifier, "ALL", 3) == 0) { 00754 status = update_repositories(); 00755 if (status != 0) { 00756 printf("Failed to update repositories\n"); 00757 db_disconnect(lock_fd); 00758 if (strncmp(qualifier, "ALL", 3) == 0) { 00759 StrFree(kasp_filename); 00760 StrFree(zone_list_filename); 00761 } 00762 return(1); 00763 } 00764 done_something = 1; 00765 } 00766 00767 /* 00768 * Now read the kasp.xml which should be in the same directory. 00769 * This lists all of the policies. 00770 */ 00771 if (strncmp(qualifier, "KASP", 4) == 0 || 00772 strncmp(qualifier, "ALL", 3) == 0) { 00773 status = update_policies(kasp_filename); 00774 if (status != 0) { 00775 printf("Failed to update policies\n"); 00776 db_disconnect(lock_fd); 00777 StrFree(kasp_filename); 00778 StrFree(zone_list_filename); 00779 return(1); 00780 } 00781 done_something = 1; 00782 } 00783 00784 /* 00785 * Take the zonelist we learnt above and read it, updating or inserting zone 00786 * records in the database as we go. 00787 */ 00788 if (strncmp(qualifier, "ZONELIST", 8) == 0 || 00789 strncmp(qualifier, "ALL", 3) == 0) { 00790 status = update_zones(zone_list_filename); 00791 if (status != 0) { 00792 printf("Failed to update zones\n"); 00793 db_disconnect(lock_fd); 00794 StrFree(kasp_filename); 00795 StrFree(zone_list_filename); 00796 return(1); 00797 } 00798 done_something = 1; 00799 } 00800 00801 /* 00802 * See if we did anything, otherwise log an error 00803 */ 00804 if (done_something == 0) { 00805 printf("Unrecognised command update %s. Please specify one of:\n", qualifier); 00806 usage_update(); 00807 } else { 00808 /* Need to poke the enforcer to wake it up */ 00809 if (restart_enforcerd() != 0) 00810 { 00811 fprintf(stderr, "Could not HUP ods-enforcerd\n"); 00812 } 00813 } 00814 00815 00816 /* Release sqlite lock file (if we have it) */ 00817 db_disconnect(lock_fd); 00818 00819 DbDisconnect(dbhandle); 00820 00821 if (kasp_filename != NULL) { 00822 StrFree(kasp_filename); 00823 } 00824 if (zone_list_filename != NULL) { 00825 StrFree(zone_list_filename); 00826 } 00827 00828 return 0; 00829 } 00830 00831 /* 00832 * Add a zone to the config and database. 00833 * 00834 * Use XMLwriter to update the zonelist.xml found in conf.xml. 00835 * Then call update_zones to push these changes into the database. 00836 * zonelist.xml will be backed up, as will the DB file if we are using sqlite 00837 * 00838 */ 00839 int 00840 cmd_addzone () 00841 { 00842 DB_HANDLE dbhandle; 00843 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 00844 char* zonelist_filename = NULL; 00845 char* backup_filename = NULL; 00846 /* The settings that we need for the zone */ 00847 char* sig_conf_name = NULL; 00848 char* input_name = NULL; 00849 char* output_name = NULL; 00850 int policy_id = 0; 00851 int new_zone; /* ignored */ 00852 00853 DB_RESULT result; /* Result of parameter query */ 00854 KSM_PARAMETER data; /* Parameter information */ 00855 00856 xmlDocPtr doc = NULL; 00857 00858 int status = 0; 00859 00860 char *path = getcwd(NULL, MAXPATHLEN); 00861 if (path == NULL) { 00862 printf("Couldn't malloc path: %s\n", strerror(errno)); 00863 exit(1); 00864 } 00865 00866 /* See what arguments we were passed (if any) otherwise set the defaults */ 00867 if (o_zone == NULL) { 00868 printf("Please specify a zone with the --zone option\n"); 00869 usage_zone(); 00870 return(1); 00871 } 00872 00873 if (o_policy == NULL) { 00874 o_policy = StrStrdup("default"); 00875 } 00876 /* 00877 * Set defaults and turn any relative paths into absolute 00878 * (sort of, not the neatest output) 00879 */ 00880 if (o_signerconf == NULL) { 00881 StrAppend(&sig_conf_name, OPENDNSSEC_STATE_DIR); 00882 StrAppend(&sig_conf_name, "/signconf/"); 00883 StrAppend(&sig_conf_name, o_zone); 00884 StrAppend(&sig_conf_name, ".xml"); 00885 } 00886 else if (*o_signerconf != '/') { 00887 StrAppend(&sig_conf_name, path); 00888 StrAppend(&sig_conf_name, "/"); 00889 StrAppend(&sig_conf_name, o_signerconf); 00890 } else { 00891 StrAppend(&sig_conf_name, o_signerconf); 00892 } 00893 00894 if (o_input == NULL) { 00895 StrAppend(&input_name, OPENDNSSEC_STATE_DIR); 00896 StrAppend(&input_name, "/unsigned/"); 00897 StrAppend(&input_name, o_zone); 00898 } 00899 else if (*o_input != '/') { 00900 StrAppend(&input_name, path); 00901 StrAppend(&input_name, "/"); 00902 StrAppend(&input_name, o_input); 00903 } else { 00904 StrAppend(&input_name, o_input); 00905 } 00906 00907 if (o_output == NULL) { 00908 StrAppend(&output_name, OPENDNSSEC_STATE_DIR); 00909 StrAppend(&output_name, "/signed/"); 00910 StrAppend(&output_name, o_zone); 00911 } 00912 else if (*o_output != '/') { 00913 StrAppend(&output_name, path); 00914 StrAppend(&output_name, "/"); 00915 StrAppend(&output_name, o_output); 00916 } else { 00917 StrAppend(&output_name, o_output); 00918 } 00919 00920 free(path); 00921 00922 /* Set zonelist from the conf.xml that we have got */ 00923 status = read_zonelist_filename(&zonelist_filename); 00924 if (status != 0) { 00925 printf("couldn't read zonelist\n"); 00926 StrFree(zonelist_filename); 00927 StrFree(sig_conf_name); 00928 StrFree(input_name); 00929 StrFree(output_name); 00930 return(1); 00931 } 00932 00933 /* 00934 * Push this new zonelist into the database 00935 */ 00936 00937 /* try to connect to the database */ 00938 status = db_connect(&dbhandle, &lock_fd, 1); 00939 if (status != 0) { 00940 printf("Failed to connect to database\n"); 00941 db_disconnect(lock_fd); 00942 StrFree(zonelist_filename); 00943 StrFree(sig_conf_name); 00944 StrFree(input_name); 00945 StrFree(output_name); 00946 return(1); 00947 } 00948 00949 /* Now stick this zone into the database */ 00950 status = KsmPolicyIdFromName(o_policy, &policy_id); 00951 if (status != 0) { 00952 printf("Error, can't find policy : %s\n", o_policy); 00953 printf("Failed to update zones\n"); 00954 db_disconnect(lock_fd); 00955 StrFree(zonelist_filename); 00956 StrFree(sig_conf_name); 00957 StrFree(input_name); 00958 StrFree(output_name); 00959 return(1); 00960 } 00961 status = KsmImportZone(o_zone, policy_id, 1, &new_zone, sig_conf_name, input_name, output_name); 00962 if (status != 0) { 00963 if (status == -2) { 00964 printf("Failed to Import zone %s; it already exists\n", o_zone); 00965 } else if (status == -3) { 00966 printf("Failed to Import zone %s; it already exists both with and without a trailing dot\n", o_zone); 00967 } else { 00968 printf("Failed to Import zone\n"); 00969 } 00970 db_disconnect(lock_fd); 00971 StrFree(zonelist_filename); 00972 StrFree(sig_conf_name); 00973 StrFree(input_name); 00974 StrFree(output_name); 00975 return(1); 00976 } 00977 00978 /* If need be (keys shared on policy) link existing keys to zone */ 00979 /* First work out if the keys are shared on this policy */ 00980 status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id); 00981 if (status != 0) { 00982 printf("Can't retrieve shared-keys parameter for policy\n"); 00983 db_disconnect(lock_fd); 00984 StrFree(zonelist_filename); 00985 StrFree(sig_conf_name); 00986 StrFree(input_name); 00987 StrFree(output_name); 00988 return(1); 00989 } 00990 status = KsmParameter(result, &data); 00991 if (status != 0) { 00992 printf("Can't retrieve shared-keys parameter for policy\n"); 00993 db_disconnect(lock_fd); 00994 StrFree(zonelist_filename); 00995 StrFree(sig_conf_name); 00996 StrFree(input_name); 00997 StrFree(output_name); 00998 return(1); 00999 } 01000 KsmParameterEnd(result); 01001 01002 /* If the policy does not share keys then skip this */ 01003 if (data.value == 1) { 01004 status = LinkKeys(o_zone, policy_id); 01005 if (status != 0) { 01006 printf("Failed to Link Keys to zone\n"); 01007 /* Carry on and write the xml if the error code was 2 01008 (not enough keys) */ 01009 if (status != 2) { 01010 db_disconnect(lock_fd); 01011 StrFree(zonelist_filename); 01012 StrFree(sig_conf_name); 01013 StrFree(input_name); 01014 StrFree(output_name); 01015 return(1); 01016 } 01017 } 01018 } 01019 01020 /* Release sqlite lock file (if we have it) */ 01021 db_disconnect(lock_fd); 01022 DbDisconnect(dbhandle); 01023 01024 if (xml_flag == 1) { 01025 /* Read the file and add our new node in memory */ 01026 /* TODO don't add if it already exists */ 01027 xmlKeepBlanksDefault(0); 01028 xmlTreeIndentString = "\t"; 01029 doc = add_zone_node(zonelist_filename, o_zone, o_policy, sig_conf_name, input_name, output_name); 01030 01031 StrFree(sig_conf_name); 01032 StrFree(input_name); 01033 StrFree(output_name); 01034 01035 if (doc == NULL) { 01036 StrFree(zonelist_filename); 01037 return(1); 01038 } 01039 01040 /* Backup the current zonelist */ 01041 StrAppend(&backup_filename, zonelist_filename); 01042 StrAppend(&backup_filename, ".backup"); 01043 status = backup_file(zonelist_filename, backup_filename); 01044 StrFree(backup_filename); 01045 if (status != 0) { 01046 StrFree(zonelist_filename); 01047 return(status); 01048 } 01049 01050 /* Save our new one over, TODO should we validate it first? */ 01051 status = xmlSaveFormatFile(zonelist_filename, doc, 1); 01052 StrFree(zonelist_filename); 01053 xmlFreeDoc(doc); 01054 01055 if (status == -1) { 01056 printf("couldn't save zonelist\n"); 01057 return(1); 01058 } 01059 } 01060 01061 /* TODO - KICK THE ENFORCER? */ 01062 /* <matthijs> TODO - ods-signer update? */ 01063 01064 if (xml_flag == 0) { 01065 printf("Imported zone: %s into database only, please run \"ods-ksmutil zonelist export\" to update zonelist.xml\n", o_zone); 01066 } else { 01067 printf("Imported zone: %s\n", o_zone); 01068 } 01069 01070 01071 return 0; 01072 } 01073 01074 /* 01075 * Delete a zone from the config 01076 */ 01077 int 01078 cmd_delzone () 01079 { 01080 01081 char* zonelist_filename = NULL; 01082 char* backup_filename = NULL; 01083 /* The settings that we need for the zone */ 01084 int zone_id = -1; 01085 int policy_id = -1; 01086 int zone_count = -1; 01087 01088 DB_RESULT result; /* Result of parameter query */ 01089 DB_RESULT result2; /* Result of zone count query */ 01090 KSM_PARAMETER shared; /* Parameter information */ 01091 01092 xmlDocPtr doc = NULL; 01093 01094 int status = 0; 01095 int user_certain; /* Continue ? */ 01096 01097 /* Database connection details */ 01098 DB_HANDLE dbhandle; 01099 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 01100 01101 /* We should either have a policy name or --all but not both */ 01102 if (all_flag && o_zone != NULL) { 01103 printf("can not use --all with --zone\n"); 01104 return(1); 01105 } 01106 else if (!all_flag && o_zone == NULL) { 01107 printf("please specify either --zone <zone> or --all\n"); 01108 return(1); 01109 } 01110 01111 /* Warn and confirm if they have asked to delete all zones */ 01112 if (all_flag == 1) { 01113 printf("*WARNING* This will remove all zones from OpenDNSSEC; are you sure? [y/N] "); 01114 01115 user_certain = getchar(); 01116 if (user_certain != 'y' && user_certain != 'Y') { 01117 printf("Okay, quitting...\n"); 01118 exit(0); 01119 } 01120 } 01121 01122 /* try to connect to the database */ 01123 status = db_connect(&dbhandle, &lock_fd, 1); 01124 if (status != 0) { 01125 printf("Failed to connect to database\n"); 01126 db_disconnect(lock_fd); 01127 return(1); 01128 } 01129 01130 /* Put dot back in if we need to; delete zone is the only time we do this */ 01131 if (td_flag == 1) { 01132 StrAppend(&o_zone, "."); 01133 } 01134 /* 01135 * DO XML STUFF FIRST 01136 */ 01137 01138 if (xml_flag == 1) { 01139 /* Set zonelist from the conf.xml that we have got */ 01140 status = read_zonelist_filename(&zonelist_filename); 01141 if (status != 0) { 01142 printf("couldn't read zonelist\n"); 01143 db_disconnect(lock_fd); 01144 StrFree(zonelist_filename); 01145 return(1); 01146 } 01147 01148 /* Read the file and delete our zone node(s) in memory */ 01149 /* N.B. This is deliberately _not_ trailing dot agnostic; the user will have to ask to delete the exact zone */ 01150 doc = del_zone_node(zonelist_filename, o_zone); 01151 if (doc == NULL) { 01152 db_disconnect(lock_fd); 01153 StrFree(zonelist_filename); 01154 return(1); 01155 } 01156 01157 /* rename the Signconf file so that if the zone is readded the old 01158 * file will not be used */ 01159 status = rename_signconf(zonelist_filename, o_zone); 01160 if (status != 0) { 01161 StrFree(zonelist_filename); 01162 db_disconnect(lock_fd); 01163 return(status); 01164 } 01165 01166 /* Backup the current zonelist */ 01167 StrAppend(&backup_filename, zonelist_filename); 01168 StrAppend(&backup_filename, ".backup"); 01169 status = backup_file(zonelist_filename, backup_filename); 01170 StrFree(backup_filename); 01171 if (status != 0) { 01172 StrFree(zonelist_filename); 01173 db_disconnect(lock_fd); 01174 return(status); 01175 } 01176 01177 /* Save our new one over, TODO should we validate it first? */ 01178 status = xmlSaveFormatFile(zonelist_filename, doc, 1); 01179 xmlFreeDoc(doc); 01180 StrFree(zonelist_filename); 01181 if (status == -1) { 01182 printf("Could not save %s\n", zonelist_filename); 01183 db_disconnect(lock_fd); 01184 return(1); 01185 } 01186 } 01187 01188 /* 01189 * NOW SORT OUT THE DATABASE (zone_id will still be -1 if we are deleting all) 01190 */ 01191 01192 /* See if the zone exists and get its ID, assuming we are not deleting all */ 01193 if (all_flag == 0) { 01194 status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id); 01195 if (status != 0) { 01196 printf("Couldn't find zone %s\n", o_zone); 01197 db_disconnect(lock_fd); 01198 return(1); 01199 } 01200 01201 /* Get the shared_keys parameter */ 01202 status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id); 01203 if (status != 0) { 01204 db_disconnect(lock_fd); 01205 return(status); 01206 } 01207 status = KsmParameter(result, &shared); 01208 if (status != 0) { 01209 db_disconnect(lock_fd); 01210 return(status); 01211 } 01212 KsmParameterEnd(result); 01213 01214 /* how many zones on this policy (needed to unlink keys) */ 01215 status = KsmZoneCountInit(&result2, policy_id); 01216 if (status == 0) { 01217 status = KsmZoneCount(result2, &zone_count); 01218 } 01219 DbFreeResult(result2); 01220 } 01221 01222 /* Mark keys as dead if appropriate */ 01223 if (all_flag == 1 || (shared.value == 1 && zone_count == 1) || shared.value == 0) { 01224 status = KsmMarkKeysAsDead(zone_id); 01225 if (status != 0) { 01226 printf("Error: failed to mark keys as dead in database\n"); 01227 db_disconnect(lock_fd); 01228 return(status); 01229 } 01230 } 01231 01232 /* Finally, we can delete the zone (and any dnsseckeys entries) */ 01233 status = KsmDeleteZone(zone_id); 01234 01235 if (status != 0) { 01236 printf("Error: failed to remove zone%s from database\n", (all_flag == 1) ? "s" : ""); 01237 db_disconnect(lock_fd); 01238 return status; 01239 } 01240 01241 /* Call the signer_engine_cli to tell it that the zonelist has changed */ 01242 /* TODO Should we do this when we remove a zone? */ 01243 if (all_flag == 0) { 01244 if (system(SIGNER_CLI_UPDATE) != 0) 01245 { 01246 printf("Could not call signer engine\n"); 01247 } 01248 } 01249 01250 /* Release sqlite lock file (if we have it) */ 01251 db_disconnect(lock_fd); 01252 01253 if (xml_flag == 0) { 01254 printf("Deleted zone: %s from database only, please run \"ods-ksmutil zonelist export\" to update zonelist.xml\n", o_zone); 01255 } 01256 01257 return 0; 01258 } 01259 01260 /* 01261 * List a zone 01262 */ 01263 int 01264 cmd_listzone () 01265 { 01266 01267 DB_HANDLE dbhandle; 01268 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 01269 01270 char* zonelist_filename = NULL; 01271 int* zone_ids; /* List of zone_ids seen from zonelist.xml */ 01272 01273 xmlTextReaderPtr reader = NULL; 01274 int ret = 0; /* status of the XML parsing */ 01275 char* tag_name = NULL; 01276 01277 int file_zone_count = 0; /* As a quick check we will compare the number of */ 01278 int j = 0; /* Another counter */ 01279 char buffer[256]; /* For constructing part of the command */ 01280 char* sql = NULL; /* SQL "IN" query */ 01281 DB_RESULT result; /* Result of the query */ 01282 DB_ROW row = NULL; /* Row data */ 01283 char* temp_name = NULL; 01284 01285 int status = 0; 01286 01287 /* Set zonelist from the conf.xml that we have got */ 01288 status = read_zonelist_filename(&zonelist_filename); 01289 if (status != 0) { 01290 printf("couldn't read zonelist\n"); 01291 if (zonelist_filename != NULL) { 01292 StrFree(zonelist_filename); 01293 } 01294 return(1); 01295 } 01296 01297 /* try to connect to the database */ 01298 status = db_connect(&dbhandle, &lock_fd, 1); 01299 if (status != 0) { 01300 printf("Failed to connect to database\n"); 01301 db_disconnect(lock_fd); 01302 return(1); 01303 } 01304 01305 /* Read through the file counting zones TODO better way to do this? */ 01306 reader = xmlNewTextReaderFilename(zonelist_filename); 01307 if (reader != NULL) { 01308 ret = xmlTextReaderRead(reader); 01309 while (ret == 1) { 01310 tag_name = (char*) xmlTextReaderLocalName(reader); 01311 /* Found <Zone> */ 01312 if (strncmp(tag_name, "Zone", 4) == 0 01313 && strncmp(tag_name, "ZoneList", 8) != 0 01314 && xmlTextReaderNodeType(reader) == 1) { 01315 file_zone_count++; 01316 } 01317 /* Read the next line */ 01318 ret = xmlTextReaderRead(reader); 01319 StrFree(tag_name); 01320 } 01321 xmlFreeTextReader(reader); 01322 if (ret != 0) { 01323 printf("%s : failed to parse\n", zonelist_filename); 01324 } 01325 } else { 01326 printf("Unable to open %s\n", zonelist_filename); 01327 } 01328 01329 /* Allocate space for the list of zone IDs */ 01330 zone_ids = MemMalloc(file_zone_count * sizeof(int)); 01331 01332 /* Read the file and list the zones as we go */ 01333 list_zone_node(zonelist_filename, zone_ids); 01334 01335 /* Now see if there are any zones in the DB which are not in the file */ 01336 if (file_zone_count != 0) { 01337 StrAppend(&sql, "select name from zones where id not in ("); 01338 for (j = 0; j < file_zone_count; ++j) { 01339 if (j != 0) { 01340 StrAppend(&sql, ","); 01341 } 01342 snprintf(buffer, sizeof(buffer), "%d", zone_ids[j]); 01343 StrAppend(&sql, buffer); 01344 } 01345 StrAppend(&sql, ")"); 01346 } else { 01347 StrAppend(&sql, "select name from zones"); 01348 } 01349 01350 status = DbExecuteSql(DbHandle(), sql, &result); 01351 if (status == 0) { 01352 status = DbFetchRow(result, &row); 01353 while (status == 0) { 01354 /* Got a row, print it */ 01355 DbString(row, 0, &temp_name); 01356 01357 printf("Found zone %s in DB but not zonelist.\n", temp_name); 01358 status = DbFetchRow(result, &row); 01359 file_zone_count++; 01360 } 01361 01362 /* Convert EOF status to success */ 01363 01364 if (status == -1) { 01365 status = 0; 01366 } 01367 01368 DbFreeResult(result); 01369 } 01370 01371 db_disconnect(lock_fd); 01372 DbDisconnect(dbhandle); 01373 01374 if (file_zone_count == 0) { 01375 printf("No zones in DB or zonelist.\n"); 01376 } 01377 01378 MemFree(zone_ids); 01379 StrFree(sql); 01380 StrFree(zonelist_filename); 01381 StrFree(temp_name); 01382 01383 return 0; 01384 } 01385 01386 /* 01387 * To export: 01388 * keys|ds for zone 01389 */ 01390 int 01391 cmd_exportkeys () 01392 { 01393 int status = 0; 01394 /* Database connection details */ 01395 DB_HANDLE dbhandle; 01396 01397 int zone_id = -1; 01398 int state_id = -1; 01399 int keytype_id = KSM_TYPE_KSK; 01400 01401 char *case_keytype = NULL; 01402 char *case_keystate = NULL; 01403 char *zone_name = NULL; 01404 01405 /* Key information */ 01406 hsm_key_t *key = NULL; 01407 ldns_rr *dnskey_rr = NULL; 01408 ldns_rr *ds_sha1_rr = NULL; 01409 ldns_rr *ds_sha256_rr = NULL; 01410 hsm_sign_params_t *sign_params = NULL; 01411 01412 char* sql = NULL; 01413 KSM_KEYDATA data; /* Data for each key */ 01414 DB_RESULT result; /* Result set from query */ 01415 size_t nchar; /* Number of characters written */ 01416 char buffer[256]; /* For constructing part of the command */ 01417 01418 int done_something = 0; /* Have we exported any keys? */ 01419 01420 /* See what arguments we were passed (if any) otherwise set the defaults */ 01421 /* Check keystate, can be state or keytype */ 01422 if (o_keystate != NULL) { 01423 case_keystate = StrStrdup(o_keystate); 01424 (void) StrToUpper(case_keystate); 01425 if (strncmp(case_keystate, "KEYPUBLISH", 10) == 0 || strncmp(o_keystate, "10", 2) == 0) { 01426 state_id = KSM_STATE_KEYPUBLISH; 01427 } 01428 else if (strncmp(case_keystate, "GENERATE", 8) == 0 || strncmp(o_keystate, "1", 1) == 0) { 01429 state_id = KSM_STATE_GENERATE; 01430 } 01431 else if (strncmp(case_keystate, "PUBLISH", 7) == 0 || strncmp(o_keystate, "2", 1) == 0) { 01432 state_id = KSM_STATE_PUBLISH; 01433 } 01434 else if (strncmp(case_keystate, "READY", 5) == 0 || strncmp(o_keystate, "3", 1) == 0) { 01435 state_id = KSM_STATE_READY; 01436 } 01437 else if (strncmp(case_keystate, "ACTIVE", 6) == 0 || strncmp(o_keystate, "4", 1) == 0) { 01438 state_id = KSM_STATE_ACTIVE; 01439 } 01440 else if (strncmp(case_keystate, "RETIRE", 6) == 0 || strncmp(o_keystate, "5", 1) == 0) { 01441 state_id = KSM_STATE_RETIRE; 01442 } 01443 else if (strncmp(case_keystate, "DEAD", 4) == 0 || strncmp(o_keystate, "6", 1) == 0) { 01444 state_id = KSM_STATE_DEAD; 01445 } 01446 else if (strncmp(case_keystate, "DSSUB", 5) == 0 || strncmp(o_keystate, "7", 1) == 0) { 01447 state_id = KSM_STATE_DSSUB; 01448 } 01449 else if (strncmp(case_keystate, "DSPUBLISH", 9) == 0 || strncmp(o_keystate, "8", 1) == 0) { 01450 state_id = KSM_STATE_DSPUBLISH; 01451 } 01452 else if (strncmp(case_keystate, "DSREADY", 7) == 0 || strncmp(o_keystate, "9", 1) == 0) { 01453 state_id = KSM_STATE_DSREADY; 01454 } 01455 else { 01456 printf("Error: Unrecognised state %s; should be one of GENERATE, PUBLISH, READY, ACTIVE, RETIRE, DEAD, DSSUB, DSPUBLISH, DSREADY or KEYPUBLISH\n", o_keystate); 01457 01458 StrFree(case_keystate); 01459 return(1); 01460 } 01461 StrFree(case_keystate); 01462 } 01463 01464 /* Check keytype */ 01465 if (o_keytype != NULL) { 01466 case_keytype = StrStrdup(o_keytype); 01467 (void) StrToUpper(case_keytype); 01468 if (strncmp(case_keytype, "KSK", 3) == 0 || strncmp(o_keytype, "257", 3) == 0) { 01469 keytype_id = KSM_TYPE_KSK; 01470 } 01471 else if (strncmp(case_keytype, "ZSK", 3) == 0 || strncmp(o_keytype, "256", 3) == 0) { 01472 keytype_id = KSM_TYPE_ZSK; 01473 } 01474 else { 01475 printf("Error: Unrecognised keytype %s; should be one of KSK or ZSK\n", o_keytype); 01476 01477 StrFree(case_keytype); 01478 return(1); 01479 } 01480 StrFree(case_keytype); 01481 } 01482 01483 /* try to connect to the database */ 01484 status = db_connect(&dbhandle, NULL, 0); 01485 if (status != 0) { 01486 printf("Failed to connect to database\n"); 01487 return(1); 01488 } 01489 01490 /* check that the zone name is valid and use it to get some ids */ 01491 if (o_zone != NULL) { 01492 status = KsmZoneIdFromName(o_zone, &zone_id); 01493 if (status != 0) { 01494 /* Try again with td */ 01495 StrAppend(&o_zone, "."); 01496 status = KsmZoneIdFromName(o_zone, &zone_id); 01497 if (status != 0) { 01498 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 01499 return(status); 01500 } 01501 } 01502 } 01503 01504 status = hsm_open(config, hsm_prompt_pin, NULL); 01505 if (status) { 01506 hsm_print_error(NULL); 01507 exit(-1); 01508 } 01509 01510 sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS); 01511 if (state_id != -1) { 01512 DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, state_id, 0); 01513 } else { 01514 nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d, %d, %d)", 01515 KSM_STATE_READY, KSM_STATE_ACTIVE, KSM_STATE_DSSUB, 01516 KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY, KSM_STATE_KEYPUBLISH); 01517 if (nchar >= sizeof(buffer)) { 01518 status = -1; 01519 return status; 01520 } 01521 DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, 0); 01522 01523 } 01524 DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype_id, 1); 01525 if (zone_id != -1) { 01526 DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 2); 01527 } 01528 DqsOrderBy(&sql, "STATE"); 01529 DqsEnd(&sql); 01530 01531 status = KsmKeyInitSql(&result, sql); 01532 if (status == 0) { 01533 status = KsmKey(result, &data); 01534 while (status == 0) { 01535 01536 /* Code to output the DNSKEY record (stolen from hsmutil) */ 01537 key = hsm_find_key_by_id(NULL, data.location); 01538 01539 if (!key) { 01540 printf("Key %s in DB but not repository\n", data.location); 01541 return -1; 01542 } 01543 01544 sign_params = hsm_sign_params_new(); 01545 /* If zone_id == -1 then we need to work out the zone name from data.zone_id */ 01546 if (zone_id == -1) { 01547 status = KsmZoneNameFromId(data.zone_id, &zone_name); 01548 if (status != 0) { 01549 printf("Error: unable to find zone name for id %d\n", zone_id); 01550 hsm_sign_params_free(sign_params); 01551 return(status); 01552 } 01553 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone_name); 01554 StrFree(zone_name); 01555 } 01556 else { 01557 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, o_zone); 01558 } 01559 01560 sign_params->algorithm = data.algorithm; 01561 sign_params->flags = LDNS_KEY_ZONE_KEY; 01562 if (keytype_id == KSM_TYPE_KSK) { 01563 sign_params->flags += LDNS_KEY_SEP_KEY; 01564 } 01565 dnskey_rr = hsm_get_dnskey(NULL, key, sign_params); 01566 sign_params->keytag = ldns_calc_keytag(dnskey_rr); 01567 01568 if (ds_flag == 0) { 01569 printf("\n;%s %s DNSKEY record:\n", KsmKeywordStateValueToName(data.state), (keytype_id == KSM_TYPE_KSK ? "KSK" : "ZSK")); 01570 ldns_rr_print(stdout, dnskey_rr); 01571 } 01572 else { 01573 01574 printf("\n;%s %s DS record (SHA1):\n", KsmKeywordStateValueToName(data.state), (keytype_id == KSM_TYPE_KSK ? "KSK" : "ZSK")); 01575 ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1); 01576 ldns_rr_print(stdout, ds_sha1_rr); 01577 01578 printf("\n;%s %s DS record (SHA256):\n", KsmKeywordStateValueToName(data.state), (keytype_id == KSM_TYPE_KSK ? "KSK" : "ZSK")); 01579 ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256); 01580 ldns_rr_print(stdout, ds_sha256_rr); 01581 } 01582 01583 done_something = 1; 01584 01585 hsm_sign_params_free(sign_params); 01586 hsm_key_free(key); 01587 status = KsmKey(result, &data); 01588 01589 } 01590 /* Convert EOF status to success */ 01591 if (status == -1) { 01592 status = 0; 01593 } 01594 01595 KsmKeyEnd(result); 01596 } 01597 01598 /* If we did nothing then explain why not */ 01599 if (!done_something) { 01600 if (state_id != -1) { 01601 printf("No keys in %s state to export.\n", KsmKeywordStateValueToName(state_id) ); 01602 } else { 01603 printf("No keys in READY state or higher to export.\n"); 01604 } 01605 } 01606 01607 /* TODO when the above is working then replicate it twice for the case where keytype == -1 */ 01608 01609 if (dnskey_rr != NULL) { 01610 ldns_rr_free(dnskey_rr); 01611 } 01612 if (ds_sha1_rr != NULL) { 01613 ldns_rr_free(ds_sha1_rr); 01614 } 01615 if (ds_sha256_rr != NULL) { 01616 ldns_rr_free(ds_sha256_rr); 01617 } 01618 01619 DbDisconnect(dbhandle); 01620 01621 return 0; 01622 } 01623 01624 /* 01625 * To export: 01626 * policies (all, unless one is named) to xml 01627 */ 01628 int 01629 cmd_exportpolicy () 01630 { 01631 int status = 0; 01632 /* Database connection details */ 01633 DB_HANDLE dbhandle; 01634 01635 xmlDocPtr doc = xmlNewDoc((const xmlChar *)"1.0"); 01636 xmlNodePtr root; 01637 KSM_POLICY *policy; 01638 01639 DB_RESULT result; /* Result set from query */ 01640 01641 /* We should either have a policy name or --all but not both */ 01642 if (all_flag && o_policy != NULL) { 01643 printf("can not use --all with --policy\n"); 01644 return(1); 01645 } 01646 else if (!all_flag && o_policy == NULL) { 01647 printf("please specify either --policy <policy> or --all\n"); 01648 return(1); 01649 } 01650 01651 /* try to connect to the database */ 01652 status = db_connect(&dbhandle, NULL, 0); 01653 if (status != 0) { 01654 printf("Failed to connect to database\n"); 01655 return(1); 01656 } 01657 01658 /* Make some space for the policy */ 01659 policy = (KSM_POLICY *)malloc(sizeof(KSM_POLICY)); 01660 policy->signer = (KSM_SIGNER_POLICY *)malloc(sizeof(KSM_SIGNER_POLICY)); 01661 policy->signature = (KSM_SIGNATURE_POLICY *)malloc(sizeof(KSM_SIGNATURE_POLICY)); 01662 policy->zone = (KSM_ZONE_POLICY *)malloc(sizeof(KSM_ZONE_POLICY)); 01663 policy->parent = (KSM_PARENT_POLICY *)malloc(sizeof(KSM_PARENT_POLICY)); 01664 policy->keys = (KSM_COMMON_KEY_POLICY *)malloc(sizeof(KSM_COMMON_KEY_POLICY)); 01665 policy->ksk = (KSM_KEY_POLICY *)malloc(sizeof(KSM_KEY_POLICY)); 01666 policy->zsk = (KSM_KEY_POLICY *)malloc(sizeof(KSM_KEY_POLICY)); 01667 policy->denial = (KSM_DENIAL_POLICY *)malloc(sizeof(KSM_DENIAL_POLICY)); 01668 policy->enforcer = (KSM_ENFORCER_POLICY *)malloc(sizeof(KSM_ENFORCER_POLICY)); 01669 /* policy->audit = (KSM_AUDIT_POLICY *)malloc(sizeof(KSM_AUDIT_POLICY)); */ 01670 policy->audit = (char *)calloc(KSM_POLICY_AUDIT_LENGTH, sizeof(char)); 01671 policy->description = (char *)calloc(KSM_POLICY_DESC_LENGTH, sizeof(char)); 01672 if (policy->signer == NULL || policy->signature == NULL || 01673 policy->zone == NULL || policy->parent == NULL || 01674 policy->keys == NULL || 01675 policy->ksk == NULL || policy->zsk == NULL || 01676 policy->denial == NULL || policy->enforcer == NULL) { 01677 fprintf(stderr, "Malloc for policy struct failed\n"); 01678 exit(1); 01679 } 01680 01681 /* Setup doc with a root node of <KASP> */ 01682 xmlKeepBlanksDefault(0); 01683 xmlTreeIndentString = " "; 01684 root = xmlNewDocNode(doc, NULL, (const xmlChar *)"KASP", NULL); 01685 (void) xmlDocSetRootElement(doc, root); 01686 01687 /* Read policies (all if policy_name == NULL; else named policy only) */ 01688 status = KsmPolicyInit(&result, o_policy); 01689 if (status == 0) { 01690 /* get the first policy */ 01691 status = KsmPolicy(result, policy); 01692 KsmPolicyRead(policy); 01693 01694 while (status == 0) { 01695 append_policy(doc, policy); 01696 01697 /* get next policy */ 01698 status = KsmPolicy(result, policy); 01699 KsmPolicyRead(policy); 01700 01701 } 01702 } 01703 01704 xmlSaveFormatFile("-", doc, 1); 01705 01706 xmlFreeDoc(doc); 01707 KsmPolicyFree(policy); 01708 01709 DbDisconnect(dbhandle); 01710 01711 return 0; 01712 } 01713 01714 /* 01715 * To export: 01716 * zonelist to xml 01717 */ 01718 int 01719 cmd_exportzonelist () 01720 { 01721 int status = 0; 01722 /* Database connection details */ 01723 DB_HANDLE dbhandle; 01724 01725 xmlDocPtr doc = xmlNewDoc((const xmlChar *)"1.0"); 01726 xmlNodePtr root; 01727 KSM_ZONE *zone; 01728 int prev_policy_id = -1; 01729 01730 DB_RESULT result; /* Result set from query */ 01731 01732 /* try to connect to the database */ 01733 status = db_connect(&dbhandle, NULL, 0); 01734 if (status != 0) { 01735 printf("Failed to connect to database\n"); 01736 return(1); 01737 } 01738 01739 /* Make some space for the zone */ 01740 zone = (KSM_ZONE *)malloc(sizeof(KSM_ZONE)); 01741 if (zone == NULL) { 01742 fprintf(stderr, "Malloc for zone struct failed\n"); 01743 exit(1); 01744 } 01745 01746 /* Setup doc with a root node of <ZoneList> */ 01747 xmlKeepBlanksDefault(0); 01748 xmlTreeIndentString = " "; 01749 root = xmlNewDocNode(doc, NULL, (const xmlChar *)"ZoneList", NULL); 01750 (void) xmlDocSetRootElement(doc, root); 01751 01752 /* Read zones */ 01753 status = KsmZoneInit(&result, -1); 01754 if (status == 0) { 01755 /* get the first zone */ 01756 status = KsmZone(result, zone); 01757 01758 while (status == 0) { 01759 if (zone->policy_id != prev_policy_id) { 01760 prev_policy_id = zone->policy_id; 01761 status = get_policy_name_from_id(zone); 01762 if (status != 0) { 01763 fprintf(stderr, "Couldn't get name for policy with ID: %d, exiting...\n", zone->policy_id); 01764 return(1); 01765 } 01766 } 01767 append_zone(doc, zone); 01768 01769 /* get next zone */ 01770 status = KsmZone(result, zone); 01771 01772 } 01773 } 01774 01775 xmlSaveFormatFile("-", doc, 1); 01776 01777 xmlFreeDoc(doc); 01778 /*KsmZoneFree(zone);*/ 01779 01780 DbDisconnect(dbhandle); 01781 01782 return 0; 01783 } 01784 01785 /* 01786 * To rollover a zone (or all zones on a policy if keys are shared) 01787 */ 01788 int 01789 cmd_rollzone () 01790 { 01791 /* Database connection details */ 01792 DB_HANDLE dbhandle; 01793 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 01794 DB_RESULT result; /* Result of parameter query */ 01795 KSM_PARAMETER data; /* Parameter information */ 01796 01797 int key_type = -1; 01798 int zone_id = -1; 01799 int policy_id = -1; 01800 01801 int status = 0; 01802 int user_certain; 01803 01804 /* If we were given a keytype, turn it into a number */ 01805 if (o_keytype != NULL) { 01806 StrToLower(o_keytype); 01807 key_type = KsmKeywordTypeNameToValue(o_keytype); 01808 } 01809 01810 /* try to connect to the database */ 01811 status = db_connect(&dbhandle, &lock_fd, 1); 01812 if (status != 0) { 01813 printf("Failed to connect to database\n"); 01814 db_disconnect(lock_fd); 01815 return(1); 01816 } 01817 01818 status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id); 01819 if (status != 0) { 01820 /* Try again with td */ 01821 StrAppend(&o_zone, "."); 01822 status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id); 01823 if (status != 0) { 01824 db_disconnect(lock_fd); 01825 return(status); 01826 } 01827 } 01828 01829 /* Get the shared_keys parameter */ 01830 status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id); 01831 if (status != 0) { 01832 db_disconnect(lock_fd); 01833 return(status); 01834 } 01835 status = KsmParameter(result, &data); 01836 if (status != 0) { 01837 db_disconnect(lock_fd); 01838 return(status); 01839 } 01840 KsmParameterEnd(result); 01841 01842 /* Warn and confirm if this will roll more than one zone */ 01843 if (data.value == 1) { 01844 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] "); 01845 01846 user_certain = getchar(); 01847 if (user_certain != 'y' && user_certain != 'Y') { 01848 printf("Okay, quitting...\n"); 01849 db_disconnect(lock_fd); 01850 exit(0); 01851 } 01852 } 01853 01854 status = keyRoll(zone_id, -1, key_type); 01855 if (status != 0) { 01856 db_disconnect(lock_fd); 01857 return(status); 01858 } 01859 01860 /* Release sqlite lock file (if we have it) */ 01861 db_disconnect(lock_fd); 01862 01863 /* Need to poke the enforcer to wake it up */ 01864 if (restart_enforcerd() != 0) 01865 { 01866 fprintf(stderr, "Could not HUP ods-enforcerd\n"); 01867 } 01868 01869 DbDisconnect(dbhandle); 01870 01871 return 0; 01872 } 01873 01874 /* 01875 * To rollover all zones on a policy 01876 */ 01877 int 01878 cmd_rollpolicy () 01879 { 01880 /* Database connection details */ 01881 DB_HANDLE dbhandle; 01882 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 01883 01884 DB_RESULT result; /* To see if the policy shares keys or not */ 01885 01886 int zone_count = -1; 01887 01888 int key_type = 0; 01889 int policy_id = 0; 01890 01891 int status = 0; 01892 int user_certain; 01893 01894 /* If we were given a keytype, turn it into a number */ 01895 if (o_keytype != NULL) { 01896 StrToLower(o_keytype); 01897 key_type = KsmKeywordTypeNameToValue(o_keytype); 01898 } 01899 01900 /* try to connect to the database */ 01901 status = db_connect(&dbhandle, &lock_fd, 1); 01902 if (status != 0) { 01903 printf("Failed to connect to database\n"); 01904 db_disconnect(lock_fd); 01905 return(1); 01906 } 01907 01908 status = KsmPolicyIdFromName(o_policy, &policy_id); 01909 if (status != 0) { 01910 printf("Error, can't find policy : %s\n", o_policy); 01911 db_disconnect(lock_fd); 01912 return(status); 01913 } 01914 01915 /* Warn and confirm */ 01916 printf("*WARNING* This will roll all keys on the policy; are you sure? [y/N] "); 01917 01918 user_certain = getchar(); 01919 if (user_certain != 'y' && user_certain != 'Y') { 01920 printf("Okay, quitting...\n"); 01921 db_disconnect(lock_fd); 01922 exit(0); 01923 } 01924 01925 /* Find out how many zones we will need to do */ 01926 /* how many zones on this policy */ 01927 status = KsmZoneCountInit(&result, policy_id); 01928 if (status == 0) { 01929 status = KsmZoneCount(result, &zone_count); 01930 } 01931 DbFreeResult(result); 01932 01933 if (status == 0) { 01934 /* make sure that we have at least one zone */ 01935 if (zone_count == 0) { 01936 printf("No zones on policy; nothing to roll\n"); 01937 db_disconnect(lock_fd); 01938 return status; 01939 } 01940 } else { 01941 printf("Couldn't count zones on policy; quitting...\n"); 01942 db_disconnect(lock_fd); 01943 exit(1); 01944 } 01945 01946 status = keyRoll(-1, policy_id, key_type); 01947 01948 /* Release sqlite lock file (if we have it) */ 01949 db_disconnect(lock_fd); 01950 01951 /* Need to poke the enforcer to wake it up */ 01952 if (restart_enforcerd() != 0) 01953 { 01954 fprintf(stderr, "Could not HUP ods-enforcerd\n"); 01955 } 01956 01957 DbDisconnect(dbhandle); 01958 01959 return 0; 01960 } 01961 01962 /* 01963 * purge dead keys from the database 01964 */ 01965 int 01966 cmd_keypurge () 01967 { 01968 int status = 0; 01969 01970 int policy_id = -1; 01971 int zone_id = -1; 01972 01973 /* Database connection details */ 01974 DB_HANDLE dbhandle; 01975 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 01976 01977 /* try to connect to the database */ 01978 status = db_connect(&dbhandle, &lock_fd, 1); 01979 if (status != 0) { 01980 printf("Failed to connect to database\n"); 01981 db_disconnect(lock_fd); 01982 return(1); 01983 } 01984 01985 /* Turn policy name into an id (if provided) */ 01986 if (o_policy != NULL) { 01987 status = KsmPolicyIdFromName(o_policy, &policy_id); 01988 if (status != 0) { 01989 printf("Error: unable to find a policy named \"%s\" in database\n", o_policy); 01990 db_disconnect(lock_fd); 01991 return status; 01992 } 01993 } 01994 01995 /* Turn zone name into an id (if provided) */ 01996 if (o_zone != NULL) { 01997 status = KsmZoneIdFromName(o_zone, &zone_id); 01998 if (status != 0) { 01999 /* Try again with td */ 02000 StrAppend(&o_zone, "."); 02001 status = KsmZoneIdFromName(o_zone, &zone_id); 02002 if (status != 0) { 02003 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 02004 db_disconnect(lock_fd); 02005 return(status); 02006 } 02007 } 02008 } 02009 02010 status = PurgeKeys(zone_id, policy_id); 02011 02012 if (status != 0) { 02013 printf("Error: failed to purge dead keys\n"); 02014 db_disconnect(lock_fd); 02015 return status; 02016 } 02017 02018 /* Release sqlite lock file (if we have it) */ 02019 db_disconnect(lock_fd); 02020 02021 DbDisconnect(dbhandle); 02022 return 0; 02023 } 02024 02025 /* 02026 * note that fact that a backup has been performed 02027 */ 02028 int 02029 cmd_backup (const char* qualifier) 02030 { 02031 int status = 0; 02032 02033 int repo_id = -1; 02034 02035 /* Database connection details */ 02036 DB_HANDLE dbhandle; 02037 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02038 02039 char* datetime = DtParseDateTimeString("now"); 02040 02041 /* Check datetime in case it came back NULL */ 02042 if (datetime == NULL) { 02043 printf("Couldn't turn \"now\" into a date, quitting...\n"); 02044 exit(1); 02045 } 02046 02047 /* try to connect to the database */ 02048 status = db_connect(&dbhandle, &lock_fd, 1); 02049 if (status != 0) { 02050 printf("Failed to connect to database\n"); 02051 db_disconnect(lock_fd); 02052 StrFree(datetime); 02053 return(1); 02054 } 02055 02056 /* Turn repo name into an id (if provided) */ 02057 if (o_repository != NULL) { 02058 status = KsmSmIdFromName(o_repository, &repo_id); 02059 if (status != 0) { 02060 printf("Error: unable to find a repository named \"%s\" in database\n", o_repository); 02061 db_disconnect(lock_fd); 02062 StrFree(datetime); 02063 return status; 02064 } 02065 } 02066 02067 /* Do Pre first */ 02068 if (strncmp(qualifier, "PREPARE", 7) == 0 || 02069 strncmp(qualifier, "DONE", 4) == 0 ) { 02070 status = KsmMarkPreBackup(repo_id, datetime); 02071 if (status == -1) { 02072 printf("There were no keys to mark\n"); 02073 } 02074 else if (status != 0) { 02075 printf("Error: failed to mark pre_backup as done\n"); 02076 db_disconnect(lock_fd); 02077 StrFree(datetime); 02078 return status; 02079 } else { 02080 if (strncmp(qualifier, "PREPARE", 7) == 0) { 02081 if (o_repository != NULL) { 02082 printf("Marked repository %s as pre-backed up at %s\n", o_repository, datetime); 02083 } else { 02084 printf("Marked all repositories as pre-backed up at %s\n", datetime); 02085 } 02086 } 02087 } 02088 } 02089 02090 /* Then commit */ 02091 if (strncmp(qualifier, "COMMIT", 6) == 0 || 02092 strncmp(qualifier, "DONE", 4) == 0 ) { 02093 status = KsmMarkBackup(repo_id, datetime); 02094 if (status == -1) { 02095 printf("There were no keys to mark\n"); 02096 } 02097 else if (status != 0) { 02098 printf("Error: failed to mark backup as done\n"); 02099 db_disconnect(lock_fd); 02100 StrFree(datetime); 02101 return status; 02102 } else { 02103 if (o_repository != NULL) { 02104 printf("Marked repository %s as backed up at %s\n", o_repository, datetime); 02105 } else { 02106 printf("Marked all repositories as backed up at %s\n", datetime); 02107 } 02108 } 02109 } 02110 02111 /* Finally rollback */ 02112 if (strncmp(qualifier, "ROLLBACK", 6) == 0 ) { 02113 status = KsmRollbackMarkPreBackup(repo_id); 02114 if (status == -1) { 02115 printf("There were no keys to rollback\n"); 02116 } 02117 else if (status != 0) { 02118 printf("Error: failed to mark backup as done\n"); 02119 db_disconnect(lock_fd); 02120 StrFree(datetime); 02121 return status; 02122 } else { 02123 if (o_repository != NULL) { 02124 printf("Rolled back pre-backup of repository %s\n", o_repository); 02125 } else { 02126 printf("Rolled back pre-backup of all repositories\n"); 02127 } 02128 } 02129 } 02130 02131 StrFree(datetime); 02132 /* Release sqlite lock file (if we have it) */ 02133 db_disconnect(lock_fd); 02134 02135 DbDisconnect(dbhandle); 02136 return 0; 02137 } 02138 02139 /* 02140 * List rollovers 02141 */ 02142 int 02143 cmd_listrolls () 02144 { 02145 int status = 0; 02146 02147 int qualifier_id = -1; /* ID of qualifer (if given) */ 02148 02149 /* Database connection details */ 02150 DB_HANDLE dbhandle; 02151 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02152 02153 /* try to connect to the database */ 02154 status = db_connect(&dbhandle, &lock_fd, 1); 02155 if (status != 0) { 02156 printf("Failed to connect to database\n"); 02157 db_disconnect(lock_fd); 02158 return(1); 02159 } 02160 02161 /* Turn zone name into an id (if provided) */ 02162 if (o_zone != NULL) { 02163 status = KsmZoneIdFromName(o_zone, &qualifier_id); 02164 if (status != 0) { 02165 /* Try again with td */ 02166 StrAppend(&o_zone, "."); 02167 status = KsmZoneIdFromName(o_zone, &qualifier_id); 02168 if (status != 0) { 02169 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 02170 db_disconnect(lock_fd); 02171 return(status); 02172 } 02173 } 02174 } 02175 02176 printf("Rollovers:\n"); 02177 02178 status = KsmListRollovers(qualifier_id); 02179 02180 if (status != 0) { 02181 printf("Error: failed to list rollovers\n"); 02182 db_disconnect(lock_fd); 02183 return status; 02184 } 02185 02186 printf("\n"); 02187 02188 /* Release sqlite lock file (if we have it) */ 02189 db_disconnect(lock_fd); 02190 02191 DbDisconnect(dbhandle); 02192 return 0; 02193 } 02194 02195 /* 02196 * List backups 02197 */ 02198 int 02199 cmd_listbackups () 02200 { 02201 int status = 0; 02202 02203 int qualifier_id = -1; /* ID of qualifer (if given) */ 02204 02205 /* Database connection details */ 02206 DB_HANDLE dbhandle; 02207 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02208 02209 /* try to connect to the database */ 02210 status = db_connect(&dbhandle, &lock_fd, 0); 02211 if (status != 0) { 02212 printf("Failed to connect to database\n"); 02213 db_disconnect(lock_fd); 02214 return(1); 02215 } 02216 02217 /* Turn repo name into an id (if provided) */ 02218 if (o_repository != NULL) { 02219 status = KsmSmIdFromName(o_repository, &qualifier_id); 02220 if (status != 0) { 02221 printf("Error: unable to find a repository named \"%s\" in database\n", o_repository); 02222 db_disconnect(lock_fd); 02223 return status; 02224 } 02225 } 02226 02227 printf("Backups:\n"); 02228 status = KsmListBackups(qualifier_id, verbose_flag); 02229 02230 if (status != 0) { 02231 printf("Error: failed to list backups\n"); 02232 db_disconnect(lock_fd); 02233 return status; 02234 } 02235 printf("\n"); 02236 02237 /* Release sqlite lock file (if we have it) */ 02238 db_disconnect(lock_fd); 02239 02240 DbDisconnect(dbhandle); 02241 return 0; 02242 } 02243 02244 /* 02245 * List repos 02246 */ 02247 int 02248 cmd_listrepo () 02249 { 02250 int status = 0; 02251 02252 /* Database connection details */ 02253 DB_HANDLE dbhandle; 02254 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02255 02256 /* try to connect to the database */ 02257 status = db_connect(&dbhandle, &lock_fd, 0); 02258 if (status != 0) { 02259 printf("Failed to connect to database\n"); 02260 db_disconnect(lock_fd); 02261 return(1); 02262 } 02263 02264 printf("Repositories:\n"); 02265 02266 status = KsmListRepos(); 02267 02268 if (status != 0) { 02269 printf("Error: failed to list repositories\n"); 02270 if (lock_fd != NULL) { 02271 fclose(lock_fd); 02272 } 02273 return status; 02274 } 02275 02276 printf("\n"); 02277 02278 /* Release sqlite lock file (if we have it) */ 02279 db_disconnect(lock_fd); 02280 02281 DbDisconnect(dbhandle); 02282 return 0; 02283 } 02284 02285 /* 02286 * List policy 02287 */ 02288 int 02289 cmd_listpolicy () 02290 { 02291 int status = 0; 02292 02293 /* Database connection details */ 02294 DB_HANDLE dbhandle; 02295 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02296 02297 /* try to connect to the database */ 02298 status = db_connect(&dbhandle, &lock_fd, 0); 02299 if (status != 0) { 02300 printf("Failed to connect to database\n"); 02301 db_disconnect(lock_fd); 02302 return(1); 02303 } 02304 02305 printf("Policies:\n"); 02306 02307 status = KsmListPolicies(); 02308 02309 if (status != 0) { 02310 printf("Error: failed to list policies\n"); 02311 db_disconnect(lock_fd); 02312 return status; 02313 } 02314 02315 printf("\n"); 02316 02317 /* Release sqlite lock file (if we have it) */ 02318 db_disconnect(lock_fd); 02319 02320 DbDisconnect(dbhandle); 02321 return 0; 02322 } 02323 02324 /* 02325 * List keys 02326 */ 02327 int 02328 cmd_listkeys () 02329 { 02330 int status = 0; 02331 int qualifier_id = -1; 02332 02333 /* Database connection details */ 02334 DB_HANDLE dbhandle; 02335 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02336 02337 /* try to connect to the database */ 02338 status = db_connect(&dbhandle, &lock_fd, 0); 02339 if (status != 0) { 02340 printf("Failed to connect to database\n"); 02341 db_disconnect(lock_fd); 02342 return(1); 02343 } 02344 02345 /* Turn zone name into an id (if provided) */ 02346 if (o_zone != NULL) { 02347 status = KsmZoneIdFromName(o_zone, &qualifier_id); 02348 if (status != 0) { 02349 /* Try again with td */ 02350 StrAppend(&o_zone, "."); 02351 status = KsmZoneIdFromName(o_zone, &qualifier_id); 02352 if (status != 0) { 02353 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 02354 db_disconnect(lock_fd); 02355 return(status); 02356 } 02357 } 02358 } 02359 02360 printf("Keys:\n"); 02361 02362 status = ListKeys(qualifier_id); 02363 02364 if (status != 0) { 02365 printf("Error: failed to list keys\n"); 02366 db_disconnect(lock_fd); 02367 return status; 02368 } 02369 02370 printf("\n"); 02371 02372 /* Release sqlite lock file (if we have it) */ 02373 db_disconnect(lock_fd); 02374 02375 DbDisconnect(dbhandle); 02376 return 0; 02377 } 02378 02379 /* 02380 * KSKretire 02381 find key (either by details provided or oldest active), 02382 make sure that it is unique and in active state, 02383 retire key and set its dead time, 02384 */ 02385 int 02386 cmd_kskretire() 02387 { 02388 int status = 0; 02389 int zone_id = -1; 02390 int policy_id = -1; 02391 int key_count = -1; 02392 int keytag_int = -1; 02393 int temp_key_state = -1; 02394 int temp_keypair_id = -1; 02395 char* temp_cka_id = NULL; /* This will be set if we find a single matching key */ 02396 int user_certain; /* Continue ? */ 02397 02398 /* Database connection details */ 02399 DB_HANDLE dbhandle; 02400 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02401 02402 char* datetime = DtParseDateTimeString("now"); 02403 02404 /* Check datetime in case it came back NULL */ 02405 if (datetime == NULL) { 02406 printf("Couldn't turn \"now\" into a date, quitting...\n"); 02407 StrFree(datetime); 02408 exit(1); 02409 } 02410 02411 /* Warn and confirm that they realise this will retire the old key */ 02412 printf("*WARNING* This will retire the currently active KSK; are you sure? [y/N] "); 02413 02414 user_certain = getchar(); 02415 if (user_certain != 'y' && user_certain != 'Y') { 02416 printf("Okay, quitting...\n"); 02417 exit(0); 02418 } 02419 02420 /* try to connect to the database */ 02421 status = db_connect(&dbhandle, &lock_fd, 1); 02422 if (status != 0) { 02423 printf("Failed to connect to database\n"); 02424 db_disconnect(lock_fd); 02425 StrFree(datetime); 02426 return(1); 02427 } 02428 02429 /* Turn zone name into an id (if provided) */ 02430 if (o_zone != NULL) { 02431 status = KsmZoneIdFromName(o_zone, &zone_id); 02432 if (status != 0) { 02433 /* Try again with td */ 02434 StrAppend(&o_zone, "."); 02435 status = KsmZoneIdFromName(o_zone, &zone_id); 02436 if (status != 0) { 02437 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 02438 db_disconnect(lock_fd); 02439 StrFree(datetime); 02440 return(status); 02441 } 02442 } 02443 } 02444 02445 /* Check the keytag is numeric */ 02446 if (o_keytag != NULL) { 02447 if (StrIsDigits(o_keytag)) { 02448 status = StrStrtoi(o_keytag, &keytag_int); 02449 if (status != 0) { 02450 printf("Error: Unable to convert keytag \"%s\"; to an integer\n", o_keytag); 02451 db_disconnect(lock_fd); 02452 StrFree(datetime); 02453 return(status); 02454 } 02455 } else { 02456 printf("Error: keytag \"%s\"; should be numeric only\n", o_keytag); 02457 db_disconnect(lock_fd); 02458 StrFree(datetime); 02459 return(1); 02460 } 02461 } 02462 02463 if (o_keytag == NULL && o_cka_id == NULL) { 02464 /* We will retire the oldest key if there are 2 or more active keys */ 02465 if (o_zone == NULL) { 02466 printf("Please provide a zone or details of the key to roll\n"); 02467 usage_keykskretire(); 02468 db_disconnect(lock_fd); 02469 StrFree(datetime); 02470 return(-1); 02471 } 02472 02473 status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_ACTIVE, &key_count, zone_id); 02474 if (status != 0) { 02475 printf("Error: failed to count active keys\n"); 02476 db_disconnect(lock_fd); 02477 StrFree(datetime); 02478 return status; 02479 } 02480 02481 /* If there are not at least 2 active keys then quit */ 02482 if (key_count < 2) { 02483 printf("Error: completing this action would leave no active keys on zone, quitting...\n"); 02484 db_disconnect(lock_fd); 02485 StrFree(datetime); 02486 return -1; 02487 } 02488 02489 /* We will need a policy id for the next bit */ 02490 status = KsmPolicyIdFromZoneId(zone_id, &policy_id); 02491 if (status != 0) { 02492 printf("Error: failed to find policy for zone\n"); 02493 db_disconnect(lock_fd); 02494 StrFree(datetime); 02495 return status; 02496 } 02497 02498 status = RetireOldKey(zone_id, policy_id, datetime); 02499 02500 if (status == 0) { 02501 printf("Old key retired\n"); 02502 } else { 02503 printf("Old key NOT retired\n"); 02504 } 02505 } else { 02506 02507 /* 02508 * Get a count of keys that match our specifiers, will also print out 02509 * matching keys; note that zone_id may be overwritten 02510 */ 02511 status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state, &temp_keypair_id); 02512 if (status != 0) { 02513 printf("Error: failed to count keys\n"); 02514 db_disconnect(lock_fd); 02515 StrFree(datetime); 02516 return status; 02517 } 02518 02519 /* If the keycount is more than 1 then display the cka_ids of the keys */ 02520 if (key_count > 1) { 02521 printf("More than one key matched your parameters, please include more information from the above keys\n"); 02522 db_disconnect(lock_fd); 02523 StrFree(datetime); 02524 return -1; 02525 } 02526 02527 /* If the keycount is 0 or the key is not ACTIVE then write a message and exit */ 02528 if (key_count == 0 || temp_key_state != KSM_STATE_ACTIVE) { 02529 printf("No keys in the ACTIVE state matched your parameters, please check the parameters\n"); 02530 db_disconnect(lock_fd); 02531 StrFree(datetime); 02532 return -1; 02533 } 02534 02535 status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_ACTIVE, &key_count, zone_id); 02536 if (status != 0) { 02537 printf("Error: failed to count active keys\n"); 02538 db_disconnect(lock_fd); 02539 StrFree(datetime); 02540 return status; 02541 } 02542 02543 /* If there are not at least 2 active keys then quit */ 02544 if (key_count < 2) { 02545 printf("Error: completing this action would leave no active keys on zone, quitting...\n"); 02546 db_disconnect(lock_fd); 02547 StrFree(datetime); 02548 return -1; 02549 } 02550 02551 /* We will need a policy id for the next bit */ 02552 status = KsmPolicyIdFromZoneId(zone_id, &policy_id); 02553 if (status != 0) { 02554 printf("Error: failed to find policy for zone\n"); 02555 db_disconnect(lock_fd); 02556 StrFree(datetime); 02557 return status; 02558 } 02559 02560 /* Retire the key */ 02561 status = ChangeKeyState(KSM_TYPE_KSK, temp_cka_id, zone_id, policy_id, datetime, KSM_STATE_RETIRE); 02562 02563 /* Let them know that it seemed to work */ 02564 if (status == 0) { 02565 printf("Key %s retired\n", temp_cka_id); 02566 } 02567 } 02568 02569 /* Release sqlite lock file (if we have it) */ 02570 db_disconnect(lock_fd); 02571 02572 DbDisconnect(dbhandle); 02573 02574 StrFree(datetime); 02575 02576 return status; 02577 } 02578 02579 /* 02580 * DS Seen 02581 mark key as having had its DS published 02582 i.e. change its state to ACTIVE and set the time 02583 also set the time at which it will go to RETIRED 02584 */ 02585 int 02586 cmd_dsseen() 02587 { 02588 int status = 0; 02589 int zone_id = -1; 02590 int policy_id = -1; 02591 int key_count = -1; 02592 int retired_count = -1; 02593 int keytag_int = -1; 02594 int temp_key_state = -1; 02595 int temp_keypair_id = -1; 02596 char* temp_cka_id = NULL; /* This will be set if we find a single matching key */ 02597 int user_certain; /* Continue ? */ 02598 02599 /* Database connection details */ 02600 DB_HANDLE dbhandle; 02601 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02602 02603 char logmsg[256]; /* For the message that we log when a key moves */ 02604 02605 char* datetime = DtParseDateTimeString("now"); 02606 02607 /* Check datetime in case it came back NULL */ 02608 if (datetime == NULL) { 02609 printf("Couldn't turn \"now\" into a date, quitting...\n"); 02610 StrFree(datetime); 02611 exit(1); 02612 } 02613 02614 /* Check that we have either a keytag or a cka_id */ 02615 if (o_keytag == NULL && o_cka_id == NULL) { 02616 printf("Please provide a keytag or a CKA_ID for the key (CKA_ID will be used if both are provided\n"); 02617 usage_keydsseen(); 02618 StrFree(datetime); 02619 return(-1); 02620 } 02621 02622 /* Warn and confirm that they realise this will retire the old key */ 02623 if (0) { 02624 printf("*WARNING* This will retire the currently active KSK; are you sure? [y/N] "); 02625 02626 user_certain = getchar(); 02627 if (user_certain != 'y' && user_certain != 'Y') { 02628 printf("Okay, quitting...\n"); 02629 exit(0); 02630 } 02631 } 02632 /* try to connect to the database */ 02633 status = db_connect(&dbhandle, &lock_fd, 1); 02634 if (status != 0) { 02635 printf("Failed to connect to database\n"); 02636 db_disconnect(lock_fd); 02637 StrFree(datetime); 02638 return(1); 02639 } 02640 02641 /* Turn zone name into an id (if provided) */ 02642 /* TODO sort out all flag */ 02643 /*if (o_zone == NULL && !all_flag) { 02644 printf("Please specify a zone or use the --all flag to indicate all zones using this key\n");*/ 02645 if (o_zone == NULL) { 02646 printf("Please specify a zone using the --zone flag\n"); 02647 usage_keydsseen(); 02648 StrFree(datetime); 02649 db_disconnect(lock_fd); 02650 return(-1); 02651 } 02652 else if (o_zone != NULL) { 02653 status = KsmZoneIdFromName(o_zone, &zone_id); 02654 if (status != 0) { 02655 /* Try again with td */ 02656 StrAppend(&o_zone, "."); 02657 status = KsmZoneIdFromName(o_zone, &zone_id); 02658 if (status != 0) { 02659 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 02660 db_disconnect(lock_fd); 02661 StrFree(datetime); 02662 return(status); 02663 } 02664 } 02665 } 02666 else if (all_flag) { 02667 printf("*WARNING* This will act on every zone where this key is in use; are you sure? [y/N] "); 02668 02669 user_certain = getchar(); 02670 if (user_certain != 'y' && user_certain != 'Y') { 02671 printf("Okay, quitting...\n"); 02672 exit(0); 02673 } 02674 02675 zone_id = -1; 02676 } 02677 02678 /* Check the keytag is numeric */ 02679 if (o_keytag != NULL) { 02680 if (StrIsDigits(o_keytag)) { 02681 status = StrStrtoi(o_keytag, &keytag_int); 02682 if (status != 0) { 02683 printf("Error: Unable to convert keytag \"%s\"; to an integer\n", o_keytag); 02684 db_disconnect(lock_fd); 02685 StrFree(datetime); 02686 return(status); 02687 } 02688 } else { 02689 printf("Error: keytag \"%s\"; should be numeric only\n", o_keytag); 02690 db_disconnect(lock_fd); 02691 StrFree(datetime); 02692 return(1); 02693 } 02694 } 02695 02696 /* 02697 * Get a count of keys that match our specifiers, will also print out 02698 * matching keys; note that zone_id may be overwritten 02699 */ 02700 status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state, &temp_keypair_id); 02701 if (status != 0) { 02702 printf("Error: failed to count keys\n"); 02703 db_disconnect(lock_fd); 02704 StrFree(datetime); 02705 return status; 02706 } 02707 02708 /* If the keycount is more than 1 then display the cka_ids of the keys */ 02709 if (key_count > 1) { 02710 printf("More than one key matched your parameters, please include more information from the above keys\n"); 02711 db_disconnect(lock_fd); 02712 StrFree(datetime); 02713 return -1; 02714 } 02715 02716 /* If the key is already active then write a message and exit */ 02717 if (temp_key_state == KSM_STATE_ACTIVE) { 02718 printf("Key is already active\n"); 02719 db_disconnect(lock_fd); 02720 StrFree(datetime); 02721 return -1; 02722 } 02723 02724 /* If the keycount is 0 then write a message and exit */ 02725 if (key_count == 0) { 02726 printf("No keys in the READY state matched your parameters, please check the parameters\n"); 02727 db_disconnect(lock_fd); 02728 StrFree(datetime); 02729 return -1; 02730 } 02731 02732 /* We will need a policy id for the next bit */ 02733 status = KsmPolicyIdFromZoneId(zone_id, &policy_id); 02734 if (status != 0) { 02735 printf("Error: failed to find policy for zone\n"); 02736 db_disconnect(lock_fd); 02737 StrFree(datetime); 02738 return status; 02739 } 02740 02741 /* Do stuff */ 02742 status = MarkDSSeen(temp_keypair_id, zone_id, policy_id, datetime, temp_key_state); 02743 02744 /* Let them know that it seemed to work */ 02745 if (status == 0) { 02746 snprintf(logmsg, 256, "Key %s made %s", temp_cka_id, (temp_key_state == KSM_STATE_READY) ? "active" : "into standby"); 02747 printf("%s\n", logmsg); 02748 02749 /* send the msg to syslog */ 02750 openlog("ods-ksmutil", 0, DEFAULT_LOG_FACILITY); 02751 syslog(LOG_INFO, "%s", logmsg); 02752 closelog(); 02753 02754 } 02755 02756 /* Retire old key, unless asked not to */ 02757 if (temp_key_state == KSM_STATE_READY) { 02758 if (retire_flag == 1) { 02759 02760 /* We will retire the oldest key if there are 2 or more active keys */ 02761 status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_ACTIVE, &key_count, zone_id); 02762 if (status != 0) { 02763 printf("Error: failed to count active keys\n"); 02764 db_disconnect(lock_fd); 02765 StrFree(datetime); 02766 return status; 02767 } 02768 02769 /* If there are not at least 2 active keys then quit */ 02770 if (key_count < 2) { 02771 /* Count retired keys to work out if this is a new zone */ 02772 /* TODO MAKE SURE THIS IS RIGHT !!! */ 02773 status = CountKeysInState(KSM_TYPE_KSK, KSM_STATE_RETIRE, &retired_count, zone_id); 02774 if (status != 0) { 02775 printf("Error: failed to count retired keys\n"); 02776 db_disconnect(lock_fd); 02777 StrFree(datetime); 02778 return status; 02779 } 02780 02781 /* Cleanup and print an error message... */ 02782 db_disconnect(lock_fd); 02783 StrFree(datetime); 02784 if (retired_count != 0) { 02785 printf("Error: retiring a key would leave no active keys on zone, skipping...\n"); 02786 return -1; 02787 } else { 02788 /* ...Unless this looks like a new zone, in which case poke 02789 the enforcerd */ 02790 if (restart_enforcerd() != 0) 02791 { 02792 fprintf(stderr, "Could not HUP ods-enforcerd\n"); 02793 } 02794 return 0; 02795 } 02796 } 02797 02798 status = RetireOldKey(zone_id, policy_id, datetime); 02799 02800 /* Let them know that it seemed to work */ 02801 if (status == 0) { 02802 printf("Old key retired\n"); 02803 } else { 02804 printf("Old key NOT retired\n"); 02805 } 02806 } else { 02807 printf("Old key NOT retired\n"); 02808 } 02809 } 02810 02811 /* Need to poke the enforcer to wake it up */ 02812 if (restart_enforcerd() != 0) 02813 { 02814 fprintf(stderr, "Could not HUP ods-enforcerd\n"); 02815 } 02816 02817 /* Release sqlite lock file (if we have it) */ 02818 db_disconnect(lock_fd); 02819 02820 DbDisconnect(dbhandle); 02821 02822 StrFree(datetime); 02823 02824 return status; 02825 } 02826 02827 /* 02828 * import a key into the ksm and set its values as specified 02829 */ 02830 int 02831 cmd_import () 02832 { 02833 int status = 0; 02834 02835 /* some strings to hold upper case versions of arguments */ 02836 char* case_keytype = NULL; /* KSK or ZSK */ 02837 char* case_algorithm = NULL; /* RSASHA1 or RSASHA1-NSEC3-SHA1 (5 or 7) */ 02838 char* case_state = NULL; /* GENERATE, PUBLISH, READY, ACTIVE or RETIRE */ 02839 02840 int repo_id = -1; 02841 int zone_id = -1; 02842 int policy_id = -1; 02843 int cka_id_exists = -1; /* do we already have this id in the HSM */ 02844 int keytype_id = -1; 02845 int size_int = -1; 02846 int algo_id = -1; 02847 int state_id = -1; 02848 char form_time[KSM_TIME_LENGTH]; /* YYYY-MM-DD HH:MM:SS + NULL Time after we reformat it */ 02849 char form_opt_time[KSM_TIME_LENGTH]; /* Opt_time after we reformat it */ 02850 02851 DB_ID keypair_id = 0; /* This will be set when we enter the keypair */ 02852 DB_ID ignore = 0; /* This will be set when we enter the dnsseckey */ 02853 02854 struct tm datetime; /* Used for getting the date/time */ 02855 02856 int fix_time = 0; /* Will we be setting the retire time? */ 02857 02858 /* Database connection details */ 02859 DB_HANDLE dbhandle; 02860 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 02861 02862 DB_RESULT result; /* Result of parameter query */ 02863 KSM_PARAMETER data; /* Parameter information */ 02864 02865 int user_certain; /* Continue ? */ 02866 02867 /* Chech that we got all arguments. */ 02868 02869 if (o_cka_id == NULL) { 02870 printf("Error: please specify a CKA_ID with the --cka_id <CKA_ID>\n"); 02871 return(1); 02872 } 02873 if (o_repository == NULL) { 02874 printf("Error: please specify a repository with the --repository <repository>\n"); 02875 return(1); 02876 } 02877 if (o_zone == NULL) { 02878 printf("Error: please specify a zone with the --zone <zone>\n"); 02879 return(1); 02880 } 02881 if (o_size == NULL) { 02882 printf("Error: please specify the number of bits with the --bits <size>\n"); 02883 return(1); 02884 } 02885 if (o_algo == NULL) { 02886 printf("Error: please specify the algorithm with the --algorithm <algorithm>\n"); 02887 return(1); 02888 } 02889 if (o_keystate == NULL) { 02890 printf("Error: please specify the state with the --keystate <state>\n"); 02891 return(1); 02892 } 02893 if (o_keytype == NULL) { 02894 printf("Error: please specify a keytype, KSK or ZSK, with the --keytype <type>\n"); 02895 return(1); 02896 } 02897 if (o_time == NULL) { 02898 printf("Error: please specify the time of when the key entered the given state with the --time <time>\n"); 02899 return(1); 02900 } 02901 02902 /* try to connect to the database */ 02903 status = db_connect(&dbhandle, &lock_fd, 1); 02904 if (status != 0) { 02905 printf("Failed to connect to database\n"); 02906 db_disconnect(lock_fd); 02907 return(1); 02908 } 02909 02910 /* check that the repository exists */ 02911 status = KsmSmIdFromName(o_repository, &repo_id); 02912 if (status != 0) { 02913 printf("Error: unable to find a repository named \"%s\" in database\n", o_repository); 02914 db_disconnect(lock_fd); 02915 return status; 02916 } 02917 02918 /* check that the zone name is valid and use it to get some ids */ 02919 status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id); 02920 if (status != 0) { 02921 /* Try again with td */ 02922 StrAppend(&o_zone, "."); 02923 status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id); 02924 if (status != 0) { 02925 printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); 02926 db_disconnect(lock_fd); 02927 return(status); 02928 } 02929 } 02930 02931 /* Check that the cka_id does not exist (in the specified HSM) */ 02932 status = (KsmCheckHSMkeyID(repo_id, o_cka_id, &cka_id_exists)); 02933 if (status != 0) { 02934 db_disconnect(lock_fd); 02935 return(status); 02936 } 02937 if (cka_id_exists == 1) { 02938 printf("Error: key with CKA_ID \"%s\" already exists in database\n", o_cka_id); 02939 db_disconnect(lock_fd); 02940 return(1); 02941 } 02942 02943 /* Check the Keytype */ 02944 case_keytype = StrStrdup(o_keytype); 02945 (void) StrToUpper(case_keytype); 02946 if (strncmp(case_keytype, "KSK", 3) == 0 || strncmp(o_keytype, "257", 3) == 0) { 02947 keytype_id = 257; 02948 } 02949 else if (strncmp(case_keytype, "ZSK", 3) == 0 || strncmp(o_keytype, "256", 3) == 0) { 02950 keytype_id = 256; 02951 } 02952 else { 02953 printf("Error: Unrecognised keytype %s; should be one of KSK or ZSK\n", o_keytype); 02954 02955 db_disconnect(lock_fd); 02956 StrFree(case_keytype); 02957 return(1); 02958 } 02959 StrFree(case_keytype); 02960 02961 /* Check the size is numeric */ 02962 if (StrIsDigits(o_size)) { 02963 status = StrStrtoi(o_size, &size_int); 02964 if (status != 0) { 02965 printf("Error: Unable to convert bits \"%s\"; to an integer\n", o_size); 02966 db_disconnect(lock_fd); 02967 return(status); 02968 } 02969 } else { 02970 printf("Error: Bits \"%s\"; should be numeric only\n", o_size); 02971 db_disconnect(lock_fd); 02972 return(1); 02973 } 02974 02975 /* Check the algorithm */ 02976 if (StrIsDigits(o_algo)) { 02977 /* Accept it as-is; The HSM will tell us if the number is not valid */ 02978 status = StrStrtoi(o_algo, &algo_id); 02979 } else { 02980 /* Convert name to an id, we get 0 if it is unrecognised */ 02981 case_algorithm = StrStrdup(o_algo); 02982 (void) StrToLower(case_algorithm); 02983 02984 algo_id = KsmKeywordAlgorithmNameToValue(case_algorithm); 02985 StrFree(case_algorithm); 02986 } 02987 02988 if (status != 0 || algo_id == 0 || hsm_supported_algorithm(algo_id) != 0) { 02989 printf("Error: Key algorithm %s not supported; try one of RSASHA1, RSASHA1-NSEC3-SHA1 or RSASHA256\n", o_algo); 02990 db_disconnect(lock_fd); 02991 return(status); 02992 } 02993 02994 /* Check the state */ 02995 case_state = StrStrdup(o_keystate); 02996 (void) StrToUpper(case_state); 02997 if (strncmp(case_state, "GENERATE", 8) == 0 || strncmp(o_keystate, "1", 1) == 0) { 02998 state_id = 1; 02999 } 03000 else if (strncmp(case_state, "PUBLISH", 7) == 0 || strncmp(o_keystate, "2", 1) == 0) { 03001 state_id = 2; 03002 } 03003 else if (strncmp(case_state, "READY", 5) == 0 || strncmp(o_keystate, "3", 1) == 0) { 03004 state_id = 3; 03005 } 03006 else if (strncmp(case_state, "ACTIVE", 6) == 0 || strncmp(o_keystate, "4", 1) == 0) { 03007 state_id = 4; 03008 } 03009 else if (strncmp(case_state, "RETIRE", 6) == 0 || strncmp(o_keystate, "5", 1) == 0) { 03010 state_id = 5; 03011 } 03012 else { 03013 printf("Error: Unrecognised state %s; should be one of GENERATE, PUBLISH, READY, ACTIVE or RETIRE\n", o_keystate); 03014 03015 db_disconnect(lock_fd); 03016 StrFree(case_state); 03017 return(1); 03018 } 03019 StrFree(case_state); 03020 03021 /* Check, and convert, the time(s) */ 03022 status = DtGeneral(o_time, &datetime); 03023 if (status != 0) { 03024 printf("Error: unable to convert \"%s\" into a date\n", o_time); 03025 date_help(); 03026 03027 db_disconnect(lock_fd); 03028 return(status); 03029 } 03030 else { 03031 snprintf(form_time, KSM_TIME_LENGTH, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d", 03032 datetime.tm_year + 1900, datetime.tm_mon + 1, datetime.tm_mday, 03033 datetime.tm_hour, datetime.tm_min, datetime.tm_sec); 03034 } 03035 03036 if (o_retire != NULL) { 03037 /* can only specify a retire time if the key is being inserted in the active state */ 03038 if (state_id != KSM_STATE_ACTIVE) { 03039 printf("Error: unable to specify retire time for a key in state \"%s\"\n", o_keystate); 03040 db_disconnect(lock_fd); 03041 return(status); 03042 } 03043 03044 status = DtGeneral(o_retire, &datetime); 03045 if (status != 0) { 03046 printf("Error: unable to convert retire time \"%s\" into a date\n", o_retire); 03047 date_help(); 03048 03049 db_disconnect(lock_fd); 03050 return(status); 03051 } 03052 else { 03053 snprintf(form_opt_time, KSM_TIME_LENGTH, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d", 03054 datetime.tm_year + 1900, datetime.tm_mon + 1, datetime.tm_mday, 03055 datetime.tm_hour, datetime.tm_min, datetime.tm_sec); 03056 fix_time = 1; 03057 } 03058 } else { 03059 form_opt_time[0] = '\0'; 03060 } 03061 03062 /* Find out if this zone has any others on a "shared keys" policy and warn */ 03063 status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id); 03064 if (status != 0) { 03065 db_disconnect(lock_fd); 03066 return(status); 03067 } 03068 status = KsmParameter(result, &data); 03069 if (status != 0) { 03070 db_disconnect(lock_fd); 03071 return(status); 03072 } 03073 KsmParameterEnd(result); 03074 03075 /* Warn and confirm if this will roll more than one zone */ 03076 if (data.value == 1) { 03077 printf("*WARNING* This zone shares keys with others, the key will be added to all; are you sure? [y/N] "); 03078 03079 user_certain = getchar(); 03080 if (user_certain != 'y' && user_certain != 'Y') { 03081 printf("Okay, quitting...\n"); 03082 db_disconnect(lock_fd); 03083 exit(0); 03084 } 03085 } 03086 03087 /* create basic keypair */ 03088 status = KsmImportKeyPair(policy_id, o_cka_id, repo_id, size_int, algo_id, state_id, form_time, fix_time, &keypair_id); 03089 if (status != 0) { 03090 printf("Error: couldn't import key\n"); 03091 db_disconnect(lock_fd); 03092 return(status); 03093 } 03094 03095 /* allocate key to zone(s) */ 03096 /* TODO might not need this any more */ 03097 /* if (data.value == 1) { 03098 status = KsmDnssecKeyCreateOnPolicy(policy_id, (int) keypair_id, keytype_id); 03099 } else {*/ 03100 status = KsmDnssecKeyCreate(zone_id, (int) keypair_id, keytype_id, state_id, form_time, form_opt_time, &ignore); 03101 03102 if (status != 0) { 03103 printf("Error: couldn't allocate key to zone(s)\n"); 03104 db_disconnect(lock_fd); 03105 return(status); 03106 } 03107 03108 printf("Key imported into zone(s)\n"); 03109 03110 /* Release sqlite lock file (if we have it) */ 03111 db_disconnect(lock_fd); 03112 03113 DbDisconnect(dbhandle); 03114 return 0; 03115 } 03116 03117 /* 03118 * make a backup of a sqlite database 03119 */ 03120 int 03121 cmd_dbbackup () 03122 { 03123 /* Database details */ 03124 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 03125 03126 /* what we will read from the file */ 03127 char *dbschema = NULL; 03128 char *host = NULL; 03129 char *port = NULL; 03130 char *user = NULL; 03131 char *password = NULL; 03132 03133 int status; 03134 03135 char* backup_filename = NULL; 03136 char* lock_filename; 03137 03138 char *path = getenv("PWD"); 03139 03140 if (DbFlavour() != SQLITE_DB) { 03141 printf("Sorry, currently this utility can only backup a sqlite database file\n"); 03142 return -1; 03143 } 03144 03145 /* Read the database details out of conf.xml */ 03146 status = get_db_details(&dbschema, &host, &port, &user, &password); 03147 if (status != 0) { 03148 StrFree(host); 03149 StrFree(port); 03150 StrFree(dbschema); 03151 StrFree(user); 03152 StrFree(password); 03153 return(status); 03154 } 03155 03156 /* set up DB lock */ 03157 lock_filename = NULL; 03158 StrAppend(&lock_filename, dbschema); 03159 StrAppend(&lock_filename, ".our_lock"); 03160 03161 lock_fd = fopen(lock_filename, "w"); 03162 status = get_lite_lock(lock_filename, lock_fd); 03163 if (status != 0) { 03164 printf("Error getting db lock\n"); 03165 if (lock_fd != NULL) { 03166 fclose(lock_fd); 03167 } 03168 StrFree(host); 03169 StrFree(port); 03170 StrFree(dbschema); 03171 StrFree(user); 03172 StrFree(password); 03173 return(1); 03174 } 03175 StrFree(lock_filename); 03176 03177 /* Work out what file to output */ 03178 if (o_output == NULL) { 03179 StrAppend(&backup_filename, dbschema); 03180 StrAppend(&backup_filename, ".backup"); 03181 } else if (*o_output != '/') { 03182 StrAppend(&backup_filename, path); 03183 StrAppend(&backup_filename, "/"); 03184 StrAppend(&backup_filename, o_output); 03185 } else { 03186 StrAppend(&backup_filename, o_output); 03187 } 03188 03189 status = backup_file(dbschema, backup_filename); 03190 03191 StrFree(backup_filename); 03192 03193 /* Cleanup */ 03194 StrFree(host); 03195 StrFree(port); 03196 StrFree(dbschema); 03197 StrFree(user); 03198 StrFree(password); 03199 03200 /* Release sqlite lock */ 03201 db_disconnect(lock_fd); 03202 03203 return status; 03204 } 03205 03206 /* 03207 * Delete any policies with no zones 03208 */ 03209 int 03210 cmd_purgepolicy () 03211 { 03212 int status = 0; 03213 03214 char* kasp_filename = NULL; 03215 char* zonelist_filename = NULL; 03216 char* backup_filename = NULL; 03217 03218 DB_HANDLE dbhandle; 03219 FILE* lock_fd = NULL; 03220 KSM_POLICY *policy; 03221 DB_RESULT result; /* Result set from policy query */ 03222 DB_RESULT result2; /* Result set from zone count query */ 03223 char sql[KSM_SQL_SIZE]; 03224 int size = -1; 03225 char* sql2; 03226 03227 FILE *test; 03228 int zone_count = -1; 03229 03230 xmlDocPtr doc = NULL; 03231 03232 int user_certain; 03233 printf("*WARNING* This feature is experimental and has not been fully tested; are you sure? [y/N] "); 03234 03235 user_certain = getchar(); 03236 if (user_certain != 'y' && user_certain != 'Y') { 03237 printf("Okay, quitting...\n"); 03238 exit(0); 03239 } 03240 03241 /* Read the conf.xml file to learn the location of the kasp.xml file. */ 03242 status = read_filenames(&zonelist_filename, &kasp_filename); 03243 if (status != 0) { 03244 printf("Failed to read conf.xml\n"); 03245 db_disconnect(lock_fd); 03246 return(1); 03247 } 03248 03249 /* Backup the current kasp.xml */ 03250 StrAppend(&backup_filename, kasp_filename); 03251 StrAppend(&backup_filename, ".backup"); 03252 status = backup_file(kasp_filename, backup_filename); 03253 StrFree(backup_filename); 03254 if (status != 0) { 03255 StrFree(kasp_filename); 03256 db_disconnect(lock_fd); 03257 return(status); 03258 } 03259 03260 /* Check that we will be able to make the changes to kasp.xml */ 03261 if ((test = fopen(kasp_filename, "ab"))==NULL) { 03262 printf("Cannot open kasp.xml for writing: %s\n", strerror(errno)); 03263 return(-1); 03264 } else { 03265 fclose(test); 03266 } 03267 03268 /* try to connect to the database */ 03269 status = db_connect(&dbhandle, &lock_fd, 1); 03270 if (status != 0) { 03271 printf("Failed to connect to database\n"); 03272 db_disconnect(lock_fd); 03273 return(1); 03274 } 03275 03276 /* Start a transaction */ 03277 status = DbBeginTransaction(); 03278 if (status != 0) { 03279 /* Something went wrong */ 03280 03281 MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 03282 db_disconnect(lock_fd); 03283 return status; 03284 } 03285 03286 /* Loop through each policy */ 03287 policy = KsmPolicyAlloc(); 03288 if (policy == NULL) { 03289 printf("Malloc for policy struct failed\n"); 03290 exit(1); 03291 } 03292 03293 /* Read all policies */ 03294 status = KsmPolicyInit(&result, NULL); 03295 if (status == 0) { 03296 /* get the first policy */ 03297 status = KsmPolicy(result, policy); 03298 while (status == 0) { 03299 /* Count zones on this policy */ 03300 status = KsmZoneCountInit(&result2, policy->id); 03301 if (status == 0) { 03302 status = KsmZoneCount(result2, &zone_count); 03303 } 03304 DbFreeResult(result2); 03305 03306 if (status == 0) { 03307 /* Only carry on if we have no zones */ 03308 if (zone_count == 0) { 03309 printf("No zones on policy %s; purging...\n", policy->name); 03310 /* set keystate to 6 across the board */ 03311 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); 03312 03313 /* Quick check that we didn't run out of space */ 03314 if (size < 0 || size >= KSM_SQL_SIZE) { 03315 printf("Couldn't construct SQL to kill orphaned keys\n"); 03316 db_disconnect(lock_fd); 03317 KsmPolicyFree(policy); 03318 return -1; 03319 } 03320 03321 status = DbExecuteSqlNoResult(DbHandle(), sql); 03322 03323 /* Report any errors */ 03324 if (status != 0) { 03325 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 03326 db_disconnect(lock_fd); 03327 KsmPolicyFree(policy); 03328 return status; 03329 } 03330 03331 /* call purge keys on that policy (all zones) */ 03332 status = PurgeKeys(-1, policy->id); 03333 if (status != 0) { 03334 printf("Key purge failed for policy %s\n", policy->name); 03335 db_disconnect(lock_fd); 03336 KsmPolicyFree(policy); 03337 return status; 03338 } 03339 03340 /* Delete the policy from DB */ 03341 sql2 = DdsInit("parameters_policies"); 03342 DdsConditionInt(&sql2, "policy_id", DQS_COMPARE_EQ, policy->id, 0); 03343 DdsEnd(&sql2); 03344 status = DbExecuteSqlNoResult(DbHandle(), sql2); 03345 DdsFree(sql2); 03346 03347 if (status != 0) 03348 { 03349 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 03350 db_disconnect(lock_fd); 03351 KsmPolicyFree(policy); 03352 return status; 03353 } 03354 03355 sql2 = DdsInit("policies"); 03356 DdsConditionInt(&sql2, "id", DQS_COMPARE_EQ, policy->id, 0); 03357 DdsEnd(&sql2); 03358 status = DbExecuteSqlNoResult(DbHandle(), sql2); 03359 DdsFree(sql2); 03360 03361 if (status != 0) 03362 { 03363 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 03364 db_disconnect(lock_fd); 03365 KsmPolicyFree(policy); 03366 return status; 03367 } 03368 03369 /* Delete the policy from the XML */ 03370 /* Read the file and delete our policy node(s) in memory */ 03371 doc = del_policy_node(kasp_filename, policy->name); 03372 if (doc == NULL) { 03373 db_disconnect(lock_fd); 03374 KsmPolicyFree(policy); 03375 StrFree(kasp_filename); 03376 return(1); 03377 } 03378 03379 /* Save our new file over the old, TODO should we validate it first? */ 03380 status = xmlSaveFormatFile(kasp_filename, doc, 1); 03381 xmlFreeDoc(doc); 03382 if (status == -1) { 03383 printf("Could not save %s\n", kasp_filename); 03384 StrFree(kasp_filename); 03385 db_disconnect(lock_fd); 03386 KsmPolicyFree(policy); 03387 return(1); 03388 } 03389 03390 } 03391 } else { 03392 printf("Couldn't count zones on policy; quitting...\n"); 03393 db_disconnect(lock_fd); 03394 exit(1); 03395 } 03396 03397 /* get next policy */ 03398 status = KsmPolicy(result, policy); 03399 } 03400 /* Reset EOF */ 03401 if (status == -1) { 03402 status = 0; 03403 } 03404 DbFreeResult(result); 03405 } 03406 03407 /* Commit or Rollback */ 03408 if (status == 0) { 03409 /* Everything worked by the looks of it */ 03410 DbCommit(); 03411 } else { 03412 /* Whatever happened, it was not good */ 03413 DbRollback(); 03414 } 03415 03416 StrFree(kasp_filename); 03417 db_disconnect(lock_fd); 03418 KsmPolicyFree(policy); 03419 return status; 03420 } 03421 03422 /* 03423 * Send command to ods-control 03424 */ 03425 int 03426 cmd_control(char *command) 03427 { 03428 int status = 0; 03429 char* ods_control_cmd = NULL; 03430 char* ptr = command; 03431 03432 /* We need the command in lower case */ 03433 if (ptr) { 03434 while (*ptr) { 03435 *ptr = tolower((int) *ptr); 03436 ++ptr; 03437 } 03438 } 03439 03440 /* Call "ods-control enforcer COMMAND" */ 03441 StrAppend(&ods_control_cmd, ODS_EN_CONTROL); 03442 StrAppend(&ods_control_cmd, command); 03443 03444 status = system(ods_control_cmd); 03445 if (status != 0) 03446 { 03447 fprintf(stderr, "Couldn't run %s\n", ods_control_cmd); 03448 } 03449 03450 StrFree(ods_control_cmd); 03451 03452 return(status); 03453 } 03454 03455 /* 03456 * Fairly basic main, just pass most things through to their handlers 03457 */ 03458 int 03459 main (int argc, char *argv[]) 03460 { 03461 int result; 03462 int ch; 03463 char* case_command = NULL; 03464 char* case_verb = NULL; 03465 03466 int option_index = 0; 03467 static struct option long_options[] = 03468 { 03469 {"all", no_argument, 0, 'a'}, 03470 {"bits", required_argument, 0, 'b'}, 03471 {"config", required_argument, 0, 'c'}, 03472 {"ds", no_argument, 0, 'd'}, 03473 {"keystate", required_argument, 0, 'e'}, 03474 {"no-retire", no_argument, 0, 'f'}, 03475 {"algorithm", required_argument, 0, 'g'}, 03476 {"help", no_argument, 0, 'h'}, 03477 {"input", required_argument, 0, 'i'}, 03478 {"cka_id", required_argument, 0, 'k'}, 03479 {"no-xml", no_argument, 0, 'm'}, 03480 {"interval", required_argument, 0, 'n'}, 03481 {"output", required_argument, 0, 'o'}, 03482 {"policy", required_argument, 0, 'p'}, 03483 {"repository", required_argument, 0, 'r'}, 03484 {"signerconf", required_argument, 0, 's'}, 03485 {"keytype", required_argument, 0, 't'}, 03486 {"time", required_argument, 0, 'w'}, 03487 {"verbose", no_argument, 0, 'v'}, 03488 {"version", no_argument, 0, 'V'}, 03489 {"keytag", required_argument, 0, 'x'}, 03490 {"retire", required_argument, 0, 'y'}, 03491 {"zone", required_argument, 0, 'z'}, 03492 {0,0,0,0} 03493 }; 03494 03495 progname = argv[0]; 03496 03497 while ((ch = getopt_long(argc, argv, "ab:c:de:fg:hi:k:n:o:p:r:s:t:vVw:x:y:z:", long_options, &option_index)) != -1) { 03498 switch (ch) { 03499 case 'a': 03500 all_flag = 1; 03501 break; 03502 case 'b': 03503 o_size = StrStrdup(optarg); 03504 break; 03505 case 'c': 03506 config = StrStrdup(optarg); 03507 break; 03508 case 'd': 03509 ds_flag = 1; 03510 break; 03511 case 'e': 03512 o_keystate = StrStrdup(optarg); 03513 break; 03514 case 'f': 03515 retire_flag = 0; 03516 break; 03517 case 'g': 03518 o_algo = StrStrdup(optarg); 03519 break; 03520 case 'h': 03521 usage(); 03522 states_help(); 03523 types_help(); 03524 date_help(); 03525 exit(0); 03526 break; 03527 case 'i': 03528 o_input = StrStrdup(optarg); 03529 break; 03530 case 'k': 03531 o_cka_id = StrStrdup(optarg); 03532 break; 03533 case 'm': 03534 xml_flag = 0; 03535 break; 03536 case 'n': 03537 o_interval = StrStrdup(optarg); 03538 break; 03539 case 'o': 03540 o_output = StrStrdup(optarg); 03541 break; 03542 case 'p': 03543 o_policy = StrStrdup(optarg); 03544 break; 03545 case 'r': 03546 o_repository = StrStrdup(optarg); 03547 break; 03548 case 's': 03549 o_signerconf = StrStrdup(optarg); 03550 break; 03551 case 't': 03552 o_keytype = StrStrdup(optarg); 03553 break; 03554 case 'V': 03555 printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); 03556 exit(0); 03557 break; 03558 case 'v': 03559 verbose_flag = 1; 03560 break; 03561 case 'w': 03562 o_time = StrStrdup(optarg); 03563 break; 03564 case 'x': 03565 o_keytag = StrStrdup(optarg); 03566 break; 03567 case 'y': 03568 o_retire = StrStrdup(optarg); 03569 break; 03570 case 'z': 03571 /* Remove trailing dot here */ 03572 o_zone = StrStrdup(optarg); 03573 if (strlen(o_zone) > 1 && o_zone[strlen(o_zone)-1] == '.') { 03574 o_zone[strlen(o_zone)-1] = '\0'; 03575 td_flag = 1; 03576 } 03577 03578 break; 03579 default: 03580 usage(); 03581 exit(1); 03582 } 03583 } 03584 argc -= optind; 03585 argv += optind; 03586 03587 if (!argc) { 03588 usage(); 03589 exit(1); 03590 } 03591 03592 03593 /*(void) KsmInit();*/ 03594 MsgInit(); 03595 MsgRegister(KME_MIN_VALUE, KME_MAX_VALUE, m_messages, ksm_log_msg); 03596 MsgRegister(DBS_MIN_VALUE, DBS_MAX_VALUE, d_messages, ksm_log_msg); 03597 03598 /* command should be one of SETUP UPDATE ZONE REPOSITORY POLICY KEY BACKUP or ROLLOVER */ 03599 case_command = StrStrdup(argv[0]); 03600 (void) StrToUpper(case_command); 03601 if (argc > 1) { 03602 /* verb should be stuff like ADD, LIST, DELETE, etc */ 03603 case_verb = StrStrdup(argv[1]); 03604 (void) StrToUpper(case_verb); 03605 } else { 03606 case_verb = StrStrdup("NULL"); 03607 } 03608 03609 03610 if (!strncmp(case_command, "SETUP", 5)) { 03611 argc --; 03612 argv ++; 03613 result = cmd_setup(); 03614 } else if (!strncmp(case_command, "UPDATE", 6)) { 03615 argc --; 03616 argv ++; 03617 result = cmd_update(case_verb); 03618 } else if (!strncmp(case_command, "START", 5) || 03619 !strncmp(case_command, "STOP", 4) || 03620 !strncmp(case_command, "NOTIFY", 6)) { 03621 argc --; 03622 argv ++; 03623 result = cmd_control(case_command); 03624 } else if (!strncmp(case_command, "ZONE", 4) && strlen(case_command) == 4) { 03625 argc --; argc --; 03626 argv ++; argv ++; 03627 03628 /* verb should be add, delete or list */ 03629 if (!strncmp(case_verb, "ADD", 3)) { 03630 result = cmd_addzone(); 03631 } else if (!strncmp(case_verb, "DELETE", 6)) { 03632 result = cmd_delzone(); 03633 } else if (!strncmp(case_verb, "LIST", 4)) { 03634 result = cmd_listzone(); 03635 } else { 03636 printf("Unknown command: zone %s\n", case_verb); 03637 usage_zone(); 03638 result = -1; 03639 } 03640 } else if (!strncmp(case_command, "REPOSITORY", 10)) { 03641 argc --; argc --; 03642 argv ++; argv ++; 03643 /* verb should be list */ 03644 if (!strncmp(case_verb, "LIST", 4)) { 03645 result = cmd_listrepo(); 03646 } else { 03647 printf("Unknown command: repository %s\n", case_verb); 03648 usage_repo(); 03649 result = -1; 03650 } 03651 } else if (!strncmp(case_command, "POLICY", 6)) { 03652 argc --; argc --; 03653 argv ++; argv ++; 03654 /* verb should be export, import, list or purge */ 03655 if (!strncmp(case_verb, "EXPORT", 6)) { 03656 result = cmd_exportpolicy(); 03657 } else if (!strncmp(case_verb, "IMPORT", 6)) { 03658 result = cmd_update("KASP"); 03659 } else if (!strncmp(case_verb, "LIST", 4)) { 03660 result = cmd_listpolicy(); 03661 } else if (!strncmp(case_verb, "PURGE", 5)) { 03662 result = cmd_purgepolicy(); 03663 } else { 03664 printf("Unknown command: policy %s\n", case_verb); 03665 usage_policy(); 03666 result = -1; 03667 } 03668 } else if (!strncmp(case_command, "KEY", 3)) { 03669 argc --; argc --; 03670 argv ++; argv ++; 03671 /* verb should be list, export import, rollover, purge, generate, ksk-retire or ds-seen */ 03672 if (!strncmp(case_verb, "LIST", 4)) { 03673 result = cmd_listkeys(); 03674 } 03675 else if (!strncmp(case_verb, "EXPORT", 6)) { 03676 result = cmd_exportkeys(); 03677 } 03678 else if (!strncmp(case_verb, "IMPORT", 6)) { 03679 result = cmd_import(); 03680 } 03681 else if (!strncmp(case_verb, "ROLLOVER", 8)) { 03682 /* Are we rolling a zone or a whole policy? */ 03683 if (o_zone != NULL && o_policy == NULL) { 03684 result = cmd_rollzone(); 03685 } 03686 else if (o_zone == NULL && o_policy != NULL) { 03687 result = cmd_rollpolicy(); 03688 } 03689 else { 03690 printf("Please provide either a zone OR a policy to rollover\n"); 03691 usage_keyroll(); 03692 result = -1; 03693 } 03694 } 03695 else if (!strncmp(case_verb, "PURGE", 5)) { 03696 if ((o_zone != NULL && o_policy == NULL) || 03697 (o_zone == NULL && o_policy != NULL)){ 03698 result = cmd_keypurge(); 03699 } 03700 else { 03701 printf("Please provide either a zone OR a policy to key purge\n"); 03702 usage_keypurge(); 03703 result = -1; 03704 } 03705 } 03706 else if (!strncmp(case_verb, "GENERATE", 8)) { 03707 result = cmd_genkeys(); 03708 } 03709 else if (!strncmp(case_verb, "KSK-RETIRE", 10)) { 03710 result = cmd_kskretire(); 03711 } 03712 else if (!strncmp(case_verb, "DS-SEEN", 7)) { 03713 result = cmd_dsseen(); 03714 } else { 03715 printf("Unknown command: key %s\n", case_verb); 03716 usage_key(); 03717 result = -1; 03718 } 03719 } else if (!strncmp(case_command, "BACKUP", 6)) { 03720 argc --; argc --; 03721 argv ++; argv ++; 03722 /* verb should be done, prepare, commit, rollback or list */ 03723 if (!strncmp(case_verb, "DONE", 4) || 03724 !strncmp(case_verb, "PREPARE", 7) || 03725 !strncmp(case_verb, "COMMIT", 6) || 03726 !strncmp(case_verb, "ROLLBACK", 8)) { 03727 result = cmd_backup(case_verb); 03728 } 03729 else if (!strncmp(case_verb, "LIST", 4)) { 03730 result = cmd_listbackups(); 03731 } else { 03732 printf("Unknown command: backup %s\n", case_verb); 03733 usage_backup(); 03734 result = -1; 03735 } 03736 } else if (!strncmp(case_command, "ROLLOVER", 8)) { 03737 argc --; argc --; 03738 argv ++; argv ++; 03739 if (!strncmp(case_verb, "LIST", 4)) { 03740 result = cmd_listrolls(); 03741 } else { 03742 printf("Unknown command: rollover %s\n", case_verb); 03743 usage_rollover(); 03744 result = -1; 03745 } 03746 } else if (!strncmp(case_command, "DATABASE", 8)) { 03747 argc --; argc --; 03748 argv ++; argv ++; 03749 /* verb should be backup */ 03750 if (!strncmp(case_verb, "BACKUP", 6)) { 03751 result = cmd_dbbackup(); 03752 } else { 03753 printf("Unknown command: database %s\n", case_verb); 03754 usage_database(); 03755 result = -1; 03756 } 03757 } else if (!strncmp(case_command, "ZONELIST", 8)) { 03758 argc --; argc --; 03759 argv ++; argv ++; 03760 /* verb should be import or export */ 03761 if (!strncmp(case_verb, "EXPORT", 6)) { 03762 result = cmd_exportzonelist(); 03763 } 03764 else if (!strncmp(case_verb, "IMPORT", 6)) { 03765 result = cmd_update("ZONELIST"); 03766 } else { 03767 printf("Unknown command: zonelist %s\n", case_verb); 03768 usage_zonelist2(); 03769 result = -1; 03770 } 03771 } else { 03772 printf("Unknown command: %s\n", argv[0]); 03773 usage(); 03774 result = -1; 03775 } 03776 03777 StrFree(case_command); 03778 StrFree(case_verb); 03779 03780 /*(void) hsm_close();*/ 03781 /*if (config) free(config);*/ 03782 03783 xmlCleanupParser(); 03784 xmlCleanupGlobals(); 03785 xmlCleanupThreads(); 03786 03787 exit(result); 03788 } 03789 03790 03791 /* 03792 * Given a conf.xml location connect to the database contained within it 03793 * 03794 * A lock will be taken out on the DB if it is SQLite; so it is important to release it 03795 * in the calling Fn when we are done with it. 03796 * If backup is set to 1 then a backup will be made (of a sqlite DB file) 03797 * 03798 * Returns 0 if a connection was made. 03799 * 1 if a connection could not be made. 03800 * -1 if any of the config files could not be read/parsed 03801 * 03802 */ 03803 int 03804 db_connect(DB_HANDLE *dbhandle, FILE** lock_fd, int backup) 03805 { 03806 /* what we will read from the file */ 03807 char *dbschema = NULL; 03808 char *host = NULL; 03809 char *port = NULL; 03810 char *user = NULL; 03811 char *password = NULL; 03812 03813 int status; 03814 03815 char* backup_filename = NULL; 03816 char* lock_filename; 03817 03818 /* Read the database details out of conf.xml */ 03819 status = get_db_details(&dbschema, &host, &port, &user, &password); 03820 if (status != 0) { 03821 StrFree(host); 03822 StrFree(port); 03823 StrFree(dbschema); 03824 StrFree(user); 03825 StrFree(password); 03826 return(status); 03827 } 03828 03829 /* If we are in sqlite mode then take a lock out on a file to 03830 prevent multiple access (not sure that we can be sure that sqlite is 03831 safe for multiple processes to access). */ 03832 if (DbFlavour() == SQLITE_DB) { 03833 03834 /* set up lock filename (it may have changed?) */ 03835 if (lock_fd != NULL) { 03836 lock_filename = NULL; 03837 StrAppend(&lock_filename, dbschema); 03838 StrAppend(&lock_filename, ".our_lock"); 03839 03840 *lock_fd = fopen(lock_filename, "w"); 03841 status = get_lite_lock(lock_filename, *lock_fd); 03842 if (status != 0) { 03843 printf("Error getting db lock\n"); 03844 if (*lock_fd != NULL) { 03845 fclose(*lock_fd); 03846 } 03847 StrFree(host); 03848 StrFree(port); 03849 StrFree(dbschema); 03850 StrFree(user); 03851 StrFree(password); 03852 return(1); 03853 } 03854 StrFree(lock_filename); 03855 } 03856 03857 /* Make a backup of the sqlite DB */ 03858 if (backup == 1) { 03859 StrAppend(&backup_filename, dbschema); 03860 StrAppend(&backup_filename, ".backup"); 03861 03862 status = backup_file(dbschema, backup_filename); 03863 03864 StrFree(backup_filename); 03865 03866 if (status == 1) { 03867 if (lock_fd != NULL) { 03868 fclose(*lock_fd); 03869 } 03870 StrFree(host); 03871 StrFree(port); 03872 StrFree(dbschema); 03873 StrFree(user); 03874 StrFree(password); 03875 return(status); 03876 } 03877 } 03878 03879 } 03880 03881 /* Finally we can do what we came here to do, connect to the database */ 03882 status = DbConnect(dbhandle, dbschema, host, password, user, port); 03883 03884 /* Cleanup */ 03885 StrFree(host); 03886 StrFree(port); 03887 StrFree(dbschema); 03888 StrFree(user); 03889 StrFree(password); 03890 03891 return(status); 03892 } 03893 03894 /* 03895 * Release the lock if the DB is SQLite 03896 * 03897 */ 03898 void 03899 db_disconnect(FILE* lock_fd) 03900 { 03901 int status = 0; 03902 03903 if (DbFlavour() == SQLITE_DB) { 03904 if (lock_fd != NULL) { 03905 status = release_lite_lock(lock_fd); 03906 if (status != 0) { 03907 printf("Error releasing db lock"); 03908 /*fclose(lock_fd);*/ 03909 return; 03910 } 03911 fclose(lock_fd); 03912 } 03913 } 03914 return; 03915 } 03916 03917 /* To overcome the potential differences in sqlite compile flags assume that it is not 03918 happy with multiple connections. 03919 03920 The following 2 functions take out a lock and release it 03921 */ 03922 03923 int get_lite_lock(char *lock_filename, FILE* lock_fd) 03924 { 03925 struct flock fl; 03926 struct timeval tv; 03927 03928 if (lock_fd == NULL) { 03929 printf("%s could not be opened\n", lock_filename); 03930 return 1; 03931 } 03932 03933 memset(&fl, 0, sizeof(struct flock)); 03934 fl.l_type = F_WRLCK; 03935 fl.l_whence = SEEK_SET; 03936 fl.l_pid = getpid(); 03937 03938 while (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) { 03939 if (errno == EACCES || errno == EAGAIN) { 03940 printf("%s already locked, sleep\n", lock_filename); 03941 03942 /* sleep for 10 seconds TODO make this configurable? */ 03943 tv.tv_sec = 10; 03944 tv.tv_usec = 0; 03945 select(0, NULL, NULL, NULL, &tv); 03946 03947 } else { 03948 printf("couldn't get lock on %s; %s\n", lock_filename, strerror(errno)); 03949 return 1; 03950 } 03951 } 03952 03953 return 0; 03954 03955 } 03956 03957 int release_lite_lock(FILE* lock_fd) 03958 { 03959 struct flock fl; 03960 03961 if (lock_fd == NULL) { 03962 return 1; 03963 } 03964 03965 memset(&fl, 0, sizeof(struct flock)); 03966 fl.l_type = F_UNLCK; 03967 fl.l_whence = SEEK_SET; 03968 03969 if (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) { 03970 return 1; 03971 } 03972 03973 return 0; 03974 } 03975 03976 /* 03977 * Now we will read the conf.xml file again, but this time we will not validate. 03978 * Instead we just learn the location of the zonelist.xml and kasp.xml files. 03979 */ 03980 int read_filenames(char** zone_list_filename, char** kasp_filename) 03981 { 03982 xmlTextReaderPtr reader = NULL; 03983 xmlDocPtr doc = NULL; 03984 xmlXPathContextPtr xpathCtx = NULL; 03985 xmlXPathObjectPtr xpathObj = NULL; 03986 int ret = 0; /* status of the XML parsing */ 03987 char* tag_name = NULL; 03988 char* temp_char = NULL; 03989 03990 xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile"; 03991 xmlChar *kaspfile_expr = (unsigned char*) "//Common/PolicyFile"; 03992 03993 /* Start reading the file; we will be looking for "Repository" tags */ 03994 reader = xmlNewTextReaderFilename(config); 03995 if (reader != NULL) { 03996 ret = xmlTextReaderRead(reader); 03997 while (ret == 1) { 03998 tag_name = (char*) xmlTextReaderLocalName(reader); 03999 /* Found <Common> */ 04000 if (strncmp(tag_name, "Common", 6) == 0 04001 && xmlTextReaderNodeType(reader) == 1) { 04002 04003 /* Expand this node and get the rest of the info with XPath */ 04004 xmlTextReaderExpand(reader); 04005 doc = xmlTextReaderCurrentDoc(reader); 04006 if (doc == NULL) { 04007 printf("Error: can not read Common section\n"); 04008 /* Don't return? try to parse the rest of the file? */ 04009 ret = xmlTextReaderRead(reader); 04010 continue; 04011 } 04012 04013 xpathCtx = xmlXPathNewContext(doc); 04014 if(xpathCtx == NULL) { 04015 printf("Error: can not create XPath context for Common section\n"); 04016 /* Don't return? try to parse the rest of the file? */ 04017 ret = xmlTextReaderRead(reader); 04018 continue; 04019 } 04020 04021 /* Evaluate xpath expression for ZoneListFile */ 04022 xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx); 04023 if(xpathObj == NULL) { 04024 printf("Error: unable to evaluate xpath expression: %s\n", zonelist_expr); 04025 /* Don't return? try to parse the rest of the file? */ 04026 ret = xmlTextReaderRead(reader); 04027 continue; 04028 } 04029 *zone_list_filename = NULL; 04030 temp_char = (char*) xmlXPathCastToString(xpathObj); 04031 StrAppend(zone_list_filename, temp_char); 04032 StrFree(temp_char); 04033 xmlXPathFreeObject(xpathObj); 04034 printf("zonelist filename set to %s.\n", *zone_list_filename); 04035 04036 /* Evaluate xpath expression for KaspFile */ 04037 xpathObj = xmlXPathEvalExpression(kaspfile_expr, xpathCtx); 04038 xmlXPathFreeContext(xpathCtx); 04039 if(xpathObj == NULL) { 04040 printf("Error: unable to evaluate xpath expression: %s\n", kaspfile_expr); 04041 /* Don't return? try to parse the rest of the file? */ 04042 ret = xmlTextReaderRead(reader); 04043 continue; 04044 } 04045 *kasp_filename = NULL; 04046 if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 04047 /* 04048 * Found Something, set it 04049 */ 04050 temp_char = (char*) xmlXPathCastToString(xpathObj); 04051 StrAppend(kasp_filename, temp_char); 04052 StrFree(temp_char); 04053 } else { 04054 /* 04055 * Set a default 04056 */ 04057 /* XXX this should be parse from the the main config */ 04058 StrAppend(kasp_filename, OPENDNSSEC_CONFIG_DIR); 04059 StrAppend(kasp_filename, "/kasp.xml"); 04060 } 04061 printf("kasp filename set to %s.\n", *kasp_filename); 04062 04063 xmlXPathFreeObject(xpathObj); 04064 } 04065 /* Read the next line */ 04066 ret = xmlTextReaderRead(reader); 04067 04068 StrFree(tag_name); 04069 } 04070 xmlFreeTextReader(reader); 04071 if (ret != 0) { 04072 printf("%s : failed to parse\n", config); 04073 return(1); 04074 } 04075 } else { 04076 printf("Unable to open %s\n", config); 04077 return(1); 04078 } 04079 if (doc) { 04080 xmlFreeDoc(doc); 04081 } 04082 04083 return 0; 04084 } 04085 04086 /* 04087 * Read the conf.xml file yet again, but this time we will not validate. 04088 * Instead we just extract the RepositoryList into the database. 04089 */ 04090 int update_repositories() 04091 { 04092 int status = 0; 04093 xmlDocPtr doc = NULL; 04094 xmlXPathContextPtr xpathCtx = NULL; 04095 xmlXPathObjectPtr xpathObj = NULL; 04096 xmlNode *curNode; 04097 char* repo_name = NULL; 04098 char* repo_capacity = NULL; 04099 int require_backup = 0; 04100 int i = 0; 04101 04102 xmlChar *node_expr = (unsigned char*) "//Configuration/RepositoryList/Repository"; 04103 04104 /* Start reading the file; we will be looking for "Repository" tags */ 04105 /* Load XML document */ 04106 doc = xmlParseFile(config); 04107 if (doc == NULL) { 04108 printf("Unable to open %s\n", config); 04109 return(1); 04110 } 04111 04112 /* Create xpath evaluation context */ 04113 xpathCtx = xmlXPathNewContext(doc); 04114 if(xpathCtx == NULL) { 04115 xmlFreeDoc(doc); 04116 return(1); 04117 } 04118 04119 /* Evaluate xpath expression */ 04120 xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx); 04121 if(xpathObj == NULL) { 04122 xmlXPathFreeContext(xpathCtx); 04123 xmlFreeDoc(doc); 04124 return(1); 04125 } 04126 04127 if (xpathObj->nodesetval) { 04128 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) { 04129 04130 require_backup = 0; 04131 StrAppend(&repo_capacity, ""); 04132 04133 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 04134 repo_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], 04135 (const xmlChar *)"name"); 04136 while (curNode) { 04137 if (xmlStrEqual(curNode->name, (const xmlChar *)"Capacity")) { 04138 repo_capacity = (char *) xmlNodeGetContent(curNode); 04139 } 04140 if (xmlStrEqual(curNode->name, (const xmlChar *)"RequireBackup")) { 04141 require_backup = 1; 04142 } 04143 04144 curNode = curNode->next; 04145 } 04146 04147 if (strlen(repo_name) != 0) { 04148 /* Log what we are about to do */ 04149 printf("Repository %s found\n", repo_name); 04150 if (strlen(repo_capacity) == 0) { 04151 printf("No Maximum Capacity set.\n"); 04152 /* 04153 * We have all the information, update/insert this repository 04154 */ 04155 status = KsmImportRepository(repo_name, "0", require_backup); 04156 } else { 04157 printf("Capacity set to %s.\n", repo_capacity); 04158 /* 04159 * We have all the information, update/insert this repository 04160 */ 04161 status = KsmImportRepository(repo_name, repo_capacity, require_backup); 04162 } 04163 if (require_backup == 0) { 04164 printf("RequireBackup NOT set; please make sure that you know the potential problems of using keys which are not recoverable\n"); 04165 } else { 04166 printf("RequireBackup set.\n"); 04167 } 04168 04169 if (status != 0) { 04170 printf("Error Importing Repository %s", repo_name); 04171 /* Don't return? try to parse the rest of the zones? */ 04172 } 04173 } else { 04174 printf("WARNING: Repository found with NULL name, skipping...\n"); 04175 } 04176 StrFree(repo_name); 04177 StrFree(repo_capacity); 04178 } 04179 } 04180 04181 if (xpathObj) { 04182 xmlXPathFreeObject(xpathObj); 04183 } 04184 if (xpathCtx) { 04185 xmlXPathFreeContext(xpathCtx); 04186 } 04187 if (doc) { 04188 xmlFreeDoc(doc); 04189 } 04190 04191 return 0; 04192 } 04193 04194 /* Read kasp.xml, validate it and grab each policy in it as we go. */ 04195 int update_policies(char* kasp_filename) 04196 { 04197 int status; 04198 04199 /* what we will read from the file */ 04200 char *policy_name = NULL; 04201 char *policy_description = NULL; 04202 04203 /* All of the XML stuff */ 04204 xmlDocPtr doc = NULL; 04205 xmlDocPtr pol_doc = NULL; 04206 xmlDocPtr rngdoc = NULL; 04207 xmlNode *curNode; 04208 xmlNode *childNode; 04209 xmlNode *childNode2; 04210 xmlNode *childNode3; 04211 xmlChar *opt_out_flag = (xmlChar *)"N"; 04212 xmlChar *share_keys_flag = (xmlChar *)"N"; 04213 xmlChar *man_roll_flag = (xmlChar *)"N"; 04214 xmlChar *rfc5011_flag = (xmlChar *)"N"; 04215 int standby_keys_flag = 0; 04216 xmlXPathContextPtr xpathCtx = NULL; 04217 xmlXPathObjectPtr xpathObj = NULL; 04218 xmlRelaxNGParserCtxtPtr rngpctx = NULL; 04219 xmlRelaxNGValidCtxtPtr rngctx = NULL; 04220 xmlRelaxNGPtr schema = NULL; 04221 int i = 0; 04222 04223 xmlChar *node_expr = (unsigned char*) "//Policy"; 04224 04225 04226 /* xmlChar *audit_expr = (unsigned char*) "//Policy/Audit"; */ 04227 int audit_found = 0; /* flag to say whether an Audit flag was found or not */ 04228 04229 KSM_POLICY *policy; 04230 04231 /* Some files, the xml and rng */ 04232 const char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/kasp.rng"; 04233 char* kaspcheck_cmd = NULL; 04234 char* kaspcheck_cmd_version = NULL; 04235 04236 StrAppend(&kaspcheck_cmd, ODS_AU_KASPCHECK); 04237 StrAppend(&kaspcheck_cmd, " -c "); 04238 StrAppend(&kaspcheck_cmd, config); 04239 04240 StrAppend(&kaspcheck_cmd_version, ODS_AU_KASPCHECK); 04241 StrAppend(&kaspcheck_cmd_version, " -v > /dev/null"); 04242 04243 /* Run kaspcheck */ 04244 status = system(kaspcheck_cmd_version); 04245 if (status == 0) 04246 { 04247 status = system(kaspcheck_cmd); 04248 if (status != 0) 04249 { 04250 fprintf(stderr, "ods-kaspcheck returned an error, please check your policy\n"); 04251 StrFree(kaspcheck_cmd); 04252 StrFree(kaspcheck_cmd_version); 04253 return(-1); 04254 } 04255 } 04256 else 04257 { 04258 fprintf(stderr, "Couldn't run ods-kaspcheck (Auditor is not installed), will carry on\n"); 04259 } 04260 04261 StrFree(kaspcheck_cmd); 04262 StrFree(kaspcheck_cmd_version); 04263 04264 /* Load XML document */ 04265 doc = xmlParseFile(kasp_filename); 04266 if (doc == NULL) { 04267 printf("Error: unable to parse file \"%s\"\n", kasp_filename); 04268 return(-1); 04269 } 04270 04271 /* Load rng document: TODO make the rng stuff optional? */ 04272 rngdoc = xmlParseFile(rngfilename); 04273 if (rngdoc == NULL) { 04274 printf("Error: unable to parse file \"%s\"\n", rngfilename); 04275 return(-1); 04276 } 04277 04278 /* Create an XML RelaxNGs parser context for the relax-ng document. */ 04279 rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc); 04280 if (rngpctx == NULL) { 04281 printf("Error: unable to create XML RelaxNGs parser context\n"); 04282 return(-1); 04283 } 04284 04285 /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */ 04286 schema = xmlRelaxNGParse(rngpctx); 04287 if (schema == NULL) { 04288 printf("Error: unable to parse a schema definition resource\n"); 04289 return(-1); 04290 } 04291 04292 /* Create an XML RelaxNGs validation context based on the given schema */ 04293 rngctx = xmlRelaxNGNewValidCtxt(schema); 04294 if (rngctx == NULL) { 04295 printf("Error: unable to create RelaxNGs validation context based on the schema\n"); 04296 return(-1); 04297 } 04298 04299 /* Validate a document tree in memory. */ 04300 status = xmlRelaxNGValidateDoc(rngctx,doc); 04301 if (status != 0) { 04302 printf("Error validating file \"%s\"\n", kasp_filename); 04303 return(-1); 04304 } 04305 04306 /* Allocate some space for our policy */ 04307 policy = KsmPolicyAlloc(); 04308 if (policy == NULL) { 04309 printf("Malloc for policy struct failed"); 04310 exit(1); 04311 } 04312 04313 /* Create xpath evaluation context */ 04314 xpathCtx = xmlXPathNewContext(doc); 04315 if(xpathCtx == NULL) { 04316 xmlFreeDoc(doc); 04317 KsmPolicyFree(policy); 04318 return(1); 04319 } 04320 04321 /* Evaluate xpath expression */ 04322 xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx); 04323 if(xpathObj == NULL) { 04324 xmlXPathFreeContext(xpathCtx); 04325 xmlFreeDoc(doc); 04326 KsmPolicyFree(policy); 04327 return(1); 04328 } 04329 04330 if (xpathObj->nodesetval) { 04331 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) { 04332 04333 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 04334 policy_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], (const xmlChar *)"name"); 04335 if (strlen(policy_name) == 0) { 04336 /* error */ 04337 printf("Error extracting policy name from %s\n", kasp_filename); 04338 break; 04339 } 04340 audit_found = 0; 04341 04342 printf("Policy %s found\n", policy_name); 04343 while (curNode) { 04344 if (xmlStrEqual(curNode->name, (const xmlChar *)"Description")) { 04345 policy_description = (char *) xmlNodeGetContent(curNode); 04346 04347 /* Insert or update this policy with the description found, 04348 we will need the policy_id too */ 04349 SetPolicyDefaults(policy, policy_name); 04350 status = KsmPolicyExists(policy_name); 04351 if (status == 0) { 04352 /* Policy exists; we will be updating it */ 04353 status = KsmPolicyRead(policy); 04354 if(status != 0) { 04355 printf("Error: unable to read policy %s; skipping\n", policy_name); 04356 curNode = curNode->next; 04357 break; 04358 } 04359 /* TODO Set description here ? */ 04360 } 04361 else { 04362 /* New policy, insert it and get the new policy_id */ 04363 status = KsmImportPolicy(policy_name, policy_description); 04364 if(status != 0) { 04365 printf("Error: unable to insert policy %s; skipping\n", policy_name); 04366 /* Don't return? try to parse the rest of the file? */ 04367 continue; 04368 } 04369 status = KsmPolicySetIdFromName(policy); 04370 04371 if (status != 0) { 04372 printf("Error: unable to get policy id for %s; skipping\n", policy_name); 04373 continue; 04374 } 04375 } 04376 } 04377 /* SIGNATURES */ 04378 else if (xmlStrEqual(curNode->name, (const xmlChar *)"Signatures")) { 04379 childNode = curNode->children; 04380 while (childNode){ 04381 if (xmlStrEqual(childNode->name, (const xmlChar *)"Resign")) { 04382 SetParamOnPolicy(xmlNodeGetContent(childNode), "resign", "signature", policy->signature->resign, policy->id, DURATION_TYPE); 04383 } 04384 else if (xmlStrEqual(childNode->name, (const xmlChar *)"Refresh")) { 04385 SetParamOnPolicy(xmlNodeGetContent(childNode), "refresh", "signature", policy->signer->refresh, policy->id, DURATION_TYPE); 04386 } 04387 else if (xmlStrEqual(childNode->name, (const xmlChar *)"Validity")) { 04388 childNode2 = childNode->children; 04389 while (childNode2){ 04390 if (xmlStrEqual(childNode2->name, (const xmlChar *)"Default")) { 04391 SetParamOnPolicy(xmlNodeGetContent(childNode2), "valdefault", "signature", policy->signature->valdefault, policy->id, DURATION_TYPE); 04392 } 04393 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Denial")) { 04394 SetParamOnPolicy(xmlNodeGetContent(childNode2), "valdenial", "signature", policy->signature->valdenial, policy->id, DURATION_TYPE); 04395 } 04396 childNode2 = childNode2->next; 04397 } 04398 } 04399 else if (xmlStrEqual(childNode->name, (const xmlChar *)"Jitter")) { 04400 SetParamOnPolicy(xmlNodeGetContent(childNode), "jitter", "signature", policy->signer->jitter, policy->id, DURATION_TYPE); 04401 } 04402 else if (xmlStrEqual(childNode->name, (const xmlChar *)"InceptionOffset")) { 04403 SetParamOnPolicy(xmlNodeGetContent(childNode), "clockskew", "signature", policy->signature->clockskew, policy->id, DURATION_TYPE); 04404 } 04405 childNode = childNode->next; 04406 } 04407 } /* End of Signatures */ 04408 else if (xmlStrEqual(curNode->name, (const xmlChar *)"Denial")) { 04409 opt_out_flag = (xmlChar *)"N"; 04410 childNode = curNode->children; 04411 while (childNode){ 04412 if (xmlStrEqual(childNode->name, (const xmlChar *)"NSEC3")) { 04413 /* NSEC3 */ 04414 status = KsmParameterSet("version", "denial", 3, policy->id); 04415 if (status != 0) { 04416 printf("Error: unable to insert/update %s for policy\n", "Denial version"); 04417 } 04418 childNode2 = childNode->children; 04419 while (childNode2){ 04420 if (xmlStrEqual(childNode2->name, (const xmlChar *)"OptOut")) { 04421 opt_out_flag = (xmlChar *)"Y"; 04422 } 04423 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Resalt")) { 04424 SetParamOnPolicy(xmlNodeGetContent(childNode2), "resalt", "denial", policy->denial->resalt, policy->id, DURATION_TYPE); 04425 } 04426 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Hash")) { 04427 childNode3 = childNode2->children; 04428 while (childNode3){ 04429 if (xmlStrEqual(childNode3->name, (const xmlChar *)"Algorithm")) { 04430 SetParamOnPolicy(xmlNodeGetContent(childNode3), "algorithm", "denial", policy->denial->algorithm, policy->id, INT_TYPE); 04431 } 04432 else if (xmlStrEqual(childNode3->name, (const xmlChar *)"Iterations")) { 04433 SetParamOnPolicy(xmlNodeGetContent(childNode3), "iterations", "denial", policy->denial->iteration, policy->id, INT_TYPE); 04434 } 04435 else if (xmlStrEqual(childNode3->name, (const xmlChar *)"Salt")) { 04436 SetParamOnPolicy(xmlGetProp(childNode3, (const xmlChar *)"length"), "saltlength", "denial", policy->denial->saltlength, policy->id, INT_TYPE); 04437 } 04438 childNode3 = childNode3->next; 04439 } 04440 } 04441 04442 childNode2 = childNode2->next; 04443 } 04444 /* Set things that we flagged */ 04445 SetParamOnPolicy(opt_out_flag, "optout", "denial", policy->denial->optout, policy->id, BOOL_TYPE); 04446 } /* End of NSEC3 */ 04447 else if (xmlStrEqual(childNode->name, (const xmlChar *)"NSEC")) { 04448 status = KsmParameterSet("version", "denial", 1, policy->id); 04449 if (status != 0) { 04450 printf("Error: unable to insert/update %s for policy\n", "Denial version"); 04451 } 04452 } 04453 childNode = childNode->next; 04454 } 04455 } /* End of Denial */ 04456 else if (xmlStrEqual(curNode->name, (const xmlChar *)"Keys")) { 04457 share_keys_flag = (xmlChar *)"N"; 04458 childNode = curNode->children; 04459 while (childNode){ 04460 if (xmlStrEqual(childNode->name, (const xmlChar *)"TTL")) { 04461 SetParamOnPolicy(xmlNodeGetContent(childNode), "ttl", "keys", policy->keys->ttl, policy->id, DURATION_TYPE); 04462 } 04463 else if (xmlStrEqual(childNode->name, (const xmlChar *)"RetireSafety")) { 04464 SetParamOnPolicy(xmlNodeGetContent(childNode), "retiresafety", "keys", policy->keys->retire_safety, policy->id, DURATION_TYPE); 04465 } 04466 else if (xmlStrEqual(childNode->name, (const xmlChar *)"PublishSafety")) { 04467 SetParamOnPolicy(xmlNodeGetContent(childNode), "publishsafety", "keys", policy->keys->publish_safety, policy->id, DURATION_TYPE); 04468 } 04469 else if (xmlStrEqual(childNode->name, (const xmlChar *)"ShareKeys")) { 04470 share_keys_flag = (xmlChar *)"Y"; 04471 } 04472 else if (xmlStrEqual(childNode->name, (const xmlChar *)"Purge")) { 04473 SetParamOnPolicy(xmlNodeGetContent(childNode), "purge", "keys", policy->keys->purge, policy->id, DURATION_TYPE); 04474 } 04475 /* KSK */ 04476 else if (xmlStrEqual(childNode->name, (const xmlChar *)"KSK")) { 04477 man_roll_flag = (xmlChar *)"N"; 04478 rfc5011_flag = (xmlChar *)"N"; 04479 childNode2 = childNode->children; 04480 while (childNode2){ 04481 if (xmlStrEqual(childNode2->name, (const xmlChar *)"Algorithm")) { 04482 SetParamOnPolicy(xmlNodeGetContent(childNode2), "algorithm", "ksk", policy->ksk->algorithm, policy->id, INT_TYPE); 04483 SetParamOnPolicy(xmlGetProp(childNode2, (const xmlChar *)"length"), "bits", "ksk", policy->ksk->bits, policy->id, INT_TYPE); 04484 04485 } 04486 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Lifetime")) { 04487 SetParamOnPolicy(xmlNodeGetContent(childNode2), "lifetime", "ksk", policy->ksk->lifetime, policy->id, DURATION_TYPE); 04488 } 04489 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Repository")) { 04490 if (SetParamOnPolicy(xmlNodeGetContent(childNode2), "repository", "ksk", policy->ksk->sm, policy->id, REPO_TYPE) != 0) { 04491 printf("Please either add the repository to conf.xml or remove the reference to it from kasp.xml\n"); 04492 /* return the error, we do not want to continue */ 04493 xmlFreeDoc(pol_doc); 04494 xmlXPathFreeContext(xpathCtx); 04495 xmlRelaxNGFree(schema); 04496 xmlRelaxNGFreeValidCtxt(rngctx); 04497 xmlRelaxNGFreeParserCtxt(rngpctx); 04498 xmlFreeDoc(doc); 04499 xmlFreeDoc(rngdoc); 04500 KsmPolicyFree(policy); 04501 04502 return(1); 04503 } 04504 } 04505 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Standby")) { 04506 SetParamOnPolicy(xmlNodeGetContent(childNode2), "standby", "ksk", policy->ksk->standby_keys, policy->id, INT_TYPE); 04507 standby_keys_flag = 1; 04508 } 04509 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"ManualRollover")) { 04510 man_roll_flag = (xmlChar *)"Y"; 04511 } 04512 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"RFC5011")) { 04513 rfc5011_flag = (xmlChar *)"Y"; 04514 } 04515 /*else if (xmlStrEqual(childNode2->name, (const xmlChar *)"RolloverScheme")) { 04516 SetParamOnPolicy(xmlNodeGetContent(childNode2), "rollover_scheme", "ksk", policy->ksk->rollover_scheme, policy->id, ROLLOVER_TYPE); 04517 }*/ 04518 childNode2 = childNode2->next; 04519 } 04520 /* Set things that we flagged */ 04521 SetParamOnPolicy(man_roll_flag, "manual_rollover", "ksk", policy->ksk->manual_rollover, policy->id, BOOL_TYPE); 04522 SetParamOnPolicy(rfc5011_flag, "rfc5011", "ksk", policy->ksk->rfc5011, policy->id, BOOL_TYPE); 04523 if (standby_keys_flag == 0) { 04524 SetParamOnPolicy((xmlChar *)"0", "standby", "ksk", policy->ksk->standby_keys, policy->id, INT_TYPE_NO_FREE); 04525 } else { 04526 standby_keys_flag = 0; 04527 } 04528 } /* End of KSK */ 04529 /* ZSK */ 04530 else if (xmlStrEqual(childNode->name, (const xmlChar *)"ZSK")) { 04531 man_roll_flag = (xmlChar *)"N"; 04532 childNode2 = childNode->children; 04533 while (childNode2){ 04534 if (xmlStrEqual(childNode2->name, (const xmlChar *)"Algorithm")) { 04535 SetParamOnPolicy(xmlNodeGetContent(childNode2), "algorithm", "zsk", policy->zsk->algorithm, policy->id, INT_TYPE); 04536 SetParamOnPolicy(xmlGetProp(childNode2, (const xmlChar *)"length"), "bits", "zsk", policy->zsk->bits, policy->id, INT_TYPE); 04537 04538 } 04539 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Lifetime")) { 04540 SetParamOnPolicy(xmlNodeGetContent(childNode2), "lifetime", "zsk", policy->zsk->lifetime, policy->id, DURATION_TYPE); 04541 } 04542 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Repository")) { 04543 if (SetParamOnPolicy(xmlNodeGetContent(childNode2), "repository", "zsk", policy->zsk->sm, policy->id, REPO_TYPE) != 0) { 04544 printf("Please either add the repository to conf.xml or remove the reference to it from kasp.xml\n"); 04545 /* return the error, we do not want to continue */ 04546 xmlFreeDoc(pol_doc); 04547 xmlXPathFreeContext(xpathCtx); 04548 xmlRelaxNGFree(schema); 04549 xmlRelaxNGFreeValidCtxt(rngctx); 04550 xmlRelaxNGFreeParserCtxt(rngpctx); 04551 xmlFreeDoc(doc); 04552 xmlFreeDoc(rngdoc); 04553 KsmPolicyFree(policy); 04554 04555 return(1); 04556 } 04557 } 04558 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Standby")) { 04559 SetParamOnPolicy(xmlNodeGetContent(childNode2), "standby", "zsk", policy->zsk->standby_keys, policy->id, INT_TYPE); 04560 standby_keys_flag = 1; 04561 } 04562 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"ManualRollover")) { 04563 man_roll_flag = (xmlChar *)"Y"; 04564 } 04565 childNode2 = childNode2->next; 04566 } 04567 /* Set things that we flagged */ 04568 SetParamOnPolicy(man_roll_flag, "manual_rollover", "zsk", policy->zsk->manual_rollover, policy->id, BOOL_TYPE); 04569 } /* End of ZSK */ 04570 04571 childNode = childNode->next; 04572 } 04573 /* Set things that we flagged */ 04574 SetParamOnPolicy(share_keys_flag, "zones_share_keys", "keys", policy->keys->share_keys, policy->id, BOOL_TYPE); 04575 if (standby_keys_flag == 0) { 04576 SetParamOnPolicy((xmlChar *)"0", "standby", "zsk", policy->zsk->standby_keys, policy->id, INT_TYPE_NO_FREE); 04577 } else { 04578 standby_keys_flag = 0; 04579 } 04580 04581 } /* End of Keys */ 04582 /* Zone */ 04583 else if (xmlStrEqual(curNode->name, (const xmlChar *)"Zone")) { 04584 childNode = curNode->children; 04585 while (childNode){ 04586 if (xmlStrEqual(childNode->name, (const xmlChar *)"PropagationDelay")) { 04587 SetParamOnPolicy(xmlNodeGetContent(childNode), "propagationdelay", "zone", policy->zone->propdelay, policy->id, DURATION_TYPE); 04588 } 04589 else if (xmlStrEqual(childNode->name, (const xmlChar *)"SOA")) { 04590 childNode2 = childNode->children; 04591 while (childNode2){ 04592 if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) { 04593 SetParamOnPolicy(xmlNodeGetContent(childNode2), "ttl", "zone", policy->zone->soa_ttl, policy->id, DURATION_TYPE); 04594 } 04595 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Minimum")) { 04596 SetParamOnPolicy(xmlNodeGetContent(childNode2), "min", "zone", policy->zone->soa_min, policy->id, DURATION_TYPE); 04597 } 04598 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Serial")) { 04599 SetParamOnPolicy(xmlNodeGetContent(childNode2), "serial", "zone", policy->zone->serial, policy->id, SERIAL_TYPE); 04600 } 04601 childNode2 = childNode2->next; 04602 } 04603 } 04604 childNode = childNode->next; 04605 } 04606 } /* End of Zone */ 04607 /* Parent */ 04608 else if (xmlStrEqual(curNode->name, (const xmlChar *)"Parent")) { 04609 childNode = curNode->children; 04610 while (childNode){ 04611 if (xmlStrEqual(childNode->name, (const xmlChar *)"PropagationDelay")) { 04612 SetParamOnPolicy(xmlNodeGetContent(childNode), "propagationdelay", "parent", policy->parent->propdelay, policy->id, DURATION_TYPE); 04613 } 04614 else if (xmlStrEqual(childNode->name, (const xmlChar *)"DS")) { 04615 childNode2 = childNode->children; 04616 while (childNode2){ 04617 if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) { 04618 SetParamOnPolicy(xmlNodeGetContent(childNode2), "ttlds", "parent", policy->parent->ds_ttl, policy->id, DURATION_TYPE); 04619 } 04620 childNode2 = childNode2->next; 04621 } 04622 } 04623 else if (xmlStrEqual(childNode->name, (const xmlChar *)"SOA")) { 04624 childNode2 = childNode->children; 04625 while (childNode2){ 04626 if (xmlStrEqual(childNode2->name, (const xmlChar *)"TTL")) { 04627 SetParamOnPolicy(xmlNodeGetContent(childNode2), "ttl", "parent", policy->parent->soa_ttl, policy->id, DURATION_TYPE); 04628 } 04629 else if (xmlStrEqual(childNode2->name, (const xmlChar *)"Minimum")) { 04630 SetParamOnPolicy(xmlNodeGetContent(childNode2), "min", "parent", policy->parent->soa_min, policy->id, DURATION_TYPE); 04631 } 04632 childNode2 = childNode2->next; 04633 } 04634 } 04635 childNode = childNode->next; 04636 } 04637 } /* End of Parent */ 04638 /* Audit */ 04639 else if (xmlStrEqual(curNode->name, (const xmlChar *)"Audit")) { 04640 status = KsmImportAudit(policy->id, ""); 04641 childNode = curNode->children; 04642 while (childNode){ 04643 if (xmlStrEqual(childNode->name, (const xmlChar *)"Partial")) { 04644 status = KsmImportAudit(policy->id, "<Partial/>"); 04645 } 04646 childNode = childNode->next; 04647 } 04648 audit_found = 1; 04649 if(status != 0) { 04650 printf("Error: unable to insert Audit info for policy %s\n", policy->name); 04651 } 04652 } 04653 04654 curNode = curNode->next; 04655 } 04656 /* Indicate in the database if we didn't find an audit tag */ 04657 if (audit_found == 0) { 04658 status = KsmImportAudit(policy->id, "NULL"); 04659 } 04660 04661 /* Free up some stuff that we don't need any more */ 04662 StrFree(policy_name); 04663 StrFree(policy_description); 04664 04665 } /* End of <Policy> */ 04666 } 04667 04668 /* Cleanup */ 04669 xmlXPathFreeContext(xpathCtx); 04670 xmlRelaxNGFree(schema); 04671 xmlRelaxNGFreeValidCtxt(rngctx); 04672 xmlRelaxNGFreeParserCtxt(rngpctx); 04673 xmlFreeDoc(doc); 04674 xmlFreeDoc(rngdoc); 04675 KsmPolicyFree(policy); 04676 04677 return(status); 04678 } 04679 04680 /* Read zonelist (as passed in) and insert/update any zones seen */ 04681 int update_zones(char* zone_list_filename) 04682 { 04683 int status = 0; 04684 xmlTextReaderPtr reader = NULL; 04685 xmlDocPtr doc = NULL; 04686 xmlXPathContextPtr xpathCtx = NULL; 04687 xmlXPathObjectPtr xpathObj = NULL; 04688 int ret = 0; /* status of the XML parsing */ 04689 char* zone_name = NULL; 04690 char* policy_name = NULL; 04691 char* current_policy = NULL; 04692 char* current_signconf = NULL; 04693 char* current_input = NULL; 04694 char* current_output = NULL; 04695 char* temp_char = NULL; 04696 char* tag_name = NULL; 04697 int policy_id = 0; 04698 int new_zone = 0; /* flag to say if the zone is new or not */ 04699 int file_zone_count = 0; /* As a quick check we will compare the number of */ 04700 int db_zone_count = 0; /* zones in the file to the number in the database */ 04701 int* zone_ids; /* List of zone_ids seen from zonelist.xml */ 04702 int temp_id; 04703 04704 char* sql = NULL; 04705 DB_RESULT result; /* Result of the query */ 04706 DB_RESULT result2; /* Result of the query */ 04707 DB_RESULT result3; /* Result of the query */ 04708 DB_ROW row = NULL; /* Row data */ 04709 KSM_PARAMETER shared; /* Parameter information */ 04710 int seen_zone = 0; 04711 int temp_count = 0; 04712 int i = 0; 04713 04714 xmlChar *name_expr = (unsigned char*) "name"; 04715 xmlChar *policy_expr = (unsigned char*) "//Zone/Policy"; 04716 xmlChar *signconf_expr = (unsigned char*) "//Zone/SignerConfiguration"; 04717 xmlChar *input_expr = (unsigned char*) "//Zone/Adapters/Input/File"; 04718 xmlChar *output_expr = (unsigned char*) "//Zone/Adapters/Output/File"; 04719 04720 /* TODO validate the file ? */ 04721 /* Read through the file counting zones TODO better way to do this? */ 04722 reader = xmlNewTextReaderFilename(zone_list_filename); 04723 if (reader != NULL) { 04724 ret = xmlTextReaderRead(reader); 04725 while (ret == 1) { 04726 tag_name = (char*) xmlTextReaderLocalName(reader); 04727 /* Found <Zone> */ 04728 if (strncmp(tag_name, "Zone", 4) == 0 04729 && strncmp(tag_name, "ZoneList", 8) != 0 04730 && xmlTextReaderNodeType(reader) == 1) { 04731 file_zone_count++; 04732 } 04733 /* Read the next line */ 04734 ret = xmlTextReaderRead(reader); 04735 StrFree(tag_name); 04736 } 04737 xmlFreeTextReader(reader); 04738 if (ret != 0) { 04739 printf("%s : failed to parse\n", zone_list_filename); 04740 } 04741 } else { 04742 printf("Unable to open %s\n", zone_list_filename); 04743 } 04744 04745 /* Allocate space for the list of zone IDs */ 04746 zone_ids = MemMalloc(file_zone_count * sizeof(int)); 04747 04748 /* Start reading the file; we will be looking for "Zone" tags */ 04749 reader = xmlNewTextReaderFilename(zone_list_filename); 04750 if (reader != NULL) { 04751 ret = xmlTextReaderRead(reader); 04752 while (ret == 1) { 04753 tag_name = (char*) xmlTextReaderLocalName(reader); 04754 /* Found <Zone> */ 04755 if (strncmp(tag_name, "Zone", 4) == 0 04756 && strncmp(tag_name, "ZoneList", 8) != 0 04757 && xmlTextReaderNodeType(reader) == 1) { 04758 /* Get the repository name */ 04759 zone_name = NULL; 04760 temp_char = (char*) xmlTextReaderGetAttribute(reader, name_expr); 04761 StrAppend(&zone_name, temp_char); 04762 StrFree(temp_char); 04763 04764 /* 04765 It is tempting to remove the trailing dot here; however I am 04766 not sure that it is the right thing to do... It trashed my 04767 test setup by deleting the zone sion. and replacing it with 04768 sion (but of course none of the keys were moved). I think 04769 that allowing people to edit zonelist.xml means that we must 04770 allow them to add the td if they want to. 04771 */ 04772 04773 /* Make sure that we got something */ 04774 if (zone_name == NULL) { 04775 /* error */ 04776 printf("Error extracting zone name from %s\n", zone_list_filename); 04777 /* Don't return? try to parse the rest of the file? */ 04778 ret = xmlTextReaderRead(reader); 04779 continue; 04780 } 04781 04782 printf("Zone %s found\n", zone_name); 04783 04784 /* Expand this node and get the rest of the info with XPath */ 04785 xmlTextReaderExpand(reader); 04786 doc = xmlTextReaderCurrentDoc(reader); 04787 if (doc == NULL) { 04788 printf("Error: can not read zone \"%s\"; skipping\n", zone_name); 04789 /* Don't return? try to parse the rest of the zones? */ 04790 ret = xmlTextReaderRead(reader); 04791 continue; 04792 } 04793 04794 xpathCtx = xmlXPathNewContext(doc); 04795 if(xpathCtx == NULL) { 04796 printf("Error: can not create XPath context for \"%s\"; skipping zone\n", zone_name); 04797 /* Don't return? try to parse the rest of the zones? */ 04798 ret = xmlTextReaderRead(reader); 04799 continue; 04800 } 04801 04802 /* Extract the Policy name for this zone */ 04803 /* Evaluate xpath expression for policy */ 04804 xpathObj = xmlXPathEvalExpression(policy_expr, xpathCtx); 04805 if(xpathObj == NULL) { 04806 printf("Error: unable to evaluate xpath expression: %s; skipping zone\n", policy_expr); 04807 /* Don't return? try to parse the rest of the zones? */ 04808 ret = xmlTextReaderRead(reader); 04809 continue; 04810 } 04811 04812 current_policy = NULL; 04813 temp_char = (char *)xmlXPathCastToString(xpathObj); 04814 StrAppend(¤t_policy, temp_char); 04815 StrFree(temp_char); 04816 printf("Policy set to %s.\n", current_policy); 04817 xmlXPathFreeObject(xpathObj); 04818 04819 /* If we have a different policy to last time get its ID */ 04820 if (policy_name == NULL || strcmp(current_policy, policy_name) != 0) { 04821 StrFree(policy_name); 04822 StrAppend(&policy_name, current_policy); 04823 04824 status = KsmPolicyIdFromName(policy_name, &policy_id); 04825 if (status != 0) { 04826 printf("Error, can't find policy : %s\n", policy_name); 04827 /* Don't return? try to parse the rest of the zones? */ 04828 ret = xmlTextReaderRead(reader); 04829 continue; 04830 } 04831 } 04832 04833 /* Extract the Signconf name for this zone */ 04834 /* Evaluate xpath expression */ 04835 xpathObj = xmlXPathEvalExpression(signconf_expr, xpathCtx); 04836 if(xpathObj == NULL) { 04837 printf("Error: unable to evaluate xpath expression: %s; skipping zone\n", signconf_expr); 04838 /* Don't return? try to parse the rest of the zones? */ 04839 ret = xmlTextReaderRead(reader); 04840 continue; 04841 } 04842 04843 current_signconf = NULL; 04844 temp_char = (char *)xmlXPathCastToString(xpathObj); 04845 StrAppend(¤t_signconf, temp_char); 04846 StrFree(temp_char); 04847 xmlXPathFreeObject(xpathObj); 04848 04849 /* Extract the Input name for this zone */ 04850 /* Evaluate xpath expression */ 04851 xpathObj = xmlXPathEvalExpression(input_expr, xpathCtx); 04852 if(xpathObj == NULL) { 04853 printf("Error: unable to evaluate xpath expression: %s; skipping zone\n", input_expr); 04854 /* Don't return? try to parse the rest of the zones? */ 04855 ret = xmlTextReaderRead(reader); 04856 continue; 04857 } 04858 04859 current_input = NULL; 04860 temp_char = (char *)xmlXPathCastToString(xpathObj); 04861 StrAppend(¤t_input, temp_char); 04862 StrFree(temp_char); 04863 xmlXPathFreeObject(xpathObj); 04864 04865 /* Extract the Output name for this zone */ 04866 /* Evaluate xpath expression */ 04867 xpathObj = xmlXPathEvalExpression(output_expr, xpathCtx); 04868 xmlXPathFreeContext(xpathCtx); 04869 if(xpathObj == NULL) { 04870 printf("Error: unable to evaluate xpath expression: %s; skipping zone\n", output_expr); 04871 /* Don't return? try to parse the rest of the zones? */ 04872 ret = xmlTextReaderRead(reader); 04873 continue; 04874 } 04875 04876 current_output = NULL; 04877 temp_char = (char *)xmlXPathCastToString(xpathObj); 04878 StrAppend(¤t_output, temp_char); 04879 StrFree(temp_char); 04880 xmlXPathFreeObject(xpathObj); 04881 04882 /* 04883 * Now we have all the information update/insert this repository 04884 */ 04885 status = KsmImportZone(zone_name, policy_id, 0, &new_zone, current_signconf, current_input, current_output); 04886 if (status != 0) { 04887 if (status == -3) { 04888 printf("Error Importing zone %s; it already exists both with and without a trailing dot\n", zone_name); 04889 } else { 04890 printf("Error Importing Zone %s\n", zone_name); 04891 } 04892 /* Don't return? try to parse the rest of the zones? */ 04893 ret = xmlTextReaderRead(reader); 04894 continue; 04895 } 04896 04897 /* If need be link existing keys to zone */ 04898 if (new_zone == 1) { 04899 printf("Added zone %s to database\n", zone_name); 04900 /* WITH NEW KEYSHARING LEAVE THIS TO THE ENFORCER TODO - CHECK THIS IS RIGHT */ 04901 /* 04902 status = KsmLinkKeys(zone_name, policy_id); 04903 if (status != 0) { 04904 printf("Failed to Link Keys to zone\n"); 04905 ret = xmlTextReaderRead(reader); 04906 continue; 04907 }*/ 04908 } 04909 04910 /* make a note of the zone_id */ 04911 status = KsmZoneIdFromName(zone_name, &temp_id); 04912 if (status != 0) { 04913 printf("Error: unable to find a zone named \"%s\" in database\n", zone_name); 04914 printf("Error: Possibly two domains differ only by having a trailing dot or not?\n"); 04915 StrFree(zone_ids); 04916 return(status); 04917 } 04918 04919 /* We malloc'd this above */ 04920 zone_ids[i] = temp_id; 04921 i++; 04922 04923 StrFree(zone_name); 04924 StrFree(current_policy); 04925 StrFree(current_signconf); 04926 StrFree(current_input); 04927 StrFree(current_output); 04928 04929 new_zone = 0; 04930 04931 } 04932 /* Read the next line */ 04933 ret = xmlTextReaderRead(reader); 04934 StrFree(tag_name); 04935 } 04936 xmlFreeTextReader(reader); 04937 if (ret != 0) { 04938 printf("%s : failed to parse\n", zone_list_filename); 04939 } 04940 } else { 04941 printf("Unable to open %s\n", zone_list_filename); 04942 } 04943 if (doc) { 04944 xmlFreeDoc(doc); 04945 } 04946 StrFree(policy_name); 04947 04948 /* Now see how many zones are in the database */ 04949 sql = DqsCountInit(DB_ZONE_TABLE); 04950 DqsEnd(&sql); 04951 04952 /* Execute query and free up the query string */ 04953 status = DbIntQuery(DbHandle(), &db_zone_count, sql); 04954 DqsFree(sql); 04955 04956 /* If the 2 numbers match then our work is done */ 04957 if (file_zone_count == db_zone_count) { 04958 StrFree(zone_ids); 04959 return 0; 04960 } 04961 /* If the file count is larger then something went wrong */ 04962 else if (file_zone_count > db_zone_count) { 04963 printf("Failed to add all zones from zonelist\n"); 04964 StrFree(zone_ids); 04965 return(1); 04966 } 04967 04968 /* If we get here we need to do some deleting, get each zone in the db 04969 * and see if it is in the zone_list that we built earlier */ 04970 /* In case there are thousands of zones we don't use an "IN" clause*/ 04971 sql = DqsSpecifyInit(DB_ZONE_TABLE, "id, name, policy_id"); 04972 DqsOrderBy(&sql, "ID"); 04973 DqsEnd(&sql); 04974 04975 status = DbExecuteSql(DbHandle(), sql, &result); 04976 04977 if (status == 0) { 04978 status = DbFetchRow(result, &row); 04979 while (status == 0) { 04980 DbInt(row, 0, &temp_id); 04981 DbString(row, 1, &zone_name); 04982 DbInt(row, 2, &policy_id); 04983 04984 seen_zone = 0; 04985 for (i = 0; i < db_zone_count; ++i) { 04986 if (temp_id == zone_ids[i]) { 04987 seen_zone = 1; 04988 break; 04989 } 04990 } 04991 04992 if (seen_zone == 0) { 04993 /* We need to delete this zone */ 04994 /* Get the shared_keys parameter */ 04995 printf("Removing zone %s from database\n", zone_name); 04996 04997 status = KsmParameterInit(&result2, "zones_share_keys", "keys", policy_id); 04998 if (status != 0) { 04999 DbFreeRow(row); 05000 DbStringFree(zone_name); 05001 StrFree(zone_ids); 05002 return(status); 05003 } 05004 status = KsmParameter(result2, &shared); 05005 if (status != 0) { 05006 DbFreeRow(row); 05007 DbStringFree(zone_name); 05008 StrFree(zone_ids); 05009 return(status); 05010 } 05011 KsmParameterEnd(result2); 05012 05013 /* how many zones on this policy (needed to unlink keys) */ 05014 status = KsmZoneCountInit(&result3, policy_id); 05015 if (status == 0) { 05016 status = KsmZoneCount(result3, &temp_count); 05017 } 05018 DbFreeResult(result3); 05019 05020 /* Mark keys as dead if appropriate */ 05021 if ((shared.value == 1 && temp_count == 1) || shared.value == 0) { 05022 status = KsmMarkKeysAsDead(temp_id); 05023 if (status != 0) { 05024 printf("Error: failed to mark keys as dead in database\n"); 05025 StrFree(zone_ids); 05026 return(status); 05027 } 05028 } 05029 05030 /* Finally, we can delete the zone (and any dnsseckeys entries) */ 05031 status = KsmDeleteZone(temp_id); 05032 } 05033 05034 status = DbFetchRow(result, &row); 05035 } 05036 /* Convert EOF status to success */ 05037 05038 if (status == -1) { 05039 status = 0; 05040 } 05041 DbFreeResult(result); 05042 } 05043 05044 DusFree(sql); 05045 DbFreeRow(row); 05046 DbStringFree(zone_name); 05047 StrFree(zone_ids); 05048 05049 return 0; 05050 } 05051 05052 /* 05053 * This encapsulates all of the steps needed to insert/update a parameter value 05054 * try to update the policy value, if it has changed 05055 * TODO possible bug where parmeters which have a value of 0 are not written (because we 05056 * only write what looks like it has changed 05057 */ 05058 int SetParamOnPolicy(const xmlChar* new_value, const char* name, const char* category, int current_value, int policy_id, int value_type) 05059 { 05060 int status = 0; 05061 int value = 0; 05062 char* temp_char = (char *)new_value; 05063 05064 /* extract the value into an int */ 05065 if (value_type == DURATION_TYPE) { 05066 if (strlen(temp_char) != 0) { 05067 status = DtXMLIntervalSeconds(temp_char, &value); 05068 if (status > 0) { 05069 printf("Error: unable to convert interval %s to seconds, error: %i\n", temp_char, status); 05070 StrFree(temp_char); 05071 return status; 05072 } 05073 else if (status == -1) { 05074 printf("Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days\n", temp_char); 05075 } 05076 StrFree(temp_char); 05077 } else { 05078 value = -1; 05079 } 05080 } 05081 else if (value_type == BOOL_TYPE) { 05082 /* Do we have an empty tag or no tag? */ 05083 if (strncmp(temp_char, "Y", 1) == 0) { 05084 value = 1; 05085 } else { 05086 value = 0; 05087 } 05088 } 05089 else if (value_type == REPO_TYPE) { 05090 /* We need to convert the repository name into an id */ 05091 status = KsmSmIdFromName(temp_char, &value); 05092 if (status != 0) { 05093 printf("Error: unable to find repository %s\n", temp_char); 05094 StrFree(temp_char); 05095 return status; 05096 } 05097 StrFree(temp_char); 05098 } 05099 else if (value_type == SERIAL_TYPE) { 05100 /* We need to convert the serial name into an id */ 05101 status = KsmSerialIdFromName(temp_char, &value); 05102 if (status != 0) { 05103 printf("Error: unable to find serial type %s\n", temp_char); 05104 StrFree(temp_char); 05105 return status; 05106 } 05107 StrFree(temp_char); 05108 } 05109 else if (value_type == ROLLOVER_TYPE) { 05110 /* We need to convert the rollover scheme name into an id */ 05111 value = KsmKeywordRollNameToValue(temp_char); 05112 if (value == 0) { 05113 printf("Error: unable to find rollover scheme %s\n", temp_char); 05114 StrFree(temp_char); 05115 return status; 05116 } 05117 StrFree(temp_char); 05118 } 05119 else { 05120 status = StrStrtoi(temp_char, &value); 05121 if (status != 0) { 05122 printf("Error: unable to convert %s to int\n", temp_char); 05123 StrFree(temp_char); 05124 return status; 05125 } 05126 if (value_type != INT_TYPE_NO_FREE) { 05127 StrFree(temp_char); 05128 } 05129 } 05130 05131 /* Now update the policy with what we found, if it is different */ 05132 if (value != current_value || current_value == 0) { 05133 status = KsmParameterSet(name, category, value, policy_id); 05134 if (status != 0) { 05135 printf("Error: unable to insert/update %s for policy\n", name); 05136 printf("Error: Is your database schema up to date?\n"); 05137 return status; 05138 } 05139 05140 /* Special step if salt length changed make sure that the salt is 05141 regenerated when the enforcer runs next */ 05142 if (strncmp(name, "saltlength", 10) == 0) { 05143 status = KsmPolicyNullSaltStamp(policy_id); 05144 if (status != 0) { 05145 printf("Error: unable to insert/update %s for policy\n", name); 05146 printf("Error: Is your database schema up to date?\n"); 05147 return status; 05148 } 05149 } 05150 } 05151 05152 return 0; 05153 } 05154 05155 void SetPolicyDefaults(KSM_POLICY *policy, char *name) 05156 { 05157 if (policy == NULL) { 05158 printf("Error, no policy provided"); 05159 return; 05160 } 05161 05162 if (name) { 05163 snprintf(policy->name, KSM_NAME_LENGTH, "%s", name); 05164 } 05165 05166 policy->signer->refresh = 0; 05167 policy->signer->jitter = 0; 05168 policy->signer->propdelay = 0; 05169 policy->signer->soamin = 0; 05170 policy->signer->soattl = 0; 05171 policy->signer->serial = 0; 05172 05173 policy->signature->clockskew = 0; 05174 policy->signature->resign = 0; 05175 policy->signature->valdefault = 0; 05176 policy->signature->valdenial = 0; 05177 05178 policy->denial->version = 0; 05179 policy->denial->resalt = 0; 05180 policy->denial->algorithm = 0; 05181 policy->denial->iteration = 0; 05182 policy->denial->optout = 0; 05183 policy->denial->ttl = 0; 05184 policy->denial->saltlength = 0; 05185 05186 policy->keys->ttl = 0; 05187 policy->keys->retire_safety = 0; 05188 policy->keys->publish_safety = 0; 05189 policy->keys->share_keys = 0; 05190 policy->keys->purge = -1; 05191 05192 policy->ksk->algorithm = 0; 05193 policy->ksk->bits = 0; 05194 policy->ksk->lifetime = 0; 05195 policy->ksk->sm = 0; 05196 policy->ksk->overlap = 0; 05197 policy->ksk->ttl = 0; 05198 policy->ksk->rfc5011 = 0; 05199 policy->ksk->type = KSM_TYPE_KSK; 05200 policy->ksk->standby_keys = 0; 05201 policy->ksk->manual_rollover = 0; 05202 policy->ksk->rollover_scheme = KSM_ROLL_DEFAULT; 05203 05204 policy->zsk->algorithm = 0; 05205 policy->zsk->bits = 0; 05206 policy->zsk->lifetime = 0; 05207 policy->zsk->sm = 0; 05208 policy->zsk->overlap = 0; 05209 policy->zsk->ttl = 0; 05210 policy->zsk->rfc5011 = 0; 05211 policy->zsk->type = KSM_TYPE_ZSK; 05212 policy->zsk->standby_keys = 0; 05213 policy->zsk->manual_rollover = 0; 05214 policy->zsk->rollover_scheme = 0; 05215 05216 policy->enforcer->keycreate = 0; 05217 policy->enforcer->backup_interval = 0; 05218 policy->enforcer->keygeninterval = 0; 05219 05220 policy->zone->propdelay = 0; 05221 policy->zone->soa_ttl = 0; 05222 policy->zone->soa_min = 0; 05223 policy->zone->serial = 0; 05224 05225 policy->parent->propdelay = 0; 05226 policy->parent->ds_ttl = 0; 05227 policy->parent->soa_ttl = 0; 05228 policy->parent->soa_min = 0; 05229 05230 } 05231 05232 /* make a backup of a file 05233 * Returns 0 on success 05234 * 1 on error 05235 * -1 if it could read the original but not open the backup 05236 */ 05237 int backup_file(const char* orig_file, const char* backup_file) 05238 { 05239 FILE *from, *to; 05240 int ch; 05241 05242 errno = 0; 05243 /* open source file */ 05244 if((from = fopen( orig_file, "rb"))==NULL) { 05245 if (errno == ENOENT) { 05246 printf("File %s does not exist, nothing to backup\n", orig_file); 05247 return(0); 05248 } 05249 else { 05250 printf("Cannot open source file.\n"); 05251 return(1); /* No point in trying to connect */ 05252 } 05253 } 05254 05255 /* open destination file */ 05256 if((to = fopen(backup_file, "wb"))==NULL) { 05257 printf("Cannot open destination file, will not make backup.\n"); 05258 fclose(from); 05259 return(-1); 05260 } 05261 else { 05262 /* copy the file */ 05263 while(!feof(from)) { 05264 ch = fgetc(from); 05265 if(ferror(from)) { 05266 printf("Error reading source file.\n"); 05267 fclose(from); 05268 fclose(to); 05269 return(1); 05270 } 05271 if(!feof(from)) fputc(ch, to); 05272 if(ferror(to)) { 05273 printf("Error writing destination file.\n"); 05274 fclose(from); 05275 fclose(to); 05276 return(1); 05277 } 05278 } 05279 05280 if(fclose(from)==EOF) { 05281 printf("Error closing source file.\n"); 05282 fclose(to); 05283 return(1); 05284 } 05285 05286 if(fclose(to)==EOF) { 05287 printf("Error closing destination file.\n"); 05288 return(1); 05289 } 05290 } 05291 return(0); 05292 } 05293 05294 /* 05295 * Given a conf.xml location extract the database details contained within it 05296 * 05297 * The caller will need to StrFree the char**s passed in 05298 * 05299 * Returns 0 if a full set of details was found 05300 * 1 if something didn't look right 05301 * -1 if any of the config files could not be read/parsed 05302 * 05303 */ 05304 int 05305 get_db_details(char** dbschema, char** host, char** port, char** user, char** password) 05306 { 05307 /* All of the XML stuff */ 05308 xmlDocPtr doc; 05309 xmlDocPtr rngdoc; 05310 xmlXPathContextPtr xpathCtx; 05311 xmlXPathObjectPtr xpathObj; 05312 xmlRelaxNGParserCtxtPtr rngpctx; 05313 xmlRelaxNGValidCtxtPtr rngctx; 05314 xmlRelaxNGPtr schema; 05315 xmlChar *litexpr = (unsigned char*) "//Configuration/Enforcer/Datastore/SQLite"; 05316 xmlChar *mysql_host = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host"; 05317 xmlChar *mysql_port = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host/@port"; 05318 xmlChar *mysql_db = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Database"; 05319 xmlChar *mysql_user = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Username"; 05320 xmlChar *mysql_pass = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Password"; 05321 05322 int status; 05323 int db_found = 0; 05324 char* temp_char = NULL; 05325 05326 /* Some files, the xml and rng */ 05327 const char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng"; 05328 05329 /* Load XML document */ 05330 doc = xmlParseFile(config); 05331 if (doc == NULL) { 05332 printf("Error: unable to parse file \"%s\"\n", config); 05333 return(-1); 05334 } 05335 05336 /* Load rng document: TODO make the rng stuff optional? */ 05337 rngdoc = xmlParseFile(rngfilename); 05338 if (rngdoc == NULL) { 05339 printf("Error: unable to parse file \"%s\"\n", rngfilename); 05340 xmlFreeDoc(doc); 05341 return(-1); 05342 } 05343 05344 /* Create an XML RelaxNGs parser context for the relax-ng document. */ 05345 rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc); 05346 xmlFreeDoc(rngdoc); 05347 if (rngpctx == NULL) { 05348 printf("Error: unable to create XML RelaxNGs parser context\n"); 05349 xmlFreeDoc(doc); 05350 return(-1); 05351 } 05352 05353 /* parse a schema definition resource and build an internal XML Schema structure which can be used to validate instances. */ 05354 schema = xmlRelaxNGParse(rngpctx); 05355 xmlRelaxNGFreeParserCtxt(rngpctx); 05356 if (schema == NULL) { 05357 printf("Error: unable to parse a schema definition resource\n"); 05358 xmlFreeDoc(doc); 05359 return(-1); 05360 } 05361 05362 /* Create an XML RelaxNGs validation context based on the given schema */ 05363 rngctx = xmlRelaxNGNewValidCtxt(schema); 05364 if (rngctx == NULL) { 05365 printf("Error: unable to create RelaxNGs validation context based on the schema\n"); 05366 xmlRelaxNGFree(schema); 05367 xmlFreeDoc(doc); 05368 return(-1); 05369 } 05370 05371 /* Validate a document tree in memory. */ 05372 status = xmlRelaxNGValidateDoc(rngctx,doc); 05373 xmlRelaxNGFreeValidCtxt(rngctx); 05374 xmlRelaxNGFree(schema); 05375 if (status != 0) { 05376 printf("Error validating file \"%s\"\n", config); 05377 xmlFreeDoc(doc); 05378 return(-1); 05379 } 05380 05381 /* Now parse a value out of the conf */ 05382 /* Create xpath evaluation context */ 05383 xpathCtx = xmlXPathNewContext(doc); 05384 if(xpathCtx == NULL) { 05385 printf("Error: unable to create new XPath context\n"); 05386 xmlFreeDoc(doc); 05387 return(-1); 05388 } 05389 05390 /* Evaluate xpath expression for SQLite file location */ 05391 xpathObj = xmlXPathEvalExpression(litexpr, xpathCtx); 05392 if(xpathObj == NULL) { 05393 printf("Error: unable to evaluate xpath expression: %s\n", litexpr); 05394 xmlXPathFreeContext(xpathCtx); 05395 xmlFreeDoc(doc); 05396 return(-1); 05397 } 05398 if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 05399 db_found = SQLITE_DB; 05400 temp_char = (char *)xmlXPathCastToString(xpathObj); 05401 StrAppend(dbschema, temp_char); 05402 StrFree(temp_char); 05403 if (verbose_flag) { 05404 fprintf(stderr, "SQLite database set to: %s\n", *dbschema); 05405 } 05406 } 05407 xmlXPathFreeObject(xpathObj); 05408 05409 if (db_found == 0) { 05410 db_found = MYSQL_DB; 05411 05412 /* Get all of the MySQL stuff read in too */ 05413 /* HOST, optional */ 05414 xpathObj = xmlXPathEvalExpression(mysql_host, xpathCtx); 05415 if(xpathObj == NULL) { 05416 printf("Error: unable to evaluate xpath expression: %s\n", mysql_host); 05417 xmlXPathFreeContext(xpathCtx); 05418 xmlFreeDoc(doc); 05419 return(-1); 05420 } 05421 if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 05422 temp_char = (char *)xmlXPathCastToString(xpathObj); 05423 StrAppend(host, temp_char); 05424 StrFree(temp_char); 05425 if (verbose_flag) { 05426 fprintf(stderr, "MySQL database host set to: %s\n", *host); 05427 } 05428 } 05429 xmlXPathFreeObject(xpathObj); 05430 05431 /* PORT, optional */ 05432 xpathObj = xmlXPathEvalExpression(mysql_port, xpathCtx); 05433 if(xpathObj == NULL) { 05434 printf("Error: unable to evaluate xpath expression: %s\n", mysql_port); 05435 xmlXPathFreeContext(xpathCtx); 05436 xmlFreeDoc(doc); 05437 return(-1); 05438 } 05439 if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 05440 temp_char = (char *)xmlXPathCastToString(xpathObj); 05441 StrAppend(port, temp_char); 05442 StrFree(temp_char); 05443 if (verbose_flag) { 05444 fprintf(stderr, "MySQL database port set to: %s\n", *port); 05445 } 05446 } 05447 xmlXPathFreeObject(xpathObj); 05448 05449 /* SCHEMA */ 05450 xpathObj = xmlXPathEvalExpression(mysql_db, xpathCtx); 05451 if(xpathObj == NULL) { 05452 printf("Error: unable to evaluate xpath expression: %s\n", mysql_db); 05453 xmlXPathFreeContext(xpathCtx); 05454 xmlFreeDoc(doc); 05455 return(-1); 05456 } 05457 if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 05458 temp_char = (char *)xmlXPathCastToString(xpathObj); 05459 StrAppend(dbschema, temp_char); 05460 StrFree(temp_char); 05461 if (verbose_flag) { 05462 fprintf(stderr, "MySQL database schema set to: %s\n", *dbschema); 05463 } 05464 } else { 05465 db_found = 0; 05466 } 05467 xmlXPathFreeObject(xpathObj); 05468 05469 /* DB USER */ 05470 xpathObj = xmlXPathEvalExpression(mysql_user, xpathCtx); 05471 if(xpathObj == NULL) { 05472 printf("Error: unable to evaluate xpath expression: %s\n", mysql_user); 05473 xmlXPathFreeContext(xpathCtx); 05474 xmlFreeDoc(doc); 05475 return(-1); 05476 } 05477 if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 05478 temp_char = (char *)xmlXPathCastToString(xpathObj); 05479 StrAppend(user, temp_char); 05480 StrFree(temp_char); 05481 if (verbose_flag) { 05482 fprintf(stderr, "MySQL database user set to: %s\n", *user); 05483 } 05484 } else { 05485 db_found = 0; 05486 } 05487 xmlXPathFreeObject(xpathObj); 05488 05489 /* DB PASSWORD */ 05490 xpathObj = xmlXPathEvalExpression(mysql_pass, xpathCtx); 05491 if(xpathObj == NULL) { 05492 printf("Error: unable to evaluate xpath expression: %s\n", mysql_pass); 05493 xmlXPathFreeContext(xpathCtx); 05494 xmlFreeDoc(doc); 05495 return(-1); 05496 } 05497 /* password may be blank */ 05498 temp_char = (char *)xmlXPathCastToString(xpathObj); 05499 StrAppend(password, temp_char); 05500 StrFree(temp_char); 05501 xmlXPathFreeObject(xpathObj); 05502 05503 if (verbose_flag) { 05504 fprintf(stderr, "MySQL database password set\n"); 05505 } 05506 05507 } 05508 05509 xmlXPathFreeContext(xpathCtx); 05510 xmlFreeDoc(doc); 05511 05512 /* Check that we found one or the other database */ 05513 if(db_found == 0) { 05514 printf("Error: unable to find complete database connection expression\n"); 05515 return(-1); 05516 } 05517 05518 /* Check that we found the right database type */ 05519 if (db_found != DbFlavour()) { 05520 printf("Error: database in config file does not match libksm\n"); 05521 return(-1); 05522 } 05523 05524 return(status); 05525 } 05526 05527 /* 05528 * Read the conf.xml file, we will not validate as that was done as we read the database. 05529 * Instead we just extract the RepositoryList into the database and also learn the 05530 * location of the zonelist. 05531 */ 05532 int read_zonelist_filename(char** zone_list_filename) 05533 { 05534 xmlTextReaderPtr reader = NULL; 05535 xmlDocPtr doc = NULL; 05536 xmlXPathContextPtr xpathCtx = NULL; 05537 xmlXPathObjectPtr xpathObj = NULL; 05538 int ret = 0; /* status of the XML parsing */ 05539 char* temp_char = NULL; 05540 char* tag_name = NULL; 05541 05542 xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile"; 05543 05544 /* Start reading the file; we will be looking for "Common" tags */ 05545 reader = xmlNewTextReaderFilename(config); 05546 if (reader != NULL) { 05547 ret = xmlTextReaderRead(reader); 05548 while (ret == 1) { 05549 tag_name = (char*) xmlTextReaderLocalName(reader); 05550 /* Found <Common> */ 05551 if (strncmp(tag_name, "Common", 6) == 0 05552 && xmlTextReaderNodeType(reader) == 1) { 05553 05554 /* Expand this node and get the rest of the info with XPath */ 05555 xmlTextReaderExpand(reader); 05556 doc = xmlTextReaderCurrentDoc(reader); 05557 if (doc == NULL) { 05558 printf("Error: can not read Common section\n"); 05559 /* Don't return? try to parse the rest of the file? */ 05560 ret = xmlTextReaderRead(reader); 05561 continue; 05562 } 05563 05564 xpathCtx = xmlXPathNewContext(doc); 05565 if(xpathCtx == NULL) { 05566 printf("Error: can not create XPath context for Common section\n"); 05567 /* Don't return? try to parse the rest of the file? */ 05568 ret = xmlTextReaderRead(reader); 05569 continue; 05570 } 05571 05572 /* Evaluate xpath expression for ZoneListFile */ 05573 xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx); 05574 if(xpathObj == NULL) { 05575 printf("Error: unable to evaluate xpath expression: %s\n", zonelist_expr); 05576 /* Don't return? try to parse the rest of the file? */ 05577 ret = xmlTextReaderRead(reader); 05578 continue; 05579 } 05580 *zone_list_filename = NULL; 05581 temp_char = (char *)xmlXPathCastToString(xpathObj); 05582 xmlXPathFreeObject(xpathObj); 05583 StrAppend(zone_list_filename, temp_char); 05584 StrFree(temp_char); 05585 printf("zonelist filename set to %s.\n", *zone_list_filename); 05586 } 05587 /* Read the next line */ 05588 ret = xmlTextReaderRead(reader); 05589 StrFree(tag_name); 05590 } 05591 xmlFreeTextReader(reader); 05592 if (ret != 0) { 05593 printf("%s : failed to parse\n", config); 05594 return(1); 05595 } 05596 } else { 05597 printf("Unable to open %s\n", config); 05598 return(1); 05599 } 05600 if (xpathCtx) { 05601 xmlXPathFreeContext(xpathCtx); 05602 } 05603 if (doc) { 05604 xmlFreeDoc(doc); 05605 } 05606 05607 return 0; 05608 } 05609 05610 xmlDocPtr add_zone_node(const char *docname, 05611 const char *zone_name, 05612 const char *policy_name, 05613 const char *sig_conf_name, 05614 const char *input_name, 05615 const char *output_name) 05616 { 05617 xmlDocPtr doc; 05618 xmlNodePtr cur; 05619 xmlNodePtr newzonenode; 05620 xmlNodePtr newadaptnode; 05621 xmlNodePtr newinputnode; 05622 xmlNodePtr newoutputnode; 05623 doc = xmlParseFile(docname); 05624 if (doc == NULL ) { 05625 fprintf(stderr,"Document not parsed successfully. \n"); 05626 return (NULL); 05627 } 05628 cur = xmlDocGetRootElement(doc); 05629 if (cur == NULL) { 05630 fprintf(stderr,"empty document\n"); 05631 xmlFreeDoc(doc); 05632 return (NULL); 05633 } 05634 if (xmlStrcmp(cur->name, (const xmlChar *) "ZoneList")) { 05635 fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList"); 05636 xmlFreeDoc(doc); 05637 return (NULL); 05638 } 05639 newzonenode = xmlNewTextChild(cur, NULL, (const xmlChar *)"Zone", NULL); 05640 (void) xmlNewProp(newzonenode, (const xmlChar *)"name", (const xmlChar *)zone_name); 05641 05642 (void) xmlNewTextChild (newzonenode, NULL, (const xmlChar *)"Policy", (const xmlChar *)policy_name); 05643 05644 (void) xmlNewTextChild (newzonenode, NULL, (const xmlChar *)"SignerConfiguration", (const xmlChar *)sig_conf_name); 05645 05646 newadaptnode = xmlNewChild (newzonenode, NULL, (const xmlChar *)"Adapters", NULL); 05647 05648 newinputnode = xmlNewChild (newadaptnode, NULL, (const xmlChar *)"Input", NULL); 05649 05650 (void) xmlNewTextChild (newinputnode, NULL, (const xmlChar *)"File", (const xmlChar *)input_name); 05651 05652 newoutputnode = xmlNewChild (newadaptnode, NULL, (const xmlChar *)"Output", NULL); 05653 05654 (void) xmlNewTextChild (newoutputnode, NULL, (const xmlChar *)"File", (const xmlChar *)output_name); 05655 05656 return(doc); 05657 } 05658 05659 xmlDocPtr del_zone_node(const char *docname, 05660 const char *zone_name) 05661 { 05662 xmlDocPtr doc; 05663 xmlNodePtr root; 05664 xmlNodePtr cur; 05665 05666 doc = xmlParseFile(docname); 05667 if (doc == NULL ) { 05668 fprintf(stderr,"Document not parsed successfully. \n"); 05669 return (NULL); 05670 } 05671 root = xmlDocGetRootElement(doc); 05672 if (root == NULL) { 05673 fprintf(stderr,"empty document\n"); 05674 xmlFreeDoc(doc); 05675 return (NULL); 05676 } 05677 if (xmlStrcmp(root->name, (const xmlChar *) "ZoneList")) { 05678 fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList"); 05679 xmlFreeDoc(doc); 05680 return (NULL); 05681 } 05682 05683 /* If we are removing all zones then just replace the root node with an empty one */ 05684 if (all_flag == 1) { 05685 cur = root->children; 05686 while (cur != NULL) 05687 { 05688 xmlUnlinkNode(cur); 05689 xmlFreeNode(cur); 05690 05691 cur = root->children; 05692 } 05693 } 05694 else { 05695 05696 /* Zone nodes are children of the root */ 05697 for(cur = root->children; cur != NULL; cur = cur->next) 05698 { 05699 /* is this the zone we are looking for? */ 05700 if (xmlStrcmp( xmlGetProp(cur, (xmlChar *) "name"), (const xmlChar *) zone_name) == 0) 05701 { 05702 xmlUnlinkNode(cur); 05703 05704 cur = root->children; /* May pass through multiple times, but will remove all instances of the zone */ 05705 } 05706 } 05707 xmlFreeNode(cur); 05708 } 05709 05710 return(doc); 05711 } 05712 05713 void list_zone_node(const char *docname, int *zone_ids) 05714 { 05715 xmlDocPtr doc; 05716 xmlNodePtr root; 05717 xmlNodePtr cur; 05718 xmlNodePtr pol; 05719 xmlChar *polChar = NULL; 05720 xmlChar *propChar = NULL; 05721 05722 int temp_id; 05723 int i = 0; 05724 int status = 0; 05725 05726 doc = xmlParseFile(docname); 05727 if (doc == NULL ) { 05728 fprintf(stderr,"Document not parsed successfully. \n"); 05729 return; 05730 } 05731 root = xmlDocGetRootElement(doc); 05732 if (root == NULL) { 05733 fprintf(stderr,"empty document\n"); 05734 xmlFreeDoc(doc); 05735 return; 05736 } 05737 if (xmlStrcmp(root->name, (const xmlChar *) "ZoneList")) { 05738 fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList"); 05739 xmlFreeDoc(doc); 05740 return; 05741 } 05742 05743 /* Zone nodes are children of the root */ 05744 for(cur = root->children; cur != NULL; cur = cur->next) 05745 { 05746 if (xmlStrcmp( cur->name, (const xmlChar *)"Zone") == 0) { 05747 propChar = xmlGetProp(cur, (xmlChar *) "name"); 05748 printf("Found Zone: %s", propChar); 05749 05750 /* make a note of the zone_id */ 05751 status = KsmZoneIdFromName((char *) propChar, &temp_id); 05752 xmlFree(propChar); 05753 if (status != 0) { 05754 printf(" (zone not in database)"); 05755 zone_ids[i] = 0; 05756 } else { 05757 zone_ids[i] = temp_id; 05758 i++; 05759 } 05760 05761 /* Print the policy name for this zone */ 05762 for(pol = cur->children; pol != NULL; pol = pol->next) 05763 { 05764 if (xmlStrcmp( pol->name, (const xmlChar *)"Policy") == 0) 05765 { 05766 polChar = xmlNodeGetContent(pol); 05767 printf("; on policy %s\n", polChar); 05768 xmlFree(polChar); 05769 } 05770 } 05771 } 05772 } 05773 05774 xmlFreeDoc(doc); 05775 05776 return; 05777 } 05778 05779 /* 05780 * Given a doc that has the start of the kasp-like xml and a policy structure 05781 * create the policy tag and contents in that doc 05782 */ 05783 int append_policy(xmlDocPtr doc, KSM_POLICY *policy) 05784 { 05785 xmlNodePtr root; 05786 xmlNodePtr policy_node; 05787 xmlNodePtr signatures_node; 05788 xmlNodePtr validity_node; 05789 xmlNodePtr denial_node; 05790 xmlNodePtr nsec_node; 05791 xmlNodePtr hash_node; 05792 xmlNodePtr salt_node; 05793 xmlNodePtr keys_node; 05794 xmlNodePtr ksk_node; 05795 xmlNodePtr ksk_alg_node; 05796 xmlNodePtr zsk_node; 05797 xmlNodePtr zsk_alg_node; 05798 xmlNodePtr zone_node; 05799 xmlNodePtr zone_soa_node; 05800 xmlNodePtr parent_node; 05801 xmlNodePtr parent_ds_node; 05802 xmlNodePtr parent_soa_node; 05803 05804 char temp_time[32]; 05805 05806 root = xmlDocGetRootElement(doc); 05807 if (root == NULL) { 05808 fprintf(stderr,"empty document\n"); 05809 return(1); 05810 } 05811 if (xmlStrcmp(root->name, (const xmlChar *) "KASP")) { 05812 fprintf(stderr,"document of the wrong type, root node != %s", "KASP"); 05813 return(1); 05814 } 05815 05816 policy_node = xmlNewTextChild(root, NULL, (const xmlChar *)"Policy", NULL); 05817 (void) xmlNewProp(policy_node, (const xmlChar *)"name", (const xmlChar *)policy->name); 05818 (void) xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Description", (const xmlChar *)policy->description); 05819 05820 /* SIGNATURES */ 05821 signatures_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Signatures", NULL); 05822 snprintf(temp_time, 32, "PT%dS", policy->signature->resign); 05823 (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Resign", (const xmlChar *)temp_time); 05824 snprintf(temp_time, 32, "PT%dS", policy->signer->refresh); 05825 (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Refresh", (const xmlChar *)temp_time); 05826 validity_node = xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Validity", NULL); 05827 snprintf(temp_time, 32, "PT%dS", policy->signature->valdefault); 05828 (void) xmlNewTextChild(validity_node, NULL, (const xmlChar *)"Default", (const xmlChar *)temp_time); 05829 snprintf(temp_time, 32, "PT%dS", policy->signature->valdenial); 05830 (void) xmlNewTextChild(validity_node, NULL, (const xmlChar *)"Denial", (const xmlChar *)temp_time); 05831 snprintf(temp_time, 32, "PT%dS", policy->signer->jitter); 05832 (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"Jitter", (const xmlChar *)temp_time); 05833 snprintf(temp_time, 32, "PT%dS", policy->signature->clockskew); 05834 (void) xmlNewTextChild(signatures_node, NULL, (const xmlChar *)"InceptionOffset", (const xmlChar *)temp_time); 05835 05836 /* DENIAL */ 05837 denial_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Denial", NULL); 05838 if (policy->denial->version == 1) /* NSEC */ 05839 { 05840 (void) xmlNewTextChild(denial_node, NULL, (const xmlChar *)"NSEC", NULL); 05841 } 05842 else /* NSEC3 */ 05843 { 05844 nsec_node = xmlNewTextChild(denial_node, NULL, (const xmlChar *)"NSEC3", NULL); 05845 if (policy->denial->optout == 1) 05846 { 05847 (void) xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"OptOut", NULL); 05848 } 05849 snprintf(temp_time, 32, "PT%dS", policy->denial->resalt); 05850 (void) xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"Resalt", (const xmlChar *)temp_time); 05851 hash_node = xmlNewTextChild(nsec_node, NULL, (const xmlChar *)"Hash", NULL); 05852 snprintf(temp_time, 32, "%d", policy->denial->algorithm); 05853 (void) xmlNewTextChild(hash_node, NULL, (const xmlChar *)"Algorithm", (const xmlChar *)temp_time); 05854 snprintf(temp_time, 32, "%d", policy->denial->iteration); 05855 (void) xmlNewTextChild(hash_node, NULL, (const xmlChar *)"Iteration", (const xmlChar *)temp_time); 05856 snprintf(temp_time, 32, "%d", policy->denial->saltlength); 05857 salt_node = xmlNewTextChild(hash_node, NULL, (const xmlChar *)"Salt", NULL); 05858 (void) xmlNewProp(salt_node, (const xmlChar *)"length", (const xmlChar *)temp_time); 05859 } 05860 05861 /* KEYS */ 05862 keys_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Keys", NULL); 05863 snprintf(temp_time, 32, "PT%dS", policy->keys->ttl); 05864 (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time); 05865 snprintf(temp_time, 32, "PT%dS", policy->keys->retire_safety); 05866 (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"RetireSafety", (const xmlChar *)temp_time); 05867 snprintf(temp_time, 32, "PT%dS", policy->keys->publish_safety); 05868 (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"PublishSafety", (const xmlChar *)temp_time); 05869 if (policy->keys->share_keys == 1) 05870 { 05871 (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"ShareKeys", NULL); 05872 } 05873 if (policy->keys->purge != -1) { 05874 snprintf(temp_time, 32, "PT%dS", policy->keys->purge); 05875 (void) xmlNewTextChild(keys_node, NULL, (const xmlChar *)"Purge", (const xmlChar *)temp_time); 05876 } 05877 /*(void) xmlNewDocComment(doc, (const xmlChar *)"Parameters that are different for zsks and ksks");*/ 05878 /* KSK */ 05879 ksk_node = xmlNewTextChild(keys_node, NULL, (const xmlChar *)"KSK", NULL); 05880 snprintf(temp_time, 32, "%d", policy->ksk->algorithm); 05881 ksk_alg_node = xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Algorithm", (const xmlChar *)temp_time); 05882 snprintf(temp_time, 32, "%d", policy->ksk->bits); 05883 (void) xmlNewProp(ksk_alg_node, (const xmlChar *)"length", (const xmlChar *)temp_time); 05884 snprintf(temp_time, 32, "PT%dS", policy->ksk->lifetime); 05885 (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Lifetime", (const xmlChar *)temp_time); 05886 (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Repository", (const xmlChar *)policy->ksk->sm_name); 05887 snprintf(temp_time, 32, "%d", policy->ksk->standby_keys); 05888 (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"Standby", (const xmlChar *)temp_time); 05889 if (policy->ksk->manual_rollover == 1) 05890 { 05891 (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"ManualRollover", NULL); 05892 } 05893 if (policy->ksk->rfc5011 == 1) 05894 { 05895 (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"RFC5011", NULL); 05896 } 05897 /* if (policy->ksk->rollover_scheme != 0) 05898 { 05899 (void) xmlNewTextChild(ksk_node, NULL, (const xmlChar *)"RolloverScheme", (const xmlChar *) KsmKeywordRollValueToName(policy->ksk->rollover_scheme)); 05900 }*/ 05901 05902 /* ZSK */ 05903 zsk_node = xmlNewTextChild(keys_node, NULL, (const xmlChar *)"ZSK", NULL); 05904 snprintf(temp_time, 32, "%d", policy->zsk->algorithm); 05905 zsk_alg_node = xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Algorithm", (const xmlChar *)temp_time); 05906 snprintf(temp_time, 32, "%d", policy->zsk->bits); 05907 (void) xmlNewProp(zsk_alg_node, (const xmlChar *)"length", (const xmlChar *)temp_time); 05908 snprintf(temp_time, 32, "PT%dS", policy->zsk->lifetime); 05909 (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Lifetime", (const xmlChar *)temp_time); 05910 (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Repository", (const xmlChar *)policy->zsk->sm_name); 05911 snprintf(temp_time, 32, "%d", policy->zsk->standby_keys); 05912 (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"Standby", (const xmlChar *)temp_time); 05913 if (policy->zsk->manual_rollover == 1) 05914 { 05915 (void) xmlNewTextChild(zsk_node, NULL, (const xmlChar *)"ManualRollover", NULL); 05916 } 05917 05918 /* ZONE */ 05919 zone_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Zone", NULL); 05920 snprintf(temp_time, 32, "PT%dS", policy->zone->propdelay); 05921 (void) xmlNewTextChild(zone_node, NULL, (const xmlChar *)"PropagationDelay", (const xmlChar *)temp_time); 05922 zone_soa_node = xmlNewTextChild(zone_node, NULL, (const xmlChar *)"SOA", NULL); 05923 snprintf(temp_time, 32, "PT%dS", policy->zone->soa_ttl); 05924 (void) xmlNewTextChild(zone_soa_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time); 05925 snprintf(temp_time, 32, "PT%dS", policy->zone->soa_min); 05926 (void) xmlNewTextChild(zone_soa_node, NULL, (const xmlChar *)"Minimum", (const xmlChar *)temp_time); 05927 (void) xmlNewTextChild(zone_soa_node, NULL, (const xmlChar *)"Serial", (const xmlChar *) KsmKeywordSerialValueToName(policy->zone->serial)); 05928 05929 /* PARENT */ 05930 parent_node = xmlNewTextChild(policy_node, NULL, (const xmlChar *)"Parent", NULL); 05931 snprintf(temp_time, 32, "PT%dS", policy->parent->propdelay); 05932 (void) xmlNewTextChild(parent_node, NULL, (const xmlChar *)"PropagationDelay", (const xmlChar *)temp_time); 05933 parent_ds_node = xmlNewTextChild(parent_node, NULL, (const xmlChar *)"DS", NULL); 05934 snprintf(temp_time, 32, "PT%dS", policy->parent->ds_ttl); 05935 (void) xmlNewTextChild(parent_ds_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time); 05936 parent_soa_node = xmlNewTextChild(parent_node, NULL, (const xmlChar *)"SOA", NULL); 05937 snprintf(temp_time, 32, "PT%dS", policy->parent->soa_ttl); 05938 (void) xmlNewTextChild(parent_soa_node, NULL, (const xmlChar *)"TTL", (const xmlChar *)temp_time); 05939 snprintf(temp_time, 32, "PT%dS", policy->parent->soa_min); 05940 (void) xmlNewTextChild(parent_soa_node, NULL, (const xmlChar *)"Minimum", (const xmlChar *)temp_time); 05941 05942 /* AUDIT (Currently this either exists and is empty or it doesn't) */ 05943 if (strncmp(policy->audit, "NULL", 4) != 0) { 05944 (void) xmlNewChild(policy_node, NULL, (const xmlChar *)"Audit", NULL); 05945 } 05946 05947 return(0); 05948 } 05949 05950 /* 05951 * Delete a policy node from kasp.xml 05952 */ 05953 xmlDocPtr del_policy_node(const char *docname, 05954 const char *policy_name) 05955 { 05956 xmlDocPtr doc; 05957 xmlNodePtr root; 05958 xmlNodePtr cur; 05959 05960 doc = xmlParseFile(docname); 05961 if (doc == NULL ) { 05962 fprintf(stderr,"Document not parsed successfully. \n"); 05963 return (NULL); 05964 } 05965 root = xmlDocGetRootElement(doc); 05966 if (root == NULL) { 05967 fprintf(stderr,"empty document\n"); 05968 xmlFreeDoc(doc); 05969 return (NULL); 05970 } 05971 if (xmlStrcmp(root->name, (const xmlChar *) "KASP")) { 05972 fprintf(stderr,"document of the wrong type, root node != %s", "KASP"); 05973 xmlFreeDoc(doc); 05974 return (NULL); 05975 } 05976 05977 05978 /* Policy nodes are children of the root */ 05979 for(cur = root->children; cur != NULL; cur = cur->next) 05980 { 05981 /* is this the zone we are looking for? */ 05982 if (xmlStrcmp( xmlGetProp(cur, (xmlChar *) "name"), (const xmlChar *) policy_name) == 0) 05983 { 05984 xmlUnlinkNode(cur); 05985 05986 cur = root->children; /* May pass through multiple times, but will remove all instances of the policy */ 05987 } 05988 } 05989 xmlFreeNode(cur); 05990 05991 return(doc); 05992 } 05993 05994 /* 05995 * CallBack to print key info to stdout 05996 */ 05997 int printKey(void* context, KSM_KEYDATA* key_data) 05998 { 05999 if (key_data->state == KSM_STATE_RETIRE && strcasecmp(key_data->retire, (char *)context) == 0) { 06000 if (key_data->keytype == KSM_TYPE_KSK) 06001 { 06002 fprintf(stdout, "KSK:"); 06003 } 06004 if (key_data->keytype == KSM_TYPE_ZSK) 06005 { 06006 fprintf(stdout, "ZSK:"); 06007 } 06008 fprintf(stdout, " %s Retired\n", key_data->location); 06009 } 06010 06011 return 0; 06012 } 06013 06014 /* 06015 * log function suitable for libksm callback 06016 */ 06017 void 06018 ksm_log_msg(const char *format) 06019 { 06020 fprintf(stderr, "%s\n", format); 06021 } 06022 06023 /*+ 06024 * ListKeys - Output a list of Keys 06025 * 06026 * 06027 * Arguments: 06028 * 06029 * int zone_id 06030 * ID of the zone (-1 for all) 06031 * 06032 * Returns: 06033 * int 06034 * Status return. 0 on success. 06035 * other on fail 06036 */ 06037 06038 int ListKeys(int zone_id) 06039 { 06040 char* sql = NULL; /* SQL query */ 06041 int status = 0; /* Status return */ 06042 char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */ 06043 DB_RESULT result; /* Result of the query */ 06044 DB_ROW row = NULL; /* Row data */ 06045 int done_row = 0; /* Have we printed a row this loop? */ 06046 06047 char* temp_zone = NULL; /* place to store zone name returned */ 06048 int temp_type = 0; /* place to store key type returned */ 06049 int temp_state = 0; /* place to store key state returned */ 06050 char* temp_ready = NULL; /* place to store ready date returned */ 06051 char* temp_active = NULL; /* place to store active date returned */ 06052 char* temp_retire = NULL; /* place to store retire date returned */ 06053 char* temp_dead = NULL; /* place to store dead date returned */ 06054 char* temp_loc = NULL; /* place to store location returned */ 06055 char* temp_hsm = NULL; /* place to store hsm returned */ 06056 int temp_alg = 0; /* place to store algorithm returned */ 06057 06058 /* Key information */ 06059 hsm_key_t *key = NULL; 06060 ldns_rr *dnskey_rr = NULL; 06061 hsm_sign_params_t *sign_params = NULL; 06062 06063 if (verbose_flag) { 06064 /* connect to the HSM */ 06065 status = hsm_open(config, hsm_prompt_pin, NULL); 06066 if (status) { 06067 hsm_print_error(NULL); 06068 return(-1); 06069 } 06070 } 06071 06072 /* Select rows */ 06073 StrAppend(&sql, "select z.name, k.keytype, k.state, k.ready, k.active, k.retire, k.dead, k.location, s.name, k.algorithm 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 "); 06074 if (zone_id != -1) { 06075 StrAppend(&sql, "and zone_id = "); 06076 snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id); 06077 StrAppend(&sql, stringval); 06078 } 06079 StrAppend(&sql, " order by zone_id"); 06080 06081 DusEnd(&sql); 06082 06083 status = DbExecuteSql(DbHandle(), sql, &result); 06084 06085 if (status == 0) { 06086 status = DbFetchRow(result, &row); 06087 if (verbose_flag == 1) { 06088 printf("Zone: Keytype: State: Date of next transition: CKA_ID: Repository: Keytag:\n"); 06089 } 06090 else { 06091 printf("Zone: Keytype: State: Date of next transition:\n"); 06092 } 06093 while (status == 0) { 06094 /* Got a row, print it */ 06095 DbString(row, 0, &temp_zone); 06096 DbInt(row, 1, &temp_type); 06097 DbInt(row, 2, &temp_state); 06098 DbString(row, 3, &temp_ready); 06099 DbString(row, 4, &temp_active); 06100 DbString(row, 5, &temp_retire); 06101 DbString(row, 6, &temp_dead); 06102 DbString(row, 7, &temp_loc); 06103 DbString(row, 8, &temp_hsm); 06104 DbInt(row, 9, &temp_alg); 06105 done_row = 0; 06106 06107 if (temp_state == KSM_STATE_PUBLISH) { 06108 printf("%-31s %-13s %-9s %-26s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_ready == NULL) ? "(not scheduled)" : temp_ready); 06109 done_row = 1; 06110 } 06111 else if (temp_state == KSM_STATE_READY) { 06112 printf("%-31s %-13s %-9s %-26s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_type == KSM_TYPE_KSK) ? "waiting for ds-seen" : "next rollover"); 06113 done_row = 1; 06114 } 06115 else if (temp_state == KSM_STATE_ACTIVE) { 06116 printf("%-31s %-13s %-9s %-26s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_retire == NULL) ? "(not scheduled)" : temp_retire); 06117 done_row = 1; 06118 } 06119 else if (temp_state == KSM_STATE_RETIRE) { 06120 printf("%-31s %-13s %-9s %-26s", temp_zone, (temp_type == KSM_TYPE_KSK) ? "KSK" : "ZSK", KsmKeywordStateValueToName(temp_state), (temp_dead == NULL) ? "(not scheduled)" : temp_dead); 06121 done_row = 1; 06122 } 06123 else if (temp_state == KSM_STATE_DSSUB) { 06124 printf("%-31s %-13s %-9s %-26s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), "waiting for ds-seen"); 06125 done_row = 1; 06126 } 06127 else if (temp_state == KSM_STATE_DSPUBLISH) { 06128 printf("%-31s %-13s %-9s %-26s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), (temp_ready == NULL) ? "(not scheduled)" : temp_ready); 06129 done_row = 1; 06130 } 06131 else if (temp_state == KSM_STATE_DSREADY) { 06132 printf("%-31s %-13s %-9s %-26s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), "When required"); 06133 done_row = 1; 06134 } 06135 else if (temp_state == KSM_STATE_KEYPUBLISH) { 06136 printf("%-31s %-13s %-9s %-26s", temp_zone, "KSK", KsmKeywordStateValueToName(temp_state), (temp_active == NULL) ? "(not scheduled)" : temp_active); 06137 done_row = 1; 06138 } 06139 06140 if (done_row == 1 && verbose_flag == 1) { 06141 key = hsm_find_key_by_id(NULL, temp_loc); 06142 if (!key) { 06143 printf("%-33s %s NOT IN repository\n", temp_loc, temp_hsm); 06144 } else { 06145 sign_params = hsm_sign_params_new(); 06146 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, temp_zone); 06147 sign_params->algorithm = temp_alg; 06148 sign_params->flags = LDNS_KEY_ZONE_KEY; 06149 if (temp_type == KSM_TYPE_KSK) { 06150 sign_params->flags += LDNS_KEY_SEP_KEY; 06151 } 06152 dnskey_rr = hsm_get_dnskey(NULL, key, sign_params); 06153 sign_params->keytag = ldns_calc_keytag(dnskey_rr); 06154 06155 printf("%-33s %-33s %d\n", temp_loc, temp_hsm, sign_params->keytag); 06156 06157 hsm_sign_params_free(sign_params); 06158 hsm_key_free(key); 06159 } 06160 } 06161 else if (done_row == 1) { 06162 printf("\n"); 06163 } 06164 06165 status = DbFetchRow(result, &row); 06166 } 06167 06168 /* Convert EOF status to success */ 06169 06170 if (status == -1) { 06171 status = 0; 06172 } 06173 06174 DbFreeResult(result); 06175 } 06176 06177 DusFree(sql); 06178 DbFreeRow(row); 06179 06180 DbStringFree(temp_zone); 06181 DbStringFree(temp_ready); 06182 DbStringFree(temp_active); 06183 DbStringFree(temp_retire); 06184 DbStringFree(temp_dead); 06185 DbStringFree(temp_loc); 06186 DbStringFree(temp_hsm); 06187 06188 if (dnskey_rr != NULL) { 06189 ldns_rr_free(dnskey_rr); 06190 } 06191 06192 return status; 06193 } 06194 06195 /*+ 06196 * PurgeKeys - Purge dead Keys 06197 * 06198 * 06199 * Arguments: 06200 * 06201 * int zone_id 06202 * ID of the zone 06203 * 06204 * int policy_id 06205 * ID of the policy 06206 * 06207 * N.B. Only one of the arguments should be set, the other should be -1 06208 * 06209 * Returns: 06210 * int 06211 * Status return. 0 on success. 06212 * other on fail 06213 */ 06214 06215 int PurgeKeys(int zone_id, int policy_id) 06216 { 06217 char* sql = NULL; /* SQL query */ 06218 char* sql1 = NULL; /* SQL query */ 06219 char* sql2 = NULL; /* SQL query */ 06220 char* sql3 = NULL; /* SQL query */ 06221 int status = 0; /* Status return */ 06222 char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */ 06223 DB_RESULT result; /* Result of the query */ 06224 DB_ROW row = NULL; /* Row data */ 06225 06226 int temp_id = -1; /* place to store the key id returned */ 06227 char* temp_loc = NULL; /* place to store location returned */ 06228 int count = 0; /* How many keys don't match the purge */ 06229 06230 int done_something = 0; /* have we done anything? */ 06231 06232 /* Key information */ 06233 hsm_key_t *key = NULL; 06234 06235 if ((zone_id == -1 && policy_id == -1) || 06236 (zone_id != -1 && policy_id != -1)){ 06237 printf("Please provide either a zone OR a policy to key purge\n"); 06238 usage_keypurge(); 06239 return(1); 06240 } 06241 06242 /* connect to the HSM */ 06243 status = hsm_open(config, hsm_prompt_pin, NULL); 06244 if (status) { 06245 hsm_print_error(NULL); 06246 return(-1); 06247 } 06248 06249 /* Select rows */ 06250 StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 "); 06251 if (zone_id != -1) { 06252 StrAppend(&sql, "and zone_id = "); 06253 snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id); 06254 StrAppend(&sql, stringval); 06255 } 06256 if (policy_id != -1) { 06257 StrAppend(&sql, "and policy_id = "); 06258 snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id); 06259 StrAppend(&sql, stringval); 06260 } 06261 DusEnd(&sql); 06262 06263 status = DbExecuteSql(DbHandle(), sql, &result); 06264 06265 if (status == 0) { 06266 status = DbFetchRow(result, &row); 06267 while (status == 0) { 06268 /* Got a row, check it */ 06269 DbInt(row, 0, &temp_id); 06270 DbString(row, 1, &temp_loc); 06271 06272 sql1 = DqsCountInit("dnsseckeys"); 06273 DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0); 06274 DdsConditionInt(&sql1, "state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1); 06275 DqsEnd(&sql1); 06276 06277 status = DbIntQuery(DbHandle(), &count, sql1); 06278 DqsFree(sql1); 06279 06280 if (status != 0) { 06281 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 06282 DbStringFree(temp_loc); 06283 DbFreeRow(row); 06284 return status; 06285 } 06286 06287 /* If the count is zero then there is no reason not to purge this key */ 06288 if (count == 0) { 06289 06290 done_something = 1; 06291 06292 /* Delete from dnsseckeys */ 06293 sql2 = DdsInit("dnsseckeys"); 06294 DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0); 06295 DdsEnd(&sql); 06296 06297 status = DbExecuteSqlNoResult(DbHandle(), sql2); 06298 DdsFree(sql2); 06299 if (status != 0) 06300 { 06301 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 06302 DbStringFree(temp_loc); 06303 DbFreeRow(row); 06304 return status; 06305 } 06306 06307 /* Delete from keypairs */ 06308 sql3 = DdsInit("keypairs"); 06309 DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0); 06310 DdsEnd(&sql); 06311 06312 status = DbExecuteSqlNoResult(DbHandle(), sql3); 06313 DdsFree(sql3); 06314 if (status != 0) 06315 { 06316 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 06317 DbStringFree(temp_loc); 06318 DbFreeRow(row); 06319 return status; 06320 } 06321 06322 /* Delete from the HSM */ 06323 key = hsm_find_key_by_id(NULL, temp_loc); 06324 06325 if (!key) { 06326 printf("Key not found: %s\n", temp_loc); 06327 DbStringFree(temp_loc); 06328 DbFreeRow(row); 06329 return -1; 06330 } 06331 06332 status = hsm_remove_key(NULL, key); 06333 06334 hsm_key_free(key); 06335 06336 if (!status) { 06337 printf("Key remove successful.\n"); 06338 } else { 06339 printf("Key remove failed.\n"); 06340 DbStringFree(temp_loc); 06341 DbFreeRow(row); 06342 return -1; 06343 } 06344 } 06345 06346 /* NEXT! */ 06347 status = DbFetchRow(result, &row); 06348 } 06349 06350 /* Convert EOF status to success */ 06351 06352 if (status == -1) { 06353 status = 0; 06354 } 06355 06356 DbFreeResult(result); 06357 } 06358 06359 if (done_something == 0) { 06360 printf("No keys to purge.\n"); 06361 } 06362 06363 DusFree(sql); 06364 DbFreeRow(row); 06365 06366 DbStringFree(temp_loc); 06367 06368 return status; 06369 } 06370 06371 int cmd_genkeys() 06372 { 06373 int status = 0; 06374 06375 int interval = -1; 06376 06377 KSM_POLICY* policy; 06378 hsm_ctx_t *ctx = NULL; 06379 06380 char *rightnow; 06381 int i = 0; 06382 char *id; 06383 hsm_key_t *key = NULL; 06384 char *hsm_error_message = NULL; 06385 DB_ID ignore = 0; 06386 int ksks_needed = 0; /* Total No of ksks needed before next generation run */ 06387 int zsks_needed = 0; /* Total No of zsks needed before next generation run */ 06388 int keys_in_queue = 0; /* number of unused keys */ 06389 int new_keys = 0; /* number of keys required */ 06390 unsigned int current_count = 0; /* number of keys already in HSM */ 06391 06392 DB_RESULT result; 06393 int zone_count = 0; /* Number of zones on policy */ 06394 06395 int same_keys = 0; /* Do ksks and zsks look the same ? */ 06396 int ksks_created = 0; /* Were any KSKs created? */ 06397 06398 /* Database connection details */ 06399 DB_HANDLE dbhandle; 06400 FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ 06401 06402 /* try to connect to the database */ 06403 status = db_connect(&dbhandle, &lock_fd, 1); 06404 if (status != 0) { 06405 printf("Failed to connect to database\n"); 06406 db_disconnect(lock_fd); 06407 return(1); 06408 } 06409 06410 policy = KsmPolicyAlloc(); 06411 if (policy == NULL) { 06412 printf("Malloc for policy struct failed\n"); 06413 db_disconnect(lock_fd); 06414 exit(1); 06415 } 06416 06417 if (o_policy == NULL) { 06418 printf("Please provide a policy name with the --policy option\n"); 06419 db_disconnect(lock_fd); 06420 KsmPolicyFree(policy); 06421 return(1); 06422 } 06423 if (o_interval == NULL) { 06424 printf("Please provide an interval with the --interval option\n"); 06425 db_disconnect(lock_fd); 06426 KsmPolicyFree(policy); 06427 return(1); 06428 } 06429 06430 SetPolicyDefaults(policy, o_policy); 06431 06432 status = KsmPolicyExists(o_policy); 06433 if (status == 0) { 06434 /* Policy exists */ 06435 status = KsmPolicyRead(policy); 06436 if(status != 0) { 06437 printf("Error: unable to read policy %s from database\n", o_policy); 06438 db_disconnect(lock_fd); 06439 KsmPolicyFree(policy); 06440 return status; 06441 } 06442 } else { 06443 printf("Error: policy %s doesn't exist in database\n", o_policy); 06444 db_disconnect(lock_fd); 06445 KsmPolicyFree(policy); 06446 return status; 06447 } 06448 06449 if (policy->shared_keys == 1 ) { 06450 printf("Key sharing is On\n"); 06451 } else { 06452 printf("Key sharing is Off\n"); 06453 } 06454 06455 status = DtXMLIntervalSeconds(o_interval, &interval); 06456 if (status > 0) { 06457 printf("Error: unable to convert Interval %s to seconds, error: ", o_interval); 06458 switch (status) { 06459 case 1: /* This has gone away, will now return 2 */ 06460 printf("invalid interval-type.\n"); 06461 break; 06462 case 2: 06463 printf("unable to translate string.\n"); 06464 break; 06465 case 3: 06466 printf("interval too long to be an int. E.g. Maximum is ~68 years on a system with 32-bit integers.\n"); 06467 break; 06468 case 4: 06469 printf("invalid pointers or text string NULL.\n"); 06470 break; 06471 default: 06472 printf("unknown\n"); 06473 } 06474 db_disconnect(lock_fd); 06475 KsmPolicyFree(policy); 06476 return status; 06477 } 06478 else if (status == -1) { 06479 printf("Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days\n", o_interval); 06480 } 06481 06482 /* Connect to the hsm */ 06483 status = hsm_open(config, hsm_prompt_pin, NULL); 06484 if (status) { 06485 hsm_error_message = hsm_get_error(ctx); 06486 if (hsm_error_message) { 06487 printf("%s\n", hsm_error_message); 06488 free(hsm_error_message); 06489 } else { 06490 /* decode the error code ourselves 06491 TODO find if there is a better way to do this (and can all of these be returned? are there others?) */ 06492 switch (status) { 06493 case HSM_ERROR: 06494 printf("hsm_open() result: HSM error\n"); 06495 break; 06496 case HSM_PIN_INCORRECT: 06497 printf("hsm_open() result: incorrect PIN\n"); 06498 break; 06499 case HSM_CONFIG_FILE_ERROR: 06500 printf("hsm_open() result: config file error\n"); 06501 break; 06502 case HSM_REPOSITORY_NOT_FOUND: 06503 printf("hsm_open() result: repository not found\n"); 06504 break; 06505 case HSM_NO_REPOSITORIES: 06506 printf("hsm_open() result: no repositories\n"); 06507 break; 06508 default: 06509 printf("hsm_open() result: %d", status); 06510 } 06511 } 06512 db_disconnect(lock_fd); 06513 KsmPolicyFree(policy); 06514 exit(1); 06515 } 06516 printf("HSM opened successfully.\n"); 06517 ctx = hsm_create_context(); 06518 06519 rightnow = DtParseDateTimeString("now"); 06520 06521 /* Check datetime in case it came back NULL */ 06522 if (rightnow == NULL) { 06523 printf("Couldn't turn \"now\" into a date, quitting...\n"); 06524 db_disconnect(lock_fd); 06525 KsmPolicyFree(policy); 06526 exit(1); 06527 } 06528 06529 if (policy->ksk->sm == policy->zsk->sm && policy->ksk->bits == policy->zsk->bits && policy->ksk->algorithm == policy->zsk->algorithm) { 06530 same_keys = 1; 06531 } else { 06532 same_keys = 0; 06533 } 06534 06535 /* How many zones on this policy */ 06536 status = KsmZoneCountInit(&result, policy->id); 06537 if (status == 0) { 06538 status = KsmZoneCount(result, &zone_count); 06539 } 06540 DbFreeResult(result); 06541 06542 if (status == 0) { 06543 /* make sure that we have at least one zone */ 06544 if (zone_count == 0) { 06545 printf("No zones on policy %s, skipping...", policy->name); 06546 db_disconnect(lock_fd); 06547 if (ctx) { 06548 hsm_destroy_context(ctx); 06549 } 06550 hsm_close(); 06551 KsmPolicyFree(policy); 06552 return status; 06553 } 06554 } else { 06555 printf("Could not count zones on policy %s", policy->name); 06556 db_disconnect(lock_fd); 06557 if (ctx) { 06558 hsm_destroy_context(ctx); 06559 } 06560 hsm_close(); 06561 KsmPolicyFree(policy); 06562 return status; 06563 } 06564 06565 /* Find out how many ksk keys are needed for the POLICY */ 06566 status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count); 06567 if (status != 0) { 06568 printf("Could not predict ksk requirement for next interval for %s\n", policy->name); 06569 /* TODO exit? continue with next policy? */ 06570 } 06571 /* Find out how many suitable keys we have */ 06572 status = KsmKeyCountStillGood(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, interval, rightnow, &keys_in_queue, KSM_TYPE_KSK); 06573 if (status != 0) { 06574 printf("Could not count current ksk numbers for policy %s\n", policy->name); 06575 /* TODO exit? continue with next policy? */ 06576 } 06577 /* Correct for shared keys */ 06578 if (policy->shared_keys == KSM_KEYS_SHARED) { 06579 keys_in_queue /= zone_count; 06580 } 06581 06582 new_keys = ksks_needed - keys_in_queue; 06583 /* fprintf(stderr, "keygen(ksk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, ksks_needed, keys_in_queue); */ 06584 06585 /* Check capacity of HSM will not be exceeded */ 06586 if (policy->ksk->sm_capacity != 0 && new_keys > 0) { 06587 current_count = hsm_count_keys_repository(ctx, policy->ksk->sm_name); 06588 if (current_count >= policy->ksk->sm_capacity) { 06589 printf("Repository %s is full, cannot create more KSKs for policy %s\n", policy->ksk->sm_name, policy->name); 06590 new_keys = 0; 06591 } 06592 else if (current_count + new_keys > policy->ksk->sm_capacity) { 06593 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_keys); 06594 new_keys = policy->ksk->sm_capacity - current_count; 06595 } 06596 } 06597 06598 /* Create the required keys */ 06599 for (i=new_keys ; i > 0 ; i--){ 06600 if (hsm_supported_algorithm(policy->ksk->algorithm) == 0) { 06601 /* NOTE: for now we know that libhsm only supports RSA keys */ 06602 key = hsm_generate_rsa_key(ctx, policy->ksk->sm_name, policy->ksk->bits); 06603 if (key) { 06604 if (verbose_flag) { 06605 printf("Created key in repository %s\n", policy->ksk->sm_name); 06606 } 06607 } else { 06608 printf("Error creating key in repository %s\n", policy->ksk->sm_name); 06609 hsm_error_message = hsm_get_error(ctx); 06610 if (hsm_error_message) { 06611 printf("%s\n", hsm_error_message); 06612 free(hsm_error_message); 06613 } 06614 db_disconnect(lock_fd); 06615 KsmPolicyFree(policy); 06616 exit(1); 06617 } 06618 id = hsm_get_key_id(ctx, key); 06619 hsm_key_free(key); 06620 status = KsmKeyPairCreate(policy->id, id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, rightnow, &ignore); 06621 if (status != 0) { 06622 printf("Error creating key in Database\n"); 06623 hsm_error_message = hsm_get_error(ctx); 06624 if (hsm_error_message) { 06625 printf("%s\n", hsm_error_message); 06626 free(hsm_error_message); 06627 } 06628 db_disconnect(lock_fd); 06629 KsmPolicyFree(policy); 06630 exit(1); 06631 } 06632 printf("Created KSK size: %i, alg: %i with id: %s in repository: %s and database.\n", policy->ksk->bits, 06633 policy->ksk->algorithm, id, policy->ksk->sm_name); 06634 free(id); 06635 } else { 06636 printf("Key algorithm %d unsupported by libhsm.\n", policy->ksk->algorithm); 06637 db_disconnect(lock_fd); 06638 KsmPolicyFree(policy); 06639 exit(1); 06640 } 06641 } 06642 ksks_created = new_keys; 06643 06644 /* Find out how many zsk keys are needed */ 06645 keys_in_queue = 0; 06646 new_keys = 0; 06647 current_count = 0; 06648 06649 /* Find out how many zsk keys are needed for the POLICY */ 06650 status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, interval, &zsks_needed, 0, zone_count); 06651 if (status != 0) { 06652 printf("Could not predict zsk requirement for next interval for %s\n", policy->name); 06653 /* TODO exit? continue with next policy? */ 06654 } 06655 /* Find out how many suitable keys we have */ 06656 status = KsmKeyCountStillGood(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, interval, rightnow, &keys_in_queue, KSM_TYPE_ZSK); 06657 if (status != 0) { 06658 printf("Could not count current zsk numbers for policy %s\n", policy->name); 06659 /* TODO exit? continue with next policy? */ 06660 } 06661 /* Correct for shared keys */ 06662 if (policy->shared_keys == KSM_KEYS_SHARED) { 06663 keys_in_queue /= zone_count; 06664 } 06665 /* Might have to account for ksks */ 06666 if (same_keys) { 06667 keys_in_queue -= ksks_needed; 06668 } 06669 06670 new_keys = zsks_needed - keys_in_queue; 06671 /* fprintf(stderr, "keygen(zsk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, zsks_needed, keys_in_queue); */ 06672 06673 /* Check capacity of HSM will not be exceeded */ 06674 if (policy->zsk->sm_capacity != 0 && new_keys > 0) { 06675 current_count = hsm_count_keys_repository(ctx, policy->zsk->sm_name); 06676 if (current_count >= policy->zsk->sm_capacity) { 06677 printf("Repository %s is full, cannot create more ZSKs for policy %s\n", policy->zsk->sm_name, policy->name); 06678 new_keys = 0; 06679 } 06680 else if (current_count + new_keys > policy->zsk->sm_capacity) { 06681 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_keys); 06682 new_keys = policy->zsk->sm_capacity - current_count; 06683 } 06684 } 06685 06686 /* Create the required keys */ 06687 for (i = new_keys ; i > 0 ; i--) { 06688 if (hsm_supported_algorithm(policy->zsk->algorithm) == 0) { 06689 /* NOTE: for now we know that libhsm only supports RSA keys */ 06690 key = hsm_generate_rsa_key(ctx, policy->zsk->sm_name, policy->zsk->bits); 06691 if (key) { 06692 if (verbose_flag) { 06693 printf("Created key in repository %s\n", policy->zsk->sm_name); 06694 } 06695 } else { 06696 printf("Error creating key in repository %s\n", policy->zsk->sm_name); 06697 hsm_error_message = hsm_get_error(ctx); 06698 if (hsm_error_message) { 06699 printf("%s\n", hsm_error_message); 06700 free(hsm_error_message); 06701 } 06702 db_disconnect(lock_fd); 06703 KsmPolicyFree(policy); 06704 exit(1); 06705 } 06706 id = hsm_get_key_id(ctx, key); 06707 hsm_key_free(key); 06708 status = KsmKeyPairCreate(policy->id, id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, rightnow, &ignore); 06709 if (status != 0) { 06710 printf("Error creating key in Database\n"); 06711 hsm_error_message = hsm_get_error(ctx); 06712 if (hsm_error_message) { 06713 printf("%s\n", hsm_error_message); 06714 free(hsm_error_message); 06715 } 06716 db_disconnect(lock_fd); 06717 KsmPolicyFree(policy); 06718 exit(1); 06719 } 06720 printf("Created ZSK size: %i, alg: %i with id: %s in repository: %s and database.\n", policy->zsk->bits, 06721 policy->zsk->algorithm, id, policy->zsk->sm_name); 06722 free(id); 06723 } else { 06724 printf("Key algorithm %d unsupported by libhsm.\n", policy->zsk->algorithm); 06725 db_disconnect(lock_fd); 06726 KsmPolicyFree(policy); 06727 exit(1); 06728 } 06729 } 06730 StrFree(rightnow); 06731 06732 /* Log if a backup needs to be run for these keys */ 06733 if (ksks_created && policy->ksk->require_backup) { 06734 printf("NOTE: keys generated in repository %s will not become active until they have been backed up\n", policy->ksk->sm_name); 06735 } 06736 if (new_keys && policy->zsk->require_backup && (policy->zsk->sm != policy->ksk->sm)) { 06737 printf("NOTE: keys generated in repository %s will not become active until they have been backed up\n", policy->zsk->sm_name); 06738 } 06739 06740 /* 06741 * Destroy HSM context 06742 */ 06743 if (ctx) { 06744 hsm_destroy_context(ctx); 06745 } 06746 status = hsm_close(); 06747 printf("all done! hsm_close result: %d\n", status); 06748 06749 KsmPolicyFree(policy); 06750 06751 /* Release sqlite lock file (if we have it) */ 06752 db_disconnect(lock_fd); 06753 06754 return status; 06755 } 06756 06757 /* Make sure (if we can) that the permissions on a file are correct for the user/group in conf.xml */ 06758 06759 int fix_file_perms(const char *dbschema) 06760 { 06761 struct stat stat_ret; 06762 06763 int status = 0; 06764 06765 xmlDocPtr doc = NULL; 06766 xmlDocPtr rngdoc = NULL; 06767 xmlXPathContextPtr xpathCtx = NULL; 06768 xmlXPathObjectPtr xpathObj = NULL; 06769 xmlRelaxNGParserCtxtPtr rngpctx = NULL; 06770 xmlRelaxNGValidCtxtPtr rngctx = NULL; 06771 xmlRelaxNGPtr schema = NULL; 06772 xmlChar *user_expr = (unsigned char*) "//Configuration/Enforcer/Privileges/User"; 06773 xmlChar *group_expr = (unsigned char*) "//Configuration/Enforcer/Privileges/Group"; 06774 06775 char* filename = OPENDNSSEC_CONFIG_FILE; 06776 char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng"; 06777 char* temp_char = NULL; 06778 06779 struct passwd *pwd; 06780 struct group *grp; 06781 06782 int uid = -1; 06783 int gid = -1; 06784 char *username = NULL; 06785 char *groupname = NULL; 06786 06787 printf("fixing permissions on file %s\n", dbschema); 06788 /* First see if we are running as root, if not then return */ 06789 if (geteuid() != 0) { 06790 return 0; 06791 } 06792 06793 /* Now see if the file exists, if it does not then return */ 06794 if (stat(dbschema, &stat_ret) != 0) { 06795 printf("cannot stat file %s: %s", dbschema, strerror(errno)); 06796 return -1; 06797 } 06798 06799 /* OKAY... read conf.xml for the user and group */ 06800 /* Load XML document */ 06801 doc = xmlParseFile(filename); 06802 if (doc == NULL) { 06803 printf("Error: unable to parse file \"%s\"", filename); 06804 return(-1); 06805 } 06806 06807 /* Load rng document */ 06808 rngdoc = xmlParseFile(rngfilename); 06809 if (rngdoc == NULL) { 06810 printf("Error: unable to parse file \"%s\"", rngfilename); 06811 return(-1); 06812 } 06813 06814 /* Create an XML RelaxNGs parser context for the relax-ng document. */ 06815 rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc); 06816 if (rngpctx == NULL) { 06817 printf("Error: unable to create XML RelaxNGs parser context"); 06818 return(-1); 06819 } 06820 06821 /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */ 06822 schema = xmlRelaxNGParse(rngpctx); 06823 if (schema == NULL) { 06824 printf("Error: unable to parse a schema definition resource"); 06825 return(-1); 06826 } 06827 06828 /* Create an XML RelaxNGs validation context based on the given schema */ 06829 rngctx = xmlRelaxNGNewValidCtxt(schema); 06830 if (rngctx == NULL) { 06831 printf("Error: unable to create RelaxNGs validation context based on the schema"); 06832 return(-1); 06833 } 06834 06835 /* Validate a document tree in memory. */ 06836 status = xmlRelaxNGValidateDoc(rngctx,doc); 06837 if (status != 0) { 06838 printf("Error validating file \"%s\"", filename); 06839 return(-1); 06840 } 06841 06842 /* Now parse a value out of the conf */ 06843 /* Create xpath evaluation context */ 06844 xpathCtx = xmlXPathNewContext(doc); 06845 if(xpathCtx == NULL) { 06846 printf("Error: unable to create new XPath context"); 06847 xmlFreeDoc(doc); 06848 return(-1); 06849 } 06850 06851 /* Set the group if specified */ 06852 xpathObj = xmlXPathEvalExpression(group_expr, xpathCtx); 06853 if(xpathObj == NULL) { 06854 printf("Error: unable to evaluate xpath expression: %s", group_expr); 06855 xmlXPathFreeContext(xpathCtx); 06856 xmlFreeDoc(doc); 06857 return(-1); 06858 } 06859 if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 06860 temp_char = (char*) xmlXPathCastToString(xpathObj); 06861 StrAppend(&groupname, temp_char); 06862 StrFree(temp_char); 06863 xmlXPathFreeObject(xpathObj); 06864 } else { 06865 groupname = NULL; 06866 } 06867 06868 /* Set the user to drop to if specified */ 06869 xpathObj = xmlXPathEvalExpression(user_expr, xpathCtx); 06870 if(xpathObj == NULL) { 06871 printf("Error: unable to evaluate xpath expression: %s", user_expr); 06872 xmlXPathFreeContext(xpathCtx); 06873 xmlFreeDoc(doc); 06874 return(-1); 06875 } 06876 if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 06877 temp_char = (char*) xmlXPathCastToString(xpathObj); 06878 StrAppend(&username, temp_char); 06879 StrFree(temp_char); 06880 xmlXPathFreeObject(xpathObj); 06881 } else { 06882 username = NULL; 06883 } 06884 06885 /* Free up the xml stuff, we are done with it */ 06886 xmlXPathFreeContext(xpathCtx); 06887 xmlRelaxNGFree(schema); 06888 xmlRelaxNGFreeValidCtxt(rngctx); 06889 xmlRelaxNGFreeParserCtxt(rngpctx); 06890 xmlFreeDoc(doc); 06891 xmlFreeDoc(rngdoc); 06892 06893 /* Set uid and gid if required */ 06894 if (username != NULL) { 06895 /* Lookup the user id in /etc/passwd */ 06896 if ((pwd = getpwnam(username)) == NULL) { 06897 printf("user '%s' does not exist. cannot chown %s...\n", username, dbschema); 06898 return(1); 06899 } else { 06900 uid = pwd->pw_uid; 06901 } 06902 endpwent(); 06903 } 06904 if (groupname) { 06905 /* Lookup the group id in /etc/groups */ 06906 if ((grp = getgrnam(groupname)) == NULL) { 06907 printf("group '%s' does not exist. cannot chown %s...\n", groupname, dbschema); 06908 exit(1); 06909 } else { 06910 gid = grp->gr_gid; 06911 } 06912 endgrent(); 06913 } 06914 06915 /* Change ownership of the db file */ 06916 if (chown(dbschema, uid, gid) == -1) { 06917 printf("cannot chown(%u,%u) %s: %s", 06918 (unsigned) uid, (unsigned) gid, dbschema, strerror(errno)); 06919 return -1; 06920 } 06921 06922 /* and change ownership of the lock file */ 06923 temp_char = NULL; 06924 StrAppend(&temp_char, dbschema); 06925 StrAppend(&temp_char, ".our_lock"); 06926 06927 if (chown(temp_char, uid, gid) == -1) { 06928 printf("cannot chown(%u,%u) %s: %s", 06929 (unsigned) uid, (unsigned) gid, temp_char, strerror(errno)); 06930 StrFree(temp_char); 06931 return -1; 06932 } 06933 06934 StrFree(temp_char); 06935 06936 return 0; 06937 } 06938 06939 /*+ 06940 * CountKeys - Find how many Keys match our criteria 06941 * 06942 * 06943 * Arguments: 06944 * 06945 * int zone_id 06946 * ID of the zone (-1 for all) 06947 * 06948 * int keytag 06949 * keytag provided (-1 if not specified) 06950 * 06951 * const char * cka_id 06952 * cka_id provided (NULL if not) 06953 * 06954 * int * key_count (returned) 06955 * count of keys matching the information specified 06956 * 06957 * char ** temp_cka_id (returned) 06958 * cka_id of key found 06959 * 06960 * int * temp_key_state (returned) 06961 * What state is the key in (only used if _one_ key returned) 06962 * 06963 * int * temp_keypair_id (returned) 06964 * ID of the key found (only used if _one_ key returned) 06965 * Returns: 06966 * int 06967 * Status return. 0 on success. 06968 * other on fail 06969 */ 06970 06971 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) 06972 { 06973 char* sql = NULL; /* SQL query */ 06974 int status = 0; /* Status return */ 06975 char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */ 06976 DB_RESULT result; /* Result of the query */ 06977 DB_ROW row = NULL; /* Row data */ 06978 06979 char buffer[256]; /* For constructing part of the command */ 06980 size_t nchar; /* Number of characters written */ 06981 06982 int done_row = 0; /* Have we found a key this loop? */ 06983 06984 int temp_zone_id = 0; /* place to store zone_id returned */ 06985 char* temp_loc = NULL; /* place to store location returned */ 06986 int temp_alg = 0; /* place to store algorithm returned */ 06987 int temp_state = 0; /* place to store state returned */ 06988 int temp_keypair = 0; /* place to store id returned */ 06989 06990 int temp_count = 0; /* Count of keys found */ 06991 06992 /* Key information */ 06993 hsm_key_t *key = NULL; 06994 ldns_rr *dnskey_rr = NULL; 06995 hsm_sign_params_t *sign_params = NULL; 06996 06997 /* connect to the HSM */ 06998 status = hsm_open(config, hsm_prompt_pin, NULL); 06999 if (status) { 07000 hsm_print_error(NULL); 07001 return(-1); 07002 } 07003 07004 /* Select rows */ 07005 nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d)", 07006 KSM_STATE_READY, KSM_STATE_ACTIVE, KSM_STATE_DSSUB); 07007 if (nchar >= sizeof(buffer)) { 07008 printf("Error: Overran buffer in CountKeys\n"); 07009 return(-1); 07010 } 07011 07012 /* TODO do I need to use the view */ 07013 StrAppend(&sql, "select k.zone_id, k.location, k.algorithm, k.state, k.id from KEYDATA_VIEW k where state in "); 07014 StrAppend(&sql, buffer); 07015 StrAppend(&sql, " and zone_id is not null and k.keytype = 257"); 07016 07017 if (*zone_id != -1) { 07018 StrAppend(&sql, " and zone_id = "); 07019 snprintf(stringval, KSM_INT_STR_SIZE, "%d", *zone_id); 07020 StrAppend(&sql, stringval); 07021 } 07022 if (cka_id != NULL) { 07023 StrAppend(&sql, " and k.location = '"); 07024 StrAppend(&sql, cka_id); 07025 StrAppend(&sql, "'"); 07026 } 07027 /* where location is unique? */ 07028 StrAppend(&sql, " group by location"); 07029 07030 DusEnd(&sql); 07031 07032 status = DbExecuteSql(DbHandle(), sql, &result); 07033 07034 /* loop round printing out the cka_id of any key that matches 07035 * if only one does then we are good, if not then we will write a 07036 * message asking for further clarification */ 07037 /* Note that we only need to do each key, not each instance of a key */ 07038 if (status == 0) { 07039 status = DbFetchRow(result, &row); 07040 while (status == 0) { 07041 /* Got a row, process it */ 07042 DbInt(row, 0, &temp_zone_id); 07043 DbString(row, 1, &temp_loc); 07044 DbInt(row, 2, &temp_alg); 07045 DbInt(row, 3, &temp_state); 07046 DbInt(row, 4, &temp_keypair); 07047 07048 done_row = 0; 07049 07050 if (keytag == -1 && cka_id == NULL) 07051 { 07052 *temp_key_state = temp_state; 07053 } 07054 07055 key = hsm_find_key_by_id(NULL, temp_loc); 07056 if (!key) { 07057 printf("cka_id %-33s in DB but NOT IN repository\n", temp_loc); 07058 } else if (keytag != -1) { 07059 sign_params = hsm_sign_params_new(); 07060 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "temp_zone"); 07061 sign_params->algorithm = temp_alg; 07062 sign_params->flags = LDNS_KEY_ZONE_KEY; 07063 sign_params->flags += LDNS_KEY_SEP_KEY; 07064 07065 dnskey_rr = hsm_get_dnskey(NULL, key, sign_params); 07066 sign_params->keytag = ldns_calc_keytag(dnskey_rr); 07067 07068 /* Have we matched our keytag? */ 07069 if (keytag == sign_params->keytag) { 07070 temp_count++; 07071 done_row = 1; 07072 *temp_cka_id = NULL; 07073 StrAppend(temp_cka_id, temp_loc); 07074 *zone_id = temp_zone_id; 07075 *temp_key_state = temp_state; 07076 *temp_keypair_id = temp_keypair; 07077 printf("Found key with CKA_ID %s\n", temp_loc); 07078 } 07079 07080 hsm_sign_params_free(sign_params); 07081 } 07082 if (key && cka_id != NULL && strncmp(cka_id, temp_loc, strlen(temp_loc)) == 0) { 07083 /* Or have we matched a provided cka_id */ 07084 if (done_row == 0) { 07085 temp_count++; 07086 *temp_cka_id = NULL; 07087 StrAppend(temp_cka_id, temp_loc); 07088 *zone_id = temp_zone_id; 07089 *temp_key_state = temp_state; 07090 *temp_keypair_id = temp_keypair; 07091 printf("Found key with CKA_ID %s\n", temp_loc); 07092 } 07093 } 07094 07095 if (key) { 07096 hsm_key_free(key); 07097 } 07098 07099 status = DbFetchRow(result, &row); 07100 } 07101 07102 /* Convert EOF status to success */ 07103 07104 if (status == -1) { 07105 status = 0; 07106 } 07107 07108 DbFreeResult(result); 07109 } 07110 07111 *key_count = temp_count; 07112 07113 DusFree(sql); 07114 DbFreeRow(row); 07115 07116 DbStringFree(temp_loc); 07117 07118 if (dnskey_rr != NULL) { 07119 ldns_rr_free(dnskey_rr); 07120 } 07121 07122 return status; 07123 } 07124 07125 /*+ 07126 * MarkDSSeen - Indicate that the DS record has been observed: 07127 * Change the state of the key to ACTIVE 07128 * 07129 * Arguments: 07130 * 07131 * const char * cka_id 07132 * cka_id of key to make active 07133 * 07134 * int zone_id 07135 * ID of the zone 07136 * 07137 * int policy_id 07138 * ID of the policy 07139 * 07140 * const char * datetime 07141 * when this is happening 07142 * 07143 * int key_state 07144 * state that the key is in 07145 * 07146 * Returns: 07147 * int 07148 * Status return. 0 on success. 07149 * other on fail 07150 */ 07151 07152 int MarkDSSeen(int keypair_id, int zone_id, int policy_id, const char *datetime, int key_state) 07153 { 07154 char* sql1 = NULL; /* SQL query */ 07155 int status = 0; /* Status return */ 07156 07157 char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */ 07158 unsigned int nchar; /* Number of characters converted */ 07159 07160 KSM_PARCOLL collection; /* Collection of parameters for zone */ 07161 int deltat; /* Time interval */ 07162 07163 (void) zone_id; 07164 07165 /* Set collection defaults */ 07166 KsmCollectionInit(&collection); 07167 07168 /* Get the values of the parameters */ 07169 status = KsmParameterCollection(&collection, policy_id); 07170 if (status != 0) { 07171 printf("Error: failed to read policy\n"); 07172 return status; 07173 } 07174 07175 /* 0) Start a transaction */ 07176 status = DbBeginTransaction(); 07177 if (status != 0) { 07178 /* Something went wrong */ 07179 07180 MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07181 return status; 07182 } 07183 07184 /* 1) Change the state of the selected Key */ 07185 if (key_state == KSM_STATE_READY) { 07186 /* We are making a key active */ 07187 07188 /* Set the interval until Retire */ 07189 deltat = collection.ksklife; 07190 07191 #ifdef USE_MYSQL 07192 nchar = snprintf(buffer, sizeof(buffer), 07193 "DATE_ADD('%s', INTERVAL %d SECOND) ", datetime, deltat); 07194 #else 07195 nchar = snprintf(buffer, sizeof(buffer), 07196 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat); 07197 #endif /* USE_MYSQL */ 07198 07199 sql1 = DusInit("dnsseckeys"); 07200 DusSetInt(&sql1, "STATE", KSM_STATE_ACTIVE, 0); 07201 DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_ACTIVE), datetime, 1); 07202 StrAppend(&sql1, ", RETIRE = "); 07203 StrAppend(&sql1, buffer); 07204 07205 DusConditionInt(&sql1, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0); 07206 DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1); 07207 DusEnd(&sql1); 07208 } 07209 else { 07210 /* We are making a standby key DSpublish */ 07211 07212 /* Set the interval until DSReady */ 07213 deltat = collection.kskttl + collection.kskpropdelay + 07214 collection.pub_safety; 07215 07216 #ifdef USE_MYSQL 07217 nchar = snprintf(buffer, sizeof(buffer), 07218 "DATE_ADD('%s', INTERVAL %d SECOND) ", datetime, deltat); 07219 #else 07220 nchar = snprintf(buffer, sizeof(buffer), 07221 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat); 07222 #endif /* USE_MYSQL */ 07223 07224 sql1 = DusInit("dnsseckeys"); 07225 DusSetInt(&sql1, "STATE", KSM_STATE_DSPUBLISH, 0); 07226 DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_PUBLISH), datetime, 1); 07227 StrAppend(&sql1, ", READY = "); 07228 StrAppend(&sql1, buffer); 07229 07230 DusConditionInt(&sql1, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0); 07231 DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1); 07232 DusEnd(&sql1); 07233 } 07234 07235 status = DbExecuteSqlNoResult(DbHandle(), sql1); 07236 DusFree(sql1); 07237 07238 /* Report any errors */ 07239 if (status != 0) { 07240 status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07241 DbRollback(); 07242 return status; 07243 } 07244 07245 /* 3) Commit or Rollback */ 07246 if (status == 0) { /* It actually can't be anything else */ 07247 /* Everything worked by the looks of it */ 07248 DbCommit(); 07249 } else { 07250 /* Whatever happened, it was not good */ 07251 DbRollback(); 07252 } 07253 07254 return status; 07255 } 07256 07257 /*+ 07258 * RetireOldKey - Retire the old KSK 07259 * 07260 * 07261 * Arguments: 07262 * 07263 * int zone_id 07264 * ID of the zone 07265 * 07266 * int policy_id 07267 * ID of the policy 07268 * 07269 * const char * datetime 07270 * when this is happening 07271 * 07272 * Returns: 07273 * int 07274 * Status return. 0 on success. 07275 * other on fail 07276 */ 07277 07278 int RetireOldKey(int zone_id, int policy_id, const char *datetime) 07279 { 07280 char* sql2 = NULL; /* SQL query */ 07281 int status = 0; /* Status return */ 07282 char* where_clause = NULL; 07283 int id = -1; /* ID of key to retire */ 07284 07285 char stringval[KSM_INT_STR_SIZE]; /* For Integer to String conversion */ 07286 char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */ 07287 unsigned int nchar; /* Number of characters converted */ 07288 07289 KSM_PARCOLL collection; /* Collection of parameters for zone */ 07290 int deltat; /* Time interval */ 07291 07292 /* Set collection defaults */ 07293 KsmCollectionInit(&collection); 07294 07295 /* Get the values of the parameters */ 07296 status = KsmParameterCollection(&collection, policy_id); 07297 if (status != 0) { 07298 printf("Error: failed to read policy\n"); 07299 return status; 07300 } 07301 07302 /* 0) Start a transaction */ 07303 status = DbBeginTransaction(); 07304 if (status != 0) { 07305 /* Something went wrong */ 07306 07307 MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07308 return status; 07309 } 07310 07311 /* 1) Retire the oldest active key, and set its deadtime */ 07312 /* work out which key */ 07313 snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id); 07314 StrAppend(&where_clause, "select id from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = "); 07315 StrAppend(&where_clause, stringval); 07316 StrAppend(&where_clause, " and retire = (select min(retire) from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = "); 07317 StrAppend(&where_clause, stringval); 07318 StrAppend(&where_clause, ")"); 07319 07320 /* Execute query and free up the query string */ 07321 status = DbIntQuery(DbHandle(), &id, where_clause); 07322 StrFree(where_clause); 07323 if (status != 0) 07324 { 07325 printf("Error: failed to find ID of key to retire\n"); 07326 DbRollback(); 07327 return status; 07328 } 07329 07330 /* work out what its deadtime should become */ 07331 deltat = collection.dsttl + collection.kskpropdelay + collection.ret_safety; 07332 07333 #ifdef USE_MYSQL 07334 nchar = snprintf(buffer, sizeof(buffer), 07335 "DATE_ADD('%s', INTERVAL %d SECOND) ", datetime, deltat); 07336 #else 07337 nchar = snprintf(buffer, sizeof(buffer), 07338 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat); 07339 #endif /* USE_MYSQL */ 07340 07341 sql2 = DusInit("dnsseckeys"); 07342 DusSetInt(&sql2, "STATE", KSM_STATE_RETIRE, 0); 07343 DusSetString(&sql2, KsmKeywordStateValueToName(KSM_STATE_RETIRE), datetime, 1); 07344 StrAppend(&sql2, ", DEAD = "); 07345 StrAppend(&sql2, buffer); 07346 DusConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, id, 0); 07347 DusConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1); 07348 07349 status = DbExecuteSqlNoResult(DbHandle(), sql2); 07350 DusFree(sql2); 07351 07352 /* Report any errors */ 07353 if (status != 0) { 07354 status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07355 DbRollback(); 07356 return status; 07357 } 07358 07359 /* 2) Commit or Rollback */ 07360 if (status == 0) { /* It actually can't be anything else */ 07361 /* Everything worked by the looks of it */ 07362 DbCommit(); 07363 } else { 07364 /* Whatever happened, it was not good */ 07365 DbRollback(); 07366 } 07367 07368 return status; 07369 } 07370 07371 /* 07372 * CountKeysInState - Count Keys in given state 07373 * 07374 * Description: 07375 * Counts the number of keys in the given state. 07376 * 07377 * Arguments: 07378 * int keytype 07379 * Either KSK or ZSK, depending on the key type 07380 * 07381 * int keystate 07382 * State of keys to count 07383 * 07384 * int* count 07385 * Number of keys meeting the condition. 07386 * 07387 * int zone_id 07388 * ID of zone that we are looking at (-1 == all zones) 07389 * 07390 * Returns: 07391 * int 07392 * Status return. 0 => success, Other => error, in which case a message 07393 * will have been output. 07394 -*/ 07395 07396 int CountKeysInState(int keytype, int keystate, int* count, int zone_id) 07397 { 07398 int clause = 0; /* Clause counter */ 07399 char* sql = NULL; /* SQL command */ 07400 int status; /* Status return */ 07401 07402 sql = DqsCountInit("KEYDATA_VIEW"); 07403 DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++); 07404 DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, keystate, clause++); 07405 if (zone_id != -1) { 07406 DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++); 07407 } 07408 DqsEnd(&sql); 07409 07410 status = DbIntQuery(DbHandle(), count, sql); 07411 DqsFree(sql); 07412 07413 if (status != 0) { 07414 printf("Error in CountKeysInState\n"); 07415 } 07416 07417 return status; 07418 } 07419 07420 /*+ 07421 * ChangeKeyState - Change the state of the specified key 07422 * 07423 * Arguments: 07424 * 07425 * int keytype 07426 * type of key we are dealing with 07427 * 07428 * const char * cka_id 07429 * cka_id of key to change 07430 * 07431 * int zone_id 07432 * ID of the zone 07433 * 07434 * int policy_id 07435 * ID of the policy 07436 * 07437 * const char * datetime 07438 * when this is happening 07439 * 07440 * int keystate 07441 * state that the key should be moved to 07442 * 07443 * Returns: 07444 * int 07445 * Status return. 0 on success. 07446 * other on fail 07447 * 07448 * TODO take keytimings out of here 07449 */ 07450 07451 int ChangeKeyState(int keytype, const char *cka_id, int zone_id, int policy_id, const char *datetime, int keystate) 07452 { 07453 char* sql1 = NULL; /* SQL query */ 07454 int status = 0; /* Status return */ 07455 07456 int count = 0; /* Count of keys whose date will be set */ 07457 char* sql = NULL; /* For creating the SQL command */ 07458 int where = 0; /* For the SQL selection */ 07459 int i = 0; /* A counter */ 07460 int j = 0; /* Another counter */ 07461 char* insql = NULL; /* SQL "IN" clause */ 07462 int* keyids; /* List of IDs of keys to promote */ 07463 DB_RESULT result; /* List result set */ 07464 KSM_KEYDATA data; /* Data for this key */ 07465 07466 char buffer[KSM_SQL_SIZE]; /* Long enough for any statement */ 07467 unsigned int nchar; /* Number of characters converted */ 07468 07469 KSM_PARCOLL collection; /* Collection of parameters for zone */ 07470 int deltat = 0; /* Time interval */ 07471 07472 (void) zone_id; 07473 07474 /* Set collection defaults */ 07475 KsmCollectionInit(&collection); 07476 07477 /* Get the values of the parameters */ 07478 status = KsmParameterCollection(&collection, policy_id); 07479 if (status != 0) { 07480 printf("Error: failed to read policy\n"); 07481 return status; 07482 } 07483 07484 /* Count how many keys will have their state changed */ 07485 07486 sql = DqsCountInit("KEYDATA_VIEW"); 07487 DqsConditionString(&sql, "location", DQS_COMPARE_EQ, cka_id, where++); 07488 if (zone_id != -1) { 07489 DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++); 07490 } 07491 DqsEnd(&sql); 07492 07493 status = DbIntQuery(DbHandle(), &count, sql); 07494 DqsFree(sql); 07495 07496 if (status != 0) { 07497 status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07498 return status; 07499 } 07500 07501 if (count == 0) { 07502 /* Nothing to do, error? */ 07503 return status; 07504 } 07505 07506 /* Allocate space for the list of key IDs */ 07507 keyids = MemMalloc(count * sizeof(int)); 07508 07509 /* Get the list of IDs */ 07510 07511 where = 0; 07512 sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS); 07513 DqsConditionString(&sql, "location", DQS_COMPARE_EQ, cka_id, where++); 07514 if (zone_id != -1) { 07515 DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++); 07516 } 07517 DqsEnd(&sql); 07518 07519 status = KsmKeyInitSql(&result, sql); 07520 DqsFree(sql); 07521 07522 if (status == 0) { 07523 while (status == 0) { 07524 status = KsmKey(result, &data); 07525 if (status == 0) { 07526 keyids[i] = data.keypair_id; 07527 i++; 07528 } 07529 } 07530 07531 /* Convert EOF status to success */ 07532 07533 if (status == -1) { 07534 status = 0; 07535 } else { 07536 status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07537 StrFree(keyids); 07538 return status; 07539 } 07540 07541 KsmKeyEnd(result); 07542 07543 } else { 07544 status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07545 StrFree(keyids); 07546 return status; 07547 } 07548 07549 /* 07550 * Now construct the "IN" statement listing the IDs of the keys we 07551 * are planning to change the state of. 07552 */ 07553 07554 StrAppend(&insql, "("); 07555 for (j = 0; j < i; ++j) { 07556 if (j != 0) { 07557 StrAppend(&insql, ","); 07558 } 07559 snprintf(buffer, sizeof(buffer), "%d", keyids[j]); 07560 StrAppend(&insql, buffer); 07561 } 07562 StrAppend(&insql, ")"); 07563 07564 /* 0) Start a transaction */ 07565 status = DbBeginTransaction(); 07566 if (status != 0) { 07567 /* Something went wrong */ 07568 07569 MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07570 StrFree(keyids); 07571 return status; 07572 } 07573 07574 /* 1) Change the state of the selected Key */ 07575 if (keystate == KSM_STATE_ACTIVE) { 07576 /* We are making a key active */ 07577 07578 /* Set the interval until Retire */ 07579 deltat = collection.ksklife; 07580 07581 #ifdef USE_MYSQL 07582 nchar = snprintf(buffer, sizeof(buffer), 07583 "DATE_ADD('%s', INTERVAL %d SECOND) ", datetime, deltat); 07584 #else 07585 nchar = snprintf(buffer, sizeof(buffer), 07586 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat); 07587 #endif /* USE_MYSQL */ 07588 07589 sql1 = DusInit("dnsseckeys"); 07590 DusSetInt(&sql1, "STATE", KSM_STATE_ACTIVE, 0); 07591 DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_ACTIVE), datetime, 1); 07592 StrAppend(&sql1, ", RETIRE = "); 07593 StrAppend(&sql1, buffer); 07594 07595 DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0); 07596 if (zone_id != -1) { 07597 DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1); 07598 } 07599 DusEnd(&sql1); 07600 } 07601 else if (keystate == KSM_STATE_RETIRE) { 07602 /* We are making a key retired */ 07603 07604 /* Set the interval until Dead */ 07605 if (keytype == KSM_TYPE_ZSK) { 07606 deltat = collection.zsksiglife + collection.propdelay + collection.ret_safety; 07607 } 07608 else if (keytype == KSM_TYPE_KSK) { 07609 deltat = collection.kskttl + collection.kskpropdelay + 07610 collection.ret_safety; /* Ipp */ 07611 } 07612 07613 #ifdef USE_MYSQL 07614 nchar = snprintf(buffer, sizeof(buffer), 07615 "DATE_ADD('%s', INTERVAL %d SECOND) ", datetime, deltat); 07616 #else 07617 nchar = snprintf(buffer, sizeof(buffer), 07618 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat); 07619 #endif /* USE_MYSQL */ 07620 07621 sql1 = DusInit("dnsseckeys"); 07622 DusSetInt(&sql1, "STATE", KSM_STATE_RETIRE, 0); 07623 DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_RETIRE), datetime, 1); 07624 StrAppend(&sql1, ", DEAD = "); 07625 StrAppend(&sql1, buffer); 07626 07627 DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0); 07628 if (zone_id != -1) { 07629 DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1); 07630 } 07631 DusEnd(&sql1); 07632 } 07633 else if (keystate == KSM_STATE_DSPUBLISH) { 07634 /* Set the interval until DSReady */ 07635 deltat = collection.kskttl + collection.kskpropdelay + 07636 collection.pub_safety; 07637 07638 #ifdef USE_MYSQL 07639 nchar = snprintf(buffer, sizeof(buffer), 07640 "DATE_ADD('%s', INTERVAL %d SECOND) ", datetime, deltat); 07641 #else 07642 nchar = snprintf(buffer, sizeof(buffer), 07643 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat); 07644 #endif /* USE_MYSQL */ 07645 07646 sql1 = DusInit("dnsseckeys"); 07647 DusSetInt(&sql1, "STATE", KSM_STATE_DSPUBLISH, 0); 07648 DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_PUBLISH), datetime, 1); 07649 StrAppend(&sql1, ", READY = "); 07650 StrAppend(&sql1, buffer); 07651 07652 DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0); 07653 if (zone_id != -1) { 07654 DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1); 07655 } 07656 DusEnd(&sql1); 07657 } 07658 else { 07659 printf("Moving to keystate %s not implemented yet\n", KsmKeywordStateValueToName(keystate)); 07660 StrFree(keyids); 07661 return -1; 07662 } 07663 07664 status = DbExecuteSqlNoResult(DbHandle(), sql1); 07665 DusFree(sql1); 07666 07667 StrFree(keyids); 07668 07669 /* Report any errors */ 07670 if (status != 0) { 07671 status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 07672 DbRollback(); 07673 return status; 07674 } 07675 07676 /* 3) Commit or Rollback */ 07677 if (status == 0) { /* It actually can't be anything else */ 07678 /* Everything worked by the looks of it */ 07679 DbCommit(); 07680 } else { 07681 /* Whatever happened, it was not good */ 07682 DbRollback(); 07683 } 07684 07685 return status; 07686 } 07687 07688 static int restart_enforcerd() 07689 { 07690 /* ToDo: This should really be rewritten so that it will read 07691 OPENDNSSEC_ENFORCER_PIDFILE and send a SIGHUP itself */ 07692 return system(RESTART_ENFORCERD_CMD); 07693 } 07694 07695 /* 07696 * Read the conf.xml file, we will not validate as that was done as we read the database. 07697 * Instead we just extract the RepositoryList into the database and also learn the 07698 * location of the zonelist. 07699 */ 07700 int get_conf_key_info(int* interval, int* man_key_gen) 07701 { 07702 int status = 0; 07703 int mysec = 0; 07704 xmlDocPtr doc = NULL; 07705 xmlXPathContextPtr xpathCtx = NULL; 07706 xmlXPathObjectPtr xpathObj = NULL; 07707 char* temp_char = NULL; 07708 07709 xmlChar *iv_expr = (unsigned char*) "//Configuration/Enforcer/Interval"; 07710 xmlChar *mk_expr = (unsigned char*) "//Configuration/Enforcer/ManualKeyGeneration"; 07711 07712 /* Load XML document */ 07713 doc = xmlParseFile(config); 07714 if (doc == NULL) { 07715 printf("Error: unable to parse file \"%s\"\n", config); 07716 return(-1); 07717 } 07718 07719 /* Create xpath evaluation context */ 07720 xpathCtx = xmlXPathNewContext(doc); 07721 if(xpathCtx == NULL) { 07722 printf("Error: unable to create new XPath context\n"); 07723 xmlFreeDoc(doc); 07724 return(-1); 07725 } 07726 07727 /* Evaluate xpath expression for interval */ 07728 xpathObj = xmlXPathEvalExpression(iv_expr, xpathCtx); 07729 if(xpathObj == NULL) { 07730 printf("Error: unable to evaluate xpath expression: %s", iv_expr); 07731 xmlXPathFreeContext(xpathCtx); 07732 xmlFreeDoc(doc); 07733 return(-1); 07734 } 07735 07736 temp_char = (char *)xmlXPathCastToString(xpathObj); 07737 status = DtXMLIntervalSeconds(temp_char, &mysec); 07738 if (status > 0) { 07739 printf("Error: unable to convert Interval %s to seconds, error: %i\n", temp_char, status); 07740 StrFree(temp_char); 07741 return status; 07742 } 07743 else if (status == -1) { 07744 printf("Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days\n", temp_char); 07745 } 07746 *interval = mysec; 07747 StrFree(temp_char); 07748 xmlXPathFreeObject(xpathObj); 07749 07750 /* Evaluate xpath expression for Manual key generation */ 07751 xpathObj = xmlXPathEvalExpression(mk_expr, xpathCtx); 07752 if(xpathObj == NULL) { 07753 printf("Error: unable to evaluate xpath expression: %s\n", mk_expr); 07754 xmlXPathFreeContext(xpathCtx); 07755 xmlFreeDoc(doc); 07756 return(-1); 07757 } 07758 07759 if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) { 07760 /* Manual key generation tag is present */ 07761 *man_key_gen = 1; 07762 } 07763 else { 07764 /* Tag absent */ 07765 *man_key_gen = 0; 07766 } 07767 xmlXPathFreeObject(xpathObj); 07768 07769 if (xpathCtx) { 07770 xmlXPathFreeContext(xpathCtx); 07771 } 07772 if (doc) { 07773 xmlFreeDoc(doc); 07774 } 07775 07776 return 0; 07777 } 07778 07779 /* TODO put this fn and the one below somewhere that we can call it from here and the enforcer */ 07780 /*+ 07781 * LinkKeys - Create required entries in Dnsseckeys table for zones added to policies 07782 * (i.e. when keysharing is turned on) 07783 * 07784 * Description: 07785 * Allocates a key in the database. 07786 * 07787 * Arguments: 07788 * const char* zone_name 07789 * name of zone 07790 * 07791 * int policy_id 07792 * ID of policy which the zone is on 07793 * 07794 * int interval 07795 * Enforcer run interval 07796 * 07797 * int man_key_gen 07798 * Manual Key Generation flag 07799 * 07800 * Returns: 07801 * int 07802 * Status return. 0=> Success, non-zero => error. 07803 -*/ 07804 07805 int LinkKeys(const char* zone_name, int policy_id) 07806 { 07807 int status = 0; 07808 07809 int interval = -1; /* Enforcer interval */ 07810 int man_key_gen = -1; /* Manual key generation flag */ 07811 07812 int zone_id = 0; /* id of zone supplied */ 07813 KSM_POLICY* policy; 07814 07815 /* Unused parameter */ 07816 (void)policy_id; 07817 07818 /* Get some info from conf.xml */ 07819 status = get_conf_key_info(&interval, &man_key_gen); 07820 if (status != 0) { 07821 printf("Failed to Link Keys to zone\n"); 07822 return(1); 07823 } 07824 07825 status = KsmZoneIdFromName(zone_name, &zone_id); 07826 if (status != 0) { 07827 return(status); 07828 } 07829 07830 policy = KsmPolicyAlloc(); 07831 if (policy == NULL) { 07832 printf("Malloc for policy struct failed\n"); 07833 exit(1); 07834 } 07835 SetPolicyDefaults(policy, o_policy); 07836 07837 status = KsmPolicyExists(o_policy); 07838 if (status == 0) { 07839 /* Policy exists */ 07840 status = KsmPolicyRead(policy); 07841 if(status != 0) { 07842 printf("Error: unable to read policy %s from database\n", o_policy); 07843 KsmPolicyFree(policy); 07844 return status; 07845 } 07846 } else { 07847 printf("Error: policy %s doesn't exist in database\n", o_policy); 07848 KsmPolicyFree(policy); 07849 return status; 07850 } 07851 07852 /* Make sure that enough keys are allocated to this zone */ 07853 status = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, interval, zone_name, man_key_gen, 0); 07854 if (status != 0) { 07855 printf("Error allocating zsks to zone %s", zone_name); 07856 KsmPolicyFree(policy); 07857 return(status); 07858 } 07859 status = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, interval, zone_name, man_key_gen, policy->ksk->rollover_scheme); 07860 if (status != 0) { 07861 printf("Error allocating ksks to zone %s", zone_name); 07862 KsmPolicyFree(policy); 07863 return(status); 07864 } 07865 07866 KsmPolicyFree(policy); 07867 return 0; 07868 } 07869 07870 /* allocateKeysToZone 07871 * 07872 * Description: 07873 * Allocates existing keys to zones 07874 * 07875 * Arguments: 07876 * policy 07877 * policy that the keys were created for 07878 * key_type 07879 * KSK or ZSK 07880 * zone_id 07881 * ID of zone in question 07882 * interval 07883 * time before next run 07884 * zone_name 07885 * just in case we need to log something 07886 * man_key_gen 07887 * lack of keys may be an issue for the user to fix 07888 * int rollover_scheme 07889 * KSK rollover scheme in use 07890 * 07891 * Returns: 07892 * int 07893 * Status return. 0=> Success, non-zero => error. 07894 * 1 == error with input 07895 * 2 == not enough keys to satisfy policy 07896 * 3 == database error 07897 -*/ 07898 07899 07900 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) 07901 { 07902 int status = 0; 07903 int keys_needed = 0; 07904 int keys_in_queue = 0; 07905 int keys_pending_retirement = 0; 07906 int new_keys = 0; 07907 int key_pair_id = 0; 07908 int i = 0; 07909 DB_ID ignore = 0; 07910 KSM_PARCOLL collection; /* Parameters collection */ 07911 char* datetime = DtParseDateTimeString("now"); 07912 07913 /* Check datetime in case it came back NULL */ 07914 if (datetime == NULL) { 07915 printf("Couldn't turn \"now\" into a date, quitting..."); 07916 exit(1); 07917 } 07918 07919 if (policy == NULL) { 07920 printf("NULL policy sent to allocateKeysToZone"); 07921 StrFree(datetime); 07922 return 1; 07923 } 07924 07925 if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) { 07926 printf("Unknown keytype: %i in allocateKeysToZone", key_type); 07927 StrFree(datetime); 07928 return 1; 07929 } 07930 07931 /* Get list of parameters */ 07932 status = KsmParameterCollection(&collection, policy->id); 07933 if (status != 0) { 07934 StrFree(datetime); 07935 return status; 07936 } 07937 07938 /* Make sure that enough keys are allocated to this zone */ 07939 /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */ 07940 status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1); 07941 if (status != 0) { 07942 printf("Could not predict key requirement for next interval for %s", zone_name); 07943 StrFree(datetime); 07944 return 3; 07945 } 07946 07947 /* How many do we have ? TODO should this include the currently active key?*/ 07948 status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id); 07949 if (status != 0) { 07950 printf("Could not count current key numbers for zone %s", zone_name); 07951 StrFree(datetime); 07952 return 3; 07953 } 07954 07955 /* or about to retire */ 07956 status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval); 07957 if (status != 0) { 07958 printf("Could not count keys which may retire before the next run (for zone %s)", zone_name); 07959 StrFree(datetime); 07960 return 3; 07961 } 07962 07963 StrFree(datetime); 07964 new_keys = keys_needed - (keys_in_queue - keys_pending_retirement); 07965 07966 /* 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); */ 07967 07968 /* Allocate keys */ 07969 for (i=0 ; i < new_keys ; i++){ 07970 key_pair_id = 0; 07971 if (key_type == KSM_TYPE_KSK) { 07972 status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id); 07973 if (status == -1 || key_pair_id == 0) { 07974 if (man_key_gen == 0) { 07975 printf("Not enough keys to satisfy ksk policy for zone: %s", zone_name); 07976 printf("ods-enforcerd will create some more keys on its next run"); 07977 } 07978 else { 07979 printf("Not enough keys to satisfy ksk policy for zone: %s", zone_name); 07980 printf("please use \"ods-ksmutil key generate\" to create some more keys."); 07981 } 07982 return 2; 07983 } 07984 else if (status != 0) { 07985 printf("Could not get an unallocated ksk for zone: %s", zone_name); 07986 return 3; 07987 } 07988 } else { 07989 status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id); 07990 if (status == -1 || key_pair_id == 0) { 07991 if (man_key_gen == 0) { 07992 printf("Not enough keys to satisfy zsk policy for zone: %s", zone_name); 07993 printf("ods-enforcerd will create some more keys on its next run"); 07994 } 07995 else { 07996 printf("Not enough keys to satisfy zsk policy for zone: %s", zone_name); 07997 printf("please use \"ods-ksmutil key generate\" to create some more keys."); 07998 } 07999 return 2; 08000 } 08001 else if (status != 0) { 08002 printf("Could not get an unallocated zsk for zone: %s", zone_name); 08003 return 3; 08004 } 08005 } 08006 if(key_pair_id > 0) { 08007 status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, NULL, &ignore); 08008 /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */ 08009 } else { 08010 /* This shouldn't happen */ 08011 printf("KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name); 08012 exit(1); 08013 } 08014 08015 } 08016 08017 return status; 08018 } 08019 08020 08021 /* keyRoll 08022 * 08023 * Description: 08024 * Rolls keys far enough for the enforcer to take over 08025 * 08026 * Arguments: 08027 * zone_id 08028 * ID of zone in question (-1 == all) 08029 * policy_id 08030 * policy that should be rolled (-1 == all) 08031 * key_type 08032 * KSK or ZSK (-1 == all) 08033 * 08034 * Returns: 08035 * int 08036 * Status return. 0=> Success, non-zero => error. 08037 -*/ 08038 08039 int keyRoll(int zone_id, int policy_id, int key_type) 08040 { 08041 08042 int status = 0; 08043 int size = -1; 08044 08045 char* sql = NULL; /* SQL query */ 08046 char* sql1 = NULL; /* SQL query */ 08047 char sql2[KSM_SQL_SIZE]; 08048 DB_RESULT result1; /* Result of the query */ 08049 DB_ROW row = NULL; /* Row data */ 08050 int temp_id = -1; /* place to store the key id returned */ 08051 int temp_type = -1; /* place to store the key type returned */ 08052 int temp_zone_id = -1; /* place to store the zone id returned */ 08053 int where = 0; 08054 int j = 0; 08055 DB_RESULT result2; /* Result of the query */ 08056 DB_RESULT result3; /* Result of the query */ 08057 DB_ROW row2 = NULL; /* Row data */ 08058 char* insql1 = NULL; /* SQL query */ 08059 char* insql2 = NULL; /* SQL query */ 08060 char buffer[32]; /* For integer conversion */ 08061 08062 char* datetime = DtParseDateTimeString("now"); 08063 08064 /* Check datetime in case it came back NULL */ 08065 if (datetime == NULL) { 08066 printf("Couldn't turn \"now\" into a date, quitting...\n"); 08067 StrFree(datetime); 08068 exit(1); 08069 } 08070 08071 /* retire the active key(s) */ 08072 /* Find the key ID */ 08073 sql = DqsSpecifyInit("KEYDATA_VIEW","id, keytype"); 08074 if (zone_id != -1) { 08075 DqsConditionInt(&sql, "zone_id", DQS_COMPARE_EQ, zone_id, where++); 08076 } 08077 if (policy_id != -1) { 08078 DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++); 08079 } 08080 DqsConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++); 08081 if (key_type != -1) { 08082 DqsConditionInt(&sql, "keytype", DQS_COMPARE_EQ, key_type, where++); 08083 } 08084 DqsEnd(&sql); 08085 08086 status = DbExecuteSql(DbHandle(), sql, &result1); 08087 08088 if (status == 0) { 08089 status = DbFetchRow(result1, &row); 08090 while (status == 0) { 08091 /* Got a row, deal with it */ 08092 DbInt(row, 0, &temp_id); 08093 DbInt(row, 1, &temp_type); 08094 08095 sql1 = DusInit("keypairs"); 08096 DusSetInt(&sql1, "fixedDate", 1, 0); 08097 DusSetInt(&sql1, "compromisedflag", 1, 1); 08098 08099 DusConditionInt(&sql1, "id", DQS_COMPARE_EQ, temp_id, 0); 08100 DusEnd(&sql1); 08101 status = DbExecuteSqlNoResult(DbHandle(), sql1); 08102 DusFree(sql1); 08103 08104 /* Report any errors */ 08105 if (status != 0) { 08106 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 08107 DbFreeRow(row); 08108 return status; 08109 } 08110 08111 /* Loop over instances of this key: */ 08112 /* active-> set retire time */ 08113 sql1 = DusInit("dnsseckeys"); 08114 DusSetString(&sql1, "RETIRE", datetime, 0); 08115 08116 DusConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0); 08117 DusConditionInt(&sql1, "state", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, 1); 08118 DusEnd(&sql1); 08119 status = DbExecuteSqlNoResult(DbHandle(), sql1); 08120 DusFree(sql1); 08121 08122 /* Report any errors */ 08123 if (status != 0) { 08124 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 08125 DbFreeRow(row); 08126 return status; 08127 } 08128 08129 /* other-> move to dead */ 08130 sql1 = DusInit("dnsseckeys"); 08131 DusSetString(&sql1, "DEAD", datetime, 0); 08132 DusSetInt(&sql1, "state", KSM_STATE_DEAD, 1); 08133 08134 DusConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0); 08135 DusConditionInt(&sql1, "state", DQS_COMPARE_NE, KSM_STATE_ACTIVE, 1); 08136 DusEnd(&sql1); 08137 status = DbExecuteSqlNoResult(DbHandle(), sql1); 08138 DusFree(sql1); 08139 08140 /* Report any errors */ 08141 if (status != 0) { 08142 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 08143 DbFreeRow(row); 08144 return status; 08145 } 08146 08147 /* Promote any standby keys if we need to, i.e. we retired a KSK 08148 and there is nothing able to take over from it */ 08149 if (temp_type == KSM_TYPE_KSK) { 08150 /* find each zone in turn */ 08151 /* Depressingly MySQL can't run the following sql; so we need 08152 to build it by parts... There has to be a better way to do 08153 this. 08154 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); */ 08155 08156 /* First INSQL: select zone_id from dnsseckeys where retire = "DATETIME" and keypair_id = temp_id*/ 08157 08158 size = snprintf(sql2, KSM_SQL_SIZE, "select zone_id from dnsseckeys where retire = \"%s\" and keypair_id = %d", datetime, temp_id); 08159 status = DbExecuteSql(DbHandle(), sql2, &result2); 08160 if (status == 0) { 08161 status = DbFetchRow(result2, &row2); 08162 while (status == 0) { 08163 /* Got a row, print it */ 08164 DbInt(row2, 0, &temp_zone_id); 08165 08166 if (j != 0) { 08167 StrAppend(&insql1, ","); 08168 } 08169 snprintf(buffer, sizeof(buffer), "%d", temp_zone_id); 08170 StrAppend(&insql1, buffer); 08171 j++; 08172 08173 status = DbFetchRow(result2, &row2); 08174 } 08175 08176 /* Convert EOF status to success */ 08177 08178 if (status == -1) { 08179 status = 0; 08180 } 08181 08182 DbFreeResult(result2); 08183 } 08184 08185 /* Second INSQL: select zone_id from KEYDATA_VIEW where policy_id = policy_id and keytype = KSK and state in (publish,ready) */ 08186 08187 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); 08188 j=0; 08189 status = DbExecuteSql(DbHandle(), sql2, &result3); 08190 if (status == 0) { 08191 status = DbFetchRow(result3, &row2); 08192 while (status == 0) { 08193 /* Got a row, print it */ 08194 DbInt(row2, 0, &temp_zone_id); 08195 08196 if (j != 0) { 08197 StrAppend(&insql2, ","); 08198 } 08199 snprintf(buffer, sizeof(buffer), "%d", temp_zone_id); 08200 StrAppend(&insql2, buffer); 08201 j++; 08202 08203 status = DbFetchRow(result3, &row2); 08204 } 08205 08206 /* Convert EOF status to success */ 08207 08208 if (status == -1) { 08209 status = 0; 08210 } 08211 08212 DbFreeResult(result3); 08213 } 08214 DbFreeRow(row2); 08215 08216 /* Finally we can do the update */ 08217 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); 08218 08219 /* Quick check that we didn't run out of space */ 08220 if (size < 0 || size >= KSM_SQL_SIZE) { 08221 printf("Couldn't construct SQL to promote standby key\n"); 08222 DbFreeRow(row); 08223 return -1; 08224 } 08225 08226 status = DbExecuteSqlNoResult(DbHandle(), sql2); 08227 08228 /* Report any errors */ 08229 if (status != 0) { 08230 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 08231 DbFreeRow(row); 08232 return status; 08233 } 08234 } 08235 08236 /* NEXT KEY */ 08237 status = DbFetchRow(result1, &row); 08238 } 08239 08240 /* Convert EOF status to success */ 08241 if (status == -1) { 08242 status = 0; 08243 } 08244 DbFreeResult(result1); 08245 } 08246 DqsFree(sql); 08247 DbFreeRow(row); 08248 08249 StrFree(datetime); 08250 08251 return status; 08252 } 08253 08254 int get_policy_name_from_id(KSM_ZONE *zone) 08255 { 08256 int where = 0; /* WHERE clause value */ 08257 char* sql = NULL; /* SQL query */ 08258 DB_RESULT result; /* Handle converted to a result object */ 08259 DB_ROW row = NULL; /* Row data */ 08260 int status = 0; /* Status return */ 08261 08262 /* Construct the query */ 08263 08264 sql = DqsSpecifyInit("policies","id, name"); 08265 DqsConditionInt(&sql, "ID", DQS_COMPARE_EQ, zone->policy_id, where++); 08266 DqsOrderBy(&sql, "id"); 08267 08268 /* Execute query and free up the query string */ 08269 status = DbExecuteSql(DbHandle(), sql, &result); 08270 DqsFree(sql); 08271 08272 if (status != 0) 08273 { 08274 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 08275 DbFreeResult(result); 08276 return status; 08277 } 08278 08279 /* Get the next row from the data */ 08280 status = DbFetchRow(result, &row); 08281 if (status == 0) { 08282 DbStringBuffer(row, DB_POLICY_NAME, zone->policy_name, KSM_NAME_LENGTH*sizeof(char)); 08283 } 08284 else if (status == -1) {} 08285 /* No rows to return (but no error) */ 08286 else { 08287 printf("SQL failed: %s\n", DbErrmsg(DbHandle())); 08288 return status; 08289 } 08290 08291 DbFreeRow(row); 08292 DbFreeResult(result); 08293 return status; 08294 } 08295 08296 int append_zone(xmlDocPtr doc, KSM_ZONE *zone) 08297 { 08298 xmlNodePtr root; 08299 xmlNodePtr zone_node; 08300 xmlNodePtr adapters_node; 08301 xmlNodePtr input_node; 08302 xmlNodePtr output_node; 08303 08304 root = xmlDocGetRootElement(doc); 08305 if (root == NULL) { 08306 fprintf(stderr,"empty document\n"); 08307 return(1); 08308 } 08309 if (xmlStrcmp(root->name, (const xmlChar *) "ZoneList")) { 08310 fprintf(stderr,"document of the wrong type, root node != %s", "ZoneList"); 08311 return(1); 08312 } 08313 08314 zone_node = xmlNewTextChild(root, NULL, (const xmlChar *)"Zone", NULL); 08315 (void) xmlNewProp(zone_node, (const xmlChar *)"name", (const xmlChar *)zone->name); 08316 08317 /* Policy */ 08318 (void) xmlNewTextChild(zone_node, NULL, (const xmlChar *)"Policy", (const xmlChar *)zone->policy_name); 08319 08320 /* SignConf */ 08321 (void) xmlNewTextChild(zone_node, NULL, (const xmlChar *)"SignerConfiguration", (const xmlChar *)zone->signconf); 08322 08323 /* Adapters */ 08324 adapters_node = xmlNewTextChild(zone_node, NULL, (const xmlChar *)"Adapters", NULL); 08325 /* Input */ 08326 input_node = xmlNewTextChild(adapters_node, NULL, (const xmlChar *)"Input", NULL); 08327 (void) xmlNewTextChild(input_node, NULL, (const xmlChar *)"File", (const xmlChar *)zone->input); 08328 /* Output */ 08329 output_node = xmlNewTextChild(adapters_node, NULL, (const xmlChar *)"Output", NULL); 08330 (void) xmlNewTextChild(output_node, NULL, (const xmlChar *)"File", (const xmlChar *)zone->output); 08331 08332 08333 return(0); 08334 } 08335 08336 int ShellQuoteString(const char* string, char* buffer, size_t buflen) 08337 { 08338 size_t i; /* Loop counter */ 08339 size_t j = 0; /* Counter for new string */ 08340 08341 size_t len = strlen(string); 08342 08343 if (string) { 08344 for (i = 0; i < len; ++i) { 08345 if (string[i] == '\'') { 08346 buffer[j++] = '\''; 08347 buffer[j++] = '\\'; 08348 buffer[j++] = '\''; 08349 } 08350 buffer[j++] = string[i]; 08351 } 08352 } 08353 buffer[j] = '\0'; 08354 return ( (j <= buflen) ? 0 : 1); 08355 } 08356 08357 int rename_signconf(const char* zonelist_filename, const char* o_zone) { 08358 int status = 0; 08359 char* signconf = NULL; 08360 char* moved_signconf = NULL; 08361 char* zone_name = NULL; 08362 int i = 0; 08363 08364 /* All of the XML stuff */ 08365 xmlDocPtr doc = NULL; 08366 xmlNode *curNode; 08367 xmlXPathContextPtr xpathCtx = NULL; 08368 xmlXPathObjectPtr xpathObj = NULL; 08369 08370 xmlChar *node_expr = (unsigned char*) "//Zone"; 08371 /* Load XML document */ 08372 doc = xmlParseFile(zonelist_filename); 08373 if (doc == NULL) { 08374 printf("Error: unable to parse file \"%s\"\n", zonelist_filename); 08375 return(-1); 08376 } 08377 /* Create xpath evaluation context */ 08378 xpathCtx = xmlXPathNewContext(doc); 08379 if(xpathCtx == NULL) { 08380 xmlFreeDoc(doc); 08381 return(1); 08382 } 08383 08384 /* Evaluate xpath expression */ 08385 xpathObj = xmlXPathEvalExpression(node_expr, xpathCtx); 08386 if(xpathObj == NULL) { 08387 xmlXPathFreeContext(xpathCtx); 08388 xmlFreeDoc(doc); 08389 return(1); 08390 } 08391 08392 if (xpathObj->nodesetval) { 08393 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) { 08394 08395 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 08396 zone_name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i], (const xmlChar *)"name"); 08397 08398 if (all_flag || (strlen(zone_name) == strlen(o_zone) && 08399 strncmp(zone_name, o_zone, strlen(zone_name)) == 0)) { 08400 08401 while (curNode) { 08402 08403 if (xmlStrEqual(curNode->name, (const xmlChar *)"SignerConfiguration")) { 08404 StrAppend(&signconf, (char *) xmlNodeGetContent(curNode)); 08405 StrAppend(&moved_signconf, signconf); 08406 StrAppend(&moved_signconf, ".ZONE_DELETED"); 08407 /* Do the move */ 08408 status = rename(signconf, moved_signconf); 08409 if (status != 0 && errno != ENOENT) 08410 { 08411 /* cope with initial condition of files not existing */ 08412 printf("Could not rename: %s -> %s", signconf, moved_signconf); 08413 StrFree(signconf); 08414 StrFree(moved_signconf); 08415 return(1); 08416 } 08417 StrFree(signconf); 08418 StrFree(moved_signconf); 08419 08420 break; 08421 } 08422 08423 curNode = curNode->next; 08424 } 08425 08426 if (!all_flag) { 08427 break; 08428 } 08429 } 08430 } 08431 } 08432 08433 return status; 08434 } 08435