]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
dnssec lame detection.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 22 Oct 2007 15:25:37 +0000 (15:25 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 22 Oct 2007 15:25:37 +0000 (15:25 +0000)
git-svn-id: file:///svn/unbound/trunk@714 be551aaa-1e26-0410-a405-d3ace91eadb9

17 files changed:
Makefile.in
doc/Changelog
doc/requirements.txt
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c
iterator/iterator.h
testcode/testbound.c
testdata/iter_dnsseclame_ds.rpl [new file with mode: 0644]
testdata/iter_dnsseclame_ds_ok.rpl [new file with mode: 0644]
testdata/iter_dnsseclame_ta.rpl [new file with mode: 0644]
testdata/iter_dnsseclame_ta_ok.rpl [new file with mode: 0644]
util/module.h
validator/val_anchor.c
validator/val_anchor.h
validator/validator.c
validator/validator.h

index 08debb5a19a2cb4f92287e0a86bbb6487769f4c7..a5761694394421d4c339503f803c6c21275e29e8 100644 (file)
@@ -99,7 +99,7 @@ $(BUILD)%.o:    $(srcdir)/%.c
 
 all:   $(COMMON_OBJ) unbound unbound-checkconf
 
-tests: unittest testbound lock-verify pktview signit memstats
+tests: all unittest testbound lock-verify pktview signit memstats
 
 test:  tests
        bash testcode/do-tests.sh
index 4d1cd736928a3a0ed0587da1cb6cd3233b29e07f..1e1d53ee888674d8e1ac3b3fb077634e3ed0802a 100644 (file)
@@ -3,6 +3,11 @@
          out test cases.
        - ISO C compat changes.
        - detect RA-no-AA lameness, as LAME.
+       - DNSSEC-lameness detection, as LAME.
+         See notes in requirements.txt for choices made.
+       - tests for lameness detection.
+       - added all to make test target; need unbound for fwd tests.
+       - testbound does not pollute /etc/unbound.
 
 19 October 2007: Wouter
        - added configure (and its files) to svn, so that the trunk is easier
index fb2e4182d5df9c61836d3a67eff9b9fedc56a72b..6fb99dff14f548a7554c09621d5a521d16e26e18 100644 (file)
@@ -121,3 +121,22 @@ o The harden-glue feature, when yes all out of zone glue is deleted, when
   as more glue is present for the recursive service to use. The feature
   is implemented so as to minimise the security risk, while trying to 
   keep this performance gain.
+o The method by which dnssec-lameness is detected is not secure. DNSSEC lame
+  is when a server has the zone in question, but lacks dnssec data, such as
+  signatures. The method to detect dnssec lameness looks at nonvalidated 
+  data from the parent of a zone. This can be used, by spoofing the parent,
+  to create a false sense of dnssec-lameness in the child, or a false sense
+  or dnssec-non-lameness in the child. The first results in the server marked
+  lame, and not used for 900 seconds, and the second will result in a 
+  validator failure (SERVFAIL again), when the query is validated later on.
+
+  Concluding, a spoof of the parent delegation can be used for many cases
+  of denial of service. I.e. a completely different NS set could be returned,
+  or the information withheld. All of these alterations can be caught by
+  the validator if the parent is signed, and result in 900 seconds bogus. 
+  The dnssec-lameness detection is used to detect operator failures, 
+  before the validator will properly verify the messages.
+
+  Also for zones for which no chain of trust exists, but a DS is given by the
+  parent, dnssec-lameness detection enables. This delivers dnnsec to our 
+  clients when possible (for client validators).
index 1c2dc111485d768a285c4fad70fbb5810c5eb0d2..3787a9c0efa6a15afd2ba6bd04a5235cecc7f390 100644 (file)
@@ -58,6 +58,7 @@
 #include "util/data/dname.h"
 #include "util/random.h"
 #include "util/fptr_wlist.h"
+#include "validator/val_anchor.h"
 
 /** fillup fetch policy array */
 static void
@@ -367,3 +368,37 @@ iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp)
        }
        return 1;
 }
