g_luaconfs.setState(luaconfsCopy);
g_dnssecmode = DNSSECMode::Off;
+ g_dnssecLOG = false;
::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Unit Tests";
}
rrc.d_signature = rc->sign(msg);
}
-static void addRRSIG(const std::unordered_map<DNSName, DNSSECPrivateKey>& keys, std::vector<DNSRecord>& records, const DNSName& signer, uint32_t sigValidity)
+typedef std::unordered_map<DNSName, std::pair<DNSSECPrivateKey, DSRecordContent> > testkeysset_t;
+
+static void addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& records, const DNSName& signer, uint32_t sigValidity)
{
if (records.empty()) {
return;
}
RRSIGRecordContent rrc;
- computeRRSIG(it->second, signer, records[recordsCount-1].d_name, records[recordsCount-1].d_type, records[recordsCount-1].d_ttl, sigValidity, rrc, recordcontents);
+ computeRRSIG(it->second.first, signer, records[recordsCount-1].d_name, records[recordsCount-1].d_type, records[recordsCount-1].d_ttl, sigValidity, rrc, recordcontents);
DNSRecord rec;
rec.d_place = records[recordsCount-1].d_place;
records.push_back(rec);
}
-static void addDNSKEY(const std::unordered_map<DNSName, DNSSECPrivateKey>& keys, const DNSName& signer, uint32_t ttl, std::vector<DNSRecord>& records)
+static void addDNSKEY(const testkeysset_t& keys, const DNSName& signer, uint32_t ttl, std::vector<DNSRecord>& records)
{
const auto it = keys.find(signer);
if (it == keys.cend()) {
rec.d_type = QType::DNSKEY;
rec.d_ttl = ttl;
- rec.d_content = std::make_shared<DNSKEYRecordContent>(it->second.getDNSKEY());
+ rec.d_content = std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY());
records.push_back(rec);
}
-static void addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records)
+static void addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records, const testkeysset_t& keys)
{
- auto luaconfsLocal = g_luaconfs.getLocal();
- const auto it = luaconfsLocal->dsAnchors.find(domain);
- if (it == luaconfsLocal->dsAnchors.cend()) {
+ const auto it = keys.find(domain);
+ if (it == keys.cend()) {
return;
}
- for (const auto& ds : it->second) {
- DNSRecord rec;
- rec.d_name = domain;
- rec.d_type = QType::DS;
- rec.d_place = DNSResourceRecord::AUTHORITY;
- rec.d_ttl = ttl;
- rec.d_content = std::make_shared<DSRecordContent>(ds);
+ DNSRecord rec;
+ rec.d_name = domain;
+ rec.d_type = QType::DS;
+ rec.d_place = DNSResourceRecord::AUTHORITY;
+ rec.d_ttl = ttl;
+ rec.d_content = std::make_shared<DSRecordContent>(it->second.second);
- records.push_back(rec);
- }
+ records.push_back(rec);
}
static void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records)
records.push_back(rec);
}
-static void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, std::unordered_map<DNSName, DNSSECPrivateKey>& keys, map<DNSName,dsmap_t>& dsAnchors)
+static void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys)
{
auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(algo));
- dcke->create(dcke->getBits());
+ dcke->create((algo <= 10) ? 2048 : dcke->getBits());
DNSSECPrivateKey dpk;
dpk.d_flags = 256;
dpk.setKey(dcke);
- keys[name] = dpk;
DSRecordContent ds = makeDSFromDNSKey(name, dpk.getDNSKEY(), digest);
- dsAnchors[name].insert(ds);
+ keys[name] = std::pair<DNSSECPrivateKey,DSRecordContent>(dpk,ds);
+}
+
+static void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys, map<DNSName,dsmap_t>& dsAnchors)
+{
+ generateKeyMaterial(name, algo, digest, keys);
+ dsAnchors[name].insert(keys[name].second);
}
/* Real tests */
/* we are primed, we should be able to resolve A a.root-servers.net. without any query */
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
ret.clear();
res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::AAAA);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
- BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
}
BOOST_AUTO_TEST_CASE(test_root_primed_ns) {
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 13);
BOOST_CHECK_EQUAL(queriesCount, 1);
}
then call getRootNS(), for which at least one of the root servers needs to answer */
vector<DNSRecord> ret;
int res = sr->beginResolve(DNSName("."), QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(queriesCount, 2);
}
/* fake that the root NS doesn't handle EDNS, check that we fallback */
vector<DNSRecord> ret;
int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(queriesWithEDNS, 1);
BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1);
/* fake that the NS doesn't handle EDNS, check that we fallback */
vector<DNSRecord> ret;
int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(queriesWithEDNS, 1);
BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1);
/* fake that the NS truncates every request over UDP, we should fallback to TCP */
vector<DNSRecord> ret;
int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
}
BOOST_AUTO_TEST_CASE(test_tc_over_tcp) {
vector<DNSRecord> ret;
int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(tcpQueriesCount, 2);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(downServers.size(), 3);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 2);
BOOST_CHECK(ret[0].d_type == QType::CNAME);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 2);
BOOST_REQUIRE(ret[0].d_type == QType::CNAME);
BOOST_CHECK_EQUAL(ret[0].d_name, target);
ret.clear();
res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
/* one for target1 */
BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(nsCounts.size(), 3);
BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.1:53")], 1);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 0);
BOOST_CHECK_EQUAL(queriesCount, 0);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(ret[0].d_ttl, SyncRes::s_minimumTTL);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_REQUIRE(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 0);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 4);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::PTR);
BOOST_CHECK_EQUAL(queriesCount, 0);
ret.clear();
res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::PTR);
BOOST_CHECK_EQUAL(queriesCount, 0);
ret.clear();
res = sr->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::PTR), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::PTR);
BOOST_CHECK_EQUAL(queriesCount, 0);
ret.clear();
res = sr->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::ANY), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::PTR);
BOOST_CHECK_EQUAL(queriesCount, 0);
ret.clear();
res = sr->beginResolve(DNSName("localhost."), QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), "127.0.0.1");
ret.clear();
res = sr->beginResolve(DNSName("localhost."), QType(QType::AAAA), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::AAAA);
BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(ret[0])->getCA().toString(), "::1");
ret.clear();
res = sr->beginResolve(DNSName("localhost."), QType(QType::ANY), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 2);
for (const auto& rec : ret) {
BOOST_REQUIRE((rec.d_type == QType::A) || rec.d_type == QType::AAAA);
ret.clear();
res = sr->beginResolve(DNSName("version.bind."), QType(QType::TXT), QClass::CHAOS, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::TXT);
BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
ret.clear();
res = sr->beginResolve(DNSName("version.bind."), QType(QType::ANY), QClass::CHAOS, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::TXT);
BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
ret.clear();
res = sr->beginResolve(DNSName("version.pdns."), QType(QType::TXT), QClass::CHAOS, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::TXT);
BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
ret.clear();
res = sr->beginResolve(DNSName("version.pdns."), QType(QType::ANY), QClass::CHAOS, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::TXT);
BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
ret.clear();
res = sr->beginResolve(DNSName("id.server."), QType(QType::TXT), QClass::CHAOS, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::TXT);
BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\"");
ret.clear();
res = sr->beginResolve(DNSName("id.server."), QType(QType::ANY), QClass::CHAOS, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::TXT);
BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\"");
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 2);
BOOST_CHECK(ret[0].d_type == QType::CNAME);
BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), authZone.toString());
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 2);
BOOST_CHECK(ret[0].d_type == QType::CNAME);
BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), externalCNAME.toString());
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::SOA);
BOOST_CHECK_EQUAL(queriesCount, 0);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(queriesCount, 1);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(queriesCount, 1);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(queriesCount, 0);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::SOA);
BOOST_CHECK_EQUAL(queriesCount, 0);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK(ret[0].d_type == QType::A);
BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
}
BOOST_AUTO_TEST_CASE(test_dnssec_rrsig) {
-// g_dnssecLOG = true;
init();
auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t keys;
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
BOOST_CHECK_EQUAL(queriesCount, 2);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 2);
}
BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> zskeys;
- std::unordered_map<DNSName, DNSSECPrivateKey> kskeys;
+ testkeysset_t zskeys;
+ testkeysset_t kskeys;
/* Generate key material for "." */
auto dckeZ = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
DNSSECPrivateKey ksk;
ksk.d_flags = 257;
ksk.setKey(dckeZ);
+ DSRecordContent kskds = makeDSFromDNSKey(target, ksk.getDNSKEY(), DNSSECKeeper::SHA256);
+
auto dckeK = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
dckeK->create(dckeK->getBits());
DNSSECPrivateKey zsk;
zsk.d_flags = 256;
zsk.setKey(dckeK);
+ DSRecordContent zskds = makeDSFromDNSKey(target, zsk.getDNSKEY(), DNSSECKeeper::SHA256);
- kskeys[target] = ksk;
- zskeys[target] = zsk;
+ kskeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(ksk, kskds);
+ zskeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(zsk, zskds);
/* Set the root DS */
- DSRecordContent drc = makeDSFromDNSKey(target, ksk.getDNSKEY(), DNSSECKeeper::SHA256);
-
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
- luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
+ luaconfsCopy.dsAnchors[g_rootdnsname].insert(kskds);
g_luaconfs.setState(luaconfsCopy);
size_t queriesCount = 0;
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
BOOST_CHECK_EQUAL(queriesCount, 2);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 2);
}
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t keys;
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
BOOST_CHECK_EQUAL(queriesCount, 2);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 2);
}
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> dskeys;
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t dskeys;
+ testkeysset_t keys;
/* Generate key material for "." */
auto dckeDS = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
DNSSECPrivateKey dskey;
dskey.d_flags = 257;
dskey.setKey(dckeDS);
+ DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::SHA256);
+
auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
dcke->create(dcke->getBits());
DNSSECPrivateKey dpk;
dpk.d_flags = 256;
dpk.setKey(dcke);
+ DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
- dskeys[target] = dskey;
- keys[target] = dpk;
+ dskeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(dskey, drc);
+ keys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(dpk, uselessdrc);
/* Set the root DS */
- DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::SHA256);
-
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
BOOST_CHECK_EQUAL(queriesCount, 2);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 2);
}
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
- std::unordered_map<DNSName, DNSSECPrivateKey> rrsigkeys;
+ testkeysset_t keys;
+ testkeysset_t rrsigkeys;
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
DNSSECPrivateKey rrsigkey;
rrsigkey.d_flags = 257;
rrsigkey.setKey(dckeRRSIG);
- rrsigkeys[target] = rrsigkey;
+ DSRecordContent rrsigds = makeDSFromDNSKey(target, rrsigkey.getDNSKEY(), DNSSECKeeper::SHA256);
+
+ rrsigkeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(rrsigkey, rrsigds);
size_t queriesCount = 0;
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
BOOST_CHECK_EQUAL(queriesCount, 2);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 2);
}
BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t keys;
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
/* 13 NS + 0 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 13);
/* no RRSIG so no query for DNSKEYs */
BOOST_CHECK_EQUAL(queriesCount, 1);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_REQUIRE_EQUAL(ret.size(), 13);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
}
BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t keys;
/* Generate key material for "." */
auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
/* Fake algorithm number (private) */
dpk.d_algorithm = 253;
- keys[target] = dpk;
-
- /* Set the root DS */
DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
+ keys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(dpk, drc);
/* Fake algorithm number (private) */
drc.d_algorithm = 253;
+ /* Set the root DS */
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
/* no supported DS so no query for DNSKEYs */
BOOST_CHECK_EQUAL(queriesCount, 1);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
}
BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t keys;
/* Generate key material for "." */
auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
DNSSECPrivateKey dpk;
dpk.d_flags = 256;
dpk.setKey(dcke);
-
- keys[target] = dpk;
-
- /* Set the root DS */
DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
/* Fake digest number (reserved) */
drc.d_digesttype = 0;
+ keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc);
+
+ /* Set the root DS */
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
/* no supported DS so no query for DNSKEYs */
BOOST_CHECK_EQUAL(queriesCount, 1);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
}
-BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_nsec) {
+BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos) {
std::unique_ptr<SyncRes> sr;
init();
initSR(sr, true, true);
primeHints();
const DNSName target("powerdns.com.");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ const ComboAddress targetAddr("192.0.2.42");
+ testkeysset_t keys;
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
- generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
- generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
- generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::SHA384, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384, DNSSECKeeper::SHA384, keys);
g_luaconfs.setState(luaconfsCopy);
size_t queriesCount = 0;
- 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
queriesCount++;
+ DNSName auth = domain;
+ if (domain == target) {
+ auth = DNSName("powerdns.com.");
+ }
if (type == QType::DS) {
setLWResult(res, 0, false, false, true);
- addDS(domain, 300, res->d_records);
- addRRSIG(keys, res->d_records, domain, 300);
+ addDS(auth, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, auth, 300);
return 1;
}
else if (type == QType::DNSKEY) {
setLWResult(res, 0, true, false, true);
- addDNSKEY(keys, domain, 300, res->d_records);
- addRRSIG(keys, res->d_records, domain, 300);
+ addDNSKEY(keys, auth, 300, res->d_records);
+ addRRSIG(keys, res->d_records, auth, 300);
return 1;
}
else if (domain == target) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
- addRRSIG(keys, res->d_records, DNSName("."), 300);
- addDS(DNSName("com."), 300, res->d_records);
+ addDS(DNSName("com."), 300, res->d_records, keys);
addRRSIG(keys, res->d_records, DNSName("."), 300);
addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
return 1;
}
else if (ip == ComboAddress("192.0.2.1:53")) {
setLWResult(res, 0, false, false, true);
- addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
- addRRSIG(keys, res->d_records, DNSName("com."), 300);
- addDS(domain, 300, res->d_records);
+ addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(auth, 300, res->d_records, keys);
addRRSIG(keys, res->d_records, DNSName("com."), 300);
addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
return 1;
}
else if (ip == ComboAddress("192.0.2.2:53")) {
- setLWResult(res, 0, true, false, true);
- addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
- addRRSIG(keys, res->d_records, domain, 300);
- addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS, QType::DNSKEY }, 600, res->d_records);
- addRRSIG(keys, res->d_records, domain, 300);
+ setLWResult(res, RCode::NoError, true, false, true);
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ addRRSIG(keys, res->d_records, auth, 300);
return 1;
}
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
- BOOST_REQUIRE_EQUAL(ret.size(), 4);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 2);
BOOST_CHECK_EQUAL(queriesCount, 6);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 2);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
}
-BOOST_AUTO_TEST_CASE(test_dnssec_nta) {
+BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta) {
std::unique_ptr<SyncRes> sr;
init();
initSR(sr, true, true);
g_dnssecmode = DNSSECMode::ValidateAll;
primeHints();
- const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
-
- /* Generate key material for "." */
- auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
- dcke->create(dcke->getBits());
- DNSSECPrivateKey dpk;
- dpk.d_flags = 256;
- dpk.setKey(dcke);
-
- keys[target] = dpk;
-
- /* Set the root DS */
- DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
+ const DNSName target("powerdns.com.");
+ const ComboAddress targetAddr("192.0.2.42");
+ testkeysset_t keys;
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dsAnchors.clear();
- luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ /* Add a NTA for "powerdns.com" */
+ luaconfsCopy.negAnchors[target] = "NTA for PowerDNS.com";
- /* Add a NTA for "." */
- luaconfsCopy.negAnchors[g_rootdnsname] = "NTA for Root";
g_luaconfs.setState(luaconfsCopy);
size_t queriesCount = 0;
- 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
queriesCount++;
- if (domain == target && type == QType::NS) {
-
+ DNSName auth = domain;
+ if (domain == target) {
+ auth = DNSName("powerdns.com.");
+ }
+ if (type == QType::DS) {
+ setLWResult(res, 0, false, false, true);
+ addDS(auth, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, auth, 300);
+ return 1;
+ }
+ else if (type == QType::DNSKEY) {
setLWResult(res, 0, true, false, true);
- char addr[] = "a.root-servers.net.";
- for (char idx = 'a'; idx <= 'm'; idx++) {
- addr[0] = idx;
+ addDNSKEY(keys, auth, 300, res->d_records);
+ addRRSIG(keys, res->d_records, auth, 300);
+ return 1;
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(auth, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, RCode::NoError, true, false, true);
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ addRRSIG(keys, res->d_records, auth, 300);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ /* Should be insecure because of the NTA */
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 2);
+ /* and a such, no query for the last DNSKEYs */
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ /* Should be insecure because of the NTA */
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 2);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("powerdns.com.");
+ const ComboAddress targetAddr("192.0.2.42");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ /* Add a NTA for "powerdns.com" */
+ luaconfsCopy.negAnchors[target] = "NTA for PowerDNS.com";
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS || type == QType::DNSKEY) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ return 1;
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, RCode::NoError, true, false, true);
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ /* Should be insecure because of the NTA */
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ /* and a such, no query for the DNSKEYs */
+ BOOST_CHECK_EQUAL(queriesCount, 4);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK_EQUAL(queriesCount, 4);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("powerdns.com.");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ setLWResult(res, 0, false, false, true);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else if (type == QType::DNSKEY) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ addRRSIG(keys, res->d_records, domain, 300);
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS, QType::DNSKEY }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 4);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 4);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("nx.powerdns.com.");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ DNSName auth = domain;
+ if (domain == target) {
+ auth = DNSName("powerdns.com.");
+ }
+ if (type == QType::DS) {
+ setLWResult(res, 0, false, false, true);
+ addDS(auth, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, auth, 300);
+ return 1;
+ }
+ else if (type == QType::DNSKEY) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, auth, 300, res->d_records);
+ addRRSIG(keys, res->d_records, auth, 300);
+ return 1;
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(auth, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, RCode::NXDomain, true, false, true);
+ addRecordToLW(res, DNSName("powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ addRRSIG(keys, res->d_records, auth, 300);
+ addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG, QType::NSEC }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, auth, 300);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NXDomain);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 4);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NXDomain);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 4);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("powerdns.com.");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ setLWResult(res, 0, false, false, true);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else if (type == QType::DNSKEY) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ addRRSIG(keys, res->d_records, domain, 300);
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS, QType::DNSKEY }, 600, res->d_records);
+ /* NO RRSIG for the NSEC record! */
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_CHECK_EQUAL(ret.size(), 3);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_REQUIRE_EQUAL(ret.size(), 3);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("powerdns.com.");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ setLWResult(res, 0, false, false, true);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else if (type == QType::DNSKEY) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ addRRSIG(keys, res->d_records, domain, 300);
+
+ /* NO NSEC record! */
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ /* no NSEC record in a secure zone, should be Bogus! */
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_CHECK_EQUAL(ret.size(), 2);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+ BOOST_REQUIRE_EQUAL(ret.size(), 2);
+ BOOST_CHECK_EQUAL(queriesCount, 6);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("powerdns.com.");
+ const ComboAddress targetAddr("192.0.2.42");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ if (domain == g_rootdnsname || domain == DNSName("com.")) {
+ setLWResult(res, 0, false, false, true);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else {
+ setLWResult(res, 0, false, false, true);
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ return 1;
+ }
+ }
+ else if (type == QType::DNSKEY) {
+ if (domain == g_rootdnsname || domain == DNSName("com.")) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else {
+ setLWResult(res, 0, false, false, true);
+ return 1;
+ }
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ /* no DS */
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK(ret[0].d_type == QType::A);
+ /* only 5 because no DNSKEY query for powerdns.com (insecure) */
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK(ret[0].d_type == QType::A);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("powerdns.com.");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ if (domain == g_rootdnsname || domain == DNSName("com.")) {
+ setLWResult(res, 0, false, false, true);
+ addDS(domain, 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else {
+ setLWResult(res, 0, false, false, true);
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ return 1;
+ }
+ }
+ else if (type == QType::DNSKEY) {
+ if (domain == g_rootdnsname || domain == DNSName("com.")) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else {
+ setLWResult(res, 0, false, false, true);
+ return 1;
+ }
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ /* no DS */
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ /* only 5 because no DNSKEY query for powerdns.com (insecure) */
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_nta) {
+ std::unique_ptr<SyncRes> sr;
+ init();
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target(".");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ /* Add a NTA for "." */
+ luaconfsCopy.negAnchors[g_rootdnsname] = "NTA for Root";
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ 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, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (domain == target && type == QType::NS) {
+
+ setLWResult(res, 0, true, false, true);
+ char addr[] = "a.root-servers.net.";
+ for (char idx = 'a'; idx <= 'm'; idx++) {
+ addr[0] = idx;
addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
}
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
/* 13 NS + 1 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 14);
BOOST_CHECK_EQUAL(queriesCount, 1);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 14);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
}
BOOST_AUTO_TEST_CASE(test_dnssec_no_ta) {
primeHints();
const DNSName target(".");
- std::unordered_map<DNSName, DNSSECPrivateKey> keys;
+ testkeysset_t keys;
/* Remove the root DS */
auto luaconfsCopy = g_luaconfs.getCopy();
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, 0);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
/* 13 NS + 0 RRSIG */
BOOST_REQUIRE_EQUAL(ret.size(), 13);
BOOST_CHECK_EQUAL(queriesCount, 1);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 13);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
}
/*