xref: /minix3/external/bsd/bind/dist/bin/dnssec/dnssec-revoke.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: dnssec-revoke.c,v 1.8 2014/12/10 04:37:51 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2009-2012, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek /*! \file */
20*00b67f09SDavid van Moolenbroek 
21*00b67f09SDavid van Moolenbroek #include <config.h>
22*00b67f09SDavid van Moolenbroek 
23*00b67f09SDavid van Moolenbroek #include <stdlib.h>
24*00b67f09SDavid van Moolenbroek #include <unistd.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
27*00b67f09SDavid van Moolenbroek #include <isc/commandline.h>
28*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
29*00b67f09SDavid van Moolenbroek #include <isc/file.h>
30*00b67f09SDavid van Moolenbroek #include <isc/hash.h>
31*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
32*00b67f09SDavid van Moolenbroek #include <isc/print.h>
33*00b67f09SDavid van Moolenbroek #include <isc/string.h>
34*00b67f09SDavid van Moolenbroek #include <isc/util.h>
35*00b67f09SDavid van Moolenbroek 
36*00b67f09SDavid van Moolenbroek #include <dns/keyvalues.h>
37*00b67f09SDavid van Moolenbroek #include <dns/result.h>
38*00b67f09SDavid van Moolenbroek 
39*00b67f09SDavid van Moolenbroek #include <dst/dst.h>
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
42*00b67f09SDavid van Moolenbroek #include <pk11/result.h>
43*00b67f09SDavid van Moolenbroek #endif
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek #include "dnssectool.h"
46*00b67f09SDavid van Moolenbroek 
47*00b67f09SDavid van Moolenbroek const char *program = "dnssec-revoke";
48*00b67f09SDavid van Moolenbroek int verbose;
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek static isc_mem_t	*mctx = NULL;
51*00b67f09SDavid van Moolenbroek 
52*00b67f09SDavid van Moolenbroek ISC_PLATFORM_NORETURN_PRE static void
53*00b67f09SDavid van Moolenbroek usage(void) ISC_PLATFORM_NORETURN_POST;
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek static void
usage(void)56*00b67f09SDavid van Moolenbroek usage(void) {
57*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "Usage:\n");
58*00b67f09SDavid van Moolenbroek 	fprintf(stderr,	"    %s [options] keyfile\n\n", program);
59*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "Version: %s\n", VERSION);
60*00b67f09SDavid van Moolenbroek #if defined(PKCS11CRYPTO)
61*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -E engine:    specify PKCS#11 provider "
62*00b67f09SDavid van Moolenbroek 					"(default: %s)\n", PK11_LIB_LOCATION);
63*00b67f09SDavid van Moolenbroek #elif defined(USE_PKCS11)
64*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -E engine:    specify OpenSSL engine "
65*00b67f09SDavid van Moolenbroek 					   "(default \"pkcs11\")\n");
66*00b67f09SDavid van Moolenbroek #else
67*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -E engine:    specify OpenSSL engine\n");
68*00b67f09SDavid van Moolenbroek #endif
69*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -f:	   force overwrite\n");
70*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -K directory: use directory for key files\n");
71*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -h:	   help\n");
72*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -r:	   remove old keyfiles after "
73*00b67f09SDavid van Moolenbroek 					   "creating revoked version\n");
74*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -v level:	   set level of verbosity\n");
75*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "    -V: print version information\n");
76*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "Output:\n");
77*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "     K<name>+<alg>+<new id>.key, "
78*00b67f09SDavid van Moolenbroek 			     "K<name>+<alg>+<new id>.private\n");
79*00b67f09SDavid van Moolenbroek 
80*00b67f09SDavid van Moolenbroek 	exit (-1);
81*00b67f09SDavid van Moolenbroek }
82*00b67f09SDavid van Moolenbroek 
83*00b67f09SDavid van Moolenbroek int
main(int argc,char ** argv)84*00b67f09SDavid van Moolenbroek main(int argc, char **argv) {
85*00b67f09SDavid van Moolenbroek 	isc_result_t result;
86*00b67f09SDavid van Moolenbroek #ifdef USE_PKCS11
87*00b67f09SDavid van Moolenbroek 	const char *engine = PKCS11_ENGINE;
88*00b67f09SDavid van Moolenbroek #else
89*00b67f09SDavid van Moolenbroek 	const char *engine = NULL;
90*00b67f09SDavid van Moolenbroek #endif
91*00b67f09SDavid van Moolenbroek 	char *filename = NULL, *dir = NULL;
92*00b67f09SDavid van Moolenbroek 	char newname[1024], oldname[1024];
93*00b67f09SDavid van Moolenbroek 	char keystr[DST_KEY_FORMATSIZE];
94*00b67f09SDavid van Moolenbroek 	char *endp;
95*00b67f09SDavid van Moolenbroek 	int ch;
96*00b67f09SDavid van Moolenbroek 	isc_entropy_t *ectx = NULL;
97*00b67f09SDavid van Moolenbroek 	dst_key_t *key = NULL;
98*00b67f09SDavid van Moolenbroek 	isc_uint32_t flags;
99*00b67f09SDavid van Moolenbroek 	isc_buffer_t buf;
100*00b67f09SDavid van Moolenbroek 	isc_boolean_t force = ISC_FALSE;
101*00b67f09SDavid van Moolenbroek 	isc_boolean_t remove = ISC_FALSE;
102*00b67f09SDavid van Moolenbroek 	isc_boolean_t id = ISC_FALSE;
103*00b67f09SDavid van Moolenbroek 
104*00b67f09SDavid van Moolenbroek 	if (argc == 1)
105*00b67f09SDavid van Moolenbroek 		usage();
106*00b67f09SDavid van Moolenbroek 
107*00b67f09SDavid van Moolenbroek 	result = isc_mem_create(0, 0, &mctx);
108*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
109*00b67f09SDavid van Moolenbroek 		fatal("Out of memory");
110*00b67f09SDavid van Moolenbroek 
111*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
112*00b67f09SDavid van Moolenbroek 	pk11_result_register();
113*00b67f09SDavid van Moolenbroek #endif
114*00b67f09SDavid van Moolenbroek 	dns_result_register();
115*00b67f09SDavid van Moolenbroek 
116*00b67f09SDavid van Moolenbroek 	isc_commandline_errprint = ISC_FALSE;
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek 	while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) {
119*00b67f09SDavid van Moolenbroek 		switch (ch) {
120*00b67f09SDavid van Moolenbroek 		    case 'E':
121*00b67f09SDavid van Moolenbroek 			engine = isc_commandline_argument;
122*00b67f09SDavid van Moolenbroek 			break;
123*00b67f09SDavid van Moolenbroek 		    case 'f':
124*00b67f09SDavid van Moolenbroek 			force = ISC_TRUE;
125*00b67f09SDavid van Moolenbroek 			break;
126*00b67f09SDavid van Moolenbroek 		    case 'K':
127*00b67f09SDavid van Moolenbroek 			/*
128*00b67f09SDavid van Moolenbroek 			 * We don't have to copy it here, but do it to
129*00b67f09SDavid van Moolenbroek 			 * simplify cleanup later
130*00b67f09SDavid van Moolenbroek 			 */
131*00b67f09SDavid van Moolenbroek 			dir = isc_mem_strdup(mctx, isc_commandline_argument);
132*00b67f09SDavid van Moolenbroek 			if (dir == NULL) {
133*00b67f09SDavid van Moolenbroek 				fatal("Failed to allocate memory for "
134*00b67f09SDavid van Moolenbroek 				      "directory");
135*00b67f09SDavid van Moolenbroek 			}
136*00b67f09SDavid van Moolenbroek 			break;
137*00b67f09SDavid van Moolenbroek 		    case 'r':
138*00b67f09SDavid van Moolenbroek 			remove = ISC_TRUE;
139*00b67f09SDavid van Moolenbroek 			break;
140*00b67f09SDavid van Moolenbroek 		    case 'R':
141*00b67f09SDavid van Moolenbroek 			id = ISC_TRUE;
142*00b67f09SDavid van Moolenbroek 			break;
143*00b67f09SDavid van Moolenbroek 		    case 'v':
144*00b67f09SDavid van Moolenbroek 			verbose = strtol(isc_commandline_argument, &endp, 0);
145*00b67f09SDavid van Moolenbroek 			if (*endp != '\0')
146*00b67f09SDavid van Moolenbroek 				fatal("-v must be followed by a number");
147*00b67f09SDavid van Moolenbroek 			break;
148*00b67f09SDavid van Moolenbroek 		    case '?':
149*00b67f09SDavid van Moolenbroek 			if (isc_commandline_option != '?')
150*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "%s: invalid argument -%c\n",
151*00b67f09SDavid van Moolenbroek 					program, isc_commandline_option);
152*00b67f09SDavid van Moolenbroek 			/* Falls into */
153*00b67f09SDavid van Moolenbroek 		    case 'h':
154*00b67f09SDavid van Moolenbroek 			/* Does not return. */
155*00b67f09SDavid van Moolenbroek 			usage();
156*00b67f09SDavid van Moolenbroek 
157*00b67f09SDavid van Moolenbroek 		    case 'V':
158*00b67f09SDavid van Moolenbroek 			/* Does not return. */
159*00b67f09SDavid van Moolenbroek 			version(program);
160*00b67f09SDavid van Moolenbroek 
161*00b67f09SDavid van Moolenbroek 		    default:
162*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "%s: unhandled option -%c\n",
163*00b67f09SDavid van Moolenbroek 				program, isc_commandline_option);
164*00b67f09SDavid van Moolenbroek 			exit(1);
165*00b67f09SDavid van Moolenbroek 		}
166*00b67f09SDavid van Moolenbroek 	}
167*00b67f09SDavid van Moolenbroek 
168*00b67f09SDavid van Moolenbroek 	if (argc < isc_commandline_index + 1 ||
169*00b67f09SDavid van Moolenbroek 	    argv[isc_commandline_index] == NULL)
170*00b67f09SDavid van Moolenbroek 		fatal("The key file name was not specified");
171*00b67f09SDavid van Moolenbroek 	if (argc > isc_commandline_index + 1)
172*00b67f09SDavid van Moolenbroek 		fatal("Extraneous arguments");
173*00b67f09SDavid van Moolenbroek 
174*00b67f09SDavid van Moolenbroek 	if (dir != NULL) {
175*00b67f09SDavid van Moolenbroek 		filename = argv[isc_commandline_index];
176*00b67f09SDavid van Moolenbroek 	} else {
177*00b67f09SDavid van Moolenbroek 		result = isc_file_splitpath(mctx, argv[isc_commandline_index],
178*00b67f09SDavid van Moolenbroek 					    &dir, &filename);
179*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
180*00b67f09SDavid van Moolenbroek 			fatal("cannot process filename %s: %s",
181*00b67f09SDavid van Moolenbroek 			      argv[isc_commandline_index],
182*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
183*00b67f09SDavid van Moolenbroek 		if (strcmp(dir, ".") == 0) {
184*00b67f09SDavid van Moolenbroek 			isc_mem_free(mctx, dir);
185*00b67f09SDavid van Moolenbroek 			dir = NULL;
186*00b67f09SDavid van Moolenbroek 		}
187*00b67f09SDavid van Moolenbroek 	}
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek 	if (ectx == NULL)
190*00b67f09SDavid van Moolenbroek 		setup_entropy(mctx, NULL, &ectx);
191*00b67f09SDavid van Moolenbroek 	result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
192*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
193*00b67f09SDavid van Moolenbroek 		fatal("Could not initialize hash");
194*00b67f09SDavid van Moolenbroek 	result = dst_lib_init2(mctx, ectx, engine,
195*00b67f09SDavid van Moolenbroek 			       ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
196*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
197*00b67f09SDavid van Moolenbroek 		fatal("Could not initialize dst: %s",
198*00b67f09SDavid van Moolenbroek 		      isc_result_totext(result));
199*00b67f09SDavid van Moolenbroek 	isc_entropy_stopcallbacksources(ectx);
200*00b67f09SDavid van Moolenbroek 
201*00b67f09SDavid van Moolenbroek 	result = dst_key_fromnamedfile(filename, dir,
202*00b67f09SDavid van Moolenbroek 				       DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
203*00b67f09SDavid van Moolenbroek 				       mctx, &key);
204*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
205*00b67f09SDavid van Moolenbroek 		fatal("Invalid keyfile name %s: %s",
206*00b67f09SDavid van Moolenbroek 		      filename, isc_result_totext(result));
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek 	if (id) {
209*00b67f09SDavid van Moolenbroek 		fprintf(stdout, "%u\n", dst_key_rid(key));
210*00b67f09SDavid van Moolenbroek 		goto cleanup;
211*00b67f09SDavid van Moolenbroek 	}
212*00b67f09SDavid van Moolenbroek 	dst_key_format(key, keystr, sizeof(keystr));
213*00b67f09SDavid van Moolenbroek 
214*00b67f09SDavid van Moolenbroek 	if (verbose > 2)
215*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "%s: %s\n", program, keystr);
216*00b67f09SDavid van Moolenbroek 
217*00b67f09SDavid van Moolenbroek 	if (force)
218*00b67f09SDavid van Moolenbroek 		set_keyversion(key);
219*00b67f09SDavid van Moolenbroek 	else
220*00b67f09SDavid van Moolenbroek 		check_keyversion(key, keystr);
221*00b67f09SDavid van Moolenbroek 
222*00b67f09SDavid van Moolenbroek 
223*00b67f09SDavid van Moolenbroek 	flags = dst_key_flags(key);
224*00b67f09SDavid van Moolenbroek 	if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
225*00b67f09SDavid van Moolenbroek 		isc_stdtime_t now;
226*00b67f09SDavid van Moolenbroek 
227*00b67f09SDavid van Moolenbroek 		if ((flags & DNS_KEYFLAG_KSK) == 0)
228*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "%s: warning: Key is not flagged "
229*00b67f09SDavid van Moolenbroek 					"as a KSK. Revoking a ZSK is "
230*00b67f09SDavid van Moolenbroek 					"legal, but undefined.\n",
231*00b67f09SDavid van Moolenbroek 					program);
232*00b67f09SDavid van Moolenbroek 
233*00b67f09SDavid van Moolenbroek 		isc_stdtime_get(&now);
234*00b67f09SDavid van Moolenbroek 		dst_key_settime(key, DST_TIME_REVOKE, now);
235*00b67f09SDavid van Moolenbroek 
236*00b67f09SDavid van Moolenbroek 		dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE);
237*00b67f09SDavid van Moolenbroek 
238*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&buf, newname, sizeof(newname));
239*00b67f09SDavid van Moolenbroek 		dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
240*00b67f09SDavid van Moolenbroek 
241*00b67f09SDavid van Moolenbroek 		if (access(newname, F_OK) == 0 && !force) {
242*00b67f09SDavid van Moolenbroek 			fatal("Key file %s already exists; "
243*00b67f09SDavid van Moolenbroek 			      "use -f to force overwrite", newname);
244*00b67f09SDavid van Moolenbroek 		}
245*00b67f09SDavid van Moolenbroek 
246*00b67f09SDavid van Moolenbroek 		result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
247*00b67f09SDavid van Moolenbroek 					dir);
248*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
249*00b67f09SDavid van Moolenbroek 			dst_key_format(key, keystr, sizeof(keystr));
250*00b67f09SDavid van Moolenbroek 			fatal("Failed to write key %s: %s", keystr,
251*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
252*00b67f09SDavid van Moolenbroek 		}
253*00b67f09SDavid van Moolenbroek 
254*00b67f09SDavid van Moolenbroek 		isc_buffer_clear(&buf);
255*00b67f09SDavid van Moolenbroek 		dst_key_buildfilename(key, 0, dir, &buf);
256*00b67f09SDavid van Moolenbroek 		printf("%s\n", newname);
257*00b67f09SDavid van Moolenbroek 
258*00b67f09SDavid van Moolenbroek 		/*
259*00b67f09SDavid van Moolenbroek 		 * Remove old key file, if told to (and if
260*00b67f09SDavid van Moolenbroek 		 * it isn't the same as the new file)
261*00b67f09SDavid van Moolenbroek 		 */
262*00b67f09SDavid van Moolenbroek 		if (remove && dst_key_alg(key) != DST_ALG_RSAMD5) {
263*00b67f09SDavid van Moolenbroek 			isc_buffer_init(&buf, oldname, sizeof(oldname));
264*00b67f09SDavid van Moolenbroek 			dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE);
265*00b67f09SDavid van Moolenbroek 			dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
266*00b67f09SDavid van Moolenbroek 			if (strcmp(oldname, newname) == 0)
267*00b67f09SDavid van Moolenbroek 				goto cleanup;
268*00b67f09SDavid van Moolenbroek 			(void)unlink(oldname);
269*00b67f09SDavid van Moolenbroek 			isc_buffer_clear(&buf);
270*00b67f09SDavid van Moolenbroek 			dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
271*00b67f09SDavid van Moolenbroek 			(void)unlink(oldname);
272*00b67f09SDavid van Moolenbroek 		}
273*00b67f09SDavid van Moolenbroek 	} else {
274*00b67f09SDavid van Moolenbroek 		dst_key_format(key, keystr, sizeof(keystr));
275*00b67f09SDavid van Moolenbroek 		fatal("Key %s is already revoked", keystr);
276*00b67f09SDavid van Moolenbroek 	}
277*00b67f09SDavid van Moolenbroek 
278*00b67f09SDavid van Moolenbroek cleanup:
279*00b67f09SDavid van Moolenbroek 	dst_key_free(&key);
280*00b67f09SDavid van Moolenbroek 	dst_lib_destroy();
281*00b67f09SDavid van Moolenbroek 	isc_hash_destroy();
282*00b67f09SDavid van Moolenbroek 	cleanup_entropy(&ectx);
283*00b67f09SDavid van Moolenbroek 	if (verbose > 10)
284*00b67f09SDavid van Moolenbroek 		isc_mem_stats(mctx, stdout);
285*00b67f09SDavid van Moolenbroek 	if (dir != NULL)
286*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, dir);
287*00b67f09SDavid van Moolenbroek 	isc_mem_destroy(&mctx);
288*00b67f09SDavid van Moolenbroek 
289*00b67f09SDavid van Moolenbroek 	return (0);
290*00b67f09SDavid van Moolenbroek }
291