+
+int 
+iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
+        struct dns_msg* msg)
+{
+       /* information not available, !env->anchors can be common */
+       if(!env || !env->anchors || !dp || !dp->name || !msg || !msg->rep)
+               return 0;
+       /* a trust anchor exists with this name, RRSIGs expected */
+       if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
+               msg->qinfo.qclass))
+               return 1;
+       /* see if DS rrset was given, in AUTH section */
+       if(reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
+               LDNS_RR_TYPE_DS, msg->qinfo.qclass))
+               return 1;
+       return 0;
+}
+
+int 
+iter_msg_has_dnssec(struct dns_msg* msg)
+{
+       size_t i;
+       if(!msg || !msg->rep)
+               return 0;
+       for(i=0; i<msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) {
+               if(((struct packed_rrset_data*)msg->rep->rrsets[i]->
+                       entry.data)->rrsig_count > 0)
+                       return 1;
+       }
+       /* empty message has no DNSSEC info, with DNSSEC the reply is
+        * not empty (NSEC) */
+       return 0;
+}
index 8b0c1c83ea6ba31522a408b9d34d857f2717f23e..1ef4c42dcd5215f27d8b103be559d903c8d2fbff 100644 (file)
@@ -136,4 +136,26 @@ void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
  */
 int iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp);
 
+/**
+ * See if delegation is expected to have DNSSEC information (RRSIGs) in 
+ * its answers, or not. Inspects delegation point (name), trust anchors,
+ * and delegation message (DS RRset) to determine this.
+ * @param env: module env with trust anchors.
+ * @param dp: delegation point.
+ * @param msg: delegation message, with DS if a secure referral.
+ * @return 1 if dnssec is expected, 0 if not.
+ */
+int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
+       struct dns_msg* msg);
+
+/**
+ * See if a message contains DNSSEC.
+ * This is examined by looking for RRSIGs. With DNSSEC a valid answer, 
+ * nxdomain, nodata, referral or cname reply has RRSIGs in answer or auth 
+ * sections, sigs on answer data, SOA, DS, or NSEC/NSEC3 records.
+ * @param msg: message to examine.
+ * @return true if DNSSEC information was found.
+ */
+int iter_msg_has_dnssec(struct dns_msg* msg);
+
 #endif /* ITERATOR_ITER_UTILS_H */
index c6f2d2f140d491c26a85b255946b67d63042f6c6..cd8e3a3a96b14f586dcd61087c03845627c9fce8 100644 (file)
@@ -114,6 +114,7 @@ iter_new(struct module_qstate* qstate, int id)
        iq->referral_count = 0;
        iq->wait_priming_stub = 0;
        iq->refetch_glue = 0;
+       iq->dnssec_expected = 0;
        iq->chase_flags = qstate->query_flags;
        /* Start with the (current) qname. */
        iq->qchase = qstate->qinfo;
@@ -730,8 +731,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
        }
        while(1) {
                
-               /* Lookup the delegation in the cache. If null, then the cache needs 
-                * to be primed for the qclass. */
+               /* Lookup the delegation in the cache. If null, then the 
+                * cache needs to be primed for the qclass. */
                iq->dp = dns_cache_find_delegation(qstate->env, delname, 
                        delnamelen, iq->qchase.qtype, iq->qchase.qclass, 
                        qstate->region, &iq->deleg_msg, (uint32_t)time(NULL));
@@ -800,6 +801,11 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
        verbose(VERB_ALGO, "cache delegation returns delegpt");
        delegpt_log(VERB_ALGO, iq->dp);
 
+       /* if the cache reply dp equals a validation anchor or msg has DS,
+        * then DNSSEC RRSIGs are expected in the reply */
+       iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp, 
+               iq->deleg_msg);
+
        /* Reset the RD flag. If this is a query restart, then the RD 
         * will have been turned off. */
        if(qstate->query_flags & BIT_RD)
@@ -1186,6 +1192,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                 * differently. No queries should be sent elsewhere */
                type = RESPONSE_TYPE_ANSWER;
        }
