1 /* $NetBSD: ddns-confgen.c,v 1.8 2014/12/10 04:37:51 christos Exp $ */
4 * Copyright (C) 2009, 2011, 2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
22 * ddns-confgen generates configuration files for dynamic DNS. It can
23 * be used as a convenient alternative to writing the ddns.key file
24 * and the corresponding key and update-policy statements in named.conf.
32 #include <isc/assertions.h>
33 #include <isc/base64.h>
34 #include <isc/buffer.h>
35 #include <isc/commandline.h>
36 #include <isc/entropy.h>
38 #include <isc/keyboard.h>
41 #include <isc/print.h>
42 #include <isc/result.h>
43 #include <isc/string.h>
48 #include <pk11/result.h>
51 #include <dns/keyvalues.h>
53 #include <dns/result.h>
56 #include <confgen/os.h>
61 #define KEYGEN_DEFAULT "tsig-key"
62 #define CONFGEN_DEFAULT "ddns-key"
64 static char program
[256];
66 static enum { progmode_keygen
, progmode_confgen
} progmode
;
67 isc_boolean_t verbose
= ISC_FALSE
; /* needed by util.c but not used here */
69 ISC_PLATFORM_NORETURN_PRE
static void
70 usage(int status
) ISC_PLATFORM_NORETURN_POST
;
74 if (progmode
== progmode_confgen
) {
77 %s [-a alg] [-k keyname] [-r randomfile] [-q] [-s name | -z zone]\n\
78 -a alg: algorithm (default hmac-sha256)\n\
79 -k keyname: name of the key as it will be used in named.conf\n\
80 -r randomfile: source of random data (use \"keyboard\" for key timing)\n\
81 -s name: domain name to be updated using the created key\n\
82 -z zone: name of the zone as it will be used in named.conf\n\
83 -q: quiet mode: print the key, with no explanatory text\n",
88 %s [-a alg] [-r randomfile] [keyname]\n\
89 -a alg: algorithm (default hmac-sha256)\n\
90 -r randomfile: source of random data (use \"keyboard\" for key timing)\n",
98 main(int argc
, char **argv
) {
99 isc_result_t result
= ISC_R_SUCCESS
;
100 isc_boolean_t show_final_mem
= ISC_FALSE
;
101 isc_boolean_t quiet
= ISC_FALSE
;
102 isc_buffer_t key_txtbuffer
;
103 char key_txtsecret
[256];
104 isc_mem_t
*mctx
= NULL
;
105 const char *randomfile
= NULL
;
106 const char *keyname
= NULL
;
107 const char *zone
= NULL
;
108 const char *self_domain
= NULL
;
110 dns_secalg_t alg
= DST_ALG_HMACSHA256
;
117 pk11_result_register();
119 dns_result_register();
121 result
= isc_file_progname(*argv
, program
, sizeof(program
));
122 if (result
!= ISC_R_SUCCESS
)
123 memmove(program
, "tsig-keygen", 11);
127 * Libtool doesn't preserve the program name prior to final
128 * installation. Remove the libtool prefix ("lt-").
130 if (strncmp(progname
, "lt-", 3) == 0)
134 (strcasecmp(progname, X) == 0 || strcasecmp(progname, X ".exe") == 0)
136 if (PROGCMP("tsig-keygen")) {
137 progmode
= progmode_keygen
;
139 } else if (PROGCMP("ddns-confgen"))
140 progmode
= progmode_confgen
;
144 isc_commandline_errprint
= ISC_FALSE
;
146 while ((ch
= isc_commandline_parse(argc
, argv
,
147 "a:hk:Mmr:qs:y:z:")) != -1) {
150 algname
= isc_commandline_argument
;
151 alg
= alg_fromtext(algname
);
152 if (alg
== DST_ALG_UNKNOWN
)
153 fatal("Unsupported algorithm '%s'", algname
);
154 keysize
= alg_bits(alg
);
160 if (progmode
== progmode_confgen
)
161 keyname
= isc_commandline_argument
;
166 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
;
169 show_final_mem
= ISC_TRUE
;
172 if (progmode
== progmode_confgen
)
178 randomfile
= isc_commandline_argument
;
181 if (progmode
== progmode_confgen
)
182 self_domain
= isc_commandline_argument
;
187 if (progmode
== progmode_confgen
)
188 zone
= isc_commandline_argument
;
193 if (isc_commandline_option
!= '?') {
194 fprintf(stderr
, "%s: invalid argument -%c\n",
195 program
, isc_commandline_option
);
201 fprintf(stderr
, "%s: unhandled option -%c\n",
202 program
, isc_commandline_option
);
207 if (progmode
== progmode_keygen
)
208 keyname
= argv
[isc_commandline_index
++];
212 if (self_domain
!= NULL
&& zone
!= NULL
)
213 usage(1); /* -s and -z cannot coexist */
215 if (argc
> isc_commandline_index
)
218 /* Use canonical algorithm name */
219 algname
= alg_totext(alg
);
221 DO("create memory context", isc_mem_create(0, 0, &mctx
));
223 if (keyname
== NULL
) {
224 const char *suffix
= NULL
;
226 keyname
= ((progmode
== progmode_keygen
)
229 if (self_domain
!= NULL
)
230 suffix
= self_domain
;
231 else if (zone
!= NULL
)
233 if (suffix
!= NULL
) {
234 len
= strlen(keyname
) + strlen(suffix
) + 2;
235 keybuf
= isc_mem_get(mctx
, len
);
237 fatal("failed to allocate memory for keyname");
238 snprintf(keybuf
, len
, "%s.%s", keyname
, suffix
);
239 keyname
= (const char *) keybuf
;
243 isc_buffer_init(&key_txtbuffer
, &key_txtsecret
, sizeof(key_txtsecret
));
245 generate_key(mctx
, randomfile
, alg
, keysize
, &key_txtbuffer
);
250 # To activate this key, place the following in named.conf, and\n\
251 # in a separate keyfile on the system or systems from which nsupdate\n\
260 (int)isc_buffer_usedlength(&key_txtbuffer
),
261 (char *)isc_buffer_base(&key_txtbuffer
));
264 if (self_domain
!= NULL
) {
266 # Then, in the \"zone\" statement for the zone containing the\n\
267 # name \"%s\", place an \"update-policy\" statement\n\
268 # like this one, adjusted as needed for your preferred permissions:\n\
270 grant %s name %s ANY;\n\
272 self_domain
, keyname
, self_domain
);
273 } else if (zone
!= NULL
) {
275 # Then, in the \"zone\" definition statement for \"%s\",\n\
276 # place an \"update-policy\" statement like this one, adjusted as \n\
277 # needed for your preferred permissions:\n\
279 grant %s zonesub ANY;\n\
284 # Then, in the \"zone\" statement for each zone you wish to dynamically\n\
285 # update, place an \"update-policy\" statement granting update permission\n\
286 # to this key. For example, the following statement grants this key\n\
287 # permission to update any name within the zone:\n\
289 grant %s zonesub ANY;\n\
295 # After the keyfile has been placed, the following command will\n\
296 # execute nsupdate using this key:\n\
297 nsupdate -k <keyfile>\n");
302 isc_mem_put(mctx
, keybuf
, len
);
305 isc_mem_stats(mctx
, stderr
);
307 isc_mem_destroy(&mctx
);