dnssectool.c revision 222395
1/* 2 * Copyright (C) 2004, 2005, 2007, 2009 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.334.5 2009-06-22 05:05:00 marka 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 50extern int verbose; 51extern const char *program; 52 53typedef struct entropysource entropysource_t; 54 55struct entropysource { 56 isc_entropysource_t *source; 57 isc_mem_t *mctx; 58 ISC_LINK(entropysource_t) link; 59}; 60 61static ISC_LIST(entropysource_t) sources; 62static fatalcallback_t *fatalcallback = NULL; 63 64void 65fatal(const char *format, ...) { 66 va_list args; 67 68 fprintf(stderr, "%s: fatal: ", 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 78void 79setfatalcallback(fatalcallback_t *callback) { 80 fatalcallback = callback; 81} 82 83void 84check_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 89void 90vbprintf(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 100void 101type_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 113void 114alg_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 126void 127sig_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 136void 137key_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 146void 147setup_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 202void 203cleanup_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 217void 218setup_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 256void 257cleanup_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 268isc_stdtime_t 269strtotime(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 299dns_rdataclass_t 300strtoclass(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} 314