]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2608. [func] Perform post signing verification checks in
authorMark Andrews <marka@isc.org>
Thu, 4 Jun 2009 02:13:37 +0000 (02:13 +0000)
committerMark Andrews <marka@isc.org>
Thu, 4 Jun 2009 02:13:37 +0000 (02:13 +0000)
                        dnssec-signzone.  These can be disabled with -P.

                        The post sign verification test ensures that for each
                        algorithm in use there is at least one non revoked
                        self signed KSK key.  That all revoked KSK keys are
                        self signed.  That all records in the zone are signed
                        by the algorithm.  [RT #19653]

25 files changed:
CHANGES
bin/dnssec/dnssec-signzone.c
bin/dnssec/dnssec-signzone.docbook
bin/dnssec/dnssectool.c
bin/tests/dnssec-signzone/Kexample.com.+005+07065.key [new file with mode: 0644]
bin/tests/dnssec-signzone/Kexample.com.+005+07065.private [new file with mode: 0644]
bin/tests/dnssec-signzone/Kexample.com.+005+23362.key [new file with mode: 0644]
bin/tests/dnssec-signzone/Kexample.com.+005+23362.private [new file with mode: 0644]
bin/tests/dnssec-signzone/bogus-ksk.key [new file with mode: 0644]
bin/tests/dnssec-signzone/bogus-zsk.key [new file with mode: 0644]
bin/tests/dnssec-signzone/run-test.sh [new file with mode: 0644]
bin/tests/dnssec-signzone/test1.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test2.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test3.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test4.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test5.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test6.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test7.zone [new file with mode: 0644]
bin/tests/dnssec-signzone/test8.zone [new file with mode: 0644]
bin/tests/system/dnssec/ns1/sign.sh
bin/tests/system/dnssec/ns2/sign.sh
bin/tests/system/dnssec/ns3/sign.sh
lib/dns/dnssec.c
lib/dns/include/dns/dnssec.h
lib/dns/include/dns/keyvalues.h

diff --git a/CHANGES b/CHANGES
index 7aff8e319036c0755e4be35b7acda510cf15cc95..18a678f1150d2ddcde3078b82531173fdf28849f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,12 @@
+2608.  [func]          Perform post signing verification checks in
+                       dnssec-signzone.  These can be disabled with -P.
+
+                       The post sign verification test ensures that for each
+                       algorithm in use there is at least one non revoked
+                       self signed KSK key.  That all revoked KSK keys are
+                       self signed.  That all records in the zone are signed
+                       by the algorithm.  [RT #19653]
+
 2607.  [bug]           named could incorrectly delete NSEC3 records for
                        empty nodes when processing a update request.
                        [RT #19749]
index 81706733c3d8a9925d946daf2d8d131c6586e9a9..e07743ea67184342d7427d71c91e0da4d5a076bd 100644 (file)
@@ -29,7 +29,7 @@
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dnssec-signzone.c,v 1.213 2009/05/07 09:33:52 fdupont Exp $ */
+/* $Id: dnssec-signzone.c,v 1.214 2009/06/04 02:13:37 marka Exp $ */
 
 /*! \file */
 
@@ -51,6 +51,7 @@
 #include <isc/os.h>
 #include <isc/print.h>
 #include <isc/random.h>
+#include <isc/rwlock.h>
 #include <isc/serial.h>
 #include <isc/stdio.h>
 #include <isc/stdlib.h>
@@ -106,6 +107,8 @@ struct signer_key_struct {
        isc_boolean_t issigningkey;
        isc_boolean_t isdsk;
        isc_boolean_t isksk;
+       isc_boolean_t wasused;
+       isc_boolean_t commandline;
        unsigned int position;
        ISC_LINK(signer_key_t) link;
 };
@@ -127,6 +130,7 @@ struct signer_event {
 
 static ISC_LIST(signer_key_t) keylist;
 static unsigned int keycount = 0;
+isc_rwlock_t keylist_lock;
 static isc_stdtime_t starttime = 0, endtime = 0, now;
 static int cycle = -1;
 static int jitter = 0;
@@ -164,6 +168,7 @@ static dns_master_style_t *dsstyle = NULL;
 static unsigned int serialformat = SOA_SERIAL_KEEP;
 static unsigned int hash_length = 0;
 static isc_boolean_t unknownalg = ISC_FALSE;
+static isc_boolean_t disable_zone_check = ISC_FALSE;
 
 #define INCSTAT(counter)               \
        if (printstats) {               \
@@ -206,6 +211,8 @@ newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
                key->isksk = ISC_FALSE;
                key->isdsk = ISC_TRUE;
        }
+       key->wasused = ISC_FALSE;
+       key->commandline = ISC_FALSE;
        key->position = keycount++;
        ISC_LINK_INIT(key, link);
        return (key);
@@ -255,13 +262,11 @@ iszonekey(signer_key_t *key) {
 }
 
 /*%
- * Finds the key that generated a RRSIG, if possible.  First look at the keys
- * that we've loaded already, and then see if there's a key on disk.
+ * Find the key if it is in our list.  If it is, return it, otherwise null.
+ * No locking is performed here, this must be done by the caller.
  */
 static signer_key_t *
-keythatsigned(dns_rdata_rrsig_t *rrsig) {
-       isc_result_t result;
-       dst_key_t *pubkey = NULL, *privkey = NULL;
+keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
        signer_key_t *key;
 
        key = ISC_LIST_HEAD(keylist);
@@ -269,15 +274,50 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
                if (rrsig->keyid == dst_key_id(key->key) &&
                    rrsig->algorithm == dst_key_alg(key->key) &&
                    dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
-                       return key;
+                       return (key);
                key = ISC_LIST_NEXT(key, link);
        }
+       return (NULL);
+}
+
+/*%
+ * Finds the key that generated a RRSIG, if possible.  First look at the keys
+ * that we've loaded already, and then see if there's a key on disk.
+ */
+static signer_key_t *
+keythatsigned(dns_rdata_rrsig_t *rrsig) {
+       isc_result_t result;
+       dst_key_t *pubkey = NULL, *privkey = NULL;
+       signer_key_t *key;
+
+       isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
+       key = keythatsigned_unlocked(rrsig);
+       isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
+       if (key != NULL)
+               return (key);
+
+       /*
+        * We did not find the key in our list.  Get a write lock now, since
+        * we may be modifying the bits.  We could do the tryupgrade() dance,
+        * but instead just get a write lock and check once again to see if
+        * it is on our list.  It's possible someone else may have added it
+        * after all.
+        */
+       isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
+
+       key = keythatsigned_unlocked(rrsig);
+       if (key != NULL) {
+               isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
+               return (key);
+       }
 
        result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
                                  rrsig->algorithm, DST_TYPE_PUBLIC,
                                  NULL, mctx, &pubkey);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
+               isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
                return (NULL);
+       }
 
        result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
                                  rrsig->algorithm,
@@ -289,6 +329,8 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
        } else
                key = newkeystruct(pubkey, ISC_FALSE);
        ISC_LIST_APPEND(keylist, key, link);
+
+       isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
        return (key);
 }
 
@@ -438,6 +480,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                                keep = ISC_TRUE;
                                wassignedby[key->position] = ISC_TRUE;
                                nowsignedby[key->position] = ISC_TRUE;
+                               key->wasused = ISC_TRUE;
                        } else {
                                vbprintf(2, "\trrsig by %s dropped - %s\n",
                                         sigstr,
@@ -453,6 +496,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                                keep = ISC_TRUE;
                                wassignedby[key->position] = ISC_TRUE;
                                nowsignedby[key->position] = ISC_TRUE;
+                               key->wasused = ISC_TRUE;
                        } else {
                                vbprintf(2, "\trrsig by %s dropped - %s\n",
                                         sigstr,
@@ -511,6 +555,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                        isc_buffer_init(&b, array, sizeof(array));
                        signwithkey(name, set, &trdata, key->key, &b);
                        nowsignedby[key->position] = ISC_TRUE;
+                       key->wasused = ISC_TRUE;
                        tuple = NULL;
                        result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
                                                      name, ttl, &trdata,
@@ -555,6 +600,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                dns_rdata_init(&trdata);
                isc_buffer_init(&b, array, sizeof(array));
                signwithkey(name, set, &trdata, key->key, &b);
+               key->wasused = ISC_TRUE;
                tuple = NULL;
                result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
                                              ttl, &trdata, &tuple);
@@ -1198,7 +1244,7 @@ cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
        dns_rdataset_t set;
        isc_result_t result, dresult;
 
-       if (outputformat != dns_masterformat_text)
+       if (outputformat != dns_masterformat_text || !disable_zone_check)
                return;
 
        dns_rdataset_init(&set);
@@ -1248,6 +1294,419 @@ postsign(void) {
        dns_dbiterator_destroy(&gdbiter);
 }
 
+static isc_boolean_t
+goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
+       dns_rdataset_t *rdataset)
+{
+       dns_rdata_dnskey_t key;
+       dns_rdata_rrsig_t sig;
+       dst_key_t *dstkey = NULL;
+       isc_result_t result;
+       
+       dns_rdata_tostruct(sigrdata, &sig, NULL);
+
+       for (result = dns_rdataset_first(keyrdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(keyrdataset)) {
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dns_rdataset_current(keyrdataset, &rdata);
+               dns_rdata_tostruct(&rdata, &key, NULL);
+               result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
+                                                &dstkey);
+               if (result != ISC_R_SUCCESS)
+                       return (ISC_FALSE);
+               if (sig.algorithm != key.algorithm ||
+                   sig.keyid != dst_key_id(dstkey) ||
+                   !dns_name_equal(&sig.signer, gorigin)) {
+                       dst_key_free(&dstkey);
+                       continue;
+               }
+               result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
+                                          mctx, sigrdata);
+               dst_key_free(&dstkey);
+               if (result == ISC_R_SUCCESS)
+                       return(ISC_TRUE);
+       }
+       return (ISC_FALSE);
+}
+
+static void
+verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
+         dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
+          char *bad_algorithms)
+{
+       unsigned char set_algorithms[256];
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char algbuf[80];
+       char typebuf[80];
+       dns_rdataset_t sigrdataset;
+       dns_rdatasetiter_t *rdsiter = NULL;
+       isc_result_t result;
+       int i;
+
+       dns_rdataset_init(&sigrdataset);
+       result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+       check_result(result, "dns_db_allrdatasets()");
+       for (result = dns_rdatasetiter_first(rdsiter);
+            result == ISC_R_SUCCESS;
+            result = dns_rdatasetiter_next(rdsiter)) {
+               dns_rdatasetiter_current(rdsiter, &sigrdataset);
+               if (sigrdataset.type == dns_rdatatype_rrsig &&
+                   sigrdataset.covers == rdataset->type)
+                       break;
+               dns_rdataset_disassociate(&sigrdataset);
+       }
+       if (result != ISC_R_SUCCESS) {
+               dns_name_format(name, namebuf, sizeof(namebuf));
+               type_format(rdataset->type, typebuf, sizeof(typebuf));
+               fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
+               for (i = 0; i < 256; i++)
+                       if (ksk_algorithms[i])
+                               bad_algorithms[i] = 1;
+               return;
+       }
+       
+       memset(set_algorithms, 0, sizeof(set_algorithms));
+       for (result = dns_rdataset_first(&sigrdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&sigrdataset)) {
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dns_rdata_rrsig_t sig;
+
+               dns_rdataset_current(&sigrdataset, &rdata);
+               dns_rdata_tostruct(&rdata, &sig, NULL);
+               if (set_algorithms[sig.algorithm] ||
+                   !ksk_algorithms[sig.algorithm])
+                       continue;
+               if (goodsig(&rdata, name, keyrdataset, rdataset))
+                       set_algorithms[sig.algorithm] = 1;
+       }
+       dns_rdatasetiter_destroy(&rdsiter);
+       if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
+               dns_name_format(name, namebuf, sizeof(namebuf));
+               type_format(rdataset->type, typebuf, sizeof(typebuf));
+               for (i = 0; i < 256; i++)
+                       if (ksk_algorithms[i] && !set_algorithms[i]) {
+                               alg_format(i, algbuf, sizeof(algbuf));
+                               fprintf(stderr, "Missing %s signature for "
+                                       "%s %s\n", algbuf, namebuf, typebuf);
+                               bad_algorithms[i] = 1;
+                       }
+       }
+       dns_rdataset_disassociate(&sigrdataset);
+}
+
+static void
+verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
+          dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
+           char *bad_algorithms)
+{
+       dns_rdataset_t rdataset;
+       dns_rdatasetiter_t *rdsiter = NULL;
+       isc_result_t result;
+
+       result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+       check_result(result, "dns_db_allrdatasets()");
+       result = dns_rdatasetiter_first(rdsiter);
+       dns_rdataset_init(&rdataset);
+       while (result == ISC_R_SUCCESS) {
+               dns_rdatasetiter_current(rdsiter, &rdataset);
+               if (rdataset.type != dns_rdatatype_rrsig &&
+                   rdataset.type != dns_rdatatype_dnskey &&
+                   (!delegation || rdataset.type == dns_rdatatype_ds ||
+                    rdataset.type == dns_rdatatype_nsec)) {
+                       verifyset(&rdataset, name, node, keyrdataset,
+                                 ksk_algorithms, bad_algorithms);
+               }
+               dns_rdataset_disassociate(&rdataset);
+               result = dns_rdatasetiter_next(rdsiter);
+       }
+       if (result != ISC_R_NOMORE)
+               fatal("rdataset iteration failed: %s",
+                     isc_result_totext(result));
+       dns_rdatasetiter_destroy(&rdsiter);
+}
+
+/*%
+ * Verify that certain things are sane:
+ *
+ *   The apex has a DNSKEY record with at least one KSK and at least
+ *   one ZSK.
+ *
+ *   The DNSKEY record was signed with at least one of the KSKs in this
+ *   set.
+ *
+ *   The rest of the zone was signed with at least one of the ZSKs
+ *   present in the DNSKEY RRSET.
+ */
+static void
+verifyzone(void) {
+       char algbuf[80];
+       dns_dbiterator_t *dbiter = NULL;
+       dns_dbnode_t *node = NULL, *nextnode = NULL;
+       dns_fixedname_t fname, fnextname, fzonecut;
+       dns_name_t *name, *nextname, *zonecut;
+       dns_rdata_dnskey_t dnskey;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       dns_rdataset_t rdataset;
+       dns_rdataset_t sigrdataset;
+       int i;
+       isc_boolean_t done = ISC_FALSE;
+       isc_boolean_t first = ISC_TRUE;
+       isc_boolean_t goodksk = ISC_FALSE;
+       isc_boolean_t goodzsk = ISC_FALSE;
+       isc_result_t result;
+       unsigned char revoked[256];
+       unsigned char standby[256];
+       unsigned char ksk_algorithms[256];
+       unsigned char zsk_algorithms[256];
+       unsigned char bad_algorithms[256];
+#ifdef ALLOW_KSKLESS_ZONES
+       isc_boolean_t allzsksigned = ISC_TRUE;
+       unsigned char self_algorithms[256];
+#endif
+
+       if (disable_zone_check)
+               return;
+
+       result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
+       if (result != ISC_R_SUCCESS)
+               fatal("failed to find the zone's origin: %s",
+                     isc_result_totext(result));
+
+       dns_rdataset_init(&rdataset);
+       dns_rdataset_init(&sigrdataset);
+       result = dns_db_findrdataset(gdb, node, gversion,
+                                    dns_rdatatype_dnskey,
+                                    0, 0, &rdataset, &sigrdataset);
+       dns_db_detachnode(gdb, &node);
+       if (result != ISC_R_SUCCESS)
+               fatal("cannot find DNSKEY rrset\n");
+
+       if (!dns_rdataset_isassociated(&sigrdataset))
+               fatal("cannot find DNSKEY RRSIGs\n");
+
+       memset(revoked, 0, sizeof(revoked));
+       memset(standby, 0, sizeof(revoked));
+       memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
+       memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
+       memset(bad_algorithms, 0, sizeof(bad_algorithms));
+#ifdef ALLOW_KSKLESS_ZONES
+       memset(self_algorithms, 0, sizeof(self_algorithms));
+#endif
+
+       /*
+        * Check that the DNSKEY RR has at least one self signing KSK and
+        * one ZSK per algorithm in it.
+        */
+       for (result = dns_rdataset_first(&rdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&rdataset)) {
+               dns_rdataset_current(&rdataset, &rdata);
+               result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
+               check_result(result, "dns_rdata_tostruct");
+
+               if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
+                       ;
+               else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
+                       if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
+                           !dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
+                                                  &sigrdataset, ISC_FALSE,
+                                                 mctx)) {
+                               char namebuf[DNS_NAME_FORMATSIZE];
+                               char buffer[1024];
+                               isc_buffer_t buf;
+
+                               dns_name_format(gorigin, namebuf,
+                                               sizeof(namebuf));
+                               isc_buffer_init(&buf, buffer, sizeof(buffer));
+                               result = dns_rdata_totext(&rdata, NULL, &buf);
+                               check_result(result, "dns_rdata_totext");
+                               fatal("revoked KSK is not self signed:\n"
+                                     "%s DNSKEY %.*s", namebuf,
+                                     (int)isc_buffer_usedlength(&buf), buffer);
+                       } 
+                       if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
+                            revoked[dnskey.algorithm] != 255)
+                               revoked[dnskey.algorithm]++;
+               } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
+                       if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
+                                             &sigrdataset, ISC_FALSE, mctx)) {
+                               if (ksk_algorithms[dnskey.algorithm] != 255)
+                                       ksk_algorithms[dnskey.algorithm]++;
+                               goodksk = ISC_TRUE;
+                       } else {
+                               if (standby[dnskey.algorithm] != 255)
+                                       standby[dnskey.algorithm]++;
+                       }
+               } else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
+                                               &sigrdataset, ISC_FALSE,
+                                               mctx)) {
+#ifdef ALLOW_KSKLESS_ZONES
+                       if (self_algorithms[dnskey.algorithm] != 255)
+                               self_algorithms[dnskey.algorithm]++;
+#endif
+                       if (zsk_algorithms[dnskey.algorithm] != 255)
+                               zsk_algorithms[dnskey.algorithm]++;
+                       goodzsk = ISC_TRUE;
+               } else {
+                       if (zsk_algorithms[dnskey.algorithm] != 255)
+                               zsk_algorithms[dnskey.algorithm]++;
+#ifdef ALLOW_KSKLESS_ZONES
+                       allzsksigned = ISC_FALSE;
+#endif
+               }
+               dns_rdata_freestruct(&dnskey);
+               dns_rdata_reset(&rdata);
+       }
+       dns_rdataset_disassociate(&sigrdataset);
+       
+       if (!goodksk) {
+#ifdef ALLOW_KSKLESS_ZONES
+               if (!goodzsk)
+                       fatal("no self signing keys found");
+               fprintf(stderr, "No self signing KSK found. Using self signed "
+                       "ZSK's for active algorithm list.\n");
+               memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
+               if (!allzsksigned)
+                       fprintf(stderr, "warning: not all ZSK's are self "
+                               "signed.\n");
+#else
+               fatal("no self signed KSK's found");
+#endif
+       }
+
+       fprintf(stderr, "Verifying the zone using the following algorithms:");
+       for (i = 0; i < 256; i++) {
+               if (ksk_algorithms[i]) {
+                       alg_format(i, algbuf, sizeof(algbuf));
+                       fprintf(stderr, " %s", algbuf);
+               }
+       }
+       fprintf(stderr, ".\n");
+       
+       if (memcmp(ksk_algorithms, zsk_algorithms, sizeof(ksk_algorithms))) {
+               for (i = 0; i < 256; i++) {
+                       if (ksk_algorithms[i] == zsk_algorithms[i])
+                               continue;
+                       alg_format(i, algbuf, sizeof(algbuf));
+                       fprintf(stderr, "Missing %s for algorithm %s\n",
+                               ksk_algorithms[i] ? "ZSK" : "self signing KSK",
+                               algbuf);
+                       bad_algorithms[i] = 1;
+               }
+       }
+
+       /*
+        * Check that all the other records were signed by keys that are
+        * present in the DNSKEY RRSET.
+        */
+
+       dns_fixedname_init(&fname);
+       name = dns_fixedname_name(&fname);
+       dns_fixedname_init(&fnextname);
+       nextname = dns_fixedname_name(&fnextname);
+       dns_fixedname_init(&fzonecut);
+       zonecut = NULL;
+
+       result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+       check_result(result, "dns_db_createiterator()");
+
+       result = dns_dbiterator_first(dbiter);
+       check_result(result, "dns_dbiterator_first()");
+
+       while (!done) {
+               isc_boolean_t isdelegation = ISC_FALSE;
+
+               dns_dbiterator_current(dbiter, &node, name);
+               if (delegation(name, node, NULL)) {
+                       zonecut = dns_fixedname_name(&fzonecut);
+                       dns_name_copy(name, zonecut, NULL);
+                       isdelegation = ISC_TRUE;
+               }
+               verifynode(name, node, isdelegation, &rdataset,
+                          ksk_algorithms, bad_algorithms);
+               result = dns_dbiterator_next(dbiter);
+               nextnode = NULL;
+               while (result == ISC_R_SUCCESS) {
+                       result = dns_dbiterator_current(dbiter, &nextnode,
+                                                       nextname);
+                       if (result != ISC_R_SUCCESS)
+                               break;
+                       if (!dns_name_issubdomain(nextname, gorigin) ||
+                           (zonecut != NULL &&
+                            dns_name_issubdomain(nextname, zonecut)))
+                       {
+                               dns_db_detachnode(gdb, &nextnode);
+                               result = dns_dbiterator_next(dbiter);
+                               continue;
+                       }
+                       dns_db_detachnode(gdb, &nextnode);
+                       break;
+               }
+               if (result == ISC_R_NOMORE) {
+                       done = ISC_TRUE;
+               } else if (result != ISC_R_SUCCESS)
+                       fatal("iterating through the database failed: %s",
+                             isc_result_totext(result));
+               dns_db_detachnode(gdb, &node);
+       }
+
+       dns_dbiterator_destroy(&dbiter);
+
+       result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
+       check_result(result, "dns_db_createiterator()");
+
+       for (result = dns_dbiterator_first(dbiter);
+            result == ISC_R_SUCCESS;
+            result = dns_dbiterator_next(dbiter) ) {
+               dns_dbiterator_current(dbiter, &node, name);
+               verifynode(name, node, ISC_FALSE, &rdataset,
+                          ksk_algorithms, bad_algorithms);
+               dns_db_detachnode(gdb, &node);
+       }
+       dns_dbiterator_destroy(&dbiter);
+
+       dns_rdataset_disassociate(&rdataset);
+
+       /*
+        * If we made it this far, we have what we consider a properly signed
+        * zone.  Set the good flag.
+        */
+       for (i = 0; i < 256; i++) {
+               if (bad_algorithms[i]) {
+                       if (first)
+                               fprintf(stderr, "The zone is not fully signed "
+                                       "for the following algorithms:");
+                       alg_format(i, algbuf, sizeof(algbuf));
+                       fprintf(stderr, " %s", algbuf);
+                       first = ISC_FALSE;
+               }
+       }
+       if (!first) {
+               fprintf(stderr, ".\n");
+               fatal("DNSSEC completeness test failed.");
+       }
+
+       if (goodksk) {
+               /*
+                * Print the success summary.
+                */
+               fprintf(stderr, "Zone signing complete:\n");
+               for (i = 0; i < 256; i++) {
+                       if (zsk_algorithms[i] || ksk_algorithms[i] ||
+                           revoked[i] || standby[i]) {
+                               alg_format(i, algbuf, sizeof(algbuf));
+                               fprintf(stderr, "Algorithm: %s: ZSKs: %u, "
+                                       "KSKs: %u active, %u revoked, %u "
+                                       "stand-by\n", algbuf,
+                                       zsk_algorithms[i], ksk_algorithms[i],
+                                       revoked[i], standby[i]);
+                       }
+               }
+       }
+}
+
 /*%
  * Sign the apex of the zone.
  * Note the origin may not be the first node if there are out of zone
@@ -1764,7 +2223,8 @@ nsec3clean(dns_name_t *name, dns_dbnode_t *node,
             result = dns_rdataset_next(&rdataset)) {
                dns_rdata_init(&rdata);
                dns_rdataset_current(&rdataset, &rdata);
-               dns_rdata_tostruct(&rdata, &nsec3, NULL);
+               result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+               check_result(result, "dns_rdata_tostruct");
                if (nsec3.hash == hashalg &&
                    nsec3.iterations == iterations &&
                    nsec3.salt_length == salt_length &&
@@ -2134,7 +2594,7 @@ warnifallksk(dns_db_t *db) {
        dns_rdataset_t rdataset;
        dns_rdata_t rdata = DNS_RDATA_INIT;
        isc_result_t result;
-       dns_rdata_key_t key;
+       dns_rdata_dnskey_t dnskey;
        isc_boolean_t have_non_ksk = ISC_FALSE;
 
        dns_db_currentversion(db, &currentversion);
@@ -2155,21 +2615,27 @@ warnifallksk(dns_db_t *db) {
        while (result == ISC_R_SUCCESS) {
                dns_rdata_reset(&rdata);
                dns_rdataset_current(&rdataset, &rdata);
-               result = dns_rdata_tostruct(&rdata, &key, NULL);
+               result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
                check_result(result, "dns_rdata_tostruct");
-               if ((key.flags & DNS_KEYFLAG_KSK) == 0) {
+               if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
                        have_non_ksk = ISC_TRUE;
                        result = ISC_R_NOMORE;
                } else
                        result = dns_rdataset_next(&rdataset);
+               dns_rdata_freestruct(&dnskey);
        }
        dns_rdataset_disassociate(&rdataset);
        dns_db_detachnode(db, &node);
        dns_db_closeversion(db, &currentversion, ISC_FALSE);
-       if (!have_non_ksk && !ignoreksk)
-               fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
-                       "Supply non-KSK dnskey or use '-z'.\n",
-                       program);
+       if (!have_non_ksk && !ignoreksk) {
+               if (disable_zone_check)
+                       fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
+                               "Supply non-KSK dnskey or use '-z'.\n",
+                               program);
+               else
+                       fatal("No non-KSK dnskey found. "
+                             "Supply non-KSK dnskey or use '-z'.");
+       }
 }
 
 static void
@@ -2370,6 +2836,8 @@ usage(void) {
        fprintf(stderr, "verify generated signatures\n");
        fprintf(stderr, "\t-p:\t");
        fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
+       fprintf(stderr, "\t-P:\t");
+       fprintf(stderr, "disable post-sign verification\n");
        fprintf(stderr, "\t-t:\t");
        fprintf(stderr, "print statistics\n");
        fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
@@ -2571,8 +3039,13 @@ main(int argc, char *argv[]) {
                                fatal("jitter must be numeric and positive");
                        break;
 
+               case 'k':
+                       if (ndskeys == MAXDSKEYS)
+                               fatal("too many key-signing keys specified");
+                       dskeyfile[ndskeys++] = isc_commandline_argument;
+                       break;
+
                case 'l':
-                       dns_fixedname_init(&dlv_fixed);
                        len = strlen(isc_commandline_argument);
                        isc_buffer_init(&b, isc_commandline_argument, len);
                        isc_buffer_add(&b, len);
@@ -2584,12 +3057,6 @@ main(int argc, char *argv[]) {
                        check_result(result, "dns_name_fromtext(dlv)");
                        break;
 
-               case 'k':
-                       if (ndskeys == MAXDSKEYS)
-                               fatal("too many key-signing keys specified");
-                       dskeyfile[ndskeys++] = isc_commandline_argument;
-                       break;
-
                case 'm':
                        break;
 
@@ -2604,15 +3071,6 @@ main(int argc, char *argv[]) {
                        serialformatstr = isc_commandline_argument;
                        break;
 
-               case 'H':
-                       iterations = strtoul(isc_commandline_argument,
-                                            &endp, 0);
-                       if (*endp != '\0')
-                               fatal("iterations must be numeric");
-                       if (iterations > 0xffffU)
-                               fatal("iterations too big");
-                       break;
-
                case 'o':
                        origin = isc_commandline_argument;
                        break;
@@ -2625,6 +3083,10 @@ main(int argc, char *argv[]) {
                        pseudorandom = ISC_TRUE;
                        break;
 
+               case 'P':
+                       disable_zone_check = ISC_TRUE;
+                       break;
+
                case 'r':
                        setup_entropy(mctx, isc_commandline_argument, &ectx);
                        break;
@@ -2657,6 +3119,18 @@ main(int argc, char *argv[]) {
                case 'z':
                        ignoreksk = ISC_TRUE;
                        break;
+
+               case '?':
+                       if (isc_commandline_option != '?')
+                               fprintf(stderr, "%s: invalid argument -%c\n",
+                                       program, isc_commandline_option);
+                       usage();
+                       break;
+
+               default:
+                       fprintf(stderr, "%s: unhandled option -%c\n",
+                               program, isc_commandline_option);
+                       exit(1);
                }
        }
 
@@ -2773,7 +3247,12 @@ main(int argc, char *argv[]) {
                              "NSEC only DNSKEY");
        }
 
+       /*
+        * We need to do this early on, as we start messing with the list
+        * of keys rather early.
+        */
        ISC_LIST_INIT(keylist);
