]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Handle RRSIG signer case consistently
authorEvan Hunt <each@isc.org>
Thu, 17 May 2012 18:39:23 +0000 (11:39 -0700)
committerEvan Hunt <each@isc.org>
Thu, 17 May 2012 18:39:23 +0000 (11:39 -0700)
3329. [bug] Handle RRSIG signer-name case consistently: We
generate RRSIG records with the signer-name in
lower case.  We accept them with any case, but if
they fail to validate, we try again in lower case.
[RT #27451]

15 files changed:
CHANGES
bin/named/statschannel.c
bin/tests/system/dnssec/clean.sh
bin/tests/system/dnssec/ns2/example.db.in
bin/tests/system/dnssec/ns2/sign.sh
bin/tests/system/dnssec/ns3/lower.example.db.in [new file with mode: 0644]
bin/tests/system/dnssec/ns3/named.conf
bin/tests/system/dnssec/ns3/sign.sh
bin/tests/system/dnssec/ns3/upper.example.db.in [new file with mode: 0644]
bin/tests/system/dnssec/tests.sh
lib/dns/dnssec.c
lib/dns/include/dns/dnssec.h
lib/dns/include/dns/log.h
lib/dns/include/dns/stats.h
lib/dns/log.c

diff --git a/CHANGES b/CHANGES
index 821e905d53c6d15ac1d9eb2a85042212da71b849..b0c50339897ea0c04fba6d3927b48a46d3f42666 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+3329.  [bug]           Handle RRSIG signer-name case consistently: We
+                       generate RRSIG records with the signer-name in
+                       lower case.  We accept them with any case, but if
+                       they fail to validate, we try again in lower case.
+                       [RT #27451]
+
        --- 9.6-ESV-R7 released ---
 
 3318.  [tuning]        Reduce the amount of work performed while holding a
index 633ccc9644d9b34a2d45d2e073d2c95777c4aabb..8d8f108fd383b76ce2d1e234734a75b9f4b813dd 100644 (file)
@@ -84,16 +84,19 @@ static const char *nsstats_desc[dns_nsstatscounter_max];
 static const char *resstats_desc[dns_resstatscounter_max];
 static const char *zonestats_desc[dns_zonestatscounter_max];
 static const char *sockstats_desc[isc_sockstatscounter_max];
+static const char *dnssecstats_desc[dns_dnssecstats_max];
 #ifdef HAVE_LIBXML2
 static const char *nsstats_xmldesc[dns_nsstatscounter_max];
 static const char *resstats_xmldesc[dns_resstatscounter_max];
 static const char *zonestats_xmldesc[dns_zonestatscounter_max];
 static const char *sockstats_xmldesc[isc_sockstatscounter_max];
+static const char *dnssecstats_xmldesc[dns_dnssecstats_max];
 #else
 #define nsstats_xmldesc NULL
 #define resstats_xmldesc NULL
 #define zonestats_xmldesc NULL
 #define sockstats_xmldesc NULL
+#define dnssecstats_xmldesc NULL
 #endif /* HAVE_LIBXML2 */
 
 #define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
@@ -107,6 +110,7 @@ static int nsstats_index[dns_nsstatscounter_max];
 static int resstats_index[dns_resstatscounter_max];
 static int zonestats_index[dns_zonestatscounter_max];
 static int sockstats_index[isc_sockstatscounter_max];
+static int dnssecstats_index[dns_dnssecstats_max];
 
 static inline void
 set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
@@ -408,6 +412,33 @@ init_desc(void) {
                         "FDwatchRecvErr");
        INSIST(i == isc_sockstatscounter_max);
 
+       /* Initialize DNSSEC statistics */
+       for (i = 0; i < dns_dnssecstats_max; i++)
+               dnssecstats_desc[i] = NULL;
+#ifdef  HAVE_LIBXML2
+       for (i = 0; i < dns_dnssecstats_max; i++)
+               dnssecstats_xmldesc[i] = NULL;
+#endif
+
+#define SET_DNSSECSTATDESC(counterid, desc, xmldesc) \
+       do { \
+               set_desc(dns_dnssecstats_ ## counterid, \
+                        dns_dnssecstats_max, \
+                        desc, dnssecstats_desc,\
+                        xmldesc, dnssecstats_xmldesc); \
+               dnssecstats_index[i++] = dns_dnssecstats_ ## counterid; \
+       } while (0)
+
+       i = 0;
+       SET_DNSSECSTATDESC(asis, "dnssec validation success with signer "
+                          "\"as is\"", "DNSSECasis");
+       SET_DNSSECSTATDESC(downcase, "dnssec validation success with signer "
+                          "lower cased", "DNSSECdowncase");
+       SET_DNSSECSTATDESC(wildcard, "dnssec validation of wildcard signature",
+                          "DNSSECwild");
+       SET_DNSSECSTATDESC(fail, "dnssec validation failures", "DNSSECfail");
+       INSIST(i == dns_dnssecstats_max);
+
        /* Sanity check */
        for (i = 0; i < dns_nsstatscounter_max; i++)
                INSIST(nsstats_desc[i] != NULL);
@@ -417,6 +448,8 @@ init_desc(void) {
                INSIST(zonestats_desc[i] != NULL);
        for (i = 0; i < isc_sockstatscounter_max; i++)
                INSIST(sockstats_desc[i] != NULL);
+       for (i = 0; i < dns_dnssecstats_max; i++)
+               INSIST(dnssecstats_desc[i] != NULL);
 #ifdef  HAVE_LIBXML2
        for (i = 0; i < dns_nsstatscounter_max; i++)
                INSIST(nsstats_xmldesc[i] != NULL);
@@ -426,6 +459,8 @@ init_desc(void) {
                INSIST(zonestats_xmldesc[i] != NULL);
        for (i = 0; i < isc_sockstatscounter_max; i++)
                INSIST(sockstats_xmldesc[i] != NULL);
+       for (i = 0; i < dns_dnssecstats_max; i++)
+               INSIST(dnssecstats_xmldesc[i] != NULL);
 #endif
 }
 
index 18d79e60dde09e142de93bf5dc5f106a61a1e20f..478f8cdd2eb5384233556a27366b3d4ed4338b9a 100644 (file)
@@ -44,3 +44,4 @@ rm -f signer/example.db
 rm -f ns2/algroll.db
 rm -f signer/example.db.after signer/example.db.before
 rm -f signer/example.db.changed
+rm -f ns3/lower.example.db ns3/upper.example.db ns3/upper.example.db.lower
index 8f1d1b49aab4f647721bdac074ce4941a44ba666..66f2798c79144a9318a0850e3f608bece3df1354 100644 (file)
@@ -119,3 +119,9 @@ ns.insecure.below-cname     A       10.53.0.3
 
 secure.below-cname     NS      ns.secure.below-cname
 ns.secure.below-cname  A       10.53.0.3
+
+upper                  NS      ns.upper
+ns.upper               A       10.53.0.3
+
+LOWER                  NS      NS.LOWER
+NS.LOWER               A       10.53.0.3
index f55c26f748352bf4b4d6b7cf685bfd2b367f8fa1..2095241fa799acaea9288eea78a11d744fdb3a37 100644 (file)
@@ -32,7 +32,7 @@ zonefile=example.db
 
 for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown \
     optout-unknown multiple rsasha256 rsasha512 update-nsec3 \
-    secure.below-cname expired
+    secure.below-cname expired upper lower
 do
        cp ../ns3/keyset-$subdomain.example. .
 done
diff --git a/bin/tests/system/dnssec/ns3/lower.example.db.in b/bin/tests/system/dnssec/ns3/lower.example.db.in
new file mode 100644 (file)
index 0000000..d71026c
--- /dev/null
@@ -0,0 +1,26 @@
+; Copyright (C) 2012  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.
+
+; $Id: lower.example.db.in,v 1.1.2.1 2012/01/17 08:31:00 marka Exp $
+
+$TTL 300       ; 5 minutes
+@                      IN SOA  MNAME1. . (
+                               2012042407 ; serial
+                               20         ; refresh (20 seconds)
+                               20         ; retry (20 seconds)
+                               1814400    ; expire (3 weeks)
+                               3600       ; minimum (1 hour)
+                               )
+@                      NS      NS
+NS                     A       10.53.0.3
index 00ed685928d5477646206ffe59f412fa2ef5ea5e..81a462421d5f877c9e260b4bc6db3f7a3fe4a0b0 100644 (file)
@@ -188,4 +188,14 @@ zone "secure.below-cname.example" {
        file "secure.below-cname.example.db.signed";
 };
 
+zone "upper.example" {
+       type master;
+       file "upper.example.db.signed";
+};
+
+zone "LOWER.EXAMPLE" {
+       type master;
+       file "lower.example.db.signed";
+};
+
 include "trusted.conf";
index 95eaee341f2f5a37e0a2985ae342a5cb8f6cd637..027fafe1975587e66edf9d213e0b9799884c9778 100644 (file)
@@ -283,3 +283,31 @@ zonefile=secure.below-cname.example.db
 keyname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
 cat $infile $keyname.key >$zonefile
 $SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
+
+#
+# A zone where the signer's name has been forced to uppercase.
+#
+zone="upper.example."
+infile="upper.example.db.in"
+zonefile="upper.example.db"
+lower="upper.example.db.lower"
+signedfile="upper.example.db.signed"
+kskname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 $zone`
+zskname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -f KSK $zone`
+cat $infile $kskname.key $zskname.key > $zonefile
+$SIGNER -P -r $RANDFILE -o $zone -f $lower $zonefile > /dev/null 2>&1
+$CHECKZONE -D upper.example $lower 2>&- | \
+        awk '$4 == "RRSIG" {$12 = toupper($12); print; next} { print }' > $signedfile
+
+#
+# Check that the signer's name is in lower case when zone name is in
+# upper case.
+#
+zone="LOWER.EXAMPLE."
+infile="lower.example.db.in"
+zonefile="lower.example.db"
+signedfile="lower.example.db.signed"
+kskname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 $zone`
+zskname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -f KSK $zone`
+cat $infile $kskname.key $zskname.key > $zonefile
+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
diff --git a/bin/tests/system/dnssec/ns3/upper.example.db.in b/bin/tests/system/dnssec/ns3/upper.example.db.in
new file mode 100644 (file)
index 0000000..52202fb
--- /dev/null
@@ -0,0 +1,26 @@
+; Copyright (C) 2012  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.
+
+; $Id: upper.example.db.in,v 1.1.2.1 2012/01/17 08:31:00 marka Exp $
+
+$TTL 300       ; 5 minutes
+@                      IN SOA  mname1. . (
+                               2012042407 ; serial
+                               20         ; refresh (20 seconds)
+                               20         ; retry (20 seconds)
+                               1814400    ; expire (3 weeks)
+                               3600       ; minimum (1 hour)
+                               )
+@                      NS      ns
+ns                     A       10.53.0.3
index 73f178f84632b15d7dab54d6394fda03e943cbb7..09e1a9296719eadabecceb98747811c3f9780e8a 100644 (file)
@@ -1129,5 +1129,25 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:testing legacy upper case signer name validation ($n)"
+ret=0
+$DIG +tcp +dnssec -p 5300 +noadd +noauth soa upper.example @10.53.0.4 \
+        > dig.out.ns4.test$n 2>&1
+grep 'flags:.* ad;' dig.out.ns4.test$n >/dev/null || ret=1
+grep 'RRSIG.*SOA.* UPPER\.EXAMPLE\. ' dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:testing that we lower case signer name ($n)"
+ret=0
+$DIG +tcp +dnssec -p 5300 +noadd +noauth soa LOWER.EXAMPLE @10.53.0.4 \
+        > dig.out.ns4.test$n 2>&1
+grep 'flags:.* ad;' dig.out.ns4.test$n >/dev/null || ret=1
+grep 'RRSIG.*SOA.* lower\.example\. ' dig.out.ns4.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
index 6e9ab9f0d0d98c1735b86e54197e3e180d117ce7..02bfc42afef94aaaea80489af7ea8558a1ca326e 100644 (file)
 #include <dns/dnssec.h>
 #include <dns/fixedname.h>
 #include <dns/keyvalues.h>
+#include <dns/log.h>
 #include <dns/message.h>
 #include <dns/rdata.h>
 #include <dns/rdatalist.h>
 #include <dns/rdataset.h>
 #include <dns/rdatastruct.h>
 #include <dns/result.h>
+#include <dns/stats.h>
 #include <dns/tsig.h>          /* for DNS_TSIG_FUDGE */
 
 #include <dst/result.h>
 
+LIBDNS_EXTERNAL_DATA isc_stats_t *dns_dnssec_stats;
+
 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
 
 #define RETERR(x) do { \
@@ -74,6 +78,12 @@ digest_callback(void *arg, isc_region_t *data) {
        return (dst_context_adddata(ctx, data));
 }
 
+static inline void
+inc_stat(isc_statscounter_t counter) {
+       if (dns_dnssec_stats != NULL)
+               isc_stats_increment(dns_dnssec_stats, counter);
+}
+
 /*
  * Make qsort happy.
  */
@@ -150,7 +160,9 @@ dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
 }
 
 static isc_result_t
-digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) {
+digest_sig(dst_context_t *ctx, isc_boolean_t downcase, dns_rdata_t *sigrdata,
+          dns_rdata_rrsig_t *rrsig)
+{
        isc_region_t r;
        isc_result_t ret;
        dns_fixedname_t fname;
@@ -162,11 +174,16 @@ digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) {
        ret = dst_context_adddata(ctx, &r);
        if (ret != ISC_R_SUCCESS)
                return (ret);
-       dns_fixedname_init(&fname);
-       RUNTIME_CHECK(dns_name_downcase(&sig->signer,
-                                       dns_fixedname_name(&fname), NULL)
-                     == ISC_R_SUCCESS);
-       dns_name_toregion(dns_fixedname_name(&fname), &r);
+       if (downcase) {
+               dns_fixedname_init(&fname);
+
+               RUNTIME_CHECK(dns_name_downcase(&rrsig->signer,
+                                               dns_fixedname_name(&fname),
+                                               NULL) == ISC_R_SUCCESS);
+               dns_name_toregion(dns_fixedname_name(&fname), &r);
+       } else 
+               dns_name_toregion(&rrsig->signer, &r);
+       
        return (dst_context_adddata(ctx, &r));
 }
 
@@ -188,6 +205,7 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        isc_uint32_t flags;
        unsigned int sigsize;
        dns_fixedname_t fnewname;
+       dns_fixedname_t fsigner;
 
        REQUIRE(name != NULL);
        REQUIRE(dns_name_countlabels(name) <= 255);
@@ -215,8 +233,14 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        sig.common.rdtype = dns_rdatatype_rrsig;
        ISC_LINK_INIT(&sig.common, link);
 
+       /*
+        * Downcase signer.
+        */
        dns_name_init(&sig.signer, NULL);
-       dns_name_clone(dst_key_name(key), &sig.signer);
+       dns_fixedname_init(&fsigner);
+       RUNTIME_CHECK(dns_name_downcase(dst_key_name(key),
+                     dns_fixedname_name(&fsigner), NULL) == ISC_R_SUCCESS);
+       dns_name_clone(dns_fixedname_name(&fsigner), &sig.signer);
 
        sig.covered = set->type;
        sig.algorithm = dst_key_alg(key);
@@ -256,7 +280,7 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        /*
         * Digest the SIG rdata.
         */
-       ret = digest_sig(ctx, &tmpsigrdata, &sig);
+       ret = digest_sig(ctx, ISC_FALSE, &tmpsigrdata, &sig);
        if (ret != ISC_R_SUCCESS)
                goto cleanup_context;
 
@@ -329,7 +353,7 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        memcpy(sig.signature, r.base, sig.siglen);
 
        ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
-                                 sig.common.rdtype, &sig, buffer);
+                                  sig.common.rdtype, &sig, buffer);
 
 cleanup_array:
        isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
