]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] 5011 tests and fixes
authorEvan Hunt <each@isc.org>
Fri, 6 Feb 2015 01:18:15 +0000 (17:18 -0800)
committerEvan Hunt <each@isc.org>
Fri, 6 Feb 2015 01:18:15 +0000 (17:18 -0800)
4056. [bug] Expanded automatic testing of trust anchor
management and fixed several small bugs including
a memory leak and a possible loss of key state
information. [RT #38458]

4055. [func] "rndc managed-keys" can be used to check status
of trust anchors or to force keys to be refreshed,
Also, the managed keys data file has easier-to-read
comments.  [RT #38458]

42 files changed:
CHANGES
bin/named/control.c
bin/named/include/named/control.h
bin/named/include/named/globals.h
bin/named/include/named/server.h
bin/named/main.c
bin/named/server.c
bin/rndc/rndc.docbook
bin/tests/system/conf.sh.in
bin/tests/system/dnssec/clean.sh
bin/tests/system/dnssec/ns3/sign.sh
bin/tests/system/dnssec/ns5/named1.conf [moved from bin/tests/system/dnssec/ns5/named.conf with 89% similarity]
bin/tests/system/dnssec/ns5/named2.conf [new file with mode: 0644]
bin/tests/system/dnssec/ns5/sign.sh [new file with mode: 0644]
bin/tests/system/dnssec/setup.sh
bin/tests/system/dnssec/tests.sh
bin/tests/system/mkeys/README [new file with mode: 0644]
bin/tests/system/mkeys/clean.sh [new file with mode: 0644]
bin/tests/system/mkeys/ns1/named1.conf [new file with mode: 0644]
bin/tests/system/mkeys/ns1/named2.conf [new file with mode: 0644]
bin/tests/system/mkeys/ns1/root.db [new file with mode: 0644]
bin/tests/system/mkeys/ns1/sign.sh [new file with mode: 0644]
bin/tests/system/mkeys/ns2/named.args [new file with mode: 0644]
bin/tests/system/mkeys/ns2/named.conf [new file with mode: 0644]
bin/tests/system/mkeys/ns3/named.args [new file with mode: 0644]
bin/tests/system/mkeys/ns3/named.conf [new file with mode: 0644]
bin/tests/system/mkeys/setup.sh [new file with mode: 0644]
bin/tests/system/mkeys/tests.sh [new file with mode: 0644]
doc/arm/notes.xml
lib/dns/include/dns/keytable.h
lib/dns/include/dns/nta.h
lib/dns/keytable.c
lib/dns/nta.c
lib/dns/rdata/generic/keydata_65533.c
lib/dns/win32/libdns.def.in
lib/dns/zone.c
lib/isc/buffer.c
lib/isc/httpd.c
lib/isc/tests/time_test.c
lib/isc/unix/include/isc/time.h
lib/isc/unix/time.c
lib/isc/win32/include/isc/time.h

diff --git a/CHANGES b/CHANGES
index 89bbcc9bb8f59e35d0129bab6ba2d4932047756d..92d839a35c268bbb65c1b280c110feff1cfb8527 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+4056.  [bug]           Expanded automatic testing of trust anchor
+                       management and fixed several small bugs including
+                       a memory leak and a possible loss of key state
+                       information. [RT #38458]
+
+4055.  [func]          "rndc managed-keys" can be used to check status
+                       of trust anchors or to force keys to be refreshed,
+                       Also, the managed keys data file has easier-to-read
+                       comments.  [RT #38458]
+
 4054.  [func]          Added a new tool 'mdig', a light weight clone of
                        dig able to send multiple pipelined queries.
                        [RT #38261]
index 3f11df5a67cd48a4931728c8a5cd16ec6148b1cb..d14b425a59f8a800ed835df5049a3f23a7d70f7d 100644 (file)
@@ -160,7 +160,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
                ns_server_dumpdb(ns_g_server, command);
                result = ISC_R_SUCCESS;
        } else if (command_compare(command, NS_COMMAND_SECROOTS)) {
-               result = ns_server_dumpsecroots(ns_g_server, command);
+               result = ns_server_dumpsecroots(ns_g_server, command, text);
        } else if (command_compare(command, NS_COMMAND_TRACE)) {
                result = ns_server_setdebuglevel(ns_g_server, command);
        } else if (command_compare(command, NS_COMMAND_NOTRACE)) {
@@ -220,6 +220,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
                result = ns_server_nta(ns_g_server, command, text);
        } else if (command_compare(command, NS_COMMAND_TESTGEN)) {
                result = ns_server_testgen(command, text);
+       } else if (command_compare(command, NS_COMMAND_MKEYS)) {
+               result = ns_server_mkeys(ns_g_server, command, text);
        } else {
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                              NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
index 24c677c928420506053dc930f0417e5a7fe8fd36..ce0d126cb794bc2f6815ad0770047fc8c21673e3 100644 (file)
@@ -71,6 +71,7 @@
 #define NS_COMMAND_ZONESTATUS  "zonestatus"
 #define NS_COMMAND_NTA         "nta"
 #define NS_COMMAND_TESTGEN     "testgen"
+#define NS_COMMAND_MKEYS       "managed-keys"
 
 isc_result_t
 ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
index 497d26ed5847f8118d2d5c3408d9518acdd5c40a..1c0b4e8afdbf7ee408cea27056a6f85221674d68 100644 (file)
@@ -175,7 +175,6 @@ EXTERN isc_boolean_t                ns_g_notcp              INIT(ISC_FALSE);
 EXTERN isc_boolean_t           ns_g_disable6           INIT(ISC_FALSE);
 EXTERN isc_boolean_t           ns_g_disable4           INIT(ISC_FALSE);
 
-
 #ifdef HAVE_GEOIP
 EXTERN dns_geoip_databases_t   *ns_g_geoip             INIT(NULL);
 #endif
index 7119ed16776e81215bfa70e34334217dfa7da6dd..ed7d3eb677767eaaaddfb9dd45c7b6137fdc9114 100644 (file)
@@ -301,7 +301,7 @@ ns_server_dumpdb(ns_server_t *server, char *args);
  * Dump the current security roots to the secroots file.
  */
 isc_result_t
-ns_server_dumpsecroots(ns_server_t *server, char *args);
+ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text);
 
 /*%
  * Change or increment the server debug level.
@@ -426,4 +426,11 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text);
  */
 isc_result_t
 ns_server_testgen(char *args, isc_buffer_t **text);
+
+/*%
+ * Force fefresh or print status for managed keys zones.
+ */
+isc_result_t
+ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text);
+
 #endif /* NAMED_SERVER_H */
index 367920c438e1ece718eb2f8ddec5c9364b26f326..47f088b9120d17757931e563d64b0bd033c443d3 100644 (file)
 #endif
 
 extern int isc_dscp_check_value;
+extern unsigned int dns_zone_mkey_hour;
+extern unsigned int dns_zone_mkey_day;
+extern unsigned int dns_zone_mkey_month;
 
 static isc_boolean_t   want_stats = ISC_FALSE;
 static char            program_name[ISC_DIR_NAMEMAX] = "named";
@@ -562,7 +565,38 @@ parse_command_line(int argc, char *argv[]) {
                        else if (!strncmp(isc_commandline_argument, "dscp=", 5))
                                isc_dscp_check_value =
                                           atoi(isc_commandline_argument + 5);
-                       else if (!strcmp(isc_commandline_argument, "notcp"))
+                       else if (!strncmp(isc_commandline_argument,
+                                         "mkeytimers=", 11))
+                       {
+                               p = strtok(isc_commandline_argument + 11, "/");
+                               if (p == NULL)
+                                       ns_main_earlyfatal("bad mkeytimer");
+                               dns_zone_mkey_hour = atoi(p);
+                               if (dns_zone_mkey_hour == 0)
+                                       ns_main_earlyfatal("bad mkeytimer");
+
+                               p = strtok(NULL, "/");
+                               if (p == NULL) {
+                                       dns_zone_mkey_day =
+                                               (24 * dns_zone_mkey_hour);
+                                       dns_zone_mkey_month =
+                                               (30 * dns_zone_mkey_day);
+                                       break;
+                               }
+                               dns_zone_mkey_day = atoi(p);
+                               if (dns_zone_mkey_day < dns_zone_mkey_hour)
+                                       ns_main_earlyfatal("bad mkeytimer");
+
+                               p = strtok(NULL, "/");
+                               if (p == NULL) {
+                                       dns_zone_mkey_month =
+                                               (30 * dns_zone_mkey_day);
+                                       break;
+                               }
+                               dns_zone_mkey_month = atoi(p);
+                               if (dns_zone_mkey_month < dns_zone_mkey_day)
+                                       ns_main_earlyfatal("bad mkeytimer");
+                       } else if (!strcmp(isc_commandline_argument, "notcp"))
                                ns_g_notcp = ISC_TRUE;
                        else
                                fprintf(stderr, "unknown -T flag '%s\n",
index 6064b28d79bb63b1838b7a9ada936abe3f4eb168..268f3adf10514adff02d937a5140e3f4e8e9b993 100644 (file)
@@ -90,6 +90,7 @@
 #include <dns/rdatastruct.h>
 #include <dns/resolver.h>
 #include <dns/rootns.h>
+#include <dns/rriterator.h>
 #include <dns/secalg.h>
 #include <dns/soa.h>
 #include <dns/stats.h>
@@ -7857,7 +7858,7 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
 }
 
 isc_result_t
-ns_server_dumpsecroots(ns_server_t *server, char *args) {
+ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text) {
        dns_view_t *view;
        dns_keytable_t *secroots = NULL;
        dns_ntatable_t *ntatable = NULL;
@@ -7872,13 +7873,25 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
        if (ptr == NULL)
                return (ISC_R_UNEXPECTEDEND);
 
+       /* "-" here means print the output instead of dumping to file */
        ptr = next_token(&args, " \t");
+       if (ptr != NULL && strcmp(ptr, "-") == 0)
+               ptr = next_token(&args, " \t");
+       else {
+               result = isc_stdio_open(server->secrootsfile, "w", &fp);
+               if (result != ISC_R_SUCCESS) {
+                       (void) putstr(text, "could not open ");
+                       (void) putstr(text, server->secrootsfile);
+                       CHECKMF(result, "could not open secroots dump file",
+                               server->secrootsfile);
+               }
+       }
 
-       CHECKMF(isc_stdio_open(server->secrootsfile, "w", &fp),
-               "could not open secroots dump file", server->secrootsfile);
        TIME_NOW(&now);
        isc_time_formattimestamp(&now, tbuf, sizeof(tbuf));
-       fprintf(fp, "%s\n", tbuf);
+       CHECK(putstr(text, "secure roots as of "));
+       CHECK(putstr(text, tbuf));
+       CHECK(putstr(text, ":\n"));
 
        do {
                for (view = ISC_LIST_HEAD(server->viewlist);
@@ -7894,12 +7907,10 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
                                result = ISC_R_SUCCESS;
                                continue;
                        }
-                       fprintf(fp, "\n Start view %s\n", view->name);
-                       fprintf(fp, "   Secure roots:\n\n");
-                       result = dns_keytable_dump(secroots, fp);
-                       if (result != ISC_R_SUCCESS)
-                               fprintf(fp, " dumpsecroots failed: %s\n",
-                                       isc_result_totext(result));
+                       CHECK(putstr(text, "\n Start view "));
+                       CHECK(putstr(text, view->name));
+                       CHECK(putstr(text, "\n   Secure roots:\n\n"));
+                       CHECK(dns_keytable_totext(secroots, text));
 
                        if (ntatable != NULL)
                                dns_ntatable_detach(&ntatable);
@@ -7908,23 +7919,30 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
                                result = ISC_R_SUCCESS;
                                continue;
                        }
-                       fprintf(fp, "\n   Negative trust anchors:\n\n");
-                       result = dns_ntatable_dump(ntatable, fp);
-                       if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
-                               fprintf(fp, " dumpntatable failed: %s\n",
-                                       isc_result_totext(result));
+                       CHECK(putstr(text, "\n   Negative trust anchors:\n\n"));
+                       CHECK(dns_ntatable_totext(ntatable, text));
                }
                if (ptr != NULL)
                        ptr = next_token(&args, " \t");
        } while (ptr != NULL);
 
  cleanup:
+       if (isc_buffer_usedlength(*text) > 0) {
+               if (fp != NULL)
+                       (void)putstr(text, "\n");
+               else
+                       (void)putnull(text);
+       }
        if (secroots != NULL)
                dns_keytable_detach(&secroots);
        if (ntatable != NULL)
                dns_ntatable_detach(&ntatable);
-       if (fp != NULL)
+       if (fp != NULL) {
+               fprintf(fp, "%.*s", (int) isc_buffer_usedlength(*text),
+                       (char *) isc_buffer_base(*text));
+               isc_buffer_clear(*text);
                (void)isc_stdio_close(fp);
+       }
        if (result == ISC_R_SUCCESS)
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
@@ -8297,7 +8315,9 @@ ns_server_status(ns_server_t *server, isc_buffer_t **text) {
        unsigned int zonecount, xferrunning, xferdeferred, soaqueries;
        unsigned int automatic;
        const char *ob = "", *cb = "", *alt = "";
-       char boottime[80], configtime[80], line[1024];
+       char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       char line[1024];
 
        if (ns_g_server->version_set) {
                ob = " (";
@@ -10039,7 +10059,11 @@ ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text) {
        const char *type, *file, *zonename = NULL;
        isc_uint32_t serial, signed_serial, nodes;
        char serbuf[16], sserbuf[16], nodebuf[16], resignbuf[512];
-       char lbuf[80], xbuf[80], rbuf[80], kbuf[80], rtbuf[80];
+       char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
        isc_time_t loadtime, expiretime, refreshtime;
        isc_time_t refreshkeytime, resigntime;
        dns_zonetype_t zonetype;
@@ -10217,7 +10241,7 @@ ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text) {
        }
 
        if (! isc_time_isepoch(&refreshtime)) {
-               CHECK(putstr(text, "\nnext refresh: "));
+               CHECK(putstr(text, "\nnext managed-keys refresh: "));
                CHECK(putstr(text, rbuf));
        }
 
@@ -10394,6 +10418,7 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) {
                        }
                        CHECK(dns_ntatable_totext(ntatable, text));
                }
+               CHECK(putnull(text));
 
                goto cleanup;
        }
@@ -10555,3 +10580,275 @@ ns_server_loadnta(ns_server_t *server) {
 
        return (ISC_R_SUCCESS);
 }
+
+static isc_result_t
+mkey_refresh(dns_view_t *view, isc_buffer_t **text) {
+       isc_result_t result;
+       char msg[DNS_NAME_FORMATSIZE + 500] = "";
+
+       snprintf(msg, sizeof(msg),
+                "refreshing managed keys for '%s'", view->name);
+       CHECK(putstr(text, msg));
+       CHECK(dns_zone_synckeyzone(view->managed_keys));
+
+ cleanup:
+       return (result);
+}
+
+static isc_result_t
+mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) {
+       isc_result_t result;
+       dns_db_t *db = NULL;
+       dns_dbversion_t *ver = NULL;
+       dns_rriterator_t rrit;
+       isc_stdtime_t now;
+       dns_name_t *prevname = NULL;
+
+       isc_stdtime_get(&now);
+
+       CHECK(dns_zone_getdb(view->managed_keys, &db));
+       dns_db_currentversion(db, &ver);
+       dns_rriterator_init(&rrit, db, ver, 0);
+       for (result = dns_rriterator_first(&rrit);
+            result == ISC_R_SUCCESS;
+            result = dns_rriterator_nextrrset(&rrit))
+       {
+               char buf[DNS_NAME_FORMATSIZE + 500];
+               dns_name_t *name = NULL;
+               dns_rdataset_t *kdset = NULL;
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dns_rdata_keydata_t kd;
+               isc_uint32_t ttl;
+
+               dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
+               if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
+                   !dns_rdataset_isassociated(kdset))
+                       continue;
+
+               if (name != prevname) {
+                       char nbuf[DNS_NAME_FORMATSIZE];
+                       dns_name_format(name, nbuf, sizeof(nbuf));
+                       snprintf(buf, sizeof(buf), "\n\n    name: %s", nbuf);
+                       CHECK(putstr(text, buf));
+               }
+                       
+
+               for (result = dns_rdataset_first(kdset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(kdset))
+               {
+                       char alg[DNS_SECALG_FORMATSIZE];
+                       char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+                       dns_keytag_t keyid;
+                       isc_region_t r;
+                       isc_time_t t;
+                       isc_boolean_t revoked;
+
+                       dns_rdata_reset(&rdata);
+                       dns_rdataset_current(kdset, &rdata);
+                       result = dns_rdata_tostruct(&rdata, &kd, NULL);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+                       dns_rdata_toregion(&rdata, &r);
+                       isc_region_consume(&r, 12);
+                       keyid = dst_region_computeid(&r, kd.algorithm);
+
+                       snprintf(buf, sizeof(buf), "\n    keyid: %u", keyid);
+                       CHECK(putstr(text, buf));
+
+                       dns_secalg_format(kd.algorithm, alg, sizeof(alg));
+                       snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg);
+                       CHECK(putstr(text, buf));
+
+                       revoked = ISC_TF((kd.flags & DNS_KEYFLAG_REVOKE) != 0);
+                       snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s",
+                                revoked ? " REVOKE" : "",
+                                ((kd.flags & DNS_KEYFLAG_KSK) != 0)
+                                  ? " SEP" : "",
+                                (kd.flags == 0) ? " (none)" : "");
+                       CHECK(putstr(text, buf));
+
+                       isc_time_set(&t, kd.refresh, 0);
+                       isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf));
+                       snprintf(buf, sizeof(buf),
+                                "\n\tnext refresh: %s", tbuf);
+                       CHECK(putstr(text, buf));
+
+                       if (kd.removehd != 0) {
+                               isc_time_set(&t, kd.removehd, 0);
+                               isc_time_formathttptimestamp(&t, tbuf,
+                                                            sizeof(tbuf));
+                               snprintf(buf, sizeof(buf),
+                                        "\n\tremove at: %s", tbuf);
+                               CHECK(putstr(text, buf));
+                       }
+
+                       isc_time_set(&t, kd.addhd, 0);
+                       isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf));
+                       if (kd.addhd == 0)
+                               snprintf(buf, sizeof(buf), "\n\tno trust");
+                       else if (revoked)
+                               snprintf(buf, sizeof(buf),
+                                        "\n\ttrust revoked");
+                       else if (kd.addhd < now)
+                               snprintf(buf, sizeof(buf),
+                                        "\n\ttrusted since: %s", tbuf);
+                       else if (kd.addhd >= now)
+                               snprintf(buf, sizeof(buf),
+                                        "\n\ttrust pending: %s", tbuf);
+                       CHECK(putstr(text, buf));
+               }
+       }
+
+       if (result == ISC_R_NOMORE)
+               result = ISC_R_SUCCESS;
+
+ cleanup:
+       if (ver != NULL) {
+               dns_rriterator_destroy(&rrit);
+               dns_db_closeversion(db, &ver, ISC_FALSE);
+       }
+       if (db != NULL)
+               dns_db_detach(&db);
+
+       return (result);
+}
+
+static isc_result_t
+mkey_status(dns_view_t *view, isc_buffer_t **text) {
+       isc_result_t result;
+       char msg[ISC_FORMATHTTPTIMESTAMP_SIZE];
+       isc_time_t t;
+
+       CHECK(putstr(text, "view: "));
+       CHECK(putstr(text, view->name));
+
+       CHECK(putstr(text, "\nnext scheduled event: "));
+
+       dns_zone_getrefreshkeytime(view->managed_keys, &t);
+       if (isc_time_isepoch(&t)) {
+               CHECK(putstr(text, "never"));
+       } else {
+               isc_time_formathttptimestamp(&t, msg, sizeof(msg));
+               CHECK(putstr(text, msg));
+       }
+
+       CHECK(mkey_dumpzone(view, text));
+
+ cleanup:
+       return (result);
+}
+
+isc_result_t
+ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text) {
+       char *cmd, *classtxt, *viewtxt = NULL;
+       isc_result_t result = ISC_R_SUCCESS;
+       dns_view_t *view = NULL;
+       dns_rdataclass_t rdclass;
+       char msg[DNS_NAME_FORMATSIZE + 500] = "";
+       enum { NONE, STATUS, REFRESH, SYNC } opt = NONE;
+       isc_boolean_t found = ISC_FALSE;
+
+       /* Skip rndc command name */
+       cmd = next_token(&args, " \t");
+       if (cmd == NULL)
+               return (ISC_R_UNEXPECTEDEND);
+
+       /* Get managed-keys subcommand */
+       cmd = next_token(&args, " \t");
+       if (cmd == NULL)
+               return (ISC_R_UNEXPECTEDEND);
+
+       if (strcasecmp(cmd, "status") == 0)
+               opt = STATUS;
+       else if (strcasecmp(cmd, "refresh") == 0)
+               opt = REFRESH;
+       else if (strcasecmp(cmd, "sync") == 0)
+               opt = SYNC;
+       else {
+               snprintf(msg, sizeof(msg), "unknown command '%s'", cmd);
+               (void) putstr(text, msg);
+               result = ISC_R_UNEXPECTED;
+               goto cleanup;
+       }
+
+       /* Look for the optional class name. */
+       classtxt = next_token(&args, " \t");
+       if (classtxt != NULL) {
+               /* Look for the optional view name. */
+               viewtxt = next_token(&args, " \t");
+       }
+
+       if (classtxt == NULL) {
+               rdclass = dns_rdataclass_in;
+       } else {
+               isc_textregion_t r;
+               r.base = classtxt;
+               r.length = strlen(classtxt);
+               result = dns_rdataclass_fromtext(&rdclass, &r);
+               if (result != ISC_R_SUCCESS) {
+                       if (viewtxt == NULL) {
+                               rdclass = dns_rdataclass_in;
+                               viewtxt = classtxt;
+                               result = ISC_R_SUCCESS;
+                       } else {
+                               snprintf(msg, sizeof(msg),
+                                        "unknown class '%s'", classtxt);
+                               (void) putstr(text, msg);
+                               goto cleanup;
+                       }
+               }
+       }
+
+       for (view = ISC_LIST_HEAD(server->viewlist);
+            view != NULL;
+            view = ISC_LIST_NEXT(view, link))
+       {
+               isc_boolean_t first = ISC_TRUE;
+               if (viewtxt != NULL &&
+                   (rdclass != view->rdclass ||
+                    strcmp(view->name, viewtxt) != 0))
+                       continue;
+
+               if (view->managed_keys == NULL) {
+                       if (viewtxt != NULL) {
+                               snprintf(msg, sizeof(msg),
+                                        "view '%s': no managed keys", viewtxt);
+                               CHECK(putstr(text, msg));
+                               goto cleanup;
+                       } else
+                               continue;
+               }
+
+               found = ISC_TRUE;
+
+               switch (opt) {
+               case REFRESH:
+                       CHECK(mkey_refresh(view, text));
+                       break;
+               case STATUS:
+                       if (!first)
+                               CHECK(putstr(text, "\n"));
+                       CHECK(mkey_status(view, text));
+                       first = ISC_FALSE;
+                       break;
+               case SYNC:
+                       CHECK(dns_zone_flush(view->managed_keys));
+                       break;
+               default:
+                       INSIST(0);
+               }
+
+               if (viewtxt != NULL)
+                       break;
+       }
+
+       if (!found)
+               CHECK(putstr(text, "no views with managed keys"));
+
+ cleanup:
+       if (isc_buffer_usedlength(*text) > 0)
+               (void) putnull(text);
+
+       return (result);
+}
index b45d2bf764edb89d7d2f6490894a581dd9fa0666..f520ee1a2adc8de8084c95a39e6fbd8dd8415535 100644 (file)
@@ -1,6 +1,6 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-               [<!ENTITY mdash "&#8212;">]>
+              "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+              [<!ENTITY mdash "&#8212;">]>
 <!--
  - Copyright (C) 2004, 2005, 2007, 2013-2015  Internet Systems Consortium, Inc. ("ISC")
  - Copyright (C) 2000, 2001  Internet Software Consortium.
 
     <variablelist>
       <varlistentry>
