]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix validation failure for parent and child on same server with an
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 29 Oct 2010 13:10:26 +0000 (13:10 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 29 Oct 2010 13:10:26 +0000 (13:10 +0000)
  insecure childzone and a CNAME from parent to child.

git-svn-id: file:///svn/unbound/trunk@2321 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testdata/val_cnametonsec.rpl [new file with mode: 0644]
testdata/val_cnametooptin.rpl [new file with mode: 0644]
testdata/val_nodata_zonecut.rpl
validator/val_nsec.c
validator/val_nsec.h
validator/val_nsec3.c
validator/validator.c

index 87a1f1ac27d24b8d7a101706c5188c7154e091eb..32522a8eb5d08ada03536dcca7e9eb7a31da0723 100644 (file)
@@ -1,5 +1,7 @@
 27 October 2010: Wouter
        - Fix uninit value in dump_infra print.
+       - Fix validation failure for parent and child on same server with an
+         insecure childzone and a CNAME from parent to child.
 
 26 October 2010: Wouter
        - dump_infra and flush_infra commands for unbound-control.
diff --git a/testdata/val_cnametonsec.rpl b/testdata/val_cnametonsec.rpl
new file mode 100644 (file)
index 0000000..9e54909
--- /dev/null
@@ -0,0 +1,158 @@
+; config options
+; The island of trust is at example.com
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 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 CNAME to insecure NSEC delegation
+
+; 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 CNAME www.sub.example.com.
+www.example.com.       3600    IN      RRSIG   CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854}
+SECTION AUTHORITY
+sub.example.com. IN NSEC zzz.example.com. NS
+sub.example.com.       3600    IN      RRSIG   NSEC 3 3 3600 20070926134802 20070829134802 2854 example.com. AJPvjSrqGbe3ZBOxV9J3XyFeOqrcPfIYPIWnlmj6G+PebJdAkvwIu9o= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+; this server also serves the zone sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. IN SOA a. b. 1 2 3 4 5
+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 CNAME www.sub.example.com.
+www.example.com.       3600    IN      RRSIG   CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854}
+SECTION AUTHORITY
+sub.example.com. IN NSEC zzz.example.com. NS
+sub.example.com.       3600    IN      RRSIG   NSEC 3 3 3600 20070926134802 20070829134802 2854 example.com. AJPvjSrqGbe3ZBOxV9J3XyFeOqrcPfIYPIWnlmj6G+PebJdAkvwIu9o= ;{id = 2854}
+sub.example.com. IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/val_cnametooptin.rpl b/testdata/val_cnametooptin.rpl
new file mode 100644 (file)
index 0000000..657dcd1
--- /dev/null
@@ -0,0 +1,162 @@
+; config options
+; The island of trust is at example.com
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 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 CNAME to insecure optin NSEC3
+
+; 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 CNAME www.sub.example.com.
+www.example.com.       3600    IN      RRSIG   CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854}
+SECTION AUTHORITY
+; NSEC3PARAM 1 0 1 -
+; example.com. -> 9vq38lj9qs6s1aruer131mbtsfnvek2p.
+; sub.example.com. -> 7t1ect6t5vp0s7se8si9d07roqupr3gc.
+; www.example.com. -> 0lverorlcjoa2lji5rik0otij3lgoj3l.
+7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com. IN NSEC3 1 0 1 - 7t1ect6t5vp0s7se8si9d07roqupr3gd NS
+7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com.  3600    IN      RRSIG   NSEC3 3 3 3600 20070926134802 20070829134802 2854 example.com. AIiTSxI4hTDiDzo+bMaOKSvjIyoChgjY19y2NQG/Mtt80sNbDBY126I= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+; this server also serves the zone sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. IN SOA a. b. 1 2 3 4 5
+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 CNAME www.sub.example.com.
+www.example.com.       3600    IN      RRSIG   CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854}
+SECTION AUTHORITY
+7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com. IN NSEC3 1 0 1 - 7t1ect6t5vp0s7se8si9d07roqupr3gd NS
+7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com.  3600    IN      RRSIG   NSEC3 3 3 3600 20070926134802 20070829134802 2854 example.com. AIiTSxI4hTDiDzo+bMaOKSvjIyoChgjY19y2NQG/Mtt80sNbDBY126I= ;{id = 2854}
+sub.example.com. IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+SCENARIO_END
index 49b52c0fd45b4f89e588a572b0c2831b280686a2..e9e50a7ce603a733aa25ed36996a53c789c53a65 100644 (file)
@@ -131,8 +131,8 @@ SECTION AUTHORITY
 ; SOA record is missing in reply.
 ; Denies A, note this is the end of the NSEC chain.
 ; from wrong side of zone-cut
