1 /* $NetBSD: dnssec-settime.c,v 1.7 2023/01/25 21:43:23 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <errno.h> 19 #include <inttypes.h> 20 #include <stdbool.h> 21 #include <stdlib.h> 22 #include <time.h> 23 #include <unistd.h> 24 25 #include <isc/buffer.h> 26 #include <isc/commandline.h> 27 #include <isc/file.h> 28 #include <isc/hash.h> 29 #include <isc/mem.h> 30 #include <isc/print.h> 31 #include <isc/string.h> 32 #include <isc/time.h> 33 #include <isc/util.h> 34 35 #include <dns/keyvalues.h> 36 #include <dns/log.h> 37 #include <dns/result.h> 38 39 #include <dst/dst.h> 40 41 #if USE_PKCS11 42 #include <pk11/result.h> 43 #endif /* if USE_PKCS11 */ 44 45 #include "dnssectool.h" 46 47 const char *program = "dnssec-settime"; 48 49 static isc_mem_t *mctx = NULL; 50 51 ISC_PLATFORM_NORETURN_PRE static void 52 usage(void) ISC_PLATFORM_NORETURN_POST; 53 54 static void 55 usage(void) { 56 fprintf(stderr, "Usage:\n"); 57 fprintf(stderr, " %s [options] keyfile\n\n", program); 58 fprintf(stderr, "Version: %s\n", VERSION); 59 fprintf(stderr, "General options:\n"); 60 #if USE_PKCS11 61 fprintf(stderr, 62 " -E engine: specify PKCS#11 provider " 63 "(default: %s)\n", 64 PK11_LIB_LOCATION); 65 #elif defined(USE_PKCS11) 66 fprintf(stderr, " -E engine: specify OpenSSL engine " 67 "(default \"pkcs11\")\n"); 68 #else /* if USE_PKCS11 */ 69 fprintf(stderr, " -E engine: specify OpenSSL engine\n"); 70 #endif /* if USE_PKCS11 */ 71 fprintf(stderr, " -f: force update of old-style " 72 "keys\n"); 73 fprintf(stderr, " -K directory: set key file location\n"); 74 fprintf(stderr, " -L ttl: set default key TTL\n"); 75 fprintf(stderr, " -v level: set level of verbosity\n"); 76 fprintf(stderr, " -V: print version information\n"); 77 fprintf(stderr, " -h: help\n"); 78 fprintf(stderr, "Timing options:\n"); 79 fprintf(stderr, " -P date/[+-]offset/none: set/unset key " 80 "publication date\n"); 81 fprintf(stderr, " -P ds date/[+-]offset/none: set/unset " 82 "DS publication date\n"); 83 fprintf(stderr, " -P sync date/[+-]offset/none: set/unset " 84 "CDS and CDNSKEY publication date\n"); 85 fprintf(stderr, " -A date/[+-]offset/none: set/unset key " 86 "activation date\n"); 87 fprintf(stderr, " -R date/[+-]offset/none: set/unset key " 88 "revocation date\n"); 89 fprintf(stderr, " -I date/[+-]offset/none: set/unset key " 90 "inactivation date\n"); 91 fprintf(stderr, " -D date/[+-]offset/none: set/unset key " 92 "deletion date\n"); 93 fprintf(stderr, " -D ds date/[+-]offset/none: set/unset " 94 "DS deletion date\n"); 95 fprintf(stderr, " -D sync date/[+-]offset/none: set/unset " 96 "CDS and CDNSKEY deletion date\n"); 97 fprintf(stderr, " -S <key>: generate a successor to an existing " 98 "key\n"); 99 fprintf(stderr, " -i <interval>: prepublication interval for " 100 "successor key " 101 "(default: 30 days)\n"); 102 fprintf(stderr, "Key state options:\n"); 103 fprintf(stderr, " -s: update key state file (default no)\n"); 104 fprintf(stderr, " -g state: set the goal state for this key\n"); 105 fprintf(stderr, " -d state date/[+-]offset: set the DS state\n"); 106 fprintf(stderr, " -k state date/[+-]offset: set the DNSKEY state\n"); 107 fprintf(stderr, " -r state date/[+-]offset: set the RRSIG (KSK) " 108 "state\n"); 109 fprintf(stderr, " -z state date/[+-]offset: set the RRSIG (ZSK) " 110 "state\n"); 111 fprintf(stderr, "Printing options:\n"); 112 fprintf(stderr, " -p C/P/Psync/A/R/I/D/Dsync/all: print a " 113 "particular time value or values\n"); 114 fprintf(stderr, " -u: print times in unix epoch " 115 "format\n"); 116 fprintf(stderr, "Output:\n"); 117 fprintf(stderr, " K<name>+<alg>+<new id>.key, " 118 "K<name>+<alg>+<new id>.private\n"); 119 120 exit(-1); 121 } 122 123 static void 124 printtime(dst_key_t *key, int type, const char *tag, bool epoch, FILE *stream) { 125 isc_result_t result; 126 isc_stdtime_t when; 127 128 if (tag != NULL) { 129 fprintf(stream, "%s: ", tag); 130 } 131 132 result = dst_key_gettime(key, type, &when); 133 if (result == ISC_R_NOTFOUND) { 134 fprintf(stream, "UNSET\n"); 135 } else if (epoch) { 136 fprintf(stream, "%d\n", (int)when); 137 } else { 138 time_t now = when; 139 struct tm t, *tm = localtime_r(&now, &t); 140 unsigned int flen; 141 char timebuf[80]; 142 143 if (tm == NULL) { 144 fprintf(stream, "INVALID\n"); 145 return; 146 } 147 148 flen = strftime(timebuf, sizeof(timebuf), 149 "%a %b %e %H:%M:%S %Y", tm); 150 INSIST(flen > 0U && flen < sizeof(timebuf)); 151 fprintf(stream, "%s\n", timebuf); 152 } 153 } 154 155 static void 156 writekey(dst_key_t *key, const char *directory, bool write_state) { 157 char newname[1024]; 158 char keystr[DST_KEY_FORMATSIZE]; 159 isc_buffer_t buf; 160 isc_result_t result; 161 int options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE; 162 163 if (write_state) { 164 options |= DST_TYPE_STATE; 165 } 166 167 isc_buffer_init(&buf, newname, sizeof(newname)); 168 result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf); 169 if (result != ISC_R_SUCCESS) { 170 fatal("Failed to build public key filename: %s", 171 isc_result_totext(result)); 172 } 173 174 result = dst_key_tofile(key, options, directory); 175 if (result != ISC_R_SUCCESS) { 176 dst_key_format(key, keystr, sizeof(keystr)); 177 fatal("Failed to write key %s: %s", keystr, 178 isc_result_totext(result)); 179 } 180 printf("%s\n", newname); 181 182 isc_buffer_clear(&buf); 183 result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf); 184 if (result != ISC_R_SUCCESS) { 185 fatal("Failed to build private key filename: %s", 186 isc_result_totext(result)); 187 } 188 printf("%s\n", newname); 189 190 if (write_state) { 191 isc_buffer_clear(&buf); 192 result = dst_key_buildfilename(key, DST_TYPE_STATE, directory, 193 &buf); 194 if (result != ISC_R_SUCCESS) { 195 fatal("Failed to build key state filename: %s", 196 isc_result_totext(result)); 197 } 198 printf("%s\n", newname); 199 } 200 } 201 202 int 203 main(int argc, char **argv) { 204 isc_result_t result; 205 const char *engine = NULL; 206 const char *filename = NULL; 207 char *directory = NULL; 208 char keystr[DST_KEY_FORMATSIZE]; 209 char *endp, *p; 210 int ch; 211 const char *predecessor = NULL; 212 dst_key_t *prevkey = NULL; 213 dst_key_t *key = NULL; 214 dns_name_t *name = NULL; 215 dns_secalg_t alg = 0; 216 unsigned int size = 0; 217 uint16_t flags = 0; 218 int prepub = -1; 219 int options; 220 dns_ttl_t ttl = 0; 221 isc_stdtime_t now; 222 isc_stdtime_t dstime = 0, dnskeytime = 0; 223 isc_stdtime_t krrsigtime = 0, zrrsigtime = 0; 224 isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; 225 isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0; 226 dst_key_state_t goal = DST_KEY_STATE_NA; 227 dst_key_state_t ds = DST_KEY_STATE_NA; 228 dst_key_state_t dnskey = DST_KEY_STATE_NA; 229 dst_key_state_t krrsig = DST_KEY_STATE_NA; 230 dst_key_state_t zrrsig = DST_KEY_STATE_NA; 231 bool setgoal = false, setds = false, setdnskey = false; 232 bool setkrrsig = false, setzrrsig = false; 233 bool setdstime = false, setdnskeytime = false; 234 bool setkrrsigtime = false, setzrrsigtime = false; 235 bool setpub = false, setact = false; 236 bool setrev = false, setinact = false; 237 bool setdel = false, setttl = false; 238 bool unsetpub = false, unsetact = false; 239 bool unsetrev = false, unsetinact = false; 240 bool unsetdel = false; 241 bool printcreate = false, printpub = false; 242 bool printact = false, printrev = false; 243 bool printinact = false, printdel = false; 244 bool force = false; 245 bool epoch = false; 246 bool changed = false; 247 bool write_state = false; 248 isc_log_t *log = NULL; 249 isc_stdtime_t syncadd = 0, syncdel = 0; 250 bool unsetsyncadd = false, setsyncadd = false; 251 bool unsetsyncdel = false, setsyncdel = false; 252 bool printsyncadd = false, printsyncdel = false; 253 isc_stdtime_t dsadd = 0, dsdel = 0; 254 bool unsetdsadd = false, setdsadd = false; 255 bool unsetdsdel = false, setdsdel = false; 256 bool printdsadd = false, printdsdel = false; 257 258 options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE; 259 260 if (argc == 1) { 261 usage(); 262 } 263 264 isc_mem_create(&mctx); 265 266 setup_logging(mctx, &log); 267 268 #if USE_PKCS11 269 pk11_result_register(); 270 #endif /* if USE_PKCS11 */ 271 dns_result_register(); 272 273 isc_commandline_errprint = false; 274 275 isc_stdtime_get(&now); 276 277 #define CMDLINE_FLAGS "A:D:d:E:fg:hI:i:K:k:L:P:p:R:r:S:suv:Vz:" 278 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { 279 switch (ch) { 280 case 'A': 281 if (setact || unsetact) { 282 fatal("-A specified more than once"); 283 } 284 285 changed = true; 286 act = strtotime(isc_commandline_argument, now, now, 287 &setact); 288 unsetact = !setact; 289 break; 290 case 'D': 291 /* -Dsync ? */ 292 if (isoptarg("sync", argv, usage)) { 293 if (unsetsyncdel || setsyncdel) { 294 fatal("-D sync specified more than " 295 "once"); 296 } 297 298 changed = true; 299 syncdel = strtotime(isc_commandline_argument, 300 now, now, &setsyncdel); 301 unsetsyncdel = !setsyncdel; 302 break; 303 } 304 /* -Dds ? */ 305 if (isoptarg("ds", argv, usage)) { 306 if (unsetdsdel || setdsdel) { 307 fatal("-D ds specified more than once"); 308 } 309 310 changed = true; 311 dsdel = strtotime(isc_commandline_argument, now, 312 now, &setdsdel); 313 unsetdsdel = !setdsdel; 314 break; 315 } 316 /* -Ddnskey ? */ 317 (void)isoptarg("dnskey", argv, usage); 318 if (setdel || unsetdel) { 319 fatal("-D specified more than once"); 320 } 321 322 changed = true; 323 del = strtotime(isc_commandline_argument, now, now, 324 &setdel); 325 unsetdel = !setdel; 326 break; 327 case 'd': 328 if (setds) { 329 fatal("-d specified more than once"); 330 } 331 332 ds = strtokeystate(isc_commandline_argument); 333 setds = true; 334 /* time */ 335 (void)isoptarg(isc_commandline_argument, argv, usage); 336 dstime = strtotime(isc_commandline_argument, now, now, 337 &setdstime); 338 break; 339 case 'E': 340 engine = isc_commandline_argument; 341 break; 342 case 'f': 343 force = true; 344 break; 345 case 'g': 346 if (setgoal) { 347 fatal("-g specified more than once"); 348 } 349 350 goal = strtokeystate(isc_commandline_argument); 351 if (goal != DST_KEY_STATE_NA && 352 goal != DST_KEY_STATE_HIDDEN && 353 goal != DST_KEY_STATE_OMNIPRESENT) 354 { 355 fatal("-g must be either none, hidden, or " 356 "omnipresent"); 357 } 358 setgoal = true; 359 break; 360 case '?': 361 if (isc_commandline_option != '?') { 362 fprintf(stderr, "%s: invalid argument -%c\n", 363 program, isc_commandline_option); 364 } 365 FALLTHROUGH; 366 case 'h': 367 /* Does not return. */ 368 usage(); 369 case 'I': 370 if (setinact || unsetinact) { 371 fatal("-I specified more than once"); 372 } 373 374 changed = true; 375 inact = strtotime(isc_commandline_argument, now, now, 376 &setinact); 377 unsetinact = !setinact; 378 break; 379 case 'i': 380 prepub = strtottl(isc_commandline_argument); 381 break; 382 case 'K': 383 /* 384 * We don't have to copy it here, but do it to 385 * simplify cleanup later 386 */ 387 directory = isc_mem_strdup(mctx, 388 isc_commandline_argument); 389 break; 390 case 'k': 391 if (setdnskey) { 392 fatal("-k specified more than once"); 393 } 394 395 dnskey = strtokeystate(isc_commandline_argument); 396 setdnskey = true; 397 /* time */ 398 (void)isoptarg(isc_commandline_argument, argv, usage); 399 dnskeytime = strtotime(isc_commandline_argument, now, 400 now, &setdnskeytime); 401 break; 402 case 'L': 403 ttl = strtottl(isc_commandline_argument); 404 setttl = true; 405 break; 406 case 'P': 407 /* -Psync ? */ 408 if (isoptarg("sync", argv, usage)) { 409 if (unsetsyncadd || setsyncadd) { 410 fatal("-P sync specified more than " 411 "once"); 412 } 413 414 changed = true; 415 syncadd = strtotime(isc_commandline_argument, 416 now, now, &setsyncadd); 417 unsetsyncadd = !setsyncadd; 418 break; 419 } 420 /* -Pds ? */ 421 if (isoptarg("ds", argv, usage)) { 422 if (unsetdsadd || setdsadd) { 423 fatal("-P ds specified more than once"); 424 } 425 426 changed = true; 427 dsadd = strtotime(isc_commandline_argument, now, 428 now, &setdsadd); 429 unsetdsadd = !setdsadd; 430 break; 431 } 432 /* -Pdnskey ? */ 433 (void)isoptarg("dnskey", argv, usage); 434 if (setpub || unsetpub) { 435 fatal("-P specified more than once"); 436 } 437 438 changed = true; 439 pub = strtotime(isc_commandline_argument, now, now, 440 &setpub); 441 unsetpub = !setpub; 442 break; 443 case 'p': 444 p = isc_commandline_argument; 445 if (!strcasecmp(p, "all")) { 446 printcreate = true; 447 printpub = true; 448 printact = true; 449 printrev = true; 450 printinact = true; 451 printdel = true; 452 printsyncadd = true; 453 printsyncdel = true; 454 printdsadd = true; 455 printdsdel = true; 456 break; 457 } 458 459 do { 460 switch (*p++) { 461 case 'A': 462 printact = true; 463 break; 464 case 'C': 465 printcreate = true; 466 break; 467 case 'D': 468 if (!strncmp(p, "sync", 4)) { 469 p += 4; 470 printsyncdel = true; 471 break; 472 } 473 if (!strncmp(p, "ds", 2)) { 474 p += 2; 475 printdsdel = true; 476 break; 477 } 478 printdel = true; 479 break; 480 case 'I': 481 printinact = true; 482 break; 483 case 'P': 484 if (!strncmp(p, "sync", 4)) { 485 p += 4; 486 printsyncadd = true; 487 break; 488 } 489 if (!strncmp(p, "ds", 2)) { 490 p += 2; 491 printdsadd = true; 492 break; 493 } 494 printpub = true; 495 break; 496 case 'R': 497 printrev = true; 498 break; 499 case ' ': 500 break; 501 default: 502 usage(); 503 break; 504 } 505 } while (*p != '\0'); 506 break; 507 case 'R': 508 if (setrev || unsetrev) { 509 fatal("-R specified more than once"); 510 } 511 512 changed = true; 513 rev = strtotime(isc_commandline_argument, now, now, 514 &setrev); 515 unsetrev = !setrev; 516 break; 517 case 'r': 518 if (setkrrsig) { 519 fatal("-r specified more than once"); 520 } 521 522 krrsig = strtokeystate(isc_commandline_argument); 523 setkrrsig = true; 524 /* time */ 525 (void)isoptarg(isc_commandline_argument, argv, usage); 526 krrsigtime = strtotime(isc_commandline_argument, now, 527 now, &setkrrsigtime); 528 break; 529 case 'S': 530 predecessor = isc_commandline_argument; 531 break; 532 case 's': 533 write_state = true; 534 break; 535 case 'u': 536 epoch = true; 537 break; 538 case 'V': 539 /* Does not return. */ 540 version(program); 541 case 'v': 542 verbose = strtol(isc_commandline_argument, &endp, 0); 543 if (*endp != '\0') { 544 fatal("-v must be followed by a number"); 545 } 546 break; 547 case 'z': 548 if (setzrrsig) { 549 fatal("-z specified more than once"); 550 } 551 552 zrrsig = strtokeystate(isc_commandline_argument); 553 setzrrsig = true; 554 (void)isoptarg(isc_commandline_argument, argv, usage); 555 zrrsigtime = strtotime(isc_commandline_argument, now, 556 now, &setzrrsigtime); 557 break; 558 559 default: 560 fprintf(stderr, "%s: unhandled option -%c\n", program, 561 isc_commandline_option); 562 exit(1); 563 } 564 } 565 566 if (argc < isc_commandline_index + 1 || 567 argv[isc_commandline_index] == NULL) 568 { 569 fatal("The key file name was not specified"); 570 } 571 if (argc > isc_commandline_index + 1) { 572 fatal("Extraneous arguments"); 573 } 574 575 if ((setgoal || setds || setdnskey || setkrrsig || setzrrsig) && 576 !write_state) 577 { 578 fatal("Options -g, -d, -k, -r and -z require -s to be set"); 579 } 580 581 result = dst_lib_init(mctx, engine); 582 if (result != ISC_R_SUCCESS) { 583 fatal("Could not initialize dst: %s", 584 isc_result_totext(result)); 585 } 586 587 if (predecessor != NULL) { 588 int major, minor; 589 590 if (prepub == -1) { 591 prepub = (30 * 86400); 592 } 593 594 if (setpub || unsetpub) { 595 fatal("-S and -P cannot be used together"); 596 } 597 if (setact || unsetact) { 598 fatal("-S and -A cannot be used together"); 599 } 600 601 result = dst_key_fromnamedfile(predecessor, directory, options, 602 mctx, &prevkey); 603 if (result != ISC_R_SUCCESS) { 604 fatal("Invalid keyfile %s: %s", filename, 605 isc_result_totext(result)); 606 } 607 if (!dst_key_isprivate(prevkey) && !dst_key_isexternal(prevkey)) 608 { 609 fatal("%s is not a private key", filename); 610 } 611 612 name = dst_key_name(prevkey); 613 alg = dst_key_alg(prevkey); 614 size = dst_key_size(prevkey); 615 flags = dst_key_flags(prevkey); 616 617 dst_key_format(prevkey, keystr, sizeof(keystr)); 618 dst_key_getprivateformat(prevkey, &major, &minor); 619 if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) { 620 fatal("Predecessor has incompatible format " 621 "version %d.%d\n\t", 622 major, minor); 623 } 624 625 result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &prevact); 626 if (result != ISC_R_SUCCESS) { 627 fatal("Predecessor has no activation date. " 628 "You must set one before\n\t" 629 "generating a successor."); 630 } 631 632 result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, 633 &previnact); 634 if (result != ISC_R_SUCCESS) { 635 fatal("Predecessor has no inactivation date. " 636 "You must set one before\n\t" 637 "generating a successor."); 638 } 639 640 pub = previnact - prepub; 641 act = previnact; 642 643 if ((previnact - prepub) < now && prepub != 0) { 644 fatal("Time until predecessor inactivation is\n\t" 645 "shorter than the prepublication interval. " 646 "Either change\n\t" 647 "predecessor inactivation date, or use the -i " 648 "option to set\n\t" 649 "a shorter prepublication interval."); 650 } 651 652 result = dst_key_gettime(prevkey, DST_TIME_DELETE, &prevdel); 653 if (result != ISC_R_SUCCESS) { 654 fprintf(stderr, 655 "%s: warning: Predecessor has no " 656 "removal date;\n\t" 657 "it will remain in the zone " 658 "indefinitely after rollover.\n", 659 program); 660 } else if (prevdel < previnact) { 661 fprintf(stderr, 662 "%s: warning: Predecessor is " 663 "scheduled to be deleted\n\t" 664 "before it is scheduled to be " 665 "inactive.\n", 666 program); 667 } 668 669 changed = setpub = setact = true; 670 } else { 671 if (prepub < 0) { 672 prepub = 0; 673 } 674 675 if (prepub > 0) { 676 if (setpub && setact && (act - prepub) < pub) { 677 fatal("Activation and publication dates " 678 "are closer together than the\n\t" 679 "prepublication interval."); 680 } 681 682 if (setpub && !setact) { 683 setact = true; 684 act = pub + prepub; 685 } else if (setact && !setpub) { 686 setpub = true; 687 pub = act - prepub; 688 } 689 690 if ((act - prepub) < now) { 691 fatal("Time until activation is shorter " 692 "than the\n\tprepublication interval."); 693 } 694 } 695 } 696 697 if (directory != NULL) { 698 filename = argv[isc_commandline_index]; 699 } else { 700 result = isc_file_splitpath(mctx, argv[isc_commandline_index], 701 &directory, &filename); 702 if (result != ISC_R_SUCCESS) { 703 fatal("cannot process filename %s: %s", 704 argv[isc_commandline_index], 705 isc_result_totext(result)); 706 } 707 } 708 709 result = dst_key_fromnamedfile(filename, directory, options, mctx, 710 &key); 711 if (result != ISC_R_SUCCESS) { 712 fatal("Invalid keyfile %s: %s", filename, 713 isc_result_totext(result)); 714 } 715 716 if (!dst_key_isprivate(key) && !dst_key_isexternal(key)) { 717 fatal("%s is not a private key", filename); 718 } 719 720 dst_key_format(key, keystr, sizeof(keystr)); 721 722 if (predecessor != NULL) { 723 if (!dns_name_equal(name, dst_key_name(key))) { 724 fatal("Key name mismatch"); 725 } 726 if (alg != dst_key_alg(key)) { 727 fatal("Key algorithm mismatch"); 728 } 729 if (size != dst_key_size(key)) { 730 fatal("Key size mismatch"); 731 } 732 if (flags != dst_key_flags(key)) { 733 fatal("Key flags mismatch"); 734 } 735 } 736 737 prevdel = previnact = 0; 738 if ((setdel && setinact && del < inact) || 739 (dst_key_gettime(key, DST_TIME_INACTIVE, &previnact) == 740 ISC_R_SUCCESS && 741 setdel && !setinact && !unsetinact && del < previnact) || 742 (dst_key_gettime(key, DST_TIME_DELETE, &prevdel) == ISC_R_SUCCESS && 743 setinact && !setdel && !unsetdel && prevdel < inact) || 744 (!setdel && !unsetdel && !setinact && !unsetinact && prevdel != 0 && 745 prevdel < previnact)) 746 { 747 fprintf(stderr, 748 "%s: warning: Key is scheduled to " 749 "be deleted before it is\n\t" 750 "scheduled to be inactive.\n", 751 program); 752 } 753 754 if (force) { 755 set_keyversion(key); 756 } else { 757 check_keyversion(key, keystr); 758 } 759 760 if (verbose > 2) { 761 fprintf(stderr, "%s: %s\n", program, keystr); 762 } 763 764 /* 765 * Set time values. 766 */ 767 if (setpub) { 768 dst_key_settime(key, DST_TIME_PUBLISH, pub); 769 } else if (unsetpub) { 770 dst_key_unsettime(key, DST_TIME_PUBLISH); 771 } 772 773 if (setact) { 774 dst_key_settime(key, DST_TIME_ACTIVATE, act); 775 } else if (unsetact) { 776 dst_key_unsettime(key, DST_TIME_ACTIVATE); 777 } 778 779 if (setrev) { 780 if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) { 781 fprintf(stderr, 782 "%s: warning: Key %s is already " 783 "revoked; changing the revocation date " 784 "will not affect this.\n", 785 program, keystr); 786 } 787 if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) { 788 fprintf(stderr, 789 "%s: warning: Key %s is not flagged as " 790 "a KSK, but -R was used. Revoking a " 791 "ZSK is legal, but undefined.\n", 792 program, keystr); 793 } 794 dst_key_settime(key, DST_TIME_REVOKE, rev); 795 } else if (unsetrev) { 796 if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) { 797 fprintf(stderr, 798 "%s: warning: Key %s is already " 799 "revoked; removing the revocation date " 800 "will not affect this.\n", 801 program, keystr); 802 } 803 dst_key_unsettime(key, DST_TIME_REVOKE); 804 } 805 806 if (setinact) { 807 dst_key_settime(key, DST_TIME_INACTIVE, inact); 808 } else if (unsetinact) { 809 dst_key_unsettime(key, DST_TIME_INACTIVE); 810 } 811 812 if (setdel) { 813 dst_key_settime(key, DST_TIME_DELETE, del); 814 } else if (unsetdel) { 815 dst_key_unsettime(key, DST_TIME_DELETE); 816 } 817 818 if (setsyncadd) { 819 dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); 820 } else if (unsetsyncadd) { 821 dst_key_unsettime(key, DST_TIME_SYNCPUBLISH); 822 } 823 824 if (setsyncdel) { 825 dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); 826 } else if (unsetsyncdel) { 827 dst_key_unsettime(key, DST_TIME_SYNCDELETE); 828 } 829 830 if (setdsadd) { 831 dst_key_settime(key, DST_TIME_DSPUBLISH, dsadd); 832 } else if (unsetdsadd) { 833 dst_key_unsettime(key, DST_TIME_DSPUBLISH); 834 } 835 836 if (setdsdel) { 837 dst_key_settime(key, DST_TIME_DSDELETE, dsdel); 838 } else if (unsetdsdel) { 839 dst_key_unsettime(key, DST_TIME_DSDELETE); 840 } 841 842 if (setttl) { 843 dst_key_setttl(key, ttl); 844 } 845 846 if (predecessor != NULL && prevkey != NULL) { 847 dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key)); 848 dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey)); 849 } 850 851 /* 852 * No metadata changes were made but we're forcing an upgrade 853 * to the new format anyway: use "-P now -A now" as the default 854 */ 855 if (force && !changed) { 856 dst_key_settime(key, DST_TIME_PUBLISH, now); 857 dst_key_settime(key, DST_TIME_ACTIVATE, now); 858 changed = true; 859 } 860 861 /* 862 * Make sure the key state goals are written. 863 */ 864 if (write_state) { 865 if (setgoal) { 866 if (goal == DST_KEY_STATE_NA) { 867 dst_key_unsetstate(key, DST_KEY_GOAL); 868 } else { 869 dst_key_setstate(key, DST_KEY_GOAL, goal); 870 } 871 changed = true; 872 } 873 if (setds) { 874 if (ds == DST_KEY_STATE_NA) { 875 dst_key_unsetstate(key, DST_KEY_DS); 876 dst_key_unsettime(key, DST_TIME_DS); 877 } else { 878 dst_key_setstate(key, DST_KEY_DS, ds); 879 dst_key_settime(key, DST_TIME_DS, dstime); 880 } 881 changed = true; 882 } 883 if (setdnskey) { 884 if (dnskey == DST_KEY_STATE_NA) { 885 dst_key_unsetstate(key, DST_KEY_DNSKEY); 886 dst_key_unsettime(key, DST_TIME_DNSKEY); 887 } else { 888 dst_key_setstate(key, DST_KEY_DNSKEY, dnskey); 889 dst_key_settime(key, DST_TIME_DNSKEY, 890 dnskeytime); 891 } 892 changed = true; 893 } 894 if (setkrrsig) { 895 if (krrsig == DST_KEY_STATE_NA) { 896 dst_key_unsetstate(key, DST_KEY_KRRSIG); 897 dst_key_unsettime(key, DST_TIME_KRRSIG); 898 } else { 899 dst_key_setstate(key, DST_KEY_KRRSIG, krrsig); 900 dst_key_settime(key, DST_TIME_KRRSIG, 901 krrsigtime); 902 } 903 changed = true; 904 } 905 if (setzrrsig) { 906 if (zrrsig == DST_KEY_STATE_NA) { 907 dst_key_unsetstate(key, DST_KEY_ZRRSIG); 908 dst_key_unsettime(key, DST_TIME_ZRRSIG); 909 } else { 910 dst_key_setstate(key, DST_KEY_ZRRSIG, zrrsig); 911 dst_key_settime(key, DST_TIME_ZRRSIG, 912 zrrsigtime); 913 } 914 changed = true; 915 } 916 } 917 918 if (!changed && setttl) { 919 changed = true; 920 } 921 922 /* 923 * Print out time values, if -p was used. 924 */ 925 if (printcreate) { 926 printtime(key, DST_TIME_CREATED, "Created", epoch, stdout); 927 } 928 929 if (printpub) { 930 printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout); 931 } 932 933 if (printact) { 934 printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout); 935 } 936 937 if (printrev) { 938 printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout); 939 } 940 941 if (printinact) { 942 printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout); 943 } 944 945 if (printdel) { 946 printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout); 947 } 948 949 if (printsyncadd) { 950 printtime(key, DST_TIME_SYNCPUBLISH, "SYNC Publish", epoch, 951 stdout); 952 } 953 954 if (printsyncdel) { 955 printtime(key, DST_TIME_SYNCDELETE, "SYNC Delete", epoch, 956 stdout); 957 } 958 959 if (printdsadd) { 960 printtime(key, DST_TIME_DSPUBLISH, "DS Publish", epoch, stdout); 961 } 962 963 if (printdsdel) { 964 printtime(key, DST_TIME_DSDELETE, "DS Delete", epoch, stdout); 965 } 966 967 if (changed) { 968 writekey(key, directory, write_state); 969 if (predecessor != NULL && prevkey != NULL) { 970 writekey(prevkey, directory, write_state); 971 } 972 } 973 974 if (prevkey != NULL) { 975 dst_key_free(&prevkey); 976 } 977 dst_key_free(&key); 978 dst_lib_destroy(); 979 if (verbose > 10) { 980 isc_mem_stats(mctx, stdout); 981 } 982 cleanup_logging(&log); 983 isc_mem_free(mctx, directory); 984 isc_mem_destroy(&mctx); 985 986 return (0); 987 } 988