-        <term>-b <replaceable class="parameter">source-address</replaceable></term>
-        <listitem>
-          <para>
-            Use <replaceable class="parameter">source-address</replaceable>
-            as the source address for the connection to the server.
-            Multiple instances are permitted to allow setting of both
-            the IPv4 and IPv6 source addresses.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-c <replaceable class="parameter">config-file</replaceable></term>
-        <listitem>
-          <para>
-            Use <replaceable class="parameter">config-file</replaceable>
-            as the configuration file instead of the default,
-            <filename>/etc/rndc.conf</filename>.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-k <replaceable class="parameter">key-file</replaceable></term>
-        <listitem>
-          <para>
-            Use <replaceable class="parameter">key-file</replaceable>
-            as the key file instead of the default,
-            <filename>/etc/rndc.key</filename>.  The key in
-            <filename>/etc/rndc.key</filename> will be used to
-            authenticate
-            commands sent to the server if the <replaceable class="parameter">config-file</replaceable>
-            does not exist.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-s <replaceable class="parameter">server</replaceable></term>
-        <listitem>
-          <para><replaceable class="parameter">server</replaceable> is
-            the name or address of the server which matches a
-            server statement in the configuration file for
-            <command>rndc</command>.  If no server is supplied on the
-            command line, the host named by the default-server clause
-            in the options statement of the <command>rndc</command>
-            configuration file will be used.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-p <replaceable class="parameter">port</replaceable></term>
-        <listitem>
-          <para>
-            Send commands to TCP port
-            <replaceable class="parameter">port</replaceable>
-            instead
-            of BIND 9's default control channel port, 953.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-q</term>
-        <listitem>
-          <para>
-            Quiet mode: Message text returned by the server
-            will not be printed except when there is an error.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-V</term>
-        <listitem>
-          <para>
-            Enable verbose logging.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term>-y <replaceable class="parameter">key_id</replaceable></term>
-        <listitem>
-          <para>
-            Use the key <replaceable class="parameter">key_id</replaceable>
-            from the configuration file.
-            <replaceable class="parameter">key_id</replaceable>
-            must be
-            known by named with the same algorithm and secret string
-            in order for control message validation to succeed.
-            If no <replaceable class="parameter">key_id</replaceable>
-            is specified, <command>rndc</command> will first look
-            for a key clause in the server statement of the server
-            being used, or if no server statement is present for that
-            host, then the default-key clause of the options statement.
-            Note that the configuration file contains shared secrets
-            which are used to send authenticated control commands
-            to name servers.  It should therefore not have general read
-            or write access.
-          </para>
-        </listitem>
+       <term>-b <replaceable class="parameter">source-address</replaceable></term>
+       <listitem>
+         <para>
+           Use <replaceable class="parameter">source-address</replaceable>
+           as the source address for the connection to the server.
+           Multiple instances are permitted to allow setting of both
+           the IPv4 and IPv6 source addresses.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-c <replaceable class="parameter">config-file</replaceable></term>
+       <listitem>
+         <para>
+           Use <replaceable class="parameter">config-file</replaceable>
+           as the configuration file instead of the default,
+           <filename>/etc/rndc.conf</filename>.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-k <replaceable class="parameter">key-file</replaceable></term>
+       <listitem>
+         <para>
+           Use <replaceable class="parameter">key-file</replaceable>
+           as the key file instead of the default,
+           <filename>/etc/rndc.key</filename>.  The key in
+           <filename>/etc/rndc.key</filename> will be used to
+           authenticate
+           commands sent to the server if the <replaceable class="parameter">config-file</replaceable>
+           does not exist.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-s <replaceable class="parameter">server</replaceable></term>
+       <listitem>
+         <para><replaceable class="parameter">server</replaceable> is
+           the name or address of the server which matches a
+           server statement in the configuration file for
+           <command>rndc</command>.  If no server is supplied on the
+           command line, the host named by the default-server clause
+           in the options statement of the <command>rndc</command>
+           configuration file will be used.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-p <replaceable class="parameter">port</replaceable></term>
+       <listitem>
+         <para>
+           Send commands to TCP port
+           <replaceable class="parameter">port</replaceable>
+           instead
+           of BIND 9's default control channel port, 953.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-q</term>
+       <listitem>
+         <para>
+           Quiet mode: Message text returned by the server
+           will not be printed except when there is an error.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-V</term>
+       <listitem>
+         <para>
+           Enable verbose logging.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-y <replaceable class="parameter">key_id</replaceable></term>
+       <listitem>
+         <para>
+           Use the key <replaceable class="parameter">key_id</replaceable>
+           from the configuration file.
+           <replaceable class="parameter">key_id</replaceable>
+           must be
+           known by named with the same algorithm and secret string
+           in order for control message validation to succeed.
+           If no <replaceable class="parameter">key_id</replaceable>
+           is specified, <command>rndc</command> will first look
+           for a key clause in the server statement of the server
+           being used, or if no server statement is present for that
+           host, then the default-key clause of the options statement.
+           Note that the configuration file contains shared secrets
+           which are used to send authenticated control commands
+           to name servers.  It should therefore not have general read
+           or write access.
+         </para>
+       </listitem>
       </varlistentry>
 
     </variablelist>
 
     <variablelist>
       <varlistentry>