+       if(!(iq->chase_flags&BIT_RD) && type != RESPONSE_TYPE_LAME && 
+               type != RESPONSE_TYPE_THROWAWAY && 
+               type != RESPONSE_TYPE_UNTYPED && iq->dnssec_expected) {
+               /* a possible answer, see if it is missing DNSSEC */
+               /* but not when forwarding, so we dont mark fwder lame */
+               if(!iter_msg_has_dnssec(iq->response))
+                       type = RESPONSE_TYPE_LAME;
+       }
 
        /* handle each of the type cases */
        if(type == RESPONSE_TYPE_ANSWER) {
@@ -1225,6 +1239,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                delegpt_log(VERB_ALGO, iq->dp);
                /* Count this as a referral. */
                iq->referral_count++;
+               /* see if the next dp is a trust anchor, or a DS was sent
+                * along, indicating dnssec is expected for next zone */
+               iq->dnssec_expected = iter_indicates_dnssec(qstate->env, 
+                       iq->dp, iq->response);
 
                /* stop current outstanding queries. 
                 * FIXME: should the outstanding queries be waited for and
@@ -1264,6 +1282,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                /* Clear the query state, since this is a query restart. */
                iq->deleg_msg = NULL;
                iq->dp = NULL;
+               iq->dnssec_expected = 0;
                /* Note the query restart. */
                iq->query_restart_count++;
 
index 16ddbb45ab491a0fc368fd18b00bf4f9cd828176..eeaf720ea3d3ea918faaacddbdd62031b61bfba6 100644 (file)
@@ -225,6 +225,13 @@ struct iter_qstate {
        /** the number of times this query as followed a referral. */
        int referral_count;
 
+       /** 
+        * expected dnssec information for this iteration step. 
+        * If dnssec rrsigs are expected and not given, the server is marked
+        * lame (dnssec-lame).
+        */
+       int dnssec_expected;
+
        /**
         * This is flag that, if true, means that this event is 
         * waiting for a stub priming query. 
index f20e89c8061cc0b99f66da8df69cebb422761458..6a45a74ecc1b3fb0f7dad901ed248e8682f85cb4 100644 (file)
@@ -135,7 +135,9 @@ setup_config(FILE* in, char* configfile, int* lineno,
        if(!cfg) fatal_exit("could not open %s: %s", 
                        configfile, strerror(errno));
        line[MAX_LINE_LEN-1] = 0;
+       /* some basic settings to not pollute the host system */
        fprintf(cfg, "server:   use-syslog: no\n");
+       fprintf(cfg, "          directory: \"\"\n");
        while(fgets(line, MAX_LINE_LEN-1, in)) {
                parse = line;
                (*lineno)++;
diff --git a/testdata/iter_dnsseclame_ds.rpl b/testdata/iter_dnsseclame_ds.rpl
new file mode 100644 (file)
index 0000000..cf4ad3d
--- /dev/null
@@ -0,0 +1,298 @@
+; config options
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       val-override-date: "20070916134226"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at ds point.
+
+; 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.sub.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
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.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
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A   1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com.        3600    IN      DNSKEY  256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com.        3600    IN      RRSIG   DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+; no NS set. not needed for this test.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com.     3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A       11.11.11.11
+www.sub.example.com.    3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; fine DNSKEY response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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 DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{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}
+ENTRY_END
+
+; correct delegation with DS
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com.        3600    IN      RRSIG   DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION 
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com.        3600    IN      RRSIG   DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; This server is DNSSEC LAME!
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+        ADDRESS 1.2.3.6
+
+; response to DNSKEY priming query
+; sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com.        3600    IN      DNSKEY  256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+SECTION AUTHORITY
+sub.example.com. IN     NS ns.sub.example.com.
+sub.example.com. IN     NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A       11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A       11.11.11.11
+www.sub.example.com.    3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_dnsseclame_ds_ok.rpl b/testdata/iter_dnsseclame_ds_ok.rpl
new file mode 100644 (file)
index 0000000..15b8926
--- /dev/null
@@ -0,0 +1,293 @@
+; config options
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       val-override-date: "20070916134226"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at ds point, which is ok.
+
+; 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.sub.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
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.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
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A   1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com.        3600    IN      DNSKEY  256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com.        3600    IN      RRSIG   DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+; no NS set. not needed for this test.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com.     3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A       11.11.11.11
+www.sub.example.com.    3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; fine DNSKEY response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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 DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{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}
+ENTRY_END
+
+; correct delegation with DS
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com.        3600    IN      RRSIG   DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION 
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com.        3600    IN      RRSIG   DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; server is not DNSSEC lame.
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+        ADDRESS 1.2.3.6
+
+; response to DNSKEY priming query
+; sub.example.com.        3600    IN      DS      30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com.        3600    IN      DNSKEY  256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com.        3600    IN      RRSIG   DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A       11.11.11.11
+www.sub.example.com.    3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+RANGE_END
+
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A       11.11.11.11
+www.sub.example.com.    3600    IN      RRSIG   A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_dnsseclame_ta.rpl b/testdata/iter_dnsseclame_ta.rpl
new file mode 100644 (file)
index 0000000..3e578f4
--- /dev/null
@@ -0,0 +1,229 @@
+; config options
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       val-override-date: "20070916134226"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at anchor point.
+
+; 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
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.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
+www.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+; this entry; glue will make unbound take this reference first.
+; it is however, the lame server.
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A   1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; lame DNSKEY response.
+; here without sigs (assuming server does unknown-RR type handling)
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+ENTRY_END
+
+; the lame response. No RRSIGS.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; the wrong answer.
+www.example.com. IN A  10.20.30.40
+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 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO 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}
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_dnsseclame_ta_ok.rpl b/testdata/iter_dnsseclame_ta_ok.rpl
new file mode 100644 (file)
index 0000000..bc5b062
--- /dev/null
@@ -0,0 +1,227 @@
+; config options
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       val-override-date: "20070916134226"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection with anchor point that is ok.
+
+; 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
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.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
+www.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A   1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A   1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; the response is not lame at all.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+ENTRY_END
+
+; response is not lame.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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}
+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 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO 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}
+ENTRY_END
+
+SCENARIO_END
index 47b8ec10cd3a0756b7785107649dc8f20807c1a9..a70306a1e6d28b06ab14ea0853724eb766cec2ee 100644 (file)
@@ -194,6 +194,11 @@ struct module_env {
        /** is validation required for messages, controls client-facing
         * validation status (AD bits) and servfails */
        int need_to_validate;
+       /** trusted key storage; these are the configured keys, if not NULL,
+        * otherwise configured by validator. These are the trust anchors,
+        * and are not primed and ready for validation, but on the bright
+        * side, they are read only memory, thus no locks and fast. */
+       struct val_anchors* anchors;
        /** module specific data. indexed by module id. */
        void* modinfo[MAX_MODULE];
 };
