]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
nsec3 hash function unit test.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 17 Sep 2007 09:25:54 +0000 (09:25 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 17 Sep 2007 09:25:54 +0000 (09:25 +0000)
git-svn-id: file:///svn/unbound/trunk@615 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testcode/unitverify.c
testdata/test_nsec3_hash.1 [new file with mode: 0644]
validator/val_nsec3.c
validator/val_nsec3.h

index be26c6b2504d80e657308bfec1b2610164170868..25cc91b8fd2c0bf214ed193a7412001eeb46e1e1 100644 (file)
@@ -1,3 +1,6 @@
+17 September 2007: Wouter
+       - NSEC3 hash cache unit test.
+
 14 September 2007: Wouter
        - nsec3 nodata proof, nods proof, wildcard proof.
        - nsec3 support for cname chain ending in noerror or nodata.
index 1a4c358a9526a890978acea8b51b157fb9be6b37..f6359bd738dc6a76b8a1d088e82bb13280bd913f 100644 (file)
 #include "testcode/unitmain.h"
 #include "validator/val_sigcrypt.h"
 #include "validator/val_nsec.h"
+#include "validator/val_nsec3.h"
 #include "validator/validator.h"
 #include "testcode/ldns-testpkts.h"
 #include "util/data/msgreply.h"
 #include "util/data/msgparse.h"
+#include "util/data/dname.h"
 #include "util/region-allocator.h"
 #include "util/alloc.h"
+#include "util/rbtree.h"
 #include "util/net_help.h"
 #include "util/module.h"
 #include "util/config_file.h"
@@ -91,7 +94,6 @@ entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, struct region*
        struct edns_data edns;
        entry_to_buf(e, pkt);
        ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns);
-       region_free_all(region);
        if(ret != 0) {
                printf("parse code %d: %s\n", ret,
                        ldns_lookup_by_id(ldns_rcodes, ret)->name);
@@ -228,6 +230,7 @@ dstest_entry(struct entry* e, struct alloc_cache* alloc, struct region*
                        printf("result(no)= %s\n", ret?"yes":"no");
                }
                unit_assert(!ret);
+               verbose(VERB_DETAIL, "DS fail: OK; matched unit test");
        } else {
                fatal_exit("Bad qname in DS unit test, yes or no");
        }
@@ -362,6 +365,87 @@ nsectest()
        unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230));
 }
 
+/** Test hash algo - NSEC3 hash it and compare result */
+static void
+nsec3_hash_test_entry(struct entry* e, rbtree_t* ct,
+       struct alloc_cache* alloc, struct region* region, 
+       ldns_buffer* buf)
+{
+       struct query_info qinfo;
+       struct reply_info* rep = NULL;
+       struct ub_packed_rrset_key* answer, *nsec3;
+       struct nsec3_cached_hash* hash;
+       int ret;
+       uint8_t* qname;
+
+       if(vsig) {
+               printf("verifying NSEC3 hash:\n");
+               ldns_pkt_print(stdout, e->reply_list->reply);
+               printf("\n");
+       }
+       entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep);
+       nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3);
+       answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA);
+       qname = region_alloc_init(region, qinfo.qname, qinfo.qname_len);
+       /* check test is OK */
+       unit_assert(nsec3 && answer && qname);
+
+       ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
+               qinfo.qname_len, &hash);
+       if(ret != 1) {
+               printf("Bad nsec3_hash_name retcode %d\n", ret);
+               unit_assert(ret == 1);
+       }
+       unit_assert(hash->dname && hash->hash && hash->hash_len &&
+               hash->b32 && hash->b32_len);
+       unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]);
+       /* does not do lowercasing. */
+       unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) 
+               == 0);
+
+       reply_info_parsedelete(rep, alloc);
+       query_info_clear(&qinfo);
+}
+
+
+/** Read file to test NSEC3 hash algo */
+static void
+nsec3_hash_test(const char* fname)
+{
+       /* 
+        * The list contains a list of ldns-testpkts entries.
+        * Every entry is a test.
+        *      The qname is hashed.
+        *      The answer section AAAA RR name is the required result.
+        *      The auth section NSEC3 is used to get hash parameters.
+        * The hash cache is maintained per file.
+        *
+        * The test does not perform canonicalization during the compare.
+        */
+       rbtree_t ct;
+       struct region* region = region_create(malloc, free);
+       struct alloc_cache alloc;
+       ldns_buffer* buf = ldns_buffer_new(65535);
+       struct entry* e;
+       struct entry* list = read_datafile(fname);
+
+       if(!list)
+               fatal_exit("could not read %s: %s", fname, strerror(errno));
+       rbtree_init(&ct, &nsec3_hash_cmp);
+       alloc_init(&alloc, NULL, 1);
+       unit_assert(region && buf);
+
+       /* ready to go! */
+       for(e = list; e; e = e->next) {
+               nsec3_hash_test_entry(e, &ct, &alloc, region, buf);
+       }
+
+       delete_entry(list);
+       region_destroy(region);
+       alloc_clear(&alloc);
+       ldns_buffer_free(buf);
+}
+
 void 
 verify_test()
 {
@@ -369,4 +453,5 @@ verify_test()
        verifytest_file("testdata/test_signatures.1", "20070818005004");
        dstest_file("testdata/test_ds_sig.1");
        nsectest();
+       nsec3_hash_test("testdata/test_nsec3_hash.1");
 }
