You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1983 lines
89 KiB

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