/contrib/bind9/bin/dnssec/dnssec-revoke.c
C | 277 lines | 212 code | 39 blank | 26 comment | 56 complexity | 673b7a0174dd321671385ec1508c8a1d MD5 | raw file
1/* 2 * Copyright (C) 2009-2011 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-revoke.c,v 1.22.124.2 2011/10/20 23:46:27 tbox Exp $ */ 18 19/*! \file */ 20 21#include <config.h> 22 23#include <libgen.h> 24#include <stdlib.h> 25#include <unistd.h> 26 27#include <isc/buffer.h> 28#include <isc/commandline.h> 29#include <isc/entropy.h> 30#include <isc/file.h> 31#include <isc/hash.h> 32#include <isc/mem.h> 33#include <isc/print.h> 34#include <isc/string.h> 35#include <isc/util.h> 36 37#include <dns/keyvalues.h> 38#include <dns/result.h> 39 40#include <dst/dst.h> 41 42#include "dnssectool.h" 43 44const char *program = "dnssec-revoke"; 45int verbose; 46 47static isc_mem_t *mctx = NULL; 48 49ISC_PLATFORM_NORETURN_PRE static void 50usage(void) ISC_PLATFORM_NORETURN_POST; 51 52static void 53usage(void) { 54 fprintf(stderr, "Usage:\n"); 55 fprintf(stderr, " %s [options] keyfile\n\n", program); 56 fprintf(stderr, "Version: %s\n", VERSION); 57#ifdef USE_PKCS11 58 fprintf(stderr, " -E engine: specify OpenSSL engine " 59 "(default \"pkcs11\")\n"); 60#else 61 fprintf(stderr, " -E engine: specify OpenSSL engine\n"); 62#endif 63 fprintf(stderr, " -f: force overwrite\n"); 64 fprintf(stderr, " -K directory: use directory for key files\n"); 65 fprintf(stderr, " -h: help\n"); 66 fprintf(stderr, " -r: remove old keyfiles after " 67 "creating revoked version\n"); 68 fprintf(stderr, " -v level: set level of verbosity\n"); 69 fprintf(stderr, "Output:\n"); 70 fprintf(stderr, " K<name>+<alg>+<new id>.key, " 71 "K<name>+<alg>+<new id>.private\n"); 72 73 exit (-1); 74} 75 76int 77main(int argc, char **argv) { 78 isc_result_t result; 79#ifdef USE_PKCS11 80 const char *engine = "pkcs11"; 81#else 82 const char *engine = NULL; 83#endif 84 char *filename = NULL, *dir = NULL; 85 char newname[1024], oldname[1024]; 86 char keystr[DST_KEY_FORMATSIZE]; 87 char *endp; 88 int ch; 89 isc_entropy_t *ectx = NULL; 90 dst_key_t *key = NULL; 91 isc_uint32_t flags; 92 isc_buffer_t buf; 93 isc_boolean_t force = ISC_FALSE; 94 isc_boolean_t remove = ISC_FALSE; 95 isc_boolean_t id = ISC_FALSE; 96 97 if (argc == 1) 98 usage(); 99 100 result = isc_mem_create(0, 0, &mctx); 101 if (result != ISC_R_SUCCESS) 102 fatal("Out of memory"); 103 104 dns_result_register(); 105 106 isc_commandline_errprint = ISC_FALSE; 107 108 while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:")) != -1) { 109 switch (ch) { 110 case 'E': 111 engine = isc_commandline_argument; 112 break; 113 case 'f': 114 force = ISC_TRUE; 115 break; 116 case 'K': 117 /* 118 * We don't have to copy it here, but do it to 119 * simplify cleanup later 120 */ 121 dir = isc_mem_strdup(mctx, isc_commandline_argument); 122 if (dir == NULL) { 123 fatal("Failed to allocate memory for " 124 "directory"); 125 } 126 break; 127 case 'r': 128 remove = ISC_TRUE; 129 break; 130 case 'R': 131 id = ISC_TRUE; 132 break; 133 case 'v': 134 verbose = strtol(isc_commandline_argument, &endp, 0); 135 if (*endp != '\0') 136 fatal("-v must be followed by a number"); 137 break; 138 case '?': 139 if (isc_commandline_option != '?') 140 fprintf(stderr, "%s: invalid argument -%c\n", 141 program, isc_commandline_option); 142 /* Falls into */ 143 case 'h': 144 usage(); 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 if (ectx == NULL) 175 setup_entropy(mctx, NULL, &ectx); 176 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); 177 if (result != ISC_R_SUCCESS) 178 fatal("Could not initialize hash"); 179 result = dst_lib_init2(mctx, ectx, engine, 180 ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); 181 if (result != ISC_R_SUCCESS) 182 fatal("Could not initialize dst: %s", 183 isc_result_totext(result)); 184 isc_entropy_stopcallbacksources(ectx); 185 186 result = dst_key_fromnamedfile(filename, dir, 187 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 188 mctx, &key); 189 if (result != ISC_R_SUCCESS) 190 fatal("Invalid keyfile name %s: %s", 191 filename, isc_result_totext(result)); 192 193 if (id) { 194 fprintf(stdout, "%u\n", dst_key_rid(key)); 195 goto cleanup; 196 } 197 dst_key_format(key, keystr, sizeof(keystr)); 198 199 if (verbose > 2) 200 fprintf(stderr, "%s: %s\n", program, keystr); 201 202 if (force) 203 set_keyversion(key); 204 else 205 check_keyversion(key, keystr); 206 207 208 flags = dst_key_flags(key); 209 if ((flags & DNS_KEYFLAG_REVOKE) == 0) { 210 isc_stdtime_t now; 211 212 if ((flags & DNS_KEYFLAG_KSK) == 0) 213 fprintf(stderr, "%s: warning: Key is not flagged " 214 "as a KSK. Revoking a ZSK is " 215 "legal, but undefined.\n", 216 program); 217 218 isc_stdtime_get(&now); 219 dst_key_settime(key, DST_TIME_REVOKE, now); 220 221 dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE); 222 223 isc_buffer_init(&buf, newname, sizeof(newname)); 224 dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); 225 226 if (access(newname, F_OK) == 0 && !force) { 227 fatal("Key file %s already exists; " 228 "use -f to force overwrite", newname); 229 } 230 231 result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 232 dir); 233 if (result != ISC_R_SUCCESS) { 234 dst_key_format(key, keystr, sizeof(keystr)); 235 fatal("Failed to write key %s: %s", keystr, 236 isc_result_totext(result)); 237 } 238 239 isc_buffer_clear(&buf); 240 dst_key_buildfilename(key, 0, dir, &buf); 241 printf("%s\n", newname); 242 243 /* 244 * Remove old key file, if told to (and if 245 * it isn't the same as the new file) 246 */ 247 if (remove && dst_key_alg(key) != DST_ALG_RSAMD5) { 248 isc_buffer_init(&buf, oldname, sizeof(oldname)); 249 dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE); 250 dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); 251 if (strcmp(oldname, newname) == 0) 252 goto cleanup; 253 if (access(oldname, F_OK) == 0) 254 unlink(oldname); 255 isc_buffer_clear(&buf); 256 dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); 257 if (access(oldname, F_OK) == 0) 258 unlink(oldname); 259 } 260 } else { 261 dst_key_format(key, keystr, sizeof(keystr)); 262 fatal("Key %s is already revoked", keystr); 263 } 264 265cleanup: 266 dst_key_free(&key); 267 dst_lib_destroy(); 268 isc_hash_destroy(); 269 cleanup_entropy(&ectx); 270 if (verbose > 10) 271 isc_mem_stats(mctx, stdout); 272 if (dir != NULL) 273 isc_mem_free(mctx, dir); 274 isc_mem_destroy(&mctx); 275 276 return (0); 277}