• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.16
/pdns/recursordist/test-syncres_cc4.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_cc4)
10

11
BOOST_AUTO_TEST_CASE(test_auth_zone_nodata)
12
{
2✔
13
  std::unique_ptr<SyncRes> sr;
2✔
14
  initSR(sr);
2✔
15

16
  primeHints();
2✔
17

18
  size_t queriesCount = 0;
2✔
19
  const DNSName target("nodata.powerdns.com.");
2✔
20
  const DNSName authZone("powerdns.com");
2✔
21

22
  SyncRes::AuthDomain ad;
2✔
23
  ad.d_name = authZone;
2✔
24
  DNSRecord dr;
2✔
25
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
26
  dr.d_name = target;
2✔
27
  dr.d_type = QType::A;
2✔
28
  dr.d_ttl = 3600;
2✔
29
  dr.setContent(std::make_shared<ARecordContent>(ComboAddress("192.0.2.1")));
2✔
30
  ad.d_records.insert(dr);
2✔
31

32
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
33
  dr.d_name = authZone;
2✔
34
  dr.d_type = QType::SOA;
2✔
35
  dr.d_ttl = 3600;
2✔
36
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
37
  ad.d_records.insert(dr);
2✔
38

39
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
40
  (*map)[authZone] = ad;
2✔
41
  SyncRes::setDomainMap(map);
2✔
42

43
  sr->setAsyncCallback([&queriesCount](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 */) {
2✔
44
    queriesCount++;
×
45

46
    return LWResult::Result::Timeout;
×
47
  });
×
48

49
  vector<DNSRecord> ret;
2✔
50
  int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
2✔
51
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
52
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
53
  BOOST_CHECK(ret[0].d_type == QType::SOA);
2✔
54
  BOOST_CHECK_EQUAL(queriesCount, 0U);
2✔
55
}
2✔
56

57
BOOST_AUTO_TEST_CASE(test_auth_zone_nx)
58
{
2✔
59
  std::unique_ptr<SyncRes> sr;
2✔
60
  initSR(sr);
2✔
61

62
  primeHints();
2✔
63

64
  size_t queriesCount = 0;
2✔
65
  const DNSName target("nx.powerdns.com.");
2✔
66
  const DNSName authZone("powerdns.com");
2✔
67

68
  SyncRes::AuthDomain ad;
2✔
69
  ad.d_name = authZone;
2✔
70
  DNSRecord dr;
2✔
71
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
72
  dr.d_name = DNSName("powerdns.com.");
2✔
73
  dr.d_type = QType::SOA;
2✔
74
  dr.d_ttl = 3600;
2✔
75
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
76
  ad.d_records.insert(dr);
2✔
77

78
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
79
  (*map)[authZone] = ad;
2✔
80
  SyncRes::setDomainMap(map);
2✔
81

82
  sr->setAsyncCallback([&queriesCount](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 */) {
2✔
83
    queriesCount++;
×
84

85
    return LWResult::Result::Timeout;
×
86
  });
×
87

88
  vector<DNSRecord> ret;
2✔
89
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
90
  BOOST_CHECK_EQUAL(res, RCode::NXDomain);
2✔
91
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
92
  BOOST_CHECK(ret[0].d_type == QType::SOA);
2✔
93
  BOOST_CHECK_EQUAL(queriesCount, 0U);
2✔
94
}
2✔
95

96
BOOST_AUTO_TEST_CASE(test_auth_zone_delegation)
97
{
2✔
98
  std::unique_ptr<SyncRes> sr;
2✔
99
  initSR(sr, true);
2✔
100

101
  primeHints();
2✔
102

103
  size_t queriesCount = 0;
2✔
104
  const DNSName target("www.test.powerdns.com.");
2✔
105
  const ComboAddress targetAddr("192.0.2.2");
2✔
106
  const DNSName ns("ns1.test.powerdns.com.");
2✔
107
  const ComboAddress nsAddr("192.0.2.1");
2✔
108
  const DNSName authZone("powerdns.com");
2✔
109

110
  SyncRes::AuthDomain ad;
2✔
111
  ad.d_name = authZone;
2✔
112
  DNSRecord dr;
2✔
113
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
114
  dr.d_name = authZone;
2✔
115
  dr.d_type = QType::SOA;
2✔
116
  dr.d_ttl = 3600;
2✔
117
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
118
  ad.d_records.insert(dr);
2✔
119

120
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
121
  dr.d_name = DNSName("test.powerdns.com.");
2✔
122
  dr.d_type = QType::NS;
2✔
123
  dr.d_ttl = 3600;
2✔
124
  dr.setContent(std::make_shared<NSRecordContent>(ns));
2✔
125
  ad.d_records.insert(dr);
2✔
126

127
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
128
  dr.d_name = ns;
2✔
129
  dr.d_type = QType::A;
2✔
130
  dr.d_ttl = 3600;
2✔
131
  dr.setContent(std::make_shared<ARecordContent>(nsAddr));
2✔
132
  ad.d_records.insert(dr);
2✔
133

134
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
135
  (*map)[authZone] = ad;
2✔
136
  SyncRes::setDomainMap(map);
2✔
137

138
  testkeysset_t keys;
2✔
139
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
140
  luaconfsCopy.dsAnchors.clear();
2✔
141
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
142
  g_luaconfs.setState(luaconfsCopy);
2✔
143

144
  /* make sure that the signature inception and validity times are computed
145
     based on the SyncRes time, not the current one, in case the function
146
     takes too long. */
147
  const time_t fixedNow = sr->getNow().tv_sec;
2✔
148

149
  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 */) {
2✔
150
    queriesCount++;
2✔
151
    if (type == QType::DS || type == QType::DNSKEY) {
2!
152
      return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys, domain == DNSName("com.") || domain == authZone, fixedNow);
×
153
    }
×
154

155
    if (address == ComboAddress(nsAddr.toString(), 53) && domain == target) {
2!
156
      setLWResult(res, 0, true, false, true);
2✔
157
      addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
2✔
158
      return LWResult::Result::Success;
2✔
159
    }
2✔
160

161
    return LWResult::Result::Timeout;
×
162
  });
2✔
163

164
  sr->setDNSSECValidationRequested(true);
2✔
165
  vector<DNSRecord> ret;
2✔
166
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
167
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
168
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
169
  BOOST_CHECK(ret[0].d_type == QType::A);
2✔
170
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
171
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
2✔
172
}
2✔
173

174
BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point)
175
{
2✔
176
  std::unique_ptr<SyncRes> sr;
2✔
177
  initSR(sr);
2✔
178

179
  primeHints();
2✔
180

181
  size_t queriesCount = 0;
2✔
182
  const DNSName target("test.powerdns.com.");
2✔
183
  const ComboAddress targetAddr("192.0.2.2");
2✔
184
  const DNSName ns("ns1.test.powerdns.com.");
2✔
185
  const ComboAddress nsAddr("192.0.2.1");
2✔
186
  const DNSName authZone("powerdns.com");
2✔
187

188
  SyncRes::AuthDomain ad;
2✔
189
  ad.d_name = authZone;
2✔
190
  DNSRecord dr;
2✔
191
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
192
  dr.d_name = authZone;
2✔
193
  dr.d_type = QType::SOA;
2✔
194
  dr.d_ttl = 3600;
2✔
195
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
196
  ad.d_records.insert(dr);
2✔
197

198
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
199
  dr.d_name = DNSName("test.powerdns.com.");
2✔
200
  dr.d_type = QType::NS;
2✔
201
  dr.d_ttl = 3600;
2✔
202
  dr.setContent(std::make_shared<NSRecordContent>(ns));
2✔
203
  ad.d_records.insert(dr);
2✔
204

205
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
206
  dr.d_name = ns;
2✔
207
  dr.d_type = QType::A;
2✔
208
  dr.d_ttl = 3600;
2✔
209
  dr.setContent(std::make_shared<ARecordContent>(nsAddr));
2✔
210
  ad.d_records.insert(dr);
2✔
211

212
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
213
  (*map)[authZone] = ad;
2✔
214
  SyncRes::setDomainMap(map);
2✔
215

216
  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 */) {
2✔
217
    queriesCount++;
2✔
218

219
    if (address == ComboAddress(nsAddr.toString(), 53) && domain == target) {
2!
220
      setLWResult(res, 0, true, false, true);
2✔
221
      addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
2✔
222
      return LWResult::Result::Success;
2✔
223
    }
2✔
224

225
    return LWResult::Result::Timeout;
×
226
  });
2✔
227

228
  vector<DNSRecord> ret;
2✔
229
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
230
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
231
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
232
  BOOST_CHECK(ret[0].d_type == QType::A);
2✔
233
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
234
}
2✔
235