@@ -360,6 +384,7 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        dst_context_t *ctx = NULL;
        int labels = 0;
        isc_uint32_t flags;
+       isc_boolean_t downcase = ISC_FALSE;
 
        REQUIRE(name != NULL);
        REQUIRE(set != NULL);
@@ -374,8 +399,10 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        if (set->type != sig.covered)
                return (DNS_R_SIGINVALID);
 
-       if (isc_serial_lt(sig.timeexpire, sig.timesigned))
+       if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
+               inc_stat(dns_dnssecstats_fail);
                return (DNS_R_SIGINVALID);
+       }
 
        if (!ignoretime) {
                isc_stdtime_get(&now);
@@ -383,10 +410,13 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
                /*
                 * Is SIG temporally valid?
                 */
-               if (isc_serial_lt((isc_uint32_t)now, sig.timesigned))
+               if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) {
+                       inc_stat(dns_dnssecstats_fail);
                        return (DNS_R_SIGFUTURE);
-               else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now))
+               } else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) {
+                       inc_stat(dns_dnssecstats_fail);
                        return (DNS_R_SIGEXPIRED);
+               }
        }
 
        /*
@@ -397,16 +427,22 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        case dns_rdatatype_ns:
        case dns_rdatatype_soa:
        case dns_rdatatype_dnskey:
-               if (!dns_name_equal(name, &sig.signer))
+               if (!dns_name_equal(name, &sig.signer)) {
+                       inc_stat(dns_dnssecstats_fail);
                        return (DNS_R_SIGINVALID);
+               }
                break;
        case dns_rdatatype_ds:
-               if (dns_name_equal(name, &sig.signer))
+               if (dns_name_equal(name, &sig.signer)) {
+                       inc_stat(dns_dnssecstats_fail);
                        return (DNS_R_SIGINVALID);
+               }
                /* FALLTHROUGH */
        default:
-               if (!dns_name_issubdomain(name, &sig.signer))
+               if (!dns_name_issubdomain(name, &sig.signer)) {
+                       inc_stat(dns_dnssecstats_fail);
                        return (DNS_R_SIGINVALID);
+               }
                break;
        }
 
@@ -414,11 +450,16 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
         * Is the key allowed to sign data?
         */
        flags = dst_key_flags(key);
-       if (flags & DNS_KEYTYPE_NOAUTH)
+       if (flags & DNS_KEYTYPE_NOAUTH) {
+               inc_stat(dns_dnssecstats_fail);
                return (DNS_R_KEYUNAUTHORIZED);
-       if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
+       }
+       if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
+               inc_stat(dns_dnssecstats_fail);
                return (DNS_R_KEYUNAUTHORIZED);
+       }
 
+ again:
        ret = dst_context_create(key, mctx, &ctx);
        if (ret != ISC_R_SUCCESS)
                goto cleanup_struct;
@@ -426,7 +467,7 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        /*
         * Digest the SIG rdata (not including the signature).
         */
-       ret = digest_sig(ctx, sigrdata, &sig);
+       ret = digest_sig(ctx, downcase, sigrdata, &sig);
        if (ret != ISC_R_SUCCESS)
                goto cleanup_context;
 
