Update repub branch u/fanf2/patch to rebasing branch u/fanf2/rebasing revision v9_13_...
[ipreg/bind9.git] / bin / dnssec / dnssec-revoke.c
1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file */
13
14 #include <inttypes.h>
15 #include <stdbool.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18
19 #include <isc/buffer.h>
20 #include <isc/commandline.h>
21 #include <isc/file.h>
22 #include <isc/hash.h>
23 #include <isc/mem.h>
24 #include <isc/print.h>
25 #include <isc/string.h>
26 #include <isc/util.h>
27
28 #include <dns/keyvalues.h>
29 #include <dns/result.h>
30
31 #include <dst/dst.h>
32
33 #if USE_PKCS11
34 #include <pk11/result.h>
35 #endif
36
37 #include "dnssectool.h"
38
39 const char *program = "dnssec-revoke";
40 int verbose;
41
42 static isc_mem_t *mctx = NULL;
43
44 ISC_PLATFORM_NORETURN_PRE static void
45 usage(void) ISC_PLATFORM_NORETURN_POST;
46
47 static void
48 usage(void) {
49 fprintf(stderr, "Usage:\n");
50 fprintf(stderr, " %s [options] keyfile\n\n", program);
51 fprintf(stderr, "Version: %s\n", VERSION);
52 #if USE_PKCS11
53 fprintf(stderr, " -E engine: specify PKCS#11 provider "
54 "(default: %s)\n", PK11_LIB_LOCATION);
55 #else
56 fprintf(stderr, " -E engine: specify OpenSSL engine\n");
57 #endif
58 fprintf(stderr, " -f: force overwrite\n");
59 fprintf(stderr, " -h: help\n");
60 fprintf(stderr, " -K directory: use directory for key files\n");
61 fprintf(stderr, " -r: remove old keyfiles after "
62 "creating revoked version\n");
63 fprintf(stderr, " -v level: set level of verbosity\n");
64 fprintf(stderr, " -V: print version information\n");
65 fprintf(stderr, "Output:\n");
66 fprintf(stderr, " K<name>+<alg>+<new id>.key, "
67 "K<name>+<alg>+<new id>.private\n");
68
69 exit (-1);
70 }
71
72 int
73 main(int argc, char **argv) {
74 isc_result_t result;
75 const char *engine = NULL;
76 char const *filename = NULL;
77 char *dir = NULL;
78 char newname[1024], oldname[1024];
79 char keystr[DST_KEY_FORMATSIZE];
80 char *endp;
81 int ch;
82 dst_key_t *key = NULL;
83 uint32_t flags;
84 isc_buffer_t buf;
85 bool force = false;
86 bool removefile = false;
87 bool id = false;
88
89 if (argc == 1)
90 usage();
91
92 result = isc_mem_create(0, 0, &mctx);
93 if (result != ISC_R_SUCCESS)
94 fatal("Out of memory");
95
96 #if HAVE_PKCS11
97 pk11_result_register();
98 #endif
99 dns_result_register();
100
101 isc_commandline_errprint = false;
102
103 while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) {
104 switch (ch) {
105 case 'E':
106 engine = isc_commandline_argument;
107 break;
108 case 'f':
109 force = true;
110 break;
111 case 'K':
112 /*
113 * We don't have to copy it here, but do it to
114 * simplify cleanup later
115 */
116 dir = isc_mem_strdup(mctx, isc_commandline_argument);
117 if (dir == NULL) {
118 fatal("Failed to allocate memory for "
119 "directory");
120 }
121 break;
122 case 'r':
123 removefile = true;
124 break;
125 case 'R':
126 id = true;
127 break;
128 case 'v':
129 verbose = strtol(isc_commandline_argument, &endp, 0);
130 if (*endp != '\0')
131 fatal("-v must be followed by a number");
132 break;
133 case '?':
134 if (isc_commandline_option != '?')
135 fprintf(stderr, "%s: invalid argument -%c\n",
136 program, isc_commandline_option);
137 /* FALLTHROUGH */
138 case 'h':
139 /* Does not return. */
140 usage();
141
142 case 'V':
143 /* Does not return. */
144 version(program);
145
146 default:
147 fprintf(stderr, "%s: unhandled option -%c\n",
148 program, isc_commandline_option);
149 exit(1);
150 }
151 }
152
153 if (argc < isc_commandline_index + 1 ||
154 argv[isc_commandline_index] == NULL)
155 fatal("The key file name was not specified");
156 if (argc > isc_commandline_index + 1)
157 fatal("Extraneous arguments");
158
159 if (dir != NULL) {
160 filename = argv[isc_commandline_index];
161 } else {
162 result = isc_file_splitpath(mctx, argv[isc_commandline_index],
163 &dir, &filename);
164 if (result != ISC_R_SUCCESS)
165 fatal("cannot process filename %s: %s",
166 argv[isc_commandline_index],
167 isc_result_totext(result));
168 if (strcmp(dir, ".") == 0) {
169 isc_mem_free(mctx, dir);
170 dir = NULL;
171 }
172 }
173
174 result = dst_lib_init(mctx, engine);
175 if (result != ISC_R_SUCCESS)
176 fatal("Could not initialize dst: %s",
177 isc_result_totext(result));
178
179 result = dst_key_fromnamedfile(filename, dir,
180 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
181 mctx, &key);
182 if (result != ISC_R_SUCCESS)
183 fatal("Invalid keyfile name %s: %s",
184 filename, isc_result_totext(result));
185
186 if (id) {
187 fprintf(stdout, "%u\n", dst_key_rid(key));
188 goto cleanup;
189 }
190 dst_key_format(key, keystr, sizeof(keystr));
191
192 if (verbose > 2)
193 fprintf(stderr, "%s: %s\n", program, keystr);
194
195 if (force)
196 set_keyversion(key);
197 else
198 check_keyversion(key, keystr);
199
200
201 flags = dst_key_flags(key);
202 if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
203 isc_stdtime_t now;
204
205 if ((flags & DNS_KEYFLAG_KSK) == 0)
206 fprintf(stderr, "%s: warning: Key is not flagged "
207 "as a KSK. Revoking a ZSK is "
208 "legal, but undefined.\n",
209 program);
210
211 isc_stdtime_get(&now);
212 dst_key_settime(key, DST_TIME_REVOKE, now);
213
214 dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE);
215
216 isc_buffer_init(&buf, newname, sizeof(newname));
217 dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
218
219 if (access(newname, F_OK) == 0 && !force) {
220 fatal("Key file %s already exists; "
221 "use -f to force overwrite", newname);
222 }
223
224 result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
225 dir);
226 if (result != ISC_R_SUCCESS) {
227 dst_key_format(key, keystr, sizeof(keystr));
228 fatal("Failed to write key %s: %s", keystr,
229 isc_result_totext(result));
230 }
231
232 isc_buffer_clear(&buf);
233 dst_key_buildfilename(key, 0, dir, &buf);
234 printf("%s\n", newname);
235
236 /*
237 * Remove old key file, if told to (and if
238 * it isn't the same as the new file)
239 */
240 if (removefile) {
241 isc_buffer_init(&buf, oldname, sizeof(oldname));
242 dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE);
243 dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
244 if (strcmp(oldname, newname) == 0)
245 goto cleanup;
246 (void)unlink(oldname);
247 isc_buffer_clear(&buf);
248 dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
249 (void)unlink(oldname);
250 }
251 } else {
252 dst_key_format(key, keystr, sizeof(keystr));
253 fatal("Key %s is already revoked", keystr);
254 }
255
256 cleanup:
257 dst_key_free(&key);
258 dst_lib_destroy();
259 if (verbose > 10)
260 isc_mem_stats(mctx, stdout);
261 if (dir != NULL)
262 isc_mem_free(mctx, dir);
263 isc_mem_destroy(&mctx);
264
265 return (0);
266 }