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.
 
 
 
 
 
 

1279 lines
53 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_cc6)
  5. BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure)
  6. {
  7. std::unique_ptr<SyncRes> sr;
  8. initSR(sr, true);
  9. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  10. primeHints();
  11. const DNSName target("www.powerdns.com.");
  12. testkeysset_t keys;
  13. auto luaconfsCopy = g_luaconfs.getCopy();
  14. luaconfsCopy.dsAnchors.clear();
  15. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  16. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  17. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  18. g_luaconfs.setState(luaconfsCopy);
  19. size_t queriesCount = 0;
  20. size_t dsQueriesCount = 0;
  21. sr->setAsyncCallback([target, &queriesCount, &dsQueriesCount, 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) {
  22. queriesCount++;
  23. if (type == QType::DS) {
  24. DNSName auth(domain);
  25. auth.chopOff();
  26. dsQueriesCount++;
  27. if (domain == target) {
  28. if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys, false) == 0) {
  29. return 0;
  30. }
  31. return 1;
  32. }
  33. setLWResult(res, 0, true, false, true);
  34. addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  35. addRRSIG(keys, res->d_records, auth, 300);
  36. return 1;
  37. }
  38. else if (type == QType::DNSKEY) {
  39. setLWResult(res, 0, true, false, true);
  40. addDNSKEY(keys, domain, 300, res->d_records);
  41. addRRSIG(keys, res->d_records, domain, 300);
  42. return 1;
  43. }
  44. else {
  45. if (isRootServer(ip)) {
  46. setLWResult(res, 0, false, false, true);
  47. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  48. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  49. /* No DS on referral, and no denial of the DS either */
  50. return 1;
  51. }
  52. else if (ip == ComboAddress("192.0.2.1:53")) {
  53. if (domain == DNSName("com.")) {
  54. setLWResult(res, 0, true, false, true);
  55. addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  56. addRRSIG(keys, res->d_records, domain, 300);
  57. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  58. addRRSIG(keys, res->d_records, domain, 300);
  59. }
  60. else {
  61. setLWResult(res, 0, false, false, true);
  62. addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  63. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  64. /* No DS on referral, and no denial of the DS either */
  65. }
  66. return 1;
  67. }
  68. else if (ip == ComboAddress("192.0.2.2:53")) {
  69. setLWResult(res, 0, true, false, true);
  70. if (type == QType::NS) {
  71. if (domain == DNSName("powerdns.com.")) {
  72. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  73. addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
  74. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  75. addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
  76. }
  77. else {
  78. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  79. addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
  80. addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A, QType::NSEC, QType::RRSIG}, 600, res->d_records);
  81. addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
  82. }
  83. }
  84. else {
  85. addRecordToLW(res, domain, QType::A, "192.0.2.42");
  86. addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
  87. }
  88. return 1;
  89. }
  90. }
  91. return 0;
  92. });
  93. vector<DNSRecord> ret;
  94. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  95. BOOST_CHECK_EQUAL(res, RCode::NoError);
  96. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  97. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  98. BOOST_CHECK_EQUAL(queriesCount, 9U);
  99. BOOST_CHECK_EQUAL(dsQueriesCount, 3U);
  100. /* again, to test the cache */
  101. ret.clear();
  102. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  103. BOOST_CHECK_EQUAL(res, RCode::NoError);
  104. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  105. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  106. BOOST_CHECK_EQUAL(queriesCount, 9U);
  107. BOOST_CHECK_EQUAL(dsQueriesCount, 3U);
  108. }
  109. BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop)
  110. {
  111. std::unique_ptr<SyncRes> sr;
  112. initSR(sr, true);
  113. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  114. primeHints();
  115. const DNSName target("www.powerdns.com.");
  116. testkeysset_t keys;
  117. auto luaconfsCopy = g_luaconfs.getCopy();
  118. luaconfsCopy.dsAnchors.clear();
  119. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  120. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  121. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  122. generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  123. g_luaconfs.setState(luaconfsCopy);
  124. size_t queriesCount = 0;
  125. 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) {
  126. queriesCount++;
  127. if (type == QType::DS) {
  128. DNSName auth(domain);
  129. auth.chopOff();
  130. setLWResult(res, 0, true, false, true);
  131. if (domain == target) {
  132. addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  133. addRRSIG(keys, res->d_records, domain, 300);
  134. }
  135. else {
  136. addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  137. addRRSIG(keys, res->d_records, auth, 300);
  138. }
  139. return 1;
  140. }
  141. else if (type == QType::DNSKEY) {
  142. setLWResult(res, 0, true, false, true);
  143. addDNSKEY(keys, domain, 300, res->d_records);
  144. addRRSIG(keys, res->d_records, domain, 300);
  145. return 1;
  146. }
  147. else {
  148. if (isRootServer(ip)) {
  149. setLWResult(res, 0, false, false, true);
  150. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  151. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  152. addDS(DNSName("com."), 300, res->d_records, keys);
  153. addRRSIG(keys, res->d_records, DNSName("."), 300);
  154. return 1;
  155. }
  156. else if (ip == ComboAddress("192.0.2.1:53")) {
  157. if (domain == DNSName("com.")) {
  158. setLWResult(res, 0, true, false, true);
  159. addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  160. addRRSIG(keys, res->d_records, domain, 300);
  161. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  162. addRRSIG(keys, res->d_records, domain, 300);
  163. }
  164. else {
  165. setLWResult(res, 0, false, false, true);
  166. addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  167. /* no DS */
  168. addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
  169. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  170. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  171. }
  172. return 1;
  173. }
  174. else if (ip == ComboAddress("192.0.2.2:53")) {
  175. if (type == QType::NS) {
  176. if (domain == DNSName("powerdns.com.")) {
  177. setLWResult(res, RCode::Refused, false, false, true);
  178. }
  179. else {
  180. setLWResult(res, 0, true, false, true);
  181. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  182. addRRSIG(keys, res->d_records, domain, 300);
  183. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  184. addRRSIG(keys, res->d_records, domain, 300);
  185. }
  186. }
  187. else {
  188. setLWResult(res, 0, true, false, true);
  189. addRecordToLW(res, domain, QType::A, "192.0.2.42");
  190. addRRSIG(keys, res->d_records, DNSName("www.powerdns.com"), 300);
  191. }
  192. return 1;
  193. }
  194. }
  195. return 0;
  196. });
  197. vector<DNSRecord> ret;
  198. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  199. BOOST_CHECK_EQUAL(res, RCode::NoError);
  200. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusSelfSignedDS);
  201. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  202. BOOST_CHECK_EQUAL(queriesCount, 8U);
  203. /* again, to test the cache */
  204. ret.clear();
  205. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  206. BOOST_CHECK_EQUAL(res, RCode::NoError);
  207. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusSelfSignedDS);
  208. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  209. BOOST_CHECK_EQUAL(queriesCount, 8U);
  210. }
  211. BOOST_AUTO_TEST_CASE(test_dnssec_ds_root)
  212. {
  213. std::unique_ptr<SyncRes> sr;
  214. initSR(sr, true);
  215. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  216. primeHints();
  217. const DNSName target(".");
  218. testkeysset_t keys;
  219. auto luaconfsCopy = g_luaconfs.getCopy();
  220. luaconfsCopy.dsAnchors.clear();
  221. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  222. g_luaconfs.setState(luaconfsCopy);
  223. size_t queriesCount = 0;
  224. 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) {
  225. queriesCount++;
  226. if (type == QType::DS) {
  227. setLWResult(res, 0, true, false, true);
  228. addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  229. addRRSIG(keys, res->d_records, DNSName("."), 300);
  230. addNSECRecordToLW(domain, DNSName("aaa."), {QType::DNSKEY, QType::SOA, QType::NS, QType::NSEC, QType::RRSIG}, 600, res->d_records);
  231. addRRSIG(keys, res->d_records, DNSName("."), 300);
  232. return 1;
  233. }
  234. return 0;
  235. });
  236. vector<DNSRecord> ret;
  237. int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  238. BOOST_CHECK_EQUAL(res, RCode::NoError);
  239. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  240. BOOST_REQUIRE_EQUAL(ret.size(), 4U);
  241. BOOST_CHECK_EQUAL(queriesCount, 1U);
  242. /* again, to test the cache */
  243. ret.clear();
  244. res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  245. BOOST_CHECK_EQUAL(res, RCode::NoError);
  246. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  247. BOOST_REQUIRE_EQUAL(ret.size(), 4U);
  248. BOOST_CHECK_EQUAL(queriesCount, 1U);
  249. }
  250. BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child)
  251. {
  252. /* check that we don't accept a signer below us */
  253. std::unique_ptr<SyncRes> sr;
  254. initSR(sr, true);
  255. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  256. primeHints();
  257. const DNSName target("www.powerdns.com.");
  258. testkeysset_t keys;
  259. auto luaconfsCopy = g_luaconfs.getCopy();
  260. luaconfsCopy.dsAnchors.clear();
  261. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  262. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  263. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  264. generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  265. generateKeyMaterial(DNSName("sub.www.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  266. g_luaconfs.setState(luaconfsCopy);
  267. size_t queriesCount = 0;
  268. 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) {
  269. queriesCount++;
  270. if (type == QType::DS) {
  271. DNSName auth(domain);
  272. auth.chopOff();
  273. setLWResult(res, 0, true, false, true);
  274. addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  275. addRRSIG(keys, res->d_records, auth, 300);
  276. return 1;
  277. }
  278. else if (type == QType::DNSKEY) {
  279. setLWResult(res, 0, true, false, true);
  280. addDNSKEY(keys, domain, 300, res->d_records);
  281. if (domain == DNSName("www.powerdns.com.")) {
  282. addRRSIG(keys, res->d_records, DNSName("sub.www.powerdns.com."), 300);
  283. }
  284. else {
  285. addRRSIG(keys, res->d_records, domain, 300);
  286. }
  287. return 1;
  288. }
  289. else {
  290. if (isRootServer(ip)) {
  291. setLWResult(res, 0, false, false, true);
  292. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  293. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  294. addDS(DNSName("com."), 300, res->d_records, keys);
  295. addRRSIG(keys, res->d_records, DNSName("."), 300);
  296. return 1;
  297. }
  298. else if (ip == ComboAddress("192.0.2.1:53")) {
  299. if (domain == DNSName("com.")) {
  300. setLWResult(res, 0, true, false, true);
  301. addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  302. addRRSIG(keys, res->d_records, domain, 300);
  303. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  304. addRRSIG(keys, res->d_records, domain, 300);
  305. }
  306. else {
  307. setLWResult(res, 0, false, false, true);
  308. addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  309. addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
  310. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  311. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  312. }
  313. return 1;
  314. }
  315. else if (ip == ComboAddress("192.0.2.2:53")) {
  316. if (type == QType::NS) {
  317. setLWResult(res, 0, true, false, true);
  318. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  319. addRRSIG(keys, res->d_records, domain, 300);
  320. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  321. addRRSIG(keys, res->d_records, domain, 300);
  322. }
  323. else {
  324. setLWResult(res, 0, true, false, true);
  325. addRecordToLW(res, domain, QType::A, "192.0.2.42");
  326. addRRSIG(keys, res->d_records, domain, 300);
  327. }
  328. return 1;
  329. }
  330. }
  331. return 0;
  332. });
  333. vector<DNSRecord> ret;
  334. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  335. BOOST_CHECK_EQUAL(res, RCode::NoError);
  336. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
  337. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  338. BOOST_CHECK_EQUAL(queriesCount, 10U);
  339. /* again, to test the cache */
  340. ret.clear();
  341. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  342. BOOST_CHECK_EQUAL(res, RCode::NoError);
  343. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
  344. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  345. BOOST_CHECK_EQUAL(queriesCount, 10U);
  346. }
  347. BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure)
  348. {
  349. std::unique_ptr<SyncRes> sr;
  350. initSR(sr, true);
  351. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  352. primeHints();
  353. const DNSName target("www.powerdns.com.");
  354. testkeysset_t keys;
  355. auto luaconfsCopy = g_luaconfs.getCopy();
  356. luaconfsCopy.dsAnchors.clear();
  357. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  358. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  359. g_luaconfs.setState(luaconfsCopy);
  360. size_t queriesCount = 0;
  361. size_t dsQueriesCount = 0;
  362. sr->setAsyncCallback([target, &queriesCount, &dsQueriesCount, 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) {
  363. queriesCount++;
  364. if (type == QType::DS) {
  365. DNSName auth(domain);
  366. auth.chopOff();
  367. dsQueriesCount++;
  368. setLWResult(res, 0, true, false, true);
  369. if (domain == DNSName("com.")) {
  370. addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
  371. }
  372. else {
  373. addRecordToLW(res, "com.", QType::SOA, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  374. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  375. addNSECRecordToLW(domain, DNSName("powerdnt.com."), {QType::NS}, 600, res->d_records);
  376. }
  377. addRRSIG(keys, res->d_records, auth, 300);
  378. return 1;
  379. }
  380. else if (type == QType::DNSKEY) {
  381. setLWResult(res, 0, true, false, true);
  382. addDNSKEY(keys, domain, 300, res->d_records);
  383. addRRSIG(keys, res->d_records, domain, 300);
  384. return 1;
  385. }
  386. else {
  387. if (isRootServer(ip)) {
  388. setLWResult(res, 0, false, false, true);
  389. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  390. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  391. /* No DS on referral, and no denial of the DS either */
  392. return 1;
  393. }
  394. else if (ip == ComboAddress("192.0.2.1:53")) {
  395. if (domain == DNSName("com.")) {
  396. setLWResult(res, 0, true, false, true);
  397. addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
  398. addRRSIG(keys, res->d_records, domain, 300);
  399. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  400. addRRSIG(keys, res->d_records, domain, 300);
  401. }
  402. else {
  403. setLWResult(res, 0, false, false, true);
  404. addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  405. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  406. /* No DS on referral, and no denial of the DS either */
  407. }
  408. return 1;
  409. }
  410. else if (ip == ComboAddress("192.0.2.2:53")) {
  411. setLWResult(res, 0, true, false, true);
  412. if (type == QType::NS) {
  413. if (domain == DNSName("powerdns.com.")) {
  414. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  415. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  416. }
  417. else {
  418. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  419. }
  420. }
  421. else {
  422. addRecordToLW(res, domain, QType::A, "192.0.2.42");
  423. }
  424. return 1;
  425. }
  426. }
  427. return 0;
  428. });
  429. vector<DNSRecord> ret;
  430. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  431. BOOST_CHECK_EQUAL(res, RCode::NoError);
  432. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  433. BOOST_REQUIRE_EQUAL(ret.size(), 1U);
  434. BOOST_CHECK_EQUAL(queriesCount, 7U);
  435. BOOST_CHECK_EQUAL(dsQueriesCount, 2U);
  436. /* again, to test the cache */
  437. ret.clear();
  438. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  439. BOOST_CHECK_EQUAL(res, RCode::NoError);
  440. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  441. BOOST_REQUIRE_EQUAL(ret.size(), 1U);
  442. BOOST_CHECK_EQUAL(queriesCount, 7U);
  443. BOOST_CHECK_EQUAL(dsQueriesCount, 2U);
  444. }
  445. BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec)
  446. {
  447. std::unique_ptr<SyncRes> sr;
  448. initSR(sr, true);
  449. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  450. primeHints();
  451. const DNSName target("powerdns.com.");
  452. testkeysset_t keys;
  453. auto luaconfsCopy = g_luaconfs.getCopy();
  454. luaconfsCopy.dsAnchors.clear();
  455. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  456. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  457. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  458. g_luaconfs.setState(luaconfsCopy);
  459. size_t queriesCount = 0;
  460. 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) {
  461. queriesCount++;
  462. if (type == QType::DS || type == QType::DNSKEY) {
  463. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  464. }
  465. else {
  466. if (isRootServer(ip)) {
  467. setLWResult(res, 0, false, false, true);
  468. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  469. addDS(DNSName("com."), 300, res->d_records, keys);
  470. addRRSIG(keys, res->d_records, DNSName("."), 300);
  471. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  472. return 1;
  473. }
  474. else if (ip == ComboAddress("192.0.2.1:53")) {
  475. if (domain == DNSName("com.")) {
  476. setLWResult(res, 0, true, false, true);
  477. addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  478. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  479. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  480. }
  481. else {
  482. setLWResult(res, 0, false, false, true);
  483. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  484. addDS(domain, 300, res->d_records, keys);
  485. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  486. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  487. }
  488. return 1;
  489. }
  490. else if (ip == ComboAddress("192.0.2.2:53")) {
  491. setLWResult(res, 0, true, false, true);
  492. if (type == QType::NS) {
  493. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  494. addRRSIG(keys, res->d_records, domain, 300);
  495. }
  496. else {
  497. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  498. addRRSIG(keys, res->d_records, domain, 300);
  499. addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS, QType::DNSKEY}, 600, res->d_records);
  500. /* NO RRSIG for the NSEC record! */
  501. }
  502. return 1;
  503. }
  504. }
  505. return 0;
  506. });
  507. /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
  508. vector<DNSRecord> ret;
  509. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  510. BOOST_CHECK_EQUAL(res, RCode::NoError);
  511. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
  512. BOOST_CHECK_EQUAL(ret.size(), 3U);
  513. BOOST_CHECK_EQUAL(queriesCount, 8U);
  514. /* again, to test the cache */
  515. ret.clear();
  516. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  517. BOOST_CHECK_EQUAL(res, RCode::NoError);
  518. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
  519. BOOST_REQUIRE_EQUAL(ret.size(), 3U);
  520. BOOST_CHECK_EQUAL(queriesCount, 8U);
  521. }
  522. BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec)
  523. {
  524. std::unique_ptr<SyncRes> sr;
  525. initSR(sr, true);
  526. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  527. primeHints();
  528. const DNSName target("powerdns.com.");
  529. testkeysset_t keys;
  530. auto luaconfsCopy = g_luaconfs.getCopy();
  531. luaconfsCopy.dsAnchors.clear();
  532. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  533. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  534. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  535. g_luaconfs.setState(luaconfsCopy);
  536. size_t queriesCount = 0;
  537. 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) {
  538. queriesCount++;
  539. if (type == QType::DS || type == QType::DNSKEY) {
  540. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  541. }
  542. else {
  543. if (isRootServer(ip)) {
  544. setLWResult(res, 0, false, false, true);
  545. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  546. addDS(DNSName("com."), 300, res->d_records, keys);
  547. addRRSIG(keys, res->d_records, DNSName("."), 300);
  548. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  549. return 1;
  550. }
  551. else if (ip == ComboAddress("192.0.2.1:53")) {
  552. if (domain == DNSName("com.")) {
  553. setLWResult(res, 0, true, false, true);
  554. addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  555. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  556. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  557. }
  558. else {
  559. setLWResult(res, 0, false, false, true);
  560. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  561. addDS(domain, 300, res->d_records, keys);
  562. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  563. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  564. }
  565. return 1;
  566. }
  567. else if (ip == ComboAddress("192.0.2.2:53")) {
  568. setLWResult(res, 0, true, false, true);
  569. if (type == QType::NS) {
  570. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  571. addRRSIG(keys, res->d_records, domain, 300);
  572. }
  573. else {
  574. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  575. addRRSIG(keys, res->d_records, domain, 300);
  576. /* NO NSEC record! */
  577. }
  578. return 1;
  579. }
  580. }
  581. return 0;
  582. });
  583. /* no NSEC record in a secure zone, should be Bogus! */
  584. vector<DNSRecord> ret;
  585. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  586. BOOST_CHECK_EQUAL(res, RCode::NoError);
  587. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusInvalidDenial);
  588. BOOST_CHECK_EQUAL(ret.size(), 2U);
  589. BOOST_CHECK_EQUAL(queriesCount, 8U);
  590. /* again, to test the cache */
  591. ret.clear();
  592. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  593. BOOST_CHECK_EQUAL(res, RCode::NoError);
  594. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusInvalidDenial);
  595. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  596. BOOST_CHECK_EQUAL(queriesCount, 8U);
  597. }
  598. BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure)
  599. {
  600. std::unique_ptr<SyncRes> sr;
  601. initSR(sr, true);
  602. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  603. primeHints();
  604. const DNSName target("powerdns.com.");
  605. const ComboAddress targetAddr("192.0.2.42");
  606. testkeysset_t keys;
  607. auto luaconfsCopy = g_luaconfs.getCopy();
  608. luaconfsCopy.dsAnchors.clear();
  609. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  610. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  611. g_luaconfs.setState(luaconfsCopy);
  612. size_t queriesCount = 0;
  613. 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) {
  614. queriesCount++;
  615. if (type == QType::DS) {
  616. if (domain == target) {
  617. setLWResult(res, 0, true, false, true);
  618. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  619. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  620. addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
  621. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  622. return 1;
  623. }
  624. else {
  625. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  626. }
  627. }
  628. else if (type == QType::DNSKEY) {
  629. if (domain == g_rootdnsname || domain == DNSName("com.")) {
  630. setLWResult(res, 0, true, false, true);
  631. addDNSKEY(keys, domain, 300, res->d_records);
  632. addRRSIG(keys, res->d_records, domain, 300);
  633. return 1;
  634. }
  635. else {
  636. setLWResult(res, 0, true, false, true);
  637. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  638. return 1;
  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, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  654. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  655. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  656. }
  657. else {
  658. setLWResult(res, 0, false, false, true);
  659. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  660. /* no DS */
  661. addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
  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. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  671. }
  672. else {
  673. addRecordToLW(res, domain, QType::A, targetAddr.toString());
  674. }
  675. return 1;
  676. }
  677. }
  678. return 0;
  679. });
  680. vector<DNSRecord> ret;
  681. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  682. BOOST_CHECK_EQUAL(res, RCode::NoError);
  683. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  684. BOOST_REQUIRE_EQUAL(ret.size(), 1U);
  685. BOOST_CHECK(ret[0].d_type == QType::A);
  686. /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
  687. 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
  688. 1 query for A */
  689. BOOST_CHECK_EQUAL(queriesCount, 7U);
  690. /* again, to test the cache */
  691. ret.clear();
  692. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  693. BOOST_CHECK_EQUAL(res, RCode::NoError);
  694. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  695. BOOST_REQUIRE_EQUAL(ret.size(), 1U);
  696. BOOST_CHECK(ret[0].d_type == QType::A);
  697. BOOST_CHECK_EQUAL(queriesCount, 7U);
  698. }
  699. BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_optout)
  700. {
  701. std::unique_ptr<SyncRes> sr;
  702. initSR(sr, true);
  703. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  704. primeHints();
  705. const DNSName target("powerdns.com.");
  706. const ComboAddress targetAddr("192.0.2.42");
  707. testkeysset_t keys;
  708. auto luaconfsCopy = g_luaconfs.getCopy();
  709. luaconfsCopy.dsAnchors.clear();
  710. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  711. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  712. g_luaconfs.setState(luaconfsCopy);
  713. size_t queriesCount = 0;
  714. 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) {
  715. queriesCount++;
  716. if (type == QType::DS) {
  717. if (domain == target) {
  718. setLWResult(res, 0, true, false, true);
  719. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  720. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  721. /* closest encloser */
  722. addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), DNSName("a.com.").toStringNoDot(), {QType::NS}, 600, res->d_records, 10, true);
  723. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  724. /* next closer */
  725. addNSEC3UnhashedRecordToLW(DNSName("oowerdns.com."), DNSName("com."), DNSName("qowerdns.com.").toStringNoDot(), {QType::NS}, 600, res->d_records, 10, true);
  726. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  727. return 1;
  728. }
  729. else {
  730. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, true, boost::none, true, true);
  731. }
  732. }
  733. else if (type == QType::DNSKEY) {
  734. if (domain == g_rootdnsname || domain == DNSName("com.")) {
  735. setLWResult(res, 0, true, false, true);
  736. addDNSKEY(keys, domain, 300, res->d_records);
  737. addRRSIG(keys, res->d_records, domain, 300);
  738. return 1;
  739. }
  740. else {
  741. setLWResult(res, 0, true, false, true);
  742. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  743. return 1;
  744. }
  745. }
  746. else {
  747. if (isRootServer(ip)) {
  748. setLWResult(res, 0, false, false, true);
  749. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  750. addDS(DNSName("com."), 300, res->d_records, keys);
  751. addRRSIG(keys, res->d_records, DNSName("."), 300);
  752. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  753. return 1;
  754. }
  755. else if (ip == ComboAddress("192.0.2.1:53")) {
  756. if (domain == DNSName("com.")) {
  757. setLWResult(res, 0, true, false, true);
  758. addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  759. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  760. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  761. }
  762. else {
  763. setLWResult(res, 0, false, false, true);
  764. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  765. /* no DS */
  766. /* closest encloser */
  767. addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), DNSName("a.com.").toStringNoDot(), {QType::NS}, 600, res->d_records, 10, true);
  768. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  769. /* next closer */
  770. addNSEC3UnhashedRecordToLW(DNSName("oowerdns.com."), DNSName("com."), DNSName("qowerdns.com.").toStringNoDot(), {QType::NS}, 600, res->d_records, 10, true);
  771. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  772. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  773. }
  774. return 1;
  775. }
  776. else if (ip == ComboAddress("192.0.2.2:53")) {
  777. setLWResult(res, 0, true, false, true);
  778. if (type == QType::NS) {
  779. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  780. }
  781. else {
  782. addRecordToLW(res, domain, QType::A, targetAddr.toString());
  783. }
  784. return 1;
  785. }
  786. }
  787. return 0;
  788. });
  789. vector<DNSRecord> ret;
  790. int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  791. BOOST_CHECK_EQUAL(res, RCode::NoError);
  792. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  793. BOOST_REQUIRE_EQUAL(ret.size(), 6U);
  794. BOOST_CHECK(ret[0].d_type == QType::SOA);
  795. BOOST_CHECK_EQUAL(queriesCount, 4U);
  796. /* again, to test the cache */
  797. ret.clear();
  798. res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  799. BOOST_CHECK_EQUAL(res, RCode::NoError);
  800. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  801. BOOST_REQUIRE_EQUAL(ret.size(), 6U);
  802. BOOST_CHECK(ret[0].d_type == QType::SOA);
  803. BOOST_CHECK_EQUAL(queriesCount, 4U);
  804. }
  805. BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nxd_optout)
  806. {
  807. std::unique_ptr<SyncRes> sr;
  808. initSR(sr, true);
  809. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  810. primeHints();
  811. const DNSName target("powerdns.com.");
  812. const ComboAddress targetAddr("192.0.2.42");
  813. testkeysset_t keys;
  814. auto luaconfsCopy = g_luaconfs.getCopy();
  815. luaconfsCopy.dsAnchors.clear();
  816. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  817. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  818. g_luaconfs.setState(luaconfsCopy);
  819. size_t queriesCount = 0;
  820. 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) {
  821. queriesCount++;
  822. if (type == QType::DS) {
  823. if (domain == target) {
  824. setLWResult(res, RCode::NXDomain, true, false, true);
  825. addRecordToLW(res, DNSName("com."), QType::SOA, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  826. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  827. /* closest encloser */
  828. addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), DNSName("a.com.").toStringNoDot(), {QType::SOA, QType::NS, QType::DS, QType::DNSKEY, QType::RRSIG, QType::NSEC3PARAM}, 600, res->d_records, 10, true);
  829. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  830. /* next closer */
  831. addNSEC3UnhashedRecordToLW(DNSName("oowerdns.com."), DNSName("com."), DNSName("qowerdns.com.").toStringNoDot(), {QType::NS}, 600, res->d_records, 10, true);
  832. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  833. return 1;
  834. }
  835. else {
  836. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, true, boost::none, true, true);
  837. }
  838. }
  839. else if (type == QType::DNSKEY) {
  840. if (domain == g_rootdnsname || domain == DNSName("com.")) {
  841. setLWResult(res, 0, true, false, true);
  842. addDNSKEY(keys, domain, 300, res->d_records);
  843. addRRSIG(keys, res->d_records, domain, 300);
  844. return 1;
  845. }
  846. else {
  847. setLWResult(res, 0, true, false, true);
  848. addRecordToLW(res, DNSName("com."), QType::SOA, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  849. return 1;
  850. }
  851. }
  852. else {
  853. if (isRootServer(ip)) {
  854. setLWResult(res, 0, false, false, true);
  855. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  856. addDS(DNSName("com."), 300, res->d_records, keys);
  857. addRRSIG(keys, res->d_records, DNSName("."), 300);
  858. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  859. return 1;
  860. }
  861. else if (ip == ComboAddress("192.0.2.1:53")) {
  862. if (domain == DNSName("com.")) {
  863. setLWResult(res, 0, true, false, true);
  864. addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  865. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  866. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  867. }
  868. else {
  869. setLWResult(res, RCode::NXDomain, true, false, true);
  870. addRecordToLW(res, DNSName("com."), QType::SOA, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  871. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  872. /* closest encloser */
  873. addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), DNSName("a.com.").toStringNoDot(), {QType::SOA, QType::NS, QType::DS, QType::DNSKEY, QType::RRSIG, QType::NSEC3PARAM}, 600, res->d_records, 10, true);
  874. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  875. /* next closer */
  876. addNSEC3UnhashedRecordToLW(DNSName("oowerdns.com."), DNSName("com."), DNSName("qowerdns.com.").toStringNoDot(), {QType::NS}, 600, res->d_records, 10, true);
  877. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  878. }
  879. return 1;
  880. }
  881. }
  882. return 0;
  883. });
  884. vector<DNSRecord> ret;
  885. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  886. BOOST_CHECK_EQUAL(res, RCode::NXDomain);
  887. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  888. BOOST_REQUIRE_EQUAL(ret.size(), 6U);
  889. BOOST_CHECK(ret[0].d_type == QType::SOA);
  890. BOOST_CHECK_EQUAL(queriesCount, 6U);
  891. /* again, to test the cache */
  892. ret.clear();
  893. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  894. BOOST_CHECK_EQUAL(res, RCode::NXDomain);
  895. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  896. BOOST_REQUIRE_EQUAL(ret.size(), 6U);
  897. BOOST_CHECK(ret[0].d_type == QType::SOA);
  898. BOOST_CHECK_EQUAL(queriesCount, 6U);
  899. }
  900. BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds)
  901. {
  902. /*
  903. Direct DS query:
  904. - parent is secure, zone is secure: DS should be secure
  905. */
  906. std::unique_ptr<SyncRes> sr;
  907. initSR(sr, true);
  908. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  909. primeHints();
  910. const DNSName target("powerdns.com.");
  911. testkeysset_t keys;
  912. auto luaconfsCopy = g_luaconfs.getCopy();
  913. luaconfsCopy.dsAnchors.clear();
  914. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  915. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  916. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  917. g_luaconfs.setState(luaconfsCopy);
  918. size_t queriesCount = 0;
  919. 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) {
  920. queriesCount++;
  921. if (type == QType::DS || type == QType::DNSKEY) {
  922. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  923. }
  924. else {
  925. if (isRootServer(ip)) {
  926. setLWResult(res, 0, false, false, true);
  927. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  928. addDS(DNSName("com."), 300, res->d_records, keys);
  929. addRRSIG(keys, res->d_records, DNSName("."), 300);
  930. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  931. return 1;
  932. }
  933. }
  934. return 0;
  935. });
  936. vector<DNSRecord> ret;
  937. int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  938. BOOST_CHECK_EQUAL(res, RCode::NoError);
  939. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  940. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  941. for (const auto& record : ret) {
  942. BOOST_CHECK(record.d_type == QType::DS || record.d_type == QType::RRSIG);
  943. }
  944. BOOST_CHECK_EQUAL(queriesCount, 4U);
  945. /* again, to test the cache */
  946. ret.clear();
  947. res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  948. BOOST_CHECK_EQUAL(res, RCode::NoError);
  949. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  950. BOOST_REQUIRE_EQUAL(ret.size(), 2U);
  951. for (const auto& record : ret) {
  952. BOOST_CHECK(record.d_type == QType::DS || record.d_type == QType::RRSIG);
  953. }
  954. BOOST_CHECK_EQUAL(queriesCount, 4U);
  955. }
  956. BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds)
  957. {
  958. /*
  959. Direct DS query:
  960. - parent is secure, zone is insecure: DS denial should be secure
  961. */
  962. std::unique_ptr<SyncRes> sr;
  963. initSR(sr, true);
  964. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  965. primeHints();
  966. const DNSName target("powerdns.com.");
  967. testkeysset_t keys;
  968. auto luaconfsCopy = g_luaconfs.getCopy();
  969. luaconfsCopy.dsAnchors.clear();
  970. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  971. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  972. g_luaconfs.setState(luaconfsCopy);
  973. size_t queriesCount = 0;
  974. 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) {
  975. queriesCount++;
  976. if (type == QType::DS || type == QType::DNSKEY) {
  977. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  978. }
  979. else {
  980. if (isRootServer(ip)) {
  981. setLWResult(res, 0, false, false, true);
  982. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  983. addDS(DNSName("com."), 300, res->d_records, keys);
  984. addRRSIG(keys, res->d_records, DNSName("."), 300);
  985. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  986. return 1;
  987. }
  988. }
  989. return 0;
  990. });
  991. vector<DNSRecord> ret;
  992. int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  993. BOOST_CHECK_EQUAL(res, RCode::NoError);
  994. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  995. BOOST_REQUIRE_EQUAL(ret.size(), 4U);
  996. for (const auto& record : ret) {
  997. BOOST_CHECK(record.d_type == QType::SOA || record.d_type == QType::NSEC || record.d_type == QType::RRSIG);
  998. }
  999. BOOST_CHECK_EQUAL(queriesCount, 4U);
  1000. /* again, to test the cache */
  1001. ret.clear();
  1002. res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret);
  1003. BOOST_CHECK_EQUAL(res, RCode::NoError);
  1004. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
  1005. BOOST_REQUIRE_EQUAL(ret.size(), 4U);
  1006. for (const auto& record : ret) {
  1007. BOOST_CHECK(record.d_type == QType::SOA || record.d_type == QType::NSEC || record.d_type == QType::RRSIG);
  1008. }
  1009. BOOST_CHECK_EQUAL(queriesCount, 4U);
  1010. }
  1011. BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut)
  1012. {
  1013. std::unique_ptr<SyncRes> sr;
  1014. initSR(sr, true);
  1015. setDNSSECValidation(sr, DNSSECMode::ValidateAll);
  1016. primeHints();
  1017. const DNSName target("www.sub.powerdns.com.");
  1018. const ComboAddress targetAddr("192.0.2.42");
  1019. testkeysset_t keys;
  1020. auto luaconfsCopy = g_luaconfs.getCopy();
  1021. luaconfsCopy.dsAnchors.clear();
  1022. generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
  1023. generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  1024. generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
  1025. g_luaconfs.setState(luaconfsCopy);
  1026. size_t queriesCount = 0;
  1027. 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) {
  1028. queriesCount++;
  1029. if (type == QType::DS) {
  1030. if (domain == DNSName("sub.powerdns.com.")) {
  1031. setLWResult(res, 0, true, false, true);
  1032. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  1033. addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
  1034. addNSECRecordToLW(domain, DNSName("z.powerdns.com."), {QType::NS}, 600, res->d_records);
  1035. addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
  1036. return 1;
  1037. }
  1038. else if (domain == DNSName("www.sub.powerdns.com.")) {
  1039. setLWResult(res, 0, true, false, true);
  1040. addRecordToLW(res, DNSName("sub.powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  1041. return 1;
  1042. }
  1043. else {
  1044. return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
  1045. }
  1046. }
  1047. else if (type == QType::DNSKEY) {
  1048. if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
  1049. setLWResult(res, 0, true, false, true);
  1050. addDNSKEY(keys, domain, 300, res->d_records);
  1051. addRRSIG(keys, res->d_records, domain, 300);
  1052. return 1;
  1053. }
  1054. else {
  1055. setLWResult(res, 0, true, false, true);
  1056. addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  1057. return 1;
  1058. }
  1059. }
  1060. else {
  1061. if (isRootServer(ip)) {
  1062. setLWResult(res, 0, false, false, true);
  1063. addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
  1064. addDS(DNSName("com."), 300, res->d_records, keys);
  1065. addRRSIG(keys, res->d_records, DNSName("."), 300);
  1066. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  1067. return 1;
  1068. }
  1069. else if (ip == ComboAddress("192.0.2.1:53")) {
  1070. if (domain == DNSName("com.")) {
  1071. setLWResult(res, 0, true, false, true);
  1072. addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
  1073. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  1074. addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
  1075. }
  1076. else {
  1077. setLWResult(res, 0, false, false, true);
  1078. addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
  1079. addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
  1080. addRRSIG(keys, res->d_records, DNSName("com."), 300);
  1081. addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
  1082. }
  1083. return 1;
  1084. }
  1085. else if (ip == ComboAddress("192.0.2.2:53")) {
  1086. setLWResult(res, 0, true, false, true);
  1087. if (type == QType::NS) {
  1088. if (domain == DNSName("www.sub.powerdns.com.")) {
  1089. addRecordToLW(res, DNSName("sub.powerdns.com"), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
  1090. }
  1091. else if (domain == DNSName("sub.powerdns.com.")) {
  1092. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  1093. }
  1094. else if (domain == DNSName("powerdns.com.")) {
  1095. addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
  1096. addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
  1097. }
  1098. }
  1099. else {
  1100. addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
  1101. }
  1102. return 1;
  1103. }
  1104. }
  1105. return 0;
  1106. });
  1107. vector<DNSRecord> ret;
  1108. int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  1109. BOOST_CHECK_EQUAL(res, RCode::NoError);
  1110. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  1111. BOOST_REQUIRE_EQUAL(ret.size(), 1U);
  1112. BOOST_CHECK(ret[0].d_type == QType::A);
  1113. BOOST_CHECK_EQUAL(queriesCount, 9U);
  1114. /* again, to test the cache */
  1115. ret.clear();
  1116. res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
  1117. BOOST_CHECK_EQUAL(res, RCode::NoError);
  1118. BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
  1119. BOOST_REQUIRE_EQUAL(ret.size(), 1U);
  1120. BOOST_CHECK(ret[0].d_type == QType::A);
  1121. BOOST_CHECK_EQUAL(queriesCount, 9U);
  1122. }
  1123. BOOST_AUTO_TEST_SUITE_END()