1 /* $NetBSD: dnssec-keyfromlabel.c,v 1.8 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 <ctype.h> 19 #include <inttypes.h> 20 #include <stdbool.h> 21 #include <stdlib.h> 22 23 #include <isc/buffer.h> 24 #include <isc/commandline.h> 25 #include <isc/mem.h> 26 #include <isc/print.h> 27 #include <isc/region.h> 28 #include <isc/string.h> 29 #include <isc/util.h> 30 31 #include <pk11/site.h> 32 33 #include <dns/dnssec.h> 34 #include <dns/fixedname.h> 35 #include <dns/keyvalues.h> 36 #include <dns/log.h> 37 #include <dns/name.h> 38 #include <dns/rdataclass.h> 39 #include <dns/result.h> 40 #include <dns/secalg.h> 41 42 #include <dst/dst.h> 43 44 #if USE_PKCS11 45 #include <pk11/result.h> 46 #endif /* if USE_PKCS11 */ 47 48 #include "dnssectool.h" 49 50 #define MAX_RSA 4096 /* should be long enough... */ 51 52 const char *program = "dnssec-keyfromlabel"; 53 54 ISC_PLATFORM_NORETURN_PRE static void 55 usage(void) ISC_PLATFORM_NORETURN_POST; 56 57 static void 58 usage(void) { 59 fprintf(stderr, "Usage:\n"); 60 fprintf(stderr, " %s -l label [options] name\n\n", program); 61 fprintf(stderr, "Version: %s\n", VERSION); 62 fprintf(stderr, "Required options:\n"); 63 fprintf(stderr, " -l label: label of the key pair\n"); 64 fprintf(stderr, " name: owner of the key\n"); 65 fprintf(stderr, "Other options:\n"); 66 fprintf(stderr, " -a algorithm: \n" 67 " DH | RSASHA1 |\n" 68 " NSEC3RSASHA1 |\n" 69 " RSASHA256 | RSASHA512 |\n" 70 " ECDSAP256SHA256 | ECDSAP384SHA384 |\n" 71 " ED25519 | ED448\n"); 72 fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); 73 fprintf(stderr, " -c class (default: IN)\n"); 74 fprintf(stderr, " -E <engine>:\n"); 75 #if USE_PKCS11 76 fprintf(stderr, 77 " path to PKCS#11 provider library " 78 "(default is %s)\n", 79 PK11_LIB_LOCATION); 80 #else /* if USE_PKCS11 */ 81 fprintf(stderr, " name of an OpenSSL engine to use\n"); 82 #endif /* if USE_PKCS11 */ 83 fprintf(stderr, " -f keyflag: KSK | REVOKE\n"); 84 fprintf(stderr, " -K directory: directory in which to place " 85 "key files\n"); 86 fprintf(stderr, " -k: generate a TYPE=KEY key\n"); 87 fprintf(stderr, " -L ttl: default key TTL\n"); 88 fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | " 89 "OTHER\n"); 90 fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); 91 fprintf(stderr, " -p protocol: default: 3 [dnssec]\n"); 92 fprintf(stderr, " -t type: " 93 "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " 94 "(default: AUTHCONF)\n"); 95 fprintf(stderr, " -y: permit keys that might collide\n"); 96 fprintf(stderr, " -v verbose level\n"); 97 fprintf(stderr, " -V: print version information\n"); 98 fprintf(stderr, "Date options:\n"); 99 fprintf(stderr, " -P date/[+-]offset: set key publication date\n"); 100 fprintf(stderr, " -P sync date/[+-]offset: set CDS and CDNSKEY " 101 "publication date\n"); 102 fprintf(stderr, " -A date/[+-]offset: set key activation date\n"); 103 fprintf(stderr, " -R date/[+-]offset: set key revocation date\n"); 104 fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n"); 105 fprintf(stderr, " -D date/[+-]offset: set key deletion date\n"); 106 fprintf(stderr, " -D sync date/[+-]offset: set CDS and CDNSKEY " 107 "deletion date\n"); 108 fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); 109 fprintf(stderr, " -C: generate a backward-compatible key, omitting" 110 " all dates\n"); 111 fprintf(stderr, " -S <key>: generate a successor to an existing " 112 "key\n"); 113 fprintf(stderr, " -i <interval>: prepublication interval for " 114 "successor key " 115 "(default: 30 days)\n"); 116 fprintf(stderr, "Output:\n"); 117 fprintf(stderr, " K<name>+<alg>+<id>.key, " 118 "K<name>+<alg>+<id>.private\n"); 119 120 exit(-1); 121 } 122 123 int 124 main(int argc, char **argv) { 125 char *algname = NULL, *freeit = NULL; 126 char *nametype = NULL, *type = NULL; 127 const char *directory = NULL; 128 const char *predecessor = NULL; 129 dst_key_t *prevkey = NULL; 130 const char *engine = NULL; 131 char *classname = NULL; 132 char *endp; 133 dst_key_t *key = NULL; 134 dns_fixedname_t fname; 135 dns_name_t *name; 136 uint16_t flags = 0, kskflag = 0, revflag = 0; 137 dns_secalg_t alg; 138 bool oldstyle = false; 139 isc_mem_t *mctx = NULL; 140 int ch; 141 int protocol = -1, signatory = 0; 142 isc_result_t ret; 143 isc_textregion_t r; 144 char filename[255]; 145 isc_buffer_t buf; 146 isc_log_t *log = NULL; 147 dns_rdataclass_t rdclass; 148 int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; 149 char *label = NULL; 150 dns_ttl_t ttl = 0; 151 isc_stdtime_t publish = 0, activate = 0, revoke = 0; 152 isc_stdtime_t inactive = 0, deltime = 0; 153 isc_stdtime_t now; 154 int prepub = -1; 155 bool setpub = false, setact = false; 156 bool setrev = false, setinact = false; 157 bool setdel = false, setttl = false; 158 bool unsetpub = false, unsetact = false; 159 bool unsetrev = false, unsetinact = false; 160 bool unsetdel = false; 161 bool genonly = false; 162 bool use_nsec3 = false; 163 bool avoid_collisions = true; 164 bool exact; 165 unsigned char c; 166 isc_stdtime_t syncadd = 0, syncdel = 0; 167 bool unsetsyncadd = false, setsyncadd = false; 168 bool unsetsyncdel = false, setsyncdel = false; 169 170 if (argc == 1) { 171 usage(); 172 } 173 174 isc_mem_create(&mctx); 175 176 #if USE_PKCS11 177 pk11_result_register(); 178 #endif /* if USE_PKCS11 */ 179 dns_result_register(); 180 181 isc_commandline_errprint = false; 182 183 isc_stdtime_get(&now); 184 185 #define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:n:P:p:R:S:t:v:Vy" 186 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { 187 switch (ch) { 188 case '3': 189 use_nsec3 = true; 190 break; 191 case 'a': 192 algname = isc_commandline_argument; 193 break; 194 case 'C': 195 oldstyle = true; 196 break; 197 case 'c': 198 classname = isc_commandline_argument; 199 break; 200 case 'E': 201 engine = isc_commandline_argument; 202 break; 203 case 'f': 204 c = (unsigned char)(isc_commandline_argument[0]); 205 if (toupper(c) == 'K') { 206 kskflag = DNS_KEYFLAG_KSK; 207 } else if (toupper(c) == 'R') { 208 revflag = DNS_KEYFLAG_REVOKE; 209 } else { 210 fatal("unknown flag '%s'", 211 isc_commandline_argument); 212 } 213 break; 214 case 'K': 215 directory = isc_commandline_argument; 216 ret = try_dir(directory); 217 if (ret != ISC_R_SUCCESS) { 218 fatal("cannot open directory %s: %s", directory, 219 isc_result_totext(ret)); 220 } 221 break; 222 case 'k': 223 options |= DST_TYPE_KEY; 224 break; 225 case 'L': 226 ttl = strtottl(isc_commandline_argument); 227 setttl = true; 228 break; 229 case 'l': 230 label = isc_mem_strdup(mctx, isc_commandline_argument); 231 break; 232 case 'n': 233 nametype = isc_commandline_argument; 234 break; 235 case 'p': 236 protocol = strtol(isc_commandline_argument, &endp, 10); 237 if (*endp != '\0' || protocol < 0 || protocol > 255) { 238 fatal("-p must be followed by a number " 239 "[0..255]"); 240 } 241 break; 242 case 't': 243 type = isc_commandline_argument; 244 break; 245 case 'v': 246 verbose = strtol(isc_commandline_argument, &endp, 0); 247 if (*endp != '\0') { 248 fatal("-v must be followed by a number"); 249 } 250 break; 251 case 'y': 252 avoid_collisions = false; 253 break; 254 case 'G': 255 genonly = true; 256 break; 257 case 'P': 258 /* -Psync ? */ 259 if (isoptarg("sync", argv, usage)) { 260 if (unsetsyncadd || setsyncadd) { 261 fatal("-P sync specified more than " 262 "once"); 263 } 264 265 syncadd = strtotime(isc_commandline_argument, 266 now, now, &setsyncadd); 267 unsetsyncadd = !setsyncadd; 268 break; 269 } 270 /* -Pdnskey ? */ 271 (void)isoptarg("dnskey", argv, usage); 272 if (setpub || unsetpub) { 273 fatal("-P specified more than once"); 274 } 275 276 publish = strtotime(isc_commandline_argument, now, now, 277 &setpub); 278 unsetpub = !setpub; 279 break; 280 case 'A': 281 if (setact || unsetact) { 282 fatal("-A specified more than once"); 283 } 284 285 activate = strtotime(isc_commandline_argument, now, now, 286 &setact); 287 unsetact = !setact; 288 break; 289 case 'R': 290 if (setrev || unsetrev) { 291 fatal("-R specified more than once"); 292 } 293 294 revoke = strtotime(isc_commandline_argument, now, now, 295 &setrev); 296 unsetrev = !setrev; 297 break; 298 case 'I': 299 if (setinact || unsetinact) { 300 fatal("-I specified more than once"); 301 } 302 303 inactive = strtotime(isc_commandline_argument, now, now, 304 &setinact); 305 unsetinact = !setinact; 306 break; 307 case 'D': 308 /* -Dsync ? */ 309 if (isoptarg("sync", argv, usage)) { 310 if (unsetsyncdel || setsyncdel) { 311 fatal("-D sync specified more than " 312 "once"); 313 } 314 315 syncdel = strtotime(isc_commandline_argument, 316 now, now, &setsyncdel); 317 unsetsyncdel = !setsyncdel; 318 break; 319 } 320 /* -Ddnskey ? */ 321 (void)isoptarg("dnskey", argv, usage); 322 if (setdel || unsetdel) { 323 fatal("-D specified more than once"); 324 } 325 326 deltime = strtotime(isc_commandline_argument, now, now, 327 &setdel); 328 unsetdel = !setdel; 329 break; 330 case 'S': 331 predecessor = isc_commandline_argument; 332 break; 333 case 'i': 334 prepub = strtottl(isc_commandline_argument); 335 break; 336 case 'F': 337 /* Reserved for FIPS mode */ 338 FALLTHROUGH; 339 case '?': 340 if (isc_commandline_option != '?') { 341 fprintf(stderr, "%s: invalid argument -%c\n", 342 program, isc_commandline_option); 343 } 344 FALLTHROUGH; 345 case 'h': 346 /* Does not return. */ 347 usage(); 348 349 case 'V': 350 /* Does not return. */ 351 version(program); 352 353 default: 354 fprintf(stderr, "%s: unhandled option -%c\n", program, 355 isc_commandline_option); 356 exit(1); 357 } 358 } 359 360 ret = dst_lib_init(mctx, engine); 361 if (ret != ISC_R_SUCCESS) { 362 fatal("could not initialize dst: %s", isc_result_totext(ret)); 363 } 364 365 setup_logging(mctx, &log); 366 367 if (predecessor == NULL) { 368 if (label == NULL) { 369 fatal("the key label was not specified"); 370 } 371 if (argc < isc_commandline_index + 1) { 372 fatal("the key name was not specified"); 373 } 374 if (argc > isc_commandline_index + 1) { 375 fatal("extraneous arguments"); 376 } 377 378 name = dns_fixedname_initname(&fname); 379 isc_buffer_init(&buf, argv[isc_commandline_index], 380 strlen(argv[isc_commandline_index])); 381 isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); 382 ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); 383 if (ret != ISC_R_SUCCESS) { 384 fatal("invalid key name %s: %s", 385 argv[isc_commandline_index], 386 isc_result_totext(ret)); 387 } 388 389 if (strchr(label, ':') == NULL) { 390 char *l; 391 int len; 392 393 len = strlen(label) + 8; 394 l = isc_mem_allocate(mctx, len); 395 snprintf(l, len, "pkcs11:%s", label); 396 isc_mem_free(mctx, label); 397 label = l; 398 } 399 400 if (algname == NULL) { 401 fatal("no algorithm specified"); 402 } 403 404 r.base = algname; 405 r.length = strlen(algname); 406 ret = dns_secalg_fromtext(&alg, &r); 407 if (ret != ISC_R_SUCCESS) { 408 fatal("unknown algorithm %s", algname); 409 } 410 if (alg == DST_ALG_DH) { 411 options |= DST_TYPE_KEY; 412 } 413 414 if (use_nsec3) { 415 switch (alg) { 416 case DST_ALG_RSASHA1: 417 alg = DST_ALG_NSEC3RSASHA1; 418 break; 419 case DST_ALG_NSEC3RSASHA1: 420 case DST_ALG_RSASHA256: 421 case DST_ALG_RSASHA512: 422 case DST_ALG_ECDSA256: 423 case DST_ALG_ECDSA384: 424 case DST_ALG_ED25519: 425 case DST_ALG_ED448: 426 break; 427 default: 428 fatal("%s is incompatible with NSEC3; " 429 "do not use the -3 option", 430 algname); 431 } 432 } 433 434 if (type != NULL && (options & DST_TYPE_KEY) != 0) { 435 if (strcasecmp(type, "NOAUTH") == 0) { 436 flags |= DNS_KEYTYPE_NOAUTH; 437 } else if (strcasecmp(type, "NOCONF") == 0) { 438 flags |= DNS_KEYTYPE_NOCONF; 439 } else if (strcasecmp(type, "NOAUTHCONF") == 0) { 440 flags |= (DNS_KEYTYPE_NOAUTH | 441 DNS_KEYTYPE_NOCONF); 442 } else if (strcasecmp(type, "AUTHCONF") == 0) { 443 /* nothing */ 444 } else { 445 fatal("invalid type %s", type); 446 } 447 } 448 449 if (!oldstyle && prepub > 0) { 450 if (setpub && setact && (activate - prepub) < publish) { 451 fatal("Activation and publication dates " 452 "are closer together than the\n\t" 453 "prepublication interval."); 454 } 455 456 if (!setpub && !setact) { 457 setpub = setact = true; 458 publish = now; 459 activate = now + prepub; 460 } else if (setpub && !setact) { 461 setact = true; 462 activate = publish + prepub; 463 } else if (setact && !setpub) { 464 setpub = true; 465 publish = activate - prepub; 466 } 467 468 if ((activate - prepub) < now) { 469 fatal("Time until activation is shorter " 470 "than the\n\tprepublication interval."); 471 } 472 } 473 } else { 474 char keystr[DST_KEY_FORMATSIZE]; 475 isc_stdtime_t when; 476 int major, minor; 477 478 if (prepub == -1) { 479 prepub = (30 * 86400); 480 } 481 482 if (algname != NULL) { 483 fatal("-S and -a cannot be used together"); 484 } 485 if (nametype != NULL) { 486 fatal("-S and -n cannot be used together"); 487 } 488 if (type != NULL) { 489 fatal("-S and -t cannot be used together"); 490 } 491 if (setpub || unsetpub) { 492 fatal("-S and -P cannot be used together"); 493 } 494 if (setact || unsetact) { 495 fatal("-S and -A cannot be used together"); 496 } 497 if (use_nsec3) { 498 fatal("-S and -3 cannot be used together"); 499 } 500 if (oldstyle) { 501 fatal("-S and -C cannot be used together"); 502 } 503 if (genonly) { 504 fatal("-S and -G cannot be used together"); 505 } 506 507 ret = dst_key_fromnamedfile(predecessor, directory, 508 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, 509 mctx, &prevkey); 510 if (ret != ISC_R_SUCCESS) { 511 fatal("Invalid keyfile %s: %s", predecessor, 512 isc_result_totext(ret)); 513 } 514 if (!dst_key_isprivate(prevkey)) { 515 fatal("%s is not a private key", predecessor); 516 } 517 518 name = dst_key_name(prevkey); 519 alg = dst_key_alg(prevkey); 520 flags = dst_key_flags(prevkey); 521 522 dst_key_format(prevkey, keystr, sizeof(keystr)); 523 dst_key_getprivateformat(prevkey, &major, &minor); 524 if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) { 525 fatal("Key %s has incompatible format version %d.%d\n\t" 526 "It is not possible to generate a successor key.", 527 keystr, major, minor); 528 } 529 530 ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); 531 if (ret != ISC_R_SUCCESS) { 532 fatal("Key %s has no activation date.\n\t" 533 "You must use dnssec-settime -A to set one " 534 "before generating a successor.", 535 keystr); 536 } 537 538 ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); 539 if (ret != ISC_R_SUCCESS) { 540 fatal("Key %s has no inactivation date.\n\t" 541 "You must use dnssec-settime -I to set one " 542 "before generating a successor.", 543 keystr); 544 } 545 546 publish = activate - prepub; 547 if (publish < now) { 548 fatal("Key %s becomes inactive\n\t" 549 "sooner than the prepublication period " 550 "for the new key ends.\n\t" 551 "Either change the inactivation date with " 552 "dnssec-settime -I,\n\t" 553 "or use the -i option to set a shorter " 554 "prepublication interval.", 555 keystr); 556 } 557 558 ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); 559 if (ret != ISC_R_SUCCESS) { 560 fprintf(stderr, 561 "%s: WARNING: Key %s has no removal " 562 "date;\n\t it will remain in the zone " 563 "indefinitely after rollover.\n\t " 564 "You can use dnssec-settime -D to " 565 "change this.\n", 566 program, keystr); 567 } 568 569 setpub = setact = true; 570 } 571 572 if (nametype == NULL) { 573 if ((options & DST_TYPE_KEY) != 0) { /* KEY */ 574 fatal("no nametype specified"); 575 } 576 flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ 577 } else if (strcasecmp(nametype, "zone") == 0) { 578 flags |= DNS_KEYOWNER_ZONE; 579 } else if ((options & DST_TYPE_KEY) != 0) { /* KEY */ 580 if (strcasecmp(nametype, "host") == 0 || 581 strcasecmp(nametype, "entity") == 0) 582 { 583 flags |= DNS_KEYOWNER_ENTITY; 584 } else if (strcasecmp(nametype, "user") == 0) { 585 flags |= DNS_KEYOWNER_USER; 586 } else { 587 fatal("invalid KEY nametype %s", nametype); 588 } 589 } else if (strcasecmp(nametype, "other") != 0) { /* DNSKEY */ 590 fatal("invalid DNSKEY nametype %s", nametype); 591 } 592 593 rdclass = strtoclass(classname); 594 595 if (directory == NULL) { 596 directory = "."; 597 } 598 599 if ((options & DST_TYPE_KEY) != 0) { /* KEY */ 600 flags |= signatory; 601 } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ 602 flags |= kskflag; 603 flags |= revflag; 604 } 605 606 if (protocol == -1) { 607 protocol = DNS_KEYPROTO_DNSSEC; 608 } else if ((options & DST_TYPE_KEY) == 0 && 609 protocol != DNS_KEYPROTO_DNSSEC) 610 { 611 fatal("invalid DNSKEY protocol: %d", protocol); 612 } 613 614 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { 615 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) { 616 fatal("specified null key with signing authority"); 617 } 618 } 619 620 if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && 621 alg == DNS_KEYALG_DH) 622 { 623 fatal("a key with algorithm '%s' cannot be a zone key", 624 algname); 625 } 626 627 isc_buffer_init(&buf, filename, sizeof(filename) - 1); 628 629 /* associate the key */ 630 ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass, 631 #if USE_PKCS11 632 "pkcs11", 633 #else /* if USE_PKCS11 */ 634 engine, 635 #endif /* if USE_PKCS11 */ 636 label, NULL, mctx, &key); 637 638 if (ret != ISC_R_SUCCESS) { 639 char namestr[DNS_NAME_FORMATSIZE]; 640 char algstr[DNS_SECALG_FORMATSIZE]; 641 dns_name_format(name, namestr, sizeof(namestr)); 642 dns_secalg_format(alg, algstr, sizeof(algstr)); 643 fatal("failed to get key %s/%s: %s", namestr, algstr, 644 isc_result_totext(ret)); 645 UNREACHABLE(); 646 exit(-1); 647 } 648 649 /* 650 * Set key timing metadata (unless using -C) 651 * 652 * Publish and activation dates are set to "now" by default, but 653 * can be overridden. Creation date is always set to "now". 654 */ 655 if (!oldstyle) { 656 dst_key_settime(key, DST_TIME_CREATED, now); 657 658 if (genonly && (setpub || setact)) { 659 fatal("cannot use -G together with -P or -A options"); 660 } 661 662 if (setpub) { 663 dst_key_settime(key, DST_TIME_PUBLISH, publish); 664 } else if (setact) { 665 dst_key_settime(key, DST_TIME_PUBLISH, activate); 666 } else if (!genonly && !unsetpub) { 667 dst_key_settime(key, DST_TIME_PUBLISH, now); 668 } 669 670 if (setact) { 671 dst_key_settime(key, DST_TIME_ACTIVATE, activate); 672 } else if (!genonly && !unsetact) { 673 dst_key_settime(key, DST_TIME_ACTIVATE, now); 674 } 675 676 if (setrev) { 677 if (kskflag == 0) { 678 fprintf(stderr, 679 "%s: warning: Key is " 680 "not flagged as a KSK, but -R " 681 "was used. Revoking a ZSK is " 682 "legal, but undefined.\n", 683 program); 684 } 685 dst_key_settime(key, DST_TIME_REVOKE, revoke); 686 } 687 688 if (setinact) { 689 dst_key_settime(key, DST_TIME_INACTIVE, inactive); 690 } 691 692 if (setdel) { 693 dst_key_settime(key, DST_TIME_DELETE, deltime); 694 } 695 if (setsyncadd) { 696 dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); 697 } 698 if (setsyncdel) { 699 dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); 700 } 701 } else { 702 if (setpub || setact || setrev || setinact || setdel || 703 unsetpub || unsetact || unsetrev || unsetinact || 704 unsetdel || genonly || setsyncadd || setsyncdel) 705 { 706 fatal("cannot use -C together with " 707 "-P, -A, -R, -I, -D, or -G options"); 708 } 709 /* 710 * Compatibility mode: Private-key-format 711 * should be set to 1.2. 712 */ 713 dst_key_setprivateformat(key, 1, 2); 714 } 715 716 /* Set default key TTL */ 717 if (setttl) { 718 dst_key_setttl(key, ttl); 719 } 720 721 /* 722 * Do not overwrite an existing key. Warn LOUDLY if there 723 * is a risk of ID collision due to this key or another key 724 * being revoked. 725 */ 726 if (key_collision(key, name, directory, mctx, &exact)) { 727 isc_buffer_clear(&buf); 728 ret = dst_key_buildfilename(key, 0, directory, &buf); 729 if (ret != ISC_R_SUCCESS) { 730 fatal("dst_key_buildfilename returned: %s\n", 731 isc_result_totext(ret)); 732 } 733 if (exact) { 734 fatal("%s: %s already exists\n", program, filename); 735 } 736 737 if (avoid_collisions) { 738 fatal("%s: %s could collide with another key upon " 739 "revokation\n", 740 program, filename); 741 } 742 743 fprintf(stderr, 744 "%s: WARNING: Key %s could collide with " 745 "another key upon revokation. If you plan " 746 "to revoke keys, destroy this key and " 747 "generate a different one.\n", 748 program, filename); 749 } 750 751 ret = dst_key_tofile(key, options, directory); 752 if (ret != ISC_R_SUCCESS) { 753 char keystr[DST_KEY_FORMATSIZE]; 754 dst_key_format(key, keystr, sizeof(keystr)); 755 fatal("failed to write key %s: %s\n", keystr, 756 isc_result_totext(ret)); 757 } 758 759 isc_buffer_clear(&buf); 760 ret = dst_key_buildfilename(key, 0, NULL, &buf); 761 if (ret != ISC_R_SUCCESS) { 762 fatal("dst_key_buildfilename returned: %s\n", 763 isc_result_totext(ret)); 764 } 765 printf("%s\n", filename); 766 dst_key_free(&key); 767 if (prevkey != NULL) { 768 dst_key_free(&prevkey); 769 } 770 771 cleanup_logging(&log); 772 dst_lib_destroy(); 773 if (verbose > 10) { 774 isc_mem_stats(mctx, stdout); 775 } 776 isc_mem_free(mctx, label); 777 isc_mem_destroy(&mctx); 778 779 if (freeit != NULL) { 780 free(freeit); 781 } 782 783 return (0); 784 } 785