236
BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard)
237
{
2✔
238
  std::unique_ptr<SyncRes> sr;
2✔
239
  initSR(sr);
2✔
240

241
  primeHints();
2✔
242

243
  size_t queriesCount = 0;
2✔
244
  const DNSName target("test.powerdns.com.");
2✔
245
  const ComboAddress targetAddr("192.0.2.2");
2✔
246
  const DNSName authZone("powerdns.com");
2✔
247

248
  SyncRes::AuthDomain ad;
2✔
249
  ad.d_name = authZone;
2✔
250
  DNSRecord dr;
2✔
251
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
252
  dr.d_name = authZone;
2✔
253
  dr.d_type = QType::SOA;
2✔
254
  dr.d_ttl = 3600;
2✔
255
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
256
  ad.d_records.insert(dr);
2✔
257

258
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
259
  dr.d_name = DNSName("*.powerdns.com.");
2✔
260
  dr.d_type = QType::A;
2✔
261
  dr.d_ttl = 3600;
2✔
262
  dr.setContent(std::make_shared<ARecordContent>(targetAddr));
2✔
263
  ad.d_records.insert(dr);
2✔
264

265
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
266
  (*map)[authZone] = ad;
2✔
267
  SyncRes::setDomainMap(map);
2✔
268

269
  sr->setAsyncCallback([&queriesCount](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 */) {
2✔
270
    queriesCount++;
×
271

272
    return LWResult::Result::Timeout;
×
273
  });
×
274

275
  vector<DNSRecord> ret;
2✔
276
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
277
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
278
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
279
  BOOST_CHECK(ret[0].d_type == QType::A);
2✔
280
  BOOST_CHECK_EQUAL(queriesCount, 0U);
2✔
281
}
2✔
282

283
BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_with_ent)
284
{
2✔
285
  std::unique_ptr<SyncRes> sr;
2✔
286
  initSR(sr);
2✔
287

288
  primeHints();
2✔
289

290
  size_t queriesCount = 0;
2✔
291
  const DNSName target("test.powerdns.com.");
2✔
292
  const ComboAddress targetAddr1("192.0.2.1");
2✔
293
  const ComboAddress targetAddr2("192.0.2.2");
2✔
294
  const DNSName authZone("powerdns.com");
2✔
295

296
  SyncRes::AuthDomain ad;
2✔
297
  ad.d_name = authZone;
2✔
298
  DNSRecord dr;
2✔
299
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
300
  dr.d_name = authZone;
2✔
301
  dr.d_type = QType::SOA;
2✔
302
  dr.d_ttl = 3600;
2✔
303
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
304
  ad.d_records.insert(dr);
2✔
305

306
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
307
  dr.d_name = DNSName("abc.xyz.test.powerdns.com.");
2✔
308
  dr.d_type = QType::A;
2✔
309
  dr.d_ttl = 3600;
2✔
310
  dr.setContent(std::make_shared<ARecordContent>(targetAddr1));
2✔
311
  ad.d_records.insert(dr);
2✔
312

313
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
314
  dr.d_name = DNSName("*.powerdns.com.");
2✔
315
  dr.d_type = QType::A;
2✔
316
  dr.d_ttl = 3600;
2✔
317
  dr.setContent(std::make_shared<ARecordContent>(targetAddr2));
2✔
318
  ad.d_records.insert(dr);
2✔
319

320
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
321
  (*map)[authZone] = ad;
2✔
322
  SyncRes::setDomainMap(map);
2✔
323

324
  sr->setAsyncCallback([&queriesCount](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 */) {
2✔
325
    queriesCount++;
×
326

327
    return LWResult::Result::Timeout;
×
328
  });
×
329

330
  vector<DNSRecord> ret;
2✔
331
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
332
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
333
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
334

335
  // WARN below should be changed to CHECK once the issue is fixed.
336
  const string m("Please fix issue #8312");
2✔
337
  BOOST_WARN_MESSAGE(ret[0].d_type == QType::SOA, m);
2✔
338
  BOOST_CHECK_EQUAL(queriesCount, 0U);
2✔
339
}
2✔
340

341
BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata)
342
{
2✔
343
  std::unique_ptr<SyncRes> sr;
2✔
344
  initSR(sr);
2✔
345

346
  primeHints();
2✔
347

348
  size_t queriesCount = 0;
2✔
349
  const DNSName target("test.powerdns.com.");
2✔
350
  const ComboAddress targetAddr("192.0.2.2");
2✔
351
  const DNSName authZone("powerdns.com");
2✔
352

353
  SyncRes::AuthDomain ad;
2✔
354
  ad.d_name = authZone;
2✔
355
  DNSRecord dr;
2✔
356
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
357
  dr.d_name = authZone;
2✔
358
  dr.d_type = QType::SOA;
2✔
359
  dr.d_ttl = 3600;
2✔
360
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
361
  ad.d_records.insert(dr);
2✔
362

363
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
364
  dr.d_name = DNSName("*.powerdns.com.");
2✔
365
  dr.d_type = QType::A;
2✔
366
  dr.d_ttl = 3600;
2✔
367
  dr.setContent(std::make_shared<ARecordContent>(targetAddr));
2✔
368
  ad.d_records.insert(dr);
2✔
369

370
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
371
  (*map)[authZone] = ad;
2✔
372
  SyncRes::setDomainMap(map);
2✔
373

374
  sr->setAsyncCallback([&queriesCount](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 */) {
2✔
375
    queriesCount++;
×
376

377
    return LWResult::Result::Timeout;
×
378
  });
×
379

380
  vector<DNSRecord> ret;
2✔
381
  int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
2✔
382
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
383
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
384
  BOOST_CHECK(ret[0].d_type == QType::SOA);
2✔
385
  BOOST_CHECK_EQUAL(queriesCount, 0U);
2✔
386
}
2✔
387

388
BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only)
389
{
2✔
390
  std::unique_ptr<SyncRes> sr;
2✔
391
  initSR(sr);
2✔
392

393
  primeHints();
2✔
394

395
  size_t queriesCount = 0;
2✔
396
  const DNSName target("powerdns.com.");
2✔
397
  const ComboAddress addr("192.0.2.5");
2✔
398

399
  SyncRes::AuthDomain ad;
2✔
400
  ad.d_name = target;
2✔
401
  DNSRecord dr;
2✔
402
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
403
  dr.d_name = target;
2✔
404
  dr.d_type = QType::SOA;
2✔
405
  dr.d_ttl = 3600;
2✔
406
  dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
2✔
407
  ad.d_records.insert(dr);
2✔
408

409
  dr.d_place = DNSResourceRecord::ANSWER;
2✔
410
  dr.d_name = target;
2✔
411
  dr.d_type = QType::A;
2✔
412
  dr.d_ttl = 3600;
2✔
413
  dr.setContent(std::make_shared<ARecordContent>(addr));
2✔
414
  ad.d_records.insert(dr);
2✔
415

416
  auto map = std::make_shared<SyncRes::domainmap_t>();
2✔
417
  (*map)[target] = ad;
2✔
418
  SyncRes::setDomainMap(map);
2✔
419

420
  sr->setAsyncCallback([&queriesCount](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 */) {
2✔
421
    queriesCount++;
×
422
    setLWResult(res, 0, true, false, true);
×
423
    addRecordToLW(res, domain, QType::A, "192.0.2.42");
×
424
    return LWResult::Result::Success;
×
425
  });
×
426

427
  /* simulate a no-RD query */
428
  sr->setCacheOnly();
2✔
429

430
  vector<DNSRecord> ret;
2✔
431
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
432
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
433
  BOOST_CHECK_EQUAL(ret.size(), 1U);
2✔
434
  BOOST_CHECK(ret[0].d_type == QType::A);
2✔
435
  BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
2✔
436
  BOOST_CHECK_EQUAL(queriesCount, 0U);
2✔
437
}
2✔
438

439
BOOST_AUTO_TEST_CASE(test_dnssec_rrsig)
440
{
2✔
441
  initSR();
2✔
442

443
  auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
444
  dcke->create(dcke->getBits());
2✔
445
  DNSSECPrivateKey dpk;
2✔
446
  dpk.setKey(std::move(dcke), 256);
2✔
447

448
  sortedRecords_t recordcontents;
2✔
449
  recordcontents.insert(getRecordContent(QType::A, "192.0.2.1"));
2✔
450

451
  DNSName qname("powerdns.com.");
2✔
452

453
  time_t now = time(nullptr);
2✔
454
  RRSIGRecordContent rrc;
2✔
455
  /* this RRSIG is valid for the current second only */
456
  computeRRSIG(dpk, qname, qname, QType::A, 600, 0, rrc, recordcontents, boost::none, now);
2✔
457

458
  skeyset_t keyset;
2✔
459
  keyset.insert(std::make_shared<DNSKEYRecordContent>(dpk.getDNSKEY()));
2✔
460

461
  std::vector<std::shared_ptr<const RRSIGRecordContent>> sigs;
2✔
462
  sigs.push_back(std::make_shared<RRSIGRecordContent>(rrc));
2✔
463

464
  pdns::validation::ValidationContext validationContext;
2✔
465
  BOOST_CHECK(validateWithKeySet(now, qname, recordcontents, sigs, keyset, std::nullopt, validationContext) == vState::Secure);
2✔
466
  BOOST_CHECK_EQUAL(validationContext.d_validationsCounter, 1U);
2✔
467
}
2✔
468

