2 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
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.
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.
18 /* $Id: dnssectool.c,v 1.45.334.5 2009/06/22 05:05:00 marka Exp $ */
23 * DNSSEC Support Routines.
30 #include <isc/buffer.h>
31 #include <isc/entropy.h>
34 #include <isc/string.h>
37 #include <isc/print.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>
48 #include "dnssectool.h"
51 extern const char *program;
53 typedef struct entropysource entropysource_t;
55 struct entropysource {
56 isc_entropysource_t *source;
58 ISC_LINK(entropysource_t) link;
61 static ISC_LIST(entropysource_t) sources;
62 static fatalcallback_t *fatalcallback = NULL;
65 fatal(const char *format, ...) {
68 fprintf(stderr, "%s: fatal: ", program);
69 va_start(args, format);
70 vfprintf(stderr, format, args);
72 fprintf(stderr, "\n");
73 if (fatalcallback != NULL)
79 setfatalcallback(fatalcallback_t *callback) {
80 fatalcallback = callback;
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));
90 vbprintf(int level, const char *fmt, ...) {
95 fprintf(stderr, "%s: ", program);
96 vfprintf(stderr, fmt, ap);
101 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
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;
114 alg_format(const dns_secalg_t alg, char *cp, unsigned int size) {
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;
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];
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);
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];
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));
147 setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) {
149 isc_logdestination_t destination;
150 isc_logconfig_t *logconfig = NULL;
151 isc_log_t *log = NULL;
159 * We want to see warnings about things like out-of-zone
160 * data in the master file even when not verbose.
162 level = ISC_LOG_WARNING;
165 level = ISC_LOG_INFO;
168 level = ISC_LOG_DEBUG(verbose - 2 + 1);
172 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
173 isc_log_setcontext(log);
175 dns_log_setcontext(log);
177 RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
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
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",
193 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
194 check_result(result, "isc_log_createchannel()");
196 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
197 NULL, NULL) == ISC_R_SUCCESS);
203 cleanup_logging(isc_log_t **logp) {
206 REQUIRE(logp != NULL);
211 isc_log_destroy(&log);
212 isc_log_setcontext(NULL);
213 dns_log_setcontext(NULL);
218 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
220 isc_entropysource_t *source = NULL;
221 entropysource_t *elt;
222 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
224 REQUIRE(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);
233 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
234 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
238 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
241 if (result != ISC_R_SUCCESS)
242 fatal("could not initialize entropy source: %s",
243 isc_result_totext(result));
245 if (source != NULL) {
246 elt = isc_mem_get(mctx, sizeof(*elt));
248 fatal("out of memory");
249 elt->source = source;
251 ISC_LINK_INIT(elt, link);
252 ISC_LIST_APPEND(sources, elt, link);
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));
265 isc_entropy_detach(ectx);
269 strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
270 isc_int64_t val, offset;
275 offset = strtol(str + 1, &endp, 0);
277 fatal("time value %s is invalid", str);
279 } else if (strncmp(str, "now+", 4) == 0) {
280 offset = strtol(str + 4, &endp, 0);
282 fatal("time value %s is invalid", str);
284 } else if (strlen(str) == 8U) {
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);
291 result = dns_time64_fromtext(str, &val);
292 if (result != ISC_R_SUCCESS)
293 fatal("time value %s is invalid", str);
296 return ((isc_stdtime_t) val);
300 strtoclass(const char *str) {
302 dns_rdataclass_t rdclass;
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);