]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc3.cc
wip
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc3.cc
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_cc3)
7
8 BOOST_AUTO_TEST_CASE(test_cache_auth)
9 {
10 std::unique_ptr<SyncRes> sr;
11 initSR(sr);
12
13 primeHints();
14
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.");
18
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);
23
24 return 1;
25 });
26
27 const time_t now = sr->getNow().tv_sec;
28
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());
35
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(s_RC->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());
43 }
44
45 BOOST_AUTO_TEST_CASE(test_delegation_only)
46 {
47 std::unique_ptr<SyncRes> sr;
48 initSR(sr);
49
50 primeHints();
51
52 /* Thanks, Verisign */
53 SyncRes::addDelegationOnly(DNSName("com."));
54 SyncRes::addDelegationOnly(DNSName("net."));
55
56 const DNSName target("nx-powerdns.com.");
57
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 1;
64 }
65 else if (ip == ComboAddress("192.0.2.1:53")) {
66
67 setLWResult(res, 0, true, false, true);
68 addRecordToLW(res, domain, QType::A, "192.0.2.42");
69 return 1;
70 }
71
72 return 0;
73 });
74
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);
79 }
80
81 BOOST_AUTO_TEST_CASE(test_unauth_any)
82 {
83 std::unique_ptr<SyncRes> sr;
84 initSR(sr);
85
86 primeHints();
87
88 const DNSName target("powerdns.com.");
89
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 1;
96 }
97 else if (ip == ComboAddress("192.0.2.1:53")) {
98
99 setLWResult(res, 0, false, false, true);
100 addRecordToLW(res, domain, QType::A, "192.0.2.42");
101 return 1;
102 }
103
104 return 0;
105 });
106
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);
111 }
112
113 static void test_no_data_f(bool qmin)
114 {
115 std::unique_ptr<SyncRes> sr;
116 initSR(sr);
117 if (qmin)
118 sr->setQNameMinimization();
119
120 primeHints();
121
122 const DNSName target("powerdns.com.");
123
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 1;
130 });
131
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);
136 }
137
138 BOOST_AUTO_TEST_CASE(test_no_data)
139 {
140 test_no_data_f(false);
141 }
142
143 BOOST_AUTO_TEST_CASE(test_no_data_qmin)
144 {
145 test_no_data_f(true);
146 }
147
148 BOOST_AUTO_TEST_CASE(test_skip_opt_any)
149 {
150 std::unique_ptr<SyncRes> sr;
151 initSR(sr);
152
153 primeHints();
154
155 const DNSName target("powerdns.com.");
156
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 0");
161 addRecordToLW(res, domain, QType::OPT, "");
162 return 1;
163 });
164
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);
169 }
170
171 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec)
172 {
173 std::unique_ptr<SyncRes> sr;
174 initSR(sr);
175
176 primeHints();
177
178 const DNSName target("powerdns.com.");
179
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 1;
188 });
189
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);
194 }
195
196 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec)
197 {
198 std::unique_ptr<SyncRes> sr;
199 initSR(sr, true);
200
201 primeHints();
202
203 const DNSName target("powerdns.com.");
204
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 1;
213 });
214
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);
219 }
220
221 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec)
222 {
223 std::unique_ptr<SyncRes> sr;
224 initSR(sr);
225
226 primeHints();
227
228 const DNSName target("powerdns.com.");
229
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 1;
238 });
239
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);
244 }
245
246 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec)
247 {
248 std::unique_ptr<SyncRes> sr;
249 initSR(sr, true);
250
251 primeHints();
252
253 const DNSName target("powerdns.com.");
254
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 1;
263 });
264
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);
269 }
270
271 BOOST_AUTO_TEST_CASE(test_qclass_none)
272 {
273 std::unique_ptr<SyncRes> sr;
274 initSR(sr);
275
276 primeHints();
277
278 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
279 size_t queriesCount = 0;
280
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) {
282 queriesCount++;
283 return 0;
284 });
285
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);
292 }
293
294 BOOST_AUTO_TEST_CASE(test_answer_no_aa)
295 {
296 std::unique_ptr<SyncRes> sr;
297 initSR(sr, true);
298
299 primeHints();
300
301 const DNSName target("powerdns.com.");
302
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 1;
307 });
308
309 const time_t now = sr->getNow().tv_sec;
310
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);
315
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(s_RC->get(now, target, QType(QType::A), false, &cached, who, &signatures), -1);
321 }
322
323 BOOST_AUTO_TEST_CASE(test_special_types)
324 {
325 std::unique_ptr<SyncRes> sr;
326 initSR(sr);
327
328 primeHints();
329
330 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
331 size_t queriesCount = 0;
332
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;
335 queriesCount++;
336 return 0;
337 });
338
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);
345
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);
350
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);
355
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);
360 }
361
362 BOOST_AUTO_TEST_CASE(test_special_names)
363 {
364 std::unique_ptr<SyncRes> sr;
365 initSR(sr);
366
367 primeHints();
368
369 /* special names should be handled internally */
370
371 size_t queriesCount = 0;
372
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) {
374 queriesCount++;
375 return 0;
376 });
377
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);
384
385 ret.clear();
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);
391
392 ret.clear();
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);
398
399 ret.clear();
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);
405
406 ret.clear();
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);
413
414 ret.clear();
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);
421
422 ret.clear();
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");
430 }
431 else {
432 BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(rec)->getCA().toString(), "::1");
433 }
434 }
435 BOOST_CHECK_EQUAL(queriesCount, 0U);
436
437 ret.clear();
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);
444
445 ret.clear();
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);
452
453 ret.clear();
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);
460
461 ret.clear();
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);
468
469 ret.clear();
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);
476
477 ret.clear();
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);
484 }
485
486 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz)
487 {
488 std::unique_ptr<SyncRes> sr;
489 initSR(sr);
490
491 primeHints();
492
493 const DNSName target("rpz.powerdns.com.");
494 const ComboAddress ns("192.0.2.1:53");
495
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 1;
502 }
503 else if (ip == ns) {
504
505 setLWResult(res, 0, true, false, true);
506 addRecordToLW(res, domain, QType::A, "192.0.2.42");
507 return 1;
508 }
509
510 return 0;
511 });
512
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);
522
523 vector<DNSRecord> ret;
524 BOOST_CHECK_THROW(sr->beginResolve(target, QType(QType::A), QClass::IN, ret), PolicyHitException);
525 }
526
527 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz)
528 {
529 std::unique_ptr<SyncRes> sr;
530 initSR(sr);
531
532 primeHints();
533
534 const DNSName target("rpz.powerdns.com.");
535 const ComboAddress ns("[2001:DB8::42]:53");
536
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 1;
543 }
544 else if (ip == ns) {
545
546 setLWResult(res, 0, true, false, true);
547 addRecordToLW(res, domain, QType::A, "192.0.2.42");
548 return 1;
549 }
550
551 return 0;
552 });
553
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);
563
564 vector<DNSRecord> ret;
565 BOOST_CHECK_THROW(sr->beginResolve(target, QType(QType::A), QClass::IN, ret), PolicyHitException);
566 }
567
568 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz)
569 {
570 std::unique_ptr<SyncRes> sr;
571 initSR(sr);
572
573 primeHints();
574
575 const DNSName target("rpz.powerdns.com.");
576 const ComboAddress ns("192.0.2.1:53");
577 const DNSName nsName("ns1.powerdns.com.");
578
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 1;
585 }
586 else if (ip == ns) {
587
588 setLWResult(res, 0, true, false, true);
589 addRecordToLW(res, domain, QType::A, "192.0.2.42");
590 return 1;
591 }
592
593 return 0;
594 });
595
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);
605
606 vector<DNSRecord> ret;
607 BOOST_CHECK_THROW(sr->beginResolve(target, QType(QType::A), QClass::IN, ret), PolicyHitException);
608 }
609
610 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled)
611 {
612 std::unique_ptr<SyncRes> sr;
613 initSR(sr);
614
615 primeHints();
616
617 const DNSName target("rpz.powerdns.com.");
618 const ComboAddress ns("192.0.2.1:53");
619 const DNSName nsName("ns1.powerdns.com.");
620
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 1;
627 }
628 else if (ip == ns) {
629
630 setLWResult(res, 0, true, false, true);
631 addRecordToLW(res, domain, QType::A, "192.0.2.42");
632 return 1;
633 }
634
635 return 0;
636 });
637
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);
648
649 /* RPZ is disabled for this query, we should not be blocked */
650 sr->setWantsRPZ(false);
651
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);
656 }
657
658 BOOST_AUTO_TEST_CASE(test_forward_zone_nord)
659 {
660 std::unique_ptr<SyncRes> sr;
661 initSR(sr);
662
663 primeHints();
664
665 const DNSName target("powerdns.com.");
666 const ComboAddress ns("192.0.2.1:53");
667 const ComboAddress forwardedNS("192.0.2.42:53");
668
669 SyncRes::AuthDomain ad;
670 ad.d_rdForward = false;
671 ad.d_servers.push_back(forwardedNS);
672 (*SyncRes::t_sstorage.domainmap)[target] = ad;
673
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);
677
678 setLWResult(res, 0, true, false, true);
679 addRecordToLW(res, domain, QType::A, "192.0.2.42");
680 return 1;
681 }
682
683 return 0;
684 });
685
686 /* simulate a no-RD query */
687 sr->setCacheOnly();
688
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);
693 }
694
695 BOOST_AUTO_TEST_CASE(test_forward_zone_rd)
696 {
697 std::unique_ptr<SyncRes> sr;
698 initSR(sr);
699
700 primeHints();
701
702 const DNSName target("powerdns.com.");
703 const ComboAddress ns("192.0.2.1:53");
704 const ComboAddress forwardedNS("192.0.2.42:53");
705
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;
711
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) {
713 queriesCount++;
714
715 if (ip == forwardedNS) {
716 BOOST_CHECK_EQUAL(sendRDQuery, true);
717
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 1;
722 }
723
724 return 0;
725 });
726
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);
732
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
737 answers. */
738 ret.clear();
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);
743 }
744
745 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord)
746 {
747 std::unique_ptr<SyncRes> sr;
748 initSR(sr);
749
750 primeHints();
751
752 const DNSName target("powerdns.com.");
753 const ComboAddress ns("192.0.2.1:53");
754 const ComboAddress forwardedNS("192.0.2.42:53");
755
756 SyncRes::AuthDomain ad;
757 ad.d_rdForward = true;
758 ad.d_servers.push_back(forwardedNS);
759 (*SyncRes::t_sstorage.domainmap)[target] = ad;
760
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);
764
765 setLWResult(res, 0, true, false, true);
766 addRecordToLW(res, domain, QType::A, "192.0.2.42");
767 return 1;
768 }
769
770 return 0;
771 });
772
773 /* simulate a no-RD query */
774 sr->setCacheOnly();
775
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);
780 }
781
782 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd)
783 {
784 std::unique_ptr<SyncRes> sr;
785 initSR(sr);
786
787 primeHints();
788
789 const DNSName target("powerdns.com.");
790 const ComboAddress ns("192.0.2.1:53");
791 const ComboAddress forwardedNS("192.0.2.42:53");
792
793 SyncRes::AuthDomain ad;
794 ad.d_rdForward = true;
795 ad.d_servers.push_back(forwardedNS);
796 (*SyncRes::t_sstorage.domainmap)[target] = ad;
797
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);
801
802 setLWResult(res, 0, true, false, true);
803 addRecordToLW(res, domain, QType::A, "192.0.2.42");
804 return 1;
805 }
806
807 return 0;
808 });
809
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);
814 }
815
816 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec)
817 {
818 std::unique_ptr<SyncRes> sr;
819 initSR(sr, true);
820
821 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
822
823 primeHints();
824 /* signed */
825 const DNSName target("test.");
826 /* unsigned */
827 const DNSName cnameTarget("cname.");
828 testkeysset_t keys;
829
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);
835
836 const ComboAddress forwardedNS("192.0.2.42:53");
837 size_t queriesCount = 0;
838
839 SyncRes::AuthDomain ad;
840 ad.d_rdForward = true;
841 ad.d_servers.push_back(forwardedNS);
842 (*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
843
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) {
845 queriesCount++;
846
847 BOOST_CHECK_EQUAL(sendRDQuery, true);
848
849 if (ip != forwardedNS) {
850 return 0;
851 }
852
853 if (type == QType::DS || type == QType::DNSKEY) {
854 return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys);
855 }
856
857 if (domain == target && type == QType::A) {
858
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");
863
864 return 1;
865 }
866 return 0;
867 });
868
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(), Insecure);
873 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
874 BOOST_CHECK_EQUAL(queriesCount, 5U);
875
876 /* again, to test the cache */
877 ret.clear();
878 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
879 BOOST_CHECK_EQUAL(res, RCode::NoError);
880 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
881 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
882 BOOST_CHECK_EQUAL(queriesCount, 5U);
883 }
884
885 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_bogus)
886 {
887 std::unique_ptr<SyncRes> sr;
888 initSR(sr, true);
889
890 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
891
892 primeHints();
893 /* signed */
894 const DNSName target("test.");
895 /* signed */
896 const DNSName cnameTarget("cname.");
897 testkeysset_t keys;
898
899 auto luaconfsCopy = g_luaconfs.getCopy();
900 luaconfsCopy.dsAnchors.clear();
901 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
902 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
903 generateKeyMaterial(cnameTarget, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
904 g_luaconfs.setState(luaconfsCopy);
905
906 const ComboAddress forwardedNS("192.0.2.42:53");
907 size_t queriesCount = 0;
908
909 SyncRes::AuthDomain ad;
910 ad.d_rdForward = true;
911 ad.d_servers.push_back(forwardedNS);
912 (*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
913
914 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) {
915 queriesCount++;
916
917 BOOST_CHECK_EQUAL(sendRDQuery, true);
918
919 if (ip != forwardedNS) {
920 return 0;
921 }
922
923 if (type == QType::DS || type == QType::DNSKEY) {
924 return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys);
925 }
926
927 if (domain == target && type == QType::A) {
928
929 setLWResult(res, 0, false, false, true);
930 addRecordToLW(res, target, QType::CNAME, cnameTarget.toString());
931 addRRSIG(keys, res->d_records, domain, 300);
932 addRecordToLW(res, cnameTarget, QType::A, "192.0.2.1");
933 /* no RRSIG in a signed zone, Bogus ! */
934
935 return 1;
936 }
937 return 0;
938 });
939
940 vector<DNSRecord> ret;
941 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
942 BOOST_CHECK_EQUAL(res, RCode::NoError);
943 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
944 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
945 BOOST_CHECK_EQUAL(queriesCount, 5U);
946
947 /* again, to test the cache */
948 ret.clear();
949 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
950 BOOST_CHECK_EQUAL(res, RCode::NoError);
951 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
952 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
953 BOOST_CHECK_EQUAL(queriesCount, 5U);
954 }
955
956 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_nodata_bogus)
957 {
958 std::unique_ptr<SyncRes> sr;
959 initSR(sr, true);
960
961 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
962
963 primeHints();
964 const DNSName target("powerdns.com.");
965 testkeysset_t keys;
966
967 auto luaconfsCopy = g_luaconfs.getCopy();
968 luaconfsCopy.dsAnchors.clear();
969 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
970 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
971 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
972 g_luaconfs.setState(luaconfsCopy);
973
974 const ComboAddress forwardedNS("192.0.2.42:53");
975 SyncRes::AuthDomain ad;
976 ad.d_rdForward = true;
977 ad.d_servers.push_back(forwardedNS);
978 (*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
979
980 size_t queriesCount = 0;
981
982 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) {
983 queriesCount++;
984
985 BOOST_CHECK_EQUAL(sendRDQuery, true);
986
987 if (ip != forwardedNS) {
988 return 0;
989 }
990
991 if (type == QType::DS || type == QType::DNSKEY) {
992 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
993 }
994 else {
995
996 setLWResult(res, 0, false, false, true);
997 return 1;
998 }
999
1000 return 0;
1001 });
1002
1003 vector<DNSRecord> ret;
1004 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1005 BOOST_CHECK_EQUAL(res, RCode::NoError);
1006 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
1007 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1008 /* com|NS, powerdns.com|NS, powerdns.com|A */
1009 BOOST_CHECK_EQUAL(queriesCount, 3U);
1010
1011 /* again, to test the cache */
1012 ret.clear();
1013 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1014 BOOST_CHECK_EQUAL(res, RCode::NoError);
1015 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
1016 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1017 /* we don't store empty results */
1018 BOOST_CHECK_EQUAL(queriesCount, 4U);
1019 }
1020
1021 BOOST_AUTO_TEST_CASE(test_auth_zone_oob)
1022 {
1023 std::unique_ptr<SyncRes> sr;
1024 initSR(sr, true);
1025
1026 primeHints();
1027
1028 size_t queriesCount = 0;
1029 const DNSName target("test.xx.");
1030 const ComboAddress targetAddr("127.0.0.1");
1031 const DNSName authZone("test.xx");
1032
1033 SyncRes::AuthDomain ad;
1034 DNSRecord dr;
1035
1036 dr.d_place = DNSResourceRecord::ANSWER;
1037 dr.d_name = target;
1038 dr.d_type = QType::A;
1039 dr.d_ttl = 1800;
1040 dr.d_content = std::make_shared<ARecordContent>(targetAddr);
1041 ad.d_records.insert(dr);
1042
1043 (*SyncRes::t_sstorage.domainmap)[authZone] = ad;
1044
1045 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) {
1046 queriesCount++;
1047 return 0;
1048 });
1049
1050 vector<DNSRecord> ret;
1051 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1052 BOOST_CHECK_EQUAL(res, 0);
1053 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1054 BOOST_CHECK(ret[0].d_type == QType::A);
1055 BOOST_CHECK_EQUAL(queriesCount, 0U);
1056 BOOST_CHECK(sr->wasOutOfBand());
1057 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
1058
1059 /* a second time, to check that the OOB flag is set when the query cache is used */
1060 ret.clear();
1061 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1062 BOOST_CHECK_EQUAL(res, 0);
1063 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1064 BOOST_CHECK(ret[0].d_type == QType::A);
1065 BOOST_CHECK_EQUAL(queriesCount, 0U);
1066 BOOST_CHECK(sr->wasOutOfBand());
1067 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
1068
1069 /* a third time, to check that the validation is disabled when the OOB flag is set */
1070 ret.clear();
1071 sr->setDNSSECValidationRequested(true);
1072 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1073 BOOST_CHECK_EQUAL(res, 0);
1074 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1075 BOOST_CHECK(ret[0].d_type == QType::A);
1076 BOOST_CHECK_EQUAL(queriesCount, 0U);
1077 BOOST_CHECK(sr->wasOutOfBand());
1078 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
1079 }
1080
1081 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname)
1082 {
1083 std::unique_ptr<SyncRes> sr;
1084 initSR(sr, true);
1085
1086 primeHints();
1087
1088 size_t queriesCount = 0;
1089 const DNSName target("cname.test.xx.");
1090 const DNSName targetCname("cname-target.test.xx.");
1091 const ComboAddress targetCnameAddr("127.0.0.1");
1092 const DNSName authZone("test.xx");
1093
1094 SyncRes::AuthDomain ad;
1095 DNSRecord dr;
1096
1097 dr.d_place = DNSResourceRecord::ANSWER;
1098 dr.d_name = target;
1099 dr.d_type = QType::CNAME;
1100 dr.d_ttl = 1800;
1101 dr.d_content = std::make_shared<CNAMERecordContent>(targetCname);
1102 ad.d_records.insert(dr);
1103
1104 dr.d_place = DNSResourceRecord::ANSWER;
1105 dr.d_name = targetCname;
1106 dr.d_type = QType::A;
1107 dr.d_ttl = 1800;
1108 dr.d_content = std::make_shared<ARecordContent>(targetCnameAddr);
1109 ad.d_records.insert(dr);
1110
1111 (*SyncRes::t_sstorage.domainmap)[authZone] = ad;
1112
1113 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) {
1114 queriesCount++;
1115 return 0;
1116 });
1117
1118 vector<DNSRecord> ret;
1119 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1120 BOOST_CHECK_EQUAL(res, 0);
1121 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1122 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1123 BOOST_CHECK(ret[1].d_type == QType::A);
1124 BOOST_CHECK_EQUAL(queriesCount, 0U);
1125 BOOST_CHECK(sr->wasOutOfBand());
1126 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
1127
1128 /* a second time, to check that the OOB flag is set when the query cache is used */
1129 ret.clear();
1130 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1131 BOOST_CHECK_EQUAL(res, 0);
1132 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1133 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1134 BOOST_CHECK(ret[1].d_type == QType::A);
1135 BOOST_CHECK_EQUAL(queriesCount, 0U);
1136 BOOST_CHECK(sr->wasOutOfBand());
1137 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
1138
1139 /* a third time, to check that the validation is disabled when the OOB flag is set */
1140 ret.clear();
1141 sr->setDNSSECValidationRequested(true);
1142 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1143 BOOST_CHECK_EQUAL(res, 0);
1144 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1145 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1146 BOOST_CHECK(ret[1].d_type == QType::A);
1147 BOOST_CHECK_EQUAL(queriesCount, 0U);
1148 BOOST_CHECK(sr->wasOutOfBand());
1149 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
1150 }
1151
1152 BOOST_AUTO_TEST_CASE(test_auth_zone)
1153 {
1154 std::unique_ptr<SyncRes> sr;
1155 initSR(sr);
1156
1157 primeHints();
1158
1159 size_t queriesCount = 0;
1160 const DNSName target("powerdns.com.");
1161 const ComboAddress addr("192.0.2.5");
1162
1163 SyncRes::AuthDomain ad;
1164 ad.d_name = target;
1165 DNSRecord dr;
1166 dr.d_place = DNSResourceRecord::ANSWER;
1167 dr.d_name = target;
1168 dr.d_type = QType::SOA;
1169 dr.d_ttl = 3600;
1170 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1171 ad.d_records.insert(dr);
1172
1173 dr.d_place = DNSResourceRecord::ANSWER;
1174 dr.d_name = target;
1175 dr.d_type = QType::A;
1176 dr.d_ttl = 3600;
1177 dr.d_content = std::make_shared<ARecordContent>(addr);
1178 ad.d_records.insert(dr);
1179
1180 auto map = std::make_shared<SyncRes::domainmap_t>();
1181 (*map)[target] = ad;
1182 SyncRes::setDomainMap(map);
1183
1184 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) {
1185 queriesCount++;
1186 setLWResult(res, 0, true, false, true);
1187 addRecordToLW(res, domain, QType::A, "192.0.2.42");
1188 return 1;
1189 });
1190
1191 vector<DNSRecord> ret;
1192 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1193 BOOST_CHECK_EQUAL(res, RCode::NoError);
1194 BOOST_CHECK_EQUAL(ret.size(), 1U);
1195 BOOST_CHECK(ret[0].d_type == QType::A);
1196 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
1197 BOOST_CHECK_EQUAL(queriesCount, 0U);
1198 }
1199
1200 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob)
1201 {
1202 std::unique_ptr<SyncRes> sr;
1203 initSR(sr);
1204
1205 primeHints();
1206
1207 size_t queriesCount = 0;
1208 const DNSName target("powerdns.com.");
1209 const DNSName authZone("internal.powerdns.com.");
1210 const ComboAddress addr("192.0.2.5");
1211
1212 SyncRes::AuthDomain ad;
1213 ad.d_name = authZone;
1214 DNSRecord dr;
1215 dr.d_place = DNSResourceRecord::ANSWER;
1216 dr.d_name = authZone;
1217 dr.d_type = QType::SOA;
1218 dr.d_ttl = 3600;
1219 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1220 ad.d_records.insert(dr);
1221
1222 dr.d_place = DNSResourceRecord::ANSWER;
1223 dr.d_name = authZone;
1224 dr.d_type = QType::A;
1225 dr.d_ttl = 3600;
1226 dr.d_content = std::make_shared<ARecordContent>(addr);
1227 ad.d_records.insert(dr);
1228
1229 auto map = std::make_shared<SyncRes::domainmap_t>();
1230 (*map)[authZone] = ad;
1231 SyncRes::setDomainMap(map);
1232
1233 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) {
1234 queriesCount++;
1235
1236 if (domain == target) {
1237 setLWResult(res, 0, true, false, true);
1238 addRecordToLW(res, target, QType::CNAME, authZone.toString(), DNSResourceRecord::ANSWER, 3600);
1239 return 1;
1240 }
1241
1242 return 0;
1243 });
1244
1245 vector<DNSRecord> ret;
1246 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1247 BOOST_CHECK_EQUAL(res, RCode::NoError);
1248 BOOST_CHECK_EQUAL(ret.size(), 2U);
1249 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1250 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), authZone.toString());
1251 BOOST_CHECK(ret[1].d_type == QType::A);
1252 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[1])->getCA().toString(), addr.toString());
1253 BOOST_CHECK_EQUAL(queriesCount, 1U);
1254 }
1255
1256 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb)
1257 {
1258 std::unique_ptr<SyncRes> sr;
1259 initSR(sr);
1260
1261 primeHints();
1262
1263 size_t queriesCount = 0;
1264 const DNSName target("powerdns.com.");
1265 const DNSName externalCNAME("www.open-xchange.com.");
1266 const ComboAddress addr("192.0.2.5");
1267
1268 SyncRes::AuthDomain ad;
1269 ad.d_name = target;
1270 DNSRecord dr;
1271 dr.d_place = DNSResourceRecord::ANSWER;
1272 dr.d_name = target;
1273 dr.d_type = QType::SOA;
1274 dr.d_ttl = 3600;
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);
1277
1278 dr.d_place = DNSResourceRecord::ANSWER;
1279 dr.d_name = target;
1280 dr.d_type = QType::CNAME;
1281 dr.d_ttl = 3600;
1282 dr.d_content = std::make_shared<CNAMERecordContent>(externalCNAME);
1283 ad.d_records.insert(dr);
1284
1285 auto map = std::make_shared<SyncRes::domainmap_t>();
1286 (*map)[target] = ad;
1287 SyncRes::setDomainMap(map);
1288
1289 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) {
1290 queriesCount++;
1291
1292 if (domain == externalCNAME) {
1293 setLWResult(res, 0, true, false, true);
1294 addRecordToLW(res, externalCNAME, QType::A, addr.toString(), DNSResourceRecord::ANSWER, 3600);
1295 return 1;
1296 }
1297
1298 return 0;
1299 });
1300
1301 vector<DNSRecord> ret;
1302 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1303 BOOST_CHECK_EQUAL(res, RCode::NoError);
1304 BOOST_CHECK_EQUAL(ret.size(), 2U);
1305 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1306 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), externalCNAME.toString());
1307 BOOST_CHECK(ret[1].d_type == QType::A);
1308 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[1])->getCA().toString(), addr.toString());
1309 BOOST_CHECK_EQUAL(queriesCount, 1U);
1310 }
1311
1312 BOOST_AUTO_TEST_SUITE_END()