]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] rndc managed-keys destroy
authorEvan Hunt <each@isc.org>
Tue, 3 Oct 2017 08:04:25 +0000 (01:04 -0700)
committerEvan Hunt <each@isc.org>
Tue, 3 Oct 2017 08:05:46 +0000 (01:05 -0700)
4750. [func] "rndc managed-keys destroy" shuts down RFC 5011 key
maintenance and deletes the managed-keys database.
If followed by "rndc reconfig" or a server restart,
key maintenance is reinitialized from scratch.
This is primarily intended for testing. [RT #32456]

CHANGES
bin/named/server.c
bin/rndc/rndc.docbook
bin/tests/system/mkeys/tests.sh
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index f5b288231cf07d9d5157ed5112f7f5b579a14f08..bcc9f823d75655ab23098e5cc21e2dd5cf3508ec 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+4750.  [func]          "rndc managed-keys destroy" shuts down RFC 5011 key
+                       maintenance and deletes the managed-keys database.
+                       If followed by "rndc reconfig" or a server restart,
+                       key maintenance is reinitialized from scratch.
+                       This is primarily intended for testing. [RT #32456]
+
 4749.  [func]          The ISC DLV service has been shut down, and all
                        DLV records have been removed from dlv.isc.org.
                        - Removed references to ISC DLV in documentation
index 2d501d03b88663de5e8880282b5a5f110a7eee39..8d5538d6e2ec4efb38bc369620fd3ea3b8f80de8 100644 (file)
@@ -6042,18 +6042,22 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
 
        /* See if we can re-use an existing keydata zone. */
        result = dns_viewlist_find(&named_g_server->viewlist,
-                                  view->name, view->rdclass,
-                                  &pview);
-       if (result != ISC_R_NOTFOUND &&
-           result != ISC_R_SUCCESS)
+                                  view->name, view->rdclass, &pview);
+       if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
                return (result);
+       }
+
+       if (pview != NULL) {
+               if (pview->managed_keys != NULL) {
+                       dns_zone_synckeyzone(pview->managed_keys);
+                       dns_zone_attach(pview->managed_keys,
+                                       &view->managed_keys);
+                       dns_zone_setview(pview->managed_keys, view);
+                       dns_view_detach(&pview);
+                       return (ISC_R_SUCCESS);
+               }
 
-       if (pview != NULL && pview->managed_keys != NULL) {
-               dns_zone_attach(pview->managed_keys, &view->managed_keys);
-               dns_zone_setview(pview->managed_keys, view);
                dns_view_detach(&pview);
-               dns_zone_synckeyzone(view->managed_keys);
-               return (ISC_R_SUCCESS);
        }
 
        /* No existing keydata zone was found; create one */
@@ -6086,8 +6090,9 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
        dns_zone_setstats(zone, named_g_server->zonestats);
        CHECK(setquerystats(zone, mctx, dns_zonestat_none));
 
-       if (view->managed_keys != NULL)
+       if (view->managed_keys != NULL) {
                dns_zone_detach(&view->managed_keys);
+       }
        dns_zone_attach(zone, &view->managed_keys);
 
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
@@ -6096,10 +6101,12 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
                      view->name, filename);
 
 cleanup:
-       if (zone != NULL)
+       if (zone != NULL) {
                dns_zone_detach(&zone);
-       if (none != NULL)
+       }
+       if (none != NULL) {
                dns_acl_detach(&none);
+       }
 
        return (result);
 }
@@ -8916,8 +8923,7 @@ run_server(isc_task_t *task, isc_event_t *event) {
                                     &named_g_addparser),
                   "creating additional configuration parser");
 
