diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c index 3b16a121ba..627c3db5f8 100644 --- a/bin/named/controlconf.c +++ b/bin/named/controlconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: controlconf.c,v 1.17 2001/07/23 01:01:31 bwelling Exp $ */ +/* $Id: controlconf.c,v 1.18 2001/08/03 05:56:19 marka Exp $ */ #include @@ -100,17 +100,6 @@ struct controllistener { ISC_LINK(controllistener_t) link; }; -static struct { - char name[64]; - char secret[192]; - cfg_parser_t *parser; - cfg_obj_t *config; - isc_sockaddr_t address; /* Last channel that needed automagic. */ -} automagic_key; - -#define NS_AUTOKEY_BITS 128 -#define NS_AUTOKEY_NAME "control_autokey" - struct ns_controls { ns_server_t *server; controllistenerlist_t listeners; @@ -647,7 +636,7 @@ controlkeylist_fromcfg(cfg_obj_t *keylist, isc_mem_t *mctx, static void register_keys(cfg_obj_t *control, cfg_obj_t *keylist, - controlkeylist_t *keyids, isc_mem_t *mctx, char *socktext) + controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) { controlkey_t *keyid, *next; cfg_obj_t *keydef; @@ -725,288 +714,119 @@ register_keys(cfg_obj_t *control, cfg_obj_t *keylist, } } +#define CHECK(x) \ + do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + static isc_result_t -make_automagic_key(isc_mem_t *mctx) { - unsigned char key_rawsecret[32]; - unsigned char key_txtsecret[32]; - isc_buffer_t key_rawbuffer; - isc_buffer_t key_txtbuffer; - isc_region_t key_rawregion; - isc_uint32_t key_id; +get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { isc_result_t result; - dst_key_t *key = NULL; + cfg_parser_t *pctx = NULL; + cfg_obj_t *config = NULL; + cfg_obj_t *key = NULL; + cfg_obj_t *algobj = NULL; + cfg_obj_t *secretobj = NULL; + char *algstr = NULL; + char *secretstr = NULL; + controlkey_t *keyid = NULL; + char secret[1024]; + isc_buffer_t b; - /* - * First generate a secret. The fourth parameter non-zero means - * that pseudorandom data is ok; good entropy is not required. - */ - result = dst_key_generate(dns_rootname, DST_ALG_HMACMD5, - NS_AUTOKEY_BITS, 1, 0, DNS_KEYPROTO_ANY, - dns_rdataclass_in, mctx, &key); + CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx)); + CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config)); + CHECK(cfg_map_get(config, "key", &key)); - if (result == ISC_R_SUCCESS) { - isc_buffer_init(&key_rawbuffer, &key_rawsecret, - sizeof(key_rawsecret)); - result = dst_key_tobuffer(key, &key_rawbuffer); + keyid = isc_mem_get(mctx, sizeof(*keyid)); + if (keyid == NULL) + CHECK(ISC_R_NOMEMORY); + keyid->keyname = isc_mem_strdup(mctx, + cfg_obj_asstring(cfg_map_getname(key))); + keyid->secret.base = NULL; + keyid->secret.length = 0; + ISC_LINK_INIT(keyid, link); + if (keyid->keyname == NULL) + CHECK(ISC_R_NOMEMORY); + + (void)cfg_map_get(key, "algorithm", &algobj); + (void)cfg_map_get(key, "secret", &secretobj); + INSIST(algobj != NULL && secretobj != NULL); + + algstr = cfg_obj_asstring(algobj); + secretstr = cfg_obj_asstring(secretobj); + + if (strcasecmp(algstr, "hmac-md5") != 0) { + cfg_obj_log(key, ns_g_lctx, + ISC_LOG_WARNING, + "unsupported algorithm '%s' in " + "key '%s' for use with command " + "channel", + algstr, keyid->keyname); + goto cleanup; } - if (result == ISC_R_SUCCESS) { - isc_buffer_init(&key_txtbuffer, &key_txtsecret, - sizeof(key_txtsecret)); - isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); - result = isc_base64_totext(&key_rawregion, -1, "", - &key_txtbuffer); + isc_buffer_init(&b, secret, sizeof(secret)); + result = isc_base64_decodestring(secretstr, &b); + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, + "secret for key '%s' on command channel: %s", + keyid->keyname, isc_result_totext(result)); + CHECK(result); } - if (result == ISC_R_SUCCESS) { - unsigned int len = isc_buffer_usedlength(&key_txtbuffer); - - INSIST(len < sizeof(automagic_key.secret)); - - memcpy(automagic_key.secret, isc_buffer_base(&key_txtbuffer), - len); - automagic_key.secret[len] = '\0'; - - /* - * Make a random name for the key and generate the config - * file statement for it. - */ - isc_random_get(&key_id); - len = snprintf(automagic_key.name, sizeof(automagic_key.name), - NS_AUTOKEY_NAME ".%u", key_id); - INSIST(len < sizeof(automagic_key.name)); + keyid->secret.length = isc_buffer_usedlength(&b); + keyid->secret.base = isc_mem_get(mctx, + keyid->secret.length); + if (keyid->secret.base == NULL) { + cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, + "couldn't register key '%s': " + "out of memory", keyid->keyname); + CHECK(ISC_R_NOMEMORY); } + memcpy(keyid->secret.base, isc_buffer_base(&b), + keyid->secret.length); + ISC_LIST_APPEND(*keyids, keyid, link); + keyid = NULL; + result = ISC_R_SUCCESS; - if (key != NULL) - dst_key_free(&key); - - if (result != ISC_R_SUCCESS) - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, - "could not generate control channel key: %s", - isc_result_totext(result)); - + cleanup: + if (keyid != NULL) + free_controlkey(keyid, mctx); + if (config != NULL) + cfg_obj_destroy(pctx, &config); + if (pctx != NULL) + cfg_parser_destroy(&pctx); return (result); } - -static void -format_automagic_keycfg(isc_buffer_t *conf) { - unsigned int len; - - len = snprintf(isc_buffer_base(conf), isc_buffer_length(conf), - "key \"%s\" {\n" - "\talgorithm hmac-md5;\n" - "\tsecret \"%s\";\n" - "};\n", - automagic_key.name, automagic_key.secret); - - INSIST(len < isc_buffer_length(conf)); - - isc_buffer_add(conf, len); -} - -static isc_result_t -parse_automagic_key(isc_mem_t *mctx) { - unsigned int len; - char cfg_data[512]; - isc_buffer_t cfg_buffer; - isc_result_t result = ISC_R_SUCCESS; - cfg_obj_t *cfg = NULL; - cfg_parser_t *parser = NULL; - - if (automagic_key.name[0] == '\0') - result = make_automagic_key(mctx); - - if (result == ISC_R_SUCCESS) { - /* - * Fake up a configuration with a dummy inet control - * to grab the keylist tuple. - */ - isc_buffer_init(&cfg_buffer, cfg_data, sizeof(cfg_data)); - format_automagic_keycfg(&cfg_buffer); - len = snprintf(isc_buffer_used(&cfg_buffer), - isc_buffer_availablelength(&cfg_buffer), - "controls { inet 127.0.0.1 allow { localhost; }" - " keys { %s; }; };", - automagic_key.name); - INSIST(len < isc_buffer_availablelength(&cfg_buffer)); - isc_buffer_add(&cfg_buffer, len); - - result = cfg_parser_create(mctx, ns_g_lctx, &parser); - } - - if (result == ISC_R_SUCCESS) - result = cfg_parse_buffer(parser, &cfg_buffer, - &cfg_type_namedconf, &cfg); - - if (result == ISC_R_SUCCESS) { - automagic_key.parser = parser; - automagic_key.config = cfg; - } else { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, - "could not parse autogenerated " - "control channel key: %s", - isc_result_totext(result)); - - if (parser != NULL) - cfg_parser_destroy(&parser); - } - - return (result); -} - -static void -finalize_automagic_key(void) { - unsigned int fsaccess; - int i; - FILE *fp; - isc_result_t result; - - (void)isc_file_remove(ns_g_autorndckeyfile); - - if (automagic_key.parser != NULL) { - /* - * An automagic key was parsed, so some channel needed it. - * Try to write the rndc.conf file. - */ - char cfg_data[512]; - char nettext[ISC_NETADDR_FORMATSIZE]; - isc_buffer_t cfg_buffer; - isc_netaddr_t netaddr; - - - result = isc_stdio_open(ns_g_autorndckeyfile, "w", &fp); - - if (result == ISC_R_SUCCESS) { - fsaccess = 0; - isc_fsaccess_add(ISC_FSACCESS_OWNER, ISC_FSACCESS_READ, - &fsaccess); - result = isc_fsaccess_set(ns_g_autorndckeyfile, - fsaccess); - - if (result != ISC_R_SUCCESS) { - isc_log_write(ns_g_lctx, - NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_CONTROL, - ISC_LOG_WARNING, - "could not set owner-only " - "access on %s: %s: " - "server control key might be " - "exposed to local users", - ns_g_autorndckeyfile, - isc_result_totext(result)); - } - - isc_buffer_init(&cfg_buffer, cfg_data, - sizeof(cfg_data)); - format_automagic_keycfg(&cfg_buffer); - - isc_netaddr_fromsockaddr(&netaddr, - &automagic_key.address); - isc_netaddr_format(&netaddr, nettext, sizeof(nettext)); - - i = fputs(isc_buffer_base(&cfg_buffer), fp); - - if (i != EOF) - i = fprintf(fp, "options {\n" - "\tdefault-server %s;\n" - "\tdefault-port %hu;\n" - "\tdefault-key \"%s\";\n" - "};\n", - nettext, - isc_sockaddr_getport( - &automagic_key.address), - automagic_key.name); - - if (i == EOF) - isc_log_write(ns_g_lctx, - NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_CONTROL, - ISC_LOG_WARNING, - "could not write %s", - ns_g_autorndckeyfile); - - result = isc_stdio_close(fp); - if (result != ISC_R_SUCCESS) - isc_log_write(ns_g_lctx, - NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_CONTROL, - ISC_LOG_WARNING, - "error closing %s: %s", - ns_g_autorndckeyfile, - isc_result_totext(result)); - } - - cfg_obj_destroy(automagic_key.parser, &automagic_key.config); - cfg_parser_destroy(&automagic_key.parser); - } -} static void -get_key_info(isc_mem_t *mctx, cfg_obj_t *config, cfg_obj_t *control, - cfg_obj_t **global_keylistp, cfg_obj_t **control_keylistp, - isc_boolean_t *explicit_key) +get_key_info(cfg_obj_t *config, cfg_obj_t *control, + cfg_obj_t **global_keylistp, cfg_obj_t **control_keylistp) { cfg_obj_t *control_keylist = NULL; cfg_obj_t *global_keylist = NULL; - isc_result_t result = ISC_R_SUCCESS; REQUIRE(global_keylistp != NULL && *global_keylistp == NULL); REQUIRE(control_keylistp != NULL && *control_keylistp == NULL); control_keylist = cfg_tuple_get(control, "keys"); - if (cfg_obj_isvoid(control_keylist) || - cfg_list_first(control_keylist) == NULL) { - cfg_obj_t *controls = NULL; - cfg_obj_t *inet = NULL; + if (!cfg_obj_isvoid(control_keylist) && + cfg_list_first(control_keylist) != NULL) + cfg_map_get(config, "key", &global_keylist); - if (automagic_key.parser == NULL) - result = parse_automagic_key(mctx); - - if (result == ISC_R_SUCCESS) { - config = automagic_key.config; - - /* - * All of these should succeed. - */ - (void)cfg_map_get(config, "key", &global_keylist); - INSIST(global_keylist != NULL); - - (void)cfg_map_get(config, "controls", &controls); - INSIST(controls != NULL); - (void)cfg_map_get(cfg_listelt_value - (cfg_list_first(controls)), - "inet", &inet); - INSIST(inet != NULL); - control_keylist = - cfg_tuple_get(cfg_listelt_value - (cfg_list_first(inet)), "keys"); - INSIST(control_keylist != NULL); - } - - *explicit_key = ISC_FALSE; - - } else { - result = cfg_map_get(config, "key", &global_keylist); - *explicit_key = config != automagic_key.config - ? ISC_TRUE : ISC_FALSE; - } - - if (result == ISC_R_SUCCESS) { - *global_keylistp = global_keylist; - *control_keylistp = control_keylist; - } else - cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, - "no key statements for use by control channel"); + *global_keylistp = global_keylist; + *control_keylistp = control_keylist; } static void update_listener(ns_controls_t *cp, controllistener_t **listenerp, cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr, - ns_aclconfctx_t *aclconfctx, char *socktext) + ns_aclconfctx_t *aclconfctx, const char *socktext) { controllistener_t *listener; cfg_obj_t *allow; @@ -1014,7 +834,6 @@ update_listener(ns_controls_t *cp, cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; controlkeylist_t keys; - isc_boolean_t explicit_key; isc_result_t result = ISC_R_SUCCESS; for (listener = ISC_LIST_HEAD(cp->listeners); @@ -1049,8 +868,7 @@ update_listener(ns_controls_t *cp, * and not able to be decrypted by the client. For this reason, * the automagic key is not regenerated on each reload. */ - get_key_info(listener->mctx, config, control, - &global_keylist, &control_keylist, &explicit_key); + get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { INSIST(global_keylist != NULL); @@ -1058,18 +876,18 @@ update_listener(ns_controls_t *cp, ISC_LIST_INIT(keys); result = controlkeylist_fromcfg(control_keylist, listener->mctx, &keys); + if (result) { + free_controlkeylist(&listener->keys, listener->mctx); + listener->keys = keys; + register_keys(control, global_keylist, &listener->keys, + listener->mctx, socktext); + } + } else { + free_controlkeylist(&listener->keys, listener->mctx); + result = get_rndckey(listener->mctx, &listener->keys); } - if (result == ISC_R_SUCCESS) { - free_controlkeylist(&listener->keys, listener->mctx); - listener->keys = keys; - register_keys(control, global_keylist, &listener->keys, - listener->mctx, socktext); - - if (! explicit_key) - automagic_key.address = listener->address; - - } else if (global_keylist != NULL) + if (result != ISC_R_SUCCESS && global_keylist != NULL) /* * This message might be a little misleading since the * "new keys" might in fact be identical to the old ones, @@ -1085,9 +903,20 @@ update_listener(ns_controls_t *cp, /* * Now, keep the old access list unless a new one can be made. */ - allow = cfg_tuple_get(control, "allow"); - result = ns_acl_fromconfig(allow, config, aclconfctx, - listener->mctx, &new_acl); + if (control != NULL) { + allow = cfg_tuple_get(control, "allow"); + result = ns_acl_fromconfig(allow, config, aclconfctx, + listener->mctx, &new_acl); + } else { + /* allow { any; } */ + result = dns_acl_create(listener->mctx, 1, &new_acl); + if (result == ISC_R_SUCCESS) { + new_acl->elements->type = dns_aclelementtype_any; + new_acl->elements->negative = ISC_FALSE; + new_acl->length = 1; + } + } + if (result == ISC_R_SUCCESS) { dns_acl_detach(&listener->acl); dns_acl_attach(new_acl, &listener->acl); @@ -1105,7 +934,7 @@ update_listener(ns_controls_t *cp, static void add_listener(ns_controls_t *cp, controllistener_t **listenerp, cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr, - ns_aclconfctx_t *aclconfctx, char *socktext) + ns_aclconfctx_t *aclconfctx, const char *socktext) { isc_mem_t *mctx = cp->server->mctx; controllistener_t *listener; @@ -1113,7 +942,6 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp, cfg_obj_t *global_keylist = NULL; cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; - isc_boolean_t explicit_key; isc_result_t result = ISC_R_SUCCESS; listener = isc_mem_get(mctx, sizeof(*listener)); @@ -1136,30 +964,42 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp, /* * Make the acl. */ - allow = cfg_tuple_get(control, "allow"); - result = ns_acl_fromconfig(allow, config, aclconfctx, mctx, - &new_acl); + if (control != NULL) { + allow = cfg_tuple_get(control, "allow"); + result = ns_acl_fromconfig(allow, config, aclconfctx, + mctx, &new_acl); + } else { + /* allow { any; } */ + result = dns_acl_create(mctx, 1, &new_acl); + if (result == ISC_R_SUCCESS) { + new_acl->elements->type = + dns_aclelementtype_any; + new_acl->elements->negative = ISC_FALSE; + new_acl->length = 1; + } + } } if (result == ISC_R_SUCCESS) { dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); - get_key_info(listener->mctx, config, control, - &global_keylist, &control_keylist, &explicit_key); + if (config != NULL) + get_key_info(config, control, &global_keylist, + &control_keylist); - if (control_keylist != NULL) + if (control_keylist != NULL) { result = controlkeylist_fromcfg(control_keylist, listener->mctx, &listener->keys); - if (result == ISC_R_SUCCESS) { - register_keys(control, global_keylist, &listener->keys, - listener->mctx, socktext); - - if (! explicit_key) - automagic_key.address = listener->address; - + if (result == ISC_R_SUCCESS) + register_keys(control, global_keylist, + &listener->keys, + listener->mctx, socktext); } else + result = get_rndckey(mctx, &listener->keys); + + if (result != ISC_R_SUCCESS && control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install keys for " "command channel %s: %s", @@ -1201,9 +1041,15 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp, free_listener(listener); } - cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, - "couldn't add command channel %s: %s", - socktext, isc_result_totext(result)); + if (control != NULL) + cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, + "couldn't add command channel %s: %s", + socktext, isc_result_totext(result)); + else + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, + "couldn't add command channel %s: %s", + socktext, isc_result_totext(result)); *listenerp = NULL; } @@ -1304,34 +1150,62 @@ ns_controls_configure(ns_controls_t *cp, cfg_obj_t *config, listener, link); } } - - finalize_automagic_key(); - - /* - * ns_control_shutdown() will stop whatever is on the global - * listeners list, which currently only has whatever sockaddrs - * were in the previous configuration (if any) that do not - * remain in the current configuration. - */ - ns_controls_shutdown(cp); - - /* - * Put all of the valid listeners on the listeners list. - * Anything already on listeners in the process of shutting - * down will be taken care of by listen_done(). - */ - ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link); - } else { - isc_result_t result; + int i; - result = parse_automagic_key(cp->server->mctx); + for (i = 0 ; i < 2; i++) { + isc_sockaddr_t addr; - if (result == ISC_R_SUCCESS) - ns_controls_configure(cp, automagic_key.config, - aclconfctx); + if (i == 1) { + if (isc_net_probeipv4() != ISC_R_SUCCESS) + continue; + isc_sockaddr_any(&addr); + } else { + if (isc_net_probeipv6() != ISC_R_SUCCESS) + continue; + isc_sockaddr_any6(&addr); + } + isc_sockaddr_setport(&addr, NS_CONTROL_PORT); + + isc_sockaddr_format(&addr, socktext, sizeof(socktext)); + + update_listener(cp, &listener, NULL, NULL, + &addr, NULL, socktext); + + if (listener != NULL) + /* + * Remove the listener from the old + * list, so it won't be shut down. + */ + ISC_LIST_UNLINK(cp->listeners, + listener, link); + else + /* + * This is a new listener. + */ + add_listener(cp, &listener, NULL, NULL, + &addr, NULL, socktext); + + if (listener != NULL) + ISC_LIST_APPEND(new_listeners, + listener, link); + } } + /* + * ns_control_shutdown() will stop whatever is on the global + * listeners list, which currently only has whatever sockaddrs + * were in the previous configuration (if any) that do not + * remain in the current configuration. + */ + ns_controls_shutdown(cp); + + /* + * Put all of the valid listeners on the listeners list. + * Anything already on listeners in the process of shutting + * down will be taken care of by listen_done(). + */ + ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link); return (ISC_R_SUCCESS); } diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 03611ea044..3220bdfe09 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.57 2001/05/31 10:38:56 tale Exp $ */ +/* $Id: globals.h,v 1.58 2001/08/03 05:56:17 marka Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -76,6 +76,8 @@ EXTERN cfg_obj_t * ns_g_config INIT(NULL); EXTERN cfg_obj_t * ns_g_defaults INIT(NULL); EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR "/named.conf"); +EXTERN const char * ns_g_keyfile INIT(NS_SYSCONFDIR + "/rndc.key"); EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR "/lwresd.conf"); EXTERN const char * lwresd_g_resolvconffile INIT("/etc" diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in index c0356d3657..949be6b25d 100644 --- a/bin/rndc/Makefile.in +++ b/bin/rndc/Makefile.in @@ -13,7 +13,7 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.29 2001/07/26 20:14:45 gson Exp $ +# $Id: Makefile.in,v 1.30 2001/08/03 05:56:16 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -27,7 +27,7 @@ CINCLUDES = ${ISC_INCLUDES} RNDCINCLUDES = ${CINCLUDES} ${ISCCC_INCLUDES} ${ISCCFG_INCLUDES} -CONFINCLUDES = ${CINCLUDES} ${DNS_INCLUDES} +CONFINCLUDES = -Iinclude ${CINCLUDES} ${DNS_INCLUDES} CDEFINES = CWARNINGS = @@ -48,6 +48,8 @@ RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS} CONFLIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} +SUBDIRS = unix + TARGETS = rndc rndc-confgen MANPAGES = rndc.8 rndc.conf.5 @@ -56,26 +58,29 @@ HTMLPAGES = rndc.html rndc.conf.html MANOBJS = ${MANPAGES} ${HTMLPAGES} +UOBJS = unix/os.@O@ + @BIND9_MAKE_RULES@ rndc.@O@: rndc.c ${LIBTOOL} ${CC} ${ALL_CFLAGS} ${RNDCINCLUDES} \ -DVERSION=\"${VERSION}\" \ -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \ - -DRNDC_AUTOCONFFILE=\"${localstatedir}/run/named.key\" \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ -c ${srcdir}/rndc.c rndc-confgen.@O@: rndc-confgen.c ${LIBTOOL} ${CC} ${ALL_CFLAGS} ${CONFINCLUDES} \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ -DRNDC_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/rndc-confgen.c rndc: rndc.@O@ util.@O@ ${RNDCDEPLIBS} ${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ rndc.@O@ util.@O@ \ ${RNDCLIBS} -rndc-confgen: rndc-confgen.@O@ util.@O@ ${CONFDEPLIBS} +rndc-confgen: rndc-confgen.@O@ util.@O@ ${UOBJS} ${CONFDEPLIBS} ${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ rndc-confgen.@O@ util.@O@ \ - ${CONFLIBS} + ${UOBJS} ${CONFLIBS} doc man:: ${MANOBJS} diff --git a/bin/rndc/include/rndc/os.h b/bin/rndc/include/rndc/os.h new file mode 100644 index 0000000000..1d0f822cfb --- /dev/null +++ b/bin/rndc/include/rndc/os.h @@ -0,0 +1,33 @@ +/* + * Copyright + */ + +/* $Id: os.h,v 1.1 2001/08/03 05:56:22 marka Exp $ */ + +#ifndef RNDC_OS_H +#define RNDC_OS_H 1 + +#include +#include + +/* + * OS specific paths that may be overriden at runtime by rndc_os_init(). + */ + + +ISC_LANG_BEGINDECLS + +FILE *safe_create(const char *filename); +/* + * Create and open 'filename' for writing. Fail if 'filename' exist. + */ + +int set_user(FILE *fd, const char *user); +/* + * Set the owner of the file refernced by 'fd' to 'user'. + * Fail is insufficient permissions or 'user' does not exist. + */ + +ISC_LANG_ENDDECLS + +#endif diff --git a/bin/rndc/rndc-confgen.c b/bin/rndc/rndc-confgen.c index 36cadcb15f..2dd10a503c 100644 --- a/bin/rndc/rndc-confgen.c +++ b/bin/rndc/rndc-confgen.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc-confgen.c,v 1.2 2001/06/29 23:32:09 gson Exp $ */ +/* $Id: rndc-confgen.c,v 1.3 2001/08/03 05:56:15 marka Exp $ */ #include @@ -40,6 +40,7 @@ #include #include +#include #include "util.h" @@ -51,18 +52,26 @@ char progname[256]; isc_boolean_t verbose = ISC_FALSE; +const char *keyfile, *keydef; + static void usage(int status) { + fprintf(stderr, "\ Usage:\n\ - %s [-b bits] [-k keyname] [-P] [-p port] [-r randomfile] [-s addr]\n\ + %s [-a] [-b bits] [-c keyfile] [-k keyname] [-P] [-p port] [-r randomfile] \ +[-s addr] [-t chrootdir] [-u user]\n\ + -a: generate just the key clause and write it to keyfile (%s)\n\ -b bits: from 1 through 512, default %d; total length of the secret\n\ + -c keyfile: specify a alterate keyfile (requires -a)\n\ -k keyname: the name as it will be used in named.conf and rndc.conf\n\ -P: using pseudorandom data for key generation is ok\n\ -p port: the port named will listen on and rndc will connect to\n\ -r randomfile: a file containing random data\n\ - -s addr: the address to which rndc should connect\n", - progname, DEFAULT_KEYLENGTH); + -s addr: the address to which rndc should connect\n\ + -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ + -u user: set the keyfile owner to \"user\" (requires -a)\n", + progname, keydef, DEFAULT_KEYLENGTH); exit (status); } @@ -91,19 +100,30 @@ main(int argc, char **argv) { int entropy_flags = 0; int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE; struct in_addr addr; + char *chrootdir = NULL; + char *user = NULL; + isc_boolean_t keyonly = ISC_FALSE; + int len; + FILE *fd; + char *buf; + + keydef = keyfile = RNDC_KEYFILE; result = isc_file_progname(*argv, progname, sizeof(progname)); if (result != ISC_R_SUCCESS) - memcpy(progname, "rndc", 5); + memcpy(progname, "rndc-confgen", 13); keyname = DEFAULT_KEYNAME; keysize = DEFAULT_KEYLENGTH; serveraddr = DEFAULT_SERVER; port = DEFAULT_PORT; - while ((ch = isc_commandline_parse(argc, argv, "b:hk:MmPp:r:s:Vy")) - != -1) { + while ((ch = isc_commandline_parse(argc, argv, + "ab:c:hk:MmPp:r:s:t:u:Vy")) != -1) { switch (ch) { + case 'a': + keyonly = ISC_TRUE; + break; case 'b': keysize = strtol(isc_commandline_argument, &p, 10); if (*p != '\0' || keysize < 0) @@ -111,6 +131,9 @@ main(int argc, char **argv) { if (keysize < 1 || keysize > 512) fatal("-b must be in the range 1 through 512"); break; + case 'c': + keyfile = isc_commandline_argument; + break; case 'h': usage(0); case 'k': @@ -142,6 +165,12 @@ main(int argc, char **argv) { if (inet_aton(serveraddr, &addr) == 0) fatal("-s should be an IPv4 or IPv6 address"); + break; + case 't': + chrootdir = isc_commandline_argument; + break; + case 'u': + user = isc_commandline_argument; break; case 'V': verbose = ISC_TRUE; @@ -211,7 +240,77 @@ main(int argc, char **argv) { */ printf("\n\n"); - printf("\ + if (keyonly) { + fd = safe_create(keyfile); + if (fd == NULL) { + fprintf(stderr, "unable to create \"%s\"\n", keyfile); + goto cleanup; + } + if (user != NULL && chrootdir == NULL) { + if (set_user(fd, user) == -1) { + fprintf(stderr, "unable to set file owner\n"); + fclose(fd); + goto cleanup; + } + } + fprintf(fd, "key \"%s\" {\n\talgorithm hmac-md5;\n" + "\tsecret \"%.*s\";\n};\n", keyname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer)); + fflush(fd); + if (ferror(fd)) { + fprintf(stderr, "write to %s failed\n", keyfile); + fclose(fd); + goto cleanup; + } + if (fclose(fd)) { + fprintf(stderr, "fclose(%s) failed\n", keyfile); + goto cleanup; + } + if (chrootdir == NULL) + goto cleanup; + + len = strlen(chrootdir) + strlen(keyfile) + 2; + buf = isc_mem_get(mctx, len); + if (buf != NULL) { + fprintf(stderr, "isc_mem_get(%d) failed\n", len); + goto cleanup; + } + snprintf(buf, len, "%s" "/" "%s", chrootdir, keyfile); + fd = safe_create(buf); + if (fd == NULL) { + fprintf(stderr, "unable to create \"%s\"\n", + buf); + isc_mem_put(mctx, buf, len); + goto cleanup; + } + if (user != NULL) { + if (set_user(fd, user) == -1) { + fprintf(stderr, "unable to set file owner\n"); + fclose(fd); + isc_mem_put(mctx, buf, len); + goto cleanup; + } + } + fprintf(fd, "key \"%s\" {\n\talgorithm hmac-md5;\n" + "\tsecret \"%.*s\";\n};\n", keyname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer)); + fflush(fd); + if (ferror(fd)) { + fprintf(stderr, "write to %s failed\n", buf); + fclose(fd); + isc_mem_put(mctx, buf, len); + goto cleanup; + } + if (fclose(fd)) { + fprintf(stderr, "fclose(%s) failed\n", buf); + isc_mem_put(mctx, buf, len); + goto cleanup; + } + isc_mem_put(mctx, buf, len); + } else { + printf("\ # Start of rndc.conf\n\ key \"%s\" {\n\ algorithm hmac-md5;\n\ @@ -236,15 +335,17 @@ options {\n\ # allow { %s; } keys { \"%s\"; };\n\ # };\n\ # End of named.conf\n", - keyname, - (int)isc_buffer_usedlength(&key_txtbuffer), - (char *)isc_buffer_base(&key_txtbuffer), - keyname, serveraddr, port, - keyname, - (int)isc_buffer_usedlength(&key_txtbuffer), - (char *)isc_buffer_base(&key_txtbuffer), - serveraddr, port, serveraddr, keyname); + keyname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer), + keyname, serveraddr, port, + keyname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer), + serveraddr, port, serveraddr, keyname); + } + cleanup: if (show_final_mem) isc_mem_stats(mctx, stderr); diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 9e93b2eb98..85d4b1acd2 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc.c,v 1.74 2001/07/26 20:37:26 gson Exp $ */ +/* $Id: rndc.c,v 1.75 2001/08/03 05:56:13 marka Exp $ */ /* * Principal Author: DCL @@ -50,6 +50,11 @@ #include #include +#if 0 +#define RNDC_MAIN +#include +#endif + #include "util.h" #ifdef HAVE_ADDRINFO @@ -70,10 +75,10 @@ char *progname; isc_boolean_t verbose; static const char *admin_conffile; -static const char *auto_conffile; +static const char *admin_keyfile; static const char *version = VERSION; static const char *servername = NULL; -static unsigned int remoteport = NS_CONTROL_PORT; +static unsigned int remoteport = 0; static isc_socketmgr_t *socketmgr = NULL; static unsigned char databuf[2048]; static isccc_ccmsg_t ccmsg; @@ -149,6 +154,7 @@ get_address(const char *host, in_port_t port, isc_sockaddr_t *sockaddr) { hints.ai_family = PF_INET6; else hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; isc_app_block(); result = getaddrinfo(host, NULL, &hints, &res); isc_app_unblock(); @@ -313,18 +319,36 @@ rndc_start(isc_task_t *task, isc_event_t *event) { } static void -parse_config(isc_mem_t *mctx, isc_log_t *log, cfg_parser_t **pctxp, - cfg_obj_t **config) +parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, + cfg_parser_t **pctxp, cfg_obj_t **configp) { isc_result_t result; const char *conffile = admin_conffile; + cfg_obj_t *defkey = NULL; + cfg_obj_t *options = NULL; + cfg_obj_t *servers = NULL; + cfg_obj_t *server = NULL; + cfg_obj_t *keys = NULL; + cfg_obj_t *key = NULL; + cfg_obj_t *defport = NULL; + cfg_obj_t *secretobj = NULL; + cfg_obj_t *algorithmobj = NULL; + cfg_obj_t *config = NULL; + cfg_listelt_t *elt; + const char *secretstr; + const char *algorithm; + static char secretarray[1024]; + const cfg_type_t *conftype = &cfg_type_rndcconf; + isc_boolean_t key_only = ISC_FALSE; if (! isc_file_exists(conffile)) { - conffile = auto_conffile; + conffile = admin_keyfile; + conftype = &cfg_type_rndckey; if (! isc_file_exists(conffile)) fatal("neither %s nor %s was found", - admin_conffile, auto_conffile); + admin_conffile, admin_keyfile); + key_only = ISC_TRUE; } DO("create parser", cfg_parser_create(mctx, log, pctxp)); @@ -332,10 +356,110 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, cfg_parser_t **pctxp, /* * The parser will output its own errors, so DO() is not used. */ - result = cfg_parse_file(*pctxp, conffile, &cfg_type_rndcconf, config); + result = cfg_parse_file(*pctxp, conffile, conftype, &config); - if (result != ISC_R_SUCCESS) - exit(1); + if (!key_only) + (void)cfg_map_get(config, "options", &options); + + if (key_only && servername == NULL) + servername = "localhost"; + else if (servername == NULL && options != NULL) { + cfg_obj_t *defserverobj = NULL; + (void)cfg_map_get(options, "default-server", &defserverobj); + if (defserverobj != NULL) + servername = cfg_obj_asstring(defserverobj); + } + + if (servername == NULL) + fatal("no server specified and no default"); + + if (!key_only) { + cfg_map_get(config, "server", &servers); + if (servers != NULL) { + for (elt = cfg_list_first(servers); + elt != NULL; + elt = cfg_list_next(elt)) + { + const char *name; + server = cfg_listelt_value(elt); + name = cfg_obj_asstring(cfg_map_getname(server)); + if (strcasecmp(name, servername) == 0) + break; + server = NULL; + } + } + } + + /* + * Look for the name of the key to use. + */ + if (keyname != NULL) + ; /* Was set on command line, do nothing. */ + else if (server != NULL) { + DO("get key for server", cfg_map_get(server, "key", &defkey)); + keyname = cfg_obj_asstring(defkey); + } else if (options != NULL) { + DO("get default key", cfg_map_get(options, "default-key", + &defkey)); + keyname = cfg_obj_asstring(defkey); + } else if (!key_only) + fatal("no key for server and no default"); + + /* + * Get the key's definition. + */ + if (key_only) + DO("get key", cfg_map_get(config, "key", &key)); + else { + DO("get config key list", cfg_map_get(config, "key", &keys)); + for (elt = cfg_list_first(keys); + elt != NULL; + elt = cfg_list_next(elt)) + { + key = cfg_listelt_value(elt); + if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)), + keyname) == 0) + break; + } + if (elt == NULL) + fatal("no key definition for name %s", keyname); + } + (void)cfg_map_get(key, "secret", &secretobj); + (void)cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) + fatal("key must have algorithm and secret"); + + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + if (strcasecmp(algorithm, "hmac-md5") != 0) + fatal("unsupported algorithm: %s", algorithm); + + secret.rstart = (unsigned char *)secretarray; + secret.rend = (unsigned char *)secretarray + sizeof(secretarray); + DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); + secret.rend = secret.rstart; + secret.rstart = (unsigned char *)secretarray; + + /* + * Find the port to connect to. + */ + if (remoteport != 0) + ; /* Was set on command line, do nothing. */ + else { + if (server != NULL) + (void)cfg_map_get(server, "port", &defport); + if (defport == NULL && options != NULL) + cfg_map_get(options, "default-port", &defport); + } + if (defport != NULL) { + remoteport = cfg_obj_asuint32(defport); + if (remoteport > 65535 || remoteport == 0) + fatal("port %d out of range", remoteport); + } else if (remoteport == 0) + remoteport = NS_CONTROL_PORT; + + *configp = config; } int @@ -349,43 +473,33 @@ main(int argc, char **argv) { isc_logdestination_t logdest; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; - cfg_obj_t *options = NULL; - cfg_obj_t *servers = NULL; - cfg_obj_t *server = NULL; - cfg_obj_t *defkey = NULL; - cfg_obj_t *keys = NULL; - cfg_obj_t *key = NULL; - cfg_obj_t *defport = NULL; - cfg_obj_t *secretobj = NULL; - cfg_obj_t *algorithmobj = NULL; - cfg_listelt_t *elt; const char *keyname = NULL; - const char *secretstr; - const char *algorithm; - isc_boolean_t portset = ISC_FALSE; - char secretarray[1024]; char *p; size_t argslen; int ch; int i; - admin_conffile = RNDC_CONFFILE; - auto_conffile = RNDC_AUTOCONFFILE; - - isc_app_start(); - result = isc_file_progname(*argv, program, sizeof(program)); if (result != ISC_R_SUCCESS) - memcpy(progname, "rndc", 5); + memcpy(program, "rndc", 5); progname = program; - while ((ch = isc_commandline_parse(argc, argv, "c:Mmp:s:Vy:")) + admin_conffile = RNDC_CONFFILE; + admin_keyfile = RNDC_KEYFILE; + + isc_app_start(); + + while ((ch = isc_commandline_parse(argc, argv, "c:k:Mmp:s:Vy:")) != -1) { switch (ch) { case 'c': admin_conffile = isc_commandline_argument; break; + case 'k': + admin_keyfile = isc_commandline_argument; + break; + case 'M': isc_mem_debugging = 1; break; @@ -396,10 +510,9 @@ main(int argc, char **argv) { case 'p': remoteport = atoi(isc_commandline_argument); - if (remoteport > 65535) + if (remoteport > 65535 || remoteport == 0) fatal("port '%s' out of range", isc_commandline_argument); - portset = ISC_TRUE; break; case 's': @@ -446,100 +559,7 @@ main(int argc, char **argv) { DO("enabling log channel", isc_log_usechannel(logconfig, "stderr", NULL, NULL)); - parse_config(mctx, log, &pctx, &config); - - (void)cfg_map_get(config, "options", &options); - - if (servername == NULL && options != NULL) { - cfg_obj_t *defserverobj = NULL; - (void)cfg_map_get(options, "default-server", &defserverobj); - if (defserverobj != NULL) - servername = cfg_obj_asstring(defserverobj); - } - - if (servername == NULL) - fatal("no server specified and no default"); - - cfg_map_get(config, "server", &servers); - if (servers != NULL) { - for (elt = cfg_list_first(servers); - elt != NULL; - elt = cfg_list_next(elt)) - { - const char *name; - server = cfg_listelt_value(elt); - name = cfg_obj_asstring(cfg_map_getname(server)); - if (strcasecmp(name, servername) == 0) - break; - server = NULL; - } - } - - /* - * Look for the name of the key to use. - */ - if (keyname != NULL) - ; /* Was set on command line, do nothing. */ - else if (server != NULL) { - DO("get key for server", cfg_map_get(server, "key", &defkey)); - keyname = cfg_obj_asstring(defkey); - } else if (options != NULL) { - DO("get default key", cfg_map_get(options, "default-key", - &defkey)); - keyname = cfg_obj_asstring(defkey); - } else - fatal("no key for server and no default"); - - /* - * Get the key's definition. - */ - DO("get config key list", cfg_map_get(config, "key", &keys)); - for (elt = cfg_list_first(keys); - elt != NULL; - elt = cfg_list_next(elt)) - { - key = cfg_listelt_value(elt); - if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)), - keyname) == 0) - break; - } - if (elt == NULL) - fatal("no key definition for name %s", keyname); - - (void)cfg_map_get(key, "secret", &secretobj); - (void)cfg_map_get(key, "algorithm", &algorithmobj); - if (secretobj == NULL || algorithmobj == NULL) - fatal("key must have algorithm and secret"); - - secretstr = cfg_obj_asstring(secretobj); - algorithm = cfg_obj_asstring(algorithmobj); - - if (strcasecmp(algorithm, "hmac-md5") != 0) - fatal("unsupported algorithm: %s", algorithm); - - secret.rstart = (unsigned char *)secretarray; - secret.rend = (unsigned char *)secretarray + sizeof(secretarray); - DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); - secret.rend = secret.rstart; - secret.rstart = (unsigned char *)secretarray; - - /* - * Find the port to connect to. - */ - if (portset) - ; /* Was set on command line, do nothing. */ - else { - if (server != NULL) - (void)cfg_map_get(server, "port", &defport); - if (defport == NULL && options != NULL) - cfg_map_get(options, "default-port", &defport); - } - if (defport != NULL) { - remoteport = cfg_obj_asuint32(defport); - if (remoteport > 65535) - fatal("port %d out of range", remoteport); - } else if (!portset) - remoteport = NS_CONTROL_PORT; + parse_config(mctx, log, keyname, &pctx, &config); isccc_result_register(); @@ -570,7 +590,7 @@ main(int argc, char **argv) { *p++ = '\0'; INSIST(p == args + argslen); - notify(command); + notify("%s", command); if (strcmp(command, "restart") == 0) fatal("'%s' is not implemented", command); diff --git a/bin/rndc/unix/Makefile.in b/bin/rndc/unix/Makefile.in new file mode 100644 index 0000000000..e8583fe475 --- /dev/null +++ b/bin/rndc/unix/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2001 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.1 2001/08/03 05:56:22 marka Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_INCLUDES@ + +CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} + +CDEFINES = +CWARNINGS = + +OBJS = os.@O@ + +SRCS = os.c + +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/bin/rndc/unix/os.c b/bin/rndc/unix/os.c new file mode 100644 index 0000000000..8dfdf8d592 --- /dev/null +++ b/bin/rndc/unix/os.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: os.c,v 1.1 2001/08/03 05:56:22 marka Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +int +set_user(FILE *fd, const char *user) { + struct passwd *pw; + + pw = getpwnam(user); + if (pw == NULL) { + errno = EINVAL; + return (-1); + } + return (fchown(fileno(fd), pw->pw_uid, -1)); +} + +FILE * +safe_create(const char *filename) { + int fd; + FILE *f; + struct stat sb; + + if (stat(filename, &sb) == -1) { + if (errno != ENOENT) + return (NULL); + } else if ((sb.st_mode & S_IFREG) == 0) { + errno = EOPNOTSUPP; + return (NULL); + } + + fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + if (fd == -1) + return (NULL); + f = fdopen(fd, "w"); + if (f == NULL) + close(fd); + return (f); +} diff --git a/configure.in b/configure.in index 06023d628b..95e350e50b 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.285 $) +AC_REVISION($Revision: 1.286 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.13) @@ -1670,6 +1670,7 @@ AC_OUTPUT( bin/named/Makefile bin/named/unix/Makefile bin/rndc/Makefile + bin/rndc/unix/Makefile bin/dig/Makefile bin/nsupdate/Makefile bin/tests/Makefile diff --git a/lib/isccfg/include/isccfg/cfg.h b/lib/isccfg/include/isccfg/cfg.h index 11360daba1..874a1dca7f 100644 --- a/lib/isccfg/include/isccfg/cfg.h +++ b/lib/isccfg/include/isccfg/cfg.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cfg.h,v 1.28 2001/07/23 16:58:18 gson Exp $ */ +/* $Id: cfg.h,v 1.29 2001/08/03 05:56:11 marka Exp $ */ #ifndef ISCCFG_CFG_H #define ISCCFG_CFG_H 1 @@ -407,6 +407,9 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_namedconf; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_rndcconf; /* A complete rndc.conf file. */ +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_rndckey; +/* A complete rndc.conf file. */ + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_keyref; /* A key reference, used as an ACL element */ diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 07e034faec..64bdbb93ce 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: parser.c,v 1.68 2001/08/02 23:36:23 gson Exp $ */ +/* $Id: parser.c,v 1.69 2001/08/03 05:56:12 marka Exp $ */ #include @@ -3466,6 +3466,24 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndcconf = { rndcconf_clausesets }; +static cfg_clausedef_t +rndckey_clauses[] = { + { "key", &cfg_type_key, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_clausedef_t * +rndckey_clausesets[] = { + rndckey_clauses, + NULL +}; + +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey = { + "rndckey", parse_mapbody, print_mapbody, &cfg_rep_map, + rndckey_clausesets +}; + + static isc_result_t cfg_gettoken(cfg_parser_t *pctx, int options) { isc_result_t result;