469
BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk)
470
{
2✔
471
  std::unique_ptr<SyncRes> sr;
2✔
472
  initSR(sr, true);
2✔
473

474
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
475

476
  primeHints();
2✔
477
  const DNSName target(".");
2✔
478
  testkeysset_t keys;
2✔
479

480
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
481
  luaconfsCopy.dsAnchors.clear();
2✔
482
  generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
2✔
483
  g_luaconfs.setState(luaconfsCopy);
2✔
484

485
  size_t queriesCount = 0;
2✔
486

487
  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 */) {
4✔
488
    queriesCount++;
4✔
489

490
    if (domain == target && type == QType::NS) {
4!
491

492
      setLWResult(res, 0, true, false, true);
2✔
493
      char addr[] = "a.root-servers.net.";
2✔
494
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
495
        addr[0] = idx;
26✔
496
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
497
      }
26✔
498

499
      addRRSIG(keys, res->d_records, domain, 300);
2✔
500

501
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
502
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
503

504
      return LWResult::Result::Success;
2✔
505
    }
2✔
506
    if (domain == target && type == QType::DNSKEY) {
2!
507

508
      setLWResult(res, 0, true, false, true);
2✔
509

510
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
511
      addRRSIG(keys, res->d_records, domain, 300);
2✔
512

513
      return LWResult::Result::Success;
2✔
514
    }
2✔
515

516
    return LWResult::Result::Timeout;
×
517
  });
2✔
518

519
  vector<DNSRecord> ret;
2✔
520
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
521
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
522
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
2✔
523
  /* 13 NS + 1 RRSIG */
524
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
525
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
526

527
  /* again, to test the cache */
528
  ret.clear();
2✔
529
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
530
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
531
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
2✔
532
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
533
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
534
}
2✔
535

536
BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk)
537
{
2✔
538
  std::unique_ptr<SyncRes> sr;
2✔
539
  initSR(sr, true);
2✔
540

541
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
542

543
  primeHints();
2✔
544
  const DNSName target(".");
2✔
545
  testkeysset_t zskeys;
2✔
546
  testkeysset_t kskeys;
2✔
547

548
  /* Generate key material for "." */
549
  auto dckeZ = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
550
  dckeZ->create(dckeZ->getBits());
2✔
551
  DNSSECPrivateKey ksk;
2✔
552
  ksk.setKey(std::move(dckeZ), 257);
2✔
553
  DSRecordContent kskds = makeDSFromDNSKey(target, ksk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
554

555
  auto dckeK = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
556
  dckeK->create(dckeK->getBits());
2✔
557
  DNSSECPrivateKey zsk;
2✔
558
  zsk.setKey(std::move(dckeK), 256);
2✔
559
  DSRecordContent zskds = makeDSFromDNSKey(target, zsk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
560

561
  kskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(ksk, kskds);
2✔
562
  zskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(zsk, zskds);
2✔
563

564
  /* Set the root DS */
565
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
566
  luaconfsCopy.dsAnchors.clear();
2✔
567
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(kskds);
2✔
568
  g_luaconfs.setState(luaconfsCopy);
2✔
569

570
  size_t queriesCount = 0;
2✔
571

572
  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 */) {
4✔
573
    queriesCount++;
4✔
574

575
    if (domain == target && type == QType::NS) {
4!
576

577
      setLWResult(res, 0, true, false, true);
2✔
578
      char addr[] = "a.root-servers.net.";
2✔
579
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
580
        addr[0] = idx;
26✔
581
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
582
      }
26✔
583

584
      addRRSIG(zskeys, res->d_records, domain, 300);
2✔
585

586
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
587
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
588

589
      return LWResult::Result::Success;
2✔
590
    }
2✔
591
    if (domain == target && type == QType::DNSKEY) {
2!
592

593
      setLWResult(res, 0, true, false, true);
2✔
594

595
      addDNSKEY(kskeys, domain, 300, res->d_records);
2✔
596
      addDNSKEY(zskeys, domain, 300, res->d_records);
2✔
597
      addRRSIG(kskeys, res->d_records, domain, 300);
2✔
598

599
      return LWResult::Result::Success;
2✔
600
    }
2✔
601

602
    return LWResult::Result::Timeout;
×
603
  });
2✔
604

605
  vector<DNSRecord> ret;
2✔
606
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
607
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
608
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
2✔
609
  /* 13 NS + 1 RRSIG */
610
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
611
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
612

613
  /* again, to test the cache */
614
  ret.clear();
2✔
615
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
616
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
617
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
2✔
618
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
619
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
620
}
2✔
621

622
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey)
623
{
2✔
624
  std::unique_ptr<SyncRes> sr;
2✔
625
  initSR(sr, true);
2✔
626

627
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
628

629
  primeHints();
2✔
630
  const DNSName target(".");
2✔
631
  testkeysset_t keys;
2✔
632

633
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
634
  luaconfsCopy.dsAnchors.clear();
2✔
635
  generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
2✔
636
  g_luaconfs.setState(luaconfsCopy);
2✔
637

638
  size_t queriesCount = 0;
2✔
639

640
  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 */) {
4✔
641
    queriesCount++;
4✔
642

643
    if (domain == target && type == QType::NS) {
4!
644

645
      setLWResult(res, 0, true, false, true);
2✔
646
      char addr[] = "a.root-servers.net.";
2✔
647
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
648
        addr[0] = idx;
26✔
649
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
650
      }
26✔
651

652
      addRRSIG(keys, res->d_records, domain, 300);
2✔
653

654
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
655
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
656

657
      return LWResult::Result::Success;
2✔
658
    }
2✔
659
    if (domain == target && type == QType::DNSKEY) {
2!
660

661
      setLWResult(res, 0, true, false, true);
2✔
662

663
      /* No DNSKEY */
664

665
      return LWResult::Result::Success;
2✔
666
    }
2✔
667

668
    return LWResult::Result::Timeout;
×
669
  });
2✔
670

671
  vector<DNSRecord> ret;
2✔
672
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
673
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
674
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
2✔
675
  /* 13 NS + 1 RRSIG */
676
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
677
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
678

679
  /* again, to test the cache */
680
  ret.clear();
2✔
681
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
682
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
683
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
2✔
684
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
685
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
686
}
2✔
687

688
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_without_zone_flag)
689
{
2✔
690
  std::unique_ptr<SyncRes> sr;
2✔
691
  initSR(sr, true);
2✔
692

693
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
694

695
  primeHints();
2✔
696
  const DNSName target(".");
2✔
697
  testkeysset_t keys;
2✔
698

699
  /* Generate key material for "." */
700
  auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
701
  dcke->create(dcke->getBits());
2✔
702
  DNSSECPrivateKey csk;
2✔
703
  csk.setKey(std::move(dcke), 0);
2✔
704
  DSRecordContent ds = makeDSFromDNSKey(target, csk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
705

706
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(csk, ds);
2✔
707

708
  /* Set the root DS */
709
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
710
  luaconfsCopy.dsAnchors.clear();
2✔
711
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(ds);
2✔
712
  g_luaconfs.setState(luaconfsCopy);
2✔
713

714
  size_t queriesCount = 0;
2✔
715

716
  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 */) {
4✔
717
    queriesCount++;
4✔
718

719
    if (domain == target && type == QType::NS) {
4!
720

721
      setLWResult(res, 0, true, false, true);
2✔
722
      char addr[] = "a.root-servers.net.";
2✔
723
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
724
        addr[0] = idx;
26✔
725
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
726
      }
26✔
727

728
      addRRSIG(keys, res->d_records, domain, 300);
2✔
729
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
730
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
731

732
      return LWResult::Result::Success;
2✔
733
    }
2✔
734
    if (domain == target && type == QType::DNSKEY) {
2!
735

736
      setLWResult(res, 0, true, false, true);
2✔
737

738
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
739
      addRRSIG(keys, res->d_records, domain, 300);
2✔
740

741
      return LWResult::Result::Success;
2✔
742
    }
2✔
743

744
    return LWResult::Result::Timeout;
×
745
  });
2✔
746

