"Fossies" - the Fresh Open Source Software Archive

Member "pdns-auth-4.2.0/pdns/recursordist/test-syncres_cc6.cc" (27 Aug 2019, 42763 Bytes) of package /linux/misc/dns/pdns-auth-4.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "test-syncres_cc6.cc" see the Fossies "Dox" file reference documentation.

    1 #define BOOST_TEST_DYN_LINK
    2 #include <boost/test/unit_test.hpp>
    3 
    4 #include "test-syncres_cc.hh"
    5 
    6 BOOST_AUTO_TEST_SUITE(syncres_cc6)
    7 
    8 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure) {
    9   std::unique_ptr<SyncRes> sr;
   10   initSR(sr, true);
   11 
   12   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
   13 
   14   primeHints();
   15   const DNSName target("www.powerdns.com.");
   16   testkeysset_t keys;
   17 
   18   auto luaconfsCopy = g_luaconfs.getCopy();
   19   luaconfsCopy.dsAnchors.clear();
   20   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
   21   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
   22   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
   23 
   24   g_luaconfs.setState(luaconfsCopy);
   25 
   26   size_t queriesCount = 0;
   27   size_t dsQueriesCount = 0;
   28 
   29   sr->setAsyncCallback([target,&queriesCount,&dsQueriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
   30       queriesCount++;
   31 
   32       if (type == QType::DS) {
   33         DNSName auth(domain);
   34         auth.chopOff();
   35         dsQueriesCount++;
   36 
   37         setLWResult(res, 0, true, false, true);
   38         addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
   39         addRRSIG(keys, res->d_records, auth, 300);
   40         return 1;
   41       }
   42       else if (type == QType::DNSKEY) {
   43         setLWResult(res, 0, true, false, true);
   44         addDNSKEY(keys, domain, 300, res->d_records);
   45         addRRSIG(keys, res->d_records, domain, 300);
   46         return 1;
   47       }
   48       else {
   49         if (isRootServer(ip)) {
   50           setLWResult(res, 0, false, false, true);
   51           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
   52           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
   53           /* No DS on referral, and no denial of the DS either */
   54           return 1;
   55         }
   56         else if (ip == ComboAddress("192.0.2.1:53")) {
   57           if (domain == DNSName("com.")) {
   58             setLWResult(res, 0, true, false, true);
   59             addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
   60             addRRSIG(keys, res->d_records, domain, 300);
   61             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
   62             addRRSIG(keys, res->d_records, domain, 300);
   63           }
   64           else {
   65             setLWResult(res, 0, false, false, true);
   66             addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
   67             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
   68             /* No DS on referral, and no denial of the DS either */
   69           }
   70           return 1;
   71         }
   72         else if (ip == ComboAddress("192.0.2.2:53")) {
   73           setLWResult(res, 0, true, false, true);
   74           if (type == QType::NS) {
   75             if (domain == DNSName("powerdns.com.")) {
   76               addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
   77               addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
   78               addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
   79               addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
   80             }
   81             else {
   82               addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
   83               addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
   84               addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A, QType::NSEC, QType::RRSIG }, 600, res->d_records);
   85               addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
   86             }
   87           }
   88           else {
   89             addRecordToLW(res, domain, QType::A, "192.0.2.42");
   90             addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
   91           }
   92 
   93           return 1;
   94         }
   95       }
   96 
   97       return 0;
   98     });
   99 
  100   vector<DNSRecord> ret;
  101   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  102   BOOST_CHECK_EQUAL(res, RCode::NoError);
  103   BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
  104   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  105   BOOST_CHECK_EQUAL(queriesCount, 9);
  106   BOOST_CHECK_EQUAL(dsQueriesCount, 3);
  107 
  108   /* again, to test the cache */
  109   ret.clear();
  110   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  111   BOOST_CHECK_EQUAL(res, RCode::NoError);
  112   BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
  113   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  114   BOOST_CHECK_EQUAL(queriesCount, 9);
  115   BOOST_CHECK_EQUAL(dsQueriesCount, 3);
  116 }
  117 
  118 BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop) {
  119   std::unique_ptr<SyncRes> sr;
  120   initSR(sr, true);
  121 
  122   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  123 
  124   primeHints();
  125   const DNSName target("www.powerdns.com.");
  126   testkeysset_t keys;
  127 
  128   auto luaconfsCopy = g_luaconfs.getCopy();
  129   luaconfsCopy.dsAnchors.clear();
  130   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  131   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  132   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  133   generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  134 
  135   g_luaconfs.setState(luaconfsCopy);
  136 
  137   size_t queriesCount = 0;
  138 
  139   sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  140       queriesCount++;
  141 
  142       if (type == QType::DS) {
  143         DNSName auth(domain);
  144         auth.chopOff();
  145 
  146         setLWResult(res, 0, true, false, true);
  147         if (domain == target) {
  148           addRecordToLW(res, domain, QType::SOA, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
  149           addRRSIG(keys, res->d_records, target, 300);
  150         }
  151         else {
  152           addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  153           addRRSIG(keys, res->d_records, auth, 300);
  154         }
  155         return 1;
  156       }
  157       else if (type == QType::DNSKEY) {
  158         setLWResult(res, 0, true, false, true);
  159         addDNSKEY(keys, domain, 300, res->d_records);
  160         addRRSIG(keys, res->d_records, domain, 300);
  161         return 1;
  162       }
  163       else {
  164         if (isRootServer(ip)) {
  165           setLWResult(res, 0, false, false, true);
  166           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  167           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  168           addDS(DNSName("com."), 300, res->d_records, keys);
  169           addRRSIG(keys, res->d_records, DNSName("."), 300);
  170           return 1;
  171         }
  172         else if (ip == ComboAddress("192.0.2.1:53")) {
  173           if (domain == DNSName("com.")) {
  174             setLWResult(res, 0, true, false, true);
  175             addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  176             addRRSIG(keys, res->d_records, domain, 300);
  177             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  178             addRRSIG(keys, res->d_records, domain, 300);
  179           }
  180           else {
  181             setLWResult(res, 0, false, false, true);
  182             addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  183             /* no DS */
  184             addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
  185             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  186             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  187           }
  188           return 1;
  189         }
  190         else if (ip == ComboAddress("192.0.2.2:53")) {
  191           if (type == QType::NS) {
  192             if (domain == DNSName("powerdns.com.")) {
  193               setLWResult(res, RCode::Refused, false, false, true);
  194             }
  195             else {
  196               setLWResult(res, 0, true, false, true);
  197               addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  198               addRRSIG(keys, res->d_records, domain, 300);
  199               addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  200               addRRSIG(keys, res->d_records, domain, 300);
  201             }
  202           }
  203           else {
  204             setLWResult(res, 0, true, false, true);
  205             addRecordToLW(res, domain, QType::A, "192.0.2.42");
  206             addRRSIG(keys, res->d_records, DNSName("www.powerdns.com"), 300);
  207           }
  208 
  209           return 1;
  210         }
  211       }
  212 
  213       return 0;
  214     });
  215 
  216   vector<DNSRecord> ret;
  217   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  218   BOOST_CHECK_EQUAL(res, RCode::NoError);
  219   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  220   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  221   BOOST_CHECK_EQUAL(queriesCount, 9);
  222 
  223   /* again, to test the cache */
  224   ret.clear();
  225   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  226   BOOST_CHECK_EQUAL(res, RCode::NoError);
  227   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  228   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  229   BOOST_CHECK_EQUAL(queriesCount, 9);
  230 }
  231 
  232 BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child) {
  233   /* check that we don't accept a signer below us */
  234   std::unique_ptr<SyncRes> sr;
  235   initSR(sr, true);
  236 
  237   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  238 
  239   primeHints();
  240   const DNSName target("www.powerdns.com.");
  241   testkeysset_t keys;
  242 
  243   auto luaconfsCopy = g_luaconfs.getCopy();
  244   luaconfsCopy.dsAnchors.clear();
  245   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  246   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  247   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  248   generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  249   generateKeyMaterial(DNSName("sub.www.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  250 
  251   g_luaconfs.setState(luaconfsCopy);
  252 
  253   size_t queriesCount = 0;
  254 
  255   sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  256       queriesCount++;
  257 
  258       if (type == QType::DS) {
  259         DNSName auth(domain);
  260         auth.chopOff();
  261 
  262         setLWResult(res, 0, true, false, true);
  263         if (domain == target) {
  264           addRecordToLW(res, domain, QType::SOA, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
  265           addRRSIG(keys, res->d_records, target, 300);
  266         }
  267         else {
  268           addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  269           addRRSIG(keys, res->d_records, auth, 300);
  270         }
  271         return 1;
  272       }
  273       else if (type == QType::DNSKEY) {
  274         setLWResult(res, 0, true, false, true);
  275         addDNSKEY(keys, domain, 300, res->d_records);
  276         if (domain == DNSName("www.powerdns.com.")) {
  277           addRRSIG(keys, res->d_records, DNSName("sub.www.powerdns.com."), 300);
  278         }
  279         else {
  280           addRRSIG(keys, res->d_records, domain, 300);
  281         }
  282         return 1;
  283       }
  284       else {
  285         if (isRootServer(ip)) {
  286           setLWResult(res, 0, false, false, true);
  287           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  288           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  289           addDS(DNSName("com."), 300, res->d_records, keys);
  290           addRRSIG(keys, res->d_records, DNSName("."), 300);
  291           return 1;
  292         }
  293         else if (ip == ComboAddress("192.0.2.1:53")) {
  294           if (domain == DNSName("com.")) {
  295             setLWResult(res, 0, true, false, true);
  296             addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  297             addRRSIG(keys, res->d_records, domain, 300);
  298             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  299             addRRSIG(keys, res->d_records, domain, 300);
  300           }
  301           else {
  302             setLWResult(res, 0, false, false, true);
  303             addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  304             addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
  305             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  306             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  307           }
  308           return 1;
  309         }
  310         else if (ip == ComboAddress("192.0.2.2:53")) {
  311           if (type == QType::NS) {
  312             setLWResult(res, 0, true, false, true);
  313             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  314             addRRSIG(keys, res->d_records, domain, 300);
  315             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  316             addRRSIG(keys, res->d_records, domain, 300);
  317           }
  318           else {
  319             setLWResult(res, 0, true, false, true);
  320             addRecordToLW(res, domain, QType::A, "192.0.2.42");
  321             addRRSIG(keys, res->d_records, domain, 300);
  322           }
  323 
  324           return 1;
  325         }
  326       }
  327 
  328       return 0;
  329     });
  330 
  331   vector<DNSRecord> ret;
  332   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  333   BOOST_CHECK_EQUAL(res, RCode::NoError);
  334   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  335   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  336   BOOST_CHECK_EQUAL(queriesCount, 9);
  337 
  338   /* again, to test the cache */
  339   ret.clear();
  340   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  341   BOOST_CHECK_EQUAL(res, RCode::NoError);
  342   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  343   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  344   BOOST_CHECK_EQUAL(queriesCount, 9);
  345 }
  346 
  347 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure) {
  348   std::unique_ptr<SyncRes> sr;
  349   initSR(sr, true);
  350 
  351   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  352 
  353   primeHints();
  354   const DNSName target("www.powerdns.com.");
  355   testkeysset_t keys;
  356 
  357   auto luaconfsCopy = g_luaconfs.getCopy();
  358   luaconfsCopy.dsAnchors.clear();
  359   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  360   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  361 
  362   g_luaconfs.setState(luaconfsCopy);
  363 
  364   size_t queriesCount = 0;
  365   size_t dsQueriesCount = 0;
  366 
  367   sr->setAsyncCallback([target,&queriesCount,&dsQueriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  368       queriesCount++;
  369 
  370       if (type == QType::DS) {
  371         DNSName auth(domain);
  372         auth.chopOff();
  373         dsQueriesCount++;
  374 
  375         setLWResult(res, 0, true, false, true);
  376         if (domain == DNSName("com.")) {
  377           addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  378         }
  379         else {
  380           addRecordToLW(res, "com.", QType::SOA, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  381           addRRSIG(keys, res->d_records, DNSName("com."), 300);
  382           addNSECRecordToLW(domain, DNSName("powerdnt.com."), { QType::NS }, 600, res->d_records);
  383         }
  384         addRRSIG(keys, res->d_records, auth, 300);
  385         return 1;
  386       }
  387       else if (type == QType::DNSKEY) {
  388         setLWResult(res, 0, true, false, true);
  389         addDNSKEY(keys, domain, 300, res->d_records);
  390         addRRSIG(keys, res->d_records, domain, 300);
  391         return 1;
  392       }
  393       else {
  394         if (isRootServer(ip)) {
  395           setLWResult(res, 0, false, false, true);
  396           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  397           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  398           /* No DS on referral, and no denial of the DS either */
  399           return 1;
  400         }
  401         else if (ip == ComboAddress("192.0.2.1:53")) {
  402           if (domain == DNSName("com.")) {
  403             setLWResult(res, 0, true, false, true);
  404             addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  405             addRRSIG(keys, res->d_records, domain, 300);
  406             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  407             addRRSIG(keys, res->d_records, domain, 300);
  408           }
  409           else {
  410             setLWResult(res, 0, false, false, true);
  411             addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  412             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  413             /* No DS on referral, and no denial of the DS either */
  414           }
  415           return 1;
  416         }
  417         else if (ip == ComboAddress("192.0.2.2:53")) {
  418           setLWResult(res, 0, true, false, true);
  419           if (type == QType::NS) {
  420             if (domain == DNSName("powerdns.com.")) {
  421               addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  422               addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  423             }
  424             else {
  425               addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  426             }
  427           }
  428           else {
  429             addRecordToLW(res, domain, QType::A, "192.0.2.42");
  430           }
  431           return 1;
  432         }
  433       }
  434 
  435       return 0;
  436     });
  437 
  438   vector<DNSRecord> ret;
  439   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  440   BOOST_CHECK_EQUAL(res, RCode::NoError);
  441   BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
  442   BOOST_REQUIRE_EQUAL(ret.size(), 1);
  443   BOOST_CHECK_EQUAL(queriesCount, 7);
  444   BOOST_CHECK_EQUAL(dsQueriesCount, 2);
  445 
  446   /* again, to test the cache */
  447   ret.clear();
  448   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  449   BOOST_CHECK_EQUAL(res, RCode::NoError);
  450   BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
  451   BOOST_REQUIRE_EQUAL(ret.size(), 1);
  452   BOOST_CHECK_EQUAL(queriesCount, 7);
  453   BOOST_CHECK_EQUAL(dsQueriesCount, 2);
  454 }
  455 
  456 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec) {
  457   std::unique_ptr<SyncRes> sr;
  458   initSR(sr, true);
  459 
  460   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  461 
  462   primeHints();
  463   const DNSName target("powerdns.com.");
  464   testkeysset_t keys;
  465 
  466   auto luaconfsCopy = g_luaconfs.getCopy();
  467   luaconfsCopy.dsAnchors.clear();
  468   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  469   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  470   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  471 
  472   g_luaconfs.setState(luaconfsCopy);
  473 
  474   size_t queriesCount = 0;
  475 
  476   sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  477       queriesCount++;
  478 
  479       if (type == QType::DS || type == QType::DNSKEY) {
  480         return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  481       }
  482       else {
  483         if (isRootServer(ip)) {
  484           setLWResult(res, 0, false, false, true);
  485           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  486           addDS(DNSName("com."), 300, res->d_records, keys);
  487           addRRSIG(keys, res->d_records, DNSName("."), 300);
  488           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  489           return 1;
  490         }
  491         else if (ip == ComboAddress("192.0.2.1:53")) {
  492           if (domain == DNSName("com.")) {
  493             setLWResult(res, 0, true, false, true);
  494             addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  495             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  496             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  497           }
  498           else {
  499             setLWResult(res, 0, false, false, true);
  500             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  501             addDS(domain, 300, res->d_records, keys);
  502             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  503             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  504           }
  505           return 1;
  506         }
  507         else if (ip == ComboAddress("192.0.2.2:53")) {
  508           setLWResult(res, 0, true, false, true);
  509           if (type == QType::NS) {
  510             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  511             addRRSIG(keys, res->d_records, domain, 300);
  512           }
  513           else {
  514             addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  515             addRRSIG(keys, res->d_records, domain, 300);
  516             addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS, QType::DNSKEY }, 600, res->d_records);
  517             /* NO RRSIG for the NSEC record! */
  518           }
  519           return 1;
  520         }
  521       }
  522 
  523       return 0;
  524     });
  525 
  526   /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
  527   vector<DNSRecord> ret;
  528   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  529   BOOST_CHECK_EQUAL(res, RCode::NoError);
  530   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  531   BOOST_CHECK_EQUAL(ret.size(), 3);
  532   BOOST_CHECK_EQUAL(queriesCount, 8);
  533 
  534   /* again, to test the cache */
  535   ret.clear();
  536   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  537   BOOST_CHECK_EQUAL(res, RCode::NoError);
  538   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  539   BOOST_REQUIRE_EQUAL(ret.size(), 3);
  540   BOOST_CHECK_EQUAL(queriesCount, 8);
  541 }
  542 
  543 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec) {
  544   std::unique_ptr<SyncRes> sr;
  545   initSR(sr, true);
  546 
  547   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  548 
  549   primeHints();
  550   const DNSName target("powerdns.com.");
  551   testkeysset_t keys;
  552 
  553   auto luaconfsCopy = g_luaconfs.getCopy();
  554   luaconfsCopy.dsAnchors.clear();
  555   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  556   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  557   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  558 
  559   g_luaconfs.setState(luaconfsCopy);
  560 
  561   size_t queriesCount = 0;
  562 
  563   sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  564       queriesCount++;
  565 
  566       if (type == QType::DS || type == QType::DNSKEY) {
  567         return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  568       }
  569       else {
  570         if (isRootServer(ip)) {
  571           setLWResult(res, 0, false, false, true);
  572           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  573           addDS(DNSName("com."), 300, res->d_records, keys);
  574           addRRSIG(keys, res->d_records, DNSName("."), 300);
  575           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  576           return 1;
  577         }
  578         else if (ip == ComboAddress("192.0.2.1:53")) {
  579           if (domain == DNSName("com.")) {
  580             setLWResult(res, 0, true, false, true);
  581             addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  582             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  583             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  584           }
  585           else {
  586             setLWResult(res, 0, false, false, true);
  587             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  588             addDS(domain, 300, res->d_records, keys);
  589             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  590             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  591           }
  592           return 1;
  593         }
  594         else if (ip == ComboAddress("192.0.2.2:53")) {
  595           setLWResult(res, 0, true, false, true);
  596           if (type == QType::NS) {
  597             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  598             addRRSIG(keys, res->d_records, domain, 300);
  599           }
  600           else {
  601             addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  602             addRRSIG(keys, res->d_records, domain, 300);
  603 
  604             /* NO NSEC record! */
  605           }
  606           return 1;
  607         }
  608       }
  609 
  610       return 0;
  611     });
  612 
  613   /* no NSEC record in a secure zone, should be Bogus! */
  614   vector<DNSRecord> ret;
  615   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  616   BOOST_CHECK_EQUAL(res, RCode::NoError);
  617   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  618   BOOST_CHECK_EQUAL(ret.size(), 2);
  619   BOOST_CHECK_EQUAL(queriesCount, 8);
  620 
  621   /* again, to test the cache */
  622   ret.clear();
  623   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  624   BOOST_CHECK_EQUAL(res, RCode::NoError);
  625   BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
  626   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  627   BOOST_CHECK_EQUAL(queriesCount, 8);
  628 }
  629 
  630 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure) {
  631   std::unique_ptr<SyncRes> sr;
  632   initSR(sr, true);
  633 
  634   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  635 
  636   primeHints();
  637   const DNSName target("powerdns.com.");
  638   const ComboAddress targetAddr("192.0.2.42");
  639   testkeysset_t keys;
  640 
  641   auto luaconfsCopy = g_luaconfs.getCopy();
  642   luaconfsCopy.dsAnchors.clear();
  643   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  644   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  645 
  646   g_luaconfs.setState(luaconfsCopy);
  647 
  648   size_t queriesCount = 0;
  649 
  650   sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  651       queriesCount++;
  652 
  653       if (type == QType::DS) {
  654         if (domain == target) {
  655           setLWResult(res, 0, true, false, true);
  656           addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  657           addRRSIG(keys, res->d_records, DNSName("com."), 300);
  658           addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
  659           addRRSIG(keys, res->d_records, DNSName("com."), 300);
  660           return 1;
  661         } else {
  662           return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  663         }
  664       }
  665       else if (type == QType::DNSKEY) {
  666         if (domain == g_rootdnsname || domain == DNSName("com.")) {
  667           setLWResult(res, 0, true, false, true);
  668           addDNSKEY(keys, domain, 300, res->d_records);
  669           addRRSIG(keys, res->d_records, domain, 300);
  670           return 1;
  671         }
  672         else {
  673           setLWResult(res, 0, true, false, true);
  674           addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  675           return 1;
  676         }
  677       }
  678       else {
  679         if (isRootServer(ip)) {
  680           setLWResult(res, 0, false, false, true);
  681           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  682           addDS(DNSName("com."), 300, res->d_records, keys);
  683           addRRSIG(keys, res->d_records, DNSName("."), 300);
  684           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  685           return 1;
  686         }
  687         else if (ip == ComboAddress("192.0.2.1:53")) {
  688           if (domain == DNSName("com.")) {
  689             setLWResult(res, 0, true, false, true);
  690             addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  691             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  692             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  693           }
  694           else {
  695             setLWResult(res, 0, false, false, true);
  696             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  697             /* no DS */
  698             addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
  699             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  700             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  701           }
  702           return 1;
  703         }
  704         else if (ip == ComboAddress("192.0.2.2:53")) {
  705           setLWResult(res, 0, true, false, true);
  706           if (type == QType::NS) {
  707             addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  708           }
  709           else {
  710             addRecordToLW(res, domain, QType::A, targetAddr.toString());
  711           }
  712           return 1;
  713         }
  714       }
  715 
  716       return 0;
  717     });
  718 
  719   vector<DNSRecord> ret;
  720   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  721   BOOST_CHECK_EQUAL(res, RCode::NoError);
  722   BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
  723   BOOST_REQUIRE_EQUAL(ret.size(), 1);
  724   BOOST_CHECK(ret[0].d_type == QType::A);
  725   /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
  726      4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
  727      1 query for A */
  728   BOOST_CHECK_EQUAL(queriesCount, 7);
  729 
  730   /* again, to test the cache */
  731   ret.clear();
  732   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  733   BOOST_CHECK_EQUAL(res, RCode::NoError);
  734   BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
  735   BOOST_REQUIRE_EQUAL(ret.size(), 1);
  736   BOOST_CHECK(ret[0].d_type == QType::A);
  737   BOOST_CHECK_EQUAL(queriesCount, 7);
  738 }
  739 
  740 
  741 BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds) {
  742   /*
  743     Direct DS query:
  744     - parent is secure, zone is secure: DS should be secure
  745   */
  746   std::unique_ptr<SyncRes> sr;
  747   initSR(sr, true);
  748 
  749   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  750 
  751   primeHints();
  752   const DNSName target("powerdns.com.");
  753   testkeysset_t keys;
  754 
  755   auto luaconfsCopy = g_luaconfs.getCopy();
  756   luaconfsCopy.dsAnchors.clear();
  757   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  758   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  759   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  760 
  761   g_luaconfs.setState(luaconfsCopy);
  762 
  763   size_t queriesCount = 0;
  764 
  765   sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  766       queriesCount++;
  767 
  768       if (type == QType::DS || type == QType::DNSKEY) {
  769         return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  770       }
  771       else {
  772         if (isRootServer(ip)) {
  773           setLWResult(res, 0, false, false, true);
  774           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  775           addDS(DNSName("com."), 300, res->d_records, keys);
  776           addRRSIG(keys, res->d_records, DNSName("."), 300);
  777           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  778           return 1;
  779         }
  780       }
  781 
  782       return 0;
  783     });
  784 
  785   vector<DNSRecord> ret;
  786   int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  787   BOOST_CHECK_EQUAL(res, RCode::NoError);
  788   BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
  789   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  790   for (const auto& record : ret) {
  791     BOOST_CHECK(record.d_type == QType::DS || record.d_type == QType::RRSIG);
  792   }
  793   BOOST_CHECK_EQUAL(queriesCount, 4);
  794 
  795   /* again, to test the cache */
  796   ret.clear();
  797   res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  798   BOOST_CHECK_EQUAL(res, RCode::NoError);
  799   BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
  800   BOOST_REQUIRE_EQUAL(ret.size(), 2);
  801   for (const auto& record : ret) {
  802     BOOST_CHECK(record.d_type == QType::DS || record.d_type == QType::RRSIG);
  803   }
  804   BOOST_CHECK_EQUAL(queriesCount, 4);
  805 }
  806 
  807 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds) {
  808   /*
  809     Direct DS query:
  810     - parent is secure, zone is insecure: DS denial should be secure
  811   */
  812   std::unique_ptr<SyncRes> sr;
  813   initSR(sr, true);
  814 
  815   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  816 
  817   primeHints();
  818   const DNSName target("powerdns.com.");
  819   testkeysset_t keys;
  820 
  821   auto luaconfsCopy = g_luaconfs.getCopy();
  822   luaconfsCopy.dsAnchors.clear();
  823   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  824   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  825 
  826   g_luaconfs.setState(luaconfsCopy);
  827 
  828   size_t queriesCount = 0;
  829 
  830   sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  831       queriesCount++;
  832 
  833       if (type == QType::DS || type == QType::DNSKEY) {
  834         return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  835       }
  836       else {
  837         if (isRootServer(ip)) {
  838           setLWResult(res, 0, false, false, true);
  839           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  840           addDS(DNSName("com."), 300, res->d_records, keys);
  841           addRRSIG(keys, res->d_records, DNSName("."), 300);
  842           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  843           return 1;
  844         }
  845       }
  846 
  847       return 0;
  848     });
  849 
  850   vector<DNSRecord> ret;
  851   int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  852   BOOST_CHECK_EQUAL(res, RCode::NoError);
  853   BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
  854   BOOST_REQUIRE_EQUAL(ret.size(), 4);
  855   for (const auto& record : ret) {
  856     BOOST_CHECK(record.d_type == QType::SOA || record.d_type == QType::NSEC || record.d_type == QType::RRSIG);
  857   }
  858   BOOST_CHECK_EQUAL(queriesCount, 4);
  859 
  860   /* again, to test the cache */
  861   ret.clear();
  862   res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  863   BOOST_CHECK_EQUAL(res, RCode::NoError);
  864   BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
  865   BOOST_REQUIRE_EQUAL(ret.size(), 4);
  866   for (const auto& record : ret) {
  867     BOOST_CHECK(record.d_type == QType::SOA || record.d_type == QType::NSEC || record.d_type == QType::RRSIG);
  868   }
  869   BOOST_CHECK_EQUAL(queriesCount, 4);
  870 }
  871 
  872 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut) {
  873   std::unique_ptr<SyncRes> sr;
  874   initSR(sr, true);
  875 
  876   setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  877 
  878   primeHints();
  879   const DNSName target("www.sub.powerdns.com.");
  880   const ComboAddress targetAddr("192.0.2.42");
  881   testkeysset_t keys;
  882 
  883   auto luaconfsCopy = g_luaconfs.getCopy();
  884   luaconfsCopy.dsAnchors.clear();
  885   generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
  886   generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  887   generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
  888 
  889   g_luaconfs.setState(luaconfsCopy);
  890 
  891   size_t queriesCount = 0;
  892 
  893   sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
  894       queriesCount++;
  895 
  896       if (type == QType::DS) {
  897         if (domain == DNSName("sub.powerdns.com.")) {
  898           setLWResult(res, 0, true, false, true);
  899           addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  900           addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
  901           addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
  902           addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
  903           return 1;
  904         }
  905         else if (domain == DNSName("www.sub.powerdns.com.")) {
  906           setLWResult(res, 0, true, false, true);
  907           addRecordToLW(res, DNSName("sub.powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  908           return 1;
  909         }
  910         else {
  911           return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  912         }
  913       }
  914       else if (type == QType::DNSKEY) {
  915         if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
  916           setLWResult(res, 0, true, false, true);
  917           addDNSKEY(keys, domain, 300, res->d_records);
  918           addRRSIG(keys, res->d_records, domain, 300);
  919           return 1;
  920         }
  921         else {
  922           setLWResult(res, 0, true, false, true);
  923           addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  924           return 1;
  925         }
  926       }
  927       else {
  928         if (isRootServer(ip)) {
  929           setLWResult(res, 0, false, false, true);
  930           addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  931           addDS(DNSName("com."), 300, res->d_records, keys);
  932           addRRSIG(keys, res->d_records, DNSName("."), 300);
  933           addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  934           return 1;
  935         }
  936         else if (ip == ComboAddress("192.0.2.1:53")) {
  937           if (domain == DNSName("com.")) {
  938             setLWResult(res, 0, true, false, true);
  939             addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  940             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  941             addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  942           }
  943           else {
  944             setLWResult(res, 0, false, false, true);
  945             addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  946             addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
  947             addRRSIG(keys, res->d_records, DNSName("com."), 300);
  948             addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  949           }
  950           return 1;
  951         }
  952         else if (ip == ComboAddress("192.0.2.2:53")) {
  953           setLWResult(res, 0, true, false, true);
  954           if (type == QType::NS) {
  955             if (domain == DNSName("www.sub.powerdns.com.")) {
  956               addRecordToLW(res, DNSName("sub.powerdns.com"), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  957             }
  958             else if (domain == DNSName("sub.powerdns.com.")) {
  959               addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  960             }
  961             else if (domain == DNSName("powerdns.com.")) {
  962               addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  963               addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
  964             }
  965           } else {
  966             addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
  967           }
  968           return 1;
  969         }
  970       }
  971 
  972       return 0;
  973     });
  974 
  975   vector<DNSRecord> ret;
  976   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  977   BOOST_CHECK_EQUAL(res, RCode::NoError);
  978   BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
  979   BOOST_REQUIRE_EQUAL(ret.size(), 1);
  980   BOOST_CHECK(ret[0].d_type == QType::A);
  981   BOOST_CHECK_EQUAL(queriesCount, 9);
  982 
  983   /* again, to test the cache */
  984   ret.clear();
  985   res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  986   BOOST_CHECK_EQUAL(res, RCode::NoError);
  987   BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
  988   BOOST_REQUIRE_EQUAL(ret.size(), 1);
  989   BOOST_CHECK(ret[0].d_type == QType::A);
  990   BOOST_CHECK_EQUAL(queriesCount, 9);
  991 }
  992 
  993 BOOST_AUTO_TEST_SUITE_END()