-www.example.com.       IN      NSEC    example.com. NS RRSIG NSEC
-www.example.com.        3600    IN      RRSIG   NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFCQcnUp3juEjo72FpC82jFwZ2DStAhQpwpdMvEycW2elKfxpDdIHlT5ERg== ;{id = 2854}
+www.example.com.       3600    IN      NSEC    example.com. NS DS RRSIG NSEC 
+www.example.com.       3600    IN      RRSIG   NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. AA+3mzAYPyQ8G9EKxeyNM+UZY+RtCiS5BOkS8h4wSxMT3lfVdadGpn8= ;{id = 2854}
 SECTION ADDITIONAL
 ENTRY_END
 RANGE_END
index d6b2ed07cfbc64c5f8a8fd405310fb9d5dd1edaa..75574ffb1ab44e402e3a49c37199c834ea39b726 100644 (file)
@@ -425,6 +425,27 @@ val_nsec_proves_name_error(struct ub_packed_rrset_key* nsec, uint8_t* qname)
        return 0;
 }
 
+int val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec, 
+       struct query_info* qinfo)
+{
+       if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) &&
+               !nsec_has_type(nsec, LDNS_RR_TYPE_DS) &&
+               !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) {
+               /* see if nsec signals an insecure delegation */
+               if(qinfo->qtype == LDNS_RR_TYPE_DS) {
+                       /* if type is DS and qname is equal to nsec, then it
+                        * is an exact match nsec, result not insecure */
+                       if(dname_strict_subdomain_c(qinfo->qname,
+                               nsec->rk.dname))
+                               return 1;
+               } else {
+                       if(dname_subdomain_c(qinfo->qname, nsec->rk.dname))
+                               return 1;
+               }
+       }
+       return 0;
+}
+
 uint8_t* 
 nsec_closest_encloser(uint8_t* qname, struct ub_packed_rrset_key* nsec)
 {
index 659edc2ff9b5cc36662b54e6b1ae48c08f950404..34f7f63b40efec601f87b6c188e2ee0e3cd3c48c 100644 (file)
@@ -169,4 +169,14 @@ int val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname,
 int val_nsec_check_dlv(struct query_info* qinfo,
        struct reply_info* rep, uint8_t** nm, size_t* nm_len);
 
+/**
+ * Determine if an nsec proves an insecure delegation towards the qname.
+ * @param nsec: nsec rrset.
+ * @param qinfo: what was queries for.
+ * @return 0 if not, 1 if an NSEC that signals an insecure delegation to
+ *     the qname.
+ */
+int val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec,
+        struct query_info* qinfo);
+
 #endif /* VALIDATOR_VAL_NSEC_H */
index e966ca7bf21e4bada951f6be54fd25e3cf915806..be99d9832ce777aa078719470af18b732e4b430b 100644 (file)
@@ -935,10 +935,12 @@ next_closer(uint8_t* qname, size_t qnamelen, uint8_t* ce,
  *     If set true, and the return value is true, then you can be 
  *     certain that the ce.nc_rrset and ce.nc_rr are set properly.
  * @param ce: closest encloser information is returned in here.
- * @return false if no closest encloser could be proven.
- *     true if a closest encloser could be proven, ce is set.
+ * @return bogus if no closest encloser could be proven.
+ *     secure if a closest encloser could be proven, ce is set.
+ *     insecure if the closest-encloser candidate turns out to prove
+ *             that an insecure delegation exists above the qname.
  */
-static int
+static enum sec_status
 nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt, 
        rbtree_t* ct, struct query_info* qinfo, int prove_does_not_exist,
        struct ce_response* ce)
@@ -951,7 +953,7 @@ nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
        if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce)) {
                verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could "
                        "not find a candidate for the closest encloser.");
-               return 0;
+               return sec_status_bogus;
        }
        log_nametypeclass(VERB_ALGO, "ce candidate", ce->ce, 0, 0);
 
@@ -959,11 +961,11 @@ nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
                if(prove_does_not_exist) {
                        verbose(VERB_ALGO, "nsec3 proveClosestEncloser: "
                                "proved that qname existed, bad");
-                       return 0;
+                       return sec_status_bogus;
                }
                /* otherwise, we need to nothing else to prove that qname 
                 * is its own closest encloser. */
-               return 1;
+               return sec_status_secure;
        }
 
        /* If the closest encloser is actually a delegation, then the 
@@ -971,14 +973,19 @@ nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
         * it should have been a DNAME response. */
        if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_NS) &&
                !nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_SOA)) {
+               if(!nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DS)) {
+                       verbose(VERB_ALGO, "nsec3 proveClosestEncloser: "
+                               "closest encloser is insecure delegation");
+                       return sec_status_insecure;
+               }
                verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest "
                        "encloser was a delegation, bad");
-               return 0;
+               return sec_status_bogus;
        }
        if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DNAME)) {
                verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest "
                        "encloser was a DNAME, bad");
-               return 0;
+               return sec_status_bogus;
        }
        
        /* Otherwise, we need to show that the next closer name is covered. */
@@ -987,9 +994,9 @@ nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
                &ce->nc_rrset, &ce->nc_rr)) {
                verbose(VERB_ALGO, "nsec3: Could not find proof that the "
                          "candidate encloser was the closest encloser");
-               return 0;
+               return sec_status_bogus;
        }
