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