index 150476b4b1811b0d3ff79af8b8bd86eef24385c8..4e5ab472338cfbeeb4f0bd8a11adbc2c0831df95 100644 (file)
@@ -121,16 +121,7 @@ init_parents(struct val_anchors* anchors)
        }
 }
 
-/**
- * Find a trust anchor. Exact matching.
- * @param anchors: anchor storage.
- * @param name: name of trust anchor (wireformat)
- * @param namelabs: labels in name
- * @param namelen: length of name
- * @param dclass: class of trust anchor
- * @return NULL if not found.
- */
-static struct trust_anchor*
+struct trust_anchor*
 anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs,
        size_t namelen, uint16_t dclass)
 {
index 2a9db472bc4a5bea73f8edde4a4df24ccdc81fb6..2032d6984ddfb95e768e00527c4064ad6991c38f 100644 (file)
@@ -141,6 +141,18 @@ int anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg);
 struct trust_anchor* anchors_lookup(struct val_anchors* anchors,
        uint8_t* qname, size_t qname_len, uint16_t qclass);
 
+/**
+ * Find a trust anchor. Exact matching.
+ * @param anchors: anchor storage.
+ * @param name: name of trust anchor (wireformat)
+ * @param namelabs: labels in name
+ * @param namelen: length of name
+ * @param dclass: class of trust anchor
+ * @return NULL if not found.
+ */
+struct trust_anchor* anchor_find(struct val_anchors* anchors, 
+       uint8_t* name, int namelabs, size_t namelen, uint16_t dclass);
+
 /**
  * Store one string as trust anchor RR.
  * @param anchors: anchor storage.
index 99b6f8a6f4063fad0130466233f53817be450e52..ac4f6275c10d151cb5d7b370b461432594e7c66c 100644 (file)
@@ -97,15 +97,16 @@ fill_nsec3_iter(struct val_env* ve, char* s, int c)
 
 /** apply config settings to validator */
 static int
