int main(int argc, char **argv) { char *algname = NULL, *classname = NULL; char *filename = NULL, *dir = NULL, *namestr; char *lookaside = NULL; char *endp; int ch; unsigned int dtype = DNS_DSDIGEST_SHA1; isc_boolean_t both = ISC_TRUE; isc_boolean_t usekeyset = ISC_FALSE; isc_boolean_t showall = ISC_FALSE; isc_result_t result; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata; dns_rdata_init(&rdata); if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "12Aa:c:d:Ff:K:l:sv:h")) != -1) { switch (ch) { case '1': dtype = DNS_DSDIGEST_SHA1; both = ISC_FALSE; break; case '2': dtype = DNS_DSDIGEST_SHA256; both = ISC_FALSE; break; case 'A': showall = ISC_TRUE; break; case 'a': algname = isc_commandline_argument; both = ISC_FALSE; break; case 'c': classname = isc_commandline_argument; break; case 'd': fprintf(stderr, "%s: the -d option is deprecated; " "use -K\n", program); /* fall through */ case 'K': dir = isc_commandline_argument; if (strlen(dir) == 0U) fatal("directory must be non-empty string"); break; case 'f': filename = isc_commandline_argument; break; case 'l': lookaside = isc_commandline_argument; if (strlen(lookaside) == 0U) fatal("lookaside must be a non-empty string"); break; case 's': usekeyset = ISC_TRUE; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (algname != NULL) { if (strcasecmp(algname, "SHA1") == 0 || strcasecmp(algname, "SHA-1") == 0) dtype = DNS_DSDIGEST_SHA1; else if (strcasecmp(algname, "SHA256") == 0 || strcasecmp(algname, "SHA-256") == 0) dtype = DNS_DSDIGEST_SHA256; #ifdef HAVE_OPENSSL_GOST else if (strcasecmp(algname, "GOST") == 0) dtype = DNS_DSDIGEST_GOST; #endif else if (strcasecmp(algname, "SHA384") == 0 || strcasecmp(algname, "SHA-384") == 0) dtype = DNS_DSDIGEST_SHA384; else fatal("unknown algorithm %s", algname); } rdclass = strtoclass(classname); if (usekeyset && filename != NULL) fatal("cannot use both -s and -f"); /* When not using -f, -A is implicit */ if (filename == NULL) showall = ISC_TRUE; if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not initialize hash"); result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(verbose, mctx, &log); dns_rdataset_init(&rdataset); if (usekeyset || filename != NULL) { if (argc < isc_commandline_index + 1 && filename != NULL) { /* using zone name as the zone file name */ namestr = filename; } else namestr = argv[isc_commandline_index]; result = initname(namestr); if (result != ISC_R_SUCCESS) fatal("could not initialize name %s", namestr); if (usekeyset) result = loadkeyset(dir, &rdataset); else result = loadsetfromfile(filename, &rdataset); if (result != ISC_R_SUCCESS) fatal("could not load DNSKEY set: %s\n", isc_result_totext(result)); for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); if (verbose > 2) logkey(&rdata); if (both) { emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else emit(dtype, showall, lookaside, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; loadkey(argv[isc_commandline_index], key_buf, DST_KEY_MAXSIZE, &rdata); if (both) { emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else emit(dtype, showall, lookaside, &rdata); } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); fflush(stdout); if (ferror(stdout)) { fprintf(stderr, "write error\n"); return (1); } else return (0); }
int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; dst_key_t *key = NULL, *oldkey; dns_fixedname_t fname; dns_name_t *name; isc_uint16_t flags = 0, ksk = 0; dns_secalg_t alg; isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE; isc_mem_t *mctx = NULL; int ch, rsa_exp = 0, generator = 0, param = 0; int protocol = -1, size = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; int dbits = 0; if (argc == 1) usage(); RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "a:b:c:d:ef:g:kn:t:p:s:r:v:h")) != -1) { switch (ch) { case 'a': algname = isc_commandline_argument; break; case 'b': size = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || size < 0) fatal("-b requires a non-negative number"); break; case 'c': classname = isc_commandline_argument; break; case 'd': dbits = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || dbits < 0) fatal("-d requires a non-negative number"); break; case 'e': rsa_exp = 1; break; case 'f': if (strcasecmp(isc_commandline_argument, "KSK") == 0) ksk = DNS_KEYFLAG_KSK; else fatal("unknown flag '%s'", isc_commandline_argument); break; case 'g': generator = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || generator <= 0) fatal("-g requires a positive number"); break; case 'k': options |= DST_TYPE_KEY; break; case 'n': nametype = isc_commandline_argument; break; case 't': type = isc_commandline_argument; break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || protocol < 0 || protocol > 255) fatal("-p must be followed by a number " "[0..255]"); break; case 's': signatory = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || signatory < 0 || signatory > 15) fatal("-s must be followed by a number " "[0..15]"); break; case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); ret = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) fatal("could not initialize dst"); setup_logging(verbose, mctx, &log); if (argc < isc_commandline_index + 1) fatal("the key name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (algname == NULL) fatal("no algorithm was specified"); if (strcasecmp(algname, "RSA") == 0) { fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" "If you still wish to use RSA (RSAMD5) please " "specify \"-a RSAMD5\"\n"); return (1); } else if (strcasecmp(algname, "HMAC-MD5") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACMD5; } else if (strcasecmp(algname, "HMAC-SHA1") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA1; } else if (strcasecmp(algname, "HMAC-SHA224") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA224; } else if (strcasecmp(algname, "HMAC-SHA256") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA256; } else if (strcasecmp(algname, "HMAC-SHA384") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA384; } else if (strcasecmp(algname, "HMAC-SHA512") == 0) { options |= DST_TYPE_KEY; alg = DST_ALG_HMACSHA512; } else { r.base = algname; r.length = strlen(algname); ret = dns_secalg_fromtext(&alg, &r); if (ret != ISC_R_SUCCESS) fatal("unknown algorithm %s", algname); if (alg == DST_ALG_DH) options |= DST_TYPE_KEY; } if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; else if (strcasecmp(type, "NOCONF") == 0) flags |= DNS_KEYTYPE_NOCONF; else if (strcasecmp(type, "NOAUTHCONF") == 0) { flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); if (size < 0) size = 0; } else if (strcasecmp(type, "AUTHCONF") == 0) /* nothing */; else fatal("invalid type %s", type); } if (size < 0) fatal("key size not specified (-b option)"); switch (alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: if (size != 0 && (size < 512 || size > MAX_RSA)) fatal("RSA key size %d out of range", size); break; case DNS_KEYALG_DH: if (size != 0 && (size < 128 || size > 4096)) fatal("DH key size %d out of range", size); break; case DNS_KEYALG_DSA: if (size != 0 && !dsa_size_ok(size)) fatal("invalid DSS key size: %d", size); break; case DST_ALG_HMACMD5: if (size < 1 || size > 512) fatal("HMAC-MD5 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 128)) fatal("HMAC-MD5 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-MD5 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA1: if (size < 1 || size > 160) fatal("HMAC-SHA1 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 160)) fatal("HMAC-SHA1 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA1 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA224: if (size < 1 || size > 224) fatal("HMAC-SHA224 key size %d out of range", size); if (dbits != 0 && (dbits < 112 || dbits > 224)) fatal("HMAC-SHA224 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA224 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA256: if (size < 1 || size > 256) fatal("HMAC-SHA256 key size %d out of range", size); if (dbits != 0 && (dbits < 128 || dbits > 256)) fatal("HMAC-SHA256 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA256 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA384: if (size < 1 || size > 384) fatal("HMAC-384 key size %d out of range", size); if (dbits != 0 && (dbits < 192 || dbits > 384)) fatal("HMAC-SHA384 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA384 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA512: if (size < 1 || size > 512) fatal("HMAC-SHA512 key size %d out of range", size); if (dbits != 0 && (dbits < 256 || dbits > 512)) fatal("HMAC-SHA512 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA512 digest bits %d not divisible by 8", dbits); break; } if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1) && rsa_exp != 0) fatal("specified RSA exponent for a non-RSA key"); if (alg != DNS_KEYALG_DH && generator != 0) fatal("specified DH generator for a non-DH key"); if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ fatal("no nametype specified"); flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ } else if (strcasecmp(nametype, "zone") == 0) flags |= DNS_KEYOWNER_ZONE; else if ((options & DST_TYPE_KEY) != 0) { /* KEY / HMAC */ if (strcasecmp(nametype, "host") == 0 || strcasecmp(nametype, "entity") == 0) flags |= DNS_KEYOWNER_ENTITY; else if (strcasecmp(nametype, "user") == 0) flags |= DNS_KEYOWNER_USER; else fatal("invalid KEY nametype %s", nametype); } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ fatal("invalid DNSKEY nametype %s", nametype); rdclass = strtoclass(classname); if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ flags |= signatory; else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ flags |= ksk; if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; else if ((options & DST_TYPE_KEY) == 0 && protocol != DNS_KEYPROTO_DNSSEC) fatal("invalid DNSKEY protocol: %d", protocol); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { if (size > 0) fatal("specified null key with non-zero size"); if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) fatal("specified null key with signing authority"); } if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)) fatal("a key with algorithm '%s' cannot be a zone key", algname); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); switch(alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: param = rsa_exp; break; case DNS_KEYALG_DH: param = generator; break; case DNS_KEYALG_DSA: case DST_ALG_HMACMD5: case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: case DST_ALG_HMACSHA256: case DST_ALG_HMACSHA384: case DST_ALG_HMACSHA512: param = 0; break; } if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) null_key = ISC_TRUE; isc_buffer_init(&buf, filename, sizeof(filename) - 1); do { conflict = ISC_FALSE; oldkey = NULL; /* generate the key */ ret = dst_key_generate(name, alg, size, param, flags, protocol, rdclass, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[ALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); alg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); exit(-1); } dst_key_setbits(key, dbits); /* * Try to read a key with the same name, alg and id from disk. * If there is one we must continue generating a new one * unless we were asked to generate a null key, in which * case we return failure. */ ret = dst_key_fromfile(name, dst_key_id(key), alg, DST_TYPE_PRIVATE, NULL, mctx, &oldkey); /* do not overwrite an existing key */ if (ret == ISC_R_SUCCESS) { dst_key_free(&oldkey); conflict = ISC_TRUE; if (null_key) break; } if (conflict == ISC_TRUE) { if (verbose > 0) { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); fprintf(stderr, "%s: %s already exists, " "generating a new key\n", program, filename); } dst_key_free(&key); } } while (conflict == ISC_TRUE); if (conflict) fatal("cannot generate a null key when a key with id 0 " "already exists"); ret = dst_key_tofile(key, options, NULL); if (ret != ISC_R_SUCCESS) { char keystr[KEY_FORMATSIZE]; key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); printf("%s\n", filename); dst_key_free(&key); cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); return (0); }
int main(int argc, char *argv[]) { char *origin = NULL, *file = NULL; char *inputformatstr = NULL; isc_result_t result; isc_log_t *log = NULL; #ifdef USE_PKCS11 const char *engine = "pkcs11"; #else const char *engine = NULL; #endif char *classname = NULL; dns_rdataclass_t rdclass; char *endp; int ch; #define CMDLINE_FLAGS \ "hm:o:I:c:E:v:Vxz" /* * Process memory debugging argument first. */ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'm': if (strcasecmp(isc_commandline_argument, "record") == 0) isc_mem_debugging |= ISC_MEM_DEBUGRECORD; if (strcasecmp(isc_commandline_argument, "trace") == 0) isc_mem_debugging |= ISC_MEM_DEBUGTRACE; if (strcasecmp(isc_commandline_argument, "usage") == 0) isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; if (strcasecmp(isc_commandline_argument, "size") == 0) isc_mem_debugging |= ISC_MEM_DEBUGSIZE; if (strcasecmp(isc_commandline_argument, "mctx") == 0) isc_mem_debugging |= ISC_MEM_DEBUGCTX; break; default: break; } } isc_commandline_reset = ISC_TRUE; check_result(isc_app_start(), "isc_app_start"); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'c': classname = isc_commandline_argument; break; case 'E': engine = isc_commandline_argument; break; case 'I': inputformatstr = isc_commandline_argument; break; case 'm': break; case 'o': origin = isc_commandline_argument; break; case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("verbose level must be numeric"); break; case 'x': keyset_kskonly = ISC_TRUE; break; case 'z': ignore_kskflag = ISC_TRUE; break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not create hash context"); result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_stdtime_get(&now); rdclass = strtoclass(classname); setup_logging(verbose, mctx, &log); argc -= isc_commandline_index; argv += isc_commandline_index; if (argc < 1) usage(); file = argv[0]; argc -= 1; argv += 1; POST(argc); POST(argv); if (origin == NULL) origin = file; if (inputformatstr != NULL) { if (strcasecmp(inputformatstr, "text") == 0) inputformat = dns_masterformat_text; else if (strcasecmp(inputformatstr, "raw") == 0) inputformat = dns_masterformat_raw; else fatal("unknown file format: %s\n", inputformatstr); } gdb = NULL; fprintf(stderr, "Loading zone '%s' from file '%s'\n", origin, file); loadzone(file, origin, rdclass, &gdb); gorigin = dns_db_origin(gdb); gclass = dns_db_class(gdb); gversion = NULL; result = dns_db_newversion(gdb, &gversion); check_result(result, "dns_db_newversion()"); verifyzone(gdb, gversion, gorigin, mctx, ignore_kskflag, keyset_kskonly); dns_db_closeversion(gdb, &gversion, ISC_FALSE); dns_db_detach(&gdb); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); (void) isc_app_finish(); return (0); }
int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; dst_key_t *key = NULL, *oldkey; dns_fixedname_t fname; dns_name_t *name; isc_uint16_t flags = 0, ksk = 0; dns_secalg_t alg; isc_boolean_t null_key = ISC_FALSE; isc_mem_t *mctx = NULL; int ch; int protocol = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; char *label = NULL; if (argc == 1) usage(); RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "a:c:f:kl:n:p:t:v:h")) != -1) { switch (ch) { case 'a': algname = isc_commandline_argument; break; case 'c': classname = isc_commandline_argument; break; case 'f': if (strcasecmp(isc_commandline_argument, "KSK") == 0) ksk = DNS_KEYFLAG_KSK; else fatal("unknown flag '%s'", isc_commandline_argument); break; case 'k': options |= DST_TYPE_KEY; break; case 'l': label = isc_commandline_argument; break; case 'n': nametype = isc_commandline_argument; break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || protocol < 0 || protocol > 255) fatal("-p must be followed by a number " "[0..255]"); break; case 't': type = isc_commandline_argument; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); ret = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) fatal("could not initialize dst"); setup_logging(verbose, mctx, &log); if (label == NULL) fatal("the key label was not specified"); if (argc < isc_commandline_index + 1) fatal("the key name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (algname == NULL) fatal("no algorithm was specified"); if (strcasecmp(algname, "RSA") == 0) { fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" "If you still wish to use RSA (RSAMD5) please " "specify \"-a RSAMD5\"\n"); return (1); } else { r.base = algname; r.length = strlen(algname); ret = dns_secalg_fromtext(&alg, &r); if (ret != ISC_R_SUCCESS) fatal("unknown algorithm %s", algname); if (alg == DST_ALG_DH) options |= DST_TYPE_KEY; } if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; else if (strcasecmp(type, "NOCONF") == 0) flags |= DNS_KEYTYPE_NOCONF; else if (strcasecmp(type, "NOAUTHCONF") == 0) { flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); } else if (strcasecmp(type, "AUTHCONF") == 0) /* nothing */; else fatal("invalid type %s", type); } if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY */ fatal("no nametype specified"); flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ } else if (strcasecmp(nametype, "zone") == 0) flags |= DNS_KEYOWNER_ZONE; else if ((options & DST_TYPE_KEY) != 0) { /* KEY */ if (strcasecmp(nametype, "host") == 0 || strcasecmp(nametype, "entity") == 0) flags |= DNS_KEYOWNER_ENTITY; else if (strcasecmp(nametype, "user") == 0) flags |= DNS_KEYOWNER_USER; else fatal("invalid KEY nametype %s", nametype); } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ fatal("invalid DNSKEY nametype %s", nametype); rdclass = strtoclass(classname); if ((options & DST_TYPE_KEY) != 0) /* KEY */ flags |= signatory; else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ flags |= ksk; if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; else if ((options & DST_TYPE_KEY) == 0 && protocol != DNS_KEYPROTO_DNSSEC) fatal("invalid DNSKEY protocol: %d", protocol); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) fatal("specified null key with signing authority"); } if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && alg == DNS_KEYALG_DH) fatal("a key with algorithm '%s' cannot be a zone key", algname); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) null_key = ISC_TRUE; isc_buffer_init(&buf, filename, sizeof(filename) - 1); /* associate the key */ ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass, "", label, NULL, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[ALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); alg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); exit(-1); } /* * Try to read a key with the same name, alg and id from disk. * If there is one we must continue generating a new one * unless we were asked to generate a null key, in which * case we return failure. */ ret = dst_key_fromfile(name, dst_key_id(key), alg, DST_TYPE_PRIVATE, NULL, mctx, &oldkey); /* do not overwrite an existing key */ if (ret == ISC_R_SUCCESS) { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); fprintf(stderr, "%s: %s already exists\n", program, filename); dst_key_free(&key); exit (1); } ret = dst_key_tofile(key, options, NULL); if (ret != ISC_R_SUCCESS) { char keystr[KEY_FORMATSIZE]; key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); printf("%s\n", filename); dst_key_free(&key); cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); return (0); }