-        <term><userinput>reload</userinput></term>
-        <listitem>
-          <para>
-            Reload configuration file and zones.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>reload <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Reload the given zone.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>refresh <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Schedule zone maintenance for the given zone.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>retransfer <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Retransfer the given slave zone from the master server.
-          </para>
-          <para>
-            If the zone is configured to use
-            <command>inline-signing</command>, the signed
-            version of the zone is discarded; after the
-            retransfer of the unsigned version is complete, the
-            signed version will be regenerated with all new
-            signatures.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>sign <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Fetch all DNSSEC keys for the given zone
-            from the key directory (see the 
-            <command>key-directory</command> option in
-            the BIND 9 Administrator Reference Manual).  If they are within
-            their publication period, merge them into the
-            zone's DNSKEY RRset.  If the DNSKEY RRset
-            is changed, then the zone is automatically
-            re-signed with the new key set.
-          </para>
-          <para>
-            This command requires that the
-            <command>auto-dnssec</command> zone option be set
-            to <literal>allow</literal> or
-            <literal>maintain</literal>,
-            and also requires the zone to be configured to
-            allow dynamic DNS.
-            (See "Dynamic Update Policies" in the Administrator
-            Reference Manual for more details.)
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>loadkeys <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Fetch all DNSSEC keys for the given zone
-            from the key directory.  If they are within
-            their publication period, merge them into the
-            zone's DNSKEY RRset.  Unlike <command>rndc
-            sign</command>, however, the zone is not
-            immediately re-signed by the new keys, but is
-            allowed to incrementally re-sign over time.
-          </para>
-          <para>
-            This command requires that the
-            <command>auto-dnssec</command> zone option
-            be set to <literal>maintain</literal>,
-            and also requires the zone to be configured to
-            allow dynamic DNS.
-            (See "Dynamic Update Policies" in the Administrator
-            Reference Manual for more details.)
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>freeze <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Suspend updates to a dynamic zone.  If no zone is
-            specified, then all zones are suspended.  This allows
-            manual edits to be made to a zone normally updated by
-            dynamic update.  It also causes changes in the
-            journal file to be synced into the master file.
-            All dynamic update attempts will be refused while
-            the zone is frozen.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>thaw <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Enable updates to a frozen dynamic zone.  If no
-            zone is specified, then all frozen zones are
-            enabled.  This causes the server to reload the zone
-            from disk, and re-enables dynamic updates after the
-            load has completed.  After a zone is thawed,
-            dynamic updates will no longer be refused.  If
-            the zone has changed and the
-            <command>ixfr-from-differences</command> option is
-            in use, then the journal file will be updated to
-            reflect changes in the zone.  Otherwise, if the
-            zone has changed, any existing journal file will be
-            removed.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>scan</userinput></term>
-        <listitem>
-          <para>
-             Scan the list of available network interfaces
-             for changes, without performing a full
-             <command>reconfig</command> or waiting for the
-             <command>interface-interval</command> timer.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>sync <optional>-clean</optional> <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Sync changes in the journal file for a dynamic zone
-            to the master file.  If the "-clean" option is
-            specified, the journal file is also removed.  If
-            no zone is specified, then all zones are synced.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>notify <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Resend NOTIFY messages for the zone.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>reconfig</userinput></term>
-        <listitem>
-          <para>
-            Reload the configuration file and load new zones,
-            but do not reload existing zone files even if they
-            have changed.
-            This is faster than a full <command>reload</command> when there
-            is a large number of zones because it avoids the need
-            to examine the
-            modification times of the zones files.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>zonestatus <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
-        <listitem>
-          <para>
-            Displays the current status of the given zone,
-            including the master file name and any include
-            files from which it was loaded, when it was most
-            recently loaded, the current serial number, the
-            number of nodes, whether the zone supports
-            dynamic updates, whether the zone is DNSSEC
-            signed, whether it uses automatic DNSSEC key
-            management or inline signing, and the scheduled
-            refresh or expiry times for the zone.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>stats</userinput></term>
-        <listitem>
-          <para>
-            Write server statistics to the statistics file.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>querylog</userinput> <optional>on|off</optional> </term>
-        <listitem>
-          <para>
-            Enable or disable query logging.  (For backward
-            compatibility, this command can also be used without
-            an argument to toggle query logging on and off.)
-          </para>
-          <para>
-            Query logging can also be enabled
-            by explicitly directing the <command>queries</command>
-            <command>category</command> to a
-            <command>channel</command> in the
-            <command>logging</command> section of
-            <filename>named.conf</filename> or by specifying
-            <command>querylog yes;</command> in the
-            <command>options</command> section of
-            <filename>named.conf</filename>.
-          </para>
-        </listitem>
-      </varlistentry>
-
+       <term><userinput>reload</userinput></term>
+       <listitem>
+         <para>
+           Reload configuration file and zones.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>reload <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Reload the given zone.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>refresh <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Schedule zone maintenance for the given zone.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>retransfer <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Retransfer the given slave zone from the master server.
+         </para>
+         <para>
+           If the zone is configured to use
+           <command>inline-signing</command>, the signed
+           version of the zone is discarded; after the
+           retransfer of the unsigned version is complete, the
+           signed version will be regenerated with all new
+           signatures.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>sign <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Fetch all DNSSEC keys for the given zone
+           from the key directory (see the 
+           <command>key-directory</command> option in
+           the BIND 9 Administrator Reference Manual).  If they are within
+           their publication period, merge them into the
+           zone's DNSKEY RRset.  If the DNSKEY RRset
+           is changed, then the zone is automatically
+           re-signed with the new key set.
+         </para>
+         <para>
+           This command requires that the
+           <command>auto-dnssec</command> zone option be set
+           to <literal>allow</literal> or
+           <literal>maintain</literal>,
+           and also requires the zone to be configured to
+           allow dynamic DNS.
+           (See "Dynamic Update Policies" in the Administrator
+           Reference Manual for more details.)
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>loadkeys <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Fetch all DNSSEC keys for the given zone
+           from the key directory.  If they are within
+           their publication period, merge them into the
+           zone's DNSKEY RRset.  Unlike <command>rndc
+           sign</command>, however, the zone is not
+           immediately re-signed by the new keys, but is
+           allowed to incrementally re-sign over time.
+         </para>
+         <para>
+           This command requires that the
+           <command>auto-dnssec</command> zone option
+           be set to <literal>maintain</literal>,
+           and also requires the zone to be configured to
+           allow dynamic DNS.
+           (See "Dynamic Update Policies" in the Administrator
+           Reference Manual for more details.)
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>freeze <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Suspend updates to a dynamic zone.  If no zone is
+           specified, then all zones are suspended.  This allows
+           manual edits to be made to a zone normally updated by
+           dynamic update.  It also causes changes in the
+           journal file to be synced into the master file.
+           All dynamic update attempts will be refused while
+           the zone is frozen.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>thaw <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Enable updates to a frozen dynamic zone.  If no
+           zone is specified, then all frozen zones are
+           enabled.  This causes the server to reload the zone
+           from disk, and re-enables dynamic updates after the
+           load has completed.  After a zone is thawed,
+           dynamic updates will no longer be refused.  If
+           the zone has changed and the
+           <command>ixfr-from-differences</command> option is
+           in use, then the journal file will be updated to
+           reflect changes in the zone.  Otherwise, if the
+           zone has changed, any existing journal file will be
+           removed.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>scan</userinput></term>
+       <listitem>
+         <para>
+            Scan the list of available network interfaces
+            for changes, without performing a full
+            <command>reconfig</command> or waiting for the
+            <command>interface-interval</command> timer.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>sync <optional>-clean</optional> <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Sync changes in the journal file for a dynamic zone
+           to the master file.  If the "-clean" option is
+           specified, the journal file is also removed.  If
+           no zone is specified, then all zones are synced.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>notify <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Resend NOTIFY messages for the zone.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>reconfig</userinput></term>
+       <listitem>
+         <para>
+           Reload the configuration file and load new zones,
+           but do not reload existing zone files even if they
+           have changed.
+           This is faster than a full <command>reload</command> when there
+           is a large number of zones because it avoids the need
+           to examine the
+           modification times of the zones files.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>zonestatus <optional><replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+       <listitem>
+         <para>
+           Displays the current status of the given zone,
+           including the master file name and any include
+           files from which it was loaded, when it was most
+           recently loaded, the current serial number, the
+           number of nodes, whether the zone supports
+           dynamic updates, whether the zone is DNSSEC
+           signed, whether it uses automatic DNSSEC key
+           management or inline signing, and the scheduled
+           refresh or expiry times for the zone.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>managed-keys <replaceable>(status | refresh | sync)</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></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>).
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>stats</userinput></term>
+       <listitem>
+         <para>
+           Write server statistics to the statistics file.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>querylog</userinput> <optional>on|off</optional> </term>
+       <listitem>
+         <para>
+           Enable or disable query logging.  (For backward
+           compatibility, this command can also be used without
+           an argument to toggle query logging on and off.)
+         </para>
+         <para>
+           Query logging can also be enabled
+           by explicitly directing the <command>queries</command>
+           <command>category</command> to a
+           <command>channel</command> in the
+           <command>logging</command> section of
+           <filename>named.conf</filename> or by specifying
+           <command>querylog yes;</command> in the
+           <command>options</command> section of
+           <filename>named.conf</filename>.
+         </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
-        <term><userinput>dumpdb <optional>-all|-cache|-zone</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
-        <listitem>
-          <para>
-            Dump the server's caches (default) and/or zones to
-            the
-            dump file for the specified views.  If no view is
-            specified, all
-            views are dumped.
-          </para>
-        </listitem>
+       <term><userinput>dumpdb <optional>-all|-cache|-zone</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
+       <listitem>
+         <para>
+           Dump the server's caches (default) and/or zones to
+           the
+           dump file for the specified views.  If no view is
+           specified, all
+           views are dumped.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>secroots <optional><replaceable>view ...</replaceable></optional></userinput></term>
-        <listitem>
-          <para>
-            Dump the server's security roots and negative trust anchors
-            to the secroots file for the specified views.  If no view is
-            specified, all views are dumped.
-          </para>
-        </listitem>
-      </varlistentry>
-
+       <term><userinput>secroots <optional>-</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
+       <listitem>
+         <para>
+           Dump the server's security roots and negative trust anchors
+           for the specified views.  If no view is specified, all views
+           are dumped.
+         </para>
+         <para>
+           If the first argument is "-", then the output is
+           returned via the <command>rndc</command> response channel
+           and printed to the standard output.
+           Otherwise, it is written to the secroots dump file, which
+           defaults to <filename>named.secroots</filename>, but can be
+           overridden via the <option>secroots-file</option> option in
+           <filename>named.conf</filename>.
+         </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
-        <term><userinput>stop <optional>-p</optional></userinput></term>
-        <listitem>
-          <para>
-            Stop the server, making sure any recent changes
-            made through dynamic update or IXFR are first saved to
-            the master files of the updated zones.
-            If <option>-p</option> is specified <command>named</command>'s process id is returned.
-            This allows an external process to determine when <command>named</command>
-            had completed stopping.
-          </para>
-        </listitem>
+       <term><userinput>stop <optional>-p</optional></userinput></term>
+       <listitem>
+         <para>
+           Stop the server, making sure any recent changes
+           made through dynamic update or IXFR are first saved to
+           the master files of the updated zones.
+           If <option>-p</option> is specified <command>named</command>'s process id is returned.
+           This allows an external process to determine when <command>named</command>
+           had completed stopping.
+         </para>
+       </listitem>
       </varlistentry>
-
-      <varlistentry>
-        <term><userinput>halt <optional>-p</optional></userinput></term>
-        <listitem>
-          <para>
-            Stop the server immediately.  Recent changes
-            made through dynamic update or IXFR are not saved to
-            the master files, but will be rolled forward from the
-            journal files when the server is restarted.
-            If <option>-p</option> is specified <command>named</command>'s process id is returned.
-            This allows an external process to determine when <command>named</command>
-            had completed halting.
-          </para>
-        </listitem>
+
+      <varlistentry>
+       <term><userinput>halt <optional>-p</optional></userinput></term>
+       <listitem>
+         <para>
+           Stop the server immediately.  Recent changes
+           made through dynamic update or IXFR are not saved to
+           the master files, but will be rolled forward from the
+           journal files when the server is restarted.
+           If <option>-p</option> is specified <command>named</command>'s process id is returned.
+           This allows an external process to determine when <command>named</command>
+           had completed halting.
+         </para>
+       </listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><userinput>trace</userinput></term>
-        <listitem>
-          <para>
-            Increment the servers debugging level by one.
-          </para>
-        </listitem>
+      <varlistentry>
+       <term><userinput>trace</userinput></term>
+       <listitem>
+         <para>
+           Increment the servers debugging level by one.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>trace <replaceable>level</replaceable></userinput></term>
-        <listitem>
-          <para>
-            Sets the server's debugging level to an explicit
-            value.
-          </para>
-        </listitem>
+       <term><userinput>trace <replaceable>level</replaceable></userinput></term>
+       <listitem>
+         <para>
+           Sets the server's debugging level to an explicit
+           value.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>notrace</userinput></term>
-        <listitem>
-          <para>
-            Sets the server's debugging level to 0.
-          </para>
-        </listitem>
-      </varlistentry>
+       <term><userinput>notrace</userinput></term>
+       <listitem>
+         <para>
+           Sets the server's debugging level to 0.
+         </para>
+       </listitem>
+      </varlistentry>
 
       <varlistentry>
