]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
rndc.key support
authorMark Andrews <marka@isc.org>
Fri, 3 Aug 2001 05:56:22 +0000 (05:56 +0000)
committerMark Andrews <marka@isc.org>
Fri, 3 Aug 2001 05:56:22 +0000 (05:56 +0000)
bin/named/controlconf.c
bin/named/include/named/globals.h
bin/rndc/Makefile.in
bin/rndc/include/rndc/os.h [new file with mode: 0644]
bin/rndc/rndc-confgen.c
bin/rndc/rndc.c
bin/rndc/unix/Makefile.in [new file with mode: 0644]
bin/rndc/unix/os.c [new file with mode: 0644]
configure.in
lib/isccfg/include/isccfg/cfg.h
lib/isccfg/parser.c

index 3b16a121ba34c6c836996c5ff4cde112890419a0..627c3db5f8a76e8b7bda7e5e29ba1a7cc26ecc8c 100644 (file)
@@ -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,
        }
 }
 
+#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;
-
-       /*
-        * 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';
+       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;
 
-               /*
-                * 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));
+       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));
+
+       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 (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);
-}
-
-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;
+       isc_buffer_init(&b, secret, sizeof(secret));
+       result = isc_base64_decodestring(secretstr, &b);
 
-       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) {
+               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)
-               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);
+       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;
+
+  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
-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 (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 (!cfg_obj_isvoid(control_keylist) &&
+           cfg_list_first(control_keylist) != NULL)
+               cfg_map_get(config, "key", &global_keylist);
 
-       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 == 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);
-               listener->keys = keys;
-               register_keys(control, global_keylist, &listener->keys,
-                             listener->mctx, socktext);
-
-               if (! explicit_key)
-                       automagic_key.address = listener->address;
+               result = get_rndckey(listener->mctx, &listener->keys);
+       }
 
-       } 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;
+
+               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);
 
-               result = parse_automagic_key(cp->server->mctx);
+                       isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+                       
+                       update_listener(cp, &listener, NULL, NULL,
+                                       &addr, NULL, socktext);
 
-               if (result == ISC_R_SUCCESS)
-                       ns_controls_configure(cp, automagic_key.config,
-                                            aclconfctx);
+                       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);
 }
 
index 03611ea04409970449e5df55f81cb0d042c627aa..3220bdfe09e2848130194dda48adf84d22851bc3 100644 (file)
@@ -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"
index c0356d36577d9dfebfbfea372ac8a0143162166e..949be6b25d5103a2c9b9cf01ac392344f329509f 100644 (file)
@@ -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 (file)
index 0000000..1d0f822
--- /dev/null
@@ -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
index 36cadcb15fded13601024289020798f0c7563b53..2dd10a503c31feb09fda54b2c7bbd94212a971c6 100644 (file)
@@ -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"
 
 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);
 
index 9e93b2eb98149bd4e8ceb743480b8b76b457d2cd..85d4b1acd22aaf6225f9b69040b289eabab6f004 100644 (file)
@@ -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
 #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;
 
-       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 (file)
index 0000000..e8583fe
--- /dev/null
@@ -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 (file)
index 0000000..8dfdf8d
--- /dev/null
@@ -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);
+}
index 06023d628b611ff8ad565156826f467047ea1773..95e350e50ba5145258a7f99218d1efe021d509df 100644 (file)
@@ -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
index 11360daba1886997d1ac99d280deadafab34da0d..874a1dca7f963059293e29dc7b3de6f77206cd4c 100644 (file)
@@ -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 */
 
index 07e034faecb0654aadf1a3ee320f6ee8991a4e88..64bdbb93cebc4231897afc6fc324b65997973324 100644 (file)
@@ -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;