]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Fixup trust anchor algorithm check.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Mar 2009 13:07:48 +0000 (13:07 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Mar 2009 13:07:48 +0000 (13:07 +0000)
git-svn-id: file:///svn/unbound/trunk@1532 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testdata/val_unalgo_anchor.rpl [new file with mode: 0644]
validator/val_anchor.c
validator/val_utils.c
validator/val_utils.h
validator/validator.c

index 16a41cc5380aa2e909d966ef9827308af992aa03..c06ffe06b85d9b63546070ef70f6c59277f70060 100644 (file)
@@ -1,5 +1,9 @@
 18 March 2009: Wouter
        - Added tests, unknown algorithms become insecure. fallback works.
+       - Fix for and test for unknown algorithms in a trust anchor
+         definition.  Trust anchors with no supported algos are ignored.
+         This means a (higher)DS or DLV entry for them could succeed, and
+         otherwise they are treated as insecure.
 
 17 March 2009: Wouter
        - unit test for unsupported algorithm in anchor warning.
diff --git a/testdata/val_unalgo_anchor.rpl b/testdata/val_unalgo_anchor.rpl
new file mode 100644 (file)
index 0000000..e588b8a
--- /dev/null
@@ -0,0 +1,150 @@
+; config options
+; The island of trust is at example.com
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 208 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       val-override-date: "20070916134226"
+       target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with unsupported algorithm trust anchor 
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com.    IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.     IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.    IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.         IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com.    3600    IN      DNSKEY  256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com.    3600    IN      RRSIG   DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+www.example.com.        3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+www.example.com.        3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
index 1f4b68d38f26949176d50334fdf6b32bb738be0b..9066078c505dc7ba49af5e54ecba9b1cb7e2c66e 100644 (file)
@@ -823,35 +823,34 @@ anchors_assemble(struct val_anchors* anchors, struct trust_anchor* ta)
 /**
  * Check DS algos for support, warn if not.
  * @param ta: trust anchor
- * @return true if all anchors are supported.
+ * @return number of DS anchors with unsupported algorithms.
  */
-static int
-anchors_ds_is_supported(struct trust_anchor* ta)
+static size_t
+anchors_ds_unsupported(struct trust_anchor* ta)
 {
-       size_t i;
+       size_t i, num = 0;
        for(i=0; i<ta->numDS; i++) {
-               if(!ds_digest_algo_is_supported(ta->ds_rrset, i))
-                       return 0;
-               if(!ds_key_algo_is_supported(ta->ds_rrset, i))
-                       return 0;
+               if(!ds_digest_algo_is_supported(ta->ds_rrset, i) || 
+                       !ds_key_algo_is_supported(ta->ds_rrset, i))
+                       num++;
        }
-       return 1;
+       return num;
 }
 
 /**
  * Check DNSKEY algos for support, warn if not.
  * @param ta: trust anchor
- * @return true if all anchors are supported.
+ * @return number of DNSKEY anchors with unsupported algorithms.
  */
-static int
-anchors_dnskey_is_supported(struct trust_anchor* ta)
+static size_t
+anchors_dnskey_unsupported(struct trust_anchor* ta)
 {
-       size_t i;
+       size_t i, num = 0;
        for(i=0; i<ta->numDNSKEY; i++) {
                if(!dnskey_algo_is_supported(ta->dnskey_rrset, i))
-                       return 0;
+                       num++;
        }
-       return 1;
+       return num;
 }
 
 /**
@@ -863,21 +862,35 @@ static int
 anchors_assemble_rrsets(struct val_anchors* anchors)
 {
        struct trust_anchor* ta;
-       RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) {
+       struct trust_anchor* next;
+       size_t nods, nokey;
+       ta=(struct trust_anchor*)rbtree_first(anchors->tree);
+       while((rbnode_t*)ta != RBTREE_NULL) {
+               next = (struct trust_anchor*)rbtree_next(&ta->node);
                if(!anchors_assemble(anchors, ta)) {
                        log_err("out of memory");
                        return 0;
                }
-               if(!anchors_ds_is_supported(ta)) {
+               nods = anchors_ds_unsupported(ta);
+               nokey = anchors_dnskey_unsupported(ta);
+               if(nods) {
                        log_nametypeclass(0, "warning: unsupported "
                                "algorithm for trust anchor", 
                                ta->name, LDNS_RR_TYPE_DS, ta->dclass);
                }
-               if(!anchors_dnskey_is_supported(ta)) {
+               if(nokey) {
                        log_nametypeclass(0, "warning: unsupported "
                                "algorithm for trust anchor", 
                                ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
                }
+               if(nods == ta->numDS && nokey == ta->numDNSKEY) {
+                       char b[257];
+                       dname_str(ta->name, b);
+                       log_warn("trust anchor %s has no supported algorithms,"
+                               " the anchor is ignored", b);
+                       (void)rbtree_delete(anchors->tree, &ta->node);
+               }
+               ta = next;
        }
        return 1;
 }
@@ -946,8 +959,9 @@ anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
                        return 0;
                }
        }
-       init_parents(anchors);
+       /* first assemble, since it may delete useless anchors */
        anchors_assemble_rrsets(anchors);
+       init_parents(anchors);
        ldns_buffer_free(parsebuf);
        return 1;
 }
