Merge from vendor branch TEXINFO:
[dragonfly.git] / contrib / bind-9.2.4rc7 / bin / dnssec / dnssectool.c
1 /*
2  * Copyright (C) 2004  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.5 2004/03/09 06:09:16 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/string.h>
27 #include <isc/time.h>
28 #include <isc/util.h>
29 #include <isc/print.h>
30
31 #include <dns/log.h>
32 #include <dns/name.h>
33 #include <dns/rdatastruct.h>
34 #include <dns/rdatatype.h>
35 #include <dns/result.h>
36 #include <dns/secalg.h>
37 #include <dns/time.h>
38
39 #include "dnssectool.h"
40
41 extern int verbose;
42 extern const char *program;
43
44 static isc_entropysource_t *source = NULL;
45 static fatalcallback_t *fatalcallback = NULL;
46
47 void
48 fatal(const char *format, ...) {
49         va_list args;
50
51         fprintf(stderr, "%s: ", program);
52         va_start(args, format);
53         vfprintf(stderr, format, args);
54         va_end(args);
55         fprintf(stderr, "\n");
56         if (fatalcallback != NULL)
57                 (*fatalcallback)();
58         exit(1);
59 }
60
61 void
62 setfatalcallback(fatalcallback_t *callback) {
63         fatalcallback = callback;
64 }
65
66 void
67 check_result(isc_result_t result, const char *message) {
68         if (result != ISC_R_SUCCESS)
69                 fatal("%s: %s", message, isc_result_totext(result));
70 }
71
72 void
73 vbprintf(int level, const char *fmt, ...) {
74         va_list ap;
75         if (level > verbose)
76                 return;
77         va_start(ap, fmt);
78         fprintf(stderr, "%s: ", program);
79         vfprintf(stderr, fmt, ap);
80         va_end(ap);
81 }
82
83 void
84 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
85         isc_buffer_t b;
86         isc_region_t r;
87         isc_result_t result;
88
89         isc_buffer_init(&b, cp, size - 1);
90         result = dns_rdatatype_totext(type, &b);
91         check_result(result, "dns_rdatatype_totext()");
92         isc_buffer_usedregion(&b, &r);
93         r.base[r.length] = 0;
94 }
95
96 void
97 alg_format(const dns_secalg_t alg, char *cp, unsigned int size) {
98         isc_buffer_t b;
99         isc_region_t r;
100         isc_result_t result;
101
102         isc_buffer_init(&b, cp, size - 1);
103         result = dns_secalg_totext(alg, &b);
104         check_result(result, "dns_secalg_totext()");
105         isc_buffer_usedregion(&b, &r);
106         r.base[r.length] = 0;
107 }
108
109 void
110 sig_format(dns_rdata_sig_t *sig, char *cp, unsigned int size) {
111         char namestr[DNS_NAME_FORMATSIZE];
112         char algstr[DNS_NAME_FORMATSIZE];
113
114         dns_name_format(&sig->signer, namestr, sizeof namestr);
115         alg_format(sig->algorithm, algstr, sizeof algstr);
116         snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
117 }
118
119 void
120 key_format(const dst_key_t *key, char *cp, unsigned int size) {
121         char namestr[DNS_NAME_FORMATSIZE];
122         char algstr[DNS_NAME_FORMATSIZE];
123
124         dns_name_format(dst_key_name(key), namestr, sizeof namestr);
125         alg_format((dns_secalg_t) dst_key_alg(key), algstr, sizeof algstr);
126         snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
127 }
128
129 void
130 setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) {
131         isc_result_t result;
132         isc_logdestination_t destination;
133         isc_logconfig_t *logconfig = NULL;
134         isc_log_t *log = NULL;
135         int level;
136
137         switch (verbose) {
138         case 0:
139                 /*
140                  * We want to see warnings about things like out-of-zone
141                  * data in the master file even when not verbose.
142                  */
143                 level = ISC_LOG_WARNING;
144                 break;
145         case 1:
146                 level = ISC_LOG_INFO;
147                 break;
148         default:
149                 level = ISC_LOG_DEBUG(verbose - 2 + 1);
150                 break;
151         }
152
153         RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
154         isc_log_setcontext(log);
155         dns_log_init(log);
156         dns_log_setcontext(log);
157
158         RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
159
160         /*
161          * Set up a channel similar to default_stderr except:
162          *  - the logging level is passed in
163          *  - the program name and logging level are printed
164          *  - no time stamp is printed
165          */
166         destination.file.stream = stderr;
167         destination.file.name = NULL;
168         destination.file.versions = ISC_LOG_ROLLNEVER;
169         destination.file.maximum_size = 0;
170         result = isc_log_createchannel(logconfig, "stderr",
171                                        ISC_LOG_TOFILEDESC,
172                                        level,
173                                        &destination,
174                                        ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
175         check_result(result, "isc_log_createchannel()");
176
177         RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
178                                          NULL, NULL) == ISC_R_SUCCESS);
179
180         *logp = log;
181 }
182
183 void
184 cleanup_logging(isc_log_t **logp) {
185         isc_log_t *log;
186
187         REQUIRE(logp != NULL);
188
189         log = *logp;
190         if (log == NULL)
191                 return;
192         isc_log_destroy(&log);
193         isc_log_setcontext(NULL);
194         dns_log_setcontext(NULL);
195         logp = NULL;
196 }
197
198 void
199 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
200         isc_result_t result;
201         int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
202
203         REQUIRE(ectx != NULL);
204         
205         if (*ectx == NULL) {
206                 result = isc_entropy_create(mctx, ectx);
207                 if (result != ISC_R_SUCCESS)
208                         fatal("could not create entropy object");
209         }
210
211         if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
212                 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
213                 randomfile = NULL;
214         }
215
216         result = isc_entropy_usebestsource(*ectx, &source, randomfile,
217                                            usekeyboard);
218
219         if (result != ISC_R_SUCCESS)
220                 fatal("could not initialize entropy source: %s",
221                       isc_result_totext(result));
222 }
223
224 void
225 cleanup_entropy(isc_entropy_t **ectx) {
226         if (source != NULL)
227                 isc_entropy_destroysource(&source);
228         isc_entropy_detach(ectx);
229 }
230
231 isc_stdtime_t
232 strtotime(char *str, isc_int64_t now, isc_int64_t base) {
233         isc_int64_t val, offset;
234         isc_result_t result;
235         char *endp;
236
237         if (str[0] == '+') {
238                 offset = strtol(str + 1, &endp, 0);
239                 if (*endp != '\0')
240                         fatal("time value %s is invalid", str);
241                 val = base + offset;
242         } else if (strncmp(str, "now+", 4) == 0) {
243                 offset = strtol(str + 4, &endp, 0);
244                 if (*endp != '\0')
245                         fatal("time value %s is invalid", str);
246                 val = now + offset;
247         } else if (strlen(str) == 8U) {
248                 char timestr[15];
249                 sprintf(timestr, "%s000000", str);
250                 result = dns_time64_fromtext(timestr, &val);
251                 if (result != ISC_R_SUCCESS)
252                         fatal("time value %s is invalid", str);
253         } else {
254                 result = dns_time64_fromtext(str, &val);
255                 if (result != ISC_R_SUCCESS)
256                         fatal("time value %s is invalid", str);
257         }
258
259         return ((isc_stdtime_t) val);
260 }