1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
4 #include "test-syncres_cc.hh"
6 BOOST_AUTO_TEST_SUITE(syncres_cc3
)
8 BOOST_AUTO_TEST_CASE(test_cache_auth
)
10 std::unique_ptr
<SyncRes
> sr
;
15 /* the auth server is sending the same answer in answer and additional,
16 check that we only return one result, and we only cache one too. */
17 const DNSName
target("cache-auth.powerdns.com.");
19 sr
->setAsyncCallback([target
](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
) {
20 setLWResult(res
, 0, true, false, true);
21 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
22 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 10);
24 return LWResult::Result::Success
;
27 const time_t now
= sr
->getNow().tv_sec
;
29 vector
<DNSRecord
> ret
;
30 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
31 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
32 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
33 BOOST_REQUIRE_EQUAL(QType(ret
.at(0).d_type
).getName(), QType(QType::A
).getName());
34 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
.at(0))->getCA().toString(), ComboAddress("192.0.2.2").toString());
36 /* check that we correctly cached only the answer entry, not the additional one */
37 const ComboAddress who
;
38 vector
<DNSRecord
> cached
;
39 BOOST_REQUIRE_GT(g_recCache
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
40 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
41 BOOST_REQUIRE_EQUAL(QType(cached
.at(0).d_type
).getName(), QType(QType::A
).getName());
42 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(cached
.at(0))->getCA().toString(), ComboAddress("192.0.2.2").toString());
45 BOOST_AUTO_TEST_CASE(test_delegation_only
)
47 std::unique_ptr
<SyncRes
> sr
;
52 /* Thanks, Verisign */
53 SyncRes::addDelegationOnly(DNSName("com."));
54 SyncRes::addDelegationOnly(DNSName("net."));
56 const DNSName
target("nx-powerdns.com.");
58 sr
->setAsyncCallback([target
](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
) {
59 if (isRootServer(ip
)) {
60 setLWResult(res
, 0, false, false, true);
61 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
62 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
63 return LWResult::Result::Success
;
65 else if (ip
== ComboAddress("192.0.2.1:53")) {
67 setLWResult(res
, 0, true, false, true);
68 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
69 return LWResult::Result::Success
;
72 return LWResult::Result::Timeout
;
75 vector
<DNSRecord
> ret
;
76 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
77 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
78 BOOST_CHECK_EQUAL(ret
.size(), 0U);
81 BOOST_AUTO_TEST_CASE(test_unauth_any
)
83 std::unique_ptr
<SyncRes
> sr
;
88 const DNSName
target("powerdns.com.");
90 sr
->setAsyncCallback([target
](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
) {
91 if (isRootServer(ip
)) {
92 setLWResult(res
, 0, false, false, true);
93 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
94 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
95 return LWResult::Result::Success
;
97 else if (ip
== ComboAddress("192.0.2.1:53")) {
99 setLWResult(res
, 0, false, false, true);
100 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
101 return LWResult::Result::Success
;
104 return LWResult::Result::Timeout
;
107 vector
<DNSRecord
> ret
;
108 int res
= sr
->beginResolve(target
, QType(QType::ANY
), QClass::IN
, ret
);
109 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
110 BOOST_CHECK_EQUAL(ret
.size(), 0U);
113 static void test_no_data_f(bool qmin
)
115 std::unique_ptr
<SyncRes
> sr
;
118 sr
->setQNameMinimization();
122 const DNSName
target("powerdns.com.");
124 sr
->setAsyncCallback(
125 [target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
,
126 struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
,
127 LWResult
* res
, bool* chained
) {
128 setLWResult(res
, 0, true, false, true);
129 return LWResult::Result::Success
;
132 vector
<DNSRecord
> ret
;
133 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
134 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
135 BOOST_CHECK_EQUAL(ret
.size(), 0U);
138 BOOST_AUTO_TEST_CASE(test_no_data
)
140 test_no_data_f(false);
143 BOOST_AUTO_TEST_CASE(test_no_data_qmin
)
145 test_no_data_f(true);
148 BOOST_AUTO_TEST_CASE(test_skip_opt_any
)
150 std::unique_ptr
<SyncRes
> sr
;
155 const DNSName
target("powerdns.com.");
157 sr
->setAsyncCallback([target
](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
) {
158 setLWResult(res
, 0, true, false, true);
159 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
160 addRecordToLW(res
, domain
, QType::ANY
, "\\# 0");
161 addRecordToLW(res
, domain
, QType::OPT
, "");
162 return LWResult::Result::Success
;
165 vector
<DNSRecord
> ret
;
166 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
167 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
168 BOOST_CHECK_EQUAL(ret
.size(), 1U);
171 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec
)
173 std::unique_ptr
<SyncRes
> sr
;
178 const DNSName
target("powerdns.com.");
180 sr
->setAsyncCallback([target
](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
) {
181 setLWResult(res
, 0, true, false, true);
182 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
183 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
184 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
185 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
186 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
187 return LWResult::Result::Success
;
190 vector
<DNSRecord
> ret
;
191 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
192 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
193 BOOST_CHECK_EQUAL(ret
.size(), 1U);
196 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec
)
198 std::unique_ptr
<SyncRes
> sr
;
203 const DNSName
target("powerdns.com.");
205 sr
->setAsyncCallback([target
](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
) {
206 setLWResult(res
, 0, true, false, true);
207 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
208 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
209 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
210 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
211 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
212 return LWResult::Result::Success
;
215 vector
<DNSRecord
> ret
;
216 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
217 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
218 BOOST_CHECK_EQUAL(ret
.size(), 4U);
221 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec
)
223 std::unique_ptr
<SyncRes
> sr
;
228 const DNSName
target("powerdns.com.");
230 sr
->setAsyncCallback([target
](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
) {
231 setLWResult(res
, RCode::NXDomain
, true, false, true);
232 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
233 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
234 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
235 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
236 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
237 return LWResult::Result::Success
;
240 vector
<DNSRecord
> ret
;
241 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
242 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
243 BOOST_CHECK_EQUAL(ret
.size(), 1U);
246 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec
)
248 std::unique_ptr
<SyncRes
> sr
;
253 const DNSName
target("powerdns.com.");
255 sr
->setAsyncCallback([target
](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 setLWResult(res
, RCode::NXDomain
, true, false, true);
257 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
258 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
259 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
260 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
261 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
262 return LWResult::Result::Success
;
265 vector
<DNSRecord
> ret
;
266 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
267 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
268 BOOST_CHECK_EQUAL(ret
.size(), 4U);
271 BOOST_AUTO_TEST_CASE(test_qclass_none
)
273 std::unique_ptr
<SyncRes
> sr
;
278 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
279 size_t queriesCount
= 0;
281 sr
->setAsyncCallback([&queriesCount
](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
) {
283 return LWResult::Result::Timeout
;
286 const DNSName
target("powerdns.com.");
287 vector
<DNSRecord
> ret
;
288 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::NONE
, ret
);
289 BOOST_CHECK_EQUAL(res
, -1);
290 BOOST_CHECK_EQUAL(ret
.size(), 0U);
291 BOOST_CHECK_EQUAL(queriesCount
, 0U);
294 BOOST_AUTO_TEST_CASE(test_answer_no_aa
)
296 std::unique_ptr
<SyncRes
> sr
;
301 const DNSName
target("powerdns.com.");
303 sr
->setAsyncCallback([target
](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
) {
304 setLWResult(res
, 0, false, false, true);
305 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
306 return LWResult::Result::Success
;
309 const time_t now
= sr
->getNow().tv_sec
;
311 vector
<DNSRecord
> ret
;
312 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
313 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
314 BOOST_CHECK_EQUAL(ret
.size(), 0U);
316 /* check that the record in the answer section has not been cached */
317 const ComboAddress who
;
318 vector
<DNSRecord
> cached
;
319 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
320 BOOST_REQUIRE_EQUAL(g_recCache
->get(now
, target
, QType(QType::A
), false, &cached
, who
, boost::none
, &signatures
), -1);
323 BOOST_AUTO_TEST_CASE(test_special_types
)
325 std::unique_ptr
<SyncRes
> sr
;
330 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
331 size_t queriesCount
= 0;
333 sr
->setAsyncCallback([&queriesCount
](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
) {
334 cerr
<< "asyncresolve called to ask " << ip
.toStringWithPort() << " about " << domain
.toString() << " / " << QType(type
).getName() << " over " << (doTCP
? "TCP" : "UDP") << " (rd: " << sendRDQuery
<< ", EDNS0 level: " << EDNS0Level
<< ")" << endl
;
336 return LWResult::Result::Timeout
;
339 const DNSName
target("powerdns.com.");
340 vector
<DNSRecord
> ret
;
341 int res
= sr
->beginResolve(target
, QType(QType::AXFR
), QClass::IN
, ret
);
342 BOOST_CHECK_EQUAL(res
, -1);
343 BOOST_CHECK_EQUAL(ret
.size(), 0U);
344 BOOST_CHECK_EQUAL(queriesCount
, 0U);
346 res
= sr
->beginResolve(target
, QType(QType::IXFR
), QClass::IN
, ret
);
347 BOOST_CHECK_EQUAL(res
, -1);
348 BOOST_CHECK_EQUAL(ret
.size(), 0U);
349 BOOST_CHECK_EQUAL(queriesCount
, 0U);
351 res
= sr
->beginResolve(target
, QType(QType::RRSIG
), QClass::IN
, ret
);
352 BOOST_CHECK_EQUAL(res
, -1);
353 BOOST_CHECK_EQUAL(ret
.size(), 0U);
354 BOOST_CHECK_EQUAL(queriesCount
, 0U);
356 res
= sr
->beginResolve(target
, QType(QType::NSEC3
), QClass::IN
, ret
);
357 BOOST_CHECK_EQUAL(res
, -1);
358 BOOST_CHECK_EQUAL(ret
.size(), 0U);
359 BOOST_CHECK_EQUAL(queriesCount
, 0U);
362 BOOST_AUTO_TEST_CASE(test_special_names
)
364 std::unique_ptr
<SyncRes
> sr
;
369 /* special names should be handled internally */
371 size_t queriesCount
= 0;
373 sr
->setAsyncCallback([&queriesCount
](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
) {
375 return LWResult::Result::Timeout
;
378 vector
<DNSRecord
> ret
;
379 int res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
380 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
381 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
382 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
383 BOOST_CHECK_EQUAL(queriesCount
, 0U);
386 res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
387 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
388 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
389 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
390 BOOST_CHECK_EQUAL(queriesCount
, 0U);
393 res
= sr
->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
394 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
395 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
396 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
397 BOOST_CHECK_EQUAL(queriesCount
, 0U);
400 res
= sr
->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
401 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
402 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
403 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
404 BOOST_CHECK_EQUAL(queriesCount
, 0U);
407 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::A
), QClass::IN
, ret
);
408 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
409 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
410 BOOST_CHECK(ret
[0].d_type
== QType::A
);
411 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), "127.0.0.1");
412 BOOST_CHECK_EQUAL(queriesCount
, 0U);
415 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::AAAA
), QClass::IN
, ret
);
416 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
417 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
418 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
419 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(ret
[0])->getCA().toString(), "::1");
420 BOOST_CHECK_EQUAL(queriesCount
, 0U);
423 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::ANY
), QClass::IN
, ret
);
424 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
425 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
426 for (const auto& rec
: ret
) {
427 BOOST_REQUIRE((rec
.d_type
== QType::A
) || rec
.d_type
== QType::AAAA
);
428 if (rec
.d_type
== QType::A
) {
429 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(rec
)->getCA().toString(), "127.0.0.1");
432 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(rec
)->getCA().toString(), "::1");
435 BOOST_CHECK_EQUAL(queriesCount
, 0U);
438 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::TXT
), QClass::CHAOS
, ret
);
439 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
440 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
441 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
442 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
443 BOOST_CHECK_EQUAL(queriesCount
, 0U);
446 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::ANY
), QClass::CHAOS
, ret
);
447 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
448 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
449 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
450 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
451 BOOST_CHECK_EQUAL(queriesCount
, 0U);
454 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::TXT
), QClass::CHAOS
, ret
);
455 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
456 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
457 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
458 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
459 BOOST_CHECK_EQUAL(queriesCount
, 0U);
462 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::ANY
), QClass::CHAOS
, ret
);
463 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
464 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
465 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
466 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
467 BOOST_CHECK_EQUAL(queriesCount
, 0U);
470 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::TXT
), QClass::CHAOS
, ret
);
471 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
472 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
473 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
474 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
475 BOOST_CHECK_EQUAL(queriesCount
, 0U);
478 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::ANY
), QClass::CHAOS
, ret
);
479 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
480 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
481 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
482 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
483 BOOST_CHECK_EQUAL(queriesCount
, 0U);
486 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz
)
488 std::unique_ptr
<SyncRes
> sr
;
493 const DNSName
target("rpz.powerdns.com.");
494 const ComboAddress
ns("192.0.2.1:53");
496 sr
->setAsyncCallback([target
, ns
](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
) {
497 if (isRootServer(ip
)) {
498 setLWResult(res
, false, true, false, true);
499 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
500 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
501 return LWResult::Result::Success
;
505 setLWResult(res
, 0, true, false, true);
506 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
507 return LWResult::Result::Success
;
510 return LWResult::Result::Timeout
;
513 DNSFilterEngine::Policy pol
;
514 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
515 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
516 zone
->setName("Unit test policy 0");
517 zone
->addNSIPTrigger(Netmask(ns
, 32), std::move(pol
));
518 auto luaconfsCopy
= g_luaconfs
.getCopy();
519 luaconfsCopy
.dfe
.clearZones();
520 luaconfsCopy
.dfe
.addZone(zone
);
521 g_luaconfs
.setState(luaconfsCopy
);
523 vector
<DNSRecord
> ret
;
524 BOOST_CHECK_THROW(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
), PolicyHitException
);
527 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz
)
529 std::unique_ptr
<SyncRes
> sr
;
534 const DNSName
target("rpz.powerdns.com.");
535 const ComboAddress
ns("[2001:DB8::42]:53");
537 sr
->setAsyncCallback([target
, ns
](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
) {
538 if (isRootServer(ip
)) {
539 setLWResult(res
, 0, false, false, true);
540 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
541 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
542 return LWResult::Result::Success
;
546 setLWResult(res
, 0, true, false, true);
547 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
548 return LWResult::Result::Success
;
551 return LWResult::Result::Timeout
;
554 DNSFilterEngine::Policy pol
;
555 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
556 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
557 zone
->setName("Unit test policy 0");
558 zone
->addNSIPTrigger(Netmask(ns
, 128), std::move(pol
));
559 auto luaconfsCopy
= g_luaconfs
.getCopy();
560 luaconfsCopy
.dfe
.clearZones();
561 luaconfsCopy
.dfe
.addZone(zone
);
562 g_luaconfs
.setState(luaconfsCopy
);
564 vector
<DNSRecord
> ret
;
565 BOOST_CHECK_THROW(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
), PolicyHitException
);
568 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz
)
570 std::unique_ptr
<SyncRes
> sr
;
575 const DNSName
target("rpz.powerdns.com.");
576 const ComboAddress
ns("192.0.2.1:53");
577 const DNSName
nsName("ns1.powerdns.com.");
579 sr
->setAsyncCallback([target
, ns
, nsName
](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
) {
580 if (isRootServer(ip
)) {
581 setLWResult(res
, 0, false, false, true);
582 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
583 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
584 return LWResult::Result::Success
;
588 setLWResult(res
, 0, true, false, true);
589 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
590 return LWResult::Result::Success
;
593 return LWResult::Result::Timeout
;
596 DNSFilterEngine::Policy pol
;
597 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
598 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
599 zone
->setName("Unit test policy 0");
600 zone
->addNSTrigger(nsName
, std::move(pol
));
601 auto luaconfsCopy
= g_luaconfs
.getCopy();
602 luaconfsCopy
.dfe
.clearZones();
603 luaconfsCopy
.dfe
.addZone(zone
);
604 g_luaconfs
.setState(luaconfsCopy
);
606 vector
<DNSRecord
> ret
;
607 BOOST_CHECK_THROW(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
), PolicyHitException
);
610 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled
)
612 std::unique_ptr
<SyncRes
> sr
;
617 const DNSName
target("rpz.powerdns.com.");
618 const ComboAddress
ns("192.0.2.1:53");
619 const DNSName
nsName("ns1.powerdns.com.");
621 sr
->setAsyncCallback([target
, ns
, nsName
](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
) {
622 if (isRootServer(ip
)) {
623 setLWResult(res
, 0, false, false, true);
624 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
625 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
626 return LWResult::Result::Success
;
630 setLWResult(res
, 0, true, false, true);
631 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
632 return LWResult::Result::Success
;
635 return LWResult::Result::Timeout
;
638 DNSFilterEngine::Policy pol
;
639 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
640 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
641 zone
->setName("Unit test policy 0");
642 zone
->addNSIPTrigger(Netmask(ns
, 128), DNSFilterEngine::Policy(pol
));
643 zone
->addNSTrigger(nsName
, std::move(pol
));
644 auto luaconfsCopy
= g_luaconfs
.getCopy();
645 luaconfsCopy
.dfe
.clearZones();
646 luaconfsCopy
.dfe
.addZone(zone
);
647 g_luaconfs
.setState(luaconfsCopy
);
649 /* RPZ is disabled for this query, we should not be blocked */
650 sr
->setWantsRPZ(false);
652 vector
<DNSRecord
> ret
;
653 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
654 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
655 BOOST_CHECK_EQUAL(ret
.size(), 1U);
658 BOOST_AUTO_TEST_CASE(test_forward_zone_nord
)
660 std::unique_ptr
<SyncRes
> sr
;
665 const DNSName
target("powerdns.com.");
666 const ComboAddress
ns("192.0.2.1:53");
667 const ComboAddress
forwardedNS("192.0.2.42:53");
669 SyncRes::AuthDomain ad
;
670 ad
.d_rdForward
= false;
671 ad
.d_servers
.push_back(forwardedNS
);
672 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
674 sr
->setAsyncCallback([forwardedNS
](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
) {
675 if (ip
== forwardedNS
) {
676 BOOST_CHECK_EQUAL(sendRDQuery
, false);
678 setLWResult(res
, 0, true, false, true);
679 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
680 return LWResult::Result::Success
;
683 return LWResult::Result::Timeout
;
686 /* simulate a no-RD query */
689 vector
<DNSRecord
> ret
;
690 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
691 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
692 BOOST_CHECK_EQUAL(ret
.size(), 1U);
695 BOOST_AUTO_TEST_CASE(test_forward_zone_rd
)
697 std::unique_ptr
<SyncRes
> sr
;
702 const DNSName
target("powerdns.com.");
703 const ComboAddress
ns("192.0.2.1:53");
704 const ComboAddress
forwardedNS("192.0.2.42:53");
706 size_t queriesCount
= 0;
707 SyncRes::AuthDomain ad
;
708 ad
.d_rdForward
= true;
709 ad
.d_servers
.push_back(forwardedNS
);
710 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
712 sr
->setAsyncCallback([forwardedNS
, &queriesCount
](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
) {
715 if (ip
== forwardedNS
) {
716 BOOST_CHECK_EQUAL(sendRDQuery
, true);
718 /* set AA=0, we are a recursor */
719 setLWResult(res
, 0, false, false, true);
720 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
721 return LWResult::Result::Success
;
724 return LWResult::Result::Timeout
;
727 vector
<DNSRecord
> ret
;
728 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
729 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
730 BOOST_CHECK_EQUAL(ret
.size(), 1U);
731 BOOST_CHECK_EQUAL(queriesCount
, 1U);
733 /* now make sure we can resolve from the cache (see #6340
734 where the entries were added to the cache but not retrieved,
735 because the recursor doesn't set the AA bit and we require
736 it. We fixed it by not requiring the AA bit for forward-recurse
739 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
740 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
741 BOOST_CHECK_EQUAL(ret
.size(), 1U);
742 BOOST_CHECK_EQUAL(queriesCount
, 1U);
745 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord
)
747 std::unique_ptr
<SyncRes
> sr
;
752 const DNSName
target("powerdns.com.");
753 const ComboAddress
ns("192.0.2.1:53");
754 const ComboAddress
forwardedNS("192.0.2.42:53");
756 SyncRes::AuthDomain ad
;
757 ad
.d_rdForward
= true;
758 ad
.d_servers
.push_back(forwardedNS
);
759 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
761 sr
->setAsyncCallback([forwardedNS
](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
) {
762 if (ip
== forwardedNS
) {
763 BOOST_CHECK_EQUAL(sendRDQuery
, false);
765 setLWResult(res
, 0, true, false, true);
766 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
767 return LWResult::Result::Success
;
770 return LWResult::Result::Timeout
;
773 /* simulate a no-RD query */
776 vector
<DNSRecord
> ret
;
777 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
778 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
779 BOOST_CHECK_EQUAL(ret
.size(), 1U);
782 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd
)
784 std::unique_ptr
<SyncRes
> sr
;
789 const DNSName
target("powerdns.com.");
790 const ComboAddress
ns("192.0.2.1:53");
791 const ComboAddress
forwardedNS("192.0.2.42:53");
793 SyncRes::AuthDomain ad
;
794 ad
.d_rdForward
= true;
795 ad
.d_servers
.push_back(forwardedNS
);
796 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
798 sr
->setAsyncCallback([forwardedNS
](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
) {
799 if (ip
== forwardedNS
) {
800 BOOST_CHECK_EQUAL(sendRDQuery
, true);
802 setLWResult(res
, 0, true, false, true);
803 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
804 return LWResult::Result::Success
;
807 return LWResult::Result::Timeout
;
810 vector
<DNSRecord
> ret
;
811 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
812 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
813 BOOST_CHECK_EQUAL(ret
.size(), 1U);
816 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec
)
818 std::unique_ptr
<SyncRes
> sr
;
821 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
825 const DNSName
target("test.");
827 const DNSName
cnameTarget("cname.");
830 auto luaconfsCopy
= g_luaconfs
.getCopy();
831 luaconfsCopy
.dsAnchors
.clear();
832 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
833 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
834 g_luaconfs
.setState(luaconfsCopy
);
836 const ComboAddress
forwardedNS("192.0.2.42:53");
837 size_t queriesCount
= 0;
839 SyncRes::AuthDomain ad
;
840 ad
.d_rdForward
= true;
841 ad
.d_servers
.push_back(forwardedNS
);
842 (*SyncRes::t_sstorage
.domainmap
)[g_rootdnsname
] = ad
;
844 sr
->setAsyncCallback([target
, cnameTarget
, keys
, forwardedNS
, &queriesCount
](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
) {
847 BOOST_CHECK_EQUAL(sendRDQuery
, true);
849 if (ip
!= forwardedNS
) {
850 return LWResult::Result::Timeout
;
853 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
854 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
857 if (domain
== target
&& type
== QType::A
) {
859 setLWResult(res
, 0, false, false, true);
860 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
861 addRRSIG(keys
, res
->d_records
, domain
, 300);
862 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
864 return LWResult::Result::Success
;
866 return LWResult::Result::Timeout
;
869 vector
<DNSRecord
> ret
;
870 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
871 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
872 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
873 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
874 BOOST_CHECK_EQUAL(queriesCount
, 5U);
876 /* again, to test the cache */
878 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
879 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
880 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
881 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
882 BOOST_CHECK_EQUAL(queriesCount
, 5U);
885 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord_dnssec
)
887 std::unique_ptr
<SyncRes
> sr
;
890 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
894 const DNSName
parent("test.");
895 const DNSName
target1("a.test.");
896 const DNSName
target2("b.test.");
900 auto luaconfsCopy
= g_luaconfs
.getCopy();
901 luaconfsCopy
.dsAnchors
.clear();
902 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
903 generateKeyMaterial(DNSName("test."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
904 g_luaconfs
.setState(luaconfsCopy
);
906 const ComboAddress
forwardedNS("192.0.2.42:53");
907 size_t queriesCount
= 0;
908 size_t DSforParentCount
= 0;
910 SyncRes::AuthDomain ad
;
911 ad
.d_rdForward
= false;
912 ad
.d_servers
.push_back(forwardedNS
);
913 (*SyncRes::t_sstorage
.domainmap
)[DNSName("test.")] = ad
;
915 sr
->setAsyncCallback([parent
, target1
, target2
, keys
, forwardedNS
, &queriesCount
, &DSforParentCount
](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
) {
918 BOOST_CHECK_EQUAL(sendRDQuery
, false);
920 if (type
== QType::DS
&& domain
== parent
) {
923 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
924 if (domain
!= parent
&& domain
.isPartOf(parent
)) {
925 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false /* no cut / delegation */);
928 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
932 if (isRootServer(ip
)) {
933 setLWResult(res
, 0, false, false, true);
934 addRecordToLW(res
, parent
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 42);
935 addRRSIG(keys
, res
->d_records
, g_rootdnsname
, 300);
936 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
939 if (ip
!= forwardedNS
) {
940 return LWResult::Result::Timeout
;
943 if (domain
== target1
&& type
== QType::A
) {
945 setLWResult(res
, 0, true, false, true);
946 addRecordToLW(res
, target1
, QType::A
, "192.0.2.1");
947 addRRSIG(keys
, res
->d_records
, parent
, 300);
949 return LWResult::Result::Success
;
951 if (domain
== target2
&& type
== QType::A
) {
953 setLWResult(res
, 0, true, false, true);
954 addRecordToLW(res
, target2
, QType::A
, "192.0.2.2");
955 addRRSIG(keys
, res
->d_records
, parent
, 300);
957 return LWResult::Result::Success
;
960 return LWResult::Result::Timeout
;
963 vector
<DNSRecord
> ret
;
964 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
965 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
966 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
967 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
968 BOOST_CHECK_EQUAL(queriesCount
, 5U);
969 BOOST_CHECK_EQUAL(DSforParentCount
, 1U);
971 /* again, to test the cache */
973 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
974 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
975 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
976 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
977 BOOST_CHECK_EQUAL(queriesCount
, 5U);
978 BOOST_CHECK_EQUAL(DSforParentCount
, 1U);
980 /* new target should no cause a DS query for tets. */
982 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
983 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
984 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
985 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
986 BOOST_CHECK_EQUAL(queriesCount
, 7U);
987 BOOST_CHECK_EQUAL(DSforParentCount
, 1U);
990 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_bogus
)
992 std::unique_ptr
<SyncRes
> sr
;
995 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
999 const DNSName
target("test.");
1001 const DNSName
cnameTarget("cname.");
1004 auto luaconfsCopy
= g_luaconfs
.getCopy();
1005 luaconfsCopy
.dsAnchors
.clear();
1006 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1007 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1008 generateKeyMaterial(cnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1009 g_luaconfs
.setState(luaconfsCopy
);
1011 const ComboAddress
forwardedNS("192.0.2.42:53");
1012 size_t queriesCount
= 0;
1014 SyncRes::AuthDomain ad
;
1015 ad
.d_rdForward
= true;
1016 ad
.d_servers
.push_back(forwardedNS
);
1017 (*SyncRes::t_sstorage
.domainmap
)[g_rootdnsname
] = ad
;
1019 sr
->setAsyncCallback([target
, cnameTarget
, keys
, forwardedNS
, &queriesCount
](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
) {
1022 BOOST_CHECK_EQUAL(sendRDQuery
, true);
1024 if (ip
!= forwardedNS
) {
1025 return LWResult::Result::Timeout
;
1028 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1029 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
1032 if (domain
== target
&& type
== QType::A
) {
1034 setLWResult(res
, 0, false, false, true);
1035 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
1036 addRRSIG(keys
, res
->d_records
, domain
, 300);
1037 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
1038 /* no RRSIG in a signed zone, Bogus ! */
1040 return LWResult::Result::Success
;
1042 return LWResult::Result::Timeout
;
1045 vector
<DNSRecord
> ret
;
1046 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1047 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1048 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::BogusNoRRSIG
);
1049 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1050 BOOST_CHECK_EQUAL(queriesCount
, 5U);
1052 /* again, to test the cache */
1054 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1055 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1056 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::BogusNoRRSIG
);
1057 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1058 BOOST_CHECK_EQUAL(queriesCount
, 5U);
1061 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_nodata_bogus
)
1063 std::unique_ptr
<SyncRes
> sr
;
1066 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1069 const DNSName
target("powerdns.com.");
1072 auto luaconfsCopy
= g_luaconfs
.getCopy();
1073 luaconfsCopy
.dsAnchors
.clear();
1074 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1075 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1076 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1077 g_luaconfs
.setState(luaconfsCopy
);
1079 const ComboAddress
forwardedNS("192.0.2.42:53");
1080 SyncRes::AuthDomain ad
;
1081 ad
.d_rdForward
= true;
1082 ad
.d_servers
.push_back(forwardedNS
);
1083 (*SyncRes::t_sstorage
.domainmap
)[g_rootdnsname
] = ad
;
1085 size_t queriesCount
= 0;
1087 sr
->setAsyncCallback([target
, forwardedNS
, &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
) {
1090 BOOST_CHECK_EQUAL(sendRDQuery
, true);
1092 if (ip
!= forwardedNS
) {
1093 return LWResult::Result::Timeout
;
1096 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1097 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1101 setLWResult(res
, 0, false, false, true);
1102 return LWResult::Result::Success
;
1105 return LWResult::Result::Timeout
;
1108 vector
<DNSRecord
> ret
;
1109 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1110 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1111 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::BogusMissingNegativeIndication
);
1112 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
1113 /* com|NS, powerdns.com|NS, powerdns.com|A */
1114 BOOST_CHECK_EQUAL(queriesCount
, 3U);
1116 /* again, to test the cache */
1118 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1119 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1120 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::BogusMissingNegativeIndication
);
1121 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
1122 /* we don't store empty results */
1123 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1126 BOOST_AUTO_TEST_CASE(test_auth_zone_oob
)
1128 std::unique_ptr
<SyncRes
> sr
;
1133 size_t queriesCount
= 0;
1134 const DNSName
target("test.xx.");
1135 const ComboAddress
targetAddr("127.0.0.1");
1136 const DNSName
authZone("test.xx");
1138 SyncRes::AuthDomain ad
;
1141 dr
.d_place
= DNSResourceRecord::ANSWER
;
1143 dr
.d_type
= QType::A
;
1145 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
1146 ad
.d_records
.insert(dr
);
1148 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
1150 sr
->setAsyncCallback([&queriesCount
](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
) {
1152 return LWResult::Result::Timeout
;
1155 vector
<DNSRecord
> ret
;
1156 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1157 BOOST_CHECK_EQUAL(res
, 0);
1158 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1159 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1160 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1161 BOOST_CHECK(sr
->wasOutOfBand());
1162 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
1164 /* a second time, to check that the OOB flag is set when the query cache is used */
1166 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1167 BOOST_CHECK_EQUAL(res
, 0);
1168 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1169 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1170 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1171 BOOST_CHECK(sr
->wasOutOfBand());
1172 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
1174 /* a third time, to check that the validation is disabled when the OOB flag is set */
1176 sr
->setDNSSECValidationRequested(true);
1177 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1178 BOOST_CHECK_EQUAL(res
, 0);
1179 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1180 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1181 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1182 BOOST_CHECK(sr
->wasOutOfBand());
1183 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
1186 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname
)
1188 std::unique_ptr
<SyncRes
> sr
;
1193 size_t queriesCount
= 0;
1194 const DNSName
target("cname.test.xx.");
1195 const DNSName
targetCname("cname-target.test.xx.");
1196 const ComboAddress
targetCnameAddr("127.0.0.1");
1197 const DNSName
authZone("test.xx");
1199 SyncRes::AuthDomain ad
;
1202 dr
.d_place
= DNSResourceRecord::ANSWER
;
1204 dr
.d_type
= QType::CNAME
;
1206 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(targetCname
);
1207 ad
.d_records
.insert(dr
);
1209 dr
.d_place
= DNSResourceRecord::ANSWER
;
1210 dr
.d_name
= targetCname
;
1211 dr
.d_type
= QType::A
;
1213 dr
.d_content
= std::make_shared
<ARecordContent
>(targetCnameAddr
);
1214 ad
.d_records
.insert(dr
);
1216 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
1218 sr
->setAsyncCallback([&queriesCount
](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
) {
1220 return LWResult::Result::Timeout
;
1223 vector
<DNSRecord
> ret
;
1224 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1225 BOOST_CHECK_EQUAL(res
, 0);
1226 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1227 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1228 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1229 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1230 BOOST_CHECK(sr
->wasOutOfBand());
1231 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
1233 /* a second time, to check that the OOB flag is set when the query cache is used */
1235 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1236 BOOST_CHECK_EQUAL(res
, 0);
1237 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1238 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1239 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1240 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1241 BOOST_CHECK(sr
->wasOutOfBand());
1242 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
1244 /* a third time, to check that the validation is disabled when the OOB flag is set */
1246 sr
->setDNSSECValidationRequested(true);
1247 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1248 BOOST_CHECK_EQUAL(res
, 0);
1249 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1250 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1251 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1252 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1253 BOOST_CHECK(sr
->wasOutOfBand());
1254 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
1257 BOOST_AUTO_TEST_CASE(test_auth_zone
)
1259 std::unique_ptr
<SyncRes
> sr
;
1264 size_t queriesCount
= 0;
1265 const DNSName
target("powerdns.com.");
1266 const ComboAddress
addr("192.0.2.5");
1268 SyncRes::AuthDomain ad
;
1271 dr
.d_place
= DNSResourceRecord::ANSWER
;
1273 dr
.d_type
= QType::SOA
;
1275 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1276 ad
.d_records
.insert(dr
);
1278 dr
.d_place
= DNSResourceRecord::ANSWER
;
1280 dr
.d_type
= QType::A
;
1282 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
1283 ad
.d_records
.insert(dr
);
1285 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
1286 (*map
)[target
] = ad
;
1287 SyncRes::setDomainMap(map
);
1289 sr
->setAsyncCallback([&queriesCount
](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
) {
1291 setLWResult(res
, 0, true, false, true);
1292 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1293 return LWResult::Result::Success
;
1296 vector
<DNSRecord
> ret
;
1297 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1298 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1299 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1300 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1301 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
1302 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1305 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob
)
1307 std::unique_ptr
<SyncRes
> sr
;
1312 size_t queriesCount
= 0;
1313 const DNSName
target("powerdns.com.");
1314 const DNSName
authZone("internal.powerdns.com.");
1315 const ComboAddress
addr("192.0.2.5");
1317 SyncRes::AuthDomain ad
;
1318 ad
.d_name
= authZone
;
1320 dr
.d_place
= DNSResourceRecord::ANSWER
;
1321 dr
.d_name
= authZone
;
1322 dr
.d_type
= QType::SOA
;
1324 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1325 ad
.d_records
.insert(dr
);
1327 dr
.d_place
= DNSResourceRecord::ANSWER
;
1328 dr
.d_name
= authZone
;
1329 dr
.d_type
= QType::A
;
1331 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
1332 ad
.d_records
.insert(dr
);
1334 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
1335 (*map
)[authZone
] = ad
;
1336 SyncRes::setDomainMap(map
);
1338 sr
->setAsyncCallback([&queriesCount
, target
, authZone
](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
) {
1341 if (domain
== target
) {
1342 setLWResult(res
, 0, true, false, true);
1343 addRecordToLW(res
, target
, QType::CNAME
, authZone
.toString(), DNSResourceRecord::ANSWER
, 3600);
1344 return LWResult::Result::Success
;
1347 return LWResult::Result::Timeout
;
1350 vector
<DNSRecord
> ret
;
1351 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1352 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1353 BOOST_CHECK_EQUAL(ret
.size(), 2U);
1354 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1355 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), authZone
.toString());
1356 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1357 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
1358 BOOST_CHECK_EQUAL(queriesCount
, 1U);
1361 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb
)
1363 std::unique_ptr
<SyncRes
> sr
;
1368 size_t queriesCount
= 0;
1369 const DNSName
target("powerdns.com.");
1370 const DNSName
externalCNAME("www.open-xchange.com.");
1371 const ComboAddress
addr("192.0.2.5");
1373 SyncRes::AuthDomain ad
;
1376 dr
.d_place
= DNSResourceRecord::ANSWER
;
1378 dr
.d_type
= QType::SOA
;
1380 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1381 ad
.d_records
.insert(dr
);
1383 dr
.d_place
= DNSResourceRecord::ANSWER
;
1385 dr
.d_type
= QType::CNAME
;
1387 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(externalCNAME
);
1388 ad
.d_records
.insert(dr
);
1390 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
1391 (*map
)[target
] = ad
;
1392 SyncRes::setDomainMap(map
);
1394 sr
->setAsyncCallback([&queriesCount
, externalCNAME
, addr
](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
) {
1397 if (domain
== externalCNAME
) {
1398 setLWResult(res
, 0, true, false, true);
1399 addRecordToLW(res
, externalCNAME
, QType::A
, addr
.toString(), DNSResourceRecord::ANSWER
, 3600);
1400 return LWResult::Result::Success
;
1403 return LWResult::Result::Timeout
;
1406 vector
<DNSRecord
> ret
;
1407 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1408 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1409 BOOST_CHECK_EQUAL(ret
.size(), 2U);
1410 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1411 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), externalCNAME
.toString());
1412 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1413 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
1414 BOOST_CHECK_EQUAL(queriesCount
, 1U);
1417 BOOST_AUTO_TEST_SUITE_END()