Annotation of src/external/mpl/bind/dist/bin/dnssec/dnssec-keygen.c, Revision 1.7
1.7 ! christos 1: /* $NetBSD: dnssec-keygen.c,v 1.1.1.6 2020/08/03 17:07:02 christos Exp $ */
1.1 christos 2:
3: /*
4: * Portions 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 http://mozilla.org/MPL/2.0/.
9: *
10: * See the COPYRIGHT file distributed with this work for additional
11: * information regarding copyright ownership.
12: *
13: * Portions Copyright (C) Network Associates, Inc.
14: *
15: * Permission to use, copy, modify, and/or distribute this software for any
16: * purpose with or without fee is hereby granted, provided that the above
17: * copyright notice and this permission notice appear in all copies.
18: *
19: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
20: * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
21: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
22: * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
25: * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26: */
27:
28: /*! \file */
29:
30: #include <ctype.h>
1.3 christos 31: #include <inttypes.h>
32: #include <stdbool.h>
1.1 christos 33: #include <stdlib.h>
34: #include <unistd.h>
35:
36: #include <isc/buffer.h>
37: #include <isc/commandline.h>
38: #include <isc/mem.h>
39: #include <isc/print.h>
40: #include <isc/region.h>
41: #include <isc/string.h>
42: #include <isc/util.h>
43:
44: #include <pk11/site.h>
45:
46: #include <dns/dnssec.h>
47: #include <dns/fixedname.h>
1.6 christos 48: #include <dns/kasp.h>
1.1 christos 49: #include <dns/keyvalues.h>
50: #include <dns/log.h>
51: #include <dns/name.h>
52: #include <dns/rdataclass.h>
53: #include <dns/result.h>
54: #include <dns/secalg.h>
55:
56: #include <dst/dst.h>
57:
1.6 christos 58: #include <isccfg/cfg.h>
59: #include <isccfg/grammar.h>
60: #include <isccfg/kaspconf.h>
61: #include <isccfg/namedconf.h>
62:
1.3 christos 63: #if USE_PKCS11
1.1 christos 64: #include <pk11/result.h>
1.6 christos 65: #endif /* if USE_PKCS11 */
1.1 christos 66:
67: #include "dnssectool.h"
68:
69: #define MAX_RSA 4096 /* should be long enough... */
70:
71: const char *program = "dnssec-keygen";
1.6 christos 72:
73: isc_log_t *lctx = NULL;
1.1 christos 74:
75: ISC_PLATFORM_NORETURN_PRE static void
76: usage(void) ISC_PLATFORM_NORETURN_POST;
77:
1.6 christos 78: static void
79: progress(int p);
80:
81: struct keygen_ctx {
82: const char *predecessor;
83: const char *policy;
84: const char *configfile;
85: const char *directory;
86: char *algname;
87: char *nametype;
88: char *type;
89: int generator;
90: int protocol;
91: int size;
92: int signatory;
93: dns_rdataclass_t rdclass;
94: int options;
95: int dbits;
96: dns_ttl_t ttl;
97: uint16_t kskflag;
98: uint16_t revflag;
99: dns_secalg_t alg;
100: /* timing data */
101: int prepub;
102: isc_stdtime_t now;
103: isc_stdtime_t publish;
104: isc_stdtime_t activate;
105: isc_stdtime_t inactive;
106: isc_stdtime_t revokekey;
107: isc_stdtime_t deltime;
108: isc_stdtime_t syncadd;
109: isc_stdtime_t syncdel;
110: bool setpub;
111: bool setact;
112: bool setinact;
113: bool setrev;
114: bool setdel;
115: bool setsyncadd;
116: bool setsyncdel;
117: bool unsetpub;
118: bool unsetact;
119: bool unsetinact;
120: bool unsetrev;
121: bool unsetdel;
122: /* how to generate the key */
123: bool setttl;
124: bool use_nsec3;
125: bool genonly;
126: bool showprogress;
127: bool quiet;
128: bool oldstyle;
129: /* state */
130: time_t lifetime;
131: bool ksk;
132: bool zsk;
133: };
134:
135: typedef struct keygen_ctx keygen_ctx_t;
1.1 christos 136:
137: static void
138: usage(void) {
139: fprintf(stderr, "Usage:\n");
140: fprintf(stderr, " %s [options] name\n\n", program);
141: fprintf(stderr, "Version: %s\n", VERSION);
142: fprintf(stderr, " name: owner of the key\n");
143: fprintf(stderr, "Options:\n");
144: fprintf(stderr, " -K <directory>: write keys into directory\n");
1.6 christos 145: fprintf(stderr, " -k <policy>: generate keys for dnssec-policy\n");
146: fprintf(stderr, " -l <file>: configuration file with dnssec-policy "
147: "statement\n");
1.1 christos 148: fprintf(stderr, " -a <algorithm>:\n");
1.4 christos 149: fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n");
1.3 christos 150: fprintf(stderr, " RSASHA256 | RSASHA512 |\n");
1.1 christos 151: fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
1.3 christos 152: fprintf(stderr, " ED25519 | ED448 | DH\n");
1.1 christos 153: fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
154: fprintf(stderr, " -b <key size in bits>:\n");
155: fprintf(stderr, " RSASHA1:\t[1024..%d]\n", MAX_RSA);
156: fprintf(stderr, " NSEC3RSASHA1:\t[1024..%d]\n", MAX_RSA);
157: fprintf(stderr, " RSASHA256:\t[1024..%d]\n", MAX_RSA);
158: fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
159: fprintf(stderr, " DH:\t\t[128..4096]\n");
160: fprintf(stderr, " ECDSAP256SHA256:\tignored\n");
161: fprintf(stderr, " ECDSAP384SHA384:\tignored\n");
162: fprintf(stderr, " ED25519:\tignored\n");
163: fprintf(stderr, " ED448:\tignored\n");
164: fprintf(stderr, " (key size defaults are set according to\n"
165: " algorithm and usage (ZSK or KSK)\n");
166: fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
1.6 christos 167: "USER | OTHER\n");
1.1 christos 168: fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
169: fprintf(stderr, " -c <class>: (default: IN)\n");
170: fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
171: fprintf(stderr, " -E <engine>:\n");
1.3 christos 172: #if USE_PKCS11
1.6 christos 173: fprintf(stderr,
174: " path to PKCS#11 provider library "
175: "(default is %s)\n",
176: PK11_LIB_LOCATION);
177: #else /* if USE_PKCS11 */
1.1 christos 178: fprintf(stderr, " name of an OpenSSL engine to use\n");
1.6 christos 179: #endif /* if USE_PKCS11 */
1.1 christos 180: fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n");
181: fprintf(stderr, " -g <generator>: use specified generator "
182: "(DH only)\n");
183: fprintf(stderr, " -L <ttl>: default key TTL\n");
184: fprintf(stderr, " -p <protocol>: (default: 3 [dnssec])\n");
185: fprintf(stderr, " -s <strength>: strength value this key signs DNS "
186: "records with (default: 0)\n");
187: fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; "
188: "use KEY for SIG(0))\n");
189: fprintf(stderr, " -t <type>: "
190: "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
191: "(default: AUTHCONF)\n");
192: fprintf(stderr, " -h: print usage and exit\n");
193: fprintf(stderr, " -m <memory debugging mode>:\n");
194: fprintf(stderr, " usage | trace | record | size | mctx\n");
195: fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n");
196: fprintf(stderr, " -V: print version information\n");
197: fprintf(stderr, "Timing options:\n");
198: fprintf(stderr, " -P date/[+-]offset/none: set key publication date "
1.6 christos 199: "(default: now)\n");
1.1 christos 200: fprintf(stderr, " -P sync date/[+-]offset/none: set CDS and CDNSKEY "
1.6 christos 201: "publication date\n");
1.1 christos 202: fprintf(stderr, " -A date/[+-]offset/none: set key activation date "
1.6 christos 203: "(default: now)\n");
1.1 christos 204: fprintf(stderr, " -R date/[+-]offset/none: set key "
1.6 christos 205: "revocation date\n");
1.1 christos 206: fprintf(stderr, " -I date/[+-]offset/none: set key "
1.6 christos 207: "inactivation date\n");
1.1 christos 208: fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n");
209: fprintf(stderr, " -D sync date/[+-]offset/none: set CDS and CDNSKEY "
1.6 christos 210: "deletion date\n");
1.1 christos 211:
212: fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
213: fprintf(stderr, " -C: generate a backward-compatible key, omitting "
214: "all dates\n");
215: fprintf(stderr, " -S <key>: generate a successor to an existing "
1.6 christos 216: "key\n");
1.1 christos 217: fprintf(stderr, " -i <interval>: prepublication interval for "
1.6 christos 218: "successor key "
219: "(default: 30 days)\n");
1.1 christos 220: fprintf(stderr, "Output:\n");
221: fprintf(stderr, " K<name>+<alg>+<id>.key, "
222: "K<name>+<alg>+<id>.private\n");
223:
1.6 christos 224: exit(-1);
1.1 christos 225: }
226:
227: static void
1.6 christos 228: progress(int p) {
1.1 christos 229: char c = '*';
230:
231: switch (p) {
232: case 0:
233: c = '.';
234: break;
235: case 1:
236: c = '+';
237: break;
238: case 2:
239: c = '*';
240: break;
241: case 3:
242: c = ' ';
243: break;
244: default:
245: break;
246: }
1.6 christos 247: (void)putc(c, stderr);
248: (void)fflush(stderr);
1.1 christos 249: }
250:
1.6 christos 251: static void
252: kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
253: dns_kasp_t **kaspp) {
254: const cfg_listelt_t *element;
255: const cfg_obj_t *kasps = NULL;
256: dns_kasp_t *kasp = NULL, *kasp_next;
257: isc_result_t result = ISC_R_NOTFOUND;
258: dns_kasplist_t kasplist;
259:
260: ISC_LIST_INIT(kasplist);
261:
262: (void)cfg_map_get(config, "dnssec-policy", &kasps);
263: for (element = cfg_list_first(kasps); element != NULL;
264: element = cfg_list_next(element))
265: {
266: cfg_obj_t *kconfig = cfg_listelt_value(element);
267: kasp = NULL;
268: if (strcmp(cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
269: name) != 0) {
270: continue;
271: }
1.1 christos 272:
1.6 christos 273: result = cfg_kasp_fromconfig(kconfig, mctx, lctx, &kasplist,
274: &kasp);
275: if (result != ISC_R_SUCCESS) {
276: fatal("failed to configure dnssec-policy '%s': %s",
277: cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
278: isc_result_totext(result));
279: }
280: INSIST(kasp != NULL);
281: dns_kasp_freeze(kasp);
282: break;
283: }
1.1 christos 284:
1.6 christos 285: *kaspp = kasp;
1.1 christos 286:
287: /*
1.6 christos 288: * Same cleanup for kasp list.
1.1 christos 289: */
1.6 christos 290: for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
291: kasp_next = ISC_LIST_NEXT(kasp, link);
292: ISC_LIST_UNLINK(kasplist, kasp, link);
293: dns_kasp_detach(&kasp);
1.1 christos 294: }
1.6 christos 295: }
1.1 christos 296:
1.6 christos 297: static void
298: keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
299: char filename[255];
300: char algstr[DNS_SECALG_FORMATSIZE];
301: uint16_t flags = 0;
302: int param = 0;
303: bool null_key = false;
304: bool conflict = false;
305: bool show_progress = false;
306: isc_buffer_t buf;
307: dns_name_t *name;
308: dns_fixedname_t fname;
309: isc_result_t ret;
310: dst_key_t *key = NULL;
311: dst_key_t *prevkey = NULL;
312:
313: UNUSED(argc);
314:
315: dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
316:
317: if (ctx->predecessor == NULL) {
318: if (ctx->prepub == -1) {
319: ctx->prepub = 0;
1.1 christos 320: }
321:
322: name = dns_fixedname_initname(&fname);
323: isc_buffer_init(&buf, argv[isc_commandline_index],
324: strlen(argv[isc_commandline_index]));
325: isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
326: ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
1.6 christos 327: if (ret != ISC_R_SUCCESS) {
1.1 christos 328: fatal("invalid key name %s: %s",
329: argv[isc_commandline_index],
330: isc_result_totext(ret));
331: }
332:
1.6 christos 333: if (!dst_algorithm_supported(ctx->alg)) {
334: fatal("unsupported algorithm: %s", algstr);
1.1 christos 335: }
336:
1.6 christos 337: if (ctx->alg == DST_ALG_DH) {
338: ctx->options |= DST_TYPE_KEY;
1.1 christos 339: }
340:
1.6 christos 341: if (ctx->use_nsec3) {
342: switch (ctx->alg) {
1.1 christos 343: case DST_ALG_RSASHA1:
1.6 christos 344: ctx->alg = DST_ALG_NSEC3RSASHA1;
1.1 christos 345: break;
346: case DST_ALG_NSEC3RSASHA1:
347: case DST_ALG_RSASHA256:
348: case DST_ALG_RSASHA512:
349: case DST_ALG_ECDSA256:
350: case DST_ALG_ECDSA384:
351: case DST_ALG_ED25519:
352: case DST_ALG_ED448:
353: break;
354: default:
1.6 christos 355: fatal("algorithm %s is incompatible with NSEC3"
356: ", do not use the -3 option",
357: algstr);
1.1 christos 358: }
359: }
360:
1.6 christos 361: if (ctx->type != NULL && (ctx->options & DST_TYPE_KEY) != 0) {
362: if (strcasecmp(ctx->type, "NOAUTH") == 0) {
1.1 christos 363: flags |= DNS_KEYTYPE_NOAUTH;
1.6 christos 364: } else if (strcasecmp(ctx->type, "NOCONF") == 0) {
1.1 christos 365: flags |= DNS_KEYTYPE_NOCONF;
1.6 christos 366: } else if (strcasecmp(ctx->type, "NOAUTHCONF") == 0) {
1.1 christos 367: flags |= (DNS_KEYTYPE_NOAUTH |
368: DNS_KEYTYPE_NOCONF);
1.6 christos 369: if (ctx->size < 0) {
370: ctx->size = 0;
371: }
372: } else if (strcasecmp(ctx->type, "AUTHCONF") == 0) {
373: /* nothing */
1.3 christos 374: } else {
1.6 christos 375: fatal("invalid type %s", ctx->type);
1.3 christos 376: }
1.1 christos 377: }
378:
1.6 christos 379: if (ctx->size < 0) {
380: switch (ctx->alg) {
1.1 christos 381: case DST_ALG_RSASHA1:
382: case DST_ALG_NSEC3RSASHA1:
383: case DST_ALG_RSASHA256:
384: case DST_ALG_RSASHA512:
1.6 christos 385: ctx->size = 2048;
1.1 christos 386: if (verbose > 0) {
1.6 christos 387: fprintf(stderr,
388: "key size not "
389: "specified; defaulting"
390: " to %d\n",
391: ctx->size);
1.1 christos 392: }
393: break;
394: case DST_ALG_ECDSA256:
395: case DST_ALG_ECDSA384:
396: case DST_ALG_ED25519:
397: case DST_ALG_ED448:
398: break;
399: default:
400: fatal("key size not specified (-b option)");
401: }
402: }
403:
1.6 christos 404: if (!ctx->oldstyle && ctx->prepub > 0) {
405: if (ctx->setpub && ctx->setact &&
406: (ctx->activate - ctx->prepub) < ctx->publish) {
1.1 christos 407: fatal("Activation and publication dates "
408: "are closer together than the\n\t"
409: "prepublication interval.");
1.6 christos 410: }
1.1 christos 411:
1.6 christos 412: if (!ctx->setpub && !ctx->setact) {
413: ctx->setpub = ctx->setact = true;
414: ctx->publish = ctx->now;
415: ctx->activate = ctx->now + ctx->prepub;
416: } else if (ctx->setpub && !ctx->setact) {
417: ctx->setact = true;
418: ctx->activate = ctx->publish + ctx->prepub;
419: } else if (ctx->setact && !ctx->setpub) {
420: ctx->setpub = true;
421: ctx->publish = ctx->activate - ctx->prepub;
1.1 christos 422: }
423:
1.6 christos 424: if ((ctx->activate - ctx->prepub) < ctx->now) {
1.1 christos 425: fatal("Time until activation is shorter "
426: "than the\n\tprepublication interval.");
1.6 christos 427: }
1.1 christos 428: }
429: } else {
430: char keystr[DST_KEY_FORMATSIZE];
431: isc_stdtime_t when;
432: int major, minor;
433:
1.6 christos 434: if (ctx->prepub == -1) {
435: ctx->prepub = (30 * 86400);
436: }
1.1 christos 437:
1.6 christos 438: if (ctx->alg != 0) {
1.1 christos 439: fatal("-S and -a cannot be used together");
1.6 christos 440: }
441: if (ctx->size >= 0) {
1.1 christos 442: fatal("-S and -b cannot be used together");
1.6 christos 443: }
444: if (ctx->nametype != NULL) {
1.1 christos 445: fatal("-S and -n cannot be used together");
1.6 christos 446: }
447: if (ctx->type != NULL) {
1.1 christos 448: fatal("-S and -t cannot be used together");
1.6 christos 449: }
450: if (ctx->setpub || ctx->unsetpub) {
1.1 christos 451: fatal("-S and -P cannot be used together");
1.6 christos 452: }
453: if (ctx->setact || ctx->unsetact) {
1.1 christos 454: fatal("-S and -A cannot be used together");
1.6 christos 455: }
456: if (ctx->use_nsec3) {
1.1 christos 457: fatal("-S and -3 cannot be used together");
1.6 christos 458: }
459: if (ctx->oldstyle) {
1.1 christos 460: fatal("-S and -C cannot be used together");
1.6 christos 461: }
462: if (ctx->genonly) {
1.1 christos 463: fatal("-S and -G cannot be used together");
1.6 christos 464: }
1.1 christos 465:
1.6 christos 466: ret = dst_key_fromnamedfile(
467: ctx->predecessor, ctx->directory,
468: (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE),
469: mctx, &prevkey);
470: if (ret != ISC_R_SUCCESS) {
471: fatal("Invalid keyfile %s: %s", ctx->predecessor,
472: isc_result_totext(ret));
473: }
474: if (!dst_key_isprivate(prevkey)) {
475: fatal("%s is not a private key", ctx->predecessor);
476: }
1.1 christos 477:
478: name = dst_key_name(prevkey);
1.6 christos 479: ctx->alg = dst_key_alg(prevkey);
480: ctx->size = dst_key_size(prevkey);
1.1 christos 481: flags = dst_key_flags(prevkey);
482:
483: dst_key_format(prevkey, keystr, sizeof(keystr));
484: dst_key_getprivateformat(prevkey, &major, &minor);
1.6 christos 485: if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
1.1 christos 486: fatal("Key %s has incompatible format version %d.%d\n\t"
487: "It is not possible to generate a successor key.",
488: keystr, major, minor);
1.6 christos 489: }
1.1 christos 490:
491: ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
1.6 christos 492: if (ret != ISC_R_SUCCESS) {
1.1 christos 493: fatal("Key %s has no activation date.\n\t"
494: "You must use dnssec-settime -A to set one "
1.6 christos 495: "before generating a successor.",
496: keystr);
497: }
1.1 christos 498:
1.6 christos 499: ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE,
500: &ctx->activate);
501: if (ret != ISC_R_SUCCESS) {
1.1 christos 502: fatal("Key %s has no inactivation date.\n\t"
503: "You must use dnssec-settime -I to set one "
1.6 christos 504: "before generating a successor.",
505: keystr);
506: }
1.1 christos 507:
1.6 christos 508: ctx->publish = ctx->activate - ctx->prepub;
509: if (ctx->publish < ctx->now) {
1.1 christos 510: fatal("Key %s becomes inactive\n\t"
511: "sooner than the prepublication period "
512: "for the new key ends.\n\t"
513: "Either change the inactivation date with "
514: "dnssec-settime -I,\n\t"
515: "or use the -i option to set a shorter "
1.6 christos 516: "prepublication interval.",
517: keystr);
518: }
1.1 christos 519:
520: ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
1.6 christos 521: if (ret != ISC_R_SUCCESS) {
522: fprintf(stderr,
523: "%s: WARNING: Key %s has no removal "
524: "date;\n\t it will remain in the zone "
525: "indefinitely after rollover.\n\t "
526: "You can use dnssec-settime -D to "
527: "change this.\n",
528: program, keystr);
529: }
1.1 christos 530:
1.6 christos 531: ctx->setpub = ctx->setact = true;
1.1 christos 532: }
533:
1.6 christos 534: switch (ctx->alg) {
1.1 christos 535: case DNS_KEYALG_RSASHA1:
536: case DNS_KEYALG_NSEC3RSASHA1:
537: case DNS_KEYALG_RSASHA256:
1.6 christos 538: if (ctx->size != 0 && (ctx->size < 1024 || ctx->size > MAX_RSA))
539: {
540: fatal("RSA key size %d out of range", ctx->size);
541: }
1.1 christos 542: break;
543: case DNS_KEYALG_RSASHA512:
1.6 christos 544: if (ctx->size != 0 && (ctx->size < 1024 || ctx->size > MAX_RSA))
545: {
546: fatal("RSA key size %d out of range", ctx->size);
547: }
1.1 christos 548: break;
549: case DNS_KEYALG_DH:
1.6 christos 550: if (ctx->size != 0 && (ctx->size < 128 || ctx->size > 4096)) {
551: fatal("DH key size %d out of range", ctx->size);
552: }
1.1 christos 553: break;
554: case DST_ALG_ECDSA256:
1.6 christos 555: ctx->size = 256;
1.1 christos 556: break;
557: case DST_ALG_ECDSA384:
1.6 christos 558: ctx->size = 384;
1.1 christos 559: break;
560: case DST_ALG_ED25519:
1.6 christos 561: ctx->size = 256;
1.1 christos 562: break;
563: case DST_ALG_ED448:
1.6 christos 564: ctx->size = 456;
1.1 christos 565: break;
566: }
567:
1.6 christos 568: if (ctx->alg != DNS_KEYALG_DH && ctx->generator != 0) {
1.1 christos 569: fatal("specified DH generator for a non-DH key");
1.6 christos 570: }
1.1 christos 571:
1.6 christos 572: if (ctx->nametype == NULL) {
573: if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
1.1 christos 574: fatal("no nametype specified");
1.6 christos 575: }
576: flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
577: } else if (strcasecmp(ctx->nametype, "zone") == 0) {
1.1 christos 578: flags |= DNS_KEYOWNER_ZONE;
1.6 christos 579: } else if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
580: if (strcasecmp(ctx->nametype, "host") == 0 ||
581: strcasecmp(ctx->nametype, "entity") == 0)
582: {
1.1 christos 583: flags |= DNS_KEYOWNER_ENTITY;
1.6 christos 584: } else if (strcasecmp(ctx->nametype, "user") == 0) {
1.1 christos 585: flags |= DNS_KEYOWNER_USER;
1.6 christos 586: } else {
587: fatal("invalid KEY nametype %s", ctx->nametype);
588: }
589: } else if (strcasecmp(ctx->nametype, "other") != 0) { /* DNSKEY */
590: fatal("invalid DNSKEY nametype %s", ctx->nametype);
591: }
592:
593: if (ctx->directory == NULL) {
594: ctx->directory = ".";
595: }
596:
597: if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
598: flags |= ctx->signatory;
599: } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
600: flags |= ctx->kskflag;
601: flags |= ctx->revflag;
602: }
603:
604: if (ctx->protocol == -1) {
605: ctx->protocol = DNS_KEYPROTO_DNSSEC;
606: } else if ((ctx->options & DST_TYPE_KEY) == 0 &&
607: ctx->protocol != DNS_KEYPROTO_DNSSEC)
608: {
609: fatal("invalid DNSKEY protocol: %d", ctx->protocol);
610: }
1.1 christos 611:
612: if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
1.6 christos 613: if (ctx->size > 0) {
1.1 christos 614: fatal("specified null key with non-zero size");
1.6 christos 615: }
616: if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) {
1.1 christos 617: fatal("specified null key with signing authority");
1.6 christos 618: }
1.1 christos 619: }
620:
621: if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
1.6 christos 622: ctx->alg == DNS_KEYALG_DH)
1.3 christos 623: {
1.6 christos 624: fatal("a key with algorithm %s cannot be a zone key", algstr);
1.3 christos 625: }
1.1 christos 626:
1.6 christos 627: switch (ctx->alg) {
1.1 christos 628: case DNS_KEYALG_RSASHA1:
629: case DNS_KEYALG_NSEC3RSASHA1:
630: case DNS_KEYALG_RSASHA256:
631: case DNS_KEYALG_RSASHA512:
1.3 christos 632: show_progress = true;
1.1 christos 633: break;
634:
635: case DNS_KEYALG_DH:
1.6 christos 636: param = ctx->generator;
1.1 christos 637: break;
638:
639: case DST_ALG_ECDSA256:
640: case DST_ALG_ECDSA384:
641: case DST_ALG_ED25519:
642: case DST_ALG_ED448:
1.3 christos 643: show_progress = true;
1.1 christos 644: break;
645: }
646:
1.6 christos 647: if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
1.3 christos 648: null_key = true;
1.6 christos 649: }
1.1 christos 650:
651: isc_buffer_init(&buf, filename, sizeof(filename) - 1);
652:
653: do {
1.3 christos 654: conflict = false;
1.1 christos 655:
1.6 christos 656: if (!ctx->quiet && show_progress) {
1.1 christos 657: fprintf(stderr, "Generating key pair.");
1.6 christos 658: ret = dst_key_generate(name, ctx->alg, ctx->size, param,
659: flags, ctx->protocol,
660: ctx->rdclass, mctx, &key,
1.3 christos 661: &progress);
1.1 christos 662: putc('\n', stderr);
663: fflush(stderr);
664: } else {
1.6 christos 665: ret = dst_key_generate(name, ctx->alg, ctx->size, param,
666: flags, ctx->protocol,
667: ctx->rdclass, mctx, &key, NULL);
1.1 christos 668: }
669:
670: if (ret != ISC_R_SUCCESS) {
671: char namestr[DNS_NAME_FORMATSIZE];
672: dns_name_format(name, namestr, sizeof(namestr));
1.6 christos 673: fatal("failed to generate key %s/%s: %s\n", namestr,
674: algstr, isc_result_totext(ret));
1.1 christos 675: }
676:
1.6 christos 677: dst_key_setbits(key, ctx->dbits);
1.1 christos 678:
679: /*
680: * Set key timing metadata (unless using -C)
681: *
682: * Creation date is always set to "now".
683: *
684: * For a new key without an explicit predecessor, publish
685: * and activation dates are set to "now" by default, but
686: * can both be overridden.
687: *
688: * For a successor key, activation is set to match the
689: * predecessor's inactivation date. Publish is set to 30
690: * days earlier than that (XXX: this should be configurable).
691: * If either of the resulting dates are in the past, that's
692: * an error; the inactivation date of the predecessor key
693: * must be updated before a successor key can be created.
694: */
1.6 christos 695: if (!ctx->oldstyle) {
696: dst_key_settime(key, DST_TIME_CREATED, ctx->now);
1.1 christos 697:
1.6 christos 698: if (ctx->genonly && (ctx->setpub || ctx->setact)) {
1.1 christos 699: fatal("cannot use -G together with "
700: "-P or -A options");
1.6 christos 701: }
1.1 christos 702:
1.6 christos 703: if (ctx->setpub) {
704: dst_key_settime(key, DST_TIME_PUBLISH,
705: ctx->publish);
706: } else if (ctx->setact && !ctx->unsetpub) {
707: dst_key_settime(key, DST_TIME_PUBLISH,
708: ctx->activate - ctx->prepub);
709: } else if (!ctx->genonly && !ctx->unsetpub) {
1.1 christos 710: dst_key_settime(key, DST_TIME_PUBLISH,
1.6 christos 711: ctx->now);
712: }
1.1 christos 713:
1.6 christos 714: if (ctx->setact) {
715: dst_key_settime(key, DST_TIME_ACTIVATE,
716: ctx->activate);
717: } else if (!ctx->genonly && !ctx->unsetact) {
1.1 christos 718: dst_key_settime(key, DST_TIME_ACTIVATE,
1.6 christos 719: ctx->now);
720: }
721:
722: if (ctx->setrev) {
723: if (ctx->kskflag == 0) {
724: fprintf(stderr,
725: "%s: warning: Key is "
1.1 christos 726: "not flagged as a KSK, but -R "
727: "was used. Revoking a ZSK is "
728: "legal, but undefined.\n",
729: program);
1.6 christos 730: }
731: dst_key_settime(key, DST_TIME_REVOKE,
732: ctx->revokekey);
1.1 christos 733: }
734:
1.6 christos 735: if (ctx->setinact) {
1.1 christos 736: dst_key_settime(key, DST_TIME_INACTIVE,
1.6 christos 737: ctx->inactive);
738: }
1.1 christos 739:
1.6 christos 740: if (ctx->setdel) {
741: if (ctx->setinact &&
742: ctx->deltime < ctx->inactive) {
743: fprintf(stderr,
744: "%s: warning: Key is "
1.1 christos 745: "scheduled to be deleted "
746: "before it is scheduled to be "
747: "made inactive.\n",
748: program);
1.6 christos 749: }
750: dst_key_settime(key, DST_TIME_DELETE,
751: ctx->deltime);
1.1 christos 752: }
753:
1.6 christos 754: if (ctx->setsyncadd) {
1.1 christos 755: dst_key_settime(key, DST_TIME_SYNCPUBLISH,
1.6 christos 756: ctx->syncadd);
757: }
1.1 christos 758:
1.6 christos 759: if (ctx->setsyncdel) {
1.1 christos 760: dst_key_settime(key, DST_TIME_SYNCDELETE,
1.6 christos 761: ctx->syncdel);
762: }
1.1 christos 763: } else {
1.6 christos 764: if (ctx->setpub || ctx->setact || ctx->setrev ||
765: ctx->setinact || ctx->setdel || ctx->unsetpub ||
766: ctx->unsetact || ctx->unsetrev || ctx->unsetinact ||
767: ctx->unsetdel || ctx->genonly || ctx->setsyncadd ||
768: ctx->setsyncdel)
769: {
1.1 christos 770: fatal("cannot use -C together with "
771: "-P, -A, -R, -I, -D, or -G options");
1.6 christos 772: }
1.1 christos 773: /*
774: * Compatibility mode: Private-key-format
775: * should be set to 1.2.
776: */
777: dst_key_setprivateformat(key, 1, 2);
778: }
779:
780: /* Set the default key TTL */
1.6 christos 781: if (ctx->setttl) {
782: dst_key_setttl(key, ctx->ttl);
783: }
784:
785: /* Set dnssec-policy related metadata */
786: if (ctx->policy) {
787: dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
788: dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
789: dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
790: }
1.1 christos 791:
792: /*
793: * Do not overwrite an existing key, or create a key
794: * if there is a risk of ID collision due to this key
795: * or another key being revoked.
796: */
1.6 christos 797: if (key_collision(key, name, ctx->directory, mctx, NULL)) {
1.3 christos 798: conflict = true;
1.1 christos 799: if (null_key) {
800: dst_key_free(&key);
801: break;
802: }
803:
804: if (verbose > 0) {
805: isc_buffer_clear(&buf);
1.6 christos 806: ret = dst_key_buildfilename(
807: key, 0, ctx->directory, &buf);
808: if (ret == ISC_R_SUCCESS) {
1.1 christos 809: fprintf(stderr,
810: "%s: %s already exists, or "
811: "might collide with another "
812: "key upon revokation. "
813: "Generating a new key\n",
814: program, filename);
1.6 christos 815: }
1.1 christos 816: }
817:
818: dst_key_free(&key);
819: }
1.7 ! christos 820: } while (conflict);
1.1 christos 821:
1.6 christos 822: if (conflict) {
1.1 christos 823: fatal("cannot generate a null key due to possible key ID "
824: "collision");
1.6 christos 825: }
826:
827: if (ctx->predecessor != NULL && prevkey != NULL) {
828: dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key));
829: dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey));
1.1 christos 830:
1.6 christos 831: ret = dst_key_tofile(prevkey, ctx->options, ctx->directory);
832: if (ret != ISC_R_SUCCESS) {
833: char keystr[DST_KEY_FORMATSIZE];
834: dst_key_format(prevkey, keystr, sizeof(keystr));
835: fatal("failed to update predecessor %s: %s\n", keystr,
836: isc_result_totext(ret));
837: }
838: }
839:
840: ret = dst_key_tofile(key, ctx->options, ctx->directory);
1.1 christos 841: if (ret != ISC_R_SUCCESS) {
842: char keystr[DST_KEY_FORMATSIZE];
843: dst_key_format(key, keystr, sizeof(keystr));
844: fatal("failed to write key %s: %s\n", keystr,
845: isc_result_totext(ret));
846: }
847:
848: isc_buffer_clear(&buf);
849: ret = dst_key_buildfilename(key, 0, NULL, &buf);
1.6 christos 850: if (ret != ISC_R_SUCCESS) {
1.1 christos 851: fatal("dst_key_buildfilename returned: %s\n",
852: isc_result_totext(ret));
1.6 christos 853: }
1.1 christos 854: printf("%s\n", filename);
1.6 christos 855:
1.1 christos 856: dst_key_free(&key);
1.6 christos 857: if (prevkey != NULL) {
1.1 christos 858: dst_key_free(&prevkey);
1.6 christos 859: }
860: }
861:
862: int
863: main(int argc, char **argv) {
864: char *algname = NULL, *freeit = NULL;
865: char *classname = NULL;
866: char *endp;
867: isc_mem_t *mctx = NULL;
868: isc_result_t ret;
869: isc_textregion_t r;
870: const char *engine = NULL;
871: unsigned char c;
872: int ch;
873:
874: keygen_ctx_t ctx = {
875: .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC,
876: .prepub = -1,
877: .protocol = -1,
878: .size = -1,
879: };
880:
881: if (argc == 1) {
882: usage();
883: }
884:
885: #if USE_PKCS11
886: pk11_result_register();
887: #endif /* if USE_PKCS11 */
888: dns_result_register();
889:
890: isc_commandline_errprint = false;
891:
892: /*
893: * Process memory debugging argument first.
894: */
895: #define CMDLINE_FLAGS \
896: "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:k:L:l:m:n:P:p:qR:r:S:s:" \
897: "T:t:v:V"
898: while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
899: switch (ch) {
900: case 'm':
901: if (strcasecmp(isc_commandline_argument, "record") == 0)
902: {
903: isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
904: }
905: if (strcasecmp(isc_commandline_argument, "trace") == 0)
906: {
907: isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
908: }
909: if (strcasecmp(isc_commandline_argument, "usage") == 0)
910: {
911: isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
912: }
913: if (strcasecmp(isc_commandline_argument, "size") == 0) {
914: isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
915: }
916: if (strcasecmp(isc_commandline_argument, "mctx") == 0) {
917: isc_mem_debugging |= ISC_MEM_DEBUGCTX;
918: }
919: break;
920: default:
921: break;
922: }
923: }
924: isc_commandline_reset = true;
925:
926: isc_mem_create(&mctx);
927: isc_stdtime_get(&ctx.now);
1.1 christos 928:
1.6 christos 929: while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
930: switch (ch) {
931: case '3':
932: ctx.use_nsec3 = true;
933: break;
934: case 'a':
935: algname = isc_commandline_argument;
936: break;
937: case 'b':
938: ctx.size = strtol(isc_commandline_argument, &endp, 10);
939: if (*endp != '\0' || ctx.size < 0) {
940: fatal("-b requires a non-negative number");
941: }
942: break;
943: case 'C':
944: ctx.oldstyle = true;
945: break;
946: case 'c':
947: classname = isc_commandline_argument;
948: break;
949: case 'd':
950: ctx.dbits = strtol(isc_commandline_argument, &endp, 10);
951: if (*endp != '\0' || ctx.dbits < 0) {
952: fatal("-d requires a non-negative number");
953: }
954: break;
955: case 'E':
956: engine = isc_commandline_argument;
957: break;
958: case 'e':
959: fprintf(stderr, "phased-out option -e "
960: "(was 'use (RSA) large exponent')\n");
961: break;
962: case 'f':
963: c = (unsigned char)(isc_commandline_argument[0]);
964: if (toupper(c) == 'K') {
965: ctx.kskflag = DNS_KEYFLAG_KSK;
966: } else if (toupper(c) == 'R') {
967: ctx.revflag = DNS_KEYFLAG_REVOKE;
968: } else {
969: fatal("unknown flag '%s'",
970: isc_commandline_argument);
971: }
972: break;
973: case 'g':
974: ctx.generator = strtol(isc_commandline_argument, &endp,
975: 10);
976: if (*endp != '\0' || ctx.generator <= 0) {
977: fatal("-g requires a positive number");
978: }
979: break;
980: case 'K':
981: ctx.directory = isc_commandline_argument;
982: ret = try_dir(ctx.directory);
983: if (ret != ISC_R_SUCCESS) {
984: fatal("cannot open directory %s: %s",
985: ctx.directory, isc_result_totext(ret));
986: }
987: break;
988: case 'k':
989: ctx.policy = isc_commandline_argument;
990: break;
991: case 'L':
992: ctx.ttl = strtottl(isc_commandline_argument);
993: ctx.setttl = true;
994: break;
995: case 'l':
996: ctx.configfile = isc_commandline_argument;
997: break;
998: case 'n':
999: ctx.nametype = isc_commandline_argument;
1000: break;
1001: case 'm':
1002: break;
1003: case 'p':
1004: ctx.protocol = strtol(isc_commandline_argument, &endp,
1005: 10);
1006: if (*endp != '\0' || ctx.protocol < 0 ||
1007: ctx.protocol > 255) {
1008: fatal("-p must be followed by a number "
1009: "[0..255]");
1010: }
1011: break;
1012: case 'q':
1013: ctx.quiet = true;
1014: break;
1015: case 'r':
1016: fatal("The -r option has been deprecated.\n"
1017: "System random data is always used.\n");
1018: break;
1019: case 's':
1020: ctx.signatory = strtol(isc_commandline_argument, &endp,
1021: 10);
1022: if (*endp != '\0' || ctx.signatory < 0 ||
1023: ctx.signatory > 15) {
1024: fatal("-s must be followed by a number "
1025: "[0..15]");
1026: }
1027: break;
1028: case 'T':
1029: if (strcasecmp(isc_commandline_argument, "KEY") == 0) {
1030: ctx.options |= DST_TYPE_KEY;
1031: } else if (strcasecmp(isc_commandline_argument,
1032: "DNSKE"
1033: "Y") == 0)
1034: {
1035: /* default behavior */
1036: } else {
1037: fatal("unknown type '%s'",
1038: isc_commandline_argument);
1039: }
1040: break;
1041: case 't':
1042: ctx.type = isc_commandline_argument;
1043: break;
1044: case 'v':
1045: endp = NULL;
1046: verbose = strtol(isc_commandline_argument, &endp, 0);
1047: if (*endp != '\0') {
1048: fatal("-v must be followed by a number");
1049: }
1050: break;
1051: case 'G':
1052: ctx.genonly = true;
1053: break;
1054: case 'P':
1055: /* -Psync ? */
1056: if (isoptarg("sync", argv, usage)) {
1057: if (ctx.setsyncadd) {
1058: fatal("-P sync specified more than "
1059: "once");
1060: }
1061:
1062: ctx.syncadd = strtotime(
1063: isc_commandline_argument, ctx.now,
1064: ctx.now, &ctx.setsyncadd);
1065: break;
1066: }
1067: (void)isoptarg("dnskey", argv, usage);
1068: if (ctx.setpub || ctx.unsetpub) {
1069: fatal("-P specified more than once");
1070: }
1071:
1072: ctx.publish = strtotime(isc_commandline_argument,
1073: ctx.now, ctx.now, &ctx.setpub);
1074: ctx.unsetpub = !ctx.setpub;
1075: break;
1076: case 'A':
1077: if (ctx.setact || ctx.unsetact) {
1078: fatal("-A specified more than once");
1079: }
1080:
1081: ctx.activate = strtotime(isc_commandline_argument,
1082: ctx.now, ctx.now, &ctx.setact);
1083: ctx.unsetact = !ctx.setact;
1084: break;
1085: case 'R':
1086: if (ctx.setrev || ctx.unsetrev) {
1087: fatal("-R specified more than once");
1088: }
1089:
1090: ctx.revokekey = strtotime(isc_commandline_argument,
1091: ctx.now, ctx.now,
1092: &ctx.setrev);
1093: ctx.unsetrev = !ctx.setrev;
1094: break;
1095: case 'I':
1096: if (ctx.setinact || ctx.unsetinact) {
1097: fatal("-I specified more than once");
1098: }
1099:
1100: ctx.inactive = strtotime(isc_commandline_argument,
1101: ctx.now, ctx.now,
1102: &ctx.setinact);
1103: ctx.unsetinact = !ctx.setinact;
1104: break;
1105: case 'D':
1106: /* -Dsync ? */
1107: if (isoptarg("sync", argv, usage)) {
1108: if (ctx.setsyncdel) {
1109: fatal("-D sync specified more than "
1110: "once");
1111: }
1112:
1113: ctx.syncdel = strtotime(
1114: isc_commandline_argument, ctx.now,
1115: ctx.now, &ctx.setsyncdel);
1116: break;
1117: }
1118: (void)isoptarg("dnskey", argv, usage);
1119: if (ctx.setdel || ctx.unsetdel) {
1120: fatal("-D specified more than once");
1121: }
1122:
1123: ctx.deltime = strtotime(isc_commandline_argument,
1124: ctx.now, ctx.now, &ctx.setdel);
1125: ctx.unsetdel = !ctx.setdel;
1126: break;
1127: case 'S':
1128: ctx.predecessor = isc_commandline_argument;
1129: break;
1130: case 'i':
1131: ctx.prepub = strtottl(isc_commandline_argument);
1132: break;
1133: case 'F':
1134: /* Reserved for FIPS mode */
1135: /* FALLTHROUGH */
1136: case '?':
1137: if (isc_commandline_option != '?') {
1138: fprintf(stderr, "%s: invalid argument -%c\n",
1139: program, isc_commandline_option);
1140: }
1141: /* FALLTHROUGH */
1142: case 'h':
1143: /* Does not return. */
1144: usage();
1145:
1146: case 'V':
1147: /* Does not return. */
1148: version(program);
1149:
1150: default:
1151: fprintf(stderr, "%s: unhandled option -%c\n", program,
1152: isc_commandline_option);
1153: exit(1);
1154: }
1155: }
1156:
1157: if (!isatty(0)) {
1158: ctx.quiet = true;
1159: }
1160:
1161: ret = dst_lib_init(mctx, engine);
1162: if (ret != ISC_R_SUCCESS) {
1163: fatal("could not initialize dst: %s", isc_result_totext(ret));
1164: }
1165:
1166: setup_logging(mctx, &lctx);
1167:
1168: ctx.rdclass = strtoclass(classname);
1169:
1170: if (ctx.configfile == NULL || ctx.configfile[0] == '\0') {
1171: ctx.configfile = NAMED_CONFFILE;
1172: }
1173:
1174: if (ctx.predecessor == NULL) {
1175: if (argc < isc_commandline_index + 1) {
1176: fatal("the key name was not specified");
1177: }
1178: if (argc > isc_commandline_index + 1) {
1179: fatal("extraneous arguments");
1180: }
1181: }
1182:
1183: if (ctx.predecessor == NULL && ctx.policy == NULL) {
1184: if (algname == NULL) {
1185: fatal("no algorithm specified");
1186: }
1187: r.base = algname;
1188: r.length = strlen(algname);
1189: ret = dns_secalg_fromtext(&ctx.alg, &r);
1190: if (ret != ISC_R_SUCCESS) {
1191: fatal("unknown algorithm %s", algname);
1192: }
1193: if (!dst_algorithm_supported(ctx.alg)) {
1194: fatal("unsupported algorithm: %s", algname);
1195: }
1196: }
1197:
1198: if (ctx.policy != NULL) {
1199: if (ctx.nametype != NULL) {
1200: fatal("-k and -n cannot be used together");
1201: }
1202: if (ctx.predecessor != NULL) {
1203: fatal("-k and -S cannot be used together");
1204: }
1205: if (ctx.oldstyle) {
1206: fatal("-k and -C cannot be used together");
1207: }
1208: if (ctx.setttl) {
1209: fatal("-k and -L cannot be used together");
1210: }
1211: if (ctx.prepub > 0) {
1212: fatal("-k and -i cannot be used together");
1213: }
1214: if (ctx.size != -1) {
1215: fatal("-k and -b cannot be used together");
1216: }
1217: if (ctx.kskflag || ctx.revflag) {
1218: fatal("-k and -f cannot be used together");
1219: }
1220: if (ctx.options & DST_TYPE_KEY) {
1221: fatal("-k and -T KEY cannot be used together");
1222: }
1223: if (ctx.use_nsec3) {
1224: fatal("-k and -3 cannot be used together");
1225: }
1226:
1227: ctx.options |= DST_TYPE_STATE;
1228:
1229: if (strcmp(ctx.policy, "default") == 0) {
1230: ctx.use_nsec3 = false;
1231: ctx.alg = DST_ALG_ECDSA256;
1232: ctx.size = 0;
1233: ctx.kskflag = DNS_KEYFLAG_KSK;
1234: ctx.ttl = 3600;
1235: ctx.setttl = true;
1236: ctx.ksk = true;
1237: ctx.zsk = true;
1238: ctx.lifetime = 0;
1239:
1240: keygen(&ctx, mctx, argc, argv);
1241: } else {
1242: cfg_parser_t *parser = NULL;
1243: cfg_obj_t *config = NULL;
1244: dns_kasp_t *kasp = NULL;
1245: dns_kasp_key_t *kaspkey = NULL;
1246:
1247: RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &parser) ==
1248: ISC_R_SUCCESS);
1249: if (cfg_parse_file(parser, ctx.configfile,
1250: &cfg_type_namedconf,
1251: &config) != ISC_R_SUCCESS)
1252: {
1253: fatal("unable to load dnssec-policy '%s' from "
1254: "'%s'",
1255: ctx.policy, ctx.configfile);
1256: }
1257:
1258: kasp_from_conf(config, mctx, ctx.policy, &kasp);
1259: if (kasp == NULL) {
1260: fatal("failed to load dnssec-policy '%s'",
1261: ctx.policy);
1262: }
1263: if (ISC_LIST_EMPTY(dns_kasp_keys(kasp))) {
1264: fatal("dnssec-policy '%s' has no keys "
1265: "configured",
1266: ctx.policy);
1267: }
1268:
1269: ctx.ttl = dns_kasp_dnskeyttl(kasp);
1270: ctx.setttl = true;
1271:
1272: kaspkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
1273:
1274: while (kaspkey != NULL) {
1275: ctx.use_nsec3 = false;
1276: ctx.alg = dns_kasp_key_algorithm(kaspkey);
1277: ctx.size = dns_kasp_key_size(kaspkey);
1278: ctx.kskflag = dns_kasp_key_ksk(kaspkey)
1279: ? DNS_KEYFLAG_KSK
1280: : 0;
1281: ctx.ksk = dns_kasp_key_ksk(kaspkey);
1282: ctx.zsk = dns_kasp_key_zsk(kaspkey);
1283: ctx.lifetime = dns_kasp_key_lifetime(kaspkey);
1284:
1285: keygen(&ctx, mctx, argc, argv);
1286:
1287: kaspkey = ISC_LIST_NEXT(kaspkey, link);
1288: }
1289:
1290: dns_kasp_detach(&kasp);
1291: cfg_obj_destroy(parser, &config);
1292: cfg_parser_destroy(&parser);
1293: }
1294: } else {
1295: keygen(&ctx, mctx, argc, argv);
1296: }
1297:
1298: cleanup_logging(&lctx);
1.1 christos 1299: dst_lib_destroy();
1.6 christos 1300: if (verbose > 10) {
1.1 christos 1301: isc_mem_stats(mctx, stdout);
1.6 christos 1302: }
1.1 christos 1303: isc_mem_destroy(&mctx);
1304:
1.6 christos 1305: if (freeit != NULL) {
1.1 christos 1306: free(freeit);
1.6 christos 1307: }
1.1 christos 1308:
1309: return (0);
1310: }
CVSweb <webmaster@jp.NetBSD.org>