[BACK]Return to dnssec-keygen.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / bind / dist / bin / dnssec

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>