index 9f7a44372c6bf8b36717a6a5875f550a6997bd89..b10084b4c29f9f55d7fc3d2cf91aad7e0e3cbea2 100644 (file)
@@ -718,16 +718,15 @@ val_mark_indeterminate(struct reply_info* rep, struct val_anchors* anchors,
 }
 
 void 
-val_mark_insecure(struct reply_info* rep, struct key_entry_key* kkey,
+val_mark_insecure(struct reply_info* rep, uint8_t* kname,
        struct rrset_cache* r, struct module_env* env)
 {
        size_t i;
        struct packed_rrset_data* d;
-       log_assert(key_entry_isnull(kkey));
        for(i=0; i<rep->rrset_count; i++) {
                d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
                if(d->security == sec_status_unchecked &&
-                  dname_subdomain_c(rep->rrsets[i]->rk.dname, kkey->name)) {
+                  dname_subdomain_c(rep->rrsets[i]->rk.dname, kname)) {
                        /* mark as insecure */
                        d->security = sec_status_insecure;
                        rrset_update_sec_status(r, rep->rrsets[i], *env->now);
index c85f503925fcabec61ca0b3fb0db225fd2385631..027cb806a7dd81d4a077fa0338fd181ed4e1c076 100644 (file)
@@ -240,12 +240,11 @@ void val_mark_indeterminate(struct reply_info* rep,
  * Mark all unchecked rrset entries below a NULL key entry as insecure.
  * Only security==unchecked rrsets are updated.
  * @param rep: the reply with rrsets.
- * @param kkey: key entry, key_entry_isnull() for it. A key entry that marks
- *     the end of secure space into insecure space.
+ * @param kname: end of secure space name.
  * @param r: rrset cache to store updated security status into.
  * @param env: module environment
  */
-void val_mark_insecure(struct reply_info* rep, struct key_entry_key* kkey,
+void val_mark_insecure(struct reply_info* rep, uint8_t* kname,
        struct rrset_cache* r, struct module_env* env);
 
 /**
index a0e9527862db9b751f9dc5f6c9095ab946c35b82..2997663586bb15de3d9a24504518e1e47674901f 100644 (file)
@@ -1209,6 +1209,17 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
        else if(vq->key_entry == NULL || (vq->trust_anchor &&
                dname_strict_subdomain_c(vq->trust_anchor->name, 
                vq->key_entry->name))) {
+               /* trust anchor is an 'unsigned' trust anchor */
+               if(vq->trust_anchor && vq->trust_anchor->numDS == 0 &&
+                       vq->trust_anchor->numDNSKEY == 0) {
+                       vq->chase_reply->security = sec_status_insecure;
+                       val_mark_insecure(vq->chase_reply, 
+                               vq->trust_anchor->name, 
+                               qstate->env->rrset_cache, qstate->env);
+                       /* go to finished state to cache this result */
+                       vq->state = VAL_FINISHED_STATE;
+                       return 1;
+               }
                /* fire off a trust anchor priming query. */
                verbose(VERB_DETAIL, "prime trust anchor");
                if(!prime_trust_anchor(qstate, vq, id, vq->trust_anchor))
@@ -1222,7 +1233,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
                 * However, we do set the status to INSECURE, since it is 
                 * essentially proven insecure. */
                vq->chase_reply->security = sec_status_insecure;
-               val_mark_insecure(vq->chase_reply, vq->key_entry, 
+               val_mark_insecure(vq->chase_reply, vq->key_entry->name
                        qstate->env->rrset_cache, qstate->env);
                /* go to finished state to cache this result */
                vq->state = VAL_FINISHED_STATE;
@@ -1394,7 +1405,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
                verbose(VERB_DETAIL, "Verified that %sresponse is INSECURE",
                        vq->signer_name?"":"unsigned ");
                vq->chase_reply->security = sec_status_insecure;
-               val_mark_insecure(vq->chase_reply, vq->key_entry, 
+               val_mark_insecure(vq->chase_reply, vq->key_entry->name
                        qstate->env->rrset_cache, qstate->env);
                return 1;
        }