747
  vector<DNSRecord> ret;
2✔
748
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
749
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
750
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoZoneKeyBitSet);
2✔
751
  /* 13 NS + 1 RRSIG */
752
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
753
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
754

755
  /* again, to test the cache */
756
  ret.clear();
2✔
757
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
758
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
759
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoZoneKeyBitSet);
2✔
760
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
761
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
762
}
2✔
763

764
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_revoked)
765
{
2✔
766
  std::unique_ptr<SyncRes> sr;
2✔
767
  initSR(sr, true);
2✔
768

769
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
770

771
  primeHints();
2✔
772
  const DNSName target(".");
2✔
773
  testkeysset_t keys;
2✔
774

775
  /* Generate key material for "." */
776
  auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
777
  dcke->create(dcke->getBits());
2✔
778
  DNSSECPrivateKey csk;
2✔
779
  csk.setKey(std::move(dcke), 257 | 128);
2✔
780
  DSRecordContent ds = makeDSFromDNSKey(target, csk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
781

782
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(csk, ds);
2✔
783

784
  /* Set the root DS */
785
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
786
  luaconfsCopy.dsAnchors.clear();
2✔
787
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(ds);
2✔
788
  g_luaconfs.setState(luaconfsCopy);
2✔
789

790
  size_t queriesCount = 0;
2✔
791

792
  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 */) {
4✔
793
    queriesCount++;
4✔
794

795
    if (domain == target && type == QType::NS) {
4!
796

797
      setLWResult(res, 0, true, false, true);
2✔
798
      char addr[] = "a.root-servers.net.";
2✔
799
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
800
        addr[0] = idx;
26✔
801
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
802
      }
26✔
803

804
      addRRSIG(keys, res->d_records, domain, 300);
2✔
805
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
806
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
807

808
      return LWResult::Result::Success;
2✔
809
    }
2✔
810
    if (domain == target && type == QType::DNSKEY) {
2!
811

812
      setLWResult(res, 0, true, false, true);
2✔
813

814
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
815
      addRRSIG(keys, res->d_records, domain, 300);
2✔
816

817
      return LWResult::Result::Success;
2✔
818
    }
2✔
819

820
    return LWResult::Result::Timeout;
×
821
  });
2✔
822

823
  vector<DNSRecord> ret;
2✔
824
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
825
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
826
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusRevokedDNSKEY);
2✔
827
  /* 13 NS + 1 RRSIG */
828
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
829
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
830

831
  /* again, to test the cache */
832
  ret.clear();
2✔
833
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
834
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
835
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusRevokedDNSKEY);
2✔
836
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
837
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
838
}
2✔
839

840
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds)
841
{
2✔
842
  std::unique_ptr<SyncRes> sr;
2✔
843
  initSR(sr, true);
2✔
844

845
  setDNSSECValidation(sr, DNSSECMode::Process);
2✔
846

847
  primeHints();
2✔
848
  const DNSName target(".");
2✔
849
  testkeysset_t dskeys;
2✔
850
  testkeysset_t keys;
2✔
851

852
  /* Generate key material for "." */
853
  auto dckeDS = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
854
  dckeDS->create(dckeDS->getBits());
2✔
855
  DNSSECPrivateKey dskey;
2✔
856
  dskey.setKey(std::move(dckeDS), 257);
2✔
857
  DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
858

859
  auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
860
  dcke->create(dcke->getBits());
2✔
861
  DNSSECPrivateKey dpk;
2✔
862
  dpk.setKey(std::move(dcke), 256);
2✔
863
  DSRecordContent seconddrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
864

865
  dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc);
2✔
866
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, seconddrc);
2✔
867

868
  /* Set the root DS */
869
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
870
  luaconfsCopy.dsAnchors.clear();
2✔
871
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
2✔
872
  g_luaconfs.setState(luaconfsCopy);
2✔
873

874
  size_t queriesCount = 0;
2✔
875

876
  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 */) {
8✔
877
    queriesCount++;
8✔
878

879
    if (domain == target && type == QType::NS) {
8!
880

881
      setLWResult(res, 0, true, false, true);
4✔
882
      char addr[] = "a.root-servers.net.";
4✔
883
      for (char idx = 'a'; idx <= 'm'; idx++) {
56✔
884
        addr[0] = idx;
52✔
885
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
52✔
886
      }
52✔
887

888
      addRRSIG(keys, res->d_records, domain, 300);
4✔
889

890
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
4✔
891
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
4✔
892

893
      return LWResult::Result::Success;
4✔
894
    }
4✔
895
    if (domain == target && type == QType::DNSKEY) {
4!
896

897
      setLWResult(res, 0, true, false, true);
4✔
898

899
      addDNSKEY(keys, domain, 300, res->d_records);
4✔
900
      addRRSIG(keys, res->d_records, domain, 300);
4✔
901

902
      return LWResult::Result::Success;
4✔
903
    }
4✔
904

905
    return LWResult::Result::Timeout;
×
906
  });
4✔
907

908
  /* === with validation enabled === */
909
  sr->setDNSSECValidationRequested(true);
2✔
910
  vector<DNSRecord> ret;
2✔
911
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
912
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
913
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
914
  /* 13 NS + 1 RRSIG */
915
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
916
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
917

918
  /* again, to test the cache */
919
  ret.clear();
2✔
920
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
921
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
922
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
923
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
924
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
925

926
  /* === first without validation, then with (just-in-time validation) === */
927
  /* clear the caches */
928
  g_recCache = std::make_unique<MemRecursorCache>();
2✔
929
  g_negCache = std::make_unique<NegCache>();
2✔
930
  sr->setDNSSECValidationRequested(false);
2✔
931
  primeHints();
2✔
932

933
  ret.clear();
2✔
934
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
935
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
936
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
2✔
937
  /* 13 NS + 1 RRSIG */
938
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
939
  BOOST_CHECK_EQUAL(queriesCount, 3U);
2✔
940

941
  /* now we ask for the DNSKEYs (still without validation) */
942
  ret.clear();
2✔
943
  res = sr->beginResolve(target, QType(QType::DNSKEY), QClass::IN, ret);
2✔
944
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
945
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
2✔
946
  /* 1 SOA + 1 RRSIG */
947
  BOOST_REQUIRE_EQUAL(ret.size(), 2U);
2✔
948
  BOOST_CHECK_EQUAL(queriesCount, 4U);
2✔
949

950
  /* again, to test the cache WITH validation */
951
  sr->setDNSSECValidationRequested(true);
2✔
952
  ret.clear();
2✔
953
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
954
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
955
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
956
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
957
  BOOST_CHECK_EQUAL(queriesCount, 4U);
2✔
958
}
2✔
959

960
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_dss)
961
{
2✔
962
  std::unique_ptr<SyncRes> sr;
2✔
963
  initSR(sr, true);
2✔
964

965
  setDNSSECValidation(sr, DNSSECMode::Process);
2✔
966

967
  primeHints();
2✔
968
  const DNSName target(".");
2✔
969
  testkeysset_t keys;
2✔
970

971
  g_maxDSsToConsider = 1;
2✔
972

973
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
974
  luaconfsCopy.dsAnchors.clear();
2✔
975
  /* generate more DSs for the zone than we are willing to consider: only the last one will be used to generate DNSKEY records */
976
  for (size_t idx = 0; idx < (g_maxDSsToConsider + 10U); idx++) {
24✔
977
    generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
22✔
978
  }
22✔
979
  g_luaconfs.setState(luaconfsCopy);
2✔
980

981
  size_t queriesCount = 0;
2✔
982

983
  sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
4✔
984
    queriesCount++;
4✔
985

986
    if (domain == target && type == QType::NS) {
4!
987

988
      setLWResult(res, 0, true, false, true);
2✔
989
      char addr[] = "a.root-servers.net.";
2✔
990
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
991
        addr[0] = idx;
26✔
992
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
993
      }
26✔
994

995
      addRRSIG(keys, res->d_records, domain, 300);
2✔
996

997
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
998
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
999

1000
      return LWResult::Result::Success;
2✔
1001
    }
2✔
1002
    else if (domain == target && type == QType::DNSKEY) {
2!
1003

1004
      setLWResult(res, 0, true, false, true);
2✔
1005

1006
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1007
      addRRSIG(keys, res->d_records, domain, 300);
2✔
1008

1009
      return LWResult::Result::Success;
2✔
1010
    }
2✔
1011

1012
    return LWResult::Result::Timeout;
×
1013
  });
4✔
1014

1015
  /* === with validation enabled === */
1016
  sr->setDNSSECValidationRequested(true);
2✔
1017
  vector<DNSRecord> ret;
2✔
1018
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1019
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1020
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
1021
  /* 13 NS + 1 RRSIG */
1022
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1023
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1024

