Merge branch 'vendor/BIND' into bind_vendor2
[dragonfly.git] / contrib / bind-9.5.2 / bin / dnssec / dnssectool.c
1 /*
2  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: dnssectool.c,v 1.45 2007/06/19 23:46:59 tbox Exp $ */
19
20 /*! \file */
21
22 /*%
23  * DNSSEC Support Routines.
24  */
25
26 #include <config.h>
27
28 #include <stdlib.h>
29
30 #include <isc/buffer.h>
31 #include <isc/entropy.h>
32 #include <isc/list.h>
33 #include <isc/mem.h>
34 #include <isc/string.h>
35 #include <isc/time.h>
36 #include <isc/util.h>
37 #include <isc/print.h>
38
39 #include <dns/log.h>
40 #include <dns/name.h>
41 #include <dns/rdatastruct.h>
42 #include <dns/rdataclass.h>
43 #include <dns/rdatatype.h>
44 #include <dns/result.h>
45 #include <dns/secalg.h>
46 #include <dns/time.h>
47
48 #include "dnssectool.h"
49
50 extern int verbose;
51 extern const char *program;
52
53 typedef struct entropysource entropysource_t;
54
55 struct entropysource {
56         isc_entropysource_t *source;
57         isc_mem_t *mctx;
58         ISC_LINK(entropysource_t) link;
59 };
60
61 static ISC_LIST(entropysource_t) sources;
62 static fatalcallback_t *fatalcallback = NULL;
63
64 void
65 fatal(const char *format, ...) {
66         va_list args;
67
68         fprintf(stderr, "%s: ", program);
69         va_start(args, format);
70         vfprintf(stderr, format, args);
71         va_end(args);
72         fprintf(stderr, "\n");
73         if (fatalcallback != NULL)
74                 (*fatalcallback)();
75         exit(1);
76 }
77
78 void
79 setfatalcallback(fatalcallback_t *callback) {
80         fatalcallback = callback;
81 }
82
83 void
84 check_result(isc_result_t result, const char *message) {
85         if (result != ISC_R_SUCCESS)
86                 fatal("%s: %s", message, isc_result_totext(result));
87 }
88
89 void
90 vbprintf(int level, const char *fmt, ...) {
91         va_list ap;
92         if (level > verbose)
93                 return;
94         va_start(ap, fmt);
95         fprintf(stderr, "%s: ", program);
96         vfprintf(stderr, fmt, ap);
97         va_end(ap);
98 }
99
100 void
101 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
102         isc_buffer_t b;
103         isc_region_t r;
104         isc_result_t result;
105
106         isc_buffer_init(&b, cp, size - 1);
107         result = dns_rdatatype_totext(type, &b);
108         check_result(result, "dns_rdatatype_totext()");
109         isc_buffer_usedregion(&b, &r);
110         r.base[r.length] = 0;
111 }
112
113 void
114 alg_format(const dns_secalg_t alg, char *cp, unsigned int size) {
115         isc_buffer_t b;
116         isc_region_t r;
117         isc_result_t result;
118
119         isc_buffer_init(&b, cp, size - 1);
120         result = dns_secalg_totext(alg, &b);
121         check_result(result, "dns_secalg_totext()");
122         isc_buffer_usedregion(&b, &r);
123         r.base[r.length] = 0;
124 }
125
126 void
127 sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
128         char namestr[DNS_NAME_FORMATSIZE];
129         char algstr[DNS_NAME_FORMATSIZE];
130
131         dns_name_format(&sig->signer, namestr, sizeof(namestr));
132         alg_format(sig->algorithm, algstr, sizeof(algstr));
133         snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
134 }
135
136 void
137 key_format(const dst_key_t *key, char *cp, unsigned int size) {
138         char namestr[DNS_NAME_FORMATSIZE];
139         char algstr[DNS_NAME_FORMATSIZE];
140
141         dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
142         alg_format((dns_secalg_t) dst_key_alg(key), algstr, sizeof(algstr));
143         snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
144 }
145
146 void
147 setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) {
148         isc_result_t result;
149         isc_logdestination_t destination;
150         isc_logconfig_t *logconfig = NULL;
151         isc_log_t *log = NULL;
152         int level;
153
154         if (verbose < 0)
155                 verbose = 0;
156         switch (verbose) {
157         case 0:
158                 /*
159                  * We want to see warnings about things like out-of-zone
160                  * data in the master file even when not verbose.
161                  */
162                 level = ISC_LOG_WARNING;
163                 break;
164         case 1:
165                 level = ISC_LOG_INFO;
166                 break;
167         default:
168                 level = ISC_LOG_DEBUG(verbose - 2 + 1);
169                 break;
170         }
171
172         RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
173         isc_log_setcontext(log);
174         dns_log_init(log);
175         dns_log_setcontext(log);
176
177         RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
178
179         /*
180          * Set up a channel similar to default_stderr except:
181          *  - the logging level is passed in
182          *  - the program name and logging level are printed
183          *  - no time stamp is printed
184          */
185         destination.file.stream = stderr;
186         destination.file.name = NULL;
187         destination.file.versions = ISC_LOG_ROLLNEVER;
188         destination.file.maximum_size = 0;
189         result = isc_log_createchannel(logconfig, "stderr",
190                                        ISC_LOG_TOFILEDESC,
191                                        level,
192                                        &destination,
193                                        ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
194         check_result(result, "isc_log_createchannel()");
195
196         RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
197                                          NULL, NULL) == ISC_R_SUCCESS);
198
199         *logp = log;
200 }
201
202 void
203 cleanup_logging(isc_log_t **logp) {
204         isc_log_t *log;
205
206         REQUIRE(logp != NULL);
207
208         log = *logp;
209         if (log == NULL)
210                 return;
211         isc_log_destroy(&log);
212         isc_log_setcontext(NULL);
213         dns_log_setcontext(NULL);
214         logp = NULL;
215 }
216
217 void
218 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
219         isc_result_t result;
220         isc_entropysource_t *source = NULL;
221         entropysource_t *elt;
222         int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
223
224         REQUIRE(ectx != NULL);
225         
226         if (*ectx == NULL) {
227                 result = isc_entropy_create(mctx, ectx);
228                 if (result != ISC_R_SUCCESS)
229                         fatal("could not create entropy object");
230                 ISC_LIST_INIT(sources);
231         }
232
233         if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
234                 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
235                 randomfile = NULL;
236         }
237
238         result = isc_entropy_usebestsource(*ectx, &source, randomfile,
239                                            usekeyboard);
240
241         if (result != ISC_R_SUCCESS)
242                 fatal("could not initialize entropy source: %s",
243                       isc_result_totext(result));
244
245         if (source != NULL) {
246                 elt = isc_mem_get(mctx, sizeof(*elt));
247                 if (elt == NULL)
248                         fatal("out of memory");
249                 elt->source = source;
250                 elt->mctx = mctx;
251                 ISC_LINK_INIT(elt, link);
252                 ISC_LIST_APPEND(sources, elt, link);
253         }
254 }
255
256 void
257 cleanup_entropy(isc_entropy_t **ectx) {
258         entropysource_t *source;
259         while (!ISC_LIST_EMPTY(sources)) {
260                 source = ISC_LIST_HEAD(sources);
261                 ISC_LIST_UNLINK(sources, source, link);
262                 isc_entropy_destroysource(&source->source);
263                 isc_mem_put(source->mctx, source, sizeof(*source));
264         }
265         isc_entropy_detach(ectx);
266 }
267
268 isc_stdtime_t
269 strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
270         isc_int64_t val, offset;
271         isc_result_t result;
272         char *endp;
273
274         if (str[0] == '+') {
275                 offset = strtol(str + 1, &endp, 0);
276                 if (*endp != '\0')
277                         fatal("time value %s is invalid", str);
278                 val = base + offset;
279         } else if (strncmp(str, "now+", 4) == 0) {
280                 offset = strtol(str + 4, &endp, 0);
281                 if (*endp != '\0')
282                         fatal("time value %s is invalid", str);
283                 val = now + offset;
284         } else if (strlen(str) == 8U) {
285                 char timestr[15];
286                 sprintf(timestr, "%s000000", str);
287                 result = dns_time64_fromtext(timestr, &val);
288                 if (result != ISC_R_SUCCESS)
289                         fatal("time value %s is invalid", str);
290         } else {
291                 result = dns_time64_fromtext(str, &val);
292                 if (result != ISC_R_SUCCESS)
293                         fatal("time value %s is invalid", str);
294         }
295
296         return ((isc_stdtime_t) val);
297 }
298
299 dns_rdataclass_t
300 strtoclass(const char *str) {
301         isc_textregion_t r;
302         dns_rdataclass_t rdclass;
303         isc_result_t ret;
304
305         if (str == NULL)
306                 return dns_rdataclass_in;
307         DE_CONST(str, r.base);
308         r.length = strlen(str);
309         ret = dns_rdataclass_fromtext(&rdclass, &r);
310         if (ret != ISC_R_SUCCESS)
311                 fatal("unknown class %s", str);
312         return (rdclass);
313 }