]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/bin/dnssec/dnssec-keyfromlabel.c
Update to version 9.6-ESV-R6, the latest from ISC, which contains numerous
[FreeBSD/stable/8.git] / contrib / bind9 / bin / dnssec / dnssec-keyfromlabel.c
1 /*
2  * Copyright (C) 2007, 2008, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
3  *
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.
7  *
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.
15  */
16
17 /* $Id$ */
18
19 /*! \file */
20
21 #include <config.h>
22
23 #include <stdlib.h>
24
25 #include <isc/buffer.h>
26 #include <isc/commandline.h>
27 #include <isc/entropy.h>
28 #include <isc/mem.h>
29 #include <isc/region.h>
30 #include <isc/string.h>
31 #include <isc/util.h>
32
33 #include <dns/fixedname.h>
34 #include <dns/keyvalues.h>
35 #include <dns/log.h>
36 #include <dns/name.h>
37 #include <dns/rdataclass.h>
38 #include <dns/result.h>
39 #include <dns/secalg.h>
40
41 #include <dst/dst.h>
42
43 #include "dnssectool.h"
44
45 #define MAX_RSA 4096 /* should be long enough... */
46
47 const char *program = "dnssec-keyfromlabel";
48 int verbose;
49
50 static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |"
51                           " NSEC3DSA | NSEC3RSASHA1 |"
52                           " RSASHA256 | RSASHA512";
53
54 ISC_PLATFORM_NORETURN_PRE static void
55 usage(void) ISC_PLATFORM_NORETURN_POST;
56
57 static void
58 usage(void) {
59         fprintf(stderr, "Usage:\n");
60         fprintf(stderr, "    %s -a alg -l label [options] name\n\n",
61                 program);
62         fprintf(stderr, "Version: %s\n", VERSION);
63         fprintf(stderr, "Required options:\n");
64         fprintf(stderr, "    -a algorithm: %s\n", algs);
65         fprintf(stderr, "    -l label: label of the key\n");
66         fprintf(stderr, "    name: owner of the key\n");
67         fprintf(stderr, "Other options:\n");
68         fprintf(stderr, "    -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
69         fprintf(stderr, "        (DNSKEY generation defaults to ZONE\n");
70         fprintf(stderr, "    -c <class> (default: IN)\n");
71         fprintf(stderr, "    -f keyflag: KSK\n");
72         fprintf(stderr, "    -t <type>: "
73                 "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
74                 "(default: AUTHCONF)\n");
75         fprintf(stderr, "    -p <protocol>: "
76                "default: 3 [dnssec]\n");
77         fprintf(stderr, "    -v <verbose level>\n");
78         fprintf(stderr, "    -k : generate a TYPE=KEY key\n");
79         fprintf(stderr, "Output:\n");
80         fprintf(stderr, "     K<name>+<alg>+<id>.key, "
81                 "K<name>+<alg>+<id>.private\n");
82
83         exit (-1);
84 }
85
86 int
87 main(int argc, char **argv) {
88         char            *algname = NULL, *nametype = NULL, *type = NULL;
89         char            *classname = NULL;
90         char            *endp;
91         dst_key_t       *key = NULL, *oldkey;
92         dns_fixedname_t fname;
93         dns_name_t      *name;
94         isc_uint16_t    flags = 0, ksk = 0;
95         dns_secalg_t    alg;
96         isc_mem_t       *mctx = NULL;
97         int             ch;
98         int             protocol = -1, signatory = 0;
99         isc_result_t    ret;
100         isc_textregion_t r;
101         char            filename[255];
102         isc_buffer_t    buf;
103         isc_log_t       *log = NULL;
104         isc_entropy_t   *ectx = NULL;
105         dns_rdataclass_t rdclass;
106         int             options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
107         char            *label = NULL;
108
109         if (argc == 1)
110                 usage();
111
112         RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
113
114         dns_result_register();
115
116         isc_commandline_errprint = ISC_FALSE;
117
118         while ((ch = isc_commandline_parse(argc, argv,
119                                          "a:c:f:kl:n:p:t:v:h")) != -1)
120         {
121             switch (ch) {
122                 case 'a':
123                         algname = isc_commandline_argument;
124                         break;
125                 case 'c':
126                         classname = isc_commandline_argument;
127                         break;
128                 case 'f':
129                         if (strcasecmp(isc_commandline_argument, "KSK") == 0)
130                                 ksk = DNS_KEYFLAG_KSK;
131                         else
132                                 fatal("unknown flag '%s'",
133                                       isc_commandline_argument);
134                         break;
135                 case 'k':
136                         options |= DST_TYPE_KEY;
137                         break;
138                 case 'l':
139                         label = isc_commandline_argument;
140                         break;
141                 case 'n':
142                         nametype = isc_commandline_argument;
143                         break;
144                 case 'p':
145                         protocol = strtol(isc_commandline_argument, &endp, 10);
146                         if (*endp != '\0' || protocol < 0 || protocol > 255)
147                                 fatal("-p must be followed by a number "
148                                       "[0..255]");
149                         break;
150                 case 't':
151                         type = isc_commandline_argument;
152                         break;
153                 case 'v':
154                         verbose = strtol(isc_commandline_argument, &endp, 0);
155                         if (*endp != '\0')
156                                 fatal("-v must be followed by a number");
157                         break;
158
159                 case '?':
160                         if (isc_commandline_option != '?')
161                                 fprintf(stderr, "%s: invalid argument -%c\n",
162                                         program, isc_commandline_option);
163                 case 'h':
164                         usage();
165
166                 default:
167                         fprintf(stderr, "%s: unhandled option -%c\n",
168                                 program, isc_commandline_option);
169                         exit(1);
170                 }
171         }
172
173         if (ectx == NULL)
174                 setup_entropy(mctx, NULL, &ectx);
175         ret = dst_lib_init(mctx, ectx,
176                            ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
177         if (ret != ISC_R_SUCCESS)
178                 fatal("could not initialize dst");
179
180         setup_logging(verbose, mctx, &log);
181
182         if (label == NULL)
183                 fatal("the key label was not specified");
184         if (argc < isc_commandline_index + 1)
185                 fatal("the key name was not specified");
186         if (argc > isc_commandline_index + 1)
187                 fatal("extraneous arguments");
188
189         if (algname == NULL)
190                 fatal("no algorithm was specified");
191         if (strcasecmp(algname, "RSA") == 0) {
192                 fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n"
193                                 "If you still wish to use RSA (RSAMD5) please "
194                                 "specify \"-a RSAMD5\"\n");
195                 return (1);
196         } else {
197                 r.base = algname;
198                 r.length = strlen(algname);
199                 ret = dns_secalg_fromtext(&alg, &r);
200                 if (ret != ISC_R_SUCCESS)
201                         fatal("unknown algorithm %s", algname);
202                 if (alg == DST_ALG_DH)
203                         options |= DST_TYPE_KEY;
204         }
205
206         if (type != NULL && (options & DST_TYPE_KEY) != 0) {
207                 if (strcasecmp(type, "NOAUTH") == 0)
208                         flags |= DNS_KEYTYPE_NOAUTH;
209                 else if (strcasecmp(type, "NOCONF") == 0)
210                         flags |= DNS_KEYTYPE_NOCONF;
211                 else if (strcasecmp(type, "NOAUTHCONF") == 0) {
212                         flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF);
213                 }
214                 else if (strcasecmp(type, "AUTHCONF") == 0)
215                         /* nothing */;
216                 else
217                         fatal("invalid type %s", type);
218         }
219
220         if (nametype == NULL) {
221                 if ((options & DST_TYPE_KEY) != 0) /* KEY */
222                         fatal("no nametype specified");
223                 flags |= DNS_KEYOWNER_ZONE;     /* DNSKEY */
224         } else if (strcasecmp(nametype, "zone") == 0)
225                 flags |= DNS_KEYOWNER_ZONE;
226         else if ((options & DST_TYPE_KEY) != 0) { /* KEY */
227                 if (strcasecmp(nametype, "host") == 0 ||
228                          strcasecmp(nametype, "entity") == 0)
229                         flags |= DNS_KEYOWNER_ENTITY;
230                 else if (strcasecmp(nametype, "user") == 0)
231                         flags |= DNS_KEYOWNER_USER;
232                 else
233                         fatal("invalid KEY nametype %s", nametype);
234         } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
235                 fatal("invalid DNSKEY nametype %s", nametype);
236
237         rdclass = strtoclass(classname);
238
239         if ((options & DST_TYPE_KEY) != 0)  /* KEY */
240                 flags |= signatory;
241         else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
242                 flags |= ksk;
243
244         if (protocol == -1)
245                 protocol = DNS_KEYPROTO_DNSSEC;
246         else if ((options & DST_TYPE_KEY) == 0 &&
247                  protocol != DNS_KEYPROTO_DNSSEC)
248                 fatal("invalid DNSKEY protocol: %d", protocol);
249
250         if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
251                 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
252                         fatal("specified null key with signing authority");
253         }
254
255         if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
256             alg == DNS_KEYALG_DH)
257                 fatal("a key with algorithm '%s' cannot be a zone key",
258                       algname);
259
260         dns_fixedname_init(&fname);
261         name = dns_fixedname_name(&fname);
262         isc_buffer_init(&buf, argv[isc_commandline_index],
263                         strlen(argv[isc_commandline_index]));
264         isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
265         ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL);
266         if (ret != ISC_R_SUCCESS)
267                 fatal("invalid key name %s: %s", argv[isc_commandline_index],
268                       isc_result_totext(ret));
269
270         isc_buffer_init(&buf, filename, sizeof(filename) - 1);
271
272         /* associate the key */
273         ret = dst_key_fromlabel(name, alg, flags, protocol,
274                                 rdclass, "", label, NULL, mctx, &key);
275         isc_entropy_stopcallbacksources(ectx);
276
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));
284                 exit(-1);
285         }
286
287         /*
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.
292          */
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                 if (ret != ISC_R_SUCCESS)
300                         fatal("dst_key_buildfilename returned: %s\n",
301                               isc_result_totext(ret));
302                 fprintf(stderr, "%s: %s already exists\n",
303                         program, filename);
304                 dst_key_free(&key);
305                 exit (1);
306         }
307
308         ret = dst_key_tofile(key, options, NULL);
309         if (ret != ISC_R_SUCCESS) {
310                 char keystr[KEY_FORMATSIZE];
311                 key_format(key, keystr, sizeof(keystr));
312                 fatal("failed to write key %s: %s\n", keystr,
313                       isc_result_totext(ret));
314         }
315
316         isc_buffer_clear(&buf);
317         ret = dst_key_buildfilename(key, 0, NULL, &buf);
318         if (ret != ISC_R_SUCCESS)
319                 fatal("dst_key_buildfilename returned: %s\n",
320                       isc_result_totext(ret));
321         printf("%s\n", filename);
322         dst_key_free(&key);
323
324         cleanup_logging(&log);
325         cleanup_entropy(&ectx);
326         dst_lib_destroy();
327         dns_name_destroy();
328         if (verbose > 10)
329                 isc_mem_stats(mctx, stdout);
330         isc_mem_destroy(&mctx);
331
332         return (0);
333 }