1025
  /* again, to test the cache */
1026
  ret.clear();
2✔
1027
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1028
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1029
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
1030
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1031
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1032

1033
  g_maxDNSKEYsToConsider = 0;
2✔
1034
}
2✔
1035

1036
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_dnskeys)
1037
{
2✔
1038
  std::unique_ptr<SyncRes> sr;
2✔
1039
  initSR(sr, true);
2✔
1040

1041
  setDNSSECValidation(sr, DNSSECMode::Process);
2✔
1042

1043
  primeHints();
2✔
1044
  const DNSName target(".");
2✔
1045
  testkeysset_t dskeys;
2✔
1046
  testkeysset_t keys;
2✔
1047

1048
  DNSKEYRecordContent dnskeyRecordContent;
2✔
1049
  dnskeyRecordContent.d_algorithm = 13;
2✔
1050
  /* Generate key material for "." */
1051
  auto dckeDS = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2
2✔
1052
Algorithm: 13 (ECDSAP256SHA256)
2✔
1053
PrivateKey: Ovj4pzrSh0U6aEVoKaPFhK1D4NMG0xrymj9+6TpwC8o=)PKEY");
2✔
1054
  DNSSECPrivateKey dskey;
2✔
1055
  dskey.setKey(std::move(dckeDS), 257);
2✔
1056
  assert(dskey.getTag() == 31337);
2✔
1057
  DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
×
1058
  dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc);
2✔
1059

1060
  /* Different key, same tag */
1061
  auto dcke = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2
2✔
1062
Algorithm: 13 (ECDSAP256SHA256)
2✔
1063
PrivateKey: n7SRA4n6NejhZBWQOhjTaICYSpkTl6plJn1ATFG23FI=)PKEY");
2✔
1064
  DNSSECPrivateKey dpk;
2✔
1065
  dpk.setKey(std::move(dcke), 256);
2✔
1066
  assert(dpk.getTag() == dskey.getTag());
2✔
1067
  DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
×
1068
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, uselessdrc);
2✔
1069

1070
  /* Set the root DS (one of them!) */
1071
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1072
  luaconfsCopy.dsAnchors.clear();
2✔
1073
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
2✔
1074
  g_luaconfs.setState(luaconfsCopy);
2✔
1075

1076
  size_t queriesCount = 0;
2✔
1077

1078
  sr->setAsyncCallback([target, &queriesCount, keys, dskeys](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 */) {
4✔
1079
    queriesCount++;
4✔
1080

1081
    if (domain == target && type == QType::NS) {
4!
1082

1083
      setLWResult(res, 0, true, false, true);
2✔
1084
      char addr[] = "a.root-servers.net.";
2✔
1085
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1086
        addr[0] = idx;
26✔
1087
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1088
      }
26✔
1089

1090
      addRRSIG(dskeys, res->d_records, domain, 300);
2✔
1091

1092
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1093
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1094

1095
      return LWResult::Result::Success;
2✔
1096
    }
2✔
1097
    else if (domain == target && type == QType::DNSKEY) {
2!
1098

1099
      setLWResult(res, 0, true, false, true);
2✔
1100

1101
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1102
      addDNSKEY(dskeys, domain, 300, res->d_records);
2✔
1103
      addRRSIG(keys, res->d_records, domain, 300);
2✔
1104
      addRRSIG(dskeys, res->d_records, domain, 300);
2✔
1105

1106
      return LWResult::Result::Success;
2✔
1107
    }
2✔
1108

1109
    return LWResult::Result::Timeout;
×
1110
  });
4✔
1111

1112
  g_maxDNSKEYsToConsider = 1;
2✔
1113

1114
  /* === with validation enabled === */
1115
  sr->setDNSSECValidationRequested(true);
2✔
1116
  vector<DNSRecord> ret;
2✔
1117
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1118
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1119
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
1120
  /* 13 NS + 1 RRSIG */
1121
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1122
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1123

1124
  /* again, to test the cache */
1125
  ret.clear();
2✔
1126
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1127
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1128
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
2✔
1129
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1130
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1131

1132
  g_maxDNSKEYsToConsider = 0;
2✔
1133
}
2✔
1134

1135
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_dnskeys_while_checking_signature)
1136
{
2✔
1137
  std::unique_ptr<SyncRes> sr;
2✔
1138
  initSR(sr, true);
2✔
1139

1140
  setDNSSECValidation(sr, DNSSECMode::Process);
2✔
1141

1142
  primeHints();
2✔
1143
  const DNSName target(".");
2✔
1144
  testkeysset_t dskeys;
2✔
1145
  testkeysset_t keys;
2✔
1146
  testkeysset_t otherkeys;
2✔
1147

1148
  DNSKEYRecordContent dnskeyRecordContent;
2✔
1149
  dnskeyRecordContent.d_algorithm = 13;
2✔
1150
  /* Generate key material for "." */
1151
  auto dckeDS = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2
2✔
1152
Algorithm: 13 (ECDSAP256SHA256)
2✔
1153
PrivateKey: Ovj4pzrSh0U6aEVoKaPFhK1D4NMG0xrymj9+6TpwC8o=)PKEY");
2✔
1154
  DNSSECPrivateKey dskey;
2✔
1155
  dskey.setKey(std::move(dckeDS), 257);
2✔
1156
  assert(dskey.getTag() == 31337);
2✔
1157
  DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
×
1158
  dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc);
2✔
1159

1160
  /* Different key, same tag */
1161
  auto dcke = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2
2✔
1162
Algorithm: 13 (ECDSAP256SHA256)
2✔
1163
PrivateKey: pTaMJcvNrPIIiQiHGvCLZZASroyQpUwew5FvCgjHNsk=)PKEY");
2✔
1164
  DNSSECPrivateKey dpk;
2✔
1165
  // why 258, you may ask? We need this record to be sorted AFTER the other one in a sortedRecords_t
1166
  // so that the validation of the DNSKEY rrset succeeds
1167
  dpk.setKey(std::move(dcke), 258);
2✔
1168
  assert(dpk.getTag() == dskey.getTag());
2✔
1169
  DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
×
1170
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, uselessdrc);
2✔
1171

1172
  /* Set the root DSs (only one of them) */
1173
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1174
  luaconfsCopy.dsAnchors.clear();
2✔
1175
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
2✔
1176
  g_luaconfs.setState(luaconfsCopy);
2✔
1177

1178
  size_t queriesCount = 0;
2✔
1179

1180
  sr->setAsyncCallback([target, &queriesCount, keys, dskeys](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 */) {
4✔
1181
    queriesCount++;
4✔
1182

1183
    if (domain == target && type == QType::NS) {
4!
1184

1185
      setLWResult(res, 0, true, false, true);
2✔
1186
      char addr[] = "a.root-servers.net.";
2✔
1187
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1188
        addr[0] = idx;
26✔
1189
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1190
      }
26✔
1191

1192
      addRRSIG(keys, res->d_records, domain, 300);
2✔
1193
      addRRSIG(dskeys, res->d_records, domain, 300);
2✔
1194

1195
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1196
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1197

1198
      return LWResult::Result::Success;
2✔
1199
    }
2✔
1200
    else if (domain == target && type == QType::DNSKEY) {
2!
1201

1202
      setLWResult(res, 0, true, false, true);
2✔
1203

1204
      addDNSKEY(dskeys, domain, 300, res->d_records);
2✔
1205
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1206
      addRRSIG(dskeys, res->d_records, domain, 300);
2✔
1207

1208
      return LWResult::Result::Success;
2✔
1209
    }
2✔
1210

1211
    return LWResult::Result::Timeout;
×
1212
  });
4✔
1213

1214
  g_maxDNSKEYsToConsider = 1;
2✔
1215

1216
  /* === with validation enabled === */
1217
  sr->setDNSSECValidationRequested(true);
2✔
1218
  vector<DNSRecord> ret;
2✔
1219
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1220
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1221
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1222
  /* 13 NS + 1 RRSIG */
1223
  BOOST_REQUIRE_EQUAL(ret.size(), 15U);
2✔
1224
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1225

1226
  /* again, to test the cache */
1227
  ret.clear();
2✔
1228
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1229
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1230
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1231
  BOOST_REQUIRE_EQUAL(ret.size(), 15U);
2✔
1232
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1233

1234
  g_maxDNSKEYsToConsider = 0;
2✔
1235
}
2✔
1236

