1224090Sdougb/* 2262706Serwin * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") 3224090Sdougb * Copyright (C) 2001, 2003 Internet Software Consortium. 4224090Sdougb * 5224090Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6224090Sdougb * purpose with or without fee is hereby granted, provided that the above 7224090Sdougb * copyright notice and this permission notice appear in all copies. 8224090Sdougb * 9224090Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10224090Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11224090Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12224090Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13224090Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14224090Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15224090Sdougb * PERFORMANCE OF THIS SOFTWARE. 16224090Sdougb */ 17224090Sdougb 18254897Serwin/* $Id: rndc-confgen.c,v 1.7 2011/03/12 04:59:46 tbox Exp $ */ 19224090Sdougb 20224090Sdougb/*! \file */ 21224090Sdougb 22224090Sdougb/** 23224090Sdougb * rndc-confgen generates configuration files for rndc. It can be used 24224090Sdougb * as a convenient alternative to writing the rndc.conf file and the 25224090Sdougb * corresponding controls and key statements in named.conf by hand. 26224090Sdougb * Alternatively, it can be run with the -a option to set up a 27224090Sdougb * rndc.key file and avoid the need for a rndc.conf file and a 28224090Sdougb * controls statement altogether. 29224090Sdougb */ 30224090Sdougb 31224090Sdougb#include <config.h> 32224090Sdougb 33224090Sdougb#include <stdlib.h> 34224090Sdougb#include <stdarg.h> 35224090Sdougb 36224090Sdougb#include <isc/assertions.h> 37224090Sdougb#include <isc/base64.h> 38224090Sdougb#include <isc/buffer.h> 39224090Sdougb#include <isc/commandline.h> 40224090Sdougb#include <isc/entropy.h> 41224090Sdougb#include <isc/file.h> 42224090Sdougb#include <isc/keyboard.h> 43224090Sdougb#include <isc/mem.h> 44224090Sdougb#include <isc/net.h> 45224090Sdougb#include <isc/print.h> 46224090Sdougb#include <isc/result.h> 47224090Sdougb#include <isc/string.h> 48224090Sdougb#include <isc/time.h> 49224090Sdougb#include <isc/util.h> 50224090Sdougb 51224090Sdougb#include <dns/keyvalues.h> 52224090Sdougb#include <dns/name.h> 53224090Sdougb 54224090Sdougb#include <dst/dst.h> 55224090Sdougb#include <confgen/os.h> 56224090Sdougb 57224090Sdougb#include "util.h" 58224090Sdougb#include "keygen.h" 59224090Sdougb 60224090Sdougb#define DEFAULT_KEYLENGTH 128 /*% Bits. */ 61224090Sdougb#define DEFAULT_KEYNAME "rndc-key" 62224090Sdougb#define DEFAULT_SERVER "127.0.0.1" 63224090Sdougb#define DEFAULT_PORT 953 64224090Sdougb 65224090Sdougbstatic char program[256]; 66224090Sdougbconst char *progname; 67224090Sdougb 68224090Sdougbisc_boolean_t verbose = ISC_FALSE; 69224090Sdougb 70224090Sdougbconst char *keyfile, *keydef; 71224090Sdougb 72224090SdougbISC_PLATFORM_NORETURN_PRE static void 73224090Sdougbusage(int status) ISC_PLATFORM_NORETURN_POST; 74224090Sdougb 75224090Sdougbstatic void 76224090Sdougbusage(int status) { 77224090Sdougb 78224090Sdougb fprintf(stderr, "\ 79224090SdougbUsage:\n\ 80224090Sdougb %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ 81224090Sdougb[-s addr] [-t chrootdir] [-u user]\n\ 82224090Sdougb -a: generate just the key clause and write it to keyfile (%s)\n\ 83224090Sdougb -b bits: from 1 through 512, default %d; total length of the secret\n\ 84224090Sdougb -c keyfile: specify an alternate key file (requires -a)\n\ 85224090Sdougb -k keyname: the name as it will be used in named.conf and rndc.conf\n\ 86224090Sdougb -p port: the port named will listen on and rndc will connect to\n\ 87224090Sdougb -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ 88224090Sdougb -s addr: the address to which rndc should connect\n\ 89224090Sdougb -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ 90224090Sdougb -u user: set the keyfile owner to \"user\" (requires -a)\n", 91224090Sdougb progname, keydef, DEFAULT_KEYLENGTH); 92224090Sdougb 93224090Sdougb exit (status); 94224090Sdougb} 95224090Sdougb 96224090Sdougbint 97224090Sdougbmain(int argc, char **argv) { 98224090Sdougb isc_boolean_t show_final_mem = ISC_FALSE; 99224090Sdougb isc_buffer_t key_txtbuffer; 100224090Sdougb char key_txtsecret[256]; 101224090Sdougb isc_mem_t *mctx = NULL; 102224090Sdougb isc_result_t result = ISC_R_SUCCESS; 103224090Sdougb const char *keyname = NULL; 104224090Sdougb const char *randomfile = NULL; 105224090Sdougb const char *serveraddr = NULL; 106224090Sdougb dns_secalg_t alg = DST_ALG_HMACMD5; 107224090Sdougb const char *algname = alg_totext(alg); 108224090Sdougb char *p; 109224090Sdougb int ch; 110224090Sdougb int port; 111224090Sdougb int keysize; 112224090Sdougb struct in_addr addr4_dummy; 113224090Sdougb struct in6_addr addr6_dummy; 114224090Sdougb char *chrootdir = NULL; 115224090Sdougb char *user = NULL; 116224090Sdougb isc_boolean_t keyonly = ISC_FALSE; 117224090Sdougb int len; 118224090Sdougb 119224090Sdougb keydef = keyfile = RNDC_KEYFILE; 120224090Sdougb 121224090Sdougb result = isc_file_progname(*argv, program, sizeof(program)); 122224090Sdougb if (result != ISC_R_SUCCESS) 123262706Serwin memmove(program, "rndc-confgen", 13); 124224090Sdougb progname = program; 125224090Sdougb 126224090Sdougb keyname = DEFAULT_KEYNAME; 127224090Sdougb keysize = DEFAULT_KEYLENGTH; 128224090Sdougb serveraddr = DEFAULT_SERVER; 129224090Sdougb port = DEFAULT_PORT; 130224090Sdougb 131224090Sdougb isc_commandline_errprint = ISC_FALSE; 132224090Sdougb 133224090Sdougb while ((ch = isc_commandline_parse(argc, argv, 134224090Sdougb "ab:c:hk:Mmp:r:s:t:u:Vy")) != -1) { 135224090Sdougb switch (ch) { 136224090Sdougb case 'a': 137224090Sdougb keyonly = ISC_TRUE; 138224090Sdougb break; 139224090Sdougb case 'b': 140224090Sdougb keysize = strtol(isc_commandline_argument, &p, 10); 141224090Sdougb if (*p != '\0' || keysize < 0) 142224090Sdougb fatal("-b requires a non-negative number"); 143224090Sdougb break; 144224090Sdougb case 'c': 145224090Sdougb keyfile = isc_commandline_argument; 146224090Sdougb break; 147224090Sdougb case 'h': 148224090Sdougb usage(0); 149224090Sdougb case 'k': 150224090Sdougb case 'y': /* Compatible with rndc -y. */ 151224090Sdougb keyname = isc_commandline_argument; 152224090Sdougb break; 153224090Sdougb case 'M': 154224090Sdougb isc_mem_debugging = ISC_MEM_DEBUGTRACE; 155224090Sdougb break; 156224090Sdougb 157224090Sdougb case 'm': 158224090Sdougb show_final_mem = ISC_TRUE; 159224090Sdougb break; 160224090Sdougb case 'p': 161224090Sdougb port = strtol(isc_commandline_argument, &p, 10); 162224090Sdougb if (*p != '\0' || port < 0 || port > 65535) 163224090Sdougb fatal("port '%s' out of range", 164224090Sdougb isc_commandline_argument); 165224090Sdougb break; 166224090Sdougb case 'r': 167224090Sdougb randomfile = isc_commandline_argument; 168224090Sdougb break; 169224090Sdougb case 's': 170224090Sdougb serveraddr = isc_commandline_argument; 171224090Sdougb if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && 172224090Sdougb inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) 173224090Sdougb fatal("-s should be an IPv4 or IPv6 address"); 174224090Sdougb break; 175224090Sdougb case 't': 176224090Sdougb chrootdir = isc_commandline_argument; 177224090Sdougb break; 178224090Sdougb case 'u': 179224090Sdougb user = isc_commandline_argument; 180224090Sdougb break; 181224090Sdougb case 'V': 182224090Sdougb verbose = ISC_TRUE; 183224090Sdougb break; 184224090Sdougb case '?': 185224090Sdougb if (isc_commandline_option != '?') { 186224090Sdougb fprintf(stderr, "%s: invalid argument -%c\n", 187224090Sdougb program, isc_commandline_option); 188224090Sdougb usage(1); 189224090Sdougb } else 190224090Sdougb usage(0); 191224090Sdougb break; 192224090Sdougb default: 193224090Sdougb fprintf(stderr, "%s: unhandled option -%c\n", 194224090Sdougb program, isc_commandline_option); 195224090Sdougb exit(1); 196224090Sdougb } 197224090Sdougb } 198224090Sdougb 199224090Sdougb argc -= isc_commandline_index; 200224090Sdougb argv += isc_commandline_index; 201225361Sdougb POST(argv); 202224090Sdougb 203224090Sdougb if (argc > 0) 204224090Sdougb usage(1); 205224090Sdougb 206224090Sdougb DO("create memory context", isc_mem_create(0, 0, &mctx)); 207224090Sdougb isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 208224090Sdougb 209224090Sdougb generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); 210224090Sdougb 211224090Sdougb if (keyonly) { 212224090Sdougb write_key_file(keyfile, chrootdir == NULL ? user : NULL, 213224090Sdougb keyname, &key_txtbuffer, alg); 214224090Sdougb 215224090Sdougb if (chrootdir != NULL) { 216224090Sdougb char *buf; 217224090Sdougb len = strlen(chrootdir) + strlen(keyfile) + 2; 218224090Sdougb buf = isc_mem_get(mctx, len); 219224090Sdougb if (buf == NULL) 220224090Sdougb fatal("isc_mem_get(%d) failed\n", len); 221224090Sdougb snprintf(buf, len, "%s%s%s", chrootdir, 222224090Sdougb (*keyfile != '/') ? "/" : "", keyfile); 223224090Sdougb 224224090Sdougb write_key_file(buf, user, keyname, &key_txtbuffer, alg); 225224090Sdougb isc_mem_put(mctx, buf, len); 226224090Sdougb } 227224090Sdougb } else { 228224090Sdougb printf("\ 229224090Sdougb# Start of rndc.conf\n\ 230224090Sdougbkey \"%s\" {\n\ 231224090Sdougb algorithm %s;\n\ 232224090Sdougb secret \"%.*s\";\n\ 233224090Sdougb};\n\ 234224090Sdougb\n\ 235224090Sdougboptions {\n\ 236224090Sdougb default-key \"%s\";\n\ 237224090Sdougb default-server %s;\n\ 238224090Sdougb default-port %d;\n\ 239224090Sdougb};\n\ 240224090Sdougb# End of rndc.conf\n\ 241224090Sdougb\n\ 242224090Sdougb# Use with the following in named.conf, adjusting the allow list as needed:\n\ 243224090Sdougb# key \"%s\" {\n\ 244224090Sdougb# algorithm %s;\n\ 245224090Sdougb# secret \"%.*s\";\n\ 246224090Sdougb# };\n\ 247224090Sdougb# \n\ 248224090Sdougb# controls {\n\ 249224090Sdougb# inet %s port %d\n\ 250224090Sdougb# allow { %s; } keys { \"%s\"; };\n\ 251224090Sdougb# };\n\ 252224090Sdougb# End of named.conf\n", 253224090Sdougb keyname, algname, 254224090Sdougb (int)isc_buffer_usedlength(&key_txtbuffer), 255224090Sdougb (char *)isc_buffer_base(&key_txtbuffer), 256224090Sdougb keyname, serveraddr, port, 257224090Sdougb keyname, algname, 258224090Sdougb (int)isc_buffer_usedlength(&key_txtbuffer), 259224090Sdougb (char *)isc_buffer_base(&key_txtbuffer), 260224090Sdougb serveraddr, port, serveraddr, keyname); 261224090Sdougb } 262224090Sdougb 263224090Sdougb if (show_final_mem) 264224090Sdougb isc_mem_stats(mctx, stderr); 265224090Sdougb 266224090Sdougb isc_mem_destroy(&mctx); 267224090Sdougb 268224090Sdougb return (0); 269224090Sdougb} 270