-        <term><userinput>flush</userinput></term>
-        <listitem>
-          <para>
-            Flushes the server's cache.
-          </para>
-        </listitem>
+       <term><userinput>flush</userinput></term>
+       <listitem>
+         <para>
+           Flushes the server's cache.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>flushname</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
-        <listitem>
-          <para>
-            Flushes the given name from the view's DNS cache
-            and, if applicable, from the view's nameserver address
-            database, bad server cache and SERVFAIL cache.
-          </para>
-        </listitem>
+       <term><userinput>flushname</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
+       <listitem>
+         <para>
+           Flushes the given name from the view's DNS cache
+           and, if applicable, from the view's nameserver address
+           database, bad server cache and SERVFAIL cache.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>flushtree</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
-        <listitem>
-          <para>
-            Flushes the given name, and all of its subdomains,
-            from the view's DNS cache, address database,
-            bad server cache, and SERVFAIL cache.
-          </para>
-        </listitem>
+       <term><userinput>flushtree</userinput> <replaceable>name</replaceable> <optional><replaceable>view</replaceable></optional> </term>
+       <listitem>
+         <para>
+           Flushes the given name, and all of its subdomains,
+           from the view's DNS cache, address database,
+           bad server cache, and SERVFAIL cache.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>status</userinput></term>
-        <listitem>
-          <para>
-            Display status of the server.
-            Note that the number of zones includes the internal <command>bind/CH</command> zone
-            and the default <command>./IN</command>
-            hint zone if there is not an
-            explicit root zone configured.
-          </para>
-        </listitem>
+       <term><userinput>status</userinput></term>
+       <listitem>
+         <para>
+           Display status of the server.
+           Note that the number of zones includes the internal <command>bind/CH</command> zone
+           and the default <command>./IN</command>
+           hint zone if there is not an
+           explicit root zone configured.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>recursing</userinput></term>
-        <listitem>
-          <para>
-            Dump the list of queries <command>named</command> is currently recursing
-            on.
-          </para>
-        </listitem>
+       <term><userinput>recursing</userinput></term>
+       <listitem>
+         <para>
+           Dump the list of queries <command>named</command> is currently recursing
+           on.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>validation ( on | off | check ) <optional><replaceable>view ...</replaceable></optional> </userinput></term>
-        <listitem>
-          <para>
-            Enable, disable, or check the current status of
-            DNSSEC validation.
-            Note <command>dnssec-enable</command> also needs to be
-            set to <userinput>yes</userinput> or
-            <userinput>auto</userinput> to be effective.
-            It defaults to enabled.
-          </para>
-        </listitem>
+       <term><userinput>validation ( on | off | check ) <optional><replaceable>view ...</replaceable></optional> </userinput></term>
+       <listitem>
+         <para>
+           Enable, disable, or check the current status of
+           DNSSEC validation.
+           Note <command>dnssec-enable</command> also needs to be
+           set to <userinput>yes</userinput> or
+           <userinput>auto</userinput> to be effective.
+           It defaults to enabled.
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>nta
+       <term><userinput>nta
        <optional>( -d | -f | -r | -l <replaceable>duration</replaceable>)</optional>
        <replaceable>domain</replaceable>
        <optional><replaceable>view</replaceable></optional>
        </userinput></term>
-        <listitem>
-          <para>
-            Sets a DNSSEC negative trust anchor (NTA)
-            for <option>domain</option>, with a lifetime of
-            <option>duration</option>.  The default lifetime is
-            configured in <filename>named.conf</filename> via the
-            <option>nta-lifetime</option> option, and defaults to
-            one hour.  The lifetime cannot exceed one week.
-          </para>
-          <para>
-            A negative trust anchor selectively disables
-            DNSSEC validation for zones that are known to be
-            failing because of misconfiguration rather than
-            an attack.  When data to be validated is
-            at or below an active NTA (and above any other
-            configured trust anchors), <command>named</command> will
-            abort the DNSSEC validation process and treat the data as
-            insecure rather than bogus.  This continues until the
-            NTA's lifetime is elapsed.
-          </para>
-          <para>
-            NTAs persist across restarts of the named server.
-            The NTAs for a view are saved in a file called
-            <filename><replaceable>name</replaceable>.nta</filename>,
-            where <replaceable>name</replaceable> is the
-            name of the view, or if it contains characters
-            that are incompatible with use as a file name, a
-            cryptographic hash generated from the name
-            of the view.
-          </para>
-          <para>
-            An existing NTA can be removed by using the
-            <option>-remove</option> option.
-          </para>
-          <para>
-            An NTA's lifetime can be specified with the
-            <option>-lifetime</option> option.  TTL-style
-            suffixes can be used to specify the lifetime in
-            seconds, minutes, or hours.  If the specified NTA
-            already exists, its lifetime will be updated to the
-            new value.  Setting <option>lifetime</option> to zero
-            is equivalent to <option>-remove</option>.
-          </para>
-          <para>
-            If <option>-dump</option> is used, any other arguments
-            are ignored, and a list of existing NTAs is printed
-            (note that this may include NTAs that are expired but
-            have not yet been cleaned up).
-          </para>
-          <para>
-            Normally, <command>named</command> will periodically
-            test to see whether data below an NTA can now be
-            validated (see the <option>nta-recheck</option> option
-            in the Administrator Reference Manual for details).
-            If data can be validated, then the NTA is regarded as
-            no longer necessary, and will be allowed to expire
-            early.  The <option>-force</option> overrides this
-            behavior and forces an NTA to persist for its entire
-            lifetime, regardless of whether data could be
-            validated if the NTA were not present.
-          </para>
-          <para>
-            All of these options can be shortened, i.e., to
-            <option>-l</option>, <option>-r</option>, <option>-d</option>,
-            and <option>-f</option>.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>tsig-list</userinput></term>
-        <listitem>
-          <para>
-            List the names of all TSIG keys currently configured
-            for use by <command>named</command> in each view.  The
-            list both statically configured keys and dynamic
-            TKEY-negotiated keys.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>tsig-delete</userinput> <replaceable>keyname</replaceable> <optional><replaceable>view</replaceable></optional></term>
-        <listitem>
-          <para>
-            Delete a given TKEY-negotiated key from the server.
-            (This does not apply to statically configured TSIG
-            keys.)
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>addzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> <replaceable>configuration</replaceable> </userinput></term>
-        <listitem>
-          <para>
-            Add a zone while the server is running.  This
-            command requires the
-            <command>allow-new-zones</command> option to be set
-            to <userinput>yes</userinput>.  The
-            <replaceable>configuration</replaceable> string
-            specified on the command line is the zone
-            configuration text that would ordinarily be
-            placed in <filename>named.conf</filename>.
-          </para>
-          <para>
-            The configuration is saved in a file called
-            <filename><replaceable>name</replaceable>.nzf</filename>,
-            where <replaceable>name</replaceable> is the
-            name of the view, or if it contains characters
-            that are incompatible with use as a file name, a
-            cryptographic hash generated from the name
-            of the view.
-            When <command>named</command> is
-            restarted, the file will be loaded into the view
-            configuration, so that zones that were added
-            can persist after a restart.
-          </para>
-          <para>
-            This sample <command>addzone</command> command
-            would add the zone <literal>example.com</literal>
-            to the default view:
-          </para>
-          <para>
+       <listitem>
+         <para>
+           Sets a DNSSEC negative trust anchor (NTA)
+           for <option>domain</option>, with a lifetime of
+           <option>duration</option>.  The default lifetime is
+           configured in <filename>named.conf</filename> via the
+           <option>nta-lifetime</option> option, and defaults to
+           one hour.  The lifetime cannot exceed one week.
+         </para>
+         <para>
+           A negative trust anchor selectively disables
+           DNSSEC validation for zones that are known to be
+           failing because of misconfiguration rather than
+           an attack.  When data to be validated is
+           at or below an active NTA (and above any other
+           configured trust anchors), <command>named</command> will
+           abort the DNSSEC validation process and treat the data as
+           insecure rather than bogus.  This continues until the
+           NTA's lifetime is elapsed.
+         </para>
+         <para>
+           NTAs persist across restarts of the named server.
+           The NTAs for a view are saved in a file called
+           <filename><replaceable>name</replaceable>.nta</filename>,
+           where <replaceable>name</replaceable> is the
+           name of the view, or if it contains characters
+           that are incompatible with use as a file name, a
+           cryptographic hash generated from the name
+           of the view.
+         </para>
+         <para>
+           An existing NTA can be removed by using the
+           <option>-remove</option> option.
+         </para>
+         <para>
+           An NTA's lifetime can be specified with the
+           <option>-lifetime</option> option.  TTL-style
+           suffixes can be used to specify the lifetime in
+           seconds, minutes, or hours.  If the specified NTA
+           already exists, its lifetime will be updated to the
+           new value.  Setting <option>lifetime</option> to zero
+           is equivalent to <option>-remove</option>.
+         </para>
+         <para>
+           If <option>-dump</option> is used, any other arguments
+           are ignored, and a list of existing NTAs is printed
+           (note that this may include NTAs that are expired but
+           have not yet been cleaned up).
+         </para>
+         <para>
+           Normally, <command>named</command> will periodically
+           test to see whether data below an NTA can now be
+           validated (see the <option>nta-recheck</option> option
+           in the Administrator Reference Manual for details).
+           If data can be validated, then the NTA is regarded as
+           no longer necessary, and will be allowed to expire
+           early.  The <option>-force</option> overrides this
+           behavior and forces an NTA to persist for its entire
+           lifetime, regardless of whether data could be
+           validated if the NTA were not present.
+         </para>
+         <para>
+           All of these options can be shortened, i.e., to
+           <option>-l</option>, <option>-r</option>, <option>-d</option>,
+           and <option>-f</option>.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>tsig-list</userinput></term>
+       <listitem>
+         <para>
+           List the names of all TSIG keys currently configured
+           for use by <command>named</command> in each view.  The
+           list both statically configured keys and dynamic
+           TKEY-negotiated keys.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>tsig-delete</userinput> <replaceable>keyname</replaceable> <optional><replaceable>view</replaceable></optional></term>
+       <listitem>
+         <para>
+           Delete a given TKEY-negotiated key from the server.
+           (This does not apply to statically configured TSIG
+           keys.)
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>addzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> <replaceable>configuration</replaceable> </userinput></term>
+       <listitem>
+         <para>
+           Add a zone while the server is running.  This
+           command requires the
+           <command>allow-new-zones</command> option to be set
+           to <userinput>yes</userinput>.  The
+           <replaceable>configuration</replaceable> string
+           specified on the command line is the zone
+           configuration text that would ordinarily be
+           placed in <filename>named.conf</filename>.
+         </para>
+         <para>
+           The configuration is saved in a file called
+           <filename><replaceable>name</replaceable>.nzf</filename>,
+           where <replaceable>name</replaceable> is the
+           name of the view, or if it contains characters
+           that are incompatible with use as a file name, a
+           cryptographic hash generated from the name
+           of the view.
+           When <command>named</command> is
+           restarted, the file will be loaded into the view
+           configuration, so that zones that were added
+           can persist after a restart.
+         </para>
+         <para>
+           This sample <command>addzone</command> command
+           would add the zone <literal>example.com</literal>
+           to the default view:
+         </para>
+         <para>
 <prompt>$ </prompt><userinput>rndc addzone example.com '{ type master; file "example.com.db"; };'</userinput>
-          </para>
-          <para>
-            (Note the brackets and semi-colon around the zone
-            configuration text.)
-          </para>
-        </listitem>
+         </para>
+         <para>
+           (Note the brackets and semi-colon around the zone
+           configuration text.)
+         </para>
+       </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><userinput>modzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> <replaceable>configuration</replaceable> </userinput></term>
-        <listitem>
-          <para>
-            Modify the configuration of a zone while the server
+       <term><userinput>modzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> <replaceable>configuration</replaceable> </userinput></term>
+       <listitem>
+         <para>
+           Modify the configuration of a zone while the server
            is running.  This command requires the
-            <command>allow-new-zones</command> option to be
+           <command>allow-new-zones</command> option to be
            set to <userinput>yes</userinput>.  As with
            <command>addzone</command>, the
-            <replaceable>configuration</replaceable> string
-            specified on the command line is the zone
-            configuration text that would ordinarily be
-            placed in <filename>named.conf</filename>.
-          </para>
-          <para>
+           <replaceable>configuration</replaceable> string
+           specified on the command line is the zone
+           configuration text that would ordinarily be
+           placed in <filename>named.conf</filename>.
+         </para>
+         <para>
            If the zone was originally added via
            <command>rndc addzone</command>, the configuration
            changes will be recorded permanently and will still be
            its original configuration.  To make the changes
            permanent, it must also be modified in
            <filename>named.conf</filename>
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>delzone <optional>-clean</optional> <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
-        <listitem>
-          <para>
-            Delete a zone while the server is running.
-          </para>
-          <para>
-            If the <option>-clean</option> is specified,
-            the zone's master file (and journal file, if any)
-            will be deleted along with the zone.  Without the
-            <option>-clean</option> option, zone files must
-            be cleaned up by hand.  (If the zone is of
-            type "slave" or "stub", the files needing to
-            be cleaned up will be reported in the output
-            of the <command>rndc delzone</command> command.)
-          </para>
-         <para>
-            If the zone was originally added via
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>delzone <optional>-clean</optional> <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
+       <listitem>
+         <para>
+           Delete a zone while the server is running.
+         </para>
+         <para>
+           If the <option>-clean</option> is specified,
+           the zone's master file (and journal file, if any)
+           will be deleted along with the zone.  Without the
+           <option>-clean</option> option, zone files must
+           be cleaned up by hand.  (If the zone is of
+           type "slave" or "stub", the files needing to
+           be cleaned up will be reported in the output
+           of the <command>rndc delzone</command> command.)
+         </para>
+         <para>
+           If the zone was originally added via
            <command>rndc addzone</command>, then it will be
            removed permanently. However, if it was originally
            configured in <filename>named.conf</filename>, then
            come back. To remove it permanently, it must also be
            removed from <filename>named.conf</filename>
          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>showzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
