2 * Copyright (C) 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
17 /* $Id: dnssec-keyfromlabel.c,v 1.4 2008/09/24 02:46:21 marka Exp $ */
25 #include <isc/buffer.h>
26 #include <isc/commandline.h>
27 #include <isc/entropy.h>
29 #include <isc/region.h>
30 #include <isc/string.h>
33 #include <dns/fixedname.h>
34 #include <dns/keyvalues.h>
37 #include <dns/rdataclass.h>
38 #include <dns/result.h>
39 #include <dns/secalg.h>
43 #include "dnssectool.h"
45 #define MAX_RSA 4096 /* should be long enough... */
47 const char *program = "dnssec-keyfromlabel";
50 static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |"
51 " NSEC3DSA | NSEC3RSASHA1";
55 fprintf(stderr, "Usage:\n");
56 fprintf(stderr, " %s -a alg -l label [options] name\n\n",
58 fprintf(stderr, "Version: %s\n", VERSION);
59 fprintf(stderr, "Required options:\n");
60 fprintf(stderr, " -a algorithm: %s\n", algs);
61 fprintf(stderr, " -l label: label of the key\n");
62 fprintf(stderr, " name: owner of the key\n");
63 fprintf(stderr, "Other options:\n");
64 fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
65 fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
66 fprintf(stderr, " -c <class> (default: IN)\n");
67 fprintf(stderr, " -f keyflag: KSK\n");
68 fprintf(stderr, " -t <type>: "
69 "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
70 "(default: AUTHCONF)\n");
71 fprintf(stderr, " -p <protocol>: "
72 "default: 3 [dnssec]\n");
73 fprintf(stderr, " -v <verbose level>\n");
74 fprintf(stderr, " -k : generate a TYPE=KEY key\n");
75 fprintf(stderr, "Output:\n");
76 fprintf(stderr, " K<name>+<alg>+<id>.key, "
77 "K<name>+<alg>+<id>.private\n");
83 main(int argc, char **argv) {
84 char *algname = NULL, *nametype = NULL, *type = NULL;
85 char *classname = NULL;
87 dst_key_t *key = NULL, *oldkey;
88 dns_fixedname_t fname;
90 isc_uint16_t flags = 0, ksk = 0;
92 isc_boolean_t null_key = ISC_FALSE;
93 isc_mem_t *mctx = NULL;
95 int protocol = -1, signatory = 0;
100 isc_log_t *log = NULL;
101 isc_entropy_t *ectx = NULL;
102 dns_rdataclass_t rdclass;
103 int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
109 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
111 dns_result_register();
113 isc_commandline_errprint = ISC_FALSE;
115 while ((ch = isc_commandline_parse(argc, argv,
116 "a:c:f:kl:n:p:t:v:h")) != -1)
120 algname = isc_commandline_argument;
123 classname = isc_commandline_argument;
126 if (strcasecmp(isc_commandline_argument, "KSK") == 0)
127 ksk = DNS_KEYFLAG_KSK;
129 fatal("unknown flag '%s'",
130 isc_commandline_argument);
133 options |= DST_TYPE_KEY;
136 label = isc_commandline_argument;
139 nametype = isc_commandline_argument;
142 protocol = strtol(isc_commandline_argument, &endp, 10);
143 if (*endp != '\0' || protocol < 0 || protocol > 255)
144 fatal("-p must be followed by a number "
148 type = isc_commandline_argument;
151 verbose = strtol(isc_commandline_argument, &endp, 0);
153 fatal("-v must be followed by a number");
157 if (isc_commandline_option != '?')
158 fprintf(stderr, "%s: invalid argument -%c\n",
159 program, isc_commandline_option);
164 fprintf(stderr, "%s: unhandled option -%c\n",
165 program, isc_commandline_option);
171 setup_entropy(mctx, NULL, &ectx);
172 ret = dst_lib_init(mctx, ectx,
173 ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
174 if (ret != ISC_R_SUCCESS)
175 fatal("could not initialize dst");
177 setup_logging(verbose, mctx, &log);
180 fatal("the key label was not specified");
181 if (argc < isc_commandline_index + 1)
182 fatal("the key name was not specified");
183 if (argc > isc_commandline_index + 1)
184 fatal("extraneous arguments");
187 fatal("no algorithm was specified");
188 if (strcasecmp(algname, "RSA") == 0) {
189 fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n"
190 "If you still wish to use RSA (RSAMD5) please "
191 "specify \"-a RSAMD5\"\n");
195 r.length = strlen(algname);
196 ret = dns_secalg_fromtext(&alg, &r);
197 if (ret != ISC_R_SUCCESS)
198 fatal("unknown algorithm %s", algname);
199 if (alg == DST_ALG_DH)
200 options |= DST_TYPE_KEY;
203 if (type != NULL && (options & DST_TYPE_KEY) != 0) {
204 if (strcasecmp(type, "NOAUTH") == 0)
205 flags |= DNS_KEYTYPE_NOAUTH;
206 else if (strcasecmp(type, "NOCONF") == 0)
207 flags |= DNS_KEYTYPE_NOCONF;
208 else if (strcasecmp(type, "NOAUTHCONF") == 0) {
209 flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF);
211 else if (strcasecmp(type, "AUTHCONF") == 0)
214 fatal("invalid type %s", type);
217 if (nametype == NULL) {
218 if ((options & DST_TYPE_KEY) != 0) /* KEY */
219 fatal("no nametype specified");
220 flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
221 } else if (strcasecmp(nametype, "zone") == 0)
222 flags |= DNS_KEYOWNER_ZONE;
223 else if ((options & DST_TYPE_KEY) != 0) { /* KEY */
224 if (strcasecmp(nametype, "host") == 0 ||
225 strcasecmp(nametype, "entity") == 0)
226 flags |= DNS_KEYOWNER_ENTITY;
227 else if (strcasecmp(nametype, "user") == 0)
228 flags |= DNS_KEYOWNER_USER;
230 fatal("invalid KEY nametype %s", nametype);
231 } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
232 fatal("invalid DNSKEY nametype %s", nametype);
234 rdclass = strtoclass(classname);
236 if ((options & DST_TYPE_KEY) != 0) /* KEY */
238 else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
242 protocol = DNS_KEYPROTO_DNSSEC;
243 else if ((options & DST_TYPE_KEY) == 0 &&
244 protocol != DNS_KEYPROTO_DNSSEC)
245 fatal("invalid DNSKEY protocol: %d", protocol);
247 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
248 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
249 fatal("specified null key with signing authority");
252 if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
253 alg == DNS_KEYALG_DH)
254 fatal("a key with algorithm '%s' cannot be a zone key",
257 dns_fixedname_init(&fname);
258 name = dns_fixedname_name(&fname);
259 isc_buffer_init(&buf, argv[isc_commandline_index],
260 strlen(argv[isc_commandline_index]));
261 isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
262 ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL);
263 if (ret != ISC_R_SUCCESS)
264 fatal("invalid key name %s: %s", argv[isc_commandline_index],
265 isc_result_totext(ret));
267 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
270 isc_buffer_init(&buf, filename, sizeof(filename) - 1);
272 /* associate the key */
273 ret = dst_key_fromlabel(name, alg, flags, protocol,
274 rdclass, "", label, NULL, mctx, &key);
275 isc_entropy_stopcallbacksources(ectx);
277 if (ret != ISC_R_SUCCESS) {
278 char namestr[DNS_NAME_FORMATSIZE];
279 char algstr[ALG_FORMATSIZE];
280 dns_name_format(name, namestr, sizeof(namestr));
281 alg_format(alg, algstr, sizeof(algstr));
282 fatal("failed to generate key %s/%s: %s\n",
283 namestr, algstr, isc_result_totext(ret));
288 * Try to read a key with the same name, alg and id from disk.
289 * If there is one we must continue generating a new one
290 * unless we were asked to generate a null key, in which
291 * case we return failure.
293 ret = dst_key_fromfile(name, dst_key_id(key), alg,
294 DST_TYPE_PRIVATE, NULL, mctx, &oldkey);
295 /* do not overwrite an existing key */
296 if (ret == ISC_R_SUCCESS) {
297 isc_buffer_clear(&buf);
298 ret = dst_key_buildfilename(key, 0, NULL, &buf);
299 fprintf(stderr, "%s: %s already exists\n",
305 ret = dst_key_tofile(key, options, NULL);
306 if (ret != ISC_R_SUCCESS) {
307 char keystr[KEY_FORMATSIZE];
308 key_format(key, keystr, sizeof(keystr));
309 fatal("failed to write key %s: %s\n", keystr,
310 isc_result_totext(ret));
313 isc_buffer_clear(&buf);
314 ret = dst_key_buildfilename(key, 0, NULL, &buf);
315 printf("%s\n", filename);
318 cleanup_logging(&log);
319 cleanup_entropy(&ectx);
323 isc_mem_stats(mctx, stdout);
324 isc_mem_destroy(&mctx);