-val_apply_cfg(struct val_env* val_env, struct config_file* cfg)
+val_apply_cfg(struct module_env* env, struct val_env* val_env, 
+       struct config_file* cfg)
 {
        int c;
        val_env->bogus_ttl = (uint32_t)cfg->bogus_ttl;
        val_env->clean_additional = cfg->val_clean_additional;
        val_env->permissive_mode = cfg->val_permissive_mode;
-       if(!val_env->anchors)
-               val_env->anchors = anchors_create();
-       if(!val_env->anchors) {
+       if(!env->anchors)
+               env->anchors = anchors_create();
+       if(!env->anchors) {
                log_err("out of memory");
                return 0;
        }
@@ -115,7 +116,7 @@ val_apply_cfg(struct val_env* val_env, struct config_file* cfg)
                log_err("out of memory");
                return 0;
        }
-       if(!anchors_apply_cfg(val_env->anchors, cfg)) {
+       if(!anchors_apply_cfg(env->anchors, cfg)) {
                log_err("validator: error in trustanchors config");
                return 0;
        }
@@ -146,7 +147,7 @@ val_init(struct module_env* env, int id)
        env->modinfo[id] = (void*)val_env;
        env->need_to_validate = 1;
        val_env->permissive_mode = 0;
-       if(!val_apply_cfg(val_env, env->cfg)) {
+       if(!val_apply_cfg(env, val_env, env->cfg)) {
                log_err("validator: could not apply configuration settings.");
                return 0;
        }
@@ -160,7 +161,7 @@ val_deinit(struct module_env* env, int id)
        if(!env || !env->modinfo || !env->modinfo[id])
                return;
        val_env = (struct val_env*)env->modinfo[id];
-       anchors_delete(val_env->anchors);
+       anchors_delete(env->anchors);
        key_cache_delete(val_env->kcache);
        free(val_env->nsec3_keysize);
        free(val_env->nsec3_maxiter);
@@ -1114,13 +1115,13 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
                }
        }
 
-       val_mark_indeterminate(vq->chase_reply, ve->anchors, 
+       val_mark_indeterminate(vq->chase_reply, qstate->env->anchors, 
                qstate->env->rrset_cache);
        vq->key_entry = NULL;
        vq->empty_DS_name = NULL;
        vq->ds_rrset = 0;
-       vq->trust_anchor = anchors_lookup(ve->anchors, vq->qchase.qname,
-               vq->qchase.qname_len, vq->qchase.qclass);
+       vq->trust_anchor = anchors_lookup(qstate->env->anchors, 
+               vq->qchase.qname, vq->qchase.qname_len, vq->qchase.qclass);
        if(vq->trust_anchor == NULL) {
                /*response isn't under a trust anchor, so we cannot validate.*/
                vq->chase_reply->security = sec_status_indeterminate;
@@ -2078,7 +2079,7 @@ val_get_mem(struct module_env* env, int id)
        if(!ve)
                return 0;
        return sizeof(*ve) + key_cache_get_mem(ve->kcache) + 
-               anchors_get_mem(ve->anchors) + 
+               anchors_get_mem(env->anchors) + 
                sizeof(size_t)*2*ve->nsec3_keyiter_count;
 }
 
index cb18e9b412f4320c7b99e7eb27c9e8eeea4f6334..8369aa76a792460ce16040013b6aeabd676d776c 100644 (file)
@@ -59,9 +59,6 @@ struct key_entry_key;
  * Global state for the validator. 
  */
 struct val_env {
-       /** trusted key storage; these are the configured keys */
-       struct val_anchors* anchors;
-
        /** key cache; these are validated keys. trusted keys only
         * end up here after being primed. */
        struct key_cache* kcache;