1 /* $NetBSD: rndc-confgen.c,v 1.8 2014/12/10 04:37:51 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 2001, 2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id: rndc-confgen.c,v 1.7 2011/03/12 04:59:46 tbox Exp */ 21 22 /*! \file */ 23 24 /** 25 * rndc-confgen generates configuration files for rndc. It can be used 26 * as a convenient alternative to writing the rndc.conf file and the 27 * corresponding controls and key statements in named.conf by hand. 28 * Alternatively, it can be run with the -a option to set up a 29 * rndc.key file and avoid the need for a rndc.conf file and a 30 * controls statement altogether. 31 */ 32 33 #include <config.h> 34 35 #include <stdlib.h> 36 #include <stdarg.h> 37 38 #include <isc/assertions.h> 39 #include <isc/base64.h> 40 #include <isc/buffer.h> 41 #include <isc/commandline.h> 42 #include <isc/entropy.h> 43 #include <isc/file.h> 44 #include <isc/keyboard.h> 45 #include <isc/mem.h> 46 #include <isc/net.h> 47 #include <isc/print.h> 48 #include <isc/result.h> 49 #include <isc/string.h> 50 #include <isc/time.h> 51 #include <isc/util.h> 52 53 #include <dns/keyvalues.h> 54 #include <dns/name.h> 55 56 #include <dst/dst.h> 57 #include <confgen/os.h> 58 59 #include "util.h" 60 #include "keygen.h" 61 62 #define DEFAULT_KEYNAME "rndc-key" 63 #define DEFAULT_SERVER "127.0.0.1" 64 #define DEFAULT_PORT 953 65 66 static char program[256]; 67 const char *progname; 68 69 isc_boolean_t verbose = ISC_FALSE; 70 71 const char *keyfile, *keydef; 72 73 ISC_PLATFORM_NORETURN_PRE static void 74 usage(int status) ISC_PLATFORM_NORETURN_POST; 75 76 static void 77 usage(int status) { 78 79 fprintf(stderr, "\ 80 Usage:\n\ 81 %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ 82 [-s addr] [-t chrootdir] [-u user]\n\ 83 -a: generate just the key clause and write it to keyfile (%s)\n\ 84 -A alg: algorithm (default hmac-md5)\n\ 85 -b bits: from 1 through 512, default 256; total length of the secret\n\ 86 -c keyfile: specify an alternate key file (requires -a)\n\ 87 -k keyname: the name as it will be used in named.conf and rndc.conf\n\ 88 -p port: the port named will listen on and rndc will connect to\n\ 89 -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ 90 -s addr: the address to which rndc should connect\n\ 91 -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ 92 -u user: set the keyfile owner to \"user\" (requires -a)\n", 93 progname, keydef); 94 95 exit (status); 96 } 97 98 int 99 main(int argc, char **argv) { 100 isc_boolean_t show_final_mem = ISC_FALSE; 101 isc_buffer_t key_txtbuffer; 102 char key_txtsecret[256]; 103 isc_mem_t *mctx = NULL; 104 isc_result_t result = ISC_R_SUCCESS; 105 const char *keyname = NULL; 106 const char *randomfile = NULL; 107 const char *serveraddr = NULL; 108 dns_secalg_t alg; 109 const char *algname; 110 char *p; 111 int ch; 112 int port; 113 int keysize = -1; 114 struct in_addr addr4_dummy; 115 struct in6_addr addr6_dummy; 116 char *chrootdir = NULL; 117 char *user = NULL; 118 isc_boolean_t keyonly = ISC_FALSE; 119 int len; 120 121 keydef = keyfile = RNDC_KEYFILE; 122 123 result = isc_file_progname(*argv, program, sizeof(program)); 124 if (result != ISC_R_SUCCESS) 125 memmove(program, "rndc-confgen", 13); 126 progname = program; 127 128 keyname = DEFAULT_KEYNAME; 129 alg = DST_ALG_HMACMD5; 130 serveraddr = DEFAULT_SERVER; 131 port = DEFAULT_PORT; 132 133 isc_commandline_errprint = ISC_FALSE; 134 135 while ((ch = isc_commandline_parse(argc, argv, 136 "aA:b:c:hk:Mmp:r:s:t:u:Vy")) != -1) 137 { 138 switch (ch) { 139 case 'a': 140 keyonly = ISC_TRUE; 141 break; 142 case 'A': 143 algname = isc_commandline_argument; 144 alg = alg_fromtext(algname); 145 if (alg == DST_ALG_UNKNOWN) 146 fatal("Unsupported algorithm '%s'", algname); 147 break; 148 case 'b': 149 keysize = strtol(isc_commandline_argument, &p, 10); 150 if (*p != '\0' || keysize < 0) 151 fatal("-b requires a non-negative number"); 152 break; 153 case 'c': 154 keyfile = isc_commandline_argument; 155 break; 156 case 'h': 157 usage(0); 158 case 'k': 159 case 'y': /* Compatible with rndc -y. */ 160 keyname = isc_commandline_argument; 161 break; 162 case 'M': 163 isc_mem_debugging = ISC_MEM_DEBUGTRACE; 164 break; 165 166 case 'm': 167 show_final_mem = ISC_TRUE; 168 break; 169 case 'p': 170 port = strtol(isc_commandline_argument, &p, 10); 171 if (*p != '\0' || port < 0 || port > 65535) 172 fatal("port '%s' out of range", 173 isc_commandline_argument); 174 break; 175 case 'r': 176 randomfile = isc_commandline_argument; 177 break; 178 case 's': 179 serveraddr = isc_commandline_argument; 180 if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && 181 inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) 182 fatal("-s should be an IPv4 or IPv6 address"); 183 break; 184 case 't': 185 chrootdir = isc_commandline_argument; 186 break; 187 case 'u': 188 user = isc_commandline_argument; 189 break; 190 case 'V': 191 verbose = ISC_TRUE; 192 break; 193 case '?': 194 if (isc_commandline_option != '?') { 195 fprintf(stderr, "%s: invalid argument -%c\n", 196 program, isc_commandline_option); 197 usage(1); 198 } else 199 usage(0); 200 break; 201 default: 202 fprintf(stderr, "%s: unhandled option -%c\n", 203 program, isc_commandline_option); 204 exit(1); 205 } 206 } 207 208 argc -= isc_commandline_index; 209 argv += isc_commandline_index; 210 POST(argv); 211 212 if (argc > 0) 213 usage(1); 214 215 if (keysize < 0) 216 keysize = alg_bits(alg); 217 algname = alg_totext(alg); 218 219 DO("create memory context", isc_mem_create(0, 0, &mctx)); 220 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 221 222 generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); 223 224 if (keyonly) { 225 write_key_file(keyfile, chrootdir == NULL ? user : NULL, 226 keyname, &key_txtbuffer, alg); 227 228 if (chrootdir != NULL) { 229 char *buf; 230 len = strlen(chrootdir) + strlen(keyfile) + 2; 231 buf = isc_mem_get(mctx, len); 232 if (buf == NULL) 233 fatal("isc_mem_get(%d) failed\n", len); 234 snprintf(buf, len, "%s%s%s", chrootdir, 235 (*keyfile != '/') ? "/" : "", keyfile); 236 237 write_key_file(buf, user, keyname, &key_txtbuffer, alg); 238 isc_mem_put(mctx, buf, len); 239 } 240 } else { 241 printf("\ 242 # Start of rndc.conf\n\ 243 key \"%s\" {\n\ 244 algorithm %s;\n\ 245 secret \"%.*s\";\n\ 246 };\n\ 247 \n\ 248 options {\n\ 249 default-key \"%s\";\n\ 250 default-server %s;\n\ 251 default-port %d;\n\ 252 };\n\ 253 # End of rndc.conf\n\ 254 \n\ 255 # Use with the following in named.conf, adjusting the allow list as needed:\n\ 256 # key \"%s\" {\n\ 257 # algorithm %s;\n\ 258 # secret \"%.*s\";\n\ 259 # };\n\ 260 # \n\ 261 # controls {\n\ 262 # inet %s port %d\n\ 263 # allow { %s; } keys { \"%s\"; };\n\ 264 # };\n\ 265 # End of named.conf\n", 266 keyname, algname, 267 (int)isc_buffer_usedlength(&key_txtbuffer), 268 (char *)isc_buffer_base(&key_txtbuffer), 269 keyname, serveraddr, port, 270 keyname, algname, 271 (int)isc_buffer_usedlength(&key_txtbuffer), 272 (char *)isc_buffer_base(&key_txtbuffer), 273 serveraddr, port, serveraddr, keyname); 274 } 275 276 if (show_final_mem) 277 isc_mem_stats(mctx, stderr); 278 279 isc_mem_destroy(&mctx); 280 281 return (0); 282 } 283