-        <listitem>
-          <para>
-            Print the configuration of a running zone.
-          </para>
-        </listitem>
-      </varlistentry>
-
-      <varlistentry>
-        <term><userinput>signing <optional>( -list | -clear <replaceable>keyid/algorithm</replaceable> | -clear <literal>all</literal> | -nsec3param ( <replaceable>parameters</replaceable> | <literal>none</literal> ) | -serial <replaceable>value</replaceable> ) </optional> <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
-        <listitem>
-          <para>
-            List, edit, or remove the DNSSEC signing state records
-            for the specified zone.  The status of ongoing DNSSEC
-            operations (such as signing or generating
-            NSEC3 chains) is stored in the zone in the form
-            of DNS resource records of type
-            <command>sig-signing-type</command>. 
-            <command>rndc signing -list</command> converts
-            these records into a human-readable form,
-            indicating which keys are currently signing
-            or have finished signing the zone, and which NSEC3
-            chains are being created or removed.
-          </para>
-          <para>
-            <command>rndc signing -clear</command> can remove
-            a single key (specified in the same format that
-            <command>rndc signing -list</command> uses to
-            display it), or all keys.  In either case, only
-            completed keys are removed; any record indicating
-            that a key has not yet finished signing the zone
-            will be retained.
-          </para>
-          <para>
-            <command>rndc signing -nsec3param</command> sets
-            the NSEC3 parameters for a zone.  This is the
-            only supported mechanism for using NSEC3 with
-            <command>inline-signing</command> zones.
-            Parameters are specified in the same format as
-            an NSEC3PARAM resource record: hash algorithm,
-            flags, iterations, and salt, in that order.
-          </para>
-          <para>
-            Currently, the only defined value for hash algorithm 
-            is <literal>1</literal>, representing SHA-1.
-            The <option>flags</option> may be set to
-            <literal>0</literal> or <literal>1</literal>,
-            depending on whether you wish to set the opt-out
-            bit in the NSEC3 chain.  <option>iterations</option>
-            defines the number of additional times to apply
-            the algorithm when generating an NSEC3 hash.  The
-            <option>salt</option> is a string of data expressed
-            in hexadecimal, a hyphen (`-') if no salt is
-            to be used, or the keyword <literal>auto</literal>,
-            which causes <command>named</command> to generate a
-            random 64-bit salt.
-          </para>
-          <para>
-            So, for example, to create an NSEC3 chain using
-            the SHA-1 hash algorithm, no opt-out flag,
-            10 iterations, and a salt value of "FFFF", use:
-            <command>rndc signing -nsec3param 1 0 10 FFFF <replaceable>zone</replaceable></command>.
-            To set the opt-out flag, 15 iterations, and no
-            salt, use:
-            <command>rndc signing -nsec3param 1 1 15 - <replaceable>zone</replaceable></command>.
-          </para>
-          <para>
-            <command>rndc signing -nsec3param none</command>
-            removes an existing NSEC3 chain and replaces it
-            with NSEC.
-          </para>
-         <para>
-            <command>rndc signing -serial value</command> sets
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>showzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
+       <listitem>
+         <para>
+           Print the configuration of a running zone.
+         </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><userinput>signing <optional>( -list | -clear <replaceable>keyid/algorithm</replaceable> | -clear <literal>all</literal> | -nsec3param ( <replaceable>parameters</replaceable> | <literal>none</literal> ) | -serial <replaceable>value</replaceable> ) </optional> <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
+       <listitem>
+         <para>
+           List, edit, or remove the DNSSEC signing state records
+           for the specified zone.  The status of ongoing DNSSEC
+           operations (such as signing or generating
+           NSEC3 chains) is stored in the zone in the form
+           of DNS resource records of type
+           <command>sig-signing-type</command>. 
+           <command>rndc signing -list</command> converts
+           these records into a human-readable form,
+           indicating which keys are currently signing
+           or have finished signing the zone, and which NSEC3
+           chains are being created or removed.
+         </para>
+         <para>
+           <command>rndc signing -clear</command> can remove
+           a single key (specified in the same format that
+           <command>rndc signing -list</command> uses to
+           display it), or all keys.  In either case, only
+           completed keys are removed; any record indicating
+           that a key has not yet finished signing the zone
+           will be retained.
+         </para>
+         <para>
+           <command>rndc signing -nsec3param</command> sets
+           the NSEC3 parameters for a zone.  This is the
+           only supported mechanism for using NSEC3 with
+           <command>inline-signing</command> zones.
+           Parameters are specified in the same format as
+           an NSEC3PARAM resource record: hash algorithm,
+           flags, iterations, and salt, in that order.
+         </para>
+         <para>
+           Currently, the only defined value for hash algorithm 
+           is <literal>1</literal>, representing SHA-1.
+           The <option>flags</option> may be set to
+           <literal>0</literal> or <literal>1</literal>,
+           depending on whether you wish to set the opt-out
+           bit in the NSEC3 chain.  <option>iterations</option>
+           defines the number of additional times to apply
+           the algorithm when generating an NSEC3 hash.  The
+           <option>salt</option> is a string of data expressed
+           in hexadecimal, a hyphen (`-') if no salt is
+           to be used, or the keyword <literal>auto</literal>,
+           which causes <command>named</command> to generate a
+           random 64-bit salt.
+         </para>
+         <para>
+           So, for example, to create an NSEC3 chain using
+           the SHA-1 hash algorithm, no opt-out flag,
+           10 iterations, and a salt value of "FFFF", use:
+           <command>rndc signing -nsec3param 1 0 10 FFFF <replaceable>zone</replaceable></command>.
+           To set the opt-out flag, 15 iterations, and no
+           salt, use:
+           <command>rndc signing -nsec3param 1 1 15 - <replaceable>zone</replaceable></command>.
+         </para>
+         <para>
+           <command>rndc signing -nsec3param none</command>
+           removes an existing NSEC3 chain and replaces it
+           with NSEC.
+         </para>
+         <para>
+           <command>rndc signing -serial value</command> sets
            the serial number of the zone to value.  If the value
            would cause the serial number to go backwards it will
            be rejected.  The primary use is to set the serial on
            inline signed zones.
          </para>
-        </listitem>
+       </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
     <title>SEE ALSO</title>
     <para><citerefentry>
-        <refentrytitle>rndc.conf</refentrytitle><manvolnum>5</manvolnum>
+       <refentrytitle>rndc.conf</refentrytitle><manvolnum>5</manvolnum>
       </citerefentry>,
       <citerefentry>
-        <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
+       <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citerefentry>
-        <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+       <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citerefentry>
-        <refentrytitle>named.conf</refentrytitle><manvolnum>5</manvolnum>
+       <refentrytitle>named.conf</refentrytitle><manvolnum>5</manvolnum>
       </citerefentry>,
       <citerefentry>
-        <refentrytitle>ndc</refentrytitle><manvolnum>8</manvolnum>
+       <refentrytitle>ndc</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>,
       <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
     </para>
index 27bedcf0e0e9f0af41119789f4e8f1f8e750c9e5..68e0bf018943c9fd90b6b553f0f3582dd15e789a 100644 (file)
@@ -69,8 +69,9 @@ SUBDIRS="acl additional allow_query addzone autosign builtin
         @COVERAGE@ database delv dlv dlvauto dlz dlzexternal dname
         dns64 dnssec dsdigest dscp ecdsa ednscompliance emptyzones
         filter-aaaa formerr forward geoip glue gost ixfr inline
-        legacy limits logfileconfig lwresd masterfile masterformat
-        metadata notify nslookup nsupdate pending pipelined @PKCS11_TEST@
+        legacy limits logfileconfig lwresd
+        masterfile masterformat metadata mkeys
+        notify nslookup nsupdate pending pipelined @PKCS11_TEST@
         reclimit redirect resolver rndc rpz rrl rrchecker rrsetorder
         rsabigexponent runtime sit sfcache smartsign sortlist spf
         staticstub statistics stub tcp tkey tsig tsiggss unknown
index c10b204b951b775b2580d9e27fd51767a97dfa35..c6d1262d12d0573b7af12b7ffcfb7c959e53e944 100644 (file)
@@ -16,7 +16,8 @@
 # PERFORMANCE OF THIS SOFTWARE.
 
 rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed
-rm -f */trusted.conf */managed.conf */tmp* */*.jnl */*.bk */*.jbk
+rm -f */trusted.conf */managed.conf */revoked.conf
+rm -f */tmp* */*.jnl */*.bk */*.jbk
 rm -f ns1/root.db ns2/example.db ns3/secure.example.db
 rm -f ns3/unsecure.example.db ns3/bogus.example.db ns3/keyless.example.db
 rm -f ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl
@@ -51,7 +52,7 @@ rm -f signer/*.db
 rm -f signer/signer.out.*
 rm -f ns2/algroll.db
 rm -f ns3/kskonly.example.db
-rm -f ns4/named.conf
+rm -f ns4/named.conf ns5/named.conf
 rm -f ns4/managed-keys.bind*
 rm -f ns3/auto-nsec.example.db ns3/auto-nsec3.example.db
 rm -f ns3/secure.below-cname.example.db
@@ -83,3 +84,4 @@ rm -f ns3/dnskey-unknown.example.db
 rm -f ns3/dnskey-unknown.example.db.tmp
 rm -f ns*/named.lock
 rm -f ns*/*.nta
+rm -f named.secroots.test*
index 650f57c1da6062258a75a81754325e6e7b2f9f08..fbb26797b24ef1335855d92a04bdb4b72ade2560 100644 (file)
@@ -15,8 +15,6 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: sign.sh,v 1.43 2011/11/04 05:36:28 each Exp $
-
 SYSTEMTESTTOP=../..
 . $SYSTEMTESTTOP/conf.sh
 
@@ -520,5 +518,5 @@ zonefile=future.example.db
 kskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
 zskname=`$KEYGEN -q -r $RANDFILE $zone`
 cat $infile $kskname.key $zskname.key >$zonefile
-$SIGNER -P -s +3600 -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+$SIGNER -P -s +3600 -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
 cp -f $kskname.key trusted-future.key
similarity index 89%
rename from bin/tests/system/dnssec/ns5/named.conf
rename to bin/tests/system/dnssec/ns5/named1.conf
index 64892ca10fbe7b76bfdc5dac74662a3b74918aad..1a13a9f776435c25044ab33dcf0c5b9c3dd4313b 100644 (file)
@@ -15,8 +15,6 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: named.conf,v 1.25 2007/06/18 23:47:28 tbox Exp $ */
-
 // NS5
 
 controls { /* empty */ };
@@ -35,6 +33,16 @@ options {
        dnssec-validation yes;
 };
 
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; };
+};
+
+
 zone "." {
        type hint;
        file "../../common/root.hint";
diff --git a/bin/tests/system/dnssec/ns5/named2.conf b/bin/tests/system/dnssec/ns5/named2.conf
new file mode 100644 (file)
index 0000000..5b60285
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC 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.
+ */
+
+// NS5
+
+controls { /* empty */ };
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; };
+};
+
+options {
+       query-source address 10.53.0.5;
+       notify-source 10.53.0.5;
+       transfer-source 10.53.0.5;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.5; 127.0.0.1; };
+       listen-on-v6 { none; };
+       recursion yes;
+};
+
+view root {
+        match-destinations { 127.0.0.1; };
+
+        zone "." {
+                type master;
+                file "root.db.signed";
+        };
+};
+
+view other {
+include "revoked.conf";
+
+        zone "." {
+                type static-stub;
+                server-addresses { 127.0.0.1; };
+        };
+};
diff --git a/bin/tests/system/dnssec/ns5/sign.sh b/bin/tests/system/dnssec/ns5/sign.sh
new file mode 100644 (file)
index 0000000..16fe760
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh -e
+#
+# Copyright (C) 2015  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+infile=../ns1/root.db.in
+zonefile=root.db.signed
+
+keyname=`$KEYGEN -r $RANDFILE -qfk $zone`
+
+# copy the KSK out first, then revoke it
+cat $keyname.key | grep -v '^; ' | $PERL -n -e '
+local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
+local $key = join("", @rest);
+print <<EOF
+managed-keys {
+    "$dn" initial-key $flags $proto $alg "$key";
+};
+EOF
+' > revoked.conf
+
+$SETTIME -R now ${keyname}.key > /dev/null
+
+# create a current set of keys, and sign the root zone
+$KEYGEN -r $RANDFILE -q $zone > /dev/null
+$KEYGEN -r $RANDFILE -qfk $zone > /dev/null
+$SIGNER -S -r $RANDFILE -o $zone -f $zonefile $infile > /dev/null 2>&1
index c2230ec9c0b7521b3da67b6148645c142ce75576..0418f9510fd0572aa22cb2eef5991c8c5a777924 100644 (file)
@@ -30,4 +30,8 @@ echo "c.bogus.example.        A       10.0.0.23" >>../ns3/bogus.example.db.signed
 
 cd ../ns3 && cp -f siginterval1.conf siginterval.conf
 cd ../ns4 && cp -f named1.conf named.conf
-cd ../ns5 && cp -f trusted.conf.bad trusted.conf
+cd ../ns5 && {
+    cp -f trusted.conf.bad trusted.conf
+    cp -f named1.conf named.conf
+    $SHELL sign.sh
+}
index 60a9bacd30390a4d1e1fd370462a79ec15061d45..0803a4c4f088dc0ffb353dd1b97429af0d21de06 100644 (file)
@@ -15,8 +15,6 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: tests.sh,v 1.109 2012/02/22 23:47:34 tbox Exp $
-
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
 
@@ -1565,10 +1563,11 @@ echo "I:checking rndc secroots ($n)"
 ret=0
 $RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 secroots 2>&1 | sed 's/^/I:ns1 /'
 keyid=`cat ns1/managed.key.id`
-linecount=`grep "./RSAMD5/$keyid ; trusted" ns4/named.secroots | wc -l`
+cp ns4/named.secroots named.secroots.test$n
+linecount=`grep "./RSAMD5/$keyid ; trusted" named.secroots.test$n | wc -l`
 [ "$linecount" -eq 1 ] || ret=1
-linecount=`cat ns4/named.secroots | wc -l`
-[ "$linecount" -eq 9 ] || ret=1
+linecount=`cat named.secroots.test$n | wc -l`
+[ "$linecount" -eq 10 ] || ret=1
 n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
@@ -2784,12 +2783,11 @@ if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
 echo "I:check KEYDATA records are printed in human readable form in key zone ($n)"
-# force the zone to be written out
-$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns4
+# force the managed-keys zone to be written out
+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 managed-keys sync 2>&1 | sed 's/^/I:ns4 /'
 ret=0
 grep KEYDATA ns4/managed-keys.bind > /dev/null || ret=1
-# restart the server
-$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4
+grep "next refresh:" ns4/managed-keys.bind > /dev/null || ret=1
 n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