@@ -505,21 +546,40 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
        r.base = sig.signature;
        r.length = sig.siglen;
        ret = dst_context_verify(ctx, &r);
-       if (ret == DST_R_VERIFYFAILURE)
-               ret = DNS_R_SIGINVALID;
+       if (ret == ISC_R_SUCCESS && downcase) {
+               char namebuf[DNS_NAME_FORMATSIZE];
+               dns_name_format(&sig.signer, namebuf, sizeof(namebuf));
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+                             DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+                             "sucessfully validated after lower casing "
+                             "signer '%s'", namebuf);
+               inc_stat(dns_dnssecstats_downcase);
+       } else if (ret == ISC_R_SUCCESS)
+               inc_stat(dns_dnssecstats_asis);
 
 cleanup_array:
        isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
 cleanup_context:
        dst_context_destroy(&ctx);
+       if (ret == DST_R_VERIFYFAILURE && !downcase) {
+               downcase = ISC_TRUE;
+               goto again;
+       }
 cleanup_struct:
        dns_rdata_freestruct(&sig);
 
+       if (ret == DST_R_VERIFYFAILURE)
+               ret = DNS_R_SIGINVALID;
+
+       if (ret != ISC_R_SUCCESS)
+               inc_stat(dns_dnssecstats_fail);
+
        if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
                if (wild != NULL)
                        RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
                                                 dns_fixedname_name(&fnewname),
                                                 wild, NULL) == ISC_R_SUCCESS);
