]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
layer/validate: layer is issuing requests for missing DS records
authorKarel Slany <karel.slany@nic.cz>
Thu, 30 Jul 2015 14:06:04 +0000 (16:06 +0200)
committerKarel Slany <karel.slany@nic.cz>
Thu, 30 Jul 2015 14:06:04 +0000 (16:06 +0200)
lib/layer/iterate.c
lib/layer/rrcache.c
lib/layer/validate.c
lib/resolve.c
lib/rplan.h
lib/zonecut.c
lib/zonecut.h
tests/testdata/iter_validate_child_zone.rpl [new file with mode: 0644]

index fb4e38c6a58b3e39a5914c6a88067bc1b680ee37..02f851430ab048cf3e92ac59ae64d3d9e00d22b2 100644 (file)
@@ -193,6 +193,8 @@ static int update_cut(knot_pkt_t *pkt, const knot_rrset_t *rr, struct kr_request
 
        /* Update zone cut name */
        if (!knot_dname_is_equal(rr->owner, cut->name)) {
+               mm_free(cut->pool, cut->parent_name);
+               cut->parent_name = cut->name; cut->name = NULL;
                kr_zonecut_set(cut, rr->owner);
                state = KNOT_STATE_DONE;
        }
index 6710c0ea6d7c0546e7d1caa14aad08645a421f36..0defa46c33630c72f957c1a29537517617577a8b 100644 (file)
@@ -243,7 +243,7 @@ static int stash_add(const knot_pkt_t *pkt, map_t *stash, const knot_rrset_t *rr
        if (ret <= 0 || ret >= KNOT_DNAME_MAXLEN) {
                return kr_error(EILSEQ);
        }
-       
+
        /* Check if already exists */
        knot_rrset_t *stashed = map_get(stash, key);
        if (!stashed) {
index 39216a05e1db90af98fd68f8f23fa06b0965bf06..7a3f66442b7485c71c68b493766b41c5101ece1a 100644 (file)
 #include <libknot/internal/base64.h>
 #include <libknot/rrtype/rdname.h>
 #include <libknot/rrtype/dnskey.h>
+#include <libknot/rrtype/rrsig.h>
 
 #include "lib/dnssec.h"
 #include "lib/layer/iterate.h"
+#include "lib/layer/validate.h"
 #include "lib/resolve.h"
 #include "lib/rplan.h"
 #include "lib/defines.h"
@@ -626,6 +628,43 @@ static int validate_keyset(struct kr_query *qry, knot_pkt_t *answer)
        return kr_ok();
 }
 
+static const knot_dname_t *section_first_signer_name(knot_pkt_t *pkt, knot_section_t section_id)
+{
+       const knot_dname_t *sname = NULL;
+       const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+       if (!sec) {
+               return sname;
+       }
+
+       for (unsigned i = 0; i < sec->count; ++i) {
+               const knot_rrset_t *rr = knot_pkt_rr(sec, i);
+               if (rr->type != KNOT_RRTYPE_RRSIG) {
+                       continue;
+               }
+
+               sname = knot_rrsig_signer_name(&rr->rrs, 0);
+               break;
+       }
+
+       return sname;
+}
+
+static const knot_dname_t *first_rrsig_signer_name(knot_pkt_t *answer)
+{
+       const knot_dname_t *ans_sname = section_first_signer_name(answer, KNOT_ANSWER);
+       const knot_dname_t *auth_sname = section_first_signer_name(answer, KNOT_AUTHORITY);
+
+       if (!ans_sname) {
+               return auth_sname;
+       } else if (!auth_sname) {
+               return ans_sname;
+       } else if (knot_dname_is_equal(ans_sname, auth_sname)) {
+               return ans_sname;
+       } else {
+               return NULL;
+       }
+}
+
 static int update_delegation(struct kr_query *qry, knot_pkt_t *answer)
 {
        int ret = kr_ok();
@@ -635,11 +674,13 @@ static int update_delegation(struct kr_query *qry, knot_pkt_t *answer)
 
        /* New trust anchor. */
        knot_rrset_t *new_ds = NULL;
-       const knot_pktsection_t *sec = knot_pkt_section(answer, KNOT_AUTHORITY);
+       knot_section_t section_id = (knot_pkt_qtype(answer) == KNOT_RRTYPE_DS) ? KNOT_ANSWER : KNOT_AUTHORITY;
+       const knot_pktsection_t *sec = knot_pkt_section(answer, section_id);
        for (unsigned i = 0; i < sec->count; ++i) {
                const knot_rrset_t *rr = knot_pkt_rr(sec, i);
                if ((rr->type != KNOT_RRTYPE_DS) ||
-                   (knot_dname_cmp(rr->owner, cut->name) != 0)) {
+                   (0)) {
+//                 (knot_dname_cmp(rr->owner, cut->name) != 0)) {
                        continue;
                }
                if (new_ds) {
@@ -702,6 +743,22 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
                }
        }
 
+       /* Check whether the current zone cut holds keys that can be used
+        * for validation (i.e. RRSIG signer name matches key owner).
+        */
+       const knot_dname_t *key_own = qry->zone_cut.key ? qry->zone_cut.key->owner : NULL;
+       const knot_dname_t *sig_name = first_rrsig_signer_name(pkt);
+       if (key_own && sig_name && !knot_dname_is_equal(key_own, sig_name)) {
+               mm_free(qry->zone_cut.pool, qry->zone_cut.missing_name);
+               qry->zone_cut.missing_name = knot_dname_copy(sig_name, qry->zone_cut.pool);
+               if (!qry->zone_cut.missing_name) {
+                       return KNOT_STATE_FAIL;
+               }
+               qry->flags |= QUERY_AWAIT_DS;
+               qry->flags &= ~QUERY_RESOLVED;
+               return KNOT_STATE_CONSUME;
+       }
+
        /* Check if this is a DNSKEY answer, check trust chain and store. */
        uint16_t qtype = knot_pkt_qtype(pkt);
        if (qtype == KNOT_RRTYPE_DNSKEY) {
@@ -730,18 +787,23 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
        }
 
        /* Update trust anchor. */
-       if (qtype == KNOT_RRTYPE_NS) {
-               ret = update_delegation(qry, pkt);
-               if (ret != 0) {
-                       return KNOT_STATE_FAIL;
-               }
+       ret = update_delegation(qry, pkt);
+       if (ret != 0) {
+               return KNOT_STATE_FAIL;
+       }
 
-               if (!qry->zone_cut.key) {
-                       DEBUG_MSG("<= missing keys for new cut\n");
-#warning TODO: set QUERY_AWAIT_CUT for next query in plan ?
+       if ((qtype == KNOT_RRTYPE_DS) && (qry->parent != NULL) && (qry->parent->zone_cut.trust_anchor == NULL)) {
+               DEBUG_MSG("updating trust anchor in zone cut\n");
+               qry->parent->zone_cut.trust_anchor = knot_rrset_copy(qry->zone_cut.trust_anchor, qry->parent->zone_cut.pool);
+               if (!qry->parent->zone_cut.trust_anchor) {
+                       return KNOT_STATE_FAIL;
                }
+               /* Update zone cut name */
+               mm_free(qry->parent->zone_cut.pool, qry->parent->zone_cut.name);
+               qry->parent->zone_cut.name = knot_dname_copy(qry->zone_cut.trust_anchor->owner, qry->parent->zone_cut.pool);
        }
        if ((qtype == KNOT_RRTYPE_DNSKEY) && (qry->parent != NULL) && (qry->parent->zone_cut.key == NULL)) {
+               DEBUG_MSG("updating keys in zone cut\n");
                qry->parent->zone_cut.key = knot_rrset_copy(qry->zone_cut.key, qry->parent->zone_cut.pool);
                if (!qry->parent->zone_cut.key) {
                        return KNOT_STATE_FAIL;
index 03c76efe9462b63a2d185f18e54f3208310055e6..965ad5a9cc4e29cbdf9d98ded091743e0070ea23 100644 (file)
@@ -504,6 +504,28 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
                qry->flags &= ~QUERY_AWAIT_CUT;
        }
 
+       /* fetch missing DS record. */
+       if ((qry->flags & QUERY_AWAIT_DS) && (qry->zone_cut.missing_name)) {
+               struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.missing_name, KNOT_CLASS_IN, KNOT_RRTYPE_DS);
+               if (!next) {
+                       return KNOT_STATE_FAIL;
+               }
+               kr_zonecut_set(&next->zone_cut, qry->zone_cut.parent_name);
+               int ret = kr_zonecut_copy(&next->zone_cut, &qry->zone_cut);
+               if (ret != 0) {
+                       return KNOT_STATE_FAIL;
+               }
+               ret = kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+               if (ret != 0) {
+                       return KNOT_STATE_FAIL;
+               }
+               /* The current trust anchor and keys cannot be used. */
+               knot_rrset_free(&qry->zone_cut.key, qry->zone_cut.pool);
+               knot_rrset_free(&qry->zone_cut.trust_anchor, qry->zone_cut.pool);
+               qry->flags &= ~QUERY_AWAIT_DS;
+               return KNOT_STATE_PRODUCE;
+       }
+
        /* Try to fetch missing DNSKEY. */
        if (want_secured && !qry->zone_cut.key && qry->stype != KNOT_RRTYPE_DNSKEY) {
                struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
index 214f8f1bf4e48c032a084bd3d4dec86abdb1913d..f317fd6174d8a036bde247bce596536448b821d7 100644 (file)
@@ -39,7 +39,8 @@
        X(EXPIRING   , 1 << 9) /**< Query response is cached, but expiring. */ \
        X(NO_EXPIRING, 1 << 10) /**< Do not use expiring cached records. */ \
        X(DNSSEC_WANT , 1 << 11) /**< Want DNSSEC secured answer. */ \
-       X(DNSSEC_BOGUS , 1 << 12) /**< Query response is DNSSEC bogus. */
+       X(DNSSEC_BOGUS , 1 << 12) /**< Query response is DNSSEC bogus. */ \
+       X(AWAIT_DS   , 1 << 13) /**< Query is waiting for DS lookup. */
 
 /** Query flags */
 enum kr_query_flag {
index c9d3bbe8d10a9565ae3430f3cfc1af030fec7436..10a4751d6ace5eea4dcd96e1dbf9b984a5f17788 100644 (file)
@@ -73,6 +73,8 @@ int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, mm_ctx_t *
        cut->pool = pool;
        cut->key  = NULL;
        cut->trust_anchor = NULL;
+       cut->parent_name = NULL;
+       cut->missing_name = NULL;
        cut->nsset = map_make();
        cut->nsset.malloc = (map_alloc_f) mm_alloc;
        cut->nsset.free = (map_free_f) mm_free;
@@ -98,6 +100,8 @@ void kr_zonecut_deinit(struct kr_zonecut *cut)
        map_clear(&cut->nsset);
        knot_rrset_free(&cut->key, cut->pool);
        knot_rrset_free(&cut->trust_anchor, cut->pool);
+       mm_free(cut->pool, cut->parent_name);
+       mm_free(cut->pool, cut->missing_name);
 }
 
 void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name)
@@ -108,10 +112,15 @@ void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name)
        knot_rrset_t *key, *ta;
        key = cut->key; cut->key = NULL;
        ta = cut->trust_anchor; cut->trust_anchor = NULL;
+       knot_dname_t *parent_name, *missing_name;
+       parent_name = cut->parent_name; cut->parent_name = NULL;
+       missing_name = cut->missing_name; cut->missing_name = NULL;
        kr_zonecut_deinit(cut);
        kr_zonecut_init(cut, name, cut->pool);
        cut->key = key;
        cut->trust_anchor = ta;
+       cut->parent_name = parent_name;
+       cut->missing_name = missing_name;
 }
 
 static int copy_addr_set(const char *k, void *v, void *baton)
index a1a051a582c71e4cd46607cb8e14f80adce124f8..82d62958ed0dbca120c62c8aadf474423b39eaee 100644 (file)
@@ -32,6 +32,8 @@ struct kr_zonecut {
        map_t nsset;        /**< Map of nameserver => address_set. */
        knot_rrset_t* key;  /**< Zone cut DNSKEY. */
        knot_rrset_t* trust_anchor; /**< Current trust anchor. */
+       knot_dname_t *parent_name; /**< Parent zone name after zone cut update. */
+       knot_dname_t *missing_name; /**< Missing zone cut name. */
 };
 
 /**
diff --git a/tests/testdata/iter_validate_child_zone.rpl b/tests/testdata/iter_validate_child_zone.rpl
new file mode 100644 (file)
index 0000000..7c1bdc9
--- /dev/null
@@ -0,0 +1,154 @@
+; config options
+server:
+       trust-anchor: ". 3600 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+       val-override-date: "1436477112"
+
+stub-zone:
+       name: "."
+       stub-addr: 198.41.0.4   # a.root-servers.net.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic validation of AAAA nic.cz.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 198.41.0.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+.                      518400  IN      NS      a.root-servers.net.
+.                      518400  IN      NS      b.root-servers.net.
+.                      518400  IN      NS      c.root-servers.net.
+.                      518400  IN      NS      d.root-servers.net.
+.                      518400  IN      NS      e.root-servers.net.
+.                      518400  IN      NS      f.root-servers.net.
+.                      518400  IN      NS      g.root-servers.net.
+.                      518400  IN      NS      h.root-servers.net.
+.                      518400  IN      NS      i.root-servers.net.
+.                      518400  IN      NS      j.root-servers.net.
+.                      518400  IN      NS      k.root-servers.net.
+.                      518400  IN      NS      l.root-servers.net.
+.                      518400  IN      NS      m.root-servers.net.
+.                      518400  IN      RRSIG   NS 8 0 518400 20150809050000 20150730040000 1518 . ntWgyA7SjlVedxDStbRA6fXl0Hq5pyBgVtBb6l+LbqgLs8/2mwPhzaEw A/BMM+wr7KQLvNSyxTl/SZny94uMVu7o2fnI6+bCP5C+lo7PWni/GvMU yj3JSq2hPv3iO/D1ch8yaKddtYL/NCwPBn9CgpW0jWIWp8FvwwCR4RAs GzA=
+SECTION ADDITIONAL
+a.root-servers.net.    518400  IN      A       198.41.0.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+.                      172800  IN      DNSKEY  257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+.                      172800  IN      DNSKEY  256 3 8 AwEAAa67bQck1JjopOOFc+iMISFcp/osWrEst2wbKbuQSUWu77QC9UHL ipiHgWN7JlqVAEjKITZz49hhkLmOpmLK55pTq+RD2kwoyNWk9cvpc+tS nIxT7i93O+3oVeLYjMWrkDAz7K45rObbHDuSBwYZKrcSIUCZnCpNMUtn PFl/04cb
+.                      172800  IN      RRSIG   DNSKEY 8 0 172800 20150804235959 20150721000000 19036 . n9FwNj80Zik2Rr2zTB4F17ydFpiZfUIv8v/XAz4EbSgRxQgFT+TCz3FW i4O7tW5REXUVNHtULiS7fxKLsHZNDPev8DA20DXAw3eEIDi9pDi01O/e 4GnljpkPnP8d5zA62Dob4cxgmhjjFTvhIjtDsH5Dd4jmyHsgBboy4grZ uJNdsez76gD4Ad6WlosZn5Hj5JwqaxZlRph/6I3va4rkp4c32w5DwaQ7 WSne8ffMHX9r7Dn6EbT3FfvnXFDNPE1P6r+qzTzC0t+M/F4R3H+VOdqg cRJcBG6zGCh9ZErhAeoiJh1WAfpjpzx+TUMzqxZCjSC/XL+l2YMKVHtF 8WNg/w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nic.cz. IN AAAA
+SECTION AUTHORITY
+cz.                    172800  IN      NS      a.ns.nic.cz.
+cz.                    86400   IN      DS      54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz.                    86400   IN      RRSIG   DS 8 1 86400 20150809050000 20150730040000 1518 . HUW1+CxxNeY43PxQvSHkspUAC1izz1VldyD0HtwEzKxSRH2GpVcdX5Gs xqaZW8HESCJL/CyEFqyQtGNnyT4EtWMaHEMkbqHH6sMpdfrAzJ1Qab+2 WI4m6kFJqpUrFh+8a+e8nL+R/zWUWL9811oEMQw80lZNnr13GLQBihn6 oJ4=
+SECTION ADDITIONAL
+a.ns.nic.cz.           172800  IN      A       194.0.12.1
+ENTRY_END
+RANGE_END
+
+;a.ns.nic.cz.
+RANGE_BEGIN 0 100
+       ADDRESS 194.0.12.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz.                    18000   IN      DNSKEY  256 3 10 AwEAAbwKeyKB5fuLe16/N5MR6OoG/PO8uxEob7HoIjK0w0wNjwINYb2w edLtzhVlA4HJ0AUUBuZiNj41hlJ474SOBlsAA7BQdtbL1V0Ksk8IC5Z8 3ldU9Mp+ynkj9p9Cl2UOBmoVFYfkbwz0BsOptcXruYA52Ayc9rHrmDPI /0Y8gZAL
+cz.                    18000   IN      DNSKEY  257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+cz.                    18000   IN      RRSIG   DNSKEY 10 1 18000 20150802000000 20150719000000 54576 cz. K04ONpLX3wseqHhUu2QLBY7wzSUszVlut5mC6jpCAqbfhgIvGMnyoWP5 lKwSvCLmjie0j1HSv8Q4OmoYGz8L+P/FGAzK4LhMturHrDtHkpuGvQJ6 //UsHQhf4iwCg5tEeHI4ZvaMmqRZI3FhBnSh0OyFjGO73FRbBU9nDrOM sPB1iCUfRfZhQU0sB/rj82ykBUma280sO1aRp3gmQHc/SVNbFfCL1Z8D htBP6sy4Jh0z3Z40d4CFZ8ZCBsIloHO44/GvXGePtr2dW4gJsoU1619B Jz+6cuTRh5RJBiweUNb/nwjBP8fNRkzH1CbjomC2FpDMnBXw7jE1GUiY vLW9Gg==
+cz.                    18000   IN      RRSIG   DNSKEY 10 1 18000 20150812154652 20150730120915 39788 cz. VD/wYs1AkTvFjZrPQ8pHVnBVN1ZAL1Lt8+RqFgvPamqpNURFmiL18sTS fKYtXQ0yd2KoNJjomjFnl2+e87KxI2+5wdlZXZdNSViMUcH0xhBY7XGj 40ke9ZxJZS6wEnyAK3WXOTM1iOF7Ig+b75N2/1eCuBxVbRE/leXvPQrN 7no=
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN AAAA
+SECTION ANSWER
+nic.cz.                        1800    IN      AAAA    2001:1488:0:3::2
+nic.cz.                        1800    IN      RRSIG   AAAA 5 2 1800 20150811224544 20150729075503 24582 nic.cz. NCCXb2Hc5wX0RxIFFhM5hKs+9NvuC23qBMDlZda16Vmn6slva9y8Itn0 Qxe59llMPTGq9iTQnY7zF0DLm5ltZ2phRUIrICYGRgF9iEoWLjMpg2xL bd5IRkgU/FLD/wBCYQn4e8llgIOoyVS2VNwF+K2wv70ZrSuSOJSRwanK Xg4=
+SECTION AUTHORITY
+nic.cz.                        1800    IN      NS      a.ns.nic.cz.
+nic.cz.                        1800    IN      NS      b.ns.nic.cz.
+nic.cz.                        1800    IN      NS      d.ns.nic.cz.
+nic.cz.                        1800    IN      RRSIG   NS 5 2 1800 20150811123349 20150729075503 24582 nic.cz. nIhW7pXwIgq84c4guDLL+geZR0y2/AD53Ti1bkdqo4USaoy8xy9LL8z9 XY2rBHRO6by6bCrfs0+LB+72DQjJ2nFy0pj4daScOOeCbM52nd8Syn3R oTW5JXAdOFtXg54RykhwYgHk+y5XzEbVpZxY7qJX7H/kIGlNNmmmOYqr acg=
+SECTION ADDITIONAL
+a.ns.nic.cz.           18000   IN      A       194.0.12.1
+b.ns.nic.cz.           18000   IN      A       194.0.12.1
+d.ns.nic.cz.           18000   IN      A       194.0.12.1
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN DS
+SECTION ANSWER
+nic.cz.                        18000   IN      DS      59916 5 1 144130216E45C4EC2BB8595E817916E8B060D87B
+nic.cz.                        18000   IN      RRSIG   DS 10 2 18000 20150812001929 20150730003853 39788 cz. FcgPAUawyGjBW8B84bGlCAtaRwdQ2MQR8OQcy+vdWvzY2QfwUZLmQLG3 lZBiqScaa8SorrbM584WiPaRk2HlDFhtLnvo+UuGeYOV2jKHxuR+beIU rQfn0IbIbWVgJvkK3OmfGx59MAK5fnLcBV3prBN/AVsUC2NK2Dm7Rotu VwI=
+ENTRY_END
+
+;a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION ANSWER
+nic.cz.                        1800    IN      DNSKEY  256 3 5 AwEAAatglK6e9CpmATmEDtjQfOMqSEGB2KT3xciP+ZuBH3qYQDggHxao Hk9cfL5uXHxEr8AqmiTNA2CJ9oVm2wlZFCTUtQS2Vxz+i30XQpIPoh1y 0fU/XHKmrVmdVGzc9OdgDyZT+8CbUInAyUin+tWM9M7ekUXAllUw5bd8 VC4SJO3z
+nic.cz.                        1800    IN      DNSKEY  257 3 5 BQEAAAABt3LenoCVTV0okqKYPDnnVJqvwCD9MKJNXg8fcOCdLQYncyoe hpwM5RK2UkZDcDxWkMo7yMa35ej+Mhpaji9si4xXD+Syl4Q06LFiFkdN /5GlVlrIdE3GW7zC7Z4sS14Vz8FbYfcRmhsh19Ob718jGZneGfw2UPbv kyxUR8wD7mguZn02fQ6tjj/Ktp4uSW9tpz3bjGMo2rX+iZk4xgbPaesA OlR/AaHdatGZsWC9CPon8mnLZeu6czm8CBDgBmnf3PE8c5+uyWj1Pw4p p0VQmnX5UrnuGpErg7qXhJm7wY2CRVRMcLX3zmjVWXW1uT9JFh2G+/pZ zxnASfKKltZpuw==
+nic.cz.                        1800    IN      RRSIG   DNSKEY 5 2 1800 20150812022439 20150729075503 59916 nic.cz. gDihwRHowOqkHMniHhPVylnvpiscTRWVajNQjMYdg2N1kKersQoJHpaL uouLMLpFUAYXI2cG+aMFJ6ym6zDJSua/4KzFPWs+OpW39KC5NAdIkXYq W/c+Wihg5qiRZHusuMeC+hmd6wNb2K0KVdtP2qOXJvxkCLD+Tu7jJCCC 2voH17qXxz3T7/R0mfCG1Dy4yE52WX5o3XF+IHrbeViBqm76CNE977qi J4IntadZJ1VpPq+U5srscBzv0g04SwT8GUaxbKfaorX3h+NxN6AwNmuB BkCqkvBbw9PgkBreASScVpmRV+fa1XC+B4r1a7+XieodWywEq1l11tUT p6vAYw==
+nic.cz.                        1800    IN      RRSIG   DNSKEY 5 2 1800 20150812040510 20150729075503 24582 nic.cz. hNPsaMZzcOy80v0FJjHdLmPOb7TNsmTsA5JdrTut4KF8757teGLNgRL/ 8Nv1cDd7O6TOkHXXH7nfhvh0BufLeAzuZu+2LZY/lrH1nVqm388UgmX/ MbEqXjQ277K0HzoGKfraMGSPiYsXdR5j2i4X7bu65ifrEQO3ymZtaxdH ZMQ=
+ENTRY_END
+
+RANGE_END
+
+STEP 0 TIME_PASSES ELAPSE 1438229000
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+nic.cz. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+nic.cz. IN AAAA
+SECTION ANSWER
+nic.cz.                        1800    IN      AAAA    2001:1488:0:3::2
+nic.cz.                        1800    IN      RRSIG   AAAA 5 2 1800 20150811224544 20150729075503 24582 nic.cz. NCCXb2Hc5wX0RxIFFhM5hKs+9NvuC23qBMDlZda16Vmn6slva9y8Itn0 Qxe59llMPTGq9iTQnY7zF0DLm5ltZ2phRUIrICYGRgF9iEoWLjMpg2xL bd5IRkgU/FLD/wBCYQn4e8llgIOoyVS2VNwF+K2wv70ZrSuSOJSRwanK Xg4=
+ENTRY_END
+
+SCENARIO_END