1237
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey)
1238
{
2✔
1239
  std::unique_ptr<SyncRes> sr;
2✔
1240
  initSR(sr, true);
2✔
1241

1242
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1243

1244
  primeHints();
2✔
1245
  const DNSName target(".");
2✔
1246
  testkeysset_t keys;
2✔
1247
  testkeysset_t rrsigkeys;
2✔
1248

1249
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1250
  luaconfsCopy.dsAnchors.clear();
2✔
1251
  generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
2✔
1252
  g_luaconfs.setState(luaconfsCopy);
2✔
1253

1254
  auto dckeRRSIG = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
1255
  dckeRRSIG->create(dckeRRSIG->getBits());
2✔
1256
  DNSSECPrivateKey rrsigkey;
2✔
1257
  rrsigkey.setKey(std::move(dckeRRSIG), 257);
2✔
1258
  DSRecordContent rrsigds = makeDSFromDNSKey(target, rrsigkey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
1259

1260
  rrsigkeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(rrsigkey, rrsigds);
2✔
1261

1262
  size_t queriesCount = 0;
2✔
1263

1264
  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 */) {
4✔
1265
    queriesCount++;
4✔
1266

1267
    if (domain == target && type == QType::NS) {
4!
1268

1269
      setLWResult(res, 0, true, false, true);
2✔
1270
      char addr[] = "a.root-servers.net.";
2✔
1271
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1272
        addr[0] = idx;
26✔
1273
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1274
      }
26✔
1275

1276
      addRRSIG(rrsigkeys, res->d_records, domain, 300);
2✔
1277

1278
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1279
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1280

1281
      return LWResult::Result::Success;
2✔
1282
    }
2✔
1283
    if (domain == target && type == QType::DNSKEY) {
2!
1284

1285
      setLWResult(res, 0, true, false, true);
2✔
1286

1287
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1288
      addRRSIG(rrsigkeys, res->d_records, domain, 300);
2✔
1289

1290
      return LWResult::Result::Success;
2✔
1291
    }
2✔
1292

1293
    return LWResult::Result::Timeout;
×
1294
  });
2✔
1295

1296
  vector<DNSRecord> ret;
2✔
1297
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1298
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1299
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1300
  /* 13 NS + 1 RRSIG */
1301
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1302
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1303

1304
  /* again, to test the cache */
1305
  ret.clear();
2✔
1306
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1307
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1308
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1309
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1310
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1311
}
2✔
1312

1313
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig)
1314
{
2✔
1315
  std::unique_ptr<SyncRes> sr;
2✔
1316
  initSR(sr, true);
2✔
1317

1318
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1319

1320
  primeHints();
2✔
1321
  const DNSName target(".");
2✔
1322
  testkeysset_t keys;
2✔
1323

1324
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1325
  luaconfsCopy.dsAnchors.clear();
2✔
1326
  generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
2✔
1327
  g_luaconfs.setState(luaconfsCopy);
2✔
1328

1329
  size_t queriesCount = 0;
2✔
1330

1331
  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 */) {
2✔
1332
    queriesCount++;
2✔
1333

1334
    if (domain == target && type == QType::NS) {
2!
1335

1336
      setLWResult(res, 0, true, false, true);
2✔
1337
      char addr[] = "a.root-servers.net.";
2✔
1338
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1339
        addr[0] = idx;
26✔
1340
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 86400);
26✔
1341
      }
26✔
1342

1343
      /* No RRSIG */
1344

1345
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1346
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1347

1348
      return LWResult::Result::Success;
2✔
1349
    }
2✔
1350
    if (domain == target && type == QType::DNSKEY) {
×
1351

1352
      setLWResult(res, 0, true, false, true);
×
1353

1354
      addDNSKEY(keys, domain, 300, res->d_records);
×
1355
      addRRSIG(keys, res->d_records, domain, 300);
×
1356

1357
      return LWResult::Result::Success;
×
1358
    }
×
1359

1360
    return LWResult::Result::Timeout;
×
1361
  });
×
1362

1363
  SyncRes::s_maxcachettl = 86400;
2✔
1364
  SyncRes::s_maxbogusttl = 3600;
2✔
1365

1366
  vector<DNSRecord> ret;
2✔
1367
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1368
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1369
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1370
  /* 13 NS + 0 RRSIG */
1371
  BOOST_REQUIRE_EQUAL(ret.size(), 13U);
2✔
1372
  /* no RRSIG so no query for DNSKEYs */
1373
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1374

1375
  /* again, to test the cache */
1376
  ret.clear();
2✔
1377
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1378
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1379
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1380
  BOOST_REQUIRE_EQUAL(ret.size(), 13U);
2✔
1381
  /* check that we capped the TTL to max-cache-bogus-ttl */
1382
  for (const auto& record : ret) {
26✔
1383
    BOOST_CHECK_LE(record.d_ttl, SyncRes::s_maxbogusttl);
26✔
1384
  }
26✔
1385
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1386
}
2✔
1387

1388
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig_noaa)
1389
{
2✔
1390
  std::unique_ptr<SyncRes> sr;
2✔
1391
  initSR(sr, true);
2✔
1392

1393
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1394

1395
  primeHints();
2✔
1396
  const DNSName target(".");
2✔
1397
  testkeysset_t keys;
2✔
1398

1399
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1400
  luaconfsCopy.dsAnchors.clear();
2✔
1401
  generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
2✔
1402
  g_luaconfs.setState(luaconfsCopy);
2✔
1403

1404
  size_t queriesCount = 0;
2✔
1405

1406
  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 */) {
2✔
1407
    queriesCount++;
2✔
1408

1409
    if (domain == target && type == QType::NS) {
2!
1410

1411
      /* We are not setting AA! */
1412
      setLWResult(res, 0, false, false, true);
2✔
1413
      char addr[] = "a.root-servers.net.";
2✔
1414
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1415
        addr[0] = idx;
26✔
1416
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 86400);
26✔
1417
      }
26✔
1418

1419
      /* No RRSIG */
1420

1421
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1422
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1423

1424
      return LWResult::Result::Success;
2✔
1425
    }
2✔
1426
    if (domain == target && type == QType::DNSKEY) {
×
1427

1428
      setLWResult(res, 0, true, false, true);
×
1429

1430
      addDNSKEY(keys, domain, 300, res->d_records);
×
1431
      addRRSIG(keys, res->d_records, domain, 300);
×
1432

1433
      return LWResult::Result::Success;
×
1434
    }
×
1435

1436
    return LWResult::Result::Timeout;
×
1437
  });
×
1438

1439
  SyncRes::s_maxcachettl = 86400;
2✔
1440
  SyncRes::s_maxbogusttl = 3600;
2✔
1441

1442
  vector<DNSRecord> ret;
2✔
1443
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1444
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1445
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1446
  /* 13 NS + 0 RRSIG */
1447
  BOOST_REQUIRE_EQUAL(ret.size(), 13U);
2✔
1448
  /* no RRSIG so no query for DNSKEYs */
1449
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1450

1451
  /* again, to test the cache */
1452
  ret.clear();
2✔
1453
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1454
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1455
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1456
  BOOST_REQUIRE_EQUAL(ret.size(), 13U);
2✔
1457
  /* check that we capped the TTL to max-cache-bogus-ttl */
1458
  for (const auto& record : ret) {
26✔
1459
    BOOST_CHECK_LE(record.d_ttl, SyncRes::s_maxbogusttl);
26✔
1460
  }
26✔
1461
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1462
}
2✔
1463

1464
BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm)
1465
{
2✔
1466
  std::unique_ptr<SyncRes> sr;
2✔
1467
  initSR(sr, true);
2✔
1468

1469
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1470

1471
  primeHints();
2✔
1472
  const DNSName target(".");
2✔
1473
  testkeysset_t keys;
2✔
1474

1475
  /* Generate key material for "." */
1476
  auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
1477
  dcke->create(dcke->getBits());
2✔
1478
  DNSSECPrivateKey dpk;
2✔
1479
  /* Fake algorithm number (private) */
1480
  dpk.setKey(std::move(dcke), 256, 253);
2✔
1481

1482
  DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
1483
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc);
2✔
1484
  /* Fake algorithm number (private) */
1485
  drc.d_algorithm = 253;
2✔
1486

1487
  /* Set the root DS */
1488
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1489
  luaconfsCopy.dsAnchors.clear();
2✔
1490
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
2✔
1491
  g_luaconfs.setState(luaconfsCopy);
2✔
1492

1493
  size_t queriesCount = 0;
2✔
1494

1495
  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 */) {
2✔
1496
    queriesCount++;
2✔
1497

1498
    if (domain == target && type == QType::NS) {
2!
1499

1500
      setLWResult(res, 0, true, false, true);
2✔
1501
      char addr[] = "a.root-servers.net.";
2✔
1502
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1503
        addr[0] = idx;
26✔
1504
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1505
      }
26✔
1506

1507
      addRRSIG(keys, res->d_records, domain, 300);
2✔
1508

1509
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1510
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1511

1512
      return LWResult::Result::Success;
2✔
1513
    }
