]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Fix autotrust initialised with DS.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 2 Nov 2009 13:56:14 +0000 (13:56 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 2 Nov 2009 13:56:14 +0000 (13:56 +0000)
git-svn-id: file:///svn/unbound/trunk@1884 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
validator/autotrust.c
validator/val_utils.c
validator/val_utils.h

index 91f009f3931a13ed561e8ace1d699cd3a2812d20..4501a327fcf815a7b6ca60da7dc0ac2035bd884e 100644 (file)
@@ -1,3 +1,6 @@
+2 November 2009: Wouter
+       - Fix bug where autotrust does not work when started with a DS.
+
 29 October 2009: Wouter
        - iana portlist updated.
        - edns-buffer-size option, default 4096.
index c079aef61f6a6830fc34364565d6299127f00394..d3389d655026f0600176a68aefc20bf1fc6e768a 100644 (file)
@@ -1274,10 +1274,49 @@ check_contains_revoked(struct module_env* env, struct val_env* ve,
        ldns_rr_list_deep_free(r);
 }
 
+/** See if a DNSKEY is verified by one of the DSes */
+static int
+key_matches_a_ds(struct module_env* env, struct val_env* ve,
+       struct ub_packed_rrset_key* dnskey_rrset, size_t key_idx,
+       struct ub_packed_rrset_key* ds_rrset)
+{
+       struct packed_rrset_data* dd = (struct packed_rrset_data*)
+                       ds_rrset->entry.data;
+       size_t ds_idx, num = dd->count;
+       int d = val_favorite_ds_algo(ds_rrset);
+       char* reason = "";
+       for(ds_idx=0; ds_idx<num; ds_idx++) {
+               if(!ds_digest_algo_is_supported(ds_rrset, ds_idx) ||
+                       !ds_key_algo_is_supported(ds_rrset, ds_idx) ||
+                       ds_get_digest_algo(ds_rrset, ds_idx) != d)
+                       continue;
+               if(ds_get_key_algo(ds_rrset, ds_idx)
+                  != dnskey_get_algo(dnskey_rrset, key_idx)
+                  || dnskey_calc_keytag(dnskey_rrset, key_idx)
+                  != ds_get_keytag(ds_rrset, ds_idx)) {
+                       continue;
+               }
+               if(!ds_digest_match_dnskey(env, dnskey_rrset, key_idx,
+                       ds_rrset, ds_idx)) {
+                       verbose(VERB_ALGO, "DS match attempt failed");
+                       continue;
+               }
+               if(dnskey_verify_rrset(env, ve, dnskey_rrset, 
+                       dnskey_rrset, key_idx, &reason) == sec_status_secure) {
+                       return 1;
+               } else {
+                       verbose(VERB_ALGO, "DS match failed because the key "
+                               "does not verify the keyset: %s", reason);
+               }
+       }
+       return 0;
+}
+
 /** Set update events */
 static int
-update_events(struct module_env* env, struct trust_anchor* tp, 
-       struct ub_packed_rrset_key* dnskey_rrset, int* changed)
+update_events(struct module_env* env, struct val_env* ve, 
+       struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, 
+       int* changed)
 {
        ldns_rr_list* r = packed_rrset_to_rr_list(dnskey_rrset, 
                env->scratch_buffer);
@@ -1315,6 +1354,12 @@ update_events(struct module_env* env, struct trust_anchor* tp,
                if(!ta) {
                        ta = add_key(tp, rr);
                        *changed = 1;
+                       /* first time seen, do we have DSes? if match: VALID */
+                       if(ta && tp->ds_rrset && key_matches_a_ds(env, ve,
+                               dnskey_rrset, i, tp->ds_rrset)) {
+                               verbose_key(ta, VERB_ALGO, "verified by DS");
+                               ta->s = AUTR_STATE_VALID;
+                       }
                }
                if(!ta) {
                        ldns_rr_list_deep_free(r);
@@ -1810,7 +1855,7 @@ int autr_process_prime(struct module_env* env, struct val_env* ve,
         * Set trustpoint query_interval and retry_time.
         * - find minimum rrsig expiration interval
         */
-       if(!update_events(env, tp, dnskey_rrset, &changed)) {
+       if(!update_events(env, ve, tp, dnskey_rrset, &changed)) {
                log_err("malloc failure in autotrust update_events. "
                        "trust point unchanged.");
                return 1; /* trust point unchanged, so exists */
index d582f87dfe679e6f15e02806581da565e83abb40..5238e1a1dd91f0d3302d8539c0b36b6ce11f6bea 100644 (file)
@@ -427,6 +427,23 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
        return sec_status_bogus;
 }
 
+int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
+{
+       size_t i, num = rrset_get_count(ds_rrset);
+       int d, digest_algo = 0; /* DS digest algo 0 is not used. */
+       /* find favorite algo, for now, highest number supported */
+       for(i=0; i<num; i++) {
+               if(!ds_digest_algo_is_supported(ds_rrset, i) ||
+                       !ds_key_algo_is_supported(ds_rrset, i)) {
+                       continue;
+               }
+               d = ds_get_digest_algo(ds_rrset, i);
+               if(d > digest_algo)
+                       digest_algo = d;
+       }
+       return digest_algo;
+}
+
 enum sec_status 
 val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
        struct ub_packed_rrset_key* dnskey_rrset,
@@ -434,8 +451,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
 {
        /* as long as this is false, we can consider this DS rrset to be
         * equivalent to no DS rrset. */
-       int has_useful_ds = 0;
-       int d, digest_algo = 0; /* DS digest algo 0 is not used. */
+       int has_useful_ds = 0, digest_algo;
        size_t i, num;
        enum sec_status sec;
 
@@ -448,17 +464,8 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
                return sec_status_bogus;
        }
 
+       digest_algo = val_favorite_ds_algo(ds_rrset);
        num = rrset_get_count(ds_rrset);
-       /* find favorite algo, for now, highest number supported */
-       for(i=0; i<num; i++) {
-               if(!ds_digest_algo_is_supported(ds_rrset, i) ||
-                       !ds_key_algo_is_supported(ds_rrset, i)) {
-                       continue;
-               }
-               d = ds_get_digest_algo(ds_rrset, i);
-               if(d > digest_algo)
-                       digest_algo = d;
-       }
        for(i=0; i<num; i++) {
                /* Check to see if we can understand this DS. 
                 * And check it is the strongest digest */
index 11c7e09695c1219e0c367f6eeb0fcba42b1185fa..ec0f912ef20e05bb41b03b6eeef23d6cdcb63c5c 100644 (file)
@@ -314,4 +314,10 @@ void val_blacklist(struct sock_list** blacklist, struct regional* region,
  */
 int val_has_signed_nsecs(struct reply_info* rep, char** reason);
 
+/**
+ * Return algo number for favorite (best) algorithm that we support in DS.
+ * @return algo number or 0 if none supported. 0 is unused as algo number.
+ */
+int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset);
+
 #endif /* VALIDATOR_VAL_UTILS_H */