]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
dnssec-keygen can create keys given dnssec-policy
authorMatthijs Mekking <matthijs@isc.org>
Wed, 11 Sep 2019 14:38:49 +0000 (16:38 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 6 Nov 2019 21:31:45 +0000 (22:31 +0100)
This commit adds code for generating keys with dnssec-keygen given
a specific dnssec-policy.

The dnssec-policy can be set with a new option '-k'. The '-l'
option can be used to set a configuration file that contains a
specific dnssec-policy.

Because the dnssec-policy dictates how the keys should look like,
many of the existing dnssec-keygen options cannot be used together
with '-k'.

If the dnssec-policy lists multiple keys, dnssec-keygen has now the
possibility to generate multiple keys at one run.

Add two tests for creating keys with '-k': One with the default
policy, one with multiple keys from the configuration.

bin/dnssec/Makefile.in
bin/dnssec/dnssec-keygen.c
bin/dnssec/dnssec-keygen.docbook
bin/dnssec/win32/keygen.vcxproj.in
bin/tests/system/kasp/clean.sh [new file with mode: 0644]
bin/tests/system/kasp/kasp.conf [new file with mode: 0644]
bin/tests/system/kasp/setup.sh [new file with mode: 0644]
bin/tests/system/kasp/tests.sh [new file with mode: 0644]
util/copyrights

index 32d79f429220e2ae0322f9916693b6ac11a8e078..7d3b15f5d3be6db6929245c47a27d746b2bf385b 100644 (file)
@@ -15,24 +15,26 @@ VERSION=@BIND9_VERSION@
 
 @BIND9_MAKE_INCLUDES@
 
-CINCLUDES =    ${DNS_INCLUDES} ${ISC_INCLUDES} \
+CINCLUDES =    ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \
                ${OPENSSL_CFLAGS}
 
-CDEFINES =     -DVERSION=\"${VERSION}\"
+CDEFINES =     -DVERSION=\"${VERSION}\" -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
 CWARNINGS =
 
 DNSLIBS =      ../../lib/dns/libdns.@A@ ${MAXMINDDB_LIBS} @DNS_CRYPTO_LIBS@
+ISCCFGLIBS =   ../../lib/isccfg/libisccfg.@A@
 ISCLIBS =      ../../lib/isc/libisc.@A@ ${OPENSSL_LIBS} ${JSON_C_LIBS} ${LIBXML2_LIBS}
 ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ${OPENSSL_LIBS} ${JSON_C_LIBS} ${LIBXML2_LIBS}
 
 DNSDEPLIBS =   ../../lib/dns/libdns.@A@
 ISCDEPLIBS =   ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS =        ../../lib/isccfg/libisccfg.@A@
 
-DEPLIBS =      ${DNSDEPLIBS} ${ISCDEPLIBS}
+DEPLIBS =      ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
 
-LIBS =         ${DNSLIBS} ${ISCLIBS} @LIBS@
+LIBS =         ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
 
-NOSYMLIBS =    ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@
+NOSYMLIBS =    ${DNSLIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@
 
 # Alphabetically
 TARGETS =      dnssec-cds@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
@@ -48,7 +50,7 @@ SRCS =                dnssec-cds.c dnssec-dsfromkey.c dnssec-importkey.c \
                dnssec-settime.c dnssec-signzone.c dnssec-verify.c \
                dnssectool.c
 
-MANPAGES =     dnssec-cds.8 dnssec-dsfromkey.8  dnssec-importkey.8 \
+MANPAGES =     dnssec-cds.8 dnssec-dsfromkey.8 dnssec-importkey.8 \
                dnssec-keyfromlabel.8 dnssec-keygen.8 dnssec-revoke.8 \
                dnssec-settime.8 dnssec-signzone.8 dnssec-verify.8
 
index 54ba5dce653d7e23dfad1a832f1e8a9faed4ff05..09b7c09508eb24730c49f48a6150d90c3aa43ae6 100644 (file)
 #include <isc/string.h>
 #include <isc/util.h>
 
+#include <isccfg/cfg.h>
+#include <isccfg/namedconf.h>
+#include <isccfg/kaspconf.h>
+#include <isccfg/grammar.h>
+
 #include <pk11/site.h>
 
 #include <dns/dnssec.h>
 #include <dns/fixedname.h>
+#include <dns/kasp.h>
 #include <dns/keyvalues.h>
 #include <dns/log.h>
 #include <dns/name.h>
@@ -115,6 +121,10 @@ struct keygen_ctx {
        bool             showprogress;
        bool             quiet;
        bool             oldstyle;
+       /* state */
+       time_t           lifetime;
+       bool             ksk;
+       bool             zsk;
 };
 
 typedef struct keygen_ctx keygen_ctx_t;
@@ -127,6 +137,9 @@ usage(void) {
        fprintf(stderr, "    name: owner of the key\n");
        fprintf(stderr, "Options:\n");
        fprintf(stderr, "    -K <directory>: write keys into directory\n");
+       fprintf(stderr, "    -k <policy>: generate keys for dnssec-policy\n");
+       fprintf(stderr, "    -l <file>: configuration file with dnssec-policy "
+                                      "statement\n");
        fprintf(stderr, "    -a <algorithm>:\n");
        fprintf(stderr, "        RSASHA1 | NSEC3RSASHA1 |\n");
        fprintf(stderr, "        RSASHA256 | RSASHA512 |\n");
@@ -229,6 +242,53 @@ progress(int p)
        (void) fflush(stderr);
 }
 
+static void
+kasp_from_conf(cfg_obj_t* config, isc_mem_t* mctx, const char* name,
+              dns_kasp_t** kaspp)
+{
+       const cfg_listelt_t *element;
+       const cfg_obj_t *kasps = NULL;
+       dns_kasp_t *kasp = NULL, *kasp_next;
+       isc_result_t result = ISC_R_NOTFOUND;
+       dns_kasplist_t kasplist;
+
+       ISC_LIST_INIT(kasplist);
+
+       (void)cfg_map_get(config, "dnssec-policy", &kasps);
+       for (element = cfg_list_first(kasps); element != NULL;
+            element = cfg_list_next(element))
+       {
+               cfg_obj_t *kconfig = cfg_listelt_value(element);
+               kasp = NULL;
+               if (strcmp(cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
+                          name) != 0)
+               {
+                       continue;
+               }
+
+               result = cfg_kasp_fromconfig(kconfig, mctx, &kasplist, &kasp);
+               if (result != ISC_R_SUCCESS) {
+                       fatal("failed to configure dnssec-policy '%s': %s",
+                             cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
+                             isc_result_totext(result));
+               }
+               INSIST(kasp != NULL);
+               dns_kasp_freeze(kasp);
+               break;
+       }
+
+       *kaspp = kasp;
+
+       /*
+        * Same cleanup for kasp list.
+        */
+       for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
+               kasp_next = ISC_LIST_NEXT(kasp, link);
+               ISC_LIST_UNLINK(kasplist, kasp, link);
+               dns_kasp_detach(&kasp);
+       }
+}
+
 static void
 keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
 {
@@ -385,7 +445,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
                        fatal("-S and -G cannot be used together");
 
                ret = dst_key_fromnamedfile(ctx->predecessor, ctx->directory,
-                                           DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+                                           (DST_TYPE_PUBLIC|
+                                            DST_TYPE_PRIVATE|DST_TYPE_STATE),
                                            mctx, &prevkey);
                if (ret != ISC_R_SUCCESS)
                        fatal("Invalid keyfile %s: %s",
@@ -665,6 +726,13 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
                if (ctx->setttl)
                        dst_key_setttl(key, ctx->ttl);
 
+               /* Set dnssec-policy related metadata */
+               if (ctx->policy) {
+                       dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
+                       dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
+                       dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
+               }
+
                /*
                 * Do not overwrite an existing key, or create a key
                 * if there is a risk of ID collision due to this key
@@ -754,8 +822,8 @@ main(int argc, char **argv) {
        /*
         * Process memory debugging argument first.
         */
-#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:L:m:n:P:p:qR:r:S:s:T:t:" \
-                     "v:V"
+#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:k:L:l:m:n:P:p:qR:r:S:s:" \
+                     "T:t:v:V"
        while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
                switch (ch) {
                case 'm':
@@ -834,10 +902,15 @@ main(int argc, char **argv) {
                                fatal("cannot open directory %s: %s",
                                      ctx.directory, isc_result_totext(ret));
                        break;
+               case 'k':
+                       ctx.policy = isc_commandline_argument;
+                       break;
                case 'L':
                        ctx.ttl = strtottl(isc_commandline_argument);
                        ctx.setttl = true;
                        break;
+               case 'l':
+                       ctx.configfile = isc_commandline_argument;
                        break;
                case 'n':
                        ctx.nametype = isc_commandline_argument;
@@ -1001,15 +1074,21 @@ main(int argc, char **argv) {
 
        ctx.rdclass = strtoclass(classname);
 
+       if (ctx.configfile == NULL || ctx.configfile[0] == '\0') {
+               ctx.configfile = NAMED_CONFFILE;
+       }
+
        if (ctx.predecessor == NULL) {
                if (argc < isc_commandline_index + 1)
                        fatal("the key name was not specified");
                if (argc > isc_commandline_index + 1)
                        fatal("extraneous arguments");
+       }
 
-               if (algname == NULL)
+       if (ctx.predecessor == NULL && ctx.policy == NULL) {
+               if (algname == NULL) {
                        fatal("no algorithm specified");
-
+               }
                r.base = algname;
                r.length = strlen(algname);
                ret = dns_secalg_fromtext(&ctx.alg, &r);
@@ -1021,7 +1100,112 @@ main(int argc, char **argv) {
                }
        }
 
-       keygen(&ctx, mctx, argc, argv);
+       if (ctx.policy != NULL) {
+               if (ctx.nametype != NULL) {
+                       fatal("-k and -n cannot be used together");
+               }
+               if (ctx.predecessor != NULL) {
+                       fatal("-k and -S cannot be used together");
+               }
+               if (ctx.oldstyle) {
+                       fatal("-k and -C cannot be used together");
+               }
+               if (ctx.setttl) {
+                       fatal("-k and -L cannot be used together");
+               }
+               if (ctx.prepub > 0) {
+                       fatal("-k and -i cannot be used together");
+               }
+               if (ctx.size != -1) {
+                       fatal("-k and -b cannot be used together");
+               }
+               if (ctx.kskflag || ctx.revflag) {
+                       fatal("-k and -f cannot be used together");
+               }
+               if (ctx.options & DST_TYPE_KEY) {
+                       fatal("-k and -T KEY cannot be used together");
+               }
+               if (ctx.use_nsec3) {
+                       fatal("-k and -3 cannot be used together");
+               }
+
+               if (ctx.setpub || ctx.setact || ctx.setrev || ctx.setinact ||
+                   ctx.setdel || ctx.unsetpub || ctx.unsetact ||
+                   ctx.unsetrev || ctx.unsetinact || ctx.unsetdel ||
+                   ctx.setsyncadd || ctx.setsyncdel)
+               {
+                       fatal("cannot use -k together with "
+                             "-P, -A, -R, -I, or -D options "
+                             "(use dnssec-settime on keys afterwards)");
+               }
+
+               ctx.options |= DST_TYPE_STATE;
+               ctx.genonly = true;
+
+               if (strcmp(ctx.policy, "default") == 0) {
+                       ctx.use_nsec3 = false;
+                       ctx.alg = DST_ALG_ECDSA256;
+                       ctx.size = 0;
+                       ctx.kskflag = DNS_KEYFLAG_KSK;
+                       ctx.ttl = 3600;
+                       ctx.setttl = true;
+                       ctx.ksk = true;
+                       ctx.zsk = true;
+                       ctx.lifetime = 0;
+
+                       keygen(&ctx, mctx, argc, argv);
+               } else {
+                       cfg_parser_t *parser = NULL;
+                       cfg_obj_t *config = NULL;
+                       dns_kasp_t* kasp = NULL;
+                       dns_kasp_key_t* kaspkey = NULL;
+
+                       RUNTIME_CHECK(cfg_parser_create(mctx, log, &parser)
+                                     == ISC_R_SUCCESS);
+                       if (cfg_parse_file(parser, ctx.configfile,
+                               &cfg_type_namedconf, &config) != ISC_R_SUCCESS)
+                       {
+                               fatal("unable to load dnssec-policy '%s' from "
+                                     "'%s'", ctx.policy, ctx.configfile);
+                       }
+
+                       kasp_from_conf(config, mctx, ctx.policy, &kasp);
+                       if (kasp == NULL) {
+                               fatal("failed to load dnssec-policy '%s'",
+                                     ctx.policy);
+                       }
+                       if (ISC_LIST_EMPTY(kasp->keys)) {
+                               fatal("dnssec-policy '%s' has no keys "
+                                     "configured", ctx.policy);
+                       }
+
+                       ctx.ttl = dns_kasp_dnskeyttl(kasp);
+                       ctx.setttl = true;
+
+                       kaspkey = ISC_LIST_HEAD(kasp->keys);
+
+                       while (kaspkey != NULL) {
+                               ctx.use_nsec3 = false;
+                               ctx.alg = dns_kasp_key_algorithm(kaspkey);
+                               ctx.size = dns_kasp_key_size(kaspkey);
+                               ctx.kskflag = dns_kasp_key_ksk(kaspkey) ?
+                                             DNS_KEYFLAG_KSK : 0;
+                               ctx.ksk = dns_kasp_key_ksk(kaspkey);
+                               ctx.zsk = dns_kasp_key_zsk(kaspkey);
+                               ctx.lifetime = dns_kasp_key_lifetime(kaspkey);
+
+                               keygen(&ctx, mctx, argc, argv);
+
+                               kaspkey = ISC_LIST_NEXT(kaspkey, link);
+                       }
+
+                       dns_kasp_detach(&kasp);
+                       cfg_obj_destroy(parser, &config);
+                       cfg_parser_destroy(&parser);
+               }
+       } else {
+               keygen(&ctx, mctx, argc, argv);
+       }
 
        cleanup_logging(&log);
        dst_lib_destroy();
index f194631db34ee7622bb110276169df4041452084..46ebec3dcd51092c9a123795dca145140972d9ef 100644 (file)
@@ -75,7 +75,9 @@
       <arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+      <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">policy</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+      <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">file</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
        </listitem>
       </varlistentry>
 
+      <varlistentry>
+       <term>-k <replaceable class="parameter">policy</replaceable></term>
+       <listitem>
+         <para>
+           Create keys for a specific dnssec-policy.  If a policy uses
+           multiple keys, <command>dnssec-keygen</command> will generate
+           multiple keys.  This will also create a ".state" file to keep
+           track of the key state.
+         </para>
+         <para>
+           This option creates keys according to the dnssec-policy
+           configuration, hence it cannot be used together with many of
+           the other options that <command>dnssec-keygen</command>
+           provides.
+         </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <term>-L <replaceable class="parameter">ttl</replaceable></term>
        <listitem>
        </listitem>
       </varlistentry>
 
+      <varlistentry>
+       <term>-l <replaceable class="parameter">file</replaceable></term>
+       <listitem>
+         <para>
+           Provide a configuration file that contains a dnssec-policy
+           statement (matching the policy set with <command>-k</command>).
+         </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <term>-n <replaceable class="parameter">nametype</replaceable></term>
        <listitem>
index 72d1d9c99f9817fab47f764c8be8f7df7103747d..ddef528081cc3da15d054114c1e2c1fa8d2e8d99 100644 (file)
       <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
       <BrowseInformation>true</BrowseInformation>
       <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
-      <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\win32;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <CompileAs>CompileAsC</CompileAs>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
-      <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libisccfg.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
@@ -94,7 +94,7 @@
       <ObjectFileName>.\$(Configuration)\</ObjectFileName>
       <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
       <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
-      <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\win32;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <CompileAs>CompileAsC</CompileAs>
     </ClCompile>
     <Link>
       <OptimizeReferences>true</OptimizeReferences>
       <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
       <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
-      <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libisccfg.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
diff --git a/bin/tests/system/kasp/clean.sh b/bin/tests/system/kasp/clean.sh
new file mode 100644 (file)
index 0000000..491354f
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./keygen.*
+rm -f ./K*.private ./K*.key ./K*.state ./K*.cmp
+rm -f ./keys/K*
+rmdir ./keys/
diff --git a/bin/tests/system/kasp/kasp.conf b/bin/tests/system/kasp/kasp.conf
new file mode 100644 (file)
index 0000000..2ef71b3
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is just a random selection of configuration options.
+ */
+
+dnssec-policy "kasp" {
+       dnskey-ttl 200;
+
+       keys {
+               csk key-directory P1Y 13;
+               ksk key-directory P1Y 8;
+               zsk key-directory P30D 8 1024;
+               zsk key-directory P6M 8 2000;
+       };
+};
diff --git a/bin/tests/system/kasp/setup.sh b/bin/tests/system/kasp/setup.sh
new file mode 100644 (file)
index 0000000..05b71ac
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. "$SYSTEMTESTTOP/conf.sh"
+
+set -e
+
+$SHELL clean.sh
+
+mkdir keys
diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh
new file mode 100644 (file)
index 0000000..92de756
--- /dev/null
@@ -0,0 +1,182 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+SYSTEMTESTTOP=..
+. "$SYSTEMTESTTOP/conf.sh"
+
+set -e
+
+status=0
+n=0
+log=1
+
+################################################################################
+# Utilities                                                                    #
+################################################################################
+
+# Get the key ids from key files for zone $2 in directory $1
+# that matches algorithm $3.
+get_keyids() {
+       dir=$1
+       zone=$2
+       algorithm=$(printf "%03d" $3)
+       start="${dir}/K${zone}.+${algorithm}+"
+       end=".key"
+
+       ls ${start}*${end} | sed "s/$dir\/K${zone}.+${algorithm}+\([0-9]\{5\}\)${end}/\1/"
+}
+
+log_error() {
+       test $log -eq 1 && echo_i "error: $1"
+       ret=$((ret+1))
+}
+
+# Check the created key in directory $1 for zone $2.
+# $3: key role. Must be one of "csk", "ksk", or "zsk".
+# $4: key identifier (zero padded)
+# $5: algorithm number
+# $6: algorithm (string format)
+# $7: algorithm length
+# $8: dnskey ttl
+# $9: key lifetime
+check_created_key() {
+       dir=$1
+       zone=$2
+       role=$3
+       key_idpad=$4
+       key_id=$(echo $key_idpad | sed 's/^0*//')
+       alg_num=$5
+        alg_numpad=$(printf "%03d" $alg_num)
+       alg_string=$6
+       length=$7
+       dnskey_ttl=$8
+       lifetime=$9
+
+       ksk="no"
+       zsk="no"
+       if [ "$role" == "ksk" ]; then
+               role2="key-signing"
+               ksk="yes"
+               flags="257"
+       elif [ "$role" == "zsk" ]; then
+               role2="zone-signing"
+               zsk="yes"
+               flags="256"
+       elif [ "$role" == "csk" ]; then
+               role2="key-signing"
+               zsk="yes"
+               ksk="yes"
+               flags="257"
+       fi
+
+       KEY_FILE="${dir}/K${zone}.+${alg_numpad}+${key_idpad}.key"
+       PRIVATE_FILE="${dir}/K${zone}.+${alg_numpad}+${key_idpad}.private"
+       STATE_FILE="${dir}/K${zone}.+${alg_numpad}+${key_idpad}.state"
+
+       # Check the public key file. We expect three lines: a comment,
+       # a "Created" line, and the DNSKEY record.
+       lines=$(cat $KEY_FILE | wc -l)
+       test "$lines" -eq 3 || log_error "bad public keyfile $KEY_FILE"
+       grep "This is a ${role2} key, keyid ${key_id}, for ${zone}." $KEY_FILE > /dev/null || log_error "mismatch top comment in $KEY_FILE"
+       grep "; Created:" $KEY_FILE > /dev/null || log_error "mismatch created comment in $KEY_FILE"
+       grep "${zone}\. ${dnskey_ttl} IN DNSKEY ${flags} 3 ${alg_num}" $KEY_FILE > /dev/null || log_error "mismatch DNSKEY record in $KEY_FILE"
+       # Now check the private key file.
+       grep "Private-key-format: v1.3" $PRIVATE_FILE > /dev/null || log_error "mismatch private key format in $PRIVATE_FILE"
+       grep "Algorithm: ${alg_num} (${alg_string})" $PRIVATE_FILE > /dev/null || log_error "mismatch algorithm in $PRIVATE_FILE"
+       grep "Created:" $PRIVATE_FILE > /dev/null || log_error "mismatch created in $PRIVATE_FILE"
+       # Now check the key state file. There should be seven lines:
+       # a top comment, "Generated", "Lifetime", "Algorithm", "Length",
+       # "KSK", and "ZSK".
+       lines=$(cat $STATE_FILE | wc -l)
+       test "$lines" -eq 7 || log_error "bad state keyfile $STATE_FILE"
+       grep "This is the state of key ${key_id}, for ${zone}." $STATE_FILE > /dev/null || log_error "mismatch top comment in $STATE_FILE"
+       # XXX: Could check if generated is ~now.
+       grep "Generated: " $STATE_FILE > /dev/null || log_error "mismatch generated in $STATE_FILE"
+       grep "Lifetime: ${lifetime}" $STATE_FILE > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
+       grep "Algorithm: ${alg_num}" $STATE_FILE > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
+       grep "Length: ${length}" $STATE_FILE > /dev/null || log_error "mismatch length in $STATE_FILE"
+       grep "KSK: ${ksk}" $STATE_FILE > /dev/null || log_error "mismatch ksk in $STATE_FILE"
+       grep "ZSK: ${zsk}" $STATE_FILE > /dev/null || log_error "mismatch zsk in $STATE_FILE"
+}
+
+################################################################################
+# Tests                                                                        #
+################################################################################
+
+#
+# dnssec-keygen
+#
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
+ret=0
+$KEYGEN -k _default kasp > keygen.out._default.test$n 2>/dev/null || ret=1
+lines=$(cat keygen.out._default.test$n | wc -l)
+test "$lines" -eq 1 || log_error "wrong number of keys created for policy _default"
+KEY_ID=$(get_keyids "." "kasp" "13")
+echo_i "check key $KEY_ID..."
+check_created_key "." "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "3600" "0"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
+ret=0
+$KEYGEN -K keys -k kasp -l kasp.conf kasp > keygen.out.kasp.test$n 2>/dev/null || ret=1
+lines=$(cat keygen.out.kasp.test$n | wc -l)
+test "$lines" -eq 4 || log_error "wrong number of keys created for policy kasp"
+# Check one algorithm.
+KEY_ID=$(get_keyids "keys" "kasp" "13")
+echo_i "check key $KEY_ID..."
+check_created_key "keys" "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "200" "31536000"
+# Temporarily don't log errors because we are searching multiple files.
+log=0
+# Check the other algorithm.
+KEY_IDS=$(get_keyids "keys" "kasp" "8")
+for KEY_ID in $KEY_IDS; do
+       echo_i "check key $KEY_ID..."
+       # There are three key files with the same algorithm.
+       # Check them until a match is found.
+       ret=0 && check_created_key "keys" "kasp" "ksk" $KEY_ID "8" "RSASHA256" "2048" "200" "31536000"
+       test "$ret" -gt 0 && ret=0 && check_created_key "keys" "kasp" "zsk" $KEY_ID "8" "RSASHA256" "1024" "200" "2592000"
+       test "$ret" -gt 0 && ret=0 && check_created_key "keys" "kasp" "zsk" $KEY_ID "8" "RSASHA256" "2000" "200" "16070400"
+       # If ret is non-zero, non of the files matched.
+       test "$ret" -eq 0 || echo_i "failed"
+       status=$((status+ret))
+
+done
+# Turn error logs on again.
+log=1
+
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
+ret=0
+$KEYGEN -k default kasp > keygen.out.default.test$n 2>/dev/null || ret=1
+lines=$(cat keygen.out.default.test$n | wc -l)
+test "$lines" -eq 1 || log_error "wrong number of keys created for policy default"
+KEY_ID=$(get_keyids "." "kasp" "13")
+echo_i "check key $KEY_ID..."
+check_created_key "." "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "3600" "0"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# dnssec-settime
+#
+
+#
+# named
+#
+
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
+
index f81e084f1f62db1f3ebf43b59d910713b3cea8b6..25250dc10be13d2aea8cdb06b50e815f66e777a8 100644 (file)
 ./bin/tests/system/ixfr/prereq.sh              SH      2001,2004,2007,2012,2014,2016,2018,2019
 ./bin/tests/system/ixfr/setup.sh               SH      2001,2004,2007,2011,2012,2013,2014,2016,2018,2019
 ./bin/tests/system/ixfr/tests.sh               SH      2001,2004,2007,2011,2012,2014,2016,2018,2019
+./bin/tests/system/kasp/clean.sh               SH      2019
+./bin/tests/system/kasp/setup.sh               SH      2019
+./bin/tests/system/kasp/tests.sh               SH      2019
 ./bin/tests/system/keepalive/clean.sh          SH      2017,2018,2019
 ./bin/tests/system/keepalive/expected          X       2017,2018,2019
 ./bin/tests/system/keepalive/setup.sh          SH      2017,2018,2019