2 * Copyright (C) 2004, 2005, 2007 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 2007/06/19 23:46:59 tbox 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: ", 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
);