@@ -3034,5 +3032,16 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:checking initialization with a revoked managed key ($n)"
+ret=0
+cp ns5/named2.conf ns5/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.5 -p 9953 reconfig 2>&1 | sed 's/^/I:ns5 /'
+sleep 3
+$DIG $DIGOPTS +dnssec -p 5300 @10.53.0.5 SOA . > dig.out.ns5.test$n
+grep "status: NOERROR" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 exit $status
diff --git a/bin/tests/system/mkeys/README b/bin/tests/system/mkeys/README
new file mode 100644 (file)
index 0000000..eb77d7b
--- /dev/null
@@ -0,0 +1,26 @@
+This is for testing managed-keys, in particular with problems
+with RFC 5011 Automated Updates of DNSSEC Trust Anchors.
+
+ns1 is the root server that offers new KSKs and hosts one record for
+testing. The TTL for the zone's records is 2 seconds.
+
+ns2 is a validator uses managed-keys.
+"named -T rfc5011holddown=4" switch is used so it will attempt to do
+the automated updates frequently.
+
+ns3 is a validator with a broken key in managed-keys.
+
+Tests TODO:
+
+- initial working KSK
+
+TODO: test using delv with new trusted key too
+
+- introduce a REVOKE bit
+
+- later remove a signature
+
+- corrupt a signature
+
+TODO: also same things with dlv auto updates of trust anchor
+
diff --git a/bin/tests/system/mkeys/clean.sh b/bin/tests/system/mkeys/clean.sh
new file mode 100644 (file)
index 0000000..dfd44a4
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) 2009-2014  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+rm -f */K* */*.signed */trusted.conf */*.jnl */*.bk
+rm -f dsset-. ns1/dsset-.
+rm -f ns*/named.lock
+rm -f */managed-keys.bind*
+rm -f */managed.conf ns1/managed.key ns1/managed.key.id
+rm -f */named.memstats */named.run
+rm -f dig.out* delv.out* rndc.out* signer.out*
+rm -f ns1/named.secroots ns1/root.db.signed*
+rm -f ns1/named.conf
diff --git a/bin/tests/system/mkeys/ns1/named1.conf b/bin/tests/system/mkeys/ns1/named1.conf
new file mode 100644 (file)
index 0000000..4298cd4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC 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.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+       query-source address 10.53.0.1;
+       notify-source 10.53.0.1;
+       transfer-source 10.53.0.1;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.1; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify no;
+       dnssec-enable yes;
+       dnssec-validation yes;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+       type master;
+       file "root.db.signed";
+       allow-update { any; };
+       auto-dnssec maintain;
+};
diff --git a/bin/tests/system/mkeys/ns1/named2.conf b/bin/tests/system/mkeys/ns1/named2.conf
new file mode 100644 (file)
index 0000000..4324524
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC 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.
+ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+       query-source address 10.53.0.1;
+       notify-source 10.53.0.1;
+       transfer-source 10.53.0.1;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.1; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify no;
+       dnssec-enable yes;
+       dnssec-validation yes;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+       type master;
+       file "root.db.signed";
+};
+
diff --git a/bin/tests/system/mkeys/ns1/root.db b/bin/tests/system/mkeys/ns1/root.db
new file mode 100644 (file)
index 0000000..461d788
--- /dev/null
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007, 2010, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000, 2001  Internet Software Consortium.
+;
+; Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+$TTL 2
+.                      IN SOA  gson.nominum.com. a.root.servers.nil. (
+                               2000042100      ; serial
+                               600             ; refresh
+                               600             ; retry
+                               1200            ; expire
+                               2               ; minimum
+                               )
+.                      NS      a.root-servers.nil.
+a.root-servers.nil.    A       10.53.0.1
+
+; no delegation
+
+example.               TXT     "This is a test."
diff --git a/bin/tests/system/mkeys/ns1/sign.sh b/bin/tests/system/mkeys/ns1/sign.sh
new file mode 100644 (file)
index 0000000..fde0e15
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/sh -e
+#
+# Copyright (C) 2004, 2006-2014  Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2003  Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+zone=.
+zonefile=root.db
+
+keyname=`$KEYGEN -qfk -r $RANDFILE $zone`
+zskkeyname=`$KEYGEN -q -r $RANDFILE $zone`
+
+$SIGNER -Sg -r $RANDFILE -o $zone $zonefile > /dev/null 2>&-
+
+# Configure the resolving server with a managed trusted key.
+cat $keyname.key | grep -v '^; ' | $PERL -n -e '
+local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
+local $key = join("", @rest);
+print <<EOF
+managed-keys {
+    "$dn" initial-key $flags $proto $alg "$key";
+};
+EOF
+' > managed.conf
+cp managed.conf ../ns2/managed.conf
+
+# Configure a trusted key statement (used by delve)
+cat $keyname.key | grep -v '^; ' | $PERL -n -e '
+local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
+local $key = join("", @rest);
+print <<EOF
+trusted-keys {
+    "$dn" $flags $proto $alg "$key";
+};
+EOF
+' > trusted.conf
+
+#
+#  Save keyname and keyid for managed key id test.
+#
+echo "$keyname" > managed.key
+keyid=`expr $keyname : 'K\.+00.+\([0-9]*\)'`
+keyid=`expr $keyid + 0`
+echo "$keyid" > managed.key.id
diff --git a/bin/tests/system/mkeys/ns2/named.args b/bin/tests/system/mkeys/ns2/named.args
new file mode 100644 (file)
index 0000000..a29041f
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -T mkeytimers=2/10/15
diff --git a/bin/tests/system/mkeys/ns2/named.conf b/bin/tests/system/mkeys/ns2/named.conf
new file mode 100644 (file)
index 0000000..9da4fcb
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011, 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC 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.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+       query-source address 10.53.0.2;
+       notify-source 10.53.0.2;
+       transfer-source 10.53.0.2;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.2; };
+       listen-on-v6 { none; };
+       recursion yes;
+        notify no;
+       dnssec-enable yes;
+       dnssec-validation auto;
+       bindkeys-file "managed.conf";
+        servfail-ttl 0;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+       type hint;
+       file "../../common/root.hint";
+};
diff --git a/bin/tests/system/mkeys/ns3/named.args b/bin/tests/system/mkeys/ns3/named.args
new file mode 100644 (file)
index 0000000..25c4289
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -T mkeytimers=2/10/20
diff --git a/bin/tests/system/mkeys/ns3/named.conf b/bin/tests/system/mkeys/ns3/named.conf
new file mode 100644 (file)
index 0000000..c6ef9f7
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011, 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC 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.
+ */
+
+// NS3
+
+controls { /* empty */ };
+
+options {
+       query-source address 10.53.0.3;
+       notify-source 10.53.0.3;
+       transfer-source 10.53.0.3;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.3; };
+       listen-on-v6 { none; };
+       recursion yes;
+        notify no;
+       dnssec-enable yes;
+       dnssec-validation yes;
+       bindkeys-file "managed.conf";
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+       type hint;
+       file "../../common/root.hint";
+};
+
+# purposely broken key for testing
+managed-keys {
+    "." initial-key 257 3 5 "PURPOSELYBROKEN/xs9iVj7QekClcpzjCf0JrvXW1z07hNMqMm6Q2FtIXMbRgfvTtHF3/ZNvcewT9hpfczC+JACHsQSYYdr7UI8oe4nJfal9+2F3pz4a+HR6CqkgrR6WLWQI1Q==";
+};
+
diff --git a/bin/tests/system/mkeys/setup.sh b/bin/tests/system/mkeys/setup.sh
new file mode 100644 (file)
index 0000000..a205bba
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+#
+# Copyright (C) 2004, 2007, 2009, 2011-2015  Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000, 2001  Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
+
+test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
+
+cp ns1/named1.conf ns1/named.conf
+
+cd ns1 && $SHELL sign.sh
diff --git a/bin/tests/system/mkeys/tests.sh b/bin/tests/system/mkeys/tests.sh
new file mode 100644 (file)
index 0000000..5408a35
--- /dev/null
@@ -0,0 +1,435 @@
+#!/bin/sh
+#
+# Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002  Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC 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.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+DELVOPTS="-a ns1/trusted.conf -p 5300"
+
+echo "I: check for signed record ($n)"
+ret=0
+$DIG $DIGOPTS +norec example.  @10.53.0.1 TXT > dig.out.ns1.test$n || ret=1
+grep "^example\.[[:space:]]*[0-9].*[[:space:]]*IN[[:space:]]*TXT[[:space:]]*\"This is a test\.\"" dig.out.ns1.test$n > /dev/null || ret=1
+grep "^example\.[[:space:]]*[0-9].*[[:space:]]*IN[[:space:]]*RRSIG[[:space:]]*TXT[[:space:]]" dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: check positive validation with valid trust anchor ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+ret=0
+echo "I: check positive validation using delv ($n)"
+$DELV $DELVOPTS @10.53.0.1 txt example > delv.out$n || ret=1
+grep "; fully validated" delv.out$n > /dev/null || ret=1       # redundant
+grep "example..*TXT.*This is a test" delv.out$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" delv.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: check for failed validation due to wrong key in managed-keys ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns3.test$n > /dev/null && ret=1
+grep "opcode: QUERY, status: SERVFAIL, id" dig.out.ns3.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: check new trust anchor can be added ($n)"
+ret=0
+standby1=`$KEYGEN -qfk -r $RANDFILE -K ns1 .`
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 5
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# there should be two keys listed now
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# one indicates current trust
+count=`grep -c "trusted since" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# one indicates pending trust
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: check new trust anchor can't be added with bad initial key ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 managed-keys refresh | sed 's/^/I: ns3 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 managed-keys sync | sed 's/^/I: ns3 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# there should be one key listed now
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# one line indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# ... and the key is not trusted
+count=`grep -c "no trust" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: remove untrusted standby key, check timer restarts ($n)"
+ret=0
+$SETTIME -D now -K ns1 $standby1 > /dev/null
+t1=`grep "trust pending" ns2/managed-keys.bind`
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+sleep 1
+t2=`grep "trust pending" ns2/managed-keys.bind`
+# trust pending date must be different
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+ret=0
+echo "I: restore untrusted standby key, revoke original key ($n)"
+t1=$t2
+$SETTIME -D none -K ns1 $standby1 > /dev/null
+$SETTIME -R now -K ns1 `cat ns1/managed.key` > /dev/null
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=`grep "trust pending" ns2/managed-keys.bind`
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+ret=0
+echo "I: refresh managed-keys, ensure same result ($n)"
+t1=$t2
+sleep 2
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=`grep "trust pending" ns2/managed-keys.bind`
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+ret=0
+echo "I: restore revoked key, ensure same result ($n)"
+t1=$t2
+$SETTIME -R none -D now -K ns1 `cat ns1/managed.key` > /dev/null
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 3
+$SETTIME -D none -K ns1 `cat ns1/managed.key` > /dev/null
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# trust is revoked
+count=`grep -c "trust revoked" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# trust is still pending on the standby key
+count=`grep -c "trust pending" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+# pending date moved forward for the standby key
+t2=`grep "trust pending" ns2/managed-keys.bind`
+[ -n "$t2" ] || ret=1
+[ "$t1" = "$t2" ] && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: reinitialize trust anchors"
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns2
+rm -f ns2/managed-keys.bind*
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns2
+
+n=`expr $n + 1`
+echo "I: check that standby key is now trusted ($n)"
+ret=0
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# both indicate current trust
+count=`grep -c "trusted since" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: revoke original key, add new standby ($n)"
+ret=0
+standby2=`$KEYGEN -qfk -r $RANDFILE -K ns1 .`
+$SETTIME -R now -K ns1 `cat ns1/managed.key` > /dev/null
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# three keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 3 ] || ret=1
+# one is revoked
+count=`grep -c "REVOKE" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# three lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 3 ] || ret=1
+# one indicates current trust
+count=`grep -c "trusted since" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# one indicates revoked trust
+count=`grep -c "trust revoked" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# one indicates trust pending
+count=`grep -c "trust pending" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: wait 15 seconds for key add/remove holddowns to expire ($n)"
+ret=0
+sleep 15
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# none revoked
+count=`grep -c "REVOKE" rndc.out.$n` 
+[ "$count" -eq 0 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# both indicate current trust
+count=`grep -c "trusted since" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: revoke all keys, confirm roll to insecure ($n)"
+ret=0
+$SETTIME -D now -K ns1 `cat ns1/managed.key` > /dev/null
+$SETTIME -R now -K ns1 $standby1 > /dev/null
+$SETTIME -R now -K ns1 $standby2 > /dev/null
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# two keys listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# both revoked
+count=`grep -c "REVOKE" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# two lines indicating trust status
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# both indicate trust revoked
+count=`grep -c "trust revoked" rndc.out.$n` 
+[ "$count" -eq 2 ] || ret=1
+# both have removal scheduled
+count=`grep -c "remove at" rndc.out.$n`
+[ "$count" -eq 2 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: check for insecure response ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: reset the root server"
+$SETTIME -D none -R none -K ns1 `cat ns1/managed.key` > /dev/null
+$SETTIME -D now -K ns1 $standby1 > /dev/null
+$SETTIME -D now -K ns1 $standby2 > /dev/null
+$SIGNER -Sg -K ns1 -N unixtime -r $RANDFILE -o . ns1/root.db > /dev/null 2>&-
+cp ns1/named2.conf ns1/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reconfig
+
+echo "I: reinitialize trust anchors"
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns2
+rm -f ns2/managed-keys.bind*
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns2
+
+n=`expr $n + 1`
+echo "I: check positive validation ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+
+n=`expr $n + 1`
+echo "I: revoke key with bad signature, check revocation is ignored ($n)"
+ret=0
+orig=`cat ns1/managed.key`
+keyid=`cat ns1/managed.key.id`
+revoked=`$REVOKE -K ns1 $orig`
+rkeyid=`expr $revoked : 'ns1/K\.+00.+\([0-9]*\)'`
+$SETTIME -R none -D none -K ns1 $standby1 > /dev/null
+$SIGNER -Sg -K ns1 -N unixtime -r $RANDFILE -O full -o . -f signer.out.$n ns1/root.db > /dev/null 2>&-
+cp -f ns1/root.db.signed ns1/root.db.tmp
+BADSIG="SVn2tLDzpNX2rxR4xRceiCsiTqcWNKh7NQ0EQfCrVzp9WEmLw60sQ5kP xGk4FS/xSKfh89hO2O/H20Bzp0lMdtr2tKy8IMdU/mBZxQf2PXhUWRkg V2buVBKugTiOPTJSnaqYCN3rSfV1o7NtC1VNHKKK/D5g6bpDehdn5Gaq kpBhN+MSCCh9OZP2IT20luS1ARXxLlvuSVXJ3JYuuhTsQXUbX/SQpNoB Lo6ahCE55szJnmAxZEbb2KOVnSlZRA6ZBHDhdtO0S4OkvcmTutvcVV+7 w53CbKdaXhirvHIh0mZXmYk2PbPLDY7PU9wSH40UiWPOB9f00wwn6hUe uEQ1Qg=="
+sed -e "/ $rkeyid \./s, \. .*$, . $BADSIG," signer.out.$n > ns1/root.db.signed
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reload . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys sync | sed 's/^/I: ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
+# one key listed
+count=`grep -c "keyid: " rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# it's the original key id
+count=`grep -c "keyid: $keyid" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+# not revoked
+count=`grep -c "REVOKE" rndc.out.$n` 
+[ "$count" -eq 0 ] || ret=1
+# trust is still current
+count=`grep -c "trust" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+count=`grep -c "trusted since" rndc.out.$n` 
+[ "$count" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: check validation fails with bad DNSKEY rrset ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "status: SERVFAIL" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: restore DNSKEY rrset, check validation succeeds again ($n)"
+ret=0
+rm -f ${revoked}.key ${revoked}.private
+$SETTIME -D none -R none -K ns1 `cat ns1/managed.key` > /dev/null
+$SETTIME -D now -K ns1 $standby1 > /dev/null
+$SETTIME -D now -K ns1 $standby2 > /dev/null
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 flush | sed 's/^/I: ns1 /'
+sleep 1
+$SIGNER -Sg -K ns1 -N unixtime -r $RANDFILE -o . ns1/root.db > /dev/null 2>&-
+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reload . | sed 's/^/I: ns1 /'
+sleep 3
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | 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
+$DIG $DIGOPTS +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
+grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
index c6f7447c4257785d8e270da06baea2cd8c551b3b..61014532b8b1c9530e50fb66ab6182222a7263d5 100644 (file)
          query and waiting the response before sending the next. [RT #38261]
        </para>
       </listitem>
+      <listitem>
+       <para>
+         To enable better monitoring and troubleshooting of RFC 5011
+         trust anchor management, the new <command>rndc managed-keys</command>
+         can be used to check status of trust anchors or to force keys
+         to be refreshed.  Also, the managed-keys data file now has
+         easier-to-read comments. [RT #38458]
+       </para>
+      </listitem>
     </itemizedlist>
   </sect2>
   <sect2 id="relnotes_changes">
          processes to grow to very large sizes. [RT #38454]
        </para>
       </listitem>
+      <listitem>
+       <para>
+         Fixed some bugs in RFC 5011 trust anchor management,
+         including a memory leak and a possible loss of state
+         information.[RT #38458]
+       </para>
+      </listitem>
     </itemizedlist>
   </sect2>
   <sect2 id="end_of_life">
index ecabaf94ca7f2f8a5ae8a10467b35b6cf26b84ff..94669c270c97a747a40f30116e869d5c4a9abe95 100644 (file)
@@ -420,6 +420,12 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp);
  * Dump the keytable on fp.
  */
 
+isc_result_t
+dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **buf);
+/*%<
+ * Dump the keytable to buffer at 'buf'
+ */
+
 dst_key_t *
 dns_keynode_key(dns_keynode_t *keynode);
 /*%<
index 31a0b956d1efd2ba93c830c06a27ebab1e6e91cd..e8d4259c327f9802e3f13d3e37e8aab2bc421d6b 100644 (file)
@@ -185,6 +185,11 @@ isc_result_t
 dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf);
 /*%<
  * Dump the NTA table to buffer at 'buf'
+ * 
+ * Requires:
+ * \li   "ntatable" is a valid table.
+ *
+ * \li   "*buf" is a valid buffer.
  */
 
 isc_result_t
index 717e37636dbbd9c3d72205c8374c35c0f6ccd357..7923d023a05bca0b257e23e875d0cafeec803cde 100644 (file)
@@ -275,16 +275,17 @@ dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
        }
 
        knode = node->data;
-       if (knode->next == NULL &&
-           (knode->key == NULL ||
-            dst_key_compare(knode->key, dstkey) == ISC_TRUE)) {
+       if (knode->next == NULL && knode->key != NULL &&
+           dst_key_compare(knode->key, dstkey) == ISC_TRUE)
+       {
                result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE);
                goto finish;
        }
 
        kprev = (dns_keynode_t **) &node->data;
        while (knode != NULL) {
-               if (dst_key_compare(knode->key, dstkey) == ISC_TRUE)
+               if (knode->key != NULL &&
+                   dst_key_compare(knode->key, dstkey) == ISC_TRUE)
                        break;
                kprev = &knode->next;
                knode = knode->next;
@@ -555,31 +556,80 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
        return (result);
 }
 
+static isc_result_t
+putstr(isc_buffer_t **b, const char *str) {
+       isc_result_t result;
+
+       result = isc_buffer_reserve(b, strlen(str));
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       
+       isc_buffer_putstr(*b, str);
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
-dns_keytable_dump(dns_keytable_t *keytable, FILE *fp)
-{
+dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
+       isc_result_t result;
+       isc_buffer_t *text = NULL;
+
+       REQUIRE(VALID_KEYTABLE(keytable));
+       REQUIRE(fp != NULL);
+
+       result = isc_buffer_allocate(keytable->mctx, &text, 4096);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       result = dns_keytable_totext(keytable, &text);
+
+       if (isc_buffer_usedlength(text) != 0) {
+               (void) putstr(&text, "\n");
+       } else if (result == ISC_R_SUCCESS)
+               (void) putstr(&text, "none");
+       else {
+               (void) putstr(&text, "could not dump key table: ");
+               (void) putstr(&text, isc_result_totext(result));
+       }
+
+       fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
+               (char *) isc_buffer_base(text));
+
+       isc_buffer_free(&text);
+       return (result);
+}
+
+isc_result_t
+dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
        isc_result_t result;
        dns_keynode_t *knode;
        dns_rbtnode_t *node;
        dns_rbtnodechain_t chain;
 
        REQUIRE(VALID_KEYTABLE(keytable));
+       REQUIRE(text != NULL && *text != NULL);
 
        RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
        dns_rbtnodechain_init(&chain, keytable->mctx);
        result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
-       if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+       if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+               if (result == ISC_R_NOTFOUND)
+                       result = ISC_R_SUCCESS;
                goto cleanup;
+       }
        for (;;) {
                char pbuf[DST_KEY_FORMATSIZE];
 
                dns_rbtnodechain_current(&chain, NULL, NULL, &node);
                for (knode = node->data; knode != NULL; knode = knode->next) {
+                       char obuf[DNS_NAME_FORMATSIZE + 200];
                        if (knode->key == NULL)
                                continue;
                        dst_key_format(knode->key, pbuf, sizeof(pbuf));
-                       fprintf(fp, "%s ; %s\n", pbuf,
+                       snprintf(obuf, sizeof(obuf), "%s ; %s\n", pbuf,
                                knode->managed ? "managed" : "trusted");
+                       result = putstr(text, obuf);
+                       if (result != ISC_R_SUCCESS)
+                               break;
                }
                result = dns_rbtnodechain_next(&chain, NULL, NULL);
                if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
index 36542cd27346b8c67486e029a0c85550357379b3..c9291617d9ef30ba4d394f4ead488d72e5454619 100644 (file)
@@ -503,6 +503,18 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
        return (answer);
 }
 
+static isc_result_t
+putstr(isc_buffer_t **b, const char *str) {
+       isc_result_t result;
+
+       result = isc_buffer_reserve(b, strlen(str));
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       
+       isc_buffer_putstr(*b, str);
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
        isc_result_t result;
@@ -518,14 +530,20 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
        RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
        dns_rbtnodechain_init(&chain, ntatable->view->mctx);
        result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL);
-       if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+       if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+               if (result == ISC_R_NOTFOUND)
+                       result = ISC_R_SUCCESS;
                goto cleanup;
+       }
        for (;;) {
                dns_rbtnodechain_current(&chain, NULL, NULL, &node);
                if (node->data != NULL) {
                        dns_nta_t *n = (dns_nta_t *) node->data;
-                       char nbuf[DNS_NAME_FORMATSIZE], tbuf[80];
-                       char obuf[DNS_NAME_FORMATSIZE + 200];
+                       char nbuf[DNS_NAME_FORMATSIZE];
+                       char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+                       char obuf[DNS_NAME_FORMATSIZE +
+                                 ISC_FORMATHTTPTIMESTAMP_SIZE +
+                                 sizeof("expired:  \n")];
                        dns_fixedname_t fn;
                        dns_name_t *name;
                        isc_time_t t;
@@ -542,12 +560,9 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
                                 n->expiry < now ? "expired" : "expiry",
                                 tbuf);
                        first = ISC_FALSE;
-                       result = isc_buffer_reserve(buf, strlen(obuf));
-                       if (result != ISC_R_SUCCESS) {
-                               result = ISC_R_NOSPACE;
+                       result = putstr(buf, obuf);
+                       if (result != ISC_R_SUCCESS)
                                goto cleanup;
-                       }
-                       isc_buffer_putstr(*buf, obuf);
                }
                result = dns_rbtnodechain_next(&chain, NULL, NULL);
                if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
@@ -557,16 +572,13 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
                }
        }
 