-       return 1;
+       return sec_status_secure;
 }
 
 /** allocate a wildcard for the closest encloser */
@@ -1022,14 +1029,19 @@ nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
        size_t wclen;
        struct ub_packed_rrset_key* wc_rrset;
        int wc_rr;
+       enum sec_status sec;
 
        /* First locate and prove the closest encloser to qname. We will 
         * use the variant that fails if the closest encloser turns out 
         * to be qname. */
-       if(!nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce)) {
-               verbose(VERB_ALGO, "nsec3 nameerror proof: failed to prove "
-                       "a closest encloser");
-               return sec_status_bogus;
+       sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce);
+       if(sec != sec_status_secure) {
+               if(sec == sec_status_bogus)
+                       verbose(VERB_ALGO, "nsec3 nameerror proof: failed "
+                               "to prove a closest encloser");
+               else    verbose(VERB_ALGO, "nsec3 nameerror proof: closest "
+                               "nsec3 is an insecure delegation");
+               return sec;
        }
        log_nametypeclass(VERB_ALGO, "nsec3 namerror: proven ce=", ce.ce,0,0);
 
@@ -1082,6 +1094,7 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
        size_t wclen;
        struct ub_packed_rrset_key* rrset;
        int rr;
+       enum sec_status sec;
 
        if(find_matching_nsec3(env, flt, ct, qinfo->qname, qinfo->qname_len, 
                &rrset, &rr)) {
@@ -1126,10 +1139,15 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
        /* For cases 3 - 5, we need the proven closest encloser, and it 
         * can't match qname. Although, at this point, we know that it 
         * won't since we just checked that. */
-       if(!nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce)) {
+       sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce);
+       if(sec == sec_status_bogus) {
                verbose(VERB_ALGO, "proveNodata: did not match qname, "
                          "nor found a proven closest encloser.");
                return sec_status_bogus;
+       } else if(sec==sec_status_insecure && qinfo->qtype!=LDNS_RR_TYPE_DS){
+               verbose(VERB_ALGO, "proveNodata: closest nsec3 is insecure "
+                         "delegation.");
+               return sec_status_insecure;
        }
 
        /* Case 3: removed */
@@ -1327,7 +1345,10 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
        }
 
        /* Otherwise, we are probably in the opt-out case. */
-       if(!nsec3_prove_closest_encloser(env, &flt, &ct, qinfo, 1, &ce)) {
+       if(nsec3_prove_closest_encloser(env, &flt, &ct, qinfo, 1, &ce)
+               != sec_status_secure) {
+               /* an insecure delegation *above* the qname does not prove
+                * anything about this qname exactly, and bogus is bogus */
                verbose(VERB_ALGO, "nsec3 provenods: did not match qname, "
                          "nor found a proven closest encloser.");
                *reason = "no NSEC3 closest encloser";
@@ -1372,7 +1393,8 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
        /* try nxdomain and nodata after another, while keeping the
         * hash cache intact */
 
-       if(nsec3_do_prove_nameerror(env, &flt, &ct, qinfo)==sec_status_secure)
+       sec = nsec3_do_prove_nameerror(env, &flt, &ct, qinfo);
+       if(sec==sec_status_secure)
                return sec_status_secure;
        sec = nsec3_do_prove_nodata(env, &flt, &ct, qinfo);
        if(sec==sec_status_secure) {
index 635058388d7dd0b51366723b750d11af067b28a0..cfce63c8ec005972610853a10266f120f9c06885 100644 (file)
@@ -695,6 +695,11 @@ validate_nodata_response(struct module_env* env, struct val_env* ve,
                        if(val_nsec_proves_name_error(s, qchase->qname)) {
                                ce = nsec_closest_encloser(qchase->qname, s);
                        }
+                       if(val_nsec_proves_insecuredelegation(s, qchase)) {
+                               verbose(VERB_ALGO, "delegation is insecure");
+                               chase_reply->security = sec_status_insecure;
+                               return;
+                       }
                } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
                        nsec3s_seen = 1;
                }
@@ -773,6 +778,11 @@ validate_nameerror_response(struct module_env* env, struct val_env* ve,
                        if(val_nsec_proves_no_wc(s, qchase->qname, 
                                qchase->qname_len))
                                has_valid_wnsec = 1;
+                       if(val_nsec_proves_insecuredelegation(s, qchase)) {
+                               verbose(VERB_ALGO, "delegation is insecure");
+                               chase_reply->security = sec_status_insecure;
+                               return;
+                       }
                } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3)
                        nsec3s_seen = 1;
        }
@@ -1116,6 +1126,11 @@ validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
                        if(val_nsec_proves_no_wc(s, qchase->qname, 
                                qchase->qname_len))
                                nxdomain_valid_wnsec = 1;
+                       if(val_nsec_proves_insecuredelegation(s, qchase)) {
+                               verbose(VERB_ALGO, "delegation is insecure");
+                               chase_reply->security = sec_status_insecure;
+                               return;
+                       }
                } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
                        nsec3s_seen = 1;
                }