00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdlib.h>
00037 #include <errno.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 #include <syslog.h>
00041
00042 #include <libxml/xmlreader.h>
00043 #include <libxml/xpath.h>
00044
00045 #include "config.h"
00046
00047 #include "daemon.h"
00048 #include "daemon_util.h"
00049 #include "enforcer.h"
00050 #include "kaspaccess.h"
00051
00052 #include "ksm/ksm.h"
00053 #include "ksm/memory.h"
00054 #include "ksm/string_util.h"
00055 #include "ksm/string_util2.h"
00056 #include "ksm/datetime.h"
00057 #include "ksm/db_fields.h"
00058
00059 #include "libhsm.h"
00060 #include "libhsmdns.h"
00061
00062 int
00063 server_init(DAEMONCONFIG *config)
00064 {
00065 if (config == NULL) {
00066 log_msg(NULL, LOG_ERR, "Error in server_init, no config provided");
00067 exit(1);
00068 }
00069
00070
00071 if (config->pidfile == NULL) {
00072 config->pidfile = OPENDNSSEC_ENFORCER_PIDFILE;
00073 }
00074
00075 return 0;
00076 }
00077
00078
00079
00080
00081 void
00082 server_main(DAEMONCONFIG *config)
00083 {
00084 DB_RESULT handle;
00085 DB_HANDLE dbhandle;
00086 int status = 0;
00087 struct timeval tv;
00088 KSM_POLICY *policy;
00089 int result;
00090 hsm_ctx_t *ctx = NULL;
00091 char *hsm_error_message = NULL;
00092
00093 FILE *lock_fd = NULL;
00094 char *lock_filename = NULL;
00095
00096 if (config == NULL) {
00097 log_msg(NULL, LOG_ERR, "Error in server_main, no config provided");
00098 exit(1);
00099 }
00100
00101 policy = KsmPolicyAlloc();
00102 if (policy == NULL) {
00103 log_msg(config, LOG_ERR, "Malloc for policy struct failed");
00104 unlink(config->pidfile);
00105 exit(1);
00106 }
00107 kaspSetPolicyDefaults(policy, NULL);
00108
00109
00110 status = ReadConfig(config , 0);
00111 if (status != 0) {
00112 log_msg(config, LOG_ERR, "Error reading config");
00113 unlink(config->pidfile);
00114 exit(1);
00115 }
00116
00117
00118
00119
00120 if (config->configfile != NULL) {
00121 result = hsm_open(config->configfile, hsm_prompt_pin, NULL);
00122 } else {
00123 result = hsm_open(OPENDNSSEC_CONFIG_FILE, hsm_prompt_pin, NULL);
00124 }
00125 if (result) {
00126 hsm_error_message = hsm_get_error(ctx);
00127 if (hsm_error_message) {
00128 log_msg(config, LOG_ERR, "%s", hsm_error_message);
00129 free(hsm_error_message);
00130 } else {
00131
00132
00133 switch (result) {
00134 case HSM_ERROR:
00135 log_msg(config, LOG_ERR, "hsm_open() result: HSM error");
00136 break;
00137 case HSM_PIN_INCORRECT:
00138 log_msg(config, LOG_ERR, "hsm_open() result: incorrect PIN");
00139 break;
00140 case HSM_CONFIG_FILE_ERROR:
00141 log_msg(config, LOG_ERR, "hsm_open() result: config file error");
00142 break;
00143 case HSM_REPOSITORY_NOT_FOUND:
00144 log_msg(config, LOG_ERR, "hsm_open() result: repository not found");
00145 break;
00146 case HSM_NO_REPOSITORIES:
00147 log_msg(config, LOG_ERR, "hsm_open() result: no repositories");
00148 break;
00149 default:
00150 log_msg(config, LOG_ERR, "hsm_open() result: %d", result);
00151 }
00152 }
00153 unlink(config->pidfile);
00154 exit(1);
00155 }
00156 log_msg(config, LOG_INFO, "HSM opened successfully.");
00157 ctx = hsm_create_context();
00158
00159
00160 while (1) {
00161
00162
00163 status = ReadConfig(config, 1);
00164 if (status != 0) {
00165 log_msg(config, LOG_ERR, "Error reading config");
00166 unlink(config->pidfile);
00167 exit(1);
00168 }
00169
00170
00171
00172 if (DbFlavour() == SQLITE_DB) {
00173
00174
00175 lock_filename = NULL;
00176 StrAppend(&lock_filename, (char *)config->schema);
00177 StrAppend(&lock_filename, ".our_lock");
00178
00179 lock_fd = fopen(lock_filename, "w");
00180 status = get_lite_lock(lock_filename, lock_fd);
00181 StrFree(lock_filename);
00182 if (status != 0) {
00183 log_msg(config, LOG_ERR, "Error getting db lock");
00184 unlink(config->pidfile);
00185 exit(1);
00186 }
00187 }
00188
00189 log_msg(config, LOG_INFO, "Connecting to Database...");
00190 kaspConnect(config, &dbhandle);
00191
00192
00193 status = KsmPolicyInit(&handle, NULL);
00194 if (status == 0) {
00195
00196 status = KsmPolicy(handle, policy);
00197 while (status == 0) {
00198 log_msg(config, LOG_INFO, "Policy %s found.", policy->name);
00199
00200 kaspSetPolicyDefaults(policy, NULL);
00201
00202
00203 status = kaspReadPolicy(policy);
00204
00205
00206 if (policy->denial->version == 3)
00207 {
00208 status = KsmPolicyUpdateSalt(policy);
00209 if (status != 0) {
00210
00211 log_msg(config, LOG_ERR, "Error (%d) updating salt for %s", status, policy->name);
00212 }
00213 }
00214
00215
00216 if (config->manualKeyGeneration == 0) {
00217 status = do_keygen(config, policy, ctx);
00218 }
00219
00220
00221
00222
00223
00224 if (policy->keys->purge != -1) {
00225 status = do_purge(policy->keys->purge, policy->id);
00226 }
00227
00228
00229 status = KsmPolicy(handle, policy);
00230 }
00231 } else {
00232 log_msg(config, LOG_ERR, "Error querying KASP DB for policies.");
00233 unlink(config->pidfile);
00234 exit(1);
00235 }
00236
00237
00238 do_communication(config, policy);
00239
00240 DbFreeResult(handle);
00241
00242
00243 log_msg(config, LOG_INFO, "Disconnecting from Database...");
00244 kaspDisconnect(&dbhandle);
00245
00246
00247 if (DbFlavour() == SQLITE_DB) {
00248 status = release_lite_lock(lock_fd);
00249 if (status != 0) {
00250 log_msg(config, LOG_ERR, "Error releasing db lock");
00251 unlink(config->pidfile);
00252 exit(1);
00253 }
00254 fclose(lock_fd);
00255 }
00256
00257 if (config->once == true ){
00258 log_msg(config, LOG_INFO, "Running once only, exiting...");
00259 break;
00260 }
00261
00262
00263 if (config->term == 1 ){
00264 log_msg(config, LOG_INFO, "Received SIGTERM, exiting...");
00265 break;
00266 }
00267
00268 if (config->term == 2 ){
00269 log_msg(config, LOG_INFO, "Received SIGINT, exiting...");
00270 break;
00271 }
00272
00273
00274 tv.tv_sec = config->interval;
00275 tv.tv_usec = 0;
00276 log_msg(config, LOG_INFO, "Sleeping for %i seconds.",config->interval);
00277 select(0, NULL, NULL, NULL, &tv);
00278
00279
00280 if (config->term == 1 ){
00281 log_msg(config, LOG_INFO, "Received SIGTERM, exiting...");
00282 break;
00283 }
00284
00285 if (config->term == 2 ){
00286 log_msg(config, LOG_INFO, "Received SIGINT, exiting...");
00287 break;
00288 }
00289 }
00290
00291
00292
00293
00294 if (ctx) {
00295 hsm_destroy_context(ctx);
00296 }
00297
00298 result = hsm_close();
00299 log_msg(config, LOG_INFO, "all done! hsm_close result: %d", result);
00300
00301 KsmPolicyFree(policy);
00302
00303 if (unlink(config->pidfile) == -1) {
00304 log_msg(config, LOG_ERR, "unlink pidfile %s failed: %s",
00305 config->pidfile?config->pidfile:"(null)",
00306 strerror(errno));
00307 }
00308
00309 xmlCleanupParser();
00310
00311 }
00312
00313 int do_keygen(DAEMONCONFIG *config, KSM_POLICY* policy, hsm_ctx_t *ctx)
00314 {
00315 int status = 0;
00316
00317 char *rightnow;
00318 int i = 0;
00319 char *id;
00320 hsm_key_t *key = NULL;
00321 char *hsm_error_message = NULL;
00322 DB_ID ignore = 0;
00323 int ksks_needed = 0;
00324 int zsks_needed = 0;
00325 int keys_in_queue = 0;
00326 int new_keys = 0;
00327 unsigned int current_count = 0;
00328
00329 int same_keys = 0;
00330 int ksks_created = 0;
00331
00332 DB_RESULT result;
00333 int zone_count = 0;
00334
00335 if (policy->shared_keys == 1 ) {
00336 log_msg(config, LOG_INFO, "Key sharing is On");
00337 } else {
00338 log_msg(config, LOG_INFO, "Key sharing is Off.");
00339 }
00340
00341 rightnow = DtParseDateTimeString("now");
00342
00343
00344 if (rightnow == NULL) {
00345 log_msg(config, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
00346 exit(1);
00347 }
00348
00349
00350 if (policy->ksk->sm == policy->zsk->sm && policy->ksk->bits == policy->zsk->bits && policy->ksk->algorithm == policy->zsk->algorithm) {
00351 same_keys = 1;
00352 } else {
00353 same_keys = 0;
00354 }
00355
00356
00357 status = KsmZoneCountInit(&result, policy->id);
00358 if (status == 0) {
00359 status = KsmZoneCount(result, &zone_count);
00360 }
00361 DbFreeResult(result);
00362
00363 if (status == 0) {
00364
00365 if (zone_count == 0) {
00366 log_msg(config, LOG_INFO, "No zones on policy %s, skipping...", policy->name);
00367 StrFree(rightnow);
00368 return status;
00369 }
00370 } else {
00371 log_msg(NULL, LOG_ERR, "Could not count zones on policy %s", policy->name);
00372 StrFree(rightnow);
00373 return status;
00374 }
00375
00376
00377 status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, config->interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count);
00378 if (status != 0) {
00379 log_msg(NULL, LOG_ERR, "Could not predict ksk requirement for next interval for %s", policy->name);
00380
00381 }
00382
00383 status = KsmKeyCountStillGood(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, config->interval, rightnow, &keys_in_queue, KSM_TYPE_KSK);
00384 if (status != 0) {
00385 log_msg(NULL, LOG_ERR, "Could not count current ksk numbers for policy %s", policy->name);
00386
00387 }
00388
00389 if (policy->shared_keys == KSM_KEYS_SHARED) {
00390 keys_in_queue /= zone_count;
00391 }
00392
00393 new_keys = ksks_needed - keys_in_queue;
00394
00395
00396
00397 if (policy->ksk->sm_capacity != 0 && new_keys >= 0) {
00398 current_count = hsm_count_keys_repository(ctx, policy->ksk->sm_name);
00399 if (current_count >= policy->ksk->sm_capacity) {
00400 log_msg(config, LOG_ERR, "Repository %s is full, cannot create more KSKs for policy %s\n", policy->ksk->sm_name, policy->name);
00401 new_keys = 0;
00402 }
00403 else if (current_count + new_keys > policy->ksk->sm_capacity) {
00404 log_msg(config, LOG_WARNING, "Repository %s is nearly full, will create %lu KSKs for policy %s (reduced from %d)\n", policy->ksk->sm_name, policy->ksk->sm_capacity - current_count, policy->name, new_keys);
00405 new_keys = policy->ksk->sm_capacity - current_count;
00406 }
00407 }
00408
00409
00410 for (i=new_keys ; i > 0 ; i--){
00411 if (hsm_supported_algorithm(policy->ksk->algorithm) == 0) {
00412
00413 key = hsm_generate_rsa_key(ctx, policy->ksk->sm_name, policy->ksk->bits);
00414 if (key) {
00415 log_msg(config, LOG_DEBUG, "Created key in repository %s", policy->ksk->sm_name);
00416 } else {
00417 log_msg(config, LOG_ERR, "Error creating key in repository %s", policy->ksk->sm_name);
00418 hsm_error_message = hsm_get_error(ctx);
00419 if (hsm_error_message) {
00420 log_msg(config, LOG_ERR, "%s", hsm_error_message);
00421 free(hsm_error_message);
00422 }
00423 unlink(config->pidfile);
00424 exit(1);
00425 }
00426 id = hsm_get_key_id(ctx, key);
00427 hsm_key_free(key);
00428 status = KsmKeyPairCreate(policy->id, id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, rightnow, &ignore);
00429 if (status != 0) {
00430 log_msg(config, LOG_ERR,"Error creating key in Database");
00431 hsm_error_message = hsm_get_error(ctx);
00432 if (hsm_error_message) {
00433 log_msg(config, LOG_ERR, "%s", hsm_error_message);
00434 free(hsm_error_message);
00435 }
00436 unlink(config->pidfile);
00437 exit(1);
00438 }
00439 log_msg(config, LOG_INFO, "Created KSK size: %i, alg: %i with id: %s in repository: %s and database.", policy->ksk->bits,
00440 policy->ksk->algorithm, id, policy->ksk->sm_name);
00441 free(id);
00442 } else {
00443 log_msg(config, LOG_ERR, "Key algorithm %d unsupported by libhsm, exiting...", policy->ksk->algorithm);
00444 unlink(config->pidfile);
00445 exit(1);
00446 }
00447 }
00448 ksks_created = new_keys;
00449
00450
00451 keys_in_queue = 0;
00452 new_keys = 0;
00453 current_count = 0;
00454
00455
00456 status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, config->interval, &zsks_needed, 0, zone_count);
00457 if (status != 0) {
00458 log_msg(NULL, LOG_ERR, "Could not predict zsk requirement for next intervalfor %s", policy->name);
00459
00460 }
00461
00462 status = KsmKeyCountStillGood(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, config->interval, rightnow, &keys_in_queue, KSM_TYPE_ZSK);
00463 if (status != 0) {
00464 log_msg(NULL, LOG_ERR, "Could not count current zsk numbers for policy %s", policy->name);
00465
00466 }
00467
00468 if (policy->shared_keys == KSM_KEYS_SHARED) {
00469 keys_in_queue /= zone_count;
00470 }
00471
00472 if (same_keys) {
00473 keys_in_queue -= ksks_needed;
00474 }
00475
00476 new_keys = zsks_needed - keys_in_queue;
00477
00478
00479
00480 if (policy->zsk->sm_capacity != 0 && new_keys >= 0) {
00481 current_count = hsm_count_keys_repository(ctx, policy->zsk->sm_name);
00482 if (current_count >= policy->zsk->sm_capacity) {
00483 log_msg(config, LOG_ERR, "Repository %s is full, cannot create more ZSKs for policy %s\n", policy->zsk->sm_name, policy->name);
00484 new_keys = 0;
00485 }
00486 else if (current_count + new_keys > policy->zsk->sm_capacity) {
00487 log_msg(config, LOG_WARNING, "Repository %s is nearly full, will create %lu ZSKs for policy %s (reduced from %d)\n", policy->zsk->sm_name, policy->zsk->sm_capacity - current_count, policy->name, new_keys);
00488 new_keys = policy->zsk->sm_capacity - current_count;
00489 }
00490 }
00491
00492
00493 for (i = new_keys ; i > 0 ; i--) {
00494 if (hsm_supported_algorithm(policy->zsk->algorithm) == 0) {
00495
00496 key = hsm_generate_rsa_key(ctx, policy->zsk->sm_name, policy->zsk->bits);
00497 if (key) {
00498 log_msg(config, LOG_DEBUG, "Created key in repository %s", policy->zsk->sm_name);
00499 } else {
00500 log_msg(config, LOG_ERR, "Error creating key in repository %s", policy->zsk->sm_name);
00501 hsm_error_message = hsm_get_error(ctx);
00502 if (hsm_error_message) {
00503 log_msg(config, LOG_ERR, "%s", hsm_error_message);
00504 free(hsm_error_message);
00505 }
00506 unlink(config->pidfile);
00507 hsm_key_free(key);
00508 exit(1);
00509 }
00510 id = hsm_get_key_id(ctx, key);
00511 hsm_key_free(key);
00512 status = KsmKeyPairCreate(policy->id, id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, rightnow, &ignore);
00513 if (status != 0) {
00514 log_msg(config, LOG_ERR,"Error creating key in Database");
00515 hsm_error_message = hsm_get_error(ctx);
00516 if (hsm_error_message) {
00517 log_msg(config, LOG_ERR, "%s", hsm_error_message);
00518 free(hsm_error_message);
00519 }
00520 unlink(config->pidfile);
00521 exit(1);
00522 }
00523 log_msg(config, LOG_INFO, "Created ZSK size: %i, alg: %i with id: %s in repository: %s and database.", policy->zsk->bits,
00524 policy->zsk->algorithm, id, policy->zsk->sm_name);
00525 free(id);
00526 } else {
00527 log_msg(config, LOG_ERR, "Key algorithm %d unsupported by libhsm, exiting...", policy->zsk->algorithm);
00528 unlink(config->pidfile);
00529 exit(1);
00530 }
00531 }
00532 StrFree(rightnow);
00533
00534
00535 if (ksks_created && policy->ksk->require_backup) {
00536 log_msg(config, LOG_INFO, "NOTE: keys generated in repository %s will not become active until they have been backed up", policy->ksk->sm_name);
00537 }
00538 if (new_keys && policy->zsk->require_backup && (policy->zsk->sm != policy->ksk->sm)) {
00539 log_msg(config, LOG_INFO, "NOTE: keys generated in repository %s will not become active until they have been backed up", policy->zsk->sm_name);
00540 }
00541
00542 return status;
00543 }
00544
00545 int do_communication(DAEMONCONFIG *config, KSM_POLICY* policy)
00546 {
00547 int status = 0;
00548 int status2 = 0;
00549
00550 xmlTextReaderPtr reader = NULL;
00551 xmlDocPtr doc = NULL;
00552 xmlXPathContextPtr xpathCtx = NULL;
00553 xmlXPathObjectPtr xpathObj = NULL;
00554
00555 int ret = 0;
00556 char* zonelist_filename = NULL;
00557 char* zone_name;
00558 char* current_policy;
00559 char* current_filename;
00560 char *tag_name;
00561 int zone_id = -1;
00562 int signer_flag = 1;
00563 char* ksk_expected = NULL;
00564
00565 xmlChar *name_expr = (unsigned char*) "name";
00566 xmlChar *policy_expr = (unsigned char*) "//Zone/Policy";
00567 xmlChar *filename_expr = (unsigned char*) "//Zone/SignerConfiguration";
00568
00569 char* temp_char = NULL;
00570
00571
00572 char* datetime = NULL;
00573 int roll_time = 0;
00574
00575
00576 if (config->configfile != NULL) {
00577 status = read_zonelist_filename(config->configfile, &zonelist_filename);
00578 } else {
00579 status = read_zonelist_filename(OPENDNSSEC_CONFIG_FILE, &zonelist_filename);
00580 }
00581
00582 if (status != 0) {
00583 log_msg(NULL, LOG_ERR, "couldn't read zonelist filename");
00584 unlink(config->pidfile);
00585 exit(1);
00586 }
00587
00588
00589 reader = xmlNewTextReaderFilename(zonelist_filename);
00590 if (reader != NULL) {
00591 ret = xmlTextReaderRead(reader);
00592 while (ret == 1) {
00593 tag_name = (char*) xmlTextReaderLocalName(reader);
00594
00595 if (strncmp(tag_name, "Zone", 4) == 0
00596 && strncmp(tag_name, "ZoneList", 8) != 0
00597 && xmlTextReaderNodeType(reader) == 1) {
00598
00599 zone_name = NULL;
00600 temp_char = (char*) xmlTextReaderGetAttribute(reader, name_expr);
00601 StrAppend(&zone_name, temp_char);
00602 StrFree(temp_char);
00603
00604 if (zone_name == NULL) {
00605
00606 log_msg(NULL, LOG_ERR, "Error extracting zone name from %s", zonelist_filename);
00607
00608 ret = xmlTextReaderRead(reader);
00609 StrFree(tag_name);
00610 continue;
00611 }
00612
00613
00614 log_msg(config, LOG_INFO, "Zone %s found.", zone_name);
00615
00616
00617 status = KsmZoneIdFromName(zone_name, &zone_id);
00618 if (status != 0 || zone_id == -1)
00619 {
00620
00621 log_msg(NULL, LOG_ERR, "Error looking up zone \"%s\" in database (please make sure that the zonelist file is up to date)", zone_name);
00622
00623 ret = xmlTextReaderRead(reader);
00624 StrFree(tag_name);
00625 StrFree(zone_name);
00626 continue;
00627 }
00628
00629
00630 xmlTextReaderExpand(reader);
00631 doc = xmlTextReaderCurrentDoc(reader);
00632 if (doc == NULL) {
00633 log_msg(config, LOG_ERR, "Error: can not read zone \"%s\"; skipping", zone_name);
00634
00635 ret = xmlTextReaderRead(reader);
00636 StrFree(tag_name);
00637 StrFree(zone_name);
00638 continue;
00639 }
00640
00641
00642
00643 xpathCtx = xmlXPathNewContext(doc);
00644 if(xpathCtx == NULL) {
00645 log_msg(config, LOG_ERR,"Error: can not create XPath context for \"%s\"; skipping zone", zone_name);
00646
00647 ret = xmlTextReaderRead(reader);
00648 StrFree(tag_name);
00649 StrFree(zone_name);
00650 continue;
00651 }
00652
00653
00654
00655 xpathObj = xmlXPathEvalExpression(policy_expr, xpathCtx);
00656 if(xpathObj == NULL) {
00657 log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s; skipping zone", policy_expr);
00658
00659 ret = xmlTextReaderRead(reader);
00660 StrFree(tag_name);
00661 StrFree(zone_name);
00662 continue;
00663 }
00664 current_policy = NULL;
00665 temp_char = (char*) xmlXPathCastToString(xpathObj);
00666 StrAppend(¤t_policy, temp_char);
00667 StrFree(temp_char);
00668 log_msg(config, LOG_INFO, "Policy for %s set to %s.", zone_name, current_policy);
00669 xmlXPathFreeObject(xpathObj);
00670
00671 if (strcmp(current_policy, policy->name) != 0) {
00672
00673
00674 kaspSetPolicyDefaults(policy, current_policy);
00675
00676 status2 = KsmPolicyRead(policy);
00677 if (status2 != 0) {
00678
00679 log_msg(config, LOG_ERR, "Error reading policy");
00680 ret = xmlTextReaderRead(reader);
00681 StrFree(tag_name);
00682 StrFree(zone_name);
00683 continue;
00684 }
00685 log_msg(config, LOG_INFO, "Policy %s found in DB.", policy->name);
00686
00687 }
00688
00689
00690 StrFree(current_policy);
00691
00692
00693 xpathObj = xmlXPathEvalExpression(filename_expr, xpathCtx);
00694 xmlXPathFreeContext(xpathCtx);
00695
00696 if(xpathObj == NULL) {
00697 log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s; skipping zone", filename_expr);
00698
00699 ret = xmlTextReaderRead(reader);
00700 StrFree(tag_name);
00701 StrFree(zone_name);
00702 continue;
00703 }
00704 current_filename = NULL;
00705 temp_char = (char*)xmlXPathCastToString(xpathObj);
00706 StrAppend(¤t_filename, temp_char);
00707 StrFree(temp_char);
00708 log_msg(config, LOG_INFO, "Config will be output to %s.", current_filename);
00709 xmlXPathFreeObject(xpathObj);
00710
00711
00712 status2 = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, 0);
00713 if (status2 != 0) {
00714 log_msg(config, LOG_ERR, "Error allocating zsks to zone %s", zone_name);
00715
00716 ret = xmlTextReaderRead(reader);
00717 StrFree(tag_name);
00718 StrFree(zone_name);
00719 StrFree(current_filename);
00720 continue;
00721 }
00722 status2 = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, config->interval, zone_name, config->manualKeyGeneration, policy->ksk->rollover_scheme);
00723 if (status2 != 0) {
00724 log_msg(config, LOG_ERR, "Error allocating ksks to zone %s", zone_name);
00725
00726 ret = xmlTextReaderRead(reader);
00727 StrFree(tag_name);
00728 StrFree(zone_name);
00729 StrFree(current_filename);
00730 continue;
00731 }
00732
00733
00734 status2 = commGenSignConf(zone_name, zone_id, current_filename, policy, &signer_flag, config->interval, config->manualKeyGeneration, config->DSSubmitCmd);
00735 if (status2 == -2) {
00736 log_msg(config, LOG_ERR, "Signconf not written for %s", zone_name);
00737
00738 ret = xmlTextReaderRead(reader);
00739 StrFree(tag_name);
00740 StrFree(zone_name);
00741 StrFree(current_filename);
00742 continue;
00743 }
00744 else if (status2 != 0) {
00745 log_msg(config, LOG_ERR, "Error writing signconf for %s", zone_name);
00746
00747 ret = xmlTextReaderRead(reader);
00748 StrFree(tag_name);
00749 StrFree(zone_name);
00750 StrFree(current_filename);
00751 continue;
00752 }
00753
00754
00755 if (config->rolloverNotify != -1) {
00756 datetime = DtParseDateTimeString("now");
00757
00758
00759 if (datetime == NULL) {
00760 log_msg(config, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
00761 unlink(config->pidfile);
00762 exit(1);
00763 }
00764
00765
00766 status2 = KsmCheckNextRollover(KSM_TYPE_KSK, zone_id, &ksk_expected);
00767 if (status2 == -1) {
00768 log_msg(config, LOG_INFO, "No active KSKs yet for zone %s, can't check for impending rollover", zone_name);
00769 }
00770 else if (status2 != 0) {
00771 log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
00772
00773 } else {
00774 status2 = DtDateDiff(ksk_expected, datetime, &roll_time);
00775 if (status2 != 0) {
00776 log_msg(config, LOG_ERR, "Error checking for impending rollover for %s", zone_name);
00777 } else {
00778
00779 if (roll_time <= config->rolloverNotify) {
00780 log_msg(config, LOG_INFO, "Rollover of KSK expected at %s for %s", ksk_expected, zone_name);
00781 }
00782 StrFree(ksk_expected);
00783 }
00784 }
00785 StrFree(datetime);
00786 }
00787
00788 StrFree(current_filename);
00789 StrFree(zone_name);
00790 }
00791
00792 ret = xmlTextReaderRead(reader);
00793 StrFree(tag_name);
00794 }
00795 xmlFreeTextReader(reader);
00796 if (ret != 0) {
00797 log_msg(config, LOG_ERR, "%s : failed to parse", zonelist_filename);
00798 }
00799 } else {
00800 log_msg(config, LOG_ERR, "Unable to open %s", zonelist_filename);
00801 }
00802
00803 xmlFreeDoc(doc);
00804 StrFree(zonelist_filename);
00805
00806 return status;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815 int commGenSignConf(char* zone_name, int zone_id, char* current_filename, KSM_POLICY *policy, int* signer_flag, int run_interval, int man_key_gen, const char* DSSubmitCmd)
00816 {
00817 int status = 0;
00818 int status2 = 0;
00819 FILE *file, *file2;
00820 int char1, char2;
00821 int same = 0;
00822 char *temp_filename;
00823
00824 char *old_filename;
00825
00826
00827 char *signer_command;
00828 int gencnt;
00829 int NewDS = 0;
00830 char* datetime = DtParseDateTimeString("now");
00831
00832
00833 if (datetime == NULL) {
00834 log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
00835 exit(1);
00836 }
00837
00838 if (zone_name == NULL || current_filename == NULL || policy == NULL)
00839 {
00840
00841 log_msg(NULL, LOG_ERR, "commGenSignConf, NULL policy or zone provided");
00842 MemFree(datetime);
00843 return -1;
00844 }
00845
00846 old_filename = NULL;
00847 StrAppend(&old_filename, current_filename);
00848 StrAppend(&old_filename, ".OLD");
00849
00850 temp_filename = NULL;
00851 StrAppend(&temp_filename, current_filename);
00852 StrAppend(&temp_filename, ".tmp");
00853
00854 file = fopen(temp_filename, "w");
00855
00856 if (file == NULL)
00857 {
00858
00859 log_msg(NULL, LOG_ERR, "Could not open: %s", temp_filename);
00860 MemFree(datetime);
00861 StrFree(temp_filename);
00862 StrFree(old_filename);
00863 return -1;
00864 }
00865
00866 fprintf(file, "<SignerConfiguration>\n");
00867 fprintf(file, "\t<Zone name=\"%s\">\n", zone_name);
00868
00869 fprintf(file, "\t\t<Signatures>\n");
00870 fprintf(file, "\t\t\t<Resign>PT%dS</Resign>\n", policy->signature->resign);
00871 fprintf(file, "\t\t\t<Refresh>PT%dS</Refresh>\n", policy->signer->refresh);
00872 fprintf(file, "\t\t\t<Validity>\n");
00873 fprintf(file, "\t\t\t\t<Default>PT%dS</Default>\n", policy->signature->valdefault);
00874 fprintf(file, "\t\t\t\t<Denial>PT%dS</Denial>\n", policy->signature->valdenial);
00875 fprintf(file, "\t\t\t</Validity>\n");
00876 fprintf(file, "\t\t\t<Jitter>PT%dS</Jitter>\n", policy->signer->jitter);
00877 fprintf(file, "\t\t\t<InceptionOffset>PT%dS</InceptionOffset>\n", policy->signature->clockskew);
00878 fprintf(file, "\t\t</Signatures>\n");
00879
00880 fprintf(file, "\n");
00881
00882 fprintf(file, "\t\t<Denial>\n");
00883 if (policy->denial->version == 3)
00884 {
00885 fprintf(file, "\t\t\t<NSEC3>\n");
00886 if (policy->denial->optout == 1)
00887 {
00888 fprintf(file, "\t\t\t\t<OptOut />\n");
00889 }
00890 fprintf(file, "\t\t\t\t<Hash>\n");
00891 fprintf(file, "\t\t\t\t\t<Algorithm>%d</Algorithm>\n", policy->denial->algorithm);
00892 fprintf(file, "\t\t\t\t\t<Iterations>%d</Iterations>\n", policy->denial->iteration);
00893 if (policy->denial->salt[0] == '\0') {
00894 fprintf(file, "\t\t\t\t\t<Salt>-</Salt>\n");
00895 } else {
00896 fprintf(file, "\t\t\t\t\t<Salt>%s</Salt>\n", policy->denial->salt);
00897 }
00898 fprintf(file, "\t\t\t\t</Hash>\n");
00899 fprintf(file, "\t\t\t</NSEC3>\n");
00900 } else {
00901 fprintf(file, "\t\t\t<NSEC />\n");
00902 }
00903
00904 fprintf(file, "\t\t</Denial>\n");
00905
00906 fprintf(file, "\n");
00907
00908
00909 fprintf(file, "\t\t<Keys>\n");
00910 fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->ksk->ttl);
00911
00912
00913 status = KsmRequestKeys(0, 0, datetime, commKeyConfig, file, policy->id, zone_id, run_interval, &NewDS);
00914 if (status != 0) {
00915
00916
00917
00918
00919 log_msg(NULL, LOG_ERR, "KsmRequestKeys returned: %d", status);
00920
00921
00922
00923 if (status == -1) {
00924 status2 = KsmRequestGenerateCount(KSM_TYPE_KSK, &gencnt, zone_id);
00925 if (status2 == 0 && gencnt == 0) {
00926 if(man_key_gen == 1) {
00927 log_msg(NULL, LOG_ERR, "There are no KSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
00928 } else {
00929 log_msg(NULL, LOG_WARNING, "There are no KSKs in the generate state; ods-enforcerd will create some on its next run.");
00930 }
00931 }
00932 else if (status2 == 0) {
00933 status2 = KsmRequestGenerateCount(KSM_TYPE_ZSK, &gencnt, zone_id);
00934 if (status2 == 0 && gencnt == 0) {
00935 if(man_key_gen == 1) {
00936 log_msg(NULL, LOG_ERR, "There are no ZSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
00937 } else {
00938 log_msg(NULL, LOG_WARNING, "There are no ZSKs in the generate state; ods-enforcerd will create some on its next run.");
00939 }
00940 }
00941 }
00942 else {
00943 log_msg(NULL, LOG_ERR, "KsmRequestGenerateCount returned: %d", status2);
00944 }
00945 }
00946
00947 status = fclose(file);
00948 unlink(temp_filename);
00949 MemFree(datetime);
00950 StrFree(temp_filename);
00951 StrFree(old_filename);
00952
00953 return -2;
00954 }
00955
00956 fprintf(file, "\t\t</Keys>\n");
00957
00958 fprintf(file, "\n");
00959
00960 fprintf(file, "\t\t<SOA>\n");
00961 fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->signer->soattl);
00962 fprintf(file, "\t\t\t<Minimum>PT%dS</Minimum>\n", policy->signer->soamin);
00963 fprintf(file, "\t\t\t<Serial>%s</Serial>\n", KsmKeywordSerialValueToName( policy->signer->serial) );
00964 fprintf(file, "\t\t</SOA>\n");
00965
00966 if (strncmp(policy->audit, "NULL", 4) != 0) {
00967 fprintf(file, "\n");
00968 fprintf(file, "\t\t<Audit />\n");
00969 fprintf(file, "\n");
00970 }
00971
00972 fprintf(file, "\t</Zone>\n");
00973 fprintf(file, "</SignerConfiguration>\n");
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 status = fclose(file);
00993 MemFree(datetime);
00994
00995 if (status == EOF)
00996 {
00997 log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
00998 StrFree(temp_filename);
00999 StrFree(old_filename);
01000 return -1;
01001 }
01002
01003
01004 file = fopen(temp_filename, "rb");
01005 if (file == NULL)
01006 {
01007
01008 log_msg(NULL, LOG_ERR, "Could not reopen: %s", temp_filename);
01009 StrFree(temp_filename);
01010 StrFree(old_filename);
01011 return -1;
01012 }
01013
01014 file2 = fopen(current_filename, "rb");
01015
01016
01017 if (file2 != NULL) {
01018 same = 1;
01019 while(!feof(file)) {
01020 char1 = fgetc(file);
01021 if(ferror(file)) {
01022 log_msg(NULL, LOG_ERR, "Could not read: %s", temp_filename);
01023 fclose(file);
01024 fclose(file2);
01025 StrFree(temp_filename);
01026 StrFree(old_filename);
01027 return -1;
01028 }
01029 char2 = fgetc(file2);
01030 if(ferror(file2)) {
01031 log_msg(NULL, LOG_ERR, "Could not read: %s", current_filename);
01032 fclose(file);
01033 fclose(file2);
01034 StrFree(temp_filename);
01035 StrFree(old_filename);
01036 return -1;
01037 }
01038 if(char1 != char2) {
01039 same = 0;
01040 break;
01041 }
01042 }
01043
01044 status = fclose(file2);
01045 if (status == EOF)
01046 {
01047 log_msg(NULL, LOG_ERR, "Could not close: %s", current_filename);
01048 fclose(file);
01049 StrFree(temp_filename);
01050 StrFree(old_filename);
01051 return -1;
01052 }
01053 }
01054
01055 status = fclose(file);
01056 if (status == EOF)
01057 {
01058 log_msg(NULL, LOG_ERR, "Could not close: %s", temp_filename);
01059 StrFree(temp_filename);
01060 StrFree(old_filename);
01061 return -1;
01062 }
01063
01064
01065
01066 if (same == 0) {
01067
01068
01069 status = rename(current_filename, old_filename);
01070 if (status != 0 && status != -1)
01071 {
01072
01073 log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", current_filename, old_filename);
01074 StrFree(old_filename);
01075 StrFree(temp_filename);
01076 return -1;
01077 }
01078
01079
01080 if (rename(temp_filename, current_filename) != 0)
01081 {
01082 log_msg(NULL, LOG_ERR, "Could not rename: %s -> %s", temp_filename, current_filename);
01083 StrFree(old_filename);
01084 StrFree(temp_filename);
01085 return -1;
01086 }
01087
01088 if (*signer_flag == 1) {
01089
01090
01091
01092
01093
01094 signer_command = NULL;
01095 StrAppend(&signer_command, SIGNER_CLI_UPDATE);
01096 StrAppend(&signer_command, " ");
01097 StrAppend(&signer_command, zone_name);
01098
01099 status = system(signer_command);
01100 if (status != 0)
01101 {
01102 log_msg(NULL, LOG_ERR, "Could not call signer engine");
01103 log_msg(NULL, LOG_INFO, "Will continue: call 'ods-signer update' to manually update zones");
01104 *signer_flag = 0;
01105 }
01106
01107 StrFree(signer_command);
01108 }
01109 }
01110 else {
01111 log_msg(NULL, LOG_INFO, "No change to: %s", current_filename);
01112 if (remove(temp_filename) != 0)
01113 {
01114 log_msg(NULL, LOG_ERR, "Could not remove: %s", temp_filename);
01115 StrFree(old_filename);
01116 StrFree(temp_filename);
01117 return -1;
01118 }
01119 }
01120
01121
01122 if (NewDS == 1) {
01123 log_msg(NULL, LOG_INFO, "DSChanged");
01124 status = NewDSSet(zone_id, zone_name, DSSubmitCmd);
01125 }
01126
01127 StrFree(old_filename);
01128 StrFree(temp_filename);
01129
01130 return 0;
01131 }
01132
01133
01134
01135
01136
01137 int commKeyConfig(void* context, KSM_KEYDATA* key_data)
01138 {
01139 FILE *file = (FILE *)context;
01140
01141 fprintf(file, "\t\t\t<Key>\n");
01142 fprintf(file, "\t\t\t\t<Flags>%d</Flags>\n", key_data->keytype);
01143 fprintf(file, "\t\t\t\t<Algorithm>%d</Algorithm>\n", key_data->algorithm);
01144 fprintf(file, "\t\t\t\t<Locator>%s</Locator>\n", key_data->location);
01145
01146 if (key_data->keytype == KSM_TYPE_KSK)
01147 {
01148 fprintf(file, "\t\t\t\t<KSK />\n");
01149 }
01150 if (key_data->keytype == KSM_TYPE_ZSK && key_data->state == KSM_STATE_ACTIVE)
01151 {
01152 fprintf(file, "\t\t\t\t<ZSK />\n");
01153 }
01154 if ((key_data->state > KSM_STATE_GENERATE && key_data->state < KSM_STATE_DEAD) || key_data->state == KSM_STATE_KEYPUBLISH)
01155 {
01156 fprintf(file, "\t\t\t\t<Publish />\n");
01157 }
01158 fprintf(file, "\t\t\t</Key>\n");
01159 fprintf(file, "\n");
01160
01161 return 0;
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 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)
01195 {
01196 int status = 0;
01197 int keys_needed = 0;
01198 int keys_in_queue = 0;
01199 int keys_pending_retirement = 0;
01200 int new_keys = 0;
01201 int key_pair_id = 0;
01202 int i = 0;
01203 DB_ID ignore = 0;
01204 KSM_PARCOLL collection;
01205 char* datetime = DtParseDateTimeString("now");
01206
01207
01208 if (datetime == NULL) {
01209 log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
01210 exit(1);
01211 }
01212
01213 if (policy == NULL) {
01214 log_msg(NULL, LOG_ERR, "NULL policy sent to allocateKeysToZone");
01215 StrFree(datetime);
01216 return 1;
01217 }
01218
01219 if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) {
01220 log_msg(NULL, LOG_ERR, "Unknown keytype: %i in allocateKeysToZone", key_type);
01221 StrFree(datetime);
01222 return 1;
01223 }
01224
01225
01226 status = KsmParameterCollection(&collection, policy->id);
01227 if (status != 0) {
01228 StrFree(datetime);
01229 return status;
01230 }
01231
01232
01233
01234 status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
01235 if (status != 0) {
01236 log_msg(NULL, LOG_ERR, "Could not predict key requirement for next interval for %s", zone_name);
01237 StrFree(datetime);
01238 return 3;
01239 }
01240
01241
01242 status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id);
01243 if (status != 0) {
01244 log_msg(NULL, LOG_ERR, "Could not count current key numbers for zone %s", zone_name);
01245 StrFree(datetime);
01246 return 3;
01247 }
01248
01249
01250 status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval);
01251 if (status != 0) {
01252 log_msg(NULL, LOG_ERR, "Could not count keys which may retire before the next run (for zone %s)", zone_name);
01253 StrFree(datetime);
01254 return 3;
01255 }
01256
01257 StrFree(datetime);
01258 new_keys = keys_needed - (keys_in_queue - keys_pending_retirement);
01259
01260
01261
01262
01263 for (i=0 ; i < new_keys ; i++){
01264 key_pair_id = 0;
01265 if (key_type == KSM_TYPE_KSK) {
01266 status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
01267 if (status == -1 || key_pair_id == 0) {
01268 if (man_key_gen == 0) {
01269 log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
01270 log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
01271 }
01272 else {
01273 log_msg(NULL, LOG_ERR, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
01274 log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
01275 }
01276 return 2;
01277 }
01278 else if (status != 0) {
01279 log_msg(NULL, LOG_ERR, "Could not get an unallocated ksk for zone: %s", zone_name);
01280 return 3;
01281 }
01282 } else {
01283 status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, policy->keys->share_keys, &key_pair_id);
01284 if (status == -1 || key_pair_id == 0) {
01285 if (man_key_gen == 0) {
01286 log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
01287 log_msg(NULL, LOG_WARNING, "ods-enforcerd will create some more keys on its next run");
01288 }
01289 else {
01290 log_msg(NULL, LOG_ERR, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
01291 log_msg(NULL, LOG_ERR, "please use \"ods-ksmutil key generate\" to create some more keys.");
01292 }
01293 return 2;
01294 }
01295 else if (status != 0) {
01296 log_msg(NULL, LOG_ERR, "Could not get an unallocated zsk for zone: %s", zone_name);
01297 return 3;
01298 }
01299 }
01300 if(key_pair_id > 0) {
01301 status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, &ignore);
01302
01303 } else {
01304
01305 log_msg(NULL, LOG_ERR, "KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name);
01306 exit(1);
01307 }
01308
01309 }
01310
01311 return status;
01312 }
01313
01314
01315
01316
01317 int read_zonelist_filename(const char* filename, char** zone_list_filename)
01318 {
01319 xmlTextReaderPtr reader = NULL;
01320 xmlDocPtr doc = NULL;
01321 xmlXPathContextPtr xpathCtx = NULL;
01322 xmlXPathObjectPtr xpathObj = NULL;
01323 int ret = 0;
01324 char* temp_char = NULL;
01325 char* tag_name = NULL;
01326
01327 xmlChar *zonelist_expr = (unsigned char*) "//Common/ZoneListFile";
01328
01329
01330 reader = xmlNewTextReaderFilename(filename);
01331 if (reader != NULL) {
01332 ret = xmlTextReaderRead(reader);
01333 while (ret == 1) {
01334 tag_name = (char*) xmlTextReaderLocalName(reader);
01335
01336 if (strncmp(tag_name, "Common", 6) == 0
01337 && xmlTextReaderNodeType(reader) == 1) {
01338
01339
01340 xmlTextReaderExpand(reader);
01341 doc = xmlTextReaderCurrentDoc(reader);
01342 if (doc == NULL) {
01343 log_msg(NULL, LOG_ERR, "Error: can not read Common section of %s", filename);
01344
01345 ret = xmlTextReaderRead(reader);
01346 continue;
01347 }
01348
01349 xpathCtx = xmlXPathNewContext(doc);
01350 if(xpathCtx == NULL) {
01351 log_msg(NULL, LOG_ERR, "Error: can not create XPath context for Common section");
01352
01353 ret = xmlTextReaderRead(reader);
01354 continue;
01355 }
01356
01357
01358 xpathObj = xmlXPathEvalExpression(zonelist_expr, xpathCtx);
01359 if(xpathObj == NULL) {
01360 log_msg(NULL, LOG_ERR, "Error: unable to evaluate xpath expression: %s", zonelist_expr);
01361
01362 ret = xmlTextReaderRead(reader);
01363 continue;
01364 }
01365 *zone_list_filename = NULL;
01366 temp_char = (char *)xmlXPathCastToString(xpathObj);
01367 StrAppend(zone_list_filename, temp_char);
01368 StrFree(temp_char);
01369 xmlXPathFreeObject(xpathObj);
01370 log_msg(NULL, LOG_INFO, "zonelist filename set to %s.", *zone_list_filename);
01371 }
01372
01373 ret = xmlTextReaderRead(reader);
01374 StrFree(tag_name);
01375 }
01376 xmlFreeTextReader(reader);
01377 if (ret != 0) {
01378 log_msg(NULL, LOG_ERR, "%s : failed to parse", filename);
01379 return(1);
01380 }
01381 } else {
01382 log_msg(NULL, LOG_ERR, "Unable to open %s", filename);
01383 return(1);
01384 }
01385 if (xpathCtx) {
01386 xmlXPathFreeContext(xpathCtx);
01387 }
01388 if (doc) {
01389 xmlFreeDoc(doc);
01390 }
01391
01392 return 0;
01393 }
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 int do_purge(int interval, int policy_id)
01414 {
01415 char* sql = NULL;
01416 char* sql1 = NULL;
01417 char* sql2 = NULL;
01418 char* sql3 = NULL;
01419 int status = 0;
01420 char stringval[KSM_INT_STR_SIZE];
01421 DB_RESULT result;
01422 DB_ROW row = NULL;
01423
01424 char buffer[KSM_SQL_SIZE];
01425 unsigned int nchar;
01426
01427 int temp_id = -1;
01428 char* temp_loc = NULL;
01429 int count = 0;
01430
01431 char *rightnow;
01432
01433
01434 hsm_key_t *key = NULL;
01435
01436 log_msg(NULL, LOG_DEBUG, "Purging keys...");
01437
01438 rightnow = DtParseDateTimeString("now");
01439
01440
01441 if (rightnow == NULL) {
01442 log_msg(NULL, LOG_DEBUG, "Couldn't turn \"now\" into a date, quitting...");
01443 exit(1);
01444 }
01445
01446
01447 StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
01448
01449 if (policy_id != -1) {
01450 StrAppend(&sql, "and policy_id = ");
01451 snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
01452 StrAppend(&sql, stringval);
01453 }
01454
01455 DusEnd(&sql);
01456
01457 status = DbExecuteSql(DbHandle(), sql, &result);
01458
01459 if (status == 0) {
01460 status = DbFetchRow(result, &row);
01461 while (status == 0) {
01462
01463 DbInt(row, 0, &temp_id);
01464 DbString(row, 1, &temp_loc);
01465
01466 sql1 = DqsCountInit("dnsseckeys");
01467 DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
01468 DdsConditionInt(&sql1, "(state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
01469
01470 #ifdef USE_MYSQL
01471 nchar = snprintf(buffer, sizeof(buffer),
01472 " or state = %d and DEAD > DATE_ADD('%s', INTERVAL -%d SECOND)) ", KSM_STATE_DEAD, rightnow, interval);
01473 #else
01474 nchar = snprintf(buffer, sizeof(buffer),
01475 " or state = %d and DEAD > DATETIME('%s', '-%d SECONDS')) ", KSM_STATE_DEAD, rightnow, interval);
01476 #endif
01477
01478 StrAppend(&sql1, buffer);
01479 DqsEnd(&sql1);
01480
01481 status = DbIntQuery(DbHandle(), &count, sql1);
01482 DqsFree(sql1);
01483
01484 if (status != 0) {
01485 log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
01486 DbStringFree(temp_loc);
01487 DbFreeRow(row);
01488 StrFree(rightnow);
01489 return status;
01490 }
01491
01492
01493 if (count == 0) {
01494
01495
01496 sql2 = DdsInit("dnsseckeys");
01497 DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
01498 DdsEnd(&sql);
01499
01500 status = DbExecuteSqlNoResult(DbHandle(), sql2);
01501 DdsFree(sql2);
01502 if (status != 0)
01503 {
01504 log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
01505 DbStringFree(temp_loc);
01506 DbFreeRow(row);
01507 StrFree(rightnow);
01508 return status;
01509 }
01510
01511
01512 sql3 = DdsInit("keypairs");
01513 DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
01514 DdsEnd(&sql);
01515
01516 status = DbExecuteSqlNoResult(DbHandle(), sql3);
01517 DdsFree(sql3);
01518 if (status != 0)
01519 {
01520 log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
01521 DbStringFree(temp_loc);
01522 DbFreeRow(row);
01523 StrFree(rightnow);
01524 return status;
01525 }
01526
01527
01528 key = hsm_find_key_by_id(NULL, temp_loc);
01529
01530 if (!key) {
01531 log_msg(NULL, LOG_ERR, "Key not found: %s\n", temp_loc);
01532 DbStringFree(temp_loc);
01533 DbFreeRow(row);
01534 StrFree(rightnow);
01535 return -1;
01536 }
01537
01538 status = hsm_remove_key(NULL, key);
01539
01540 hsm_key_free(key);
01541
01542 if (!status) {
01543 log_msg(NULL, LOG_INFO, "Key remove successful.\n");
01544 } else {
01545 log_msg(NULL, LOG_ERR, "Key remove failed.\n");
01546 DbStringFree(temp_loc);
01547 DbFreeRow(row);
01548 StrFree(rightnow);
01549 return -1;
01550 }
01551 }
01552
01553
01554 status = DbFetchRow(result, &row);
01555 }
01556
01557
01558
01559 if (status == -1) {
01560 status = 0;
01561 }
01562
01563 DbFreeResult(result);
01564 }
01565
01566 DusFree(sql);
01567 DbFreeRow(row);
01568
01569 DbStringFree(temp_loc);
01570 StrFree(rightnow);
01571
01572 return status;
01573 }
01574
01575 int NewDSSet(int zone_id, const char* zone_name, const char* DSSubmitCmd) {
01576 int where = 0;
01577 char* sql = NULL;
01578 char* sql2 = NULL;
01579 int status = 0;
01580 int count = 0;
01581 int i = 0;
01582 int j = 0;
01583 char* insql = NULL;
01584 int* keyids;
01585 DB_RESULT result;
01586 KSM_KEYDATA data;
01587 size_t nchar;
01588 char buffer[256];
01589 char* count_clause = NULL;
01590 char* where_clause = NULL;
01591 int id = -1;
01592 int active_count = -1;
01593
01594 char stringval[KSM_INT_STR_SIZE];
01595 DB_RESULT result3;
01596 KSM_KEYDATA data3;
01597 char* ds_buffer = NULL;
01598 char* ds_seen_buffer = NULL;
01599 char* temp_char = NULL;
01600
01601
01602 hsm_key_t *key = NULL;
01603 ldns_rr *dnskey_rr = NULL;
01604 hsm_sign_params_t *sign_params = NULL;
01605
01606 FILE *fp;
01607 int bytes_written = -1;
01608
01609 nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d, %d, %d, %d, %d)",
01610 KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE,
01611 KSM_STATE_DSSUB, KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY,
01612 KSM_STATE_KEYPUBLISH, KSM_STATE_RETIRE);
01613 if (nchar >= sizeof(buffer)) {
01614 status = -1;
01615 return status;
01616 }
01617
01618
01619
01620
01621 count_clause = DqsCountInit("KEYDATA_VIEW");
01622 DqsConditionInt(&count_clause, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
01623 DqsConditionInt(&count_clause, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
01624 if (zone_id != -1) {
01625 DqsConditionInt(&count_clause, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
01626 }
01627
01628 status = DbIntQuery(DbHandle(), &active_count, count_clause);
01629 StrFree(count_clause);
01630 if (status != 0)
01631 {
01632 log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
01633 return status;
01634 }
01635
01636 if (active_count > 0) {
01637
01638 snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
01639 StrAppend(&where_clause, "select id from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
01640 StrAppend(&where_clause, stringval);
01641 StrAppend(&where_clause, " and retire = (select min(retire) from KEYDATA_VIEW where state = 4 and keytype = 257 and zone_id = ");
01642 StrAppend(&where_clause, stringval);
01643 StrAppend(&where_clause, ")");
01644
01645
01646 status = DbIntQuery(DbHandle(), &id, where_clause);
01647 StrFree(where_clause);
01648 if (status != 0)
01649 {
01650 log_msg(NULL, LOG_ERR, "Error: failed to find ID of key to retire\n");
01651 return status;
01652 }
01653 }
01654
01655
01656 where = 0;
01657 sql = DqsCountInit("KEYDATA_VIEW");
01658 DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
01659 DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
01660 if (zone_id != -1) {
01661 DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
01662 }
01663 if (id != -1) {
01664 DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
01665 }
01666 DqsEnd(&sql);
01667
01668 status = DbIntQuery(DbHandle(), &count, sql);
01669 DqsFree(sql);
01670
01671 if (status != 0) {
01672
01673 return status;
01674 }
01675
01676 if (count == 0) {
01677
01678 return status;
01679 }
01680
01681
01682 keyids = MemMalloc(count * sizeof(int));
01683
01684
01685
01686 where = 0;
01687 sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
01688 DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, where++);
01689 DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, where++);
01690 if (zone_id != -1) {
01691 DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
01692 }
01693 if (id != -1) {
01694 DqsConditionInt(&sql, "ID", DQS_COMPARE_NE, id, where++);
01695 }
01696 DqsEnd(&sql);
01697
01698 status = KsmKeyInitSql(&result, sql);
01699 DqsFree(sql);
01700
01701 if (status == 0) {
01702 while (status == 0) {
01703 status = KsmKey(result, &data);
01704 if (status == 0) {
01705 keyids[i] = data.keypair_id;
01706 i++;
01707 }
01708 }
01709
01710
01711
01712 if (status == -1) {
01713 status = 0;
01714 } else {
01715
01716 StrFree(keyids);
01717 return status;
01718 }
01719
01720 KsmKeyEnd(result);
01721
01722 } else {
01723
01724 StrFree(keyids);
01725 return status;
01726 }
01727
01728
01729
01730
01731
01732
01733 StrAppend(&insql, "(");
01734 for (j = 0; j < i; ++j) {
01735 if (j != 0) {
01736 StrAppend(&insql, ",");
01737 }
01738 snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
01739 StrAppend(&insql, buffer);
01740 }
01741 StrAppend(&insql, ")");
01742
01743 StrFree(keyids);
01744
01745
01746 sql2 = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
01747 DqsConditionKeyword(&sql2, "ID", DQS_COMPARE_IN, insql, 0);
01748 DqsConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
01749 DqsEnd(&sql2);
01750
01751 log_msg(NULL, LOG_INFO, "DS Record set has changed, the current set looks like:");
01752
01753 status = KsmKeyInitSql(&result3, sql2);
01754 DqsFree(sql2);
01755 if (status == 0) {
01756 status = KsmKey(result3, &data3);
01757 while (status == 0) {
01758
01759
01760 key = hsm_find_key_by_id(NULL, data3.location);
01761
01762 if (!key) {
01763 log_msg(NULL, LOG_ERR, "Key %s in DB but not repository.", data3.location);
01764 StrFree(insql);
01765 return status;
01766 }
01767
01768 StrAppend(&ds_seen_buffer, ", ");
01769 StrAppend(&ds_seen_buffer, data3.location);
01770
01771 sign_params = hsm_sign_params_new();
01772 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone_name);
01773 sign_params->algorithm = data3.algorithm;
01774 sign_params->flags = LDNS_KEY_ZONE_KEY;
01775 sign_params->flags += LDNS_KEY_SEP_KEY;
01776 dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
01777
01778 temp_char = ldns_rr2str(dnskey_rr);
01779 ldns_rr_free(dnskey_rr);
01780
01781
01782 for (i = 0; temp_char[i]; ++i) {
01783 if (temp_char[i] == '\t') {
01784 temp_char[i] = ' ';
01785 }
01786 }
01787 log_msg(NULL, LOG_INFO, "%s", temp_char);
01788
01789
01790
01791 for (i = 0; temp_char[i]; ++i) {
01792 if (temp_char[i] == ';') {
01793 temp_char[i] = '\n';
01794 temp_char[i+1] = '\0';
01795 break;
01796 }
01797 }
01798 StrAppend(&ds_buffer, temp_char);
01799 StrFree(temp_char);
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814 hsm_sign_params_free(sign_params);
01815 hsm_key_free(key);
01816 status = KsmKey(result3, &data3);
01817 }
01818
01819 if (status == -1) {
01820 status = 0;
01821 }
01822
01823 KsmKeyEnd(result3);
01824 }
01825
01826 if (DSSubmitCmd[0] != '\0') {
01827
01828 fp = popen(DSSubmitCmd, "w");
01829 if (fp == NULL) {
01830 log_msg(NULL, LOG_ERR, "Failed to run command: %s: %s", DSSubmitCmd, strerror(errno));
01831 return -1;
01832 }
01833 bytes_written = fprintf(fp, "%s", ds_buffer);
01834 if (bytes_written < 0) {
01835 log_msg(NULL, LOG_ERR, "Failed to write to %s: %s", DSSubmitCmd, strerror(errno));
01836 return -1;
01837 }
01838
01839 if (pclose(fp) == -1) {
01840 log_msg(NULL, LOG_ERR, "Failed to close %s: %s", DSSubmitCmd, strerror(errno));
01841 return -1;
01842 }
01843 }
01844
01845 StrFree(ds_buffer);
01846
01847 log_msg(NULL, LOG_INFO, "Once the new DS records are seen in DNS please issue the ds-seen command for zone %s with the following cka_ids%s", zone_name, ds_seen_buffer);
01848
01849 StrFree(ds_seen_buffer);
01850
01851 StrFree(insql);
01852
01853 return status;
01854 }