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