+               inc_stat(dns_dnssecstats_wildcard);
                ret = DNS_R_FROMWILDCARD;
        }
        return (ret);
index 6a2cbb4c19a5ac9c5814338f50fa6ffd43eaad15..22a8a41e6d48d4c5e3de96074e1dbbaba2e3fea0 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <isc/lang.h>
 #include <isc/stdtime.h>
+#include <isc/stats.h>
 
 #include <dns/types.h>
 
@@ -31,6 +32,8 @@
 
 ISC_LANG_BEGINDECLS
 
+LIBDNS_EXTERNAL_DATA extern isc_stats_t *dns_dnssec_stats;
+
 /*%< Maximum number of keys supported in a zone. */
 #define DNS_MAXZONEKEYS 32
 
@@ -60,8 +63,8 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
                isc_stdtime_t *inception, isc_stdtime_t *expire,
                isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata);
 /*%<
- *     Generates a SIG record covering this rdataset.  This has no effect
- *     on existing SIG records.
+ *     Generates a RRSIG record covering this rdataset.  This has no effect
+ *     on existing RRSIG records.
  *
  *     Requires:
  *\li          'name' (the owner name of the record) is a valid name
@@ -94,9 +97,9 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
                   isc_boolean_t ignoretime, isc_mem_t *mctx,
                   dns_rdata_t *sigrdata, dns_name_t *wild);
 /*%<
- *     Verifies the SIG record covering this rdataset signed by a specific
- *     key.  This does not determine if the key's owner is authorized to
- *     sign this record, as this requires a resolver or database.
+ *     Verifies the RRSIG record covering this rdataset signed by a specific
+ *     key.  This does not determine if the key's owner is authorized to sign
+ *     this record, as this requires a resolver or database.
  *     If 'ignoretime' is ISC_TRUE, temporal validity will not be checked.
  *
  *     Requires:
index 475d8095b637e68207f812b3dce923453e545c0c..6c874301f252b679c7ab7fafa55e83942589a72c 100644 (file)
@@ -73,6 +73,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
 #define DNS_LOGMODULE_HINTS            (&dns_modules[24])
 #define DNS_LOGMODULE_ACACHE           (&dns_modules[25])
 #define DNS_LOGMODULE_DLZ              (&dns_modules[26])
+#define DNS_LOGMODULE_DNSSEC           (&dns_modules[27])
 
 ISC_LANG_BEGINDECLS
 
index bc77d1e9c5a366732099deb55173e99244e315d5..5364267272a02b6c4fea07a2a282e65ceb1cf187 100644 (file)
@@ -64,6 +64,16 @@ enum {
 
        dns_resstatscounter_max = 30,
 
+       /*
+        * DNSSEC stats.
+        */
+       dns_dnssecstats_asis = 0,
+       dns_dnssecstats_downcase = 1,
+       dns_dnssecstats_wildcard = 2,
+       dns_dnssecstats_fail = 3,
+
+       dns_dnssecstats_max = 4,
+
        /*%
         * Zone statistics counters.
         */
index 17af1d9b2d4cce5e8d27d0f2b2b88323ec75e009..b49e6505bccf0c4da909652d934a2f4879a24366 100644 (file)
@@ -79,6 +79,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = {
        { "dns/hints",          0 },
        { "dns/acache",         0 },
        { "dns/dlz",            0 },
+       { "dns/dnssec",         0 },
        { NULL,                 0 }
 };