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