-       CHECKFATAL(load_configuration(named_g_conffile, server,
-                                     ISC_TRUE),
+       CHECKFATAL(load_configuration(named_g_conffile, server, ISC_TRUE),
                   "loading configuration");
 
        isc_hash_init();
@@ -14067,6 +14073,78 @@ mkey_refresh(dns_view_t *view, isc_buffer_t **text) {
        return (result);
 }
 
+static isc_result_t
+mkey_destroy(named_server_t *server, dns_view_t *view, isc_buffer_t **text) {
+       isc_result_t result;
+       char msg[DNS_NAME_FORMATSIZE + 500] = "";
+       isc_boolean_t exclusive = ISC_FALSE;
+       const char *file = NULL;
+       dns_db_t *dbp = NULL;
+       dns_zone_t *mkzone = NULL;
+       isc_boolean_t removed = ISC_FALSE;
+
+       if (view->managed_keys == NULL) {
+               CHECK(ISC_R_NOTFOUND);
+       }
+
+       snprintf(msg, sizeof(msg),
+                "destroying managed-keys database for '%s'", view->name);
+       CHECK(putstr(text, msg));
+
+       result = isc_task_beginexclusive(server->task);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+       exclusive = ISC_TRUE;
+
+       /* Remove and clean up managed keys zone from view */
+       mkzone = view->managed_keys;
+       view->managed_keys = NULL;
+       (void)dns_zone_flush(mkzone);
+
+       /* Unload zone database */
+       if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) {
+               dns_db_detach(&dbp);
+               dns_zone_unload(mkzone);
+       }
+
+       /* Delete files */
+       file = dns_zone_getfile(mkzone);
+       result = isc_file_remove(file);
+       if (result == ISC_R_SUCCESS) {
+               removed = ISC_TRUE;
+       } else {
+               isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+                             NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+                             "file %s not removed: %s",
+                             file, isc_result_totext(result));
+       }
+
+       file = dns_zone_getjournal(mkzone);
+       result = isc_file_remove(file);
+       if (result == ISC_R_SUCCESS) {
+               removed = ISC_TRUE;
+       } else {
+               isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+                             NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
+                             "file %s not removed: %s",
+                             file, isc_result_totext(result));
+       }
+
+       if (!removed) {
+               CHECK(putstr(text, "error: no files could be removed"));
+               CHECK(ISC_R_FAILURE);
+       }
+
+       dns_zone_detach(&mkzone);
+       result = ISC_R_SUCCESS;
+
+ cleanup:
+       if (exclusive) {
+               isc_task_endexclusive(server->task);
+       }
+       return (result);
+}
+
+
 static isc_result_t
 mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) {
        isc_result_t result;
@@ -14220,27 +14298,31 @@ named_server_mkeys(named_server_t *server, isc_lex_t *lex,
        dns_view_t *view = NULL;
        dns_rdataclass_t rdclass;
        char msg[DNS_NAME_FORMATSIZE + 500] = "";
-       enum { NONE, STATUS, REFRESH, SYNC } opt = NONE;
+       enum { NONE, STATUS, REFRESH, SYNC, DESTROY } opt = NONE;
        isc_boolean_t found = ISC_FALSE;
        isc_boolean_t first = ISC_TRUE;
 
        /* Skip rndc command name */
        cmd = next_token(lex, text);
-       if (cmd == NULL)
+       if (cmd == NULL) {
                return (ISC_R_UNEXPECTEDEND);
+       }
 
        /* Get managed-keys subcommand */
        cmd = next_token(lex, text);
-       if (cmd == NULL)
+       if (cmd == NULL) {
                return (ISC_R_UNEXPECTEDEND);
+       }
 
-       if (strcasecmp(cmd, "status") == 0)
+       if (strcasecmp(cmd, "status") == 0) {
                opt = STATUS;
-       else if (strcasecmp(cmd, "refresh") == 0)
+       } else if (strcasecmp(cmd, "refresh") == 0) {
                opt = REFRESH;
-       else if (strcasecmp(cmd, "sync") == 0)
+       } else if (strcasecmp(cmd, "sync") == 0) {
                opt = SYNC;
-       else {
+       } else if (strcasecmp(cmd, "destroy") == 0) {
+               opt = DESTROY;
+       } else {
                snprintf(msg, sizeof(msg), "unknown command '%s'", cmd);
                (void) putstr(text, msg);
                result = ISC_R_UNEXPECTED;
@@ -14282,7 +14364,9 @@ named_server_mkeys(named_server_t *server, isc_lex_t *lex,
                if (viewtxt != NULL &&
                    (rdclass != view->rdclass ||
                     strcmp(view->name, viewtxt) != 0))
+               {
                        continue;
+               }
 
                if (view->managed_keys == NULL) {
                        if (viewtxt != NULL) {
@@ -14290,8 +14374,9 @@ named_server_mkeys(named_server_t *server, isc_lex_t *lex,
                                         "view '%s': no managed keys", viewtxt);
                                CHECK(putstr(text, msg));
                                goto cleanup;
-                       } else
+                       } else {
                                continue;
+                       }
                }
 
                found = ISC_TRUE;
@@ -14301,28 +14386,35 @@ named_server_mkeys(named_server_t *server, isc_lex_t *lex,
                        CHECK(mkey_refresh(view, text));
                        break;
                case STATUS:
-                       if (!first)
+                       if (!first) {
                                CHECK(putstr(text, "\n\n"));
+                       }
                        CHECK(mkey_status(view, text));
                        first = ISC_FALSE;
                        break;
                case SYNC:
                        CHECK(dns_zone_flush(view->managed_keys));
                        break;
+               case DESTROY:
+                       CHECK(mkey_destroy(server, view, text));
+                       break;
                default:
                        INSIST(0);
                }
 
-               if (viewtxt != NULL)
+               if (viewtxt != NULL) {
                        break;
+               }
        }
 
-       if (!found)
+       if (!found) {
                CHECK(putstr(text, "no views with managed keys"));
+       }
 
  cleanup:
-       if (isc_buffer_usedlength(*text) > 0)
+       if (isc_buffer_usedlength(*text) > 0) {
                (void) putnull(text);
+       }
 
        return (result);
 }
index 959864523359e8b6208e9bb412dc9bce1eab6533..5974a522b31e7fa2a870afb1bd419359a468d377 100644 (file)
       </varlistentry>
 
       <varlistentry>
-       <term><userinput>managed-keys <replaceable>(status | refresh | sync)</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <term><userinput>managed-keys <replaceable>(status | refresh | sync | destroy)</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
        <listitem>
          <para>
-           When run with the "status" keyword, print the current
-           status of the managed-keys database for the specified
-           view, or for all views if none is specified.  When run
-           with the "refresh" keyword, force an immediate refresh
-           of all the managed-keys in the specified view, or all
-           views.  When run with the "sync" keyword, force an
-           immediate dump of the managed-keys database to disk (in
-           the file <filename>managed-keys.bind</filename> or
-           (<filename><replaceable>viewname</replaceable>.mkeys</filename>).
+            Inspect and control the "managed-keys" database which
+            handles RFC 5011 DNSSEC trust anchor maintenance. If a view
+            is specified, these commands are applied to that view;
+            otherwise they are applied to all views.
+          </para>
+          <itemizedlist>
+            <listitem>
+              <para>
+                When run with the <literal>status</literal> keyword, prints
+                the current status of the managed-keys database.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                When run with the <literal>refresh</literal> keyword,
+                forces an immediate refresh query to be sent for all
+                the managed keys, updating the managed-keys database
+                if any new keys are found, without waiting the normal
+                refresh interval.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                When run with the <literal>sync</literal> keyword, forces an
+                immediate dump of the managed-keys database to disk
+                (in the file <filename>managed-keys.bind</filename> or
+                (<filename><replaceable>viewname</replaceable>.mkeys</filename>).
+                This synchronizes the database with its journal file, so
+                that the database's current contents can be inspected
+                visually.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                When run with the <literal>destroy</literal> keyword, the
+                managed-keys database is shut down and deleted, and all key
+                maintenance is terminated.  This command should be used only
+                with extreme caution.
+              </para>
+              <para>
+                Existing keys that are already trusted are not deleted
+                from memory; DNSSEC validation can continue after this
+                command is used. However, key maintenance operations will
+                cease until <command>named</command> is restarted or
+                reconfigured, and all existing key maintenance state
+                will be deleted.
+              </para>
+              <para>
+                Running <command>rndc reconfig>/command> or restarting
+                <command>named</command> immediately after this command
+                will cause key maintenance to be reinitialized from scratch,
+                just as if the server were being started for the first time.
+                This is primarily intended for testing, but it may also be
+                used, for example, to jumpstart the acquisition of new keys
+                in the event of a trust anchor rollover, or as a
+                brute-force repair for key maintenance problems.
+              </para>
+            </listitem>
+          </itemizedlist>
          </para>
        </listitem>
       </varlistentry>
index cbeff3e1f7ba02e2cfd553e6e03cf210f61f6a0b..b9806f3431f4463e97846d1da9e8b70a419cd9c0 100644 (file)
@@ -548,5 +548,19 @@ grep "query '_ta-[0-9a-f]*/NULL/IN' approved" ns1/named.run > /dev/null || ret=1
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo "I: check 'rndc-managed-keys destroy' ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys destroy | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+grep "no views with managed keys" rndc.out.$n > /dev/null || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+grep "name: \." rndc.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 [ $status -eq 0 ] || exit 1
index 93d912c1bbb095b21282925317e5c1f992d31748..11dfa4e861991a4e65e7128f788d2767838bdcad 100644 (file)
          entropy source.  [RT #31459] [RT #46047]
        </para>
       </listitem>
+      <listitem>
+       <para>
+         <command>rndc managed-keys destroy</command> shuts down all
+         RFC 5011 DNSSEC trust anchor maintenance, and deletes any
+         existing managed keys database. If immediately followed by
+         <command>rndc reconfig</command>, this will reinitialize
+         key maintenance just as if the server was being started for
+         the first time.
+       </para>
+       <para>
+         This is intended for testing purposes, but can be used -- with
+         extreme caution -- as a brute-force repair for unrecoverable
+         problems with a managed keys database, to jumpstart the key
+         acquisition process if <filename>bind.keys</filename> is updated,
+         etc. [RT #32456]
+       </para>
+      </listitem>
     </itemizedlist>
   </section>