2✔
1514
    if (domain == target && type == QType::DNSKEY) {
×
1515

1516
      setLWResult(res, 0, true, false, true);
×
1517

1518
      addDNSKEY(keys, domain, 300, res->d_records);
×
1519
      addRRSIG(keys, res->d_records, domain, 300);
×
1520

1521
      return LWResult::Result::Success;
×
1522
    }
×
1523

1524
    return LWResult::Result::Timeout;
×
1525
  });
×
1526

1527
  vector<DNSRecord> ret;
2✔
1528
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1529
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1530
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
2✔
1531
  /* 13 NS + 1 RRSIG */
1532
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1533
  /* no supported DS so no query for DNSKEYs */
1534
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1535

1536
  /* again, to test the cache */
1537
  ret.clear();
2✔
1538
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1539
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1540
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
2✔
1541
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1542
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1543
}
2✔
1544

1545
BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest)
1546
{
2✔
1547
  std::unique_ptr<SyncRes> sr;
2✔
1548
  initSR(sr, true);
2✔
1549

1550
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1551

1552
  primeHints();
2✔
1553
  const DNSName target(".");
2✔
1554
  testkeysset_t keys;
2✔
1555

1556
  /* Generate key material for "." */
1557
  auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
2✔
1558
  dcke->create(dcke->getBits());
2✔
1559
  DNSSECPrivateKey dpk;
2✔
1560
  dpk.setKey(std::move(dcke), 256);
2✔
1561
  DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
2✔
1562
  /* Fake digest number (reserved) */
1563
  drc.d_digesttype = 0;
2✔
1564

1565
  keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc);
2✔
1566

1567
  /* Set the root DS */
1568
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1569
  luaconfsCopy.dsAnchors.clear();
2✔
1570
  luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
2✔
1571
  g_luaconfs.setState(luaconfsCopy);
2✔
1572

1573
  size_t queriesCount = 0;
2✔
1574

1575
  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 */) {
2✔
1576
    queriesCount++;
2✔
1577

1578
    if (domain == target && type == QType::NS) {
2!
1579

1580
      setLWResult(res, 0, true, false, true);
2✔
1581
      char addr[] = "a.root-servers.net.";
2✔
1582
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1583
        addr[0] = idx;
26✔
1584
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1585
      }
26✔
1586

1587
      addRRSIG(keys, res->d_records, domain, 300);
2✔
1588

1589
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1590
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1591

1592
      return LWResult::Result::Success;
2✔
1593
    }
2✔
1594
    if (domain == target && type == QType::DNSKEY) {
×
1595

1596
      setLWResult(res, 0, true, false, true);
×
1597

1598
      addDNSKEY(keys, domain, 300, res->d_records);
×
1599
      addRRSIG(keys, res->d_records, domain, 300);
×
1600

1601
      return LWResult::Result::Success;
×
1602
    }
×
1603

1604
    return LWResult::Result::Timeout;
×
1605
  });
×
1606

1607
  vector<DNSRecord> ret;
2✔
1608
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1609
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1610
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
2✔
1611
  /* 13 NS + 1 RRSIG */
1612
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1613
  /* no supported DS so no query for DNSKEYs */
1614
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1615

1616
  /* again, to test the cache */
1617
  ret.clear();
2✔
1618
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1619
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1620
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
2✔
1621
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1622
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
1623
}
2✔
1624

1625
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig)
1626
{
2✔
1627
  std::unique_ptr<SyncRes> sr;
2✔
1628
  initSR(sr, true);
2✔
1629

1630
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1631

1632
  primeHints();
2✔
1633
  const DNSName target(".");
2✔
1634
  testkeysset_t keys;
2✔
1635

1636
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1637
  luaconfsCopy.dsAnchors.clear();
2✔
1638
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
1639

1640
  g_luaconfs.setState(luaconfsCopy);
2✔
1641
  /* make sure that the signature inception and validity times are computed
1642
     based on the SyncRes time, not the current one, in case the function
1643
     takes too long. */
1644
  const time_t fixedNow = sr->getNow().tv_sec;
2✔
1645

1646
  size_t queriesCount = 0;
2✔
1647

1648
  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 */) {
4✔
1649
    queriesCount++;
4✔
1650

1651
    if (domain == target && type == QType::NS) {
4!
1652

1653
      setLWResult(res, 0, true, false, true);
2✔
1654
      char addr[] = "a.root-servers.net.";
2✔
1655
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1656
        addr[0] = idx;
26✔
1657
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1658
      }
26✔
1659

1660
      addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow);
2✔
1661

1662
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1663
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1664

1665
      return LWResult::Result::Success;
2✔
1666
    }
2✔
1667
    if (domain == target && type == QType::DNSKEY) {
2!
1668

1669
      setLWResult(res, 0, true, false, true);
2✔
1670

1671
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1672
      addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow);
2✔
1673

1674
      return LWResult::Result::Success;
2✔
1675
    }
2✔
1676

1677
    return LWResult::Result::Timeout;
×
1678
  });
2✔
1679

1680
  vector<DNSRecord> ret;
2✔
1681
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1682
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1683
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1684
  /* 13 NS + 1 RRSIG */
1685
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1686
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1687

1688
  /* again, to test the cache */
1689
  ret.clear();
2✔
1690
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1691
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1692
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1693
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1694
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1695
}
2✔
1696

1697
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_sigs)
1698
{
2✔
1699
  std::unique_ptr<SyncRes> sr;
2✔
1700
  initSR(sr, true);
2✔
1701

1702
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1703

1704
  primeHints();
2✔
1705
  const DNSName target(".");
2✔
1706
  testkeysset_t keys;
2✔
1707

1708
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1709
  luaconfsCopy.dsAnchors.clear();
2✔
1710
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
1711

1712
  g_luaconfs.setState(luaconfsCopy);
2✔
1713
  /* make sure that the signature inception and validity times are computed
1714
     based on the SyncRes time, not the current one, in case the function
1715
     takes too long. */
1716
  const time_t fixedNow = sr->getNow().tv_sec;
2✔
1717

1718
  size_t queriesCount = 0;
2✔
1719

1720
  sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](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 */) {
4✔
1721
    queriesCount++;
4✔
1722

1723
    if (domain == target && type == QType::NS) {
4!
1724

1725
      setLWResult(res, 0, true, false, true);
2✔
1726
      char addr[] = "a.root-servers.net.";
2✔
1727
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1728
        addr[0] = idx;
26✔
1729
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1730
      }
26✔
1731

1732
      addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow);
2✔
1733
      addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow);
2✔
1734
      addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow);
2✔
1735

1736
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1737
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1738

1739
      return LWResult::Result::Success;
2✔
1740
    }
2✔
1741
    else if (domain == target && type == QType::DNSKEY) {
2!
1742

1743
      setLWResult(res, 0, true, false, true);
2✔
1744

1745
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1746
      addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow);
2✔
1747

1748
      return LWResult::Result::Success;
2✔
1749
    }
2✔
1750

1751
    return LWResult::Result::Timeout;
×
1752
  });
4✔
1753

1754
  g_maxRRSIGsPerRecordToConsider = 2;
2✔
1755

1756
  vector<DNSRecord> ret;
2✔
1757
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1758
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1759
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1760
  /* 13 NS + 1 RRSIG */
1761
  BOOST_REQUIRE_EQUAL(ret.size(), 16U);
2✔
1762
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1763

1764
  /* again, to test the cache */
1765
  ret.clear();
2✔
1766
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1767
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1768
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1769
  BOOST_REQUIRE_EQUAL(ret.size(), 16U);
2✔
1770
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1771

1772
  g_maxRRSIGsPerRecordToConsider = 0;
2✔
1773
}
2✔
1774

1775
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_sig_validations)
1776
{
2✔
1777
  std::unique_ptr<SyncRes> sr;
2✔
1778
  initSR(sr, true);
2✔
1779

1780
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1781

1782
  primeHints();
2✔
1783
  const DNSName target(".");
2✔
1784
  testkeysset_t keys;
2✔
1785

1786
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1787
  luaconfsCopy.dsAnchors.clear();
2✔
1788
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
1789

1790
  g_luaconfs.setState(luaconfsCopy);
2✔
1791
  /* make sure that the signature inception and validity times are computed
1792
     based on the SyncRes time, not the current one, in case the function
1793
     takes too long. */
1794
  const time_t fixedNow = sr->getNow().tv_sec;
2✔
1795

1796
  size_t queriesCount = 0;
2✔
1797

1798
  sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](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 */) {
4✔
1799
    queriesCount++;
4✔
1800

1801
    if (domain == target && type == QType::NS) {
4!
1802

1803
      setLWResult(res, 0, true, false, true);
2✔
1804
      char addr[] = "a.root-servers.net.";
2✔
1805
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1806
        addr[0] = idx;
26✔
1807
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1808
      }
26✔
1809

1810
      addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow);
