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