-       isc_buffer_reserve(buf, 1);
-       if (isc_buffer_availablelength(*buf) != 0)
-               isc_buffer_putuint8(*buf, 0);
-
    cleanup:
        dns_rbtnodechain_invalidate(&chain);
        RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
        return (result);
 }
 
+#if 0
 isc_result_t
 dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
        isc_result_t result;
@@ -615,6 +627,34 @@ dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
        RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
        return (result);
 }
+#endif
+
+isc_result_t
+dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
+       isc_result_t result;
+       isc_buffer_t *text = NULL;
+       int len = 4096;
+
+       result = isc_buffer_allocate(ntatable->view->mctx, &text, len);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       result = dns_ntatable_totext(ntatable, &text);
+
+       if (isc_buffer_usedlength(text) != 0) {
+               (void) putstr(&text, "\n");
+       } else if (result == ISC_R_SUCCESS) {
+               (void) putstr(&text, "none");
+       } else {
+               (void) putstr(&text, "could not dump NTA table: ");
+               (void) putstr(&text, isc_result_totext(result));
+       }
+
+       fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
+               (char *) isc_buffer_base(text));
+       isc_buffer_free(&text);
+       return (result);
+}
 
 isc_result_t
 dns_ntatable_save(dns_ntatable_t *ntatable, FILE *fp) {
index fae2bce8dbeb750cf710a8385687dc9e4397ef54..1e5741863fa91248d56611584e35090bce944873 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id$ */
-
 #ifndef GENERIC_KEYDATA_65533_C
 #define GENERIC_KEYDATA_65533_C 1
 
+#include <isc/time.h>
+#include <isc/stdtime.h>
+
 #include <dst/dst.h>
 
 #define RRTYPE_KEYDATA_ATTRIBUTES (0)
@@ -97,7 +98,7 @@ totext_keydata(ARGS_TOTEXT) {
        char buf[sizeof("64000")];
        unsigned int flags;
        unsigned char algorithm;
-       unsigned long when;
+       unsigned long refresh, add, remove;
        char algbuf[DNS_NAME_FORMATSIZE];
        const char *keyinfo;
 
@@ -109,21 +110,21 @@ totext_keydata(ARGS_TOTEXT) {
        dns_rdata_toregion(rdata, &sr);
 
        /* refresh timer */
-       when = uint32_fromregion(&sr);
+       refresh = uint32_fromregion(&sr);
        isc_region_consume(&sr, 4);
-       RETERR(dns_time32_totext(when, target));
+       RETERR(dns_time32_totext(refresh, target));
        RETERR(str_totext(" ", target));
 
        /* add hold-down */
-       when = uint32_fromregion(&sr);
+       add = uint32_fromregion(&sr);
        isc_region_consume(&sr, 4);
-       RETERR(dns_time32_totext(when, target));
+       RETERR(dns_time32_totext(add, target));
        RETERR(str_totext(" ", target));
 
        /* remove hold-down */
-       when = uint32_fromregion(&sr);
+       remove = uint32_fromregion(&sr);
        isc_region_consume(&sr, 4);
-       RETERR(dns_time32_totext(when, target));
+       RETERR(dns_time32_totext(remove, target));
        RETERR(str_totext(" ", target));
 
        /* flags */
@@ -176,6 +177,10 @@ totext_keydata(ARGS_TOTEXT) {
 
        if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
                isc_region_t tmpr;
+               char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+               char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+               char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+               isc_time_t t;
 
                RETERR(str_totext(" ; ", target));
                RETERR(str_totext(keyinfo, target));
@@ -189,6 +194,47 @@ totext_keydata(ARGS_TOTEXT) {
                isc_region_consume(&tmpr, 12);
                sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
                RETERR(str_totext(buf, target));
+
+               if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+                       isc_stdtime_t now;
+
+                       isc_stdtime_get(&now);
+
+                       RETERR(str_totext(tctx->linebreak, target)); 
+                       RETERR(str_totext("; next refresh: ", target));
+                       isc_time_set(&t, refresh, 0);
+                       isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf));
+                       RETERR(str_totext(rbuf, target));
+
+                       if (add == 0) {
+                               RETERR(str_totext(tctx->linebreak, target)); 
+                               RETERR(str_totext("; no trust", target));
+                       } else {
+                               RETERR(str_totext(tctx->linebreak, target)); 
+                               if (add < now) {
+                                       RETERR(str_totext("; trusted since: ",
+                                                         target));
+                               } else {
+                                       RETERR(str_totext("; trust pending: ",
+                                                         target));
+                               }
+                               isc_time_set(&t, add, 0);
+                               isc_time_formathttptimestamp(&t, abuf,
+                                                            sizeof(abuf));
+                               RETERR(str_totext(abuf, target));
+                       }
+
+                       if (remove != 0) {
+                               RETERR(str_totext(tctx->linebreak, target)); 
+                               RETERR(str_totext("; removal pending: ",
+                                                 target));
+                               isc_time_set(&t, remove, 0);
+                               isc_time_formathttptimestamp(&t, dbuf,
+                                                            sizeof(dbuf));
+                               RETERR(str_totext(dbuf, target));
+                       }
+               }
+
        }
        return (ISC_R_SUCCESS);
 }
index 4b9a60210584adc5bf85c1cb5a73c23862254567..373380ba4763c2d9301ecda4edb68607cc426541 100644 (file)
@@ -383,6 +383,7 @@ dns_keytable_findnextkeynode
 dns_keytable_issecuredomain
 dns_keytable_marksecure
 dns_keytable_nextkeynode
+dns_keytable_totext
 dns_lib_init
 dns_lib_initmsgcat
 dns_lib_shutdown
index 1bc8608ed633e8e7bc17246e80906d5d7ada7a1c..2e409ce172cb09ab711105e9010e7b5e1646b28a 100644 (file)
@@ -704,6 +704,16 @@ struct dns_include {
 #define DAY (24*HOUR)
 #define MONTH (30*DAY)
 
+/*
+ * These can be overridden by the -T mkeytimers option on the command
+ * line, so that we can test with shorter periods than specified in
+ * RFC 5011.
+ */
+unsigned int dns_zone_mkey_hour = HOUR;
+unsigned int dns_zone_mkey_day = (24 * HOUR);
+unsigned int dns_zone_mkey_month = (30 * DAY);
+
+
 #define SEND_BUFFER_SIZE 2048
 
 static void zone_settimer(dns_zone_t *, isc_time_t *);
@@ -3459,7 +3469,7 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
  */
 static void
 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
-                   isc_stdtime_t now)
+                   isc_stdtime_t now, isc_boolean_t force)
 {
        const char me[] = "set_refreshkeytimer";
        isc_stdtime_t then;
@@ -3468,6 +3478,8 @@ set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
 
        ENTER;
        then = key->refresh;
+       if (force)
+               then = now;
        if (key->addhd > now && key->addhd < then)
                then = key->addhd;
        if (key->removehd > now && key->removehd < then)
@@ -3547,8 +3559,9 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
                CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
                                    dst_key_name(key), 0, &rdata));
                *changed = ISC_TRUE;