2✔
1811
      addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow);
2✔
1812

1813
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1814
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1815

1816
      return LWResult::Result::Success;
2✔
1817
    }
2✔
1818
    else if (domain == target && type == QType::DNSKEY) {
2!
1819

1820
      setLWResult(res, 0, true, false, true);
2✔
1821

1822
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1823
      addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow);
2✔
1824

1825
      return LWResult::Result::Success;
2✔
1826
    }
2✔
1827

1828
    return LWResult::Result::Timeout;
×
1829
  });
4✔
1830

1831
  SyncRes::s_maxvalidationsperq = 1U;
2✔
1832

1833
  vector<DNSRecord> ret;
2✔
1834
  BOOST_REQUIRE_THROW(sr->beginResolve(target, QType(QType::NS), QClass::IN, ret), ImmediateServFailException);
2✔
1835

1836
  SyncRes::s_maxvalidationsperq = 0U;
2✔
1837
}
2✔
1838

1839
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo)
1840
{
2✔
1841
  std::unique_ptr<SyncRes> sr;
2✔
1842
  initSR(sr, true);
2✔
1843

1844
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1845

1846
  primeHints();
2✔
1847
  const DNSName target(".");
2✔
1848
  testkeysset_t keys;
2✔
1849

1850
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1851
  luaconfsCopy.dsAnchors.clear();
2✔
1852
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
1853

1854
  g_luaconfs.setState(luaconfsCopy);
2✔
1855

1856
  size_t queriesCount = 0;
2✔
1857

1858
  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 */) {
4✔
1859
    queriesCount++;
4✔
1860

1861
    if (domain == target && type == QType::NS) {
4!
1862

1863
      setLWResult(res, 0, true, false, true);
2✔
1864
      char addr[] = "a.root-servers.net.";
2✔
1865
      for (char idx = 'a'; idx <= 'm'; idx++) {
28✔
1866
        addr[0] = idx;
26✔
1867
        addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
26✔
1868
      }
26✔
1869

1870
      /* FORCE WRONG ALGO */
1871
      addRRSIG(keys, res->d_records, domain, 300, false, DNSSECKeeper::RSASHA256);
2✔
1872

1873
      addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1874
      addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1875

1876
      return LWResult::Result::Success;
2✔
1877
    }
2✔
1878
    if (domain == target && type == QType::DNSKEY) {
2!
1879

1880
      setLWResult(res, 0, true, false, true);
2✔
1881

1882
      addDNSKEY(keys, domain, 300, res->d_records);
2✔
1883
      addRRSIG(keys, res->d_records, domain, 300);
2✔
1884

1885
      return LWResult::Result::Success;
2✔
1886
    }
2✔
1887

1888
    return LWResult::Result::Timeout;
×
1889
  });
2✔
1890

1891
  vector<DNSRecord> ret;
2✔
1892
  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1893
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1894
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1895
  /* 13 NS + 1 RRSIG */
1896
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1897
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1898

1899
  /* again, to test the cache */
1900
  ret.clear();
2✔
1901
  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
2✔
1902
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1903
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
2✔
1904
  BOOST_REQUIRE_EQUAL(ret.size(), 14U);
2✔
1905
  BOOST_CHECK_EQUAL(queriesCount, 2U);
2✔
1906
}
2✔
1907

1908
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds)
1909
{
2✔
1910
  std::unique_ptr<SyncRes> sr;
2✔
1911
  initSR(sr, true);
2✔
1912

1913
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1914

1915
  primeHints();
2✔
1916
  const DNSName target("com.");
2✔
1917
  const ComboAddress targetAddr("192.0.2.42");
2✔
1918
  testkeysset_t keys;
2✔
1919

1920
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
1921
  luaconfsCopy.dsAnchors.clear();
2✔
1922
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
1923
  generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
2✔
1924

1925
  g_luaconfs.setState(luaconfsCopy);
2✔
1926

1927
  size_t queriesCount = 0;
2✔
1928

1929
  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 */) {
6✔
1930
    queriesCount++;
6✔
1931

1932
    DNSName auth = domain;
6✔
1933

1934
    if (type == QType::DS || type == QType::DNSKEY) {
6!
1935
      if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys) == LWResult::Result::Timeout) {
2!
1936
        return LWResult::Result::Timeout;
×
1937
      }
×
1938

1939
      if (type == QType::DS && domain == target) {
2!
1940
        /* remove the last record, which is the DS's RRSIG */
1941
        res->d_records.pop_back();
×
1942
      }
×
1943

1944
      return LWResult::Result::Success;
2✔
1945
    }
2✔
1946

1947
    if (isRootServer(address)) {
4✔
1948
      setLWResult(res, 0, false, false, true);
2✔
1949
      addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
2✔
1950
      /* Include the DS but omit the RRSIG*/
1951
      addDS(DNSName("com."), 300, res->d_records, keys);
2✔
1952
      addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
2✔
1953
      return LWResult::Result::Success;
2✔
1954
    }
2✔
1955

1956
    if (address == ComboAddress("192.0.2.1:53")) {
2!
1957
      setLWResult(res, RCode::NoError, true, false, true);
2✔
1958
      addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
2✔
1959
      addRRSIG(keys, res->d_records, auth, 300);
2✔
1960
      return LWResult::Result::Success;
2✔
1961
    }
2✔
1962

1963
    return LWResult::Result::Timeout;
×
1964
  });
2✔
1965

1966
  vector<DNSRecord> ret;
2✔
1967
  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
1968
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1969
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1970
  BOOST_REQUIRE_EQUAL(ret.size(), 2U);
2✔
1971
  BOOST_CHECK_EQUAL(queriesCount, 3U);
2✔
1972

1973
  /* again, to test the cache */
1974
  ret.clear();
2✔
1975
  res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2✔
1976
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1977
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1978
  BOOST_REQUIRE_EQUAL(ret.size(), 2U);
2✔
1979
  BOOST_CHECK_EQUAL(queriesCount, 3U);
2✔
1980

1981
  /* now we ask directly for the DS */
1982
  ret.clear();
2✔
1983
  res = sr->beginResolve(DNSName("com."), QType(QType::DS), QClass::IN, ret);
2✔
1984
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
1985
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
1986
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
1987
  BOOST_CHECK_EQUAL(queriesCount, 3U);
2✔
1988
}
2✔
1989

1990
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct)
1991
{
2✔
1992
  std::unique_ptr<SyncRes> sr;
2✔
1993
  initSR(sr, true);
2✔
1994

1995
  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
2✔
1996

1997
  primeHints();
2✔
1998
  const DNSName target("com.");
2✔
1999
  testkeysset_t keys;
2✔
2000

2001
  auto luaconfsCopy = g_luaconfs.getCopy();
2✔
2002
  luaconfsCopy.dsAnchors.clear();
2✔
2003
  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
2✔
2004
  generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
2✔
2005

2006
  g_luaconfs.setState(luaconfsCopy);
2✔
2007

2008
  size_t queriesCount = 0;
2✔
2009

2010
  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 */) {
2✔
2011
    queriesCount++;
2✔
2012

2013
    DNSName auth = domain;
2✔
2014

2015
    if (type == QType::DS || type == QType::DNSKEY) {
2!
2016
      if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys) == LWResult::Result::Timeout) {
2!
2017
        return LWResult::Result::Timeout;
×
2018
      }
×
2019

2020
      if (type == QType::DS && domain == target) {
2!
2021
        /* remove the last record, which is the DS's RRSIG */
2022
        res->d_records.pop_back();
2✔
2023
      }
2✔
2024

2025
      return LWResult::Result::Success;
2✔
2026
    }
2✔
2027

2028
    if (isRootServer(address)) {
×
2029
      setLWResult(res, 0, false, false, true);
×
2030
      addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
×
2031
      /* Include the DS but omit the RRSIG*/
2032
      addDS(DNSName("com."), 300, res->d_records, keys);
×
2033
      addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
×
2034
      return LWResult::Result::Success;
×
2035
    }
×
2036

2037
    return LWResult::Result::Timeout;
×
2038
  });
×
2039

2040
  vector<DNSRecord> ret;
2✔
2041
  int res = sr->beginResolve(DNSName("com."), QType(QType::DS), QClass::IN, ret);
2✔
2042
  BOOST_CHECK_EQUAL(res, RCode::NoError);
2✔
2043
  BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
2✔
2044
  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
2✔
2045
  BOOST_CHECK_EQUAL(queriesCount, 1U);
2✔
2046
}
2✔
2047

2048
BOOST_AUTO_TEST_SUITE_END()
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc