]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc7.cc
Merge pull request #11431 from jroessler-ox/docs-kskzskroll-update
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc7.cc
1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
3 #endif
4
5 #include <boost/test/unit_test.hpp>
6
7 #include "test-syncres_cc.hh"
8
9 BOOST_AUTO_TEST_SUITE(syncres_cc7)
10
11 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut)
12 {
13 std::unique_ptr<SyncRes> sr;
14 initSR(sr, true);
15
16 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
17
18 primeHints();
19 const DNSName target("www.sub.powerdns.com.");
20 const ComboAddress targetAddr("192.0.2.42");
21 testkeysset_t keys;
22
23 auto luaconfsCopy = g_luaconfs.getCopy();
24 luaconfsCopy.dsAnchors.clear();
25 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
26 /* No key material for .com */
27 /* But TA for sub.powerdns.com. */
28 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
29 luaconfsCopy.dsAnchors[DNSName("sub.powerdns.com.")].insert(keys[DNSName("sub.powerdns.com.")].second);
30 g_luaconfs.setState(luaconfsCopy);
31
32 size_t queriesCount = 0;
33
34 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
35 queriesCount++;
36
37 if (type == QType::DS) {
38 if (domain == DNSName("www.sub.powerdns.com")) {
39 setLWResult(res, 0, true, false, true);
40 addRecordToLW(res, DNSName("sub.powerdns.com"), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
41 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
42 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), {QType::A}, 600, res->d_records);
43 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
44 }
45 else {
46 setLWResult(res, 0, true, false, true);
47
48 if (domain == DNSName("com.")) {
49 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
50 addRRSIG(keys, res->d_records, DNSName("."), 300);
51 /* no DS */
52 addNSECRecordToLW(DNSName("com."), DNSName("dom."), {QType::NS}, 600, res->d_records);
53 addRRSIG(keys, res->d_records, DNSName("."), 300);
54 }
55 else {
56 setLWResult(res, 0, true, false, true);
57 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
58 }
59 }
60 return LWResult::Result::Success;
61 }
62 if (type == QType::DNSKEY) {
63 if (domain == g_rootdnsname || domain == DNSName("sub.powerdns.com.")) {
64 setLWResult(res, 0, true, false, true);
65 addDNSKEY(keys, domain, 300, res->d_records);
66 addRRSIG(keys, res->d_records, domain, 300);
67 return LWResult::Result::Success;
68 }
69 }
70 else {
71 if (isRootServer(address)) {
72 setLWResult(res, 0, false, false, true);
73 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
74 /* no DS */
75 addNSECRecordToLW(DNSName("com."), DNSName("dom."), {QType::NS}, 600, res->d_records);
76 addRRSIG(keys, res->d_records, DNSName("."), 300);
77 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
78 return LWResult::Result::Success;
79 }
80 if (address == ComboAddress("192.0.2.1:53")) {
81 if (domain == DNSName("com.")) {
82 setLWResult(res, 0, true, false, true);
83 addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
84 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
85 }
86 else if (domain.isPartOf(DNSName("powerdns.com."))) {
87 setLWResult(res, 0, false, false, true);
88 addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
89 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
90 }
91 return LWResult::Result::Success;
92 }
93 if (address == ComboAddress("192.0.2.2:53")) {
94 setLWResult(res, 0, true, false, true);
95 if (type == QType::NS) {
96 if (domain == DNSName("www.sub.powerdns.com.")) {
97 addRecordToLW(res, DNSName("sub.powerdns.com"), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
98 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
99 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), {QType::A}, 600, res->d_records);
100 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
101 }
102 else if (domain == DNSName("sub.powerdns.com.")) {
103 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
104 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com."), 300);
105 }
106 else if (domain == DNSName("powerdns.com.")) {
107 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
108 }
109 }
110 else if (domain == DNSName("www.sub.powerdns.com.")) {
111 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
112 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com."), 300);
113 }
114 return LWResult::Result::Success;
115 }
116 }
117
118 return LWResult::Result::Timeout;
119 });
120
121 vector<DNSRecord> ret;
122 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
123 BOOST_CHECK_EQUAL(res, RCode::NoError);
124 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
125 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
126 BOOST_CHECK(ret[0].d_type == QType::A);
127 BOOST_CHECK_EQUAL(queriesCount, 5U);
128
129 /* again, to test the cache */
130 ret.clear();
131 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
132 BOOST_CHECK_EQUAL(res, RCode::NoError);
133 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
134 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
135 BOOST_CHECK(ret[0].d_type == QType::A);
136 BOOST_CHECK_EQUAL(queriesCount, 5U);
137 }
138
139 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata)
140 {
141 std::unique_ptr<SyncRes> sr;
142 initSR(sr, true);
143
144 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
145
146 primeHints();
147 const DNSName target("powerdns.com.");
148 testkeysset_t keys;
149
150 auto luaconfsCopy = g_luaconfs.getCopy();
151 luaconfsCopy.dsAnchors.clear();
152 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
153 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
154
155 g_luaconfs.setState(luaconfsCopy);
156
157 size_t queriesCount = 0;
158
159 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
160 queriesCount++;
161
162 if (type == QType::DS) {
163 if (domain == target) {
164 setLWResult(res, 0, true, false, true);
165 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
166 addRRSIG(keys, res->d_records, DNSName("com."), 300);
167 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
168 addRRSIG(keys, res->d_records, DNSName("com."), 300);
169 return LWResult::Result::Success;
170 }
171 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
172 }
173 else if (type == QType::DNSKEY) {
174 if (domain == g_rootdnsname || domain == DNSName("com.")) {
175 setLWResult(res, 0, true, false, true);
176 addDNSKEY(keys, domain, 300, res->d_records);
177 addRRSIG(keys, res->d_records, domain, 300);
178 return LWResult::Result::Success;
179 }
180 setLWResult(res, 0, true, false, true);
181 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
182 return LWResult::Result::Success;
183 }
184 else {
185 if (isRootServer(address)) {
186 setLWResult(res, 0, false, false, true);
187 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
188 addDS(DNSName("com."), 300, res->d_records, keys);
189 addRRSIG(keys, res->d_records, DNSName("."), 300);
190 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
191 return LWResult::Result::Success;
192 }
193 if (address == ComboAddress("192.0.2.1:53")) {
194 if (domain == DNSName("com.")) {
195 setLWResult(res, 0, true, false, true);
196 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
197 addRRSIG(keys, res->d_records, DNSName("com."), 300);
198 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
199 addRRSIG(keys, res->d_records, DNSName("com."), 300);
200 }
201 else {
202 setLWResult(res, 0, false, false, true);
203 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
204 /* no DS */
205 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
206 addRRSIG(keys, res->d_records, DNSName("com."), 300);
207 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
208 }
209 return LWResult::Result::Success;
210 }
211 if (address == ComboAddress("192.0.2.2:53")) {
212 if (type == QType::NS) {
213 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
214 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
215 }
216 else {
217 setLWResult(res, 0, true, false, true);
218 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
219 }
220 return LWResult::Result::Success;
221 }
222 }
223
224 return LWResult::Result::Timeout;
225 });
226
227 vector<DNSRecord> ret;
228 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
229 BOOST_CHECK_EQUAL(res, RCode::NoError);
230 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
231 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
232 /* 4 NS (com from root, com from com, powerdns.com from com,
233 powerdns.com from powerdns.com)
234 2 DNSKEY (. and com., none for powerdns.com because no DS)
235 1 query for A
236 */
237 BOOST_CHECK_EQUAL(queriesCount, 5U);
238
239 /* again, to test the cache */
240 ret.clear();
241 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
242 BOOST_CHECK_EQUAL(res, RCode::NoError);
243 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
244 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
245 BOOST_CHECK_EQUAL(queriesCount, 5U);
246
247 /* Request the DS for powerdns.com, which does not exist. We should get
248 the denial proof AND the SOA */
249 ret.clear();
250 res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
251 BOOST_CHECK_EQUAL(res, RCode::NoError);
252 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
253 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
254 bool soaFound = false;
255 for (const auto& record : ret) {
256 if (record.d_type == QType::SOA) {
257 soaFound = true;
258 break;
259 }
260 }
261 BOOST_CHECK_EQUAL(soaFound, true);
262 BOOST_CHECK_EQUAL(queriesCount, 6U);
263 }
264
265 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname)
266 {
267 std::unique_ptr<SyncRes> sr;
268 initSR(sr, true);
269
270 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
271
272 primeHints();
273 const DNSName target("powerdns.com.");
274 const DNSName targetCName("power-dns.com.");
275 const ComboAddress targetCNameAddr("192.0.2.42");
276 testkeysset_t keys;
277
278 auto luaconfsCopy = g_luaconfs.getCopy();
279 luaconfsCopy.dsAnchors.clear();
280 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
281 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
282 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
283 g_luaconfs.setState(luaconfsCopy);
284
285 size_t queriesCount = 0;
286
287 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
288 queriesCount++;
289
290 if (type == QType::DS) {
291 if (domain == targetCName) {
292 setLWResult(res, 0, true, false, true);
293 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
294 addRRSIG(keys, res->d_records, DNSName("com."), 300);
295 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
296 addRRSIG(keys, res->d_records, DNSName("com."), 300);
297 return LWResult::Result::Success;
298 }
299 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
300 }
301 if (type == QType::DNSKEY) {
302 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
303 setLWResult(res, 0, true, false, true);
304 addDNSKEY(keys, domain, 300, res->d_records);
305 addRRSIG(keys, res->d_records, domain, 300);
306 return LWResult::Result::Success;
307 }
308 setLWResult(res, 0, true, false, true);
309 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
310 return LWResult::Result::Success;
311 }
312 else {
313 if (isRootServer(address)) {
314 setLWResult(res, 0, false, false, true);
315 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
316 addDS(DNSName("com."), 300, res->d_records, keys);
317 addRRSIG(keys, res->d_records, DNSName("."), 300);
318 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
319 return LWResult::Result::Success;
320 }
321 if (address == ComboAddress("192.0.2.1:53")) {
322 setLWResult(res, 0, false, false, true);
323 if (domain == DNSName("com.")) {
324 setLWResult(res, 0, true, false, true);
325 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
326 addRRSIG(keys, res->d_records, DNSName("com."), 300);
327 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
328 addRRSIG(keys, res->d_records, DNSName("com."), 300);
329 }
330 else {
331 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
332 if (domain == DNSName("powerdns.com.")) {
333 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
334 }
335 else if (domain == targetCName) {
336 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
337 }
338 addRRSIG(keys, res->d_records, DNSName("com."), 300);
339 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
340 }
341
342 return LWResult::Result::Success;
343 }
344 if (address == ComboAddress("192.0.2.2:53")) {
345 setLWResult(res, 0, true, false, true);
346
347 if (type == QType::NS) {
348 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
349 if (domain == DNSName("powerdns.com.")) {
350 addRRSIG(keys, res->d_records, domain, 300);
351 }
352 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
353 if (domain == DNSName("powerdns.com.")) {
354 addRRSIG(keys, res->d_records, domain, 300);
355 }
356 }
357 else {
358 if (domain == DNSName("powerdns.com.")) {
359 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
360 addRRSIG(keys, res->d_records, domain, 300);
361 }
362 else if (domain == targetCName) {
363 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
364 }
365 }
366
367 return LWResult::Result::Success;
368 }
369 }
370
371 return LWResult::Result::Timeout;
372 });
373
374 vector<DNSRecord> ret;
375 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
376 BOOST_CHECK_EQUAL(res, RCode::NoError);
377 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
378 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
379 BOOST_CHECK_EQUAL(queriesCount, 8U);
380
381 /* again, to test the cache */
382 ret.clear();
383 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
384 BOOST_CHECK_EQUAL(res, RCode::NoError);
385 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
386 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
387 BOOST_CHECK_EQUAL(queriesCount, 8U);
388 }
389
390 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname_glue)
391 {
392 std::unique_ptr<SyncRes> sr;
393 initSR(sr, true);
394
395 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
396
397 primeHints();
398 const DNSName target("powerdns.com.");
399 const DNSName targetCName1("cname.sub.powerdns.com.");
400 const DNSName targetCName2("cname2.sub.powerdns.com.");
401 const ComboAddress targetCName2Addr("192.0.2.42");
402 testkeysset_t keys;
403
404 auto luaconfsCopy = g_luaconfs.getCopy();
405 luaconfsCopy.dsAnchors.clear();
406 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
407 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
408 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
409 g_luaconfs.setState(luaconfsCopy);
410
411 size_t queriesCount = 0;
412
413 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
414 queriesCount++;
415
416 if (type == QType::DS || type == QType::DNSKEY) {
417 if (domain == DNSName("sub.powerdns.com")) {
418 setLWResult(res, 0, true, false, true);
419 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
420 addRRSIG(keys, res->d_records, DNSName("com."), 300);
421 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
422 addRRSIG(keys, res->d_records, DNSName("com."), 300);
423 return LWResult::Result::Success;
424 }
425 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
426 }
427 {
428 if (isRootServer(address)) {
429 setLWResult(res, 0, false, false, true);
430 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
431 addDS(DNSName("com."), 300, res->d_records, keys);
432 addRRSIG(keys, res->d_records, DNSName("."), 300);
433 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
434 return LWResult::Result::Success;
435 }
436 if (address == ComboAddress("192.0.2.1:53")) {
437 setLWResult(res, 0, false, false, true);
438 if (domain == DNSName("com.")) {
439 setLWResult(res, 0, true, false, true);
440 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
441 addRRSIG(keys, res->d_records, DNSName("com."), 300);
442 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
443 addRRSIG(keys, res->d_records, DNSName("com."), 300);
444 }
445 else {
446 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
447 if (domain == DNSName("powerdns.com.")) {
448 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
449 }
450 else if (domain == DNSName("sub.powerdns.com")) {
451 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
452 }
453 addRRSIG(keys, res->d_records, DNSName("com."), 300);
454 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
455 }
456
457 return LWResult::Result::Success;
458 }
459 if (address == ComboAddress("192.0.2.2:53")) {
460 setLWResult(res, 0, true, false, true);
461
462 if (type == QType::NS) {
463 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
464 if (domain == DNSName("powerdns.com.")) {
465 addRRSIG(keys, res->d_records, domain, 300);
466 }
467 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
468 if (domain == DNSName("powerdns.com.")) {
469 addRRSIG(keys, res->d_records, domain, 300);
470 }
471 }
472 else {
473 if (domain == DNSName("powerdns.com.")) {
474 addRecordToLW(res, domain, QType::CNAME, targetCName1.toString());
475 addRRSIG(keys, res->d_records, domain, 300);
476 /* add the CNAME target as a glue, with no RRSIG since the sub zone is insecure */
477 addRecordToLW(res, targetCName1, QType::CNAME, targetCName2.toString());
478 addRecordToLW(res, targetCName2, QType::A, targetCName2Addr.toString());
479 }
480 else if (domain == targetCName1) {
481 addRecordToLW(res, domain, QType::CNAME, targetCName2.toString());
482 }
483 else if (domain == targetCName2) {
484 addRecordToLW(res, domain, QType::A, targetCName2Addr.toString());
485 }
486 }
487
488 return LWResult::Result::Success;
489 }
490 }
491
492 return LWResult::Result::Timeout;
493 });
494
495 vector<DNSRecord> ret;
496 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
497 BOOST_CHECK_EQUAL(res, RCode::NoError);
498 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
499 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
500 BOOST_CHECK_EQUAL(queriesCount, 9U);
501
502 /* again, to test the cache */
503 ret.clear();
504 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
505 BOOST_CHECK_EQUAL(res, RCode::NoError);
506 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
507 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
508 BOOST_CHECK_EQUAL(queriesCount, 9U);
509 }
510
511 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname)
512 {
513 std::unique_ptr<SyncRes> sr;
514 initSR(sr, true);
515
516 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
517
518 primeHints();
519 const DNSName target("power-dns.com.");
520 const DNSName targetCName("powerdns.com.");
521 const ComboAddress targetCNameAddr("192.0.2.42");
522 testkeysset_t keys;
523
524 auto luaconfsCopy = g_luaconfs.getCopy();
525 luaconfsCopy.dsAnchors.clear();
526 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
527 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
528 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
529 g_luaconfs.setState(luaconfsCopy);
530
531 size_t queriesCount = 0;
532
533 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
534 queriesCount++;
535
536 if (type == QType::DS) {
537 if (domain == DNSName("power-dns.com.")) {
538 setLWResult(res, 0, true, false, true);
539 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
540 addRRSIG(keys, res->d_records, DNSName("com."), 300);
541 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
542 addRRSIG(keys, res->d_records, DNSName("com."), 300);
543 return LWResult::Result::Success;
544 }
545 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
546 }
547 if (type == QType::DNSKEY) {
548 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
549 setLWResult(res, 0, true, false, true);
550 addDNSKEY(keys, domain, 300, res->d_records);
551 addRRSIG(keys, res->d_records, domain, 300);
552 return LWResult::Result::Success;
553 }
554 setLWResult(res, 0, true, false, true);
555 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
556 return LWResult::Result::Success;
557 }
558 else {
559 if (isRootServer(address)) {
560 setLWResult(res, 0, false, false, true);
561 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
562 addDS(DNSName("com."), 300, res->d_records, keys);
563 addRRSIG(keys, res->d_records, DNSName("."), 300);
564 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
565 return LWResult::Result::Success;
566 }
567 if (address == ComboAddress("192.0.2.1:53")) {
568 if (domain == DNSName("com.")) {
569 setLWResult(res, 0, true, false, true);
570 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
571 addRRSIG(keys, res->d_records, DNSName("com."), 300);
572 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
573 addRRSIG(keys, res->d_records, DNSName("com."), 300);
574 }
575 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
576 setLWResult(res, 0, false, false, true);
577 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
578 if (domain == targetCName) {
579 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
580 }
581 else if (domain == target) {
582 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
583 }
584 addRRSIG(keys, res->d_records, DNSName("com."), 300);
585 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
586 }
587 return LWResult::Result::Success;
588 }
589 if (address == ComboAddress("192.0.2.2:53")) {
590 setLWResult(res, 0, true, false, true);
591 if (type == QType::NS) {
592 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
593 if (domain == DNSName("powerdns.com.")) {
594 addRRSIG(keys, res->d_records, domain, 300);
595 }
596 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
597 if (domain == DNSName("powerdns.com.")) {
598 addRRSIG(keys, res->d_records, domain, 300);
599 }
600 }
601 else {
602 if (domain == target) {
603 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
604 }
605 else if (domain == targetCName) {
606 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
607 addRRSIG(keys, res->d_records, domain, 300);
608 }
609 }
610 return LWResult::Result::Success;
611 }
612 }
613
614 return LWResult::Result::Timeout;
615 });
616
617 vector<DNSRecord> ret;
618 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
619 BOOST_CHECK_EQUAL(res, RCode::NoError);
620 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
621 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
622 BOOST_CHECK_EQUAL(queriesCount, 8U);
623
624 /* again, to test the cache */
625 ret.clear();
626 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
627 BOOST_CHECK_EQUAL(res, RCode::NoError);
628 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
629 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
630 BOOST_CHECK_EQUAL(queriesCount, 8U);
631 }
632
633 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname)
634 {
635 std::unique_ptr<SyncRes> sr;
636 initSR(sr, true);
637
638 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
639
640 primeHints();
641 const DNSName target("power-dns.com.");
642 const DNSName targetCName("powerdns.com.");
643 const ComboAddress targetCNameAddr("192.0.2.42");
644 testkeysset_t keys;
645
646 auto luaconfsCopy = g_luaconfs.getCopy();
647 luaconfsCopy.dsAnchors.clear();
648 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
649 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
650 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
651 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
652 g_luaconfs.setState(luaconfsCopy);
653
654 size_t queriesCount = 0;
655
656 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
657 queriesCount++;
658
659 if (type == QType::DS || type == QType::DNSKEY) {
660 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
661 }
662 {
663 if (isRootServer(address)) {
664 setLWResult(res, 0, false, false, true);
665 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
666 addDS(DNSName("com."), 300, res->d_records, keys);
667 addRRSIG(keys, res->d_records, DNSName("."), 300);
668 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
669 return LWResult::Result::Success;
670 }
671 if (address == ComboAddress("192.0.2.1:53")) {
672 if (domain == DNSName("com.")) {
673 setLWResult(res, 0, true, false, true);
674 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
675 addRRSIG(keys, res->d_records, DNSName("com."), 300);
676 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
677 addRRSIG(keys, res->d_records, DNSName("com."), 300);
678 }
679 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
680 setLWResult(res, 0, false, false, true);
681 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
682 addDS(DNSName(domain), 300, res->d_records, keys);
683 addRRSIG(keys, res->d_records, DNSName("com."), 300);
684 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
685 }
686 return LWResult::Result::Success;
687 }
688 if (address == ComboAddress("192.0.2.2:53")) {
689 setLWResult(res, 0, true, false, true);
690 if (type == QType::NS) {
691 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
692 addRRSIG(keys, res->d_records, domain, 300);
693 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
694 addRRSIG(keys, res->d_records, domain, 300);
695 }
696 else {
697 if (domain == target) {
698 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
699 /* No RRSIG, leading to bogus */
700 }
701 else if (domain == targetCName) {
702 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
703 addRRSIG(keys, res->d_records, domain, 300);
704 }
705 }
706 return LWResult::Result::Success;
707 }
708 }
709
710 return LWResult::Result::Timeout;
711 });
712
713 vector<DNSRecord> ret;
714 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
715 BOOST_CHECK_EQUAL(res, RCode::NoError);
716 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
717 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
718 BOOST_CHECK_EQUAL(queriesCount, 8U);
719
720 /* again, to test the cache */
721 ret.clear();
722 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
723 BOOST_CHECK_EQUAL(res, RCode::NoError);
724 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
725 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
726 BOOST_CHECK_EQUAL(queriesCount, 8U);
727 }
728
729 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname)
730 {
731 std::unique_ptr<SyncRes> sr;
732 initSR(sr, true);
733
734 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
735
736 primeHints();
737 const DNSName target("power-dns.com.");
738 const DNSName targetCName("powerdns.com.");
739 const ComboAddress targetCNameAddr("192.0.2.42");
740 testkeysset_t keys;
741
742 auto luaconfsCopy = g_luaconfs.getCopy();
743 luaconfsCopy.dsAnchors.clear();
744 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
745 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
746 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
747 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
748 g_luaconfs.setState(luaconfsCopy);
749
750 size_t queriesCount = 0;
751
752 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
753 queriesCount++;
754
755 if (type == QType::DS || type == QType::DNSKEY) {
756 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
757 }
758 {
759 if (isRootServer(address)) {
760 setLWResult(res, 0, false, false, true);
761 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
762 addDS(DNSName("com."), 300, res->d_records, keys);
763 addRRSIG(keys, res->d_records, DNSName("."), 300);
764 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
765 return LWResult::Result::Success;
766 }
767 if (address == ComboAddress("192.0.2.1:53")) {
768 if (domain == DNSName("com.")) {
769 setLWResult(res, 0, true, false, true);
770 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
771 addRRSIG(keys, res->d_records, DNSName("com."), 300);
772 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
773 addRRSIG(keys, res->d_records, DNSName("com."), 300);
774 }
775 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
776 setLWResult(res, 0, false, false, true);
777 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
778 addDS(DNSName(domain), 300, res->d_records, keys);
779 addRRSIG(keys, res->d_records, DNSName("com."), 300);
780 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
781 }
782 return LWResult::Result::Success;
783 }
784 if (address == ComboAddress("192.0.2.2:53")) {
785 setLWResult(res, 0, true, false, true);
786 if (type == QType::NS) {
787 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
788 addRRSIG(keys, res->d_records, domain, 300);
789 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
790 addRRSIG(keys, res->d_records, domain, 300);
791 }
792 else {
793 if (domain == target) {
794 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
795 addRRSIG(keys, res->d_records, domain, 300);
796 }
797 else if (domain == targetCName) {
798 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
799 /* No RRSIG, leading to bogus */
800 }
801 }
802 return LWResult::Result::Success;
803 }
804 }
805
806 return LWResult::Result::Timeout;
807 });
808
809 vector<DNSRecord> ret;
810 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
811 BOOST_CHECK_EQUAL(res, RCode::NoError);
812 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
813 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
814 BOOST_CHECK_EQUAL(queriesCount, 8U);
815
816 /* again, to test the cache */
817 ret.clear();
818 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
819 BOOST_CHECK_EQUAL(res, RCode::NoError);
820 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
821 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
822 BOOST_CHECK_EQUAL(queriesCount, 8U);
823 }
824
825 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname)
826 {
827 std::unique_ptr<SyncRes> sr;
828 initSR(sr, true);
829
830 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
831
832 primeHints();
833 const DNSName target("power-dns.com.");
834 const DNSName targetCName("powerdns.com.");
835 const ComboAddress targetCNameAddr("192.0.2.42");
836 testkeysset_t keys;
837
838 auto luaconfsCopy = g_luaconfs.getCopy();
839 luaconfsCopy.dsAnchors.clear();
840 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
841 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
842 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
843 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
844 g_luaconfs.setState(luaconfsCopy);
845
846 size_t queriesCount = 0;
847
848 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
849 queriesCount++;
850
851 if (type == QType::DS || type == QType::DNSKEY) {
852 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
853 }
854 {
855 if (isRootServer(address)) {
856 setLWResult(res, 0, false, false, true);
857 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
858 addDS(DNSName("com."), 300, res->d_records, keys);
859 addRRSIG(keys, res->d_records, DNSName("."), 300);
860 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
861 return LWResult::Result::Success;
862 }
863 if (address == ComboAddress("192.0.2.1:53")) {
864 if (domain == DNSName("com.")) {
865 setLWResult(res, 0, true, false, true);
866 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
867 addRRSIG(keys, res->d_records, DNSName("com."), 300);
868 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
869 addRRSIG(keys, res->d_records, DNSName("com."), 300);
870 }
871 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
872 setLWResult(res, 0, false, false, true);
873 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
874 addDS(DNSName(domain), 300, res->d_records, keys);
875 addRRSIG(keys, res->d_records, DNSName("com."), 300);
876 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
877 }
878 return LWResult::Result::Success;
879 }
880 if (address == ComboAddress("192.0.2.2:53")) {
881 setLWResult(res, 0, true, false, true);
882 if (type == QType::NS) {
883 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
884 addRRSIG(keys, res->d_records, domain, 300);
885 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
886 addRRSIG(keys, res->d_records, domain, 300);
887 }
888 else {
889 if (domain == target) {
890 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
891 addRRSIG(keys, res->d_records, domain, 300);
892 }
893 else if (domain == targetCName) {
894 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
895 addRRSIG(keys, res->d_records, domain, 300);
896 }
897 }
898 return LWResult::Result::Success;
899 }
900 }
901
902 return LWResult::Result::Timeout;
903 });
904
905 vector<DNSRecord> ret;
906 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
907 BOOST_CHECK_EQUAL(res, RCode::NoError);
908 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
909 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
910 BOOST_CHECK_EQUAL(queriesCount, 9U);
911
912 /* again, to test the cache */
913 ret.clear();
914 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
915 BOOST_CHECK_EQUAL(res, RCode::NoError);
916 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
917 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
918 BOOST_CHECK_EQUAL(queriesCount, 9U);
919 }
920
921 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname)
922 {
923 std::unique_ptr<SyncRes> sr;
924 initSR(sr, true);
925
926 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
927
928 primeHints();
929 const DNSName target("powerdns.com.");
930 const DNSName targetCName("power-dns.com.");
931 const ComboAddress targetCNameAddr("192.0.2.42");
932 testkeysset_t keys;
933
934 auto luaconfsCopy = g_luaconfs.getCopy();
935 luaconfsCopy.dsAnchors.clear();
936 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
937 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
938 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
939 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
940 g_luaconfs.setState(luaconfsCopy);
941
942 size_t queriesCount = 0;
943
944 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
945 queriesCount++;
946
947 if (type == QType::DS) {
948 if (domain == DNSName("power-dns.com.")) {
949 setLWResult(res, 0, true, false, true);
950 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
951 addRRSIG(keys, res->d_records, DNSName("com."), 300);
952 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
953 addRRSIG(keys, res->d_records, DNSName("com."), 300);
954 return LWResult::Result::Success;
955 }
956 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
957 }
958 if (type == QType::DNSKEY) {
959 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
960 setLWResult(res, 0, true, false, true);
961 addDNSKEY(keys, domain, 300, res->d_records);
962 addRRSIG(keys, res->d_records, domain, 300);
963 return LWResult::Result::Success;
964 }
965 setLWResult(res, 0, true, false, true);
966 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
967 return LWResult::Result::Success;
968 }
969 else {
970 if (isRootServer(address)) {
971 setLWResult(res, 0, false, false, true);
972 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
973 addDS(DNSName("com."), 300, res->d_records, keys);
974 addRRSIG(keys, res->d_records, DNSName("."), 300);
975 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
976 return LWResult::Result::Success;
977 }
978 if (address == ComboAddress("192.0.2.1:53")) {
979 if (domain == DNSName("com.")) {
980 setLWResult(res, 0, true, false, true);
981 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
982 addRRSIG(keys, res->d_records, DNSName("com."), 300);
983 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
984 addRRSIG(keys, res->d_records, DNSName("com."), 300);
985 }
986 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
987 setLWResult(res, 0, false, false, true);
988 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
989 if (domain == DNSName("powerdns.com.")) {
990 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
991 }
992 else if (domain == targetCName) {
993 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
994 }
995 addRRSIG(keys, res->d_records, DNSName("com."), 300);
996 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
997 }
998 return LWResult::Result::Success;
999 }
1000 if (address == ComboAddress("192.0.2.2:53")) {
1001 setLWResult(res, 0, true, false, true);
1002 if (type == QType::NS) {
1003 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
1004 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1005 }
1006 else {
1007 if (domain == DNSName("powerdns.com.")) {
1008 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
1009 /* No RRSIG -> Bogus */
1010 }
1011 else if (domain == targetCName) {
1012 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
1013 }
1014 }
1015 return LWResult::Result::Success;
1016 }
1017 }
1018
1019 return LWResult::Result::Timeout;
1020 });
1021
1022 vector<DNSRecord> ret;
1023 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1024 BOOST_CHECK_EQUAL(res, RCode::NoError);
1025 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1026 /* no RRSIG to show */
1027 BOOST_CHECK_EQUAL(ret.size(), 2U);
1028 BOOST_CHECK_EQUAL(queriesCount, 7U);
1029
1030 /* again, to test the cache */
1031 ret.clear();
1032 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1033 BOOST_CHECK_EQUAL(res, RCode::NoError);
1034 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1035 BOOST_CHECK_EQUAL(ret.size(), 2U);
1036 BOOST_CHECK_EQUAL(queriesCount, 7U);
1037 }
1038
1039 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta)
1040 {
1041 std::unique_ptr<SyncRes> sr;
1042 initSR(sr, true);
1043
1044 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1045
1046 primeHints();
1047 const DNSName target("powerdns.com.");
1048 const ComboAddress targetAddr("192.0.2.42");
1049 testkeysset_t keys;
1050
1051 auto luaconfsCopy = g_luaconfs.getCopy();
1052 luaconfsCopy.dsAnchors.clear();
1053 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1054 /* No key material for .com */
1055 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1056 luaconfsCopy.dsAnchors[target].insert(keys[target].second);
1057 g_luaconfs.setState(luaconfsCopy);
1058
1059 size_t queriesCount = 0;
1060
1061 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1062 queriesCount++;
1063
1064 if (type == QType::DNSKEY) {
1065 if (domain == g_rootdnsname || domain == DNSName("powerdns.com.")) {
1066 setLWResult(res, 0, true, false, true);
1067 addDNSKEY(keys, domain, 300, res->d_records);
1068 addRRSIG(keys, res->d_records, domain, 300);
1069 return LWResult::Result::Success;
1070 }
1071 if (domain == DNSName("com.")) {
1072 setLWResult(res, 0, true, false, true);
1073 addRecordToLW(res, domain, QType::SOA, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1074 return LWResult::Result::Success;
1075 }
1076 }
1077 else {
1078 if (isRootServer(address)) {
1079 setLWResult(res, 0, false, false, true);
1080 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
1081 addNSECRecordToLW(DNSName("com."), DNSName("com."), {QType::NS}, 600, res->d_records);
1082 addRRSIG(keys, res->d_records, DNSName("."), 300);
1083 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1084 return LWResult::Result::Success;
1085 }
1086 if (address == ComboAddress("192.0.2.1:53")) {
1087 if (target == domain) {
1088 setLWResult(res, 0, false, false, true);
1089 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
1090 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1091 }
1092 else if (domain == DNSName("com.")) {
1093 setLWResult(res, 0, true, false, true);
1094 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
1095 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1096 }
1097 return LWResult::Result::Success;
1098 }
1099 if (address == ComboAddress("192.0.2.2:53")) {
1100 setLWResult(res, 0, true, false, true);
1101 if (type == QType::NS) {
1102 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
1103 }
1104 else {
1105 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
1106 }
1107 addRRSIG(keys, res->d_records, domain, 300);
1108 return LWResult::Result::Success;
1109 }
1110 }
1111
1112 return LWResult::Result::Timeout;
1113 });
1114
1115 vector<DNSRecord> ret;
1116 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1117 BOOST_CHECK_EQUAL(res, RCode::NoError);
1118 /* should be insecure but we have a TA for powerdns.com. */
1119 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
1120 /* We got a RRSIG */
1121 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1122 BOOST_CHECK(ret[0].d_type == QType::A);
1123 BOOST_CHECK_EQUAL(queriesCount, 5U);
1124
1125 /* again, to test the cache */
1126 ret.clear();
1127 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1128 BOOST_CHECK_EQUAL(res, RCode::NoError);
1129 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
1130 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1131 BOOST_CHECK(ret[0].d_type == QType::A);
1132 BOOST_CHECK_EQUAL(queriesCount, 5U);
1133 }
1134
1135 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig)
1136 {
1137 std::unique_ptr<SyncRes> sr;
1138 initSR(sr, true);
1139
1140 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1141
1142 primeHints();
1143 const DNSName target("powerdns.com.");
1144 const ComboAddress targetAddr("192.0.2.42");
1145 testkeysset_t keys;
1146
1147 auto luaconfsCopy = g_luaconfs.getCopy();
1148 luaconfsCopy.dsAnchors.clear();
1149 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1150 /* No key material for .com */
1151 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1152 luaconfsCopy.dsAnchors[target].insert(keys[target].second);
1153 g_luaconfs.setState(luaconfsCopy);
1154
1155 size_t queriesCount = 0;
1156
1157 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1158 queriesCount++;
1159
1160 if (type == QType::DNSKEY) {
1161 if (domain == g_rootdnsname || domain == DNSName("powerdns.com.")) {
1162 setLWResult(res, 0, true, false, true);
1163 addDNSKEY(keys, domain, 300, res->d_records);
1164 addRRSIG(keys, res->d_records, domain, 300);
1165 return LWResult::Result::Success;
1166 }
1167 if (domain == DNSName("com.")) {
1168 setLWResult(res, 0, true, false, true);
1169 addRecordToLW(res, domain, QType::SOA, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1170 return LWResult::Result::Success;
1171 }
1172 }
1173 else {
1174 if (target.isPartOf(domain) && isRootServer(address)) {
1175 setLWResult(res, 0, false, false, true);
1176 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
1177 addNSECRecordToLW(DNSName("com."), DNSName("com."), {QType::NS}, 600, res->d_records);
1178 addRRSIG(keys, res->d_records, DNSName("."), 300);
1179 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1180 return LWResult::Result::Success;
1181 }
1182 if (address == ComboAddress("192.0.2.1:53")) {
1183 if (target == domain) {
1184 setLWResult(res, 0, false, false, true);
1185 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
1186 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1187 }
1188 else if (domain == DNSName("com.")) {
1189 setLWResult(res, 0, true, false, true);
1190 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
1191 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1192 }
1193 return LWResult::Result::Success;
1194 }
1195 if (domain == target && address == ComboAddress("192.0.2.2:53")) {
1196 setLWResult(res, 0, true, false, true);
1197 if (type == QType::NS) {
1198 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
1199 }
1200 else {
1201 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
1202 }
1203 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
1204 return LWResult::Result::Success;
1205 }
1206 }
1207
1208 return LWResult::Result::Timeout;
1209 });
1210
1211 vector<DNSRecord> ret;
1212 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1213 BOOST_CHECK_EQUAL(res, RCode::NoError);
1214 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
1215 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1216 /* No RRSIG */
1217 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1218 BOOST_CHECK(ret[0].d_type == QType::A);
1219 BOOST_CHECK_EQUAL(queriesCount, 4U);
1220
1221 /* again, to test the cache */
1222 ret.clear();
1223 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1224 BOOST_CHECK_EQUAL(res, RCode::NoError);
1225 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1226 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1227 BOOST_CHECK(ret[0].d_type == QType::A);
1228 BOOST_CHECK_EQUAL(queriesCount, 4U);
1229 }
1230
1231 BOOST_AUTO_TEST_CASE(test_dnssec_nta)
1232 {
1233 std::unique_ptr<SyncRes> sr;
1234 initSR(sr, true);
1235
1236 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1237
1238 primeHints();
1239 const DNSName target(".");
1240 testkeysset_t keys;
1241
1242 auto luaconfsCopy = g_luaconfs.getCopy();
1243 luaconfsCopy.dsAnchors.clear();
1244 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1245 /* Add a NTA for "." */
1246 luaconfsCopy.negAnchors[g_rootdnsname] = "NTA for Root";
1247 g_luaconfs.setState(luaconfsCopy);
1248
1249 size_t queriesCount = 0;
1250
1251 sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1252 queriesCount++;
1253
1254 if (domain == target && type == QType::NS) {
1255
1256 setLWResult(res, 0, true, false, true);
1257 char addr[] = "a.root-servers.net.";
1258 for (char idx = 'a'; idx <= 'm'; idx++) {
1259 addr[0] = idx;
1260 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1261 }
1262
1263 addRRSIG(keys, res->d_records, domain, 300);
1264
1265 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1266 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1267
1268 return LWResult::Result::Success;
1269 }
1270 if (domain == target && type == QType::DNSKEY) {
1271
1272 setLWResult(res, 0, true, false, true);
1273
1274 /* No DNSKEY */
1275
1276 return LWResult::Result::Success;
1277 }
1278
1279 return LWResult::Result::Timeout;
1280 });
1281
1282 vector<DNSRecord> ret;
1283 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1284 BOOST_CHECK_EQUAL(res, RCode::NoError);
1285 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1286 /* 13 NS + 1 RRSIG */
1287 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1288 BOOST_CHECK_EQUAL(queriesCount, 1U);
1289
1290 /* again, to test the cache */
1291 ret.clear();
1292 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1293 BOOST_CHECK_EQUAL(res, RCode::NoError);
1294 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1295 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1296 BOOST_CHECK_EQUAL(queriesCount, 1U);
1297 }
1298
1299 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta)
1300 {
1301 std::unique_ptr<SyncRes> sr;
1302 initSR(sr, true);
1303
1304 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1305
1306 primeHints();
1307 const DNSName target(".");
1308 testkeysset_t keys;
1309
1310 /* Remove the root DS */
1311 auto luaconfsCopy = g_luaconfs.getCopy();
1312 luaconfsCopy.dsAnchors.clear();
1313 g_luaconfs.setState(luaconfsCopy);
1314
1315 size_t queriesCount = 0;
1316
1317 sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1318 queriesCount++;
1319
1320 if (domain == target && type == QType::NS) {
1321
1322 setLWResult(res, 0, true, false, true);
1323 char addr[] = "a.root-servers.net.";
1324 for (char idx = 'a'; idx <= 'm'; idx++) {
1325 addr[0] = idx;
1326 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1327 }
1328
1329 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1330 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1331
1332 return LWResult::Result::Success;
1333 }
1334
1335 return LWResult::Result::Timeout;
1336 });
1337
1338 vector<DNSRecord> ret;
1339 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1340 BOOST_CHECK_EQUAL(res, RCode::NoError);
1341 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1342 /* 13 NS + 0 RRSIG */
1343 BOOST_REQUIRE_EQUAL(ret.size(), 13U);
1344 BOOST_CHECK_EQUAL(queriesCount, 1U);
1345
1346 /* again, to test the cache */
1347 ret.clear();
1348 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1349 BOOST_CHECK_EQUAL(res, RCode::NoError);
1350 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1351 BOOST_REQUIRE_EQUAL(ret.size(), 13U);
1352 BOOST_CHECK_EQUAL(queriesCount, 1U);
1353 }
1354
1355 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata)
1356 {
1357 std::unique_ptr<SyncRes> sr;
1358 initSR(sr, true);
1359
1360 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1361
1362 primeHints();
1363 const DNSName target("powerdns.com.");
1364 testkeysset_t keys;
1365
1366 auto luaconfsCopy = g_luaconfs.getCopy();
1367 luaconfsCopy.dsAnchors.clear();
1368 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1369 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1370 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1371 g_luaconfs.setState(luaconfsCopy);
1372
1373 size_t queriesCount = 0;
1374
1375 sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1376 queriesCount++;
1377
1378 if (type == QType::DS || type == QType::DNSKEY) {
1379 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1380 }
1381 if (type == QType::A) {
1382 if (domain == DNSName("com.")) {
1383 setLWResult(res, 0, true, false, true);
1384 addRecordToLW(res, DNSName("com"), QType::SOA, "whatever.com. blah.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1385 addRRSIG(keys, res->d_records, DNSName("com"), 300);
1386 addNSECRecordToLW(DNSName("com"), DNSName("com."), {QType::SOA}, 600, res->d_records);
1387 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1388 return LWResult::Result::Success;
1389 }
1390 if (domain == target) {
1391 setLWResult(res, 0, true, false, true);
1392 return LWResult::Result::Success;
1393 }
1394 }
1395
1396 return LWResult::Result::Timeout;
1397 });
1398
1399 vector<DNSRecord> ret;
1400 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1401 BOOST_CHECK_EQUAL(res, RCode::NoError);
1402 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
1403 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1404 /* powerdns.com|A, com|A, com|DNSKEY, powerdns.com|DS */
1405 BOOST_CHECK_EQUAL(queriesCount, 4U);
1406
1407 /* again, to test the cache */
1408 ret.clear();
1409 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1410 BOOST_CHECK_EQUAL(res, RCode::NoError);
1411 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
1412 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1413 /* we don't store empty results */
1414 BOOST_CHECK_EQUAL(queriesCount, 5U);
1415 }
1416
1417 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_missing_soa_on_nodata)
1418 {
1419 std::unique_ptr<SyncRes> sr;
1420 initSR(sr, true);
1421
1422 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1423
1424 primeHints();
1425 const DNSName target("powerdns.com.");
1426 testkeysset_t keys;
1427
1428 auto luaconfsCopy = g_luaconfs.getCopy();
1429 luaconfsCopy.dsAnchors.clear();
1430 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1431 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1432 g_luaconfs.setState(luaconfsCopy);
1433
1434 size_t queriesCount = 0;
1435
1436 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1437 queriesCount++;
1438
1439 if (type == QType::DS || type == QType::DNSKEY) {
1440 if (domain.isPartOf(target)) {
1441 /* proves cut */
1442 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, true);
1443 }
1444 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1445 }
1446 if (isRootServer(address)) {
1447 setLWResult(res, 0, false, false, true);
1448 addRecordToLW(res, "com.", QType::NS, "ns1.com.", DNSResourceRecord::AUTHORITY, 3600);
1449 addDS(DNSName("com."), 300, res->d_records, keys);
1450 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1451 addRecordToLW(res, "ns1.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1452 return LWResult::Result::Success;
1453 }
1454 else {
1455 if (domain == DNSName("com.")) {
1456 setLWResult(res, 0, true, false, true);
1457 addRecordToLW(res, DNSName("com"), QType::SOA, "whatever.com. blah.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1458 addRRSIG(keys, res->d_records, DNSName("com"), 300);
1459 addNSECRecordToLW(DNSName("com"), DNSName("com."), {QType::SOA}, 600, res->d_records);
1460 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1461 return LWResult::Result::Success;
1462 }
1463 if (domain == target) {
1464 setLWResult(res, 0, true, false, true);
1465 return LWResult::Result::Success;
1466 }
1467 }
1468
1469 return LWResult::Result::Timeout;
1470 });
1471
1472 vector<DNSRecord> ret;
1473 int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
1474 BOOST_CHECK_EQUAL(res, RCode::NoError);
1475 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1476 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1477 /* powerdns.com|A, com|A, com|DNSKEY, powerdns.com|DS */
1478 BOOST_CHECK_EQUAL(queriesCount, 4U);
1479
1480 /* again, to test the cache */
1481 ret.clear();
1482 res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
1483 BOOST_CHECK_EQUAL(res, RCode::NoError);
1484 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1485 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1486 /* we don't store empty results */
1487 BOOST_CHECK_EQUAL(queriesCount, 5U);
1488 }
1489
1490 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_missing_soa_on_nxd)
1491 {
1492 std::unique_ptr<SyncRes> sr;
1493 initSR(sr, true);
1494
1495 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1496
1497 primeHints();
1498 const DNSName target("powerdns.com.");
1499 testkeysset_t keys;
1500
1501 auto luaconfsCopy = g_luaconfs.getCopy();
1502 luaconfsCopy.dsAnchors.clear();
1503 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1504 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1505 g_luaconfs.setState(luaconfsCopy);
1506
1507 size_t queriesCount = 0;
1508
1509 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1510 queriesCount++;
1511
1512 if (type == QType::DS || type == QType::DNSKEY) {
1513 if (domain.isPartOf(target)) {
1514 /* proves cut */
1515 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, true);
1516 }
1517 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1518 }
1519 if (isRootServer(address)) {
1520 setLWResult(res, 0, false, false, true);
1521 addRecordToLW(res, "com.", QType::NS, "ns1.com.", DNSResourceRecord::AUTHORITY, 3600);
1522 addDS(DNSName("com."), 300, res->d_records, keys);
1523 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1524 addRecordToLW(res, "ns1.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1525 return LWResult::Result::Success;
1526 }
1527 else {
1528 if (domain == DNSName("com.")) {
1529 setLWResult(res, 0, true, false, true);
1530 addRecordToLW(res, DNSName("com"), QType::SOA, "whatever.com. blah.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1531 addRRSIG(keys, res->d_records, DNSName("com"), 300);
1532 addNSECRecordToLW(DNSName("com"), DNSName("com."), {QType::SOA}, 600, res->d_records);
1533 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1534 return LWResult::Result::Success;
1535 }
1536 if (domain == target) {
1537 setLWResult(res, RCode::NXDomain, true, false, true);
1538 return LWResult::Result::Success;
1539 }
1540 }
1541
1542 return LWResult::Result::Timeout;
1543 });
1544
1545 vector<DNSRecord> ret;
1546 int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
1547 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1548 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1549 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1550 /* powerdns.com|A, com|A, com|DNSKEY, powerdns.com|DS */
1551 BOOST_CHECK_EQUAL(queriesCount, 4U);
1552
1553 /* again, to test the cache */
1554 ret.clear();
1555 res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
1556 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1557 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1558 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1559 /* we don't store empty results */
1560 BOOST_CHECK_EQUAL(queriesCount, 5U);
1561 }
1562
1563 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nxdomain)
1564 {
1565 std::unique_ptr<SyncRes> sr;
1566 initSR(sr, true);
1567
1568 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1569
1570 primeHints();
1571 const DNSName target("powerdns.com.");
1572 testkeysset_t keys;
1573
1574 auto luaconfsCopy = g_luaconfs.getCopy();
1575 luaconfsCopy.dsAnchors.clear();
1576 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1577 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1578 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1579 g_luaconfs.setState(luaconfsCopy);
1580
1581 size_t queriesCount = 0;
1582
1583 sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1584 queriesCount++;
1585
1586 if (type == QType::DS || type == QType::DNSKEY) {
1587 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1588 }
1589 if (type == QType::A) {
1590 if (domain == DNSName("com.")) {
1591 setLWResult(res, 0, true, false, true);
1592 addRecordToLW(res, DNSName("com"), QType::SOA, "whatever.com. blah.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1593 addRRSIG(keys, res->d_records, DNSName("com"), 300);
1594 addNSECRecordToLW(DNSName("com"), DNSName("com."), {QType::SOA}, 600, res->d_records);
1595 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1596 return LWResult::Result::Success;
1597 }
1598 if (domain == target) {
1599 setLWResult(res, RCode::NXDomain, true, false, true);
1600 return LWResult::Result::Success;
1601 }
1602 }
1603
1604 return LWResult::Result::Timeout;
1605 });
1606
1607 vector<DNSRecord> ret;
1608 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1609 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1610 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
1611 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1612
1613 /* powerdns.com|A, com|A, powerdns.com|DS, com|DNSKEY */
1614 BOOST_CHECK_EQUAL(queriesCount, 4U);
1615
1616 /* again, to test the cache */
1617 ret.clear();
1618 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1619 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1620 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
1621 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1622 /* we don't store empty results */
1623 BOOST_CHECK_EQUAL(queriesCount, 5U);
1624 }
1625
1626 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cut_with_cname_at_apex)
1627 {
1628 std::unique_ptr<SyncRes> sr;
1629 initSR(sr, true);
1630
1631 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1632
1633 primeHints();
1634 const DNSName target("powerdns.com.");
1635 const DNSName targetCName("power-dns.com.");
1636 const ComboAddress targetCNameAddr("192.0.2.42");
1637 testkeysset_t keys;
1638
1639 auto luaconfsCopy = g_luaconfs.getCopy();
1640 luaconfsCopy.dsAnchors.clear();
1641 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1642 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1643 g_luaconfs.setState(luaconfsCopy);
1644
1645 size_t queriesCount = 0;
1646
1647 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1648 queriesCount++;
1649
1650 if (type == QType::DS) {
1651 if (domain == DNSName("www.powerdns.com.") || domain == DNSName("www2.powerdns.com.")) {
1652 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, false);
1653 }
1654 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1655 }
1656 if (type == QType::DNSKEY) {
1657 if (domain == g_rootdnsname || domain == DNSName("com.")) {
1658 setLWResult(res, 0, true, false, true);
1659 addDNSKEY(keys, domain, 300, res->d_records);
1660 addRRSIG(keys, res->d_records, domain, 300);
1661 return LWResult::Result::Success;
1662 }
1663 setLWResult(res, 0, true, false, true);
1664 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1665 return LWResult::Result::Success;
1666 }
1667 else {
1668 if (isRootServer(address)) {
1669 setLWResult(res, 0, false, false, true);
1670 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
1671 addDS(DNSName("com."), 300, res->d_records, keys);
1672 addRRSIG(keys, res->d_records, DNSName("."), 300);
1673 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1674 return LWResult::Result::Success;
1675 }
1676 if (address == ComboAddress("192.0.2.1:53")) {
1677 setLWResult(res, 0, false, false, true);
1678 if (domain == DNSName("com.")) {
1679 setLWResult(res, 0, true, false, true);
1680 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
1681 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1682 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1683 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1684 }
1685 else {
1686 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
1687 if (domain.isPartOf(DNSName("powerdns.com."))) {
1688 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
1689 }
1690 else if (domain == targetCName) {
1691 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), {QType::NS}, 600, res->d_records);
1692 }
1693 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1694 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1695 }
1696
1697 return LWResult::Result::Success;
1698 }
1699 if (address == ComboAddress("192.0.2.2:53")) {
1700 setLWResult(res, 0, true, false, true);
1701
1702 if (type == QType::NS) {
1703 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
1704 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1705 }
1706 else {
1707 if (domain == DNSName("powerdns.com.")) {
1708 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
1709 }
1710 else if (domain == DNSName("www.powerdns.com.") || domain == DNSName("www2.powerdns.com.")) {
1711 addRecordToLW(res, domain, QType::A, "192.0.2.43");
1712 }
1713 else if (domain == targetCName) {
1714 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
1715 }
1716 }
1717
1718 return LWResult::Result::Success;
1719 }
1720 }
1721
1722 return LWResult::Result::Timeout;
1723 });
1724
1725 vector<DNSRecord> ret;
1726 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1727 BOOST_CHECK_EQUAL(res, RCode::NoError);
1728 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1729 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1730 BOOST_CHECK_EQUAL(queriesCount, 7U);
1731
1732 /* again, to test the cache */
1733 ret.clear();
1734 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1735 BOOST_CHECK_EQUAL(res, RCode::NoError);
1736 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1737 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1738 BOOST_CHECK_EQUAL(queriesCount, 7U);
1739
1740 /* this time we ask for www.powerdns.com, let's make sure the CNAME does not get in the way */
1741 ret.clear();
1742 res = sr->beginResolve(DNSName("www.powerdns.com."), QType(QType::A), QClass::IN, ret);
1743 BOOST_CHECK_EQUAL(res, RCode::NoError);
1744 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1745 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1746 BOOST_CHECK_EQUAL(queriesCount, 8U);
1747
1748 /* now we remove the denial of powerdns.com DS from the cache and ask www2 */
1749 BOOST_REQUIRE_EQUAL(g_negCache->wipe(target, false), 1U);
1750 ret.clear();
1751 res = sr->beginResolve(DNSName("www2.powerdns.com."), QType(QType::A), QClass::IN, ret);
1752 BOOST_CHECK_EQUAL(res, RCode::NoError);
1753 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1754 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1755 BOOST_CHECK_EQUAL(queriesCount, 10U);
1756 }
1757
1758 BOOST_AUTO_TEST_CASE(test_dnssec_cname_inside_secure_zone)
1759 {
1760 /* this test makes sure we don't request the DS
1761 again and again when there is a CNAME inside a
1762 Secure zone */
1763 std::unique_ptr<SyncRes> sr;
1764 initSR(sr, true);
1765
1766 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1767
1768 primeHints();
1769 const DNSName target("powerdns.com.");
1770 const DNSName targetCName("power-dns.com.");
1771 const ComboAddress targetCNameAddr("192.0.2.42");
1772 testkeysset_t keys;
1773
1774 auto luaconfsCopy = g_luaconfs.getCopy();
1775 luaconfsCopy.dsAnchors.clear();
1776 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1777 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1778 g_luaconfs.setState(luaconfsCopy);
1779
1780 size_t queriesCount = 0;
1781
1782 sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) {
1783 queriesCount++;
1784
1785 if (type == QType::DS) {
1786 if (domain.isPartOf(DNSName("powerdns.com.")) || domain.isPartOf(DNSName("power-dns.com."))) {
1787 /* no cut */
1788 /* technically the zone is com., but we are going to chop off in genericDSAndDNSKEYHandler() */
1789 return genericDSAndDNSKEYHandler(res, domain, DNSName("powerdns.com."), type, keys, false);
1790 }
1791 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1792 }
1793 if (type == QType::DNSKEY) {
1794 if (domain == g_rootdnsname || domain == DNSName("com.")) {
1795 setLWResult(res, 0, true, false, true);
1796 addDNSKEY(keys, domain, 300, res->d_records);
1797 addRRSIG(keys, res->d_records, domain, 300);
1798 return LWResult::Result::Success;
1799 }
1800 setLWResult(res, 0, true, false, true);
1801 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1802 return LWResult::Result::Success;
1803 }
1804 else {
1805 if (isRootServer(address)) {
1806 setLWResult(res, 0, false, false, true);
1807 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
1808 addDS(DNSName("com."), 300, res->d_records, keys);
1809 addRRSIG(keys, res->d_records, DNSName("."), 300);
1810 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1811 return LWResult::Result::Success;
1812 }
1813 if (address == ComboAddress("192.0.2.1:53")) {
1814 setLWResult(res, 0, true, false, true);
1815
1816 if (domain == DNSName("com.")) {
1817 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
1818 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1819 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1820 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1821 }
1822 else {
1823 if (domain == DNSName("powerdns.com.")) {
1824 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
1825 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1826 }
1827 else if (domain == DNSName("www.powerdns.com.") || domain == DNSName("www2.powerdns.com.")) {
1828 addRecordToLW(res, domain, QType::A, "192.0.2.43");
1829 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1830 }
1831 else if (domain == targetCName) {
1832 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
1833 addRRSIG(keys, res->d_records, DNSName("com."), 300);
1834 }
1835 }
1836
1837 return LWResult::Result::Success;
1838 }
1839 }
1840
1841 return LWResult::Result::Timeout;
1842 });
1843
1844 vector<DNSRecord> ret;
1845 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1846 BOOST_CHECK_EQUAL(res, RCode::NoError);
1847 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
1848 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
1849 BOOST_CHECK_EQUAL(queriesCount, 5U);
1850
1851 /* again, to test the cache */
1852 ret.clear();
1853 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1854 BOOST_CHECK_EQUAL(res, RCode::NoError);
1855 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
1856 BOOST_REQUIRE_EQUAL(ret.size(), 4U);
1857 BOOST_CHECK_EQUAL(queriesCount, 5U);
1858
1859 /* this time we ask for www.powerdns.com, let's make sure the CNAME does not get in the way */
1860 ret.clear();
1861 res = sr->beginResolve(DNSName("www.powerdns.com."), QType(QType::A), QClass::IN, ret);
1862 BOOST_CHECK_EQUAL(res, RCode::NoError);
1863 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
1864 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1865 BOOST_CHECK_EQUAL(queriesCount, 6U);
1866
1867 /* now we remove the denial of powerdns.com DS from the cache and ask www2 */
1868 g_negCache->wipe(target, false);
1869 ret.clear();
1870 res = sr->beginResolve(DNSName("www2.powerdns.com."), QType(QType::A), QClass::IN, ret);
1871 BOOST_CHECK_EQUAL(res, RCode::NoError);
1872 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
1873 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1874 BOOST_CHECK_EQUAL(queriesCount, 7U);
1875 }
1876
1877 BOOST_AUTO_TEST_SUITE_END()