]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - contrib/bind9/bin/dnssec/dnssec-keyfromlabel.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / contrib / bind9 / bin / dnssec / dnssec-keyfromlabel.c
1 /*
2  * Copyright (C) 2007, 2008  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: dnssec-keyfromlabel.c,v 1.4 2008/09/24 02:46:21 marka Exp $ */
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
53 static void
54 usage(void) {
55         fprintf(stderr, "Usage:\n");
56         fprintf(stderr, "    %s -a alg -l label [options] name\n\n",
57                 program);
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");
78
79         exit (-1);
80 }
81
82 int
83 main(int argc, char **argv) {
84         char            *algname = NULL, *nametype = NULL, *type = NULL;
85         char            *classname = NULL;
86         char            *endp;
87         dst_key_t       *key = NULL, *oldkey;
88         dns_fixedname_t fname;
89         dns_name_t      *name;
90         isc_uint16_t    flags = 0, ksk = 0;
91         dns_secalg_t    alg;
92         isc_boolean_t   null_key = ISC_FALSE;
93         isc_mem_t       *mctx = NULL;
94         int             ch;
95         int             protocol = -1, signatory = 0;
96         isc_result_t    ret;
97         isc_textregion_t r;
98         char            filename[255];
99         isc_buffer_t    buf;
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;
104         char            *label = NULL;
105
106         if (argc == 1)
107                 usage();
108
109         RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
110
111         dns_result_register();
112
113         isc_commandline_errprint = ISC_FALSE;
114
115         while ((ch = isc_commandline_parse(argc, argv,
116                                          "a:c:f:kl:n:p:t:v:h")) != -1)
117         {
118             switch (ch) {
119                 case 'a':
120                         algname = isc_commandline_argument;
121                         break;
122                 case 'c':
123                         classname = isc_commandline_argument;
124                         break;
125                 case 'f':
126                         if (strcasecmp(isc_commandline_argument, "KSK") == 0)
127                                 ksk = DNS_KEYFLAG_KSK;
128                         else
129                                 fatal("unknown flag '%s'",
130                                       isc_commandline_argument);
131                         break;
132                 case 'k':
133                         options |= DST_TYPE_KEY;
134                         break;
135                 case 'l':
136                         label = isc_commandline_argument;
137                         break;
138                 case 'n':
139                         nametype = isc_commandline_argument;
140                         break;
141                 case 'p':
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 "
145                                       "[0..255]");
146                         break;
147                 case 't':
148                         type = isc_commandline_argument;
149                         break;
150                 case 'v':
151                         verbose = strtol(isc_commandline_argument, &endp, 0);
152                         if (*endp != '\0')
153                                 fatal("-v must be followed by a number");
154                         break;
155
156                 case '?':
157                         if (isc_commandline_option != '?')
158                                 fprintf(stderr, "%s: invalid argument -%c\n",
159                                         program, isc_commandline_option);
160                 case 'h':
161                         usage();
162
163                 default:
164                         fprintf(stderr, "%s: unhandled option -%c\n",
165                                 program, isc_commandline_option);
166                         exit(1);
167                 }
168         }
169
170         if (ectx == NULL)
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");
176
177         setup_logging(verbose, mctx, &log);
178
179         if (label == NULL)
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");
185
186         if (algname == NULL)
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");
192                 return (1);
193         } else {
194                 r.base = algname;
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;
201         }
202
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);
210                 }
211                 else if (strcasecmp(type, "AUTHCONF") == 0)
212                         /* nothing */;
213                 else
214                         fatal("invalid type %s", type);
215         }
216
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;
229                 else
230                         fatal("invalid KEY nametype %s", nametype);
231         } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
232                 fatal("invalid DNSKEY nametype %s", nametype);
233
234         rdclass = strtoclass(classname);
235
236         if ((options & DST_TYPE_KEY) != 0)  /* KEY */
237                 flags |= signatory;
238         else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
239                 flags |= ksk;
240
241         if (protocol == -1)
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);
246
247         if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
248                 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
249                         fatal("specified null key with signing authority");
250         }
251
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",
255                       algname);
256
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));
266
267         if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
268                 null_key = ISC_TRUE;
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                 fprintf(stderr, "%s: %s already exists\n",
300                         program, filename);
301                 dst_key_free(&key);
302                 exit (1);
303         }
304
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));
311         }
312
313         isc_buffer_clear(&buf);
314         ret = dst_key_buildfilename(key, 0, NULL, &buf);
315         printf("%s\n", filename);
316         dst_key_free(&key);
317
318         cleanup_logging(&log);
319         cleanup_entropy(&ectx);
320         dst_lib_destroy();
321         dns_name_destroy();
322         if (verbose > 10)
323                 isc_mem_stats(mctx, stdout);
324         isc_mem_destroy(&mctx);
325
326         return (0);
327 }