mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 15:05:23 +00:00
rndc.key support
This commit is contained in:
@@ -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 <config.h>
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
isc_result_t result;
|
||||
dst_key_t *key = NULL;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_buffer_init(&key_rawbuffer, &key_rawsecret,
|
||||
sizeof(key_rawsecret));
|
||||
result = dst_key_tobuffer(key, &key_rawbuffer);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
}
|
||||
#define CHECK(x) \
|
||||
do { \
|
||||
result = (x); \
|
||||
if (result != ISC_R_SUCCESS) \
|
||||
goto cleanup; \
|
||||
} while (0)
|
||||
|
||||
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;
|
||||
get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
|
||||
isc_result_t result;
|
||||
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;
|
||||
|
||||
(void)isc_file_remove(ns_g_autorndckeyfile);
|
||||
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 (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;
|
||||
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);
|
||||
|
||||
result = isc_stdio_open(ns_g_autorndckeyfile, "w", &fp);
|
||||
algstr = cfg_obj_asstring(algobj);
|
||||
secretstr = cfg_obj_asstring(secretobj);
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, secret, sizeof(secret));
|
||||
result = isc_base64_decodestring(secretstr, &b);
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
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;
|
||||
|
||||
cfg_obj_destroy(automagic_key.parser, &automagic_key.config);
|
||||
cfg_parser_destroy(&automagic_key.parser);
|
||||
}
|
||||
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
|
||||
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");
|
||||
}
|
||||
|
||||
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 == ISC_R_SUCCESS) {
|
||||
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 (! 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
if (control != NULL) {
|
||||
allow = cfg_tuple_get(control, "allow");
|
||||
result = ns_acl_fromconfig(allow, config, aclconfctx, mctx,
|
||||
&new_acl);
|
||||
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,
|
||||
if (result == ISC_R_SUCCESS)
|
||||
register_keys(control, global_keylist,
|
||||
&listener->keys,
|
||||
listener->mctx, socktext);
|
||||
|
||||
if (! explicit_key)
|
||||
automagic_key.address = listener->address;
|
||||
|
||||
} 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);
|
||||
}
|
||||
|
||||
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,8 +1150,47 @@ ns_controls_configure(ns_controls_t *cp, cfg_obj_t *config,
|
||||
listener, link);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
|
||||
finalize_automagic_key();
|
||||
for (i = 0 ; i < 2; i++) {
|
||||
isc_sockaddr_t addr;
|
||||
|
||||
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
|
||||
@@ -1321,17 +1206,6 @@ ns_controls_configure(ns_controls_t *cp, cfg_obj_t *config,
|
||||
* down will be taken care of by listen_done().
|
||||
*/
|
||||
ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
|
||||
|
||||
} else {
|
||||
isc_result_t result;
|
||||
|
||||
result = parse_automagic_key(cp->server->mctx);
|
||||
|
||||
if (result == ISC_R_SUCCESS)
|
||||
ns_controls_configure(cp, automagic_key.config,
|
||||
aclconfctx);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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}
|
||||
|
||||
|
33
bin/rndc/include/rndc/os.h
Normal file
33
bin/rndc/include/rndc/os.h
Normal file
@@ -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 <isc/lang.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* 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
|
@@ -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 <config.h>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <dns/name.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <rndc/os.h>
|
||||
|
||||
#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,6 +240,76 @@ main(int argc, char **argv) {
|
||||
*/
|
||||
printf("\n\n");
|
||||
|
||||
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\
|
||||
@@ -244,7 +343,9 @@ options {\n\
|
||||
(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);
|
||||
|
||||
|
276
bin/rndc/rndc.c
276
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 <isccc/types.h>
|
||||
#include <isccc/util.h>
|
||||
|
||||
#if 0
|
||||
#define RNDC_MAIN
|
||||
#include <rndc/os.h>
|
||||
#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;
|
||||
|
||||
result = isc_file_progname(*argv, program, sizeof(program));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
memcpy(program, "rndc", 5);
|
||||
progname = program;
|
||||
|
||||
admin_conffile = RNDC_CONFFILE;
|
||||
auto_conffile = RNDC_AUTOCONFFILE;
|
||||
admin_keyfile = RNDC_KEYFILE;
|
||||
|
||||
isc_app_start();
|
||||
|
||||
result = isc_file_progname(*argv, program, sizeof(program));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
memcpy(progname, "rndc", 5);
|
||||
progname = program;
|
||||
|
||||
while ((ch = isc_commandline_parse(argc, argv, "c:Mmp:s:Vy:"))
|
||||
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);
|
||||
|
36
bin/rndc/unix/Makefile.in
Normal file
36
bin/rndc/unix/Makefile.in
Normal file
@@ -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@
|
65
bin/rndc/unix/os.c
Normal file
65
bin/rndc/unix/os.c
Normal file
@@ -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 <config.h>
|
||||
|
||||
#include <rndc/os.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
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);
|
||||
}
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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 <config.h>
|
||||
|
||||
@@ -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;
|
||||
|
Reference in New Issue
Block a user