2 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.
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.
18 /* $Id: rndc-confgen.c,v 1.18.18.3 2005/04/29 00:15:40 marka Exp $ */
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.
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>
42 #include <isc/keyboard.h>
45 #include <isc/print.h>
46 #include <isc/result.h>
47 #include <isc/string.h>
51 #include <dns/keyvalues.h>
59 #define DEFAULT_KEYLENGTH 128 /*% Bits. */
60 #define DEFAULT_KEYNAME "rndc-key"
61 #define DEFAULT_SERVER "127.0.0.1"
62 #define DEFAULT_PORT 953
64 static char program
[256];
67 isc_boolean_t verbose
= ISC_FALSE
;
69 const char *keyfile
, *keydef
;
76 %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \
77 [-s addr] [-t chrootdir] [-u user]\n\
78 -a: generate just the key clause and write it to keyfile (%s)\n\
79 -b bits: from 1 through 512, default %d; total length of the secret\n\
80 -c keyfile: specify an alternate key file (requires -a)\n\
81 -k keyname: the name as it will be used in named.conf and rndc.conf\n\
82 -p port: the port named will listen on and rndc will connect to\n\
83 -r randomfile: a file containing random data\n\
84 -s addr: the address to which rndc should connect\n\
85 -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\
86 -u user: set the keyfile owner to \"user\" (requires -a)\n",
87 progname
, keydef
, DEFAULT_KEYLENGTH
);
93 * Write an rndc.key file to 'keyfile'. If 'user' is non-NULL,
94 * make that user the owner of the file. The key will have
95 * the name 'keyname' and the secret in the buffer 'secret'.
98 write_key_file(const char *keyfile
, const char *user
,
99 const char *keyname
, isc_buffer_t
*secret
)
103 fd
= safe_create(keyfile
);
105 fatal( "unable to create \"%s\"\n", keyfile
);
107 if (set_user(fd
, user
) == -1)
108 fatal("unable to set file owner\n");
110 fprintf(fd
, "key \"%s\" {\n\talgorithm hmac-md5;\n"
111 "\tsecret \"%.*s\";\n};\n", keyname
,
112 (int)isc_buffer_usedlength(secret
),
113 (char *)isc_buffer_base(secret
));
116 fatal("write to %s failed\n", keyfile
);
118 fatal("fclose(%s) failed\n", keyfile
);
119 fprintf(stderr
, "wrote key file \"%s\"\n", keyfile
);
123 main(int argc
, char **argv
) {
124 isc_boolean_t show_final_mem
= ISC_FALSE
;
125 isc_buffer_t key_rawbuffer
;
126 isc_buffer_t key_txtbuffer
;
127 isc_region_t key_rawregion
;
128 isc_mem_t
*mctx
= NULL
;
129 isc_entropy_t
*ectx
= NULL
;
130 isc_entropysource_t
*entropy_source
= NULL
;
131 isc_result_t result
= ISC_R_SUCCESS
;
132 dst_key_t
*key
= NULL
;
133 const char *keyname
= NULL
;
134 const char *randomfile
= NULL
;
135 const char *serveraddr
= NULL
;
136 char key_rawsecret
[64];
137 char key_txtsecret
[256];
142 int entropy_flags
= 0;
143 int open_keyboard
= ISC_ENTROPY_KEYBOARDMAYBE
;
144 struct in_addr addr4_dummy
;
145 struct in6_addr addr6_dummy
;
146 char *chrootdir
= NULL
;
148 isc_boolean_t keyonly
= ISC_FALSE
;
151 keydef
= keyfile
= RNDC_KEYFILE
;
153 result
= isc_file_progname(*argv
, program
, sizeof(program
));
154 if (result
!= ISC_R_SUCCESS
)
155 memcpy(program
, "rndc-confgen", 13);
158 keyname
= DEFAULT_KEYNAME
;
159 keysize
= DEFAULT_KEYLENGTH
;
160 serveraddr
= DEFAULT_SERVER
;
163 while ((ch
= isc_commandline_parse(argc
, argv
,
164 "ab:c:hk:Mmp:r:s:t:u:Vy")) != -1) {
170 keysize
= strtol(isc_commandline_argument
, &p
, 10);
171 if (*p
!= '\0' || keysize
< 0)
172 fatal("-b requires a non-negative number");
173 if (keysize
< 1 || keysize
> 512)
174 fatal("-b must be in the range 1 through 512");
177 keyfile
= isc_commandline_argument
;
182 case 'y': /* Compatible with rndc -y. */
183 keyname
= isc_commandline_argument
;
186 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
;
190 show_final_mem
= ISC_TRUE
;
193 port
= strtol(isc_commandline_argument
, &p
, 10);
194 if (*p
!= '\0' || port
< 0 || port
> 65535)
195 fatal("port '%s' out of range",
196 isc_commandline_argument
);
199 randomfile
= isc_commandline_argument
;
202 serveraddr
= isc_commandline_argument
;
203 if (inet_pton(AF_INET
, serveraddr
, &addr4_dummy
) != 1 &&
204 inet_pton(AF_INET6
, serveraddr
, &addr6_dummy
) != 1)
205 fatal("-s should be an IPv4 or IPv6 address");
208 chrootdir
= isc_commandline_argument
;
211 user
= isc_commandline_argument
;
220 fatal("unexpected error parsing command arguments: "
226 argc
-= isc_commandline_index
;
227 argv
+= isc_commandline_index
;
232 DO("create memory context", isc_mem_create(0, 0, &mctx
));
234 DO("create entropy context", isc_entropy_create(mctx
, &ectx
));
236 if (randomfile
!= NULL
&& strcmp(randomfile
, "keyboard") == 0) {
238 open_keyboard
= ISC_ENTROPY_KEYBOARDYES
;
240 DO("start entropy source", isc_entropy_usebestsource(ectx
,
245 entropy_flags
= ISC_ENTROPY_BLOCKING
| ISC_ENTROPY_GOODONLY
;
247 DO("initialize dst library", dst_lib_init(mctx
, ectx
, entropy_flags
));
249 DO("generate key", dst_key_generate(dns_rootname
, DST_ALG_HMACMD5
,
252 dns_rdataclass_in
, mctx
, &key
));
254 isc_buffer_init(&key_rawbuffer
, &key_rawsecret
, sizeof(key_rawsecret
));
256 DO("dump key to buffer", dst_key_tobuffer(key
, &key_rawbuffer
));
258 isc_buffer_init(&key_txtbuffer
, &key_txtsecret
, sizeof(key_txtsecret
));
259 isc_buffer_usedregion(&key_rawbuffer
, &key_rawregion
);
261 DO("bsse64 encode secret", isc_base64_totext(&key_rawregion
, -1, "",
265 * Shut down the entropy source now so the "stop typing" message
266 * does not muck with the output.
268 if (entropy_source
!= NULL
)
269 isc_entropy_destroysource(&entropy_source
);
274 isc_entropy_detach(&ectx
);
278 write_key_file(keyfile
, chrootdir
== NULL
? user
: NULL
,
279 keyname
, &key_txtbuffer
);
281 if (chrootdir
!= NULL
) {
283 len
= strlen(chrootdir
) + strlen(keyfile
) + 2;
284 buf
= isc_mem_get(mctx
, len
);
286 fatal("isc_mem_get(%d) failed\n", len
);
287 snprintf(buf
, len
, "%s%s%s", chrootdir
,
288 (*keyfile
!= '/') ? "/" : "", keyfile
);
290 write_key_file(buf
, user
, keyname
, &key_txtbuffer
);
291 isc_mem_put(mctx
, buf
, len
);
295 # Start of rndc.conf\n\
297 algorithm hmac-md5;\n\
302 default-key \"%s\";\n\
303 default-server %s;\n\
306 # End of rndc.conf\n\
308 # Use with the following in named.conf, adjusting the allow list as needed:\n\
310 # algorithm hmac-md5;\n\
311 # secret \"%.*s\";\n\
316 # allow { %s; } keys { \"%s\"; };\n\
318 # End of named.conf\n",
320 (int)isc_buffer_usedlength(&key_txtbuffer
),
321 (char *)isc_buffer_base(&key_txtbuffer
),
322 keyname
, serveraddr
, port
,
324 (int)isc_buffer_usedlength(&key_txtbuffer
),
325 (char *)isc_buffer_base(&key_txtbuffer
),
326 serveraddr
, port
, serveraddr
, keyname
);
330 isc_mem_stats(mctx
, stderr
);
332 isc_mem_destroy(&mctx
);