]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/bin/dnssec/dnssec-verify.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[FreeBSD/releng/9.3.git] / contrib / bind9 / bin / dnssec / dnssec-verify.c
1 /*
2  * Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id: dnssec-verify.c,v 1.1.2.1 2011/03/16 06:37:51 each Exp $ */
18
19 /*! \file */
20
21 #include <config.h>
22
23 #include <stdlib.h>
24 #include <time.h>
25
26 #include <isc/app.h>
27 #include <isc/base32.h>
28 #include <isc/commandline.h>
29 #include <isc/entropy.h>
30 #include <isc/event.h>
31 #include <isc/file.h>
32 #include <isc/hash.h>
33 #include <isc/hex.h>
34 #include <isc/mem.h>
35 #include <isc/mutex.h>
36 #include <isc/os.h>
37 #include <isc/print.h>
38 #include <isc/random.h>
39 #include <isc/rwlock.h>
40 #include <isc/serial.h>
41 #include <isc/stdio.h>
42 #include <isc/stdlib.h>
43 #include <isc/string.h>
44 #include <isc/time.h>
45 #include <isc/util.h>
46
47 #include <dns/db.h>
48 #include <dns/dbiterator.h>
49 #include <dns/diff.h>
50 #include <dns/dnssec.h>
51 #include <dns/ds.h>
52 #include <dns/fixedname.h>
53 #include <dns/keyvalues.h>
54 #include <dns/log.h>
55 #include <dns/master.h>
56 #include <dns/masterdump.h>
57 #include <dns/nsec.h>
58 #include <dns/nsec3.h>
59 #include <dns/rdata.h>
60 #include <dns/rdatalist.h>
61 #include <dns/rdataset.h>
62 #include <dns/rdataclass.h>
63 #include <dns/rdatasetiter.h>
64 #include <dns/rdatastruct.h>
65 #include <dns/rdatatype.h>
66 #include <dns/result.h>
67 #include <dns/soa.h>
68 #include <dns/time.h>
69
70 #include <dst/dst.h>
71
72 #include "dnssectool.h"
73
74 const char *program = "dnssec-verify";
75 int verbose;
76
77 static isc_stdtime_t now;
78 static isc_mem_t *mctx = NULL;
79 static isc_entropy_t *ectx = NULL;
80 static dns_masterformat_t inputformat = dns_masterformat_text;
81 static dns_db_t *gdb;                   /* The database */
82 static dns_dbversion_t *gversion;       /* The database version */
83 static dns_rdataclass_t gclass;         /* The class */
84 static dns_name_t *gorigin;             /* The database origin */
85 static isc_boolean_t ignore_kskflag = ISC_FALSE;
86 static isc_boolean_t keyset_kskonly = ISC_FALSE;
87
88 /*%
89  * Load the zone file from disk
90  */
91 static void
92 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
93         isc_buffer_t b;
94         int len;
95         dns_fixedname_t fname;
96         dns_name_t *name;
97         isc_result_t result;
98
99         len = strlen(origin);
100         isc_buffer_init(&b, origin, len);
101         isc_buffer_add(&b, len);
102
103         dns_fixedname_init(&fname);
104         name = dns_fixedname_name(&fname);
105         result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
106         if (result != ISC_R_SUCCESS)
107                 fatal("failed converting name '%s' to dns format: %s",
108                       origin, isc_result_totext(result));
109
110         result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
111                                rdclass, 0, NULL, db);
112         check_result(result, "dns_db_create()");
113
114         result = dns_db_load2(*db, file, inputformat);
115         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
116                 fatal("failed loading zone from '%s': %s",
117                       file, isc_result_totext(result));
118 }
119
120 ISC_PLATFORM_NORETURN_PRE static void
121 usage(void) ISC_PLATFORM_NORETURN_POST;
122
123 static void
124 usage(void) {
125         fprintf(stderr, "Usage:\n");
126         fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
127
128         fprintf(stderr, "\n");
129
130         fprintf(stderr, "Version: %s\n", VERSION);
131
132         fprintf(stderr, "Options: (default value in parenthesis) \n");
133         fprintf(stderr, "\t-v debuglevel (0)\n");
134         fprintf(stderr, "\t-o origin:\n");
135         fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
136         fprintf(stderr, "\t-I format:\n");
137         fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
138         fprintf(stderr, "\t-c class (IN)\n");
139         fprintf(stderr, "\t-E engine:\n");
140 #ifdef USE_PKCS11
141         fprintf(stderr, "\t\tname of an OpenSSL engine to use "
142                                 "(default is \"pkcs11\")\n");
143 #else
144         fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
145 #endif
146         fprintf(stderr, "\t-x:\tDNSKEY record signed with KSKs only, "
147                         "not ZSKs\n");
148         fprintf(stderr, "\t-z:\tAll records signed with KSKs\n");
149         exit(0);
150 }
151
152 int
153 main(int argc, char *argv[]) {
154         char *origin = NULL, *file = NULL;
155         char *inputformatstr = NULL;
156         isc_result_t result;
157         isc_log_t *log = NULL;
158 #ifdef USE_PKCS11
159         const char *engine = "pkcs11";
160 #else
161         const char *engine = NULL;
162 #endif
163         char *classname = NULL;
164         dns_rdataclass_t rdclass;
165         char ch, *endp;
166
167 #define CMDLINE_FLAGS \
168         "m:o:I:c:E:v:xz"
169
170         /*
171          * Process memory debugging argument first.
172          */
173         while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
174                 switch (ch) {
175                 case 'm':
176                         if (strcasecmp(isc_commandline_argument, "record") == 0)
177                                 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
178                         if (strcasecmp(isc_commandline_argument, "trace") == 0)
179                                 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
180                         if (strcasecmp(isc_commandline_argument, "usage") == 0)
181                                 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
182                         if (strcasecmp(isc_commandline_argument, "size") == 0)
183                                 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
184                         if (strcasecmp(isc_commandline_argument, "mctx") == 0)
185                                 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
186                         break;
187                 default:
188                         break;
189                 }
190         }
191         isc_commandline_reset = ISC_TRUE;
192         check_result(isc_app_start(), "isc_app_start");
193
194         result = isc_mem_create(0, 0, &mctx);
195         if (result != ISC_R_SUCCESS)
196                 fatal("out of memory");
197
198         dns_result_register();
199
200         isc_commandline_errprint = ISC_FALSE;
201
202         while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
203                 switch (ch) {
204                 case 'c':
205                         classname = isc_commandline_argument;
206                         break;
207
208                 case 'E':
209                         engine = isc_commandline_argument;
210                         break;
211
212                 case 'h':
213                         usage();
214                         break;
215
216                 case 'I':
217                         inputformatstr = isc_commandline_argument;
218                         break;
219
220                 case 'm':
221                         break;
222
223                 case 'o':
224                         origin = isc_commandline_argument;
225                         break;
226
227                 case 'v':
228                         endp = NULL;
229                         verbose = strtol(isc_commandline_argument, &endp, 0);
230                         if (*endp != '\0')
231                                 fatal("verbose level must be numeric");
232                         break;
233
234                 case 'x':
235                         keyset_kskonly = ISC_TRUE;
236                         break;
237
238                 case 'z':
239                         ignore_kskflag = ISC_TRUE;
240                         break;
241
242                 case '?':
243                         if (isc_commandline_option != '?')
244                                 fprintf(stderr, "%s: invalid argument -%c\n",
245                                         program, isc_commandline_option);
246                         usage();
247                         break;
248
249                 default:
250                         fprintf(stderr, "%s: unhandled option -%c\n",
251                                 program, isc_commandline_option);
252                         exit(1);
253                 }
254         }
255
256         if (ectx == NULL)
257                 setup_entropy(mctx, NULL, &ectx);
258
259         result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
260         if (result != ISC_R_SUCCESS)
261                 fatal("could not create hash context");
262
263         result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING);
264         if (result != ISC_R_SUCCESS)
265                 fatal("could not initialize dst: %s",
266                       isc_result_totext(result));
267
268         isc_stdtime_get(&now);
269
270         rdclass = strtoclass(classname);
271
272         setup_logging(verbose, mctx, &log);
273
274         argc -= isc_commandline_index;
275         argv += isc_commandline_index;
276
277         if (argc < 1)
278                 usage();
279
280         file = argv[0];
281
282         argc -= 1;
283         argv += 1;
284
285         POST(argc);
286         POST(argv);
287
288         if (origin == NULL)
289                 origin = file;
290
291         if (inputformatstr != NULL) {
292                 if (strcasecmp(inputformatstr, "text") == 0)
293                         inputformat = dns_masterformat_text;
294                 else if (strcasecmp(inputformatstr, "raw") == 0)
295                         inputformat = dns_masterformat_raw;
296                 else
297                         fatal("unknown file format: %s\n", inputformatstr);
298         }
299
300         gdb = NULL;
301         fprintf(stderr, "Loading zone '%s' from file '%s'\n", origin, file);
302         loadzone(file, origin, rdclass, &gdb);
303         gorigin = dns_db_origin(gdb);
304         gclass = dns_db_class(gdb);
305
306         gversion = NULL;
307         result = dns_db_newversion(gdb, &gversion);
308         check_result(result, "dns_db_newversion()");
309
310         verifyzone(gdb, gversion, gorigin, mctx,
311                    ignore_kskflag, keyset_kskonly);
312
313         dns_db_closeversion(gdb, &gversion, ISC_FALSE);
314         dns_db_detach(&gdb);
315
316         cleanup_logging(&log);
317         dst_lib_destroy();
318         isc_hash_destroy();
319         cleanup_entropy(&ectx);
320         dns_name_destroy();
321         if (verbose > 10)
322                 isc_mem_stats(mctx, stdout);
323         isc_mem_destroy(&mctx);
324
325         (void) isc_app_finish();
326
327         return (0);
328 }