+       isc_rwlock_init(&keylist_lock, 0, 0);
 
        if (argc == 0) {
                loadzonekeys(gdb);
@@ -2810,6 +3289,7 @@ main(int argc, char *argv[]) {
                        }
                        if (key == NULL) {
                                key = newkeystruct(newkey, ISC_TRUE);
+                               key->commandline = ISC_TRUE;
                                ISC_LIST_APPEND(keylist, key, link);
                        } else
                                dst_key_free(&newkey);
@@ -2860,8 +3340,11 @@ main(int argc, char *argv[]) {
        }
 
        if (ISC_LIST_EMPTY(keylist)) {
-               fprintf(stderr, "%s: warning: No keys specified or found\n",
-                       program);
+               if (disable_zone_check)
+                       fprintf(stderr, "%s: warning: No keys specified or found\n",
+                               program);
+               else
+                       fatal("No signing keys specified or found.");
                nokeys = ISC_TRUE;
        }
 
@@ -2976,6 +3459,7 @@ main(int argc, char *argv[]) {
        isc_taskmgr_destroy(&taskmgr);
        isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
        postsign();
+       verifyzone();
 
        if (outputformat != dns_masterformat_text) {
                result = dns_master_dumptostream2(mctx, gdb, gversion,
index 2f26ba4e15502dee92fdfd7938b72bac538a6059..120adda16ef1a10061e873ad45bd0f07cc278d39 100644 (file)
@@ -18,7 +18,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- $Id: dnssec-signzone.docbook,v 1.31 2008/10/14 14:28:25 jreed Exp $ -->
+<!-- $Id: dnssec-signzone.docbook,v 1.32 2009/06/04 02:13:37 marka Exp $ -->
 <refentry id="man.dnssec-signzone">
   <refentryinfo>
     <date>June 30, 2000</date>
@@ -72,6 +72,7 @@
       <arg><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
       <arg><option>-O <replaceable class="parameter">output-format</replaceable></option></arg>
       <arg><option>-p</option></arg>
+      <arg><option>-P</option></arg>
       <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
       <arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
       <arg><option>-t</option></arg>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>-P</term>
+        <listitem>
+          <para>
+           Disable post sign verification tests.
+          </para>
+          <para>
+           The post sign verification test ensures that for each algorithm
+           in use there is at least one non revoked self signed KSK key.
+           That all revoked KSK keys are self signed.  That all records
+           in the zone are signed by the algorithm.
+          </para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term>-r <replaceable class="parameter">randomdev</replaceable></term>
         <listitem>
index e933a06d6023fdb47a36bef56bc1fd3976700beb..8588fd545e055ac6f67b95f327bbdc135a015595 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dnssectool.c,v 1.45 2007/06/19 23:46:59 tbox Exp $ */
+/* $Id: dnssectool.c,v 1.46 2009/06/04 02:13:37 marka Exp $ */
 
 /*! \file */
 
@@ -65,7 +65,7 @@ void
 fatal(const char *format, ...) {
        va_list args;
 
-       fprintf(stderr, "%s: ", program);
+       fprintf(stderr, "%s: fatal: ", program);
        va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
diff --git a/bin/tests/dnssec-signzone/Kexample.com.+005+07065.key b/bin/tests/dnssec-signzone/Kexample.com.+005+07065.key
new file mode 100644 (file)
index 0000000..e4bdce2
--- /dev/null
@@ -0,0 +1 @@
+example.com. IN DNSKEY 256 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpZ
diff --git a/bin/tests/dnssec-signzone/Kexample.com.+005+07065.private b/bin/tests/dnssec-signzone/Kexample.com.+005+07065.private
new file mode 100644 (file)
index 0000000..db928c5
--- /dev/null
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: oXTPXsN2QEAqJhJxU2rOypfDtXP8LHk4LDtP/pGdT8qIa/zXmSUfahvLBFlfZlwSD1HxJTNCI/3KBjSzXEXkgViLfYexZ+01XtX+A3A2sycYLSBXZ7c5rCxDYJhZllXA5uv9+Zwohe5jp5F0m3I6KUxGGW+ugl1dnDUJB2JzGlk=
+PublicExponent: AQAB
+PrivateExponent: QrbJmRabHiFlSSYFvbo8iGn9bFTotlfAZkZ732y72+SMSlLHo3g7atThJoLncJxKuhnZ0s1DXyvW9omAM3iN2lxfVDW58at1amj/lWRDYkjI0fM8z6eyrF4U2lHKDM2YEstg+sGAAs5DUZBbli4Y7+zHjhxSKLYvRf4AJvX8aoE=
+Prime1: 0259CgdF0JW+miedRZXC6tn3FijZJ4/j5edzd8IpTpdUSZupQg9hMP1ot7crreNq7MnzO0Z2ImbowUx8CDOuXQ==
+Prime2: w31/WLM2275Z1tsHEOhrntUQCUk55B4PNOCmM4hjp0vAvA/SVSgAYRNb7rc/ujaLf0DnxnDsnVsFAS2PmvQELQ==
+Exponent1: yKPhJNMh/X8dEUzmglJMVnHheLXq3RA/RL0PZmZqrJoO8os1Y+sUYFkaNr0sRie6IFrE50tGb/8YgdcDHQVuQQ==
+Exponent2: lVhDuGy5RSjnk1eiz0zwIthctutlOZupPFk/P3E7yGv74vAnXH0BxSe3/Oer3MOc0GuyZYyRhyko6px28AbpRQ==
+Coefficient: Hjup1nDnPFkQrxU2qLQBJrDz+ipw0RkNhsjWs6IgAq1Mq4sFV50bR9hOTLDd9oNhhtAwVjF+Oc0WIq+M1Mi6Ow==
diff --git a/bin/tests/dnssec-signzone/Kexample.com.+005+23362.key b/bin/tests/dnssec-signzone/Kexample.com.+005+23362.key
new file mode 100644 (file)
index 0000000..6f4fec8
--- /dev/null
@@ -0,0 +1 @@
+example.com. IN DNSKEY 257 3 5 AwEAAbuWh5W3eGwixISqPwxszotQ0246KqhUB2Mb6JqNMJd6cWR66IrX YnevpIHsb6oanqJmVzOcJ6Yj3rXOIYtYYXgLbT7EJ8x7BNCZPHxG+w5C 7I1WsDbT6eGf//FLn2c4odKLOXaWCVITeNy61w43IlteIT9Q1egKdt+8 a7X9605j
diff --git a/bin/tests/dnssec-signzone/Kexample.com.+005+23362.private b/bin/tests/dnssec-signzone/Kexample.com.+005+23362.private
new file mode 100644 (file)
index 0000000..2d299d0
--- /dev/null
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: u5aHlbd4bCLEhKo/DGzOi1DTbjoqqFQHYxvomo0wl3pxZHroitdid6+kgexvqhqeomZXM5wnpiPetc4hi1hheAttPsQnzHsE0Jk8fEb7DkLsjVawNtPp4Z//8UufZzih0os5dpYJUhN43LrXDjciW14hP1DV6Ap237xrtf3rTmM=
+PublicExponent: AQAB
+PrivateExponent: XZSssv3CL3/wtZYQuewV5d4+e8C8wxiYTtL/aQqCcS7+HnhKRelJEBgpYz9GPX/mH3Iakn6WMQW39s6MYW2HwXUnqhsvHoyabGX0Dbc/1LcY4J2VPgzVHwSXYm+j4unOByOOS4KoBtUAQxJsTBokVZrZ5pKsLUK9X2gdywYw+PE=
+Prime1: 9fB7PaygjKoT1nbbeEMy1KYNqetg3zmN49Mk6ilEWxzJXKSSjTIhdkiLGXtYmE8rDBLBiYm8YWNe7YdA9PbQ7Q==
+Prime2: w0L7mTOLDecH3XAkC/wvALv8K9KSoZ31ajidKBxV15u8awj5AxDG7gjerYgCLjU1fq1GulMr11j8r4ftQn3Cjw==
+Exponent1: Up52yEE1rgt0npdPIxdv+//Ml0h7QoITKHXF8OPsEq+Y9YZTtRsiIpo8IFNPb9somuWyHoImxpCbUzAcoi5IAQ==
+Exponent2: uYTbvYx+UsAt9dOFPCnnkqAJEK3qCUomET0m/CQn30mldGC7DpGTIDgnMeLmh3agk/IYIBHDtsBinHfeEe2guw==
+Coefficient: FiHAet8On9Yaz1ksEAlCWulwck3zPWIsgqJBM2J4kHhgHTm17mZyxtVxIzLAMBNMIBcFl40FCpmPmTLY5QK5mw==
diff --git a/bin/tests/dnssec-signzone/bogus-ksk.key b/bin/tests/dnssec-signzone/bogus-ksk.key
new file mode 100644 (file)
index 0000000..af4640b
--- /dev/null
@@ -0,0 +1,6 @@
+;
+; This is a bogus key.  It will not have a .private file.
+;
+; This will be key id 7091
+;
+example.com. IN DNSKEY 257 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpz
diff --git a/bin/tests/dnssec-signzone/bogus-zsk.key b/bin/tests/dnssec-signzone/bogus-zsk.key
new file mode 100644 (file)
index 0000000..2e53d5c
--- /dev/null
@@ -0,0 +1,6 @@
+;
+; This is a bogus key.  It will not have a .private file.
+;
+; This will be key id 7092
+;
+example.com. IN DNSKEY 256 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpz
diff --git a/bin/tests/dnssec-signzone/run-test.sh b/bin/tests/dnssec-signzone/run-test.sh
new file mode 100644 (file)
index 0000000..066811c
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+
+sign="../../dnssec/dnssec-signzone -f signed.zone -o example.com."
+
+signit() {
+       rm -f signed.zone
+       grep '^;' $zone
+       $sign $zone
+}
+
+expect_success() {
+       if ! test -f signed.zone ; then
+               echo "Error: expected success, but sign failed for $zone."
+       else
+               echo "Success:  Sign succeeded for $zone."
+       fi
+}
+
+expect_failure() {
+       if test -f signed.zone ; then
+               echo "Error: expected failure, but sign succeeded for $zone."
+       else
+               echo "Success:  Sign failed (expected) for $zone"
+       fi
+}
+
+zone="test1.zone" ; signit ; expect_success
+zone="test2.zone" ; signit ; expect_failure
+zone="test3.zone" ; signit ; expect_failure
+zone="test4.zone" ; signit ; expect_success
+zone="test5.zone" ; signit ; expect_failure
+zone="test6.zone" ; signit ; expect_failure
+zone="test7.zone" ; signit ; expect_failure
+zone="test8.zone" ; signit ; expect_failure
diff --git a/bin/tests/dnssec-signzone/test1.zone b/bin/tests/dnssec-signzone/test1.zone
new file mode 100644 (file)
index 0000000..a53fba7
--- /dev/null
@@ -0,0 +1,9 @@
+;
+;      This is a zone which has two DNSKEY records, both of which have
+; existing private key files available.  They should be loaded automatically
+; and the zone correctly signed.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+07065.key
+$include Kexample.com.+005+23362.key
diff --git a/bin/tests/dnssec-signzone/test2.zone b/bin/tests/dnssec-signzone/test2.zone
new file mode 100644 (file)
index 0000000..731c291
--- /dev/null
@@ -0,0 +1,8 @@
+;
+;      This is a zone which has one non-KSK DNSKEY record for which the
+; private key file exists.  It should be loaded automatically and the zone
+; correctly signed.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+07065.key
diff --git a/bin/tests/dnssec-signzone/test3.zone b/bin/tests/dnssec-signzone/test3.zone
new file mode 100644 (file)
index 0000000..ec05bee
--- /dev/null
@@ -0,0 +1,8 @@
+;
+;       This is a zone which has one KSK DNSKEY record for which the
+; private key file exists.  It should be loaded automatically.  As there
+; is no non-KSK DNSKEY the resulting zone should be rejected.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+23362.key
diff --git a/bin/tests/dnssec-signzone/test4.zone b/bin/tests/dnssec-signzone/test4.zone
new file mode 100644 (file)
index 0000000..a146736
--- /dev/null
@@ -0,0 +1,10 @@
+;
+;      This is a zone which has three DNSKEY records, two (KSK + ZSK) of
+; which have existing private key files available.  The third is a 
+; pre-published ZSK.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+07065.key
+$include Kexample.com.+005+23362.key
+$include bogus-zsk.key
diff --git a/bin/tests/dnssec-signzone/test5.zone b/bin/tests/dnssec-signzone/test5.zone
new file mode 100644 (file)
index 0000000..546ebad
--- /dev/null
@@ -0,0 +1,9 @@
+;
+;      This is a zone which has three DNSKEY records, two (KSK +ZSK) of which
+; have existing private key files available.  The third is a KSK.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+07065.key
+$include Kexample.com.+005+23362.key
+$include bogus-ksk.key
diff --git a/bin/tests/dnssec-signzone/test6.zone b/bin/tests/dnssec-signzone/test6.zone
new file mode 100644 (file)
index 0000000..91091f7
--- /dev/null
@@ -0,0 +1,11 @@
+;
+;      This is a zone which has four DNSKEY records, two (KK + ZSK) of which
+; have existing private key files available.  There are also a KSK and ZSK
+; for which there will be no signatures.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+07065.key
+$include Kexample.com.+005+23362.key
+$include bogus-ksk.key
+$include bogus-zsk.key
diff --git a/bin/tests/dnssec-signzone/test7.zone b/bin/tests/dnssec-signzone/test7.zone
new file mode 100644 (file)
index 0000000..e18e7c6
--- /dev/null
@@ -0,0 +1,9 @@
+;
+;      This is a zone which has two DNSKEY records, none of which have 
+; existing private key files available.  The resulting zone should fail
+; the consistancy tests.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include bogus-ksk.key
+$include bogus-zsk.key
diff --git a/bin/tests/dnssec-signzone/test8.zone b/bin/tests/dnssec-signzone/test8.zone
new file mode 100644 (file)
index 0000000..cc51f0a
--- /dev/null
@@ -0,0 +1,9 @@
+;
+;      This is a zone which has two DNSKEY records, one of which,
+; the KSK, has a private key.  The resulting zone should be rejected as
+; it has no ZSK signatures.
+;
+$TTL 3600
+example.com.   IN      SOA ns hostmaster 00090000 1200 3600 604800 300
+$include Kexample.com.+005+23362.key
+$include bogus-zsk.key
index 9bc0dddaf1c391b9231379738c93f1032c4b3b2e..0960136acae25a85cd97259ed63cf6fc93c07d11 100644 (file)
@@ -15,7 +15,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: sign.sh,v 1.25 2008/09/25 04:02:38 tbox Exp $
+# $Id: sign.sh,v 1.26 2009/06/04 02:13:37 marka Exp $
 
 SYSTEMTESTTOP=../..
 . $SYSTEMTESTTOP/conf.sh
@@ -35,8 +35,7 @@ keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
 
 cat $infile $keyname.key > $zonefile
 
-echo $SIGNER -g -r $RANDFILE -o $zone $zonefile
-$SIGNER -g -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
 
 # Configure the resolving server with a trusted key.
 
index 4389678cd45b1331ccd61ba9bf7c1ad20a99fabe..b87c289a364f7ee6c222119d6336a3082fc4ba9b 100644 (file)
@@ -15,7 +15,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: sign.sh,v 1.30 2008/09/25 04:02:38 tbox Exp $
+# $Id: sign.sh,v 1.31 2009/06/04 02:13:37 marka Exp $
 
 SYSTEMTESTTOP=../..
 . $SYSTEMTESTTOP/conf.sh
@@ -40,7 +40,7 @@ keyname2=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
 
 cat $infile $keyname1.key $keyname2.key >$zonefile
 
-$SIGNER -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+$SIGNER -P -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
 
 # Sign the privately secure file
 
@@ -52,7 +52,7 @@ privkeyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $privzone`
 
 cat $privinfile $privkeyname.key >$privzonefile
 
-$SIGNER -g -r $RANDFILE -o $privzone -l dlv $privzonefile > /dev/null
+$SIGNER -P -g -r $RANDFILE -o $privzone -l dlv $privzonefile > /dev/null
 
 # Sign the DLV secure zone.
 
@@ -65,4 +65,4 @@ dlvkeyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $dlvzone`
 
 cat $dlvinfile $dlvkeyname.key dlvset-$privzone > $dlvzonefile
 
-$SIGNER -g -r $RANDFILE -o $dlvzone $dlvzonefile > /dev/null
+$SIGNER -P -g -r $RANDFILE -o $dlvzone $dlvzonefile > /dev/null
index eb362aa9a561c7890a36530996c79d90fd886e83..8b224a9691d04c5703be3e440d28cb02ed580bf7 100644 (file)
@@ -15,7 +15,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: sign.sh,v 1.25 2008/09/25 04:02:38 tbox Exp $
+# $Id: sign.sh,v 1.26 2009/06/04 02:13:37 marka Exp $
 
 SYSTEMTESTTOP=../..
 . $SYSTEMTESTTOP/conf.sh
@@ -30,7 +30,7 @@ keyname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 
 zone=bogus.example.
 infile=bogus.example.db.in
@@ -40,7 +40,7 @@ keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 
 zone=dynamic.example.
 infile=dynamic.example.db.in
@@ -51,7 +51,7 @@ keyname2=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 1024 -n zone -f KSK $zone`
 
 cat $infile $keyname1.key $keyname2.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 
 zone=keyless.example.
 infile=keyless.example.db.in
@@ -61,7 +61,7 @@ keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 
 # Change the signer field of the a.b.keyless.example SIG A
 # to point to a provably nonexistent KEY record.
@@ -81,7 +81,7 @@ keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 #  NSEC3/NSEC3 test zone
@@ -94,7 +94,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 #  OPTOUT/NSEC3 test zone
@@ -107,7 +107,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 # A nsec3 zone (non-optout).
@@ -120,7 +120,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -g -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -g -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 #  OPTOUT/NSEC test zone
@@ -133,7 +133,7 @@ keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 #  OPTOUT/NSEC3 test zone
@@ -146,7 +146,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 #  OPTOUT/OPTOUT test zone
@@ -159,7 +159,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 # A optout nsec3 zone.
@@ -172,7 +172,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -g -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -g -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 # A nsec3 zone (non-optout) with unknown hash algorithm.
@@ -185,7 +185,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -3 - -U -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -U -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 # A optout nsec3 zone.
@@ -198,7 +198,7 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -3 - -U -A -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -U -A -r $RANDFILE -o $zone $zonefile > /dev/null
 
 #
 # A multiple parameter nsec3 zone.
@@ -211,14 +211,14 @@ keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
 
 cat $infile $keyname.key >$zonefile
 
-$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null
 mv $zonefile.signed $zonefile
-$SIGNER -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
 mv $zonefile.signed $zonefile
-$SIGNER -3 AAAA -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 AAAA -r $RANDFILE -o $zone $zonefile > /dev/null
 mv $zonefile.signed $zonefile
-$SIGNER -3 BBBB -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 BBBB -r $RANDFILE -o $zone $zonefile > /dev/null
 mv $zonefile.signed $zonefile
-$SIGNER -3 CCCC -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 CCCC -r $RANDFILE -o $zone $zonefile > /dev/null
 mv $zonefile.signed $zonefile
-$SIGNER -3 DDDD -r $RANDFILE -o $zone $zonefile > /dev/null
+$SIGNER -P -3 DDDD -r $RANDFILE -o $zone $zonefile > /dev/null
index f06d715c4d32f15879e02446ca1187549b9dfb05..a9b42c4d618f5b1e12dc47fb4d1a7b54aab68fdf 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 /*
- * $Id: dnssec.c,v 1.93 2008/11/14 23:47:33 tbox Exp $
+ * $Id: dnssec.c,v 1.94 2009/06/04 02:13:37 marka Exp $
  */
 
 /*! \file */
@@ -93,6 +93,7 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
        isc_result_t ret;
        int i = 0, n;
        dns_rdata_t *data;
+       dns_rdataset_t rdataset;
 
        n = dns_rdataset_count(set);
 
@@ -100,8 +101,11 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
        if (data == NULL)
                return (ISC_R_NOMEMORY);
 
-       ret = dns_rdataset_first(set);
+       dns_rdataset_init(&rdataset);
+       dns_rdataset_clone(set, &rdataset);
+       ret = dns_rdataset_first(&rdataset);
        if (ret != ISC_R_SUCCESS) {
+               dns_rdataset_disassociate(&rdataset);
                isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
                return (ret);
        }
@@ -111,8 +115,8 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
         */
        do {
                dns_rdata_init(&data[i]);
-               dns_rdataset_current(set, &data[i++]);
-       } while (dns_rdataset_next(set) == ISC_R_SUCCESS);
+               dns_rdataset_current(&rdataset, &data[i++]);
+       } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS);
 
        /*
         * Sort the array.
@@ -120,6 +124,7 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
        qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
        *rdata = data;
        *nrdata = n;
+       dns_rdataset_disassociate(&rdataset);
        return (ISC_R_SUCCESS);
 }
 
@@ -890,3 +895,59 @@ failure:
 
        return (result);
 }
+
+/*%
+ * Does this key ('rdata') self sign the rrset ('rdataset')?
+ */
+isc_boolean_t
+dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
+                    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+                    isc_boolean_t ignoretime, isc_mem_t *mctx)
+{
+       dst_key_t *dstkey = NULL;
+        dns_keytag_t keytag;
+        dns_rdata_dnskey_t key;
+        dns_rdata_rrsig_t sig;
+        dns_rdata_t sigrdata = DNS_RDATA_INIT;
+        isc_result_t result;
+
+        INSIST(rdataset->type == dns_rdatatype_key ||
+               rdataset->type == dns_rdatatype_dnskey);
+       if (rdataset->type == dns_rdatatype_key) {
+               INSIST(sigrdataset->type == dns_rdatatype_sig);
+               INSIST(sigrdataset->covers == dns_rdatatype_key);
+       } else {
+               INSIST(sigrdataset->type == dns_rdatatype_rrsig);
+               INSIST(sigrdataset->covers == dns_rdatatype_dnskey);
+       }
+
+       result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey);
+       if (result != ISC_R_SUCCESS)
+               return (ISC_FALSE);
+       result = dns_rdata_tostruct(rdata, &key, NULL);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+       keytag = dst_key_id(dstkey);
+       for (result = dns_rdataset_first(sigrdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(sigrdataset))
+       {
+               dns_rdata_reset(&sigrdata);
+               dns_rdataset_current(sigrdataset, &sigrdata);
+               result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+               if (sig.algorithm == key.algorithm &&
+                   sig.keyid == keytag) {
+                       result = dns_dnssec_verify2(name, rdataset, dstkey,
+                                                   ignoretime, mctx,
+                                                   &sigrdata, NULL);
+                       if (result == ISC_R_SUCCESS) {
+                               dst_key_free(&dstkey);
+                               return (ISC_TRUE);
+                       }
+               }
+        }
+       dst_key_free(&dstkey);
+        return (ISC_FALSE);
+}
index f8a59d05f87fe981dc5d5c3ebec80ba9de126f97..ace1240e10f74a5fe373820353d5d2cf33230216 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dnssec.h,v 1.32 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: dnssec.h,v 1.33 2009/06/04 02:13:37 marka Exp $ */
 
 #ifndef DNS_DNSSEC_H
 #define DNS_DNSSEC_H 1
@@ -178,6 +178,12 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
  *\li          DST_R_*
  */
 
+isc_boolean_t
+dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
+                     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+                     isc_boolean_t ignoretime, isc_mem_t *mctx);
+
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_DNSSEC_H */
index 7040389403668f9a967eedca490ac73b3427aecc..a9eaad7073d2a230a3558a8c061d481173c52cbf 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: keyvalues.h,v 1.23 2008/09/25 04:02:39 tbox Exp $ */
+/* $Id: keyvalues.h,v 1.24 2009/06/04 02:13:37 marka Exp $ */
 
 #ifndef DNS_KEYVALUES_H
 #define DNS_KEYVALUES_H 1
@@ -42,7 +42,7 @@
 #define DNS_KEYOWNER_ENTITY    0x0200  /*%< key is assoc. with entity eg host */
 #define DNS_KEYOWNER_ZONE      0x0100  /*%< key is zone key */
 #define DNS_KEYOWNER_RESERVED  0x0300  /*%< reserved meaning */
-#define DNS_KEYFLAG_RESERVED8  0x0080  /*%< reserved - must be zero */
+#define DNS_KEYFLAG_REVOKE     0x0080  /*%< key revoked (per rfc5001) */
 #define DNS_KEYFLAG_RESERVED9  0x0040  /*%< reserved - must be zero */
 #define DNS_KEYFLAG_RESERVED10 0x0020  /*%< reserved - must be zero */
 #define DNS_KEYFLAG_RESERVED11 0x0010  /*%< reserved - must be zero */