diff --git a/testdata/test_nsec3_hash.1 b/testdata/test_nsec3_hash.1
new file mode 100644 (file)
index 0000000..7b3813e
--- /dev/null
@@ -0,0 +1,180 @@
+;
+; NSEC3 hash algo test file.
+; The hash cache is maintained for the duration of the file.
+; Every entry is a hash test.
+;      query name is hashed.
+;      answer AAAA record hash the correct hashed answer name.
+;      auth NSEC3 record has the hash parameters.
+;
+
+
+; These are from the nsec3-draft-11 example zone.
+; H(example)       = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+ENTRY_BEGIN
+SECTION QUESTION
+example. IN AAAA
+SECTION ANSWER
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(a.example)     = 35mthgpgcu1qg68fab165klnsnk3dpvl
+ENTRY_BEGIN
+SECTION QUESTION
+a.example.     IN      AAAA
+SECTION ANSWER
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(ai.example)    = gjeqe526plbf1g8mklp59enfd789njgi
+ENTRY_BEGIN
+SECTION QUESTION
+ai.example.    IN      AAAA
+SECTION ANSWER
+gjeqe526plbf1g8mklp59enfd789njgi.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(ns1.example)   = 2t7b4g4vsa5smi47k61mv5bv1a22bojr
+ENTRY_BEGIN
+SECTION QUESTION
+ns1.example.   IN      AAAA
+SECTION ANSWER
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(ns2.example)   = q04jkcevqvmu85r014c7dkba38o0ji5r
+ENTRY_BEGIN
+SECTION QUESTION
+ns2.example.  IN      AAAA
+SECTION ANSWER
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(w.example)     = k8udemvp1j2f7eg6jebps17vp3n8i58h
+ENTRY_BEGIN
+SECTION QUESTION
+w.example.     IN      AAAA
+SECTION ANSWER
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(*.w.example)   = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+ENTRY_BEGIN
+SECTION QUESTION
+*.w.example.   IN      AAAA
+SECTION ANSWER
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(x.w.example)   = b4um86eghhds6nea196smvmlo4ors995
+ENTRY_BEGIN
+SECTION QUESTION
+x.w.example.   IN      AAAA
+SECTION ANSWER
+b4um86eghhds6nea196smvmlo4ors995.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(y.w.example)   = ji6neoaepv8b5o6k4ev33abha8ht9fgc
+ENTRY_BEGIN
+SECTION QUESTION
+y.w.example.   IN      AAAA
+SECTION ANSWER
+ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(x.y.w.example) = 2vptu5timamqttgl4luu9kg21e0aor3s
+ENTRY_BEGIN
+SECTION QUESTION
+x.y.w.example. IN      AAAA
+SECTION ANSWER
+2vptu5timamqttgl4luu9kg21e0aor3s.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; H(xx.example)    = t644ebqk9bibcna874givr6joj62mlhv
+; capitalization changed.
+ENTRY_BEGIN
+SECTION QUESTION
+xX.example.    IN      AAAA
+SECTION ANSWER
+t644ebqk9bibcna874givr6joj62mlhv.example.      AAAA    ::1
+SECTION AUTHORITY
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd (gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+ENTRY_END
+
+; H(2t7b4g4vsa5smi47k61mv5bv1a22bojr.example)
+;                  = kohar7mbb8dc2ce8a9qvl8hon4k53uhi
+ENTRY_BEGIN
+SECTION QUESTION
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example.      IN      AAAA
+SECTION ANSWER
+kohar7mbb8dc2ce8a9qvl8hon4k53uhi.example.      AAAA    ::1
+SECTION AUTHORITY
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd (gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+ENTRY_END
+
+
+
+; repeat entry to test the cache.
+; H(example)       = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+ENTRY_BEGIN
+SECTION QUESTION
+example. IN AAAA
+SECTION ANSWER
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; repeat entry to test the cache.
+; H(a.example)     = 35mthgpgcu1qg68fab165klnsnk3dpvl
+ENTRY_BEGIN
+SECTION QUESTION
+a.example.     IN      AAAA
+SECTION ANSWER
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; repeat entry to test the cache.
+; H(ai.example)    = gjeqe526plbf1g8mklp59enfd789njgi
+ENTRY_BEGIN
+SECTION QUESTION
+ai.example.    IN      AAAA
+SECTION ANSWER
+gjeqe526plbf1g8mklp59enfd789njgi.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
+; repeat entry to test the cache.
+; capitalization of qname.
+; H(ai.example)    = gjeqe526plbf1g8mklp59enfd789njgi
+ENTRY_BEGIN
+SECTION QUESTION
+AI.example.    IN      AAAA
+SECTION ANSWER
+gjeqe526plbf1g8mklp59enfd789njgi.example. AAAA ::1
+SECTION AUTHORITY
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+ENTRY_END
+
index e048fef44051fcb633537ef2f3b33743e2e44e2f..6474b85cf3b5d35e2896a8720eb71b671dfbda21 100644 (file)
@@ -66,33 +66,6 @@ int b32_ntop_extended_hex(uint8_t const *src, size_t srclength,
 int b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, 
        uint8_t *target, size_t targsize);
 
-/**
- * The NSEC3 hash result storage.
- * Consists of an rbtree, with these nodes in it.
- * The nodes detail how a set of parameters (from nsec3 rr) plus
- * a dname result in a hash.
- */
-struct nsec3_cached_hash {
-       /** rbtree node, key is this structure */
-       rbnode_t node;
-       /** where are the parameters for conversion, in this rrset data */
-       struct ub_packed_rrset_key* nsec3;
-       /** where are the parameters for conversion, this RR number in data */
-       int rr;
-       /** the name to convert */
-       uint8_t* dname;
-       /** length of the dname */
-       size_t dname_len;
-       /** the hash result (not base32 encoded) */
-       uint8_t* hash;
-       /** length of hash in bytes */
-       size_t hash_len;
-       /** the hash result in base32 encoding */
-       uint8_t* b32;
-       /** length of base32 encoding (as a label) */
-       size_t b32_len;
-};
-
 /**
  * Closest encloser (ce) proof results
  * Contains the ce and the next-closer (nc) proof.
@@ -472,7 +445,7 @@ nsec3_iteration_count_high(struct val_env* ve, struct nsec3_filter* filter,
 }
 
 /** nsec3_cache_compare for rbtree */
-static int
+int
 nsec3_hash_cmp(const void* c1, const void* c2) 
 {
        struct nsec3_cached_hash* h1 = (struct nsec3_cached_hash*)c1;
@@ -545,6 +518,7 @@ nsec3_calc_hash(struct region* region, ldns_buffer* buf,
                                        (unsigned long)ldns_buffer_limit(buf),
                                        (unsigned char*)c->hash);
                        }
+                       break;
 #endif /* SHA_DIGEST_LENGTH */
                default:
                        log_err("nsec3 hash of unknown algo %d", algo);
@@ -573,22 +547,7 @@ nsec3_calc_b32(struct region* region, ldns_buffer* buf,
        return 1;
 }
 
-/**
- * Obtain the hash of an owner name.
- * @param table: the cache table. Must be inited at start.
- * @param region: scratch region to use for allocation.
- * @param buf: temporary buffer.
- * @param nsec3: the rrset with parameters
- * @param rr: rr number from d that has the NSEC3 parameters to hash to.
- * @param dname: name to hash
- * @param dname_len: the length of the name.
- * @param hash: the hash node is returned on success.
- * @return:
- *     1 on success, either from cache or newly hashed hash is returned.
- *     0 on a malloc failure.
- *     -1 if the NSEC3 rr was badly formatted (i.e. formerr).
- */
-static int
+int
 nsec3_hash_name(rbtree_t* table, struct region* region, ldns_buffer* buf,
        struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname, 
        size_t dname_len, struct nsec3_cached_hash** hash)
index af83e6f0f291f64cbc5b2de8a004c55dc1fc307c..1c55d4ff3474a0d0631989c887e9080f6b232d5f 100644 (file)
@@ -66,7 +66,9 @@
 
 #ifndef VALIDATOR_VAL_NSEC3_H
 #define VALIDATOR_VAL_NSEC3_H
+#include "util/rbtree.h"
 struct val_env;
+struct region;
 struct module_env;
 struct ub_packed_rrset_key;
 enum sec_status;
@@ -211,4 +213,60 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key** list, size_t num, 
        struct query_info* qinfo, struct key_entry_key* kkey, int* nodata);
 
+/**
+ * The NSEC3 hash result storage.
+ * Consists of an rbtree, with these nodes in it.
+ * The nodes detail how a set of parameters (from nsec3 rr) plus
+ * a dname result in a hash.
+ */
+struct nsec3_cached_hash {
+       /** rbtree node, key is this structure */
+       rbnode_t node;
+       /** where are the parameters for conversion, in this rrset data */
+       struct ub_packed_rrset_key* nsec3;
+       /** where are the parameters for conversion, this RR number in data */
+       int rr;
+       /** the name to convert */
+       uint8_t* dname;
+       /** length of the dname */
+       size_t dname_len;
+       /** the hash result (not base32 encoded) */
+       uint8_t* hash;
+       /** length of hash in bytes */
+       size_t hash_len;
+       /** the hash result in base32 encoding */
+       uint8_t* b32;
+       /** length of base32 encoding (as a label) */
+       size_t b32_len;
+};
+
+/**
+ * Rbtree for hash cache comparison function
+ */
+int nsec3_hash_cmp(const void* c1, const void* c2);
+
+/**
+ * Obtain the hash of an owner name.
+ * Used internally by the nsec3 proof functions in this file.
+ * published to enable unit testing of hash algorithms and cache.
+ *
+ * @param table: the cache table. Must be inited at start.
+ * @param region: scratch region to use for allocation.
+ *     This region holds the tree, if you wipe the region, reinit the tree.
+ * @param buf: temporary buffer.
+ * @param nsec3: the rrset with parameters
+ * @param rr: rr number from d that has the NSEC3 parameters to hash to.
+ * @param dname: name to hash
+ *     This pointer is used inside the tree, assumed region-alloced.
+ * @param dname_len: the length of the name.
+ * @param hash: the hash node is returned on success.
+ * @return:
+ *     1 on success, either from cache or newly hashed hash is returned.
+ *     0 on a malloc failure.
+ *     -1 if the NSEC3 rr was badly formatted (i.e. formerr).
+ */
+int nsec3_hash_name(rbtree_t* table, struct region* region, ldns_buffer* buf,
+       struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname, 
+       size_t dname_len, struct nsec3_cached_hash** hash);
+
 #endif /* VALIDATOR_VAL_NSEC3_H */