+
                /* Refresh new keys from the zone apex as soon as possible. */
-               set_refreshkeytimer(zone, &keydata, now);
+               set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
 
  skip:
                result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
@@ -3704,8 +3717,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
                        continue;
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-               /* Set the key refresh timer. */
-               set_refreshkeytimer(zone, &keydata, now);
+               /* Set the key refresh timer to force a fast refresh. */
+               set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
 
                /* If the removal timer is nonzero, this key was revoked. */
                if (keydata.removehd != 0) {
@@ -3973,7 +3986,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
                result = dns_keytable_find(sr, rrname, &keynode);
                if ((result != ISC_R_SUCCESS &&
                     result != DNS_R_PARTIALMATCH) ||
-                   dns_keynode_managed(keynode) == ISC_FALSE) {
+                   dns_keynode_managed(keynode) == ISC_FALSE)
+               {
                        CHECK(delete_keydata(db, ver, &diff,
                                             rrname, rdataset));
                        changed = ISC_TRUE;
@@ -8382,7 +8396,8 @@ zone_sign(dns_zone_t *zone) {
 
 static isc_result_t
 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
-             unsigned char *data, int size) {
+             unsigned char *data, int size)
+{
        dns_rdata_dnskey_t dnskey;
        dns_rdata_keydata_t keydata;
        isc_buffer_t buf;
@@ -8479,11 +8494,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
        if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
                rdset = &kfetch->dnskeysigset;
        else
-               return (now + HOUR);
+               return (now + dns_zone_mkey_hour);
 
        result = dns_rdataset_first(rdset);
        if (result != ISC_R_SUCCESS)
-               return (now + HOUR);
+               return (now + dns_zone_mkey_hour);
 
        dns_rdataset_current(rdset, &sigrr);
        result = dns_rdata_tostruct(&sigrr, &sig, NULL);
@@ -8498,11 +8513,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
                                t = exp;
                }
 
-               if (t > (15*DAY))
-                       t = (15*DAY);
+               if (t > (15 * dns_zone_mkey_day))
+                       t = (15 * dns_zone_mkey_day);
 
-               if (t < HOUR)
-                       t = HOUR;
+               if (t < dns_zone_mkey_hour)
+                       t = dns_zone_mkey_hour;
        } else {
                t = sig.originalttl / 10;
 
@@ -8512,11 +8527,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
                                t = exp;
                }
 
-               if (t > DAY)
-                       t = DAY;
+               if (t > dns_zone_mkey_day)
+                       t = dns_zone_mkey_day;
 
-               if (t < HOUR)
-                       t = HOUR;
+               if (t < dns_zone_mkey_hour)
+                       t = dns_zone_mkey_hour;
        }
 
        return (now + t);
@@ -8559,7 +8574,7 @@ minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
                if (result != ISC_R_SUCCESS)
                        goto failure;
                keydata.refresh = refresh_time(kfetch, ISC_TRUE);
-               set_refreshkeytimer(zone, &keydata, now);
+               set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
 
                dns_rdata_reset(&rdata);
                isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
@@ -8602,8 +8617,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
        /* Generate a key from keydata */
        isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
        dns_keydata_todnskey(keydata, &dnskey, NULL);
-       dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
-                                    &dnskey, &keyb);
+       dns_rdata_fromstruct(&rr, keydata->common.rdclass,
+                            dns_rdatatype_dnskey, &dnskey, &keyb);
        result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
        if (result != ISC_R_SUCCESS)
                return (ISC_FALSE);
@@ -8611,7 +8626,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
        /* See if that key generated any of the signatures */
        for (result = dns_rdataset_first(&kfetch->dnskeysigset);
             result == ISC_R_SUCCESS;
-            result = dns_rdataset_next(&kfetch->dnskeysigset)) {
+            result = dns_rdataset_next(&kfetch->dnskeysigset))
+       {
                dns_fixedname_t fixed;
                dns_fixedname_init(&fixed);
 
@@ -8621,8 +8637,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
                if (dst_key_alg(dstkey) == sig.algorithm &&
-                   (dst_key_id(dstkey) == sig.keyid ||
-                    dst_key_rid(dstkey) == sig.keyid)) {
+                   dst_key_rid(dstkey) == sig.keyid)
+               {
                        result = dns_dnssec_verify2(keyname,
                                            &kfetch->dnskeyset,
                                            dstkey, ISC_FALSE, mctx, &sigrr,
@@ -8784,8 +8800,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                                dns_trust_secure;
                                        kfetch->dnskeysigset.trust =
                                                dns_trust_secure;
-                                       dns_keytable_detachkeynode(secroots,
-                                                                  &keynode);
                                        break;
                                }
                        }
@@ -8796,6 +8810,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                        keynode = nextnode;
                }
 
+               if (keynode != NULL)
+                       dns_keytable_detachkeynode(secroots, &keynode);
+
                if (kfetch->dnskeyset.trust == dns_trust_secure)
                        break;
        }
@@ -8840,31 +8857,34 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                        isc_boolean_t deletekey = ISC_FALSE;
 
                        if (!secure) {
-                               if (now > keydata.removehd)
+                               if (keydata.removehd != 0 &&
+                                   keydata.removehd <= now)
                                        deletekey = ISC_TRUE;
-                       } else if (now < keydata.addhd) {
+                       } else if (keydata.addhd == 0) {
+                               deletekey = ISC_TRUE;
+                       } else if (keydata.addhd > now) {
                                dns_zone_log(zone, ISC_LOG_WARNING,
                                             "Pending key unexpectedly missing "
                                             "from %s; restarting acceptance "
                                             "timer", namebuf);
-                               keydata.addhd = now + MONTH;
+                               if (keydata.addhd < now + dns_zone_mkey_month)
+                                       keydata.addhd =
+                                               now + dns_zone_mkey_month;
                                keydata.refresh = refresh_time(kfetch,
                                                               ISC_FALSE);
-                       } else if (keydata.addhd == 0) {
-                               keydata.addhd = now;
                        } else if (keydata.removehd == 0) {
                                dns_zone_log(zone, ISC_LOG_WARNING,
                                             "Active key unexpectedly missing "
                                             "from %s", namebuf);
-                               keydata.refresh = now + HOUR;
-                       } else if (now > keydata.removehd) {
+                               keydata.refresh = now + dns_zone_mkey_hour;
+                       } else if (keydata.removehd <= now) {
                                deletekey = ISC_TRUE;
                        } else {
                                keydata.refresh = refresh_time(kfetch,
                                                               ISC_FALSE);
                        }
 
-                       if  (secure || deletekey) {
+                       if (secure || deletekey) {
                                /* Delete old version */
                                CHECK(update_one_rr(kfetch->db, ver, &diff,
                                                    DNS_DIFFOP_DEL, keyname, 0,
@@ -8885,7 +8905,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                            DNS_DIFFOP_ADD, keyname, 0,
                                            &keydatarr));
 
-                       set_refreshkeytimer(zone, &keydata, now);
+                       set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
                }
        }
 
@@ -8907,7 +8927,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
         */
        for (result = dns_rdataset_first(&kfetch->dnskeyset);
             result == ISC_R_SUCCESS;
-            result = dns_rdataset_next(&kfetch->dnskeyset)) {
+            result = dns_rdataset_next(&kfetch->dnskeyset))
+       {
                isc_boolean_t revoked = ISC_FALSE;
                isc_boolean_t newkey = ISC_FALSE;
                isc_boolean_t updatekey = ISC_FALSE;
@@ -8943,34 +8964,43 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                        dns_view_untrust(zone->view, keyname,
                                                         &dnskey, mctx);
 
+                                       /* But ensure there's a null key */
+                                       fail_secure(zone, keyname);
+
                                        /* If initializing, delete now */
                                        if (keydata.addhd == 0)
                                                deletekey = ISC_TRUE;
-                                       else
-                                               keydata.removehd = now + MONTH;
+                                       else {
+                                               keydata.removehd = now +
+                                                       dns_zone_mkey_month;
+                                               keydata.flags |=
+                                                       DNS_KEYFLAG_REVOKE;
+                                       }
                                } else if (keydata.removehd < now) {
                                        /* Scheduled for removal */
                                        deletekey = ISC_TRUE;
                                }
-                       } else if (revoked) {
-                               if (secure && keydata.removehd == 0) {
-                                       dns_zone_log(zone, ISC_LOG_WARNING,
-                                                    "Active key for zone "
-                                                    "'%s' is revoked but "
-                                                    "did not self-sign; "
-                                                        "ignoring.", namebuf);
-                                               continue;
-                               }
+                       } else if (revoked && keydata.removehd == 0) {
+                               dns_zone_log(zone, ISC_LOG_WARNING,
+                                            "Active key for zone "
+                                            "'%s' is revoked but "
+                                            "did not self-sign; "
+                                            "ignoring.", namebuf);
+                                       continue;
                        } else if (secure) {
                                if (keydata.removehd != 0) {
                                        /*
                                         * Key isn't revoked--but it
                                         * seems it used to be.
                                         * Remove it now and add it
-                                        * back as if it were a fresh key.
+                                        * back as if it were a fresh key,
+                                        * with a 30 day acceptance timer.
                                         */
                                        deletekey = ISC_TRUE;
                                        newkey = ISC_TRUE;
+                                       keydata.removehd = 0;
+                                       keydata.addhd = 
+                                               now + dns_zone_mkey_month;
                                } else if (keydata.addhd > now)
                                        pending++;
                                else if (keydata.addhd == 0)
@@ -8978,6 +9008,13 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
 
                                if (keydata.addhd <= now)
                                        trustkey = ISC_TRUE;
+                       } else if (keydata.addhd > now) {
+                               /*
+                                * Not secure, and key is pending:
+                                * reset the acceptance timer
+                                */
+                               pending++;
+                               keydata.addhd = now + dns_zone_mkey_month;
                        }
 
                        if (!deletekey && !newkey)
@@ -9039,7 +9076,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
                        dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
                                               NULL);
-                       keydata.addhd = initializing ? now : now + MONTH;
+                       keydata.addhd = initializing
+                                        ? now : now + dns_zone_mkey_month;
                        keydata.refresh = refresh_time(kfetch, ISC_FALSE);
                        dns_rdata_reset(&keydatarr);
                        isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
@@ -9062,7 +9100,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
 
                if (secure && !deletekey) {
                        INSIST(newkey || updatekey);
-                       set_refreshkeytimer(zone, &keydata, now);
+                       set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
                }
        }
 
@@ -9276,7 +9314,7 @@ zone_refreshkeys(dns_zone_t *zone) {
                char timebuf[80];
 
                TIME_NOW(&timenow);
-               DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
+               DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
                zone->refreshkeytime = timethen;
                zone_settimer(zone, &timenow);
 
index 5d2b4fba4c7a4485bd80b5b16b151df53222131b..8e785f284866e8ac8781d71747ae7f6ee2fb71d7 100644 (file)
@@ -471,6 +471,7 @@ isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length) {
 
        REQUIRE(dynbuffer != NULL);
        REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
+       REQUIRE((*dynbuffer)->mctx != NULL);
 
        if ((*dynbuffer)->length > length)
                return (ISC_R_NOSPACE);
@@ -502,12 +503,16 @@ isc_result_t
 isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size) {
        isc_uint64_t len;
 
+       REQUIRE(dynbuffer != NULL);
        REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
 
        len = (*dynbuffer)->length;
        if ((len - (*dynbuffer)->used) >= size)
                return (ISC_R_SUCCESS);
 
+       if ((*dynbuffer)->mctx == NULL)
+               return (ISC_R_NOSPACE);
+
        /* Round to nearest buffer size increment */
        len = size + (*dynbuffer)->used;
        len = (len + ISC_BUFFER_INCR - 1 - ((len - 1) % ISC_BUFFER_INCR));
index 18817363fac6735bc2605f4714ccaf2cc9e17c02..3a4e47653412331b7c7028cce44ca1ec91cf4637 100644 (file)
@@ -648,7 +648,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
        isc_socketevent_t *sev = (isc_socketevent_t *)ev;
        isc_httpdurl_t *url;
        isc_time_t now;
-       char datebuf[32];  /* Only need 30, but safety first */
+       char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
 
        ENTER("recv");
 
@@ -729,7 +729,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
        isc_httpd_addheader(httpd, "Expires", datebuf);
 
        if (url != NULL && url->isstatic) {
-               char loadbuf[32];
+               char loadbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
                isc_time_formathttptimestamp(&url->loadtime,
                                             loadbuf, sizeof(loadbuf));
                isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
index caddec2bec4c69a4c2af9599b8d9a60e71283640..eb56ff9fb65ebb64b974c7415964767689b87196 100644 (file)
@@ -29,7 +29,7 @@ ATF_TC_HEAD(isc_time_parsehttptimestamp, tc) {
 ATF_TC_BODY(isc_time_parsehttptimestamp, tc) {
        isc_result_t result;
        isc_time_t t, x;
-       char buf[100];
+       char buf[ISC_FORMATHTTPTIMESTAMP_SIZE];
 
        setenv("TZ", "PST8PDT", 1);
        result = isc_time_now(&t);
index 2a83f099305fb72c12c9753ceebd596ccb5375a5..ade55247a93b944918102024575b733fcfb8197c 100644 (file)
@@ -43,6 +43,13 @@ struct isc_interval {
 
 extern const isc_interval_t * const isc_interval_zero;
 
+/*
+ * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
+ * more for other locales to handle longer national abbreviations when
+ * expanding strftime's %a and %b.
+ */
+#define ISC_FORMATHTTPTIMESTAMP_SIZE 50
+
 ISC_LANG_BEGINDECLS
 
 void
index caa31b4f65750d0c955a8253bd2be09db9a3ca1a..97ccfa06779a412df8f6fa185f2bb64bc369bf70 100644 (file)
@@ -406,6 +406,9 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
 
        REQUIRE(len > 0);
 
+       /*
+        * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+ %b (29+)
+        */
        now = (time_t)t->seconds;
        flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
        INSIST(flen < len);
index fe842ab95bd8610fc5b9191e1fc078e7c62b9d8f..bfd5bc0d622c60b3b813cb78a2e397815d68b8ce 100644 (file)
@@ -41,6 +41,13 @@ struct isc_interval {
 
 LIBISC_EXTERNAL_DATA extern const isc_interval_t * const isc_interval_zero;
 
+/*
+ * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
+ * more for other locales to handle longer national abbreviations when
+ * expanding strftime's %a and %b.
+ */
+#define ISC_FORMATHTTPTIMESTAMP_SIZE 50
+
 ISC_LANG_BEGINDECLS
 
 void