PageRenderTime 2178ms CodeModel.GetById 30ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/ldns/drill/dnssec.c

https://github.com/thesjg/DragonFlyBSD
C | 509 lines | 378 code | 73 blank | 58 comment | 101 complexity | 603c6d1963a81970d9fbc7ae2364230f MD5 | raw file
  1. /*
  2. * dnssec.c
  3. * Some DNSSEC helper function are defined here
  4. * and tracing is done
  5. * (c) 2005 NLnet Labs
  6. *
  7. * See the file LICENSE for the license
  8. *
  9. */
  10. #include "drill.h"
  11. #include <ldns/ldns.h>
  12. /* get rr_type from a server from a server */
  13. ldns_rr_list *
  14. get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c)
  15. {
  16. /* query, retrieve, extract and return */
  17. ldns_pkt *p;
  18. ldns_rr_list *found;
  19. p = ldns_pkt_new();
  20. found = NULL;
  21. if (ldns_resolver_send(&p, res, zname, t, c, 0) != LDNS_STATUS_OK) {
  22. /* oops */
  23. return NULL;
  24. } else {
  25. found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION);
  26. }
  27. return found;
  28. }
  29. void
  30. drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p)
  31. {
  32. ldns_rr_list *new_nss;
  33. ldns_rr_list *hostnames;
  34. if (verbosity < 5) {
  35. return;
  36. }
  37. hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
  38. new_nss = ldns_pkt_rr_list_by_type(p,
  39. LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER);
  40. ldns_rr_list_print(fd, new_nss);
  41. /* new_nss can be empty.... */
  42. fprintf(fd, ";; Received %d bytes from %s#%d(",
  43. (int) ldns_pkt_size(p),
  44. ldns_rdf2str(ldns_pkt_answerfrom(p)),
  45. (int) ldns_resolver_port(r));
  46. /* if we can resolve this print it, other print the ip again */
  47. if (hostnames) {
  48. ldns_rdf_print(fd,
  49. ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
  50. ldns_rr_list_deep_free(hostnames);
  51. } else {
  52. fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
  53. }
  54. fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
  55. }
  56. void
  57. drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p)
  58. {
  59. ldns_rr_list *hostnames;
  60. if (verbosity < 5) {
  61. return;
  62. }
  63. hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0);
  64. fprintf(fd, ";; Received %d bytes from %s#%d(",
  65. (int) ldns_pkt_size(p),
  66. ldns_rdf2str(ldns_pkt_answerfrom(p)),
  67. (int) ldns_resolver_port(r));
  68. /* if we can resolve this print it, other print the ip again */
  69. if (hostnames) {
  70. ldns_rdf_print(fd,
  71. ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0));
  72. ldns_rr_list_deep_free(hostnames);
  73. } else {
  74. fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p)));
  75. }
  76. fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p));
  77. }
  78. /*
  79. * generic function to get some RRset from a nameserver
  80. * and possible some signatures too (that would be the day...)
  81. */
  82. ldns_pkt_type
  83. get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t,
  84. ldns_rr_list **rrlist, ldns_rr_list **sig)
  85. {
  86. ldns_pkt_type pt = LDNS_PACKET_UNKNOWN;
  87. ldns_rr_list *rr = NULL;
  88. ldns_rr_list *sigs = NULL;
  89. size_t i;
  90. if (!p) {
  91. if (rrlist) {
  92. *rrlist = NULL;
  93. }
  94. return LDNS_PACKET_UNKNOWN;
  95. }
  96. pt = ldns_pkt_reply_type(p);
  97. if (name) {
  98. rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER);
  99. if (!rr) {
  100. rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY);
  101. }
  102. sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG,
  103. LDNS_SECTION_ANSWER);
  104. if (!sigs) {
  105. sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG,
  106. LDNS_SECTION_AUTHORITY);
  107. }
  108. } else {
  109. /* A DS-referral - get the DS records if they are there */
  110. rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY);
  111. sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG,
  112. LDNS_SECTION_AUTHORITY);
  113. }
  114. if (sig) {
  115. *sig = ldns_rr_list_new();
  116. for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) {
  117. /* only add the sigs that cover this type */
  118. if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) ==
  119. t) {
  120. ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i)));
  121. }
  122. }
  123. }
  124. ldns_rr_list_deep_free(sigs);
  125. if (rrlist) {
  126. *rrlist = rr;
  127. }
  128. if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) {
  129. return pt;
  130. } else {
  131. return LDNS_PACKET_ANSWER;
  132. }
  133. }
  134. ldns_status
  135. ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
  136. {
  137. uint16_t nsec_i;
  138. ldns_rr_list *nsecs;
  139. ldns_status result;
  140. if (verbosity >= 5) {
  141. printf("VERIFY DENIAL FROM:\n");
  142. ldns_pkt_print(stdout, pkt);
  143. }
  144. result = LDNS_STATUS_CRYPTO_NO_RRSIG;
  145. /* Try to see if there are NSECS in the packet */
  146. nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION);
  147. if (nsecs) {
  148. for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
  149. /* there are four options:
  150. * - name equals ownername and is covered by the type bitmap
  151. * - name equals ownername but is not covered by the type bitmap
  152. * - name falls within nsec coverage but is not equal to the owner name
  153. * - name falls outside of nsec coverage
  154. */
  155. if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
  156. /*
  157. printf("CHECKING NSEC:\n");
  158. ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i));
  159. printf("DAWASEM\n");
  160. */
  161. if (ldns_nsec_bitmap_covers_type(
  162. ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs,
  163. nsec_i)),
  164. type)) {
  165. /* Error, according to the nsec this rrset is signed */
  166. result = LDNS_STATUS_CRYPTO_NO_RRSIG;
  167. } else {
  168. /* ok nsec denies existence */
  169. if (verbosity >= 3) {
  170. printf(";; Existence of data set with this type denied by NSEC\n");
  171. }
  172. /*printf(";; Verifiably insecure.\n");*/
  173. if (nsec_rrs && nsec_rr_sigs) {
  174. (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
  175. }
  176. ldns_rr_list_deep_free(nsecs);
  177. return LDNS_STATUS_OK;
  178. }
  179. } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
  180. if (verbosity >= 3) {
  181. printf(";; Existence of data set with this name denied by NSEC\n");
  182. }
  183. if (nsec_rrs && nsec_rr_sigs) {
  184. (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs);
  185. }
  186. ldns_rr_list_deep_free(nsecs);
  187. return LDNS_STATUS_OK;
  188. } else {
  189. /* nsec has nothing to do with this data */
  190. }
  191. }
  192. ldns_rr_list_deep_free(nsecs);
  193. } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) {
  194. ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION);
  195. ldns_rr* q = ldns_rr_new();
  196. if(!sigs) return LDNS_STATUS_MEM_ERR;
  197. if(!q) return LDNS_STATUS_MEM_ERR;
  198. ldns_rr_set_question(q, 1);
  199. ldns_rr_set_ttl(q, 0);
  200. ldns_rr_set_owner(q, ldns_rdf_clone(name));
  201. if(!ldns_rr_owner(q)) return LDNS_STATUS_MEM_ERR;
  202. ldns_rr_set_type(q, type);
  203. result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0);
  204. ldns_rr_free(q);
  205. ldns_rr_list_deep_free(nsecs);
  206. ldns_rr_list_deep_free(sigs);
  207. }
  208. return result;
  209. }
  210. /* NSEC3 draft -07 */
  211. /*return hash name match*/
  212. ldns_rr *
  213. ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) {
  214. uint8_t algorithm;
  215. uint32_t iterations;
  216. uint8_t salt_length;
  217. uint8_t *salt;
  218. ldns_rdf *sname, *hashed_sname;
  219. size_t nsec_i;
  220. ldns_rr *nsec;
  221. ldns_rr *result = NULL;
  222. ldns_status status;
  223. const ldns_rr_descriptor *descriptor;
  224. ldns_rdf *zone_name;
  225. if (verbosity >= 4) {
  226. printf(";; finding exact match for ");
  227. descriptor = ldns_rr_descript(qtype);
  228. if (descriptor && descriptor->_name) {
  229. printf("%s ", descriptor->_name);
  230. } else {
  231. printf("TYPE%d ", qtype);
  232. }
  233. ldns_rdf_print(stdout, qname);
  234. printf("\n");
  235. }
  236. if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
  237. if (verbosity >= 4) {
  238. printf("no qname, nsec3s or list empty\n");
  239. }
  240. return NULL;
  241. }
  242. nsec = ldns_rr_list_rr(nsec3s, 0);
  243. algorithm = ldns_nsec3_algorithm(nsec);
  244. salt_length = ldns_nsec3_salt_length(nsec);
  245. salt = ldns_nsec3_salt_data(nsec);
  246. iterations = ldns_nsec3_iterations(nsec);
  247. sname = ldns_rdf_clone(qname);
  248. if (verbosity >= 4) {
  249. printf(";; owner name hashes to: ");
  250. }
  251. hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
  252. zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
  253. status = ldns_dname_cat(hashed_sname, zone_name);
  254. if (verbosity >= 4) {
  255. ldns_rdf_print(stdout, hashed_sname);
  256. printf("\n");
  257. }
  258. for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
  259. nsec = ldns_rr_list_rr(nsec3s, nsec_i);
  260. /* check values of iterations etc! */
  261. /* exact match? */
  262. if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
  263. result = nsec;
  264. goto done;
  265. }
  266. }
  267. done:
  268. ldns_rdf_deep_free(zone_name);
  269. ldns_rdf_deep_free(sname);
  270. ldns_rdf_deep_free(hashed_sname);
  271. LDNS_FREE(salt);
  272. if (verbosity >= 4) {
  273. if (result) {
  274. printf(";; Found.\n");
  275. } else {
  276. printf(";; Not foud.\n");
  277. }
  278. }
  279. return result;
  280. }
  281. /*return the owner name of the closest encloser for name from the list of rrs */
  282. /* this is NOT the hash, but the original name! */
  283. ldns_rdf *
  284. ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s)
  285. {
  286. /* remember parameters, they must match */
  287. uint8_t algorithm;
  288. uint32_t iterations;
  289. uint8_t salt_length;
  290. uint8_t *salt;
  291. ldns_rdf *sname, *hashed_sname, *tmp;
  292. ldns_rr *ce;
  293. bool flag;
  294. bool exact_match_found;
  295. bool in_range_found;
  296. ldns_status status;
  297. ldns_rdf *zone_name;
  298. size_t nsec_i;
  299. ldns_rr *nsec;
  300. ldns_rdf *result = NULL;
  301. if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
  302. return NULL;
  303. }
  304. if (verbosity >= 4) {
  305. printf(";; finding closest encloser for type %d ", qtype);
  306. ldns_rdf_print(stdout, qname);
  307. printf("\n");
  308. }
  309. nsec = ldns_rr_list_rr(nsec3s, 0);
  310. algorithm = ldns_nsec3_algorithm(nsec);
  311. salt_length = ldns_nsec3_salt_length(nsec);
  312. salt = ldns_nsec3_salt_data(nsec);
  313. iterations = ldns_nsec3_iterations(nsec);
  314. sname = ldns_rdf_clone(qname);
  315. ce = NULL;
  316. flag = false;
  317. zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
  318. /* algorithm from nsec3-07 8.3 */
  319. while (ldns_dname_label_count(sname) > 0) {
  320. exact_match_found = false;
  321. in_range_found = false;
  322. if (verbosity >= 3) {
  323. printf(";; ");
  324. ldns_rdf_print(stdout, sname);
  325. printf(" hashes to: ");
  326. }
  327. hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt);
  328. status = ldns_dname_cat(hashed_sname, zone_name);
  329. if (verbosity >= 3) {
  330. ldns_rdf_print(stdout, hashed_sname);
  331. printf("\n");
  332. }
  333. for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
  334. nsec = ldns_rr_list_rr(nsec3s, nsec_i);
  335. /* check values of iterations etc! */
  336. /* exact match? */
  337. if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
  338. if (verbosity >= 4) {
  339. printf(";; exact match found\n");
  340. }
  341. exact_match_found = true;
  342. } else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
  343. if (verbosity >= 4) {
  344. printf(";; in range of an nsec\n");
  345. }
  346. in_range_found = true;
  347. }
  348. }
  349. if (!exact_match_found && in_range_found) {
  350. flag = true;
  351. } else if (exact_match_found && flag) {
  352. result = ldns_rdf_clone(sname);
  353. } else if (exact_match_found && !flag) {
  354. // error!
  355. if (verbosity >= 4) {
  356. printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n");
  357. }
  358. ldns_rdf_deep_free(hashed_sname);
  359. goto done;
  360. } else {
  361. flag = false;
  362. }
  363. ldns_rdf_deep_free(hashed_sname);
  364. tmp = sname;
  365. sname = ldns_dname_left_chop(sname);
  366. ldns_rdf_deep_free(tmp);
  367. }
  368. done:
  369. LDNS_FREE(salt);
  370. ldns_rdf_deep_free(zone_name);
  371. ldns_rdf_deep_free(sname);
  372. if (!result) {
  373. if (verbosity >= 4) {
  374. printf(";; no closest encloser found\n");
  375. }
  376. }
  377. /* todo checks from end of 6.2. here or in caller? */
  378. return result;
  379. }
  380. /* special case were there was a wildcard expansion match, the exact match must be disproven */
  381. ldns_status
  382. ldns_verify_denial_wildcard(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs)
  383. {
  384. ldns_rdf *nsec3_ce = NULL;
  385. ldns_rr *nsec3_ex = NULL;
  386. ldns_rdf *wildcard_name = NULL;
  387. ldns_rdf *nsec3_wc_ce = NULL;
  388. ldns_rr *nsec3_wc_ex = NULL;
  389. ldns_rdf *chopped_dname = NULL;
  390. ldns_rr_list *nsecs;
  391. ldns_status result = LDNS_STATUS_ERR;
  392. nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION);
  393. if (nsecs) {
  394. wildcard_name = ldns_dname_new_frm_str("*");
  395. chopped_dname = ldns_dname_left_chop(name);
  396. result = ldns_dname_cat(wildcard_name, chopped_dname);
  397. ldns_rdf_deep_free(chopped_dname);
  398. nsec3_ex = ldns_nsec3_exact_match(name, type, nsecs);
  399. nsec3_ce = ldns_nsec3_closest_encloser(name, type, nsecs);
  400. nsec3_wc_ce = ldns_nsec3_closest_encloser(wildcard_name, type, nsecs);
  401. nsec3_wc_ex = ldns_nsec3_exact_match(wildcard_name, type, nsecs);
  402. if (nsec3_ex) {
  403. if (verbosity >= 3) {
  404. printf(";; Error, exact match for for name found, but should not exist (draft -07 section 8.8)\n");
  405. }
  406. result = LDNS_STATUS_NSEC3_ERR;
  407. } else if (!nsec3_ce) {
  408. if (verbosity >= 3) {
  409. printf(";; Error, closest encloser for exact match missing in wildcard response (draft -07 section 8.8)\n");
  410. }
  411. result = LDNS_STATUS_NSEC3_ERR;
  412. /*
  413. } else if (!nsec3_wc_ex) {
  414. printf(";; Error, no wildcard nsec3 match: ");
  415. ldns_rdf_print(stdout, wildcard_name);
  416. printf(" (draft -07 section 8.8)\n");
  417. result = LDNS_STATUS_NSEC3_ERR;
  418. */
  419. /* } else if (!nsec */
  420. } else {
  421. if (verbosity >= 3) {
  422. printf(";; wilcard expansion proven\n");
  423. }
  424. result = LDNS_STATUS_OK;
  425. }
  426. } else {
  427. if (verbosity >= 3) {
  428. printf(";; Error: no NSEC or NSEC3 records in answer\n");
  429. }
  430. result = LDNS_STATUS_CRYPTO_NO_RRSIG;
  431. }
  432. if (nsecs && nsec_rrs && nsec_rr_sigs) {
  433. (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, 0)), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs);
  434. }
  435. return result;
  436. }