/contrib/bind9/lib/dns/dnssec.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1768 lines · 1281 code · 258 blank · 229 comment · 400 complexity · 30a08016b58babe76cd80e174ff1c03f MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /*
  18. * $Id$
  19. */
  20. /*! \file */
  21. #include <config.h>
  22. #include <stdlib.h>
  23. #include <isc/buffer.h>
  24. #include <isc/dir.h>
  25. #include <isc/mem.h>
  26. #include <isc/serial.h>
  27. #include <isc/string.h>
  28. #include <isc/util.h>
  29. #include <dns/db.h>
  30. #include <dns/diff.h>
  31. #include <dns/dnssec.h>
  32. #include <dns/fixedname.h>
  33. #include <dns/keyvalues.h>
  34. #include <dns/log.h>
  35. #include <dns/message.h>
  36. #include <dns/rdata.h>
  37. #include <dns/rdatalist.h>
  38. #include <dns/rdataset.h>
  39. #include <dns/rdatastruct.h>
  40. #include <dns/result.h>
  41. #include <dns/tsig.h> /* for DNS_TSIG_FUDGE */
  42. #include <dst/result.h>
  43. #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
  44. #define RETERR(x) do { \
  45. result = (x); \
  46. if (result != ISC_R_SUCCESS) \
  47. goto failure; \
  48. } while (0)
  49. #define TYPE_SIGN 0
  50. #define TYPE_VERIFY 1
  51. static isc_result_t
  52. digest_callback(void *arg, isc_region_t *data);
  53. static int
  54. rdata_compare_wrapper(const void *rdata1, const void *rdata2);
  55. static isc_result_t
  56. rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
  57. dns_rdata_t **rdata, int *nrdata);
  58. static isc_result_t
  59. digest_callback(void *arg, isc_region_t *data) {
  60. dst_context_t *ctx = arg;
  61. return (dst_context_adddata(ctx, data));
  62. }
  63. /*
  64. * Make qsort happy.
  65. */
  66. static int
  67. rdata_compare_wrapper(const void *rdata1, const void *rdata2) {
  68. return (dns_rdata_compare((const dns_rdata_t *)rdata1,
  69. (const dns_rdata_t *)rdata2));
  70. }
  71. /*
  72. * Sort the rdataset into an array.
  73. */
  74. static isc_result_t
  75. rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
  76. dns_rdata_t **rdata, int *nrdata)
  77. {
  78. isc_result_t ret;
  79. int i = 0, n;
  80. dns_rdata_t *data;
  81. dns_rdataset_t rdataset;
  82. n = dns_rdataset_count(set);
  83. data = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
  84. if (data == NULL)
  85. return (ISC_R_NOMEMORY);
  86. dns_rdataset_init(&rdataset);
  87. dns_rdataset_clone(set, &rdataset);
  88. ret = dns_rdataset_first(&rdataset);
  89. if (ret != ISC_R_SUCCESS) {
  90. dns_rdataset_disassociate(&rdataset);
  91. isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
  92. return (ret);
  93. }
  94. /*
  95. * Put them in the array.
  96. */
  97. do {
  98. dns_rdata_init(&data[i]);
  99. dns_rdataset_current(&rdataset, &data[i++]);
  100. } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS);
  101. /*
  102. * Sort the array.
  103. */
  104. qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
  105. *rdata = data;
  106. *nrdata = n;
  107. dns_rdataset_disassociate(&rdataset);
  108. return (ISC_R_SUCCESS);
  109. }
  110. isc_result_t
  111. dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
  112. dst_key_t **key)
  113. {
  114. isc_buffer_t b;
  115. isc_region_t r;
  116. INSIST(name != NULL);
  117. INSIST(rdata != NULL);
  118. INSIST(mctx != NULL);
  119. INSIST(key != NULL);
  120. INSIST(*key == NULL);
  121. REQUIRE(rdata->type == dns_rdatatype_key ||
  122. rdata->type == dns_rdatatype_dnskey);
  123. dns_rdata_toregion(rdata, &r);
  124. isc_buffer_init(&b, r.base, r.length);
  125. isc_buffer_add(&b, r.length);
  126. return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key));
  127. }
  128. static isc_result_t
  129. digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) {
  130. isc_region_t r;
  131. isc_result_t ret;
  132. dns_fixedname_t fname;
  133. dns_rdata_toregion(sigrdata, &r);
  134. INSIST(r.length >= 19);
  135. r.length = 18;
  136. ret = dst_context_adddata(ctx, &r);
  137. if (ret != ISC_R_SUCCESS)
  138. return (ret);
  139. dns_fixedname_init(&fname);
  140. RUNTIME_CHECK(dns_name_downcase(&sig->signer,
  141. dns_fixedname_name(&fname), NULL)
  142. == ISC_R_SUCCESS);
  143. dns_name_toregion(dns_fixedname_name(&fname), &r);
  144. return (dst_context_adddata(ctx, &r));
  145. }
  146. isc_result_t
  147. dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
  148. isc_stdtime_t *inception, isc_stdtime_t *expire,
  149. isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata)
  150. {
  151. dns_rdata_rrsig_t sig;
  152. dns_rdata_t tmpsigrdata;
  153. dns_rdata_t *rdatas;
  154. int nrdatas, i;
  155. isc_buffer_t sigbuf, envbuf;
  156. isc_region_t r;
  157. dst_context_t *ctx = NULL;
  158. isc_result_t ret;
  159. isc_buffer_t *databuf = NULL;
  160. char data[256 + 8];
  161. isc_uint32_t flags;
  162. unsigned int sigsize;
  163. dns_fixedname_t fnewname;
  164. REQUIRE(name != NULL);
  165. REQUIRE(dns_name_countlabels(name) <= 255);
  166. REQUIRE(set != NULL);
  167. REQUIRE(key != NULL);
  168. REQUIRE(inception != NULL);
  169. REQUIRE(expire != NULL);
  170. REQUIRE(mctx != NULL);
  171. REQUIRE(sigrdata != NULL);
  172. if (*inception >= *expire)
  173. return (DNS_R_INVALIDTIME);
  174. /*
  175. * Is the key allowed to sign data?
  176. */
  177. flags = dst_key_flags(key);
  178. if (flags & DNS_KEYTYPE_NOAUTH)
  179. return (DNS_R_KEYUNAUTHORIZED);
  180. if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
  181. return (DNS_R_KEYUNAUTHORIZED);
  182. sig.mctx = mctx;
  183. sig.common.rdclass = set->rdclass;
  184. sig.common.rdtype = dns_rdatatype_rrsig;
  185. ISC_LINK_INIT(&sig.common, link);
  186. dns_name_init(&sig.signer, NULL);
  187. dns_name_clone(dst_key_name(key), &sig.signer);
  188. sig.covered = set->type;
  189. sig.algorithm = dst_key_alg(key);
  190. sig.labels = dns_name_countlabels(name) - 1;
  191. if (dns_name_iswildcard(name))
  192. sig.labels--;
  193. sig.originalttl = set->ttl;
  194. sig.timesigned = *inception;
  195. sig.timeexpire = *expire;
  196. sig.keyid = dst_key_id(key);
  197. ret = dst_key_sigsize(key, &sigsize);
  198. if (ret != ISC_R_SUCCESS)
  199. return (ret);
  200. sig.siglen = sigsize;
  201. /*
  202. * The actual contents of sig.signature are not important yet, since
  203. * they're not used in digest_sig().
  204. */
  205. sig.signature = isc_mem_get(mctx, sig.siglen);
  206. if (sig.signature == NULL)
  207. return (ISC_R_NOMEMORY);
  208. ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
  209. if (ret != ISC_R_SUCCESS)
  210. goto cleanup_signature;
  211. dns_rdata_init(&tmpsigrdata);
  212. ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
  213. sig.common.rdtype, &sig, databuf);
  214. if (ret != ISC_R_SUCCESS)
  215. goto cleanup_databuf;
  216. ret = dst_context_create(key, mctx, &ctx);
  217. if (ret != ISC_R_SUCCESS)
  218. goto cleanup_databuf;
  219. /*
  220. * Digest the SIG rdata.
  221. */
  222. ret = digest_sig(ctx, &tmpsigrdata, &sig);
  223. if (ret != ISC_R_SUCCESS)
  224. goto cleanup_context;
  225. dns_fixedname_init(&fnewname);
  226. RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
  227. NULL) == ISC_R_SUCCESS);
  228. dns_name_toregion(dns_fixedname_name(&fnewname), &r);
  229. /*
  230. * Create an envelope for each rdata: <name|type|class|ttl>.
  231. */
  232. isc_buffer_init(&envbuf, data, sizeof(data));
  233. memcpy(data, r.base, r.length);
  234. isc_buffer_add(&envbuf, r.length);
  235. isc_buffer_putuint16(&envbuf, set->type);
  236. isc_buffer_putuint16(&envbuf, set->rdclass);
  237. isc_buffer_putuint32(&envbuf, set->ttl);
  238. ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
  239. if (ret != ISC_R_SUCCESS)
  240. goto cleanup_context;
  241. isc_buffer_usedregion(&envbuf, &r);
  242. for (i = 0; i < nrdatas; i++) {
  243. isc_uint16_t len;
  244. isc_buffer_t lenbuf;
  245. isc_region_t lenr;
  246. /*
  247. * Skip duplicates.
  248. */
  249. if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
  250. continue;
  251. /*
  252. * Digest the envelope.
  253. */
  254. ret = dst_context_adddata(ctx, &r);
  255. if (ret != ISC_R_SUCCESS)
  256. goto cleanup_array;
  257. /*
  258. * Digest the length of the rdata.
  259. */
  260. isc_buffer_init(&lenbuf, &len, sizeof(len));
  261. INSIST(rdatas[i].length < 65536);
  262. isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
  263. isc_buffer_usedregion(&lenbuf, &lenr);
  264. ret = dst_context_adddata(ctx, &lenr);
  265. if (ret != ISC_R_SUCCESS)
  266. goto cleanup_array;
  267. /*
  268. * Digest the rdata.
  269. */
  270. ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
  271. if (ret != ISC_R_SUCCESS)
  272. goto cleanup_array;
  273. }
  274. isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
  275. ret = dst_context_sign(ctx, &sigbuf);
  276. if (ret != ISC_R_SUCCESS)
  277. goto cleanup_array;
  278. isc_buffer_usedregion(&sigbuf, &r);
  279. if (r.length != sig.siglen) {
  280. ret = ISC_R_NOSPACE;
  281. goto cleanup_array;
  282. }
  283. memcpy(sig.signature, r.base, sig.siglen);
  284. ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
  285. sig.common.rdtype, &sig, buffer);
  286. cleanup_array:
  287. isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
  288. cleanup_context:
  289. dst_context_destroy(&ctx);
  290. cleanup_databuf:
  291. isc_buffer_free(&databuf);
  292. cleanup_signature:
  293. isc_mem_put(mctx, sig.signature, sig.siglen);
  294. return (ret);
  295. }
  296. isc_result_t
  297. dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
  298. isc_boolean_t ignoretime, isc_mem_t *mctx,
  299. dns_rdata_t *sigrdata, dns_name_t *wild)
  300. {
  301. dns_rdata_rrsig_t sig;
  302. dns_fixedname_t fnewname;
  303. isc_region_t r;
  304. isc_buffer_t envbuf;
  305. dns_rdata_t *rdatas;
  306. int nrdatas, i;
  307. isc_stdtime_t now;
  308. isc_result_t ret;
  309. unsigned char data[300];
  310. dst_context_t *ctx = NULL;
  311. int labels = 0;
  312. isc_uint32_t flags;
  313. REQUIRE(name != NULL);
  314. REQUIRE(set != NULL);
  315. REQUIRE(key != NULL);
  316. REQUIRE(mctx != NULL);
  317. REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig);
  318. ret = dns_rdata_tostruct(sigrdata, &sig, NULL);
  319. if (ret != ISC_R_SUCCESS)
  320. return (ret);
  321. if (set->type != sig.covered)
  322. return (DNS_R_SIGINVALID);
  323. if (isc_serial_lt(sig.timeexpire, sig.timesigned))
  324. return (DNS_R_SIGINVALID);
  325. if (!ignoretime) {
  326. isc_stdtime_get(&now);
  327. /*
  328. * Is SIG temporally valid?
  329. */
  330. if (isc_serial_lt((isc_uint32_t)now, sig.timesigned))
  331. return (DNS_R_SIGFUTURE);
  332. else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now))
  333. return (DNS_R_SIGEXPIRED);
  334. }
  335. /*
  336. * NS, SOA and DNSSKEY records are signed by their owner.
  337. * DS records are signed by the parent.
  338. */
  339. switch (set->type) {
  340. case dns_rdatatype_ns:
  341. case dns_rdatatype_soa:
  342. case dns_rdatatype_dnskey:
  343. if (!dns_name_equal(name, &sig.signer))
  344. return (DNS_R_SIGINVALID);
  345. break;
  346. case dns_rdatatype_ds:
  347. if (dns_name_equal(name, &sig.signer))
  348. return (DNS_R_SIGINVALID);
  349. /* FALLTHROUGH */
  350. default:
  351. if (!dns_name_issubdomain(name, &sig.signer))
  352. return (DNS_R_SIGINVALID);
  353. break;
  354. }
  355. /*
  356. * Is the key allowed to sign data?
  357. */
  358. flags = dst_key_flags(key);
  359. if (flags & DNS_KEYTYPE_NOAUTH)
  360. return (DNS_R_KEYUNAUTHORIZED);
  361. if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
  362. return (DNS_R_KEYUNAUTHORIZED);
  363. ret = dst_context_create(key, mctx, &ctx);
  364. if (ret != ISC_R_SUCCESS)
  365. goto cleanup_struct;
  366. /*
  367. * Digest the SIG rdata (not including the signature).
  368. */
  369. ret = digest_sig(ctx, sigrdata, &sig);
  370. if (ret != ISC_R_SUCCESS)
  371. goto cleanup_context;
  372. /*
  373. * If the name is an expanded wildcard, use the wildcard name.
  374. */
  375. dns_fixedname_init(&fnewname);
  376. labels = dns_name_countlabels(name) - 1;
  377. RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
  378. NULL) == ISC_R_SUCCESS);
  379. if (labels - sig.labels > 0)
  380. dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1,
  381. NULL, dns_fixedname_name(&fnewname));
  382. dns_name_toregion(dns_fixedname_name(&fnewname), &r);
  383. /*
  384. * Create an envelope for each rdata: <name|type|class|ttl>.
  385. */
  386. isc_buffer_init(&envbuf, data, sizeof(data));
  387. if (labels - sig.labels > 0) {
  388. isc_buffer_putuint8(&envbuf, 1);
  389. isc_buffer_putuint8(&envbuf, '*');
  390. memcpy(data + 2, r.base, r.length);
  391. }
  392. else
  393. memcpy(data, r.base, r.length);
  394. isc_buffer_add(&envbuf, r.length);
  395. isc_buffer_putuint16(&envbuf, set->type);
  396. isc_buffer_putuint16(&envbuf, set->rdclass);
  397. isc_buffer_putuint32(&envbuf, sig.originalttl);
  398. ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
  399. if (ret != ISC_R_SUCCESS)
  400. goto cleanup_context;
  401. isc_buffer_usedregion(&envbuf, &r);
  402. for (i = 0; i < nrdatas; i++) {
  403. isc_uint16_t len;
  404. isc_buffer_t lenbuf;
  405. isc_region_t lenr;
  406. /*
  407. * Skip duplicates.
  408. */
  409. if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
  410. continue;
  411. /*
  412. * Digest the envelope.
  413. */
  414. ret = dst_context_adddata(ctx, &r);
  415. if (ret != ISC_R_SUCCESS)
  416. goto cleanup_array;
  417. /*
  418. * Digest the rdata length.
  419. */
  420. isc_buffer_init(&lenbuf, &len, sizeof(len));
  421. INSIST(rdatas[i].length < 65536);
  422. isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
  423. isc_buffer_usedregion(&lenbuf, &lenr);
  424. /*
  425. * Digest the rdata.
  426. */
  427. ret = dst_context_adddata(ctx, &lenr);
  428. if (ret != ISC_R_SUCCESS)
  429. goto cleanup_array;
  430. ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
  431. if (ret != ISC_R_SUCCESS)
  432. goto cleanup_array;
  433. }
  434. r.base = sig.signature;
  435. r.length = sig.siglen;
  436. ret = dst_context_verify(ctx, &r);
  437. if (ret == DST_R_VERIFYFAILURE)
  438. ret = DNS_R_SIGINVALID;
  439. cleanup_array:
  440. isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
  441. cleanup_context:
  442. dst_context_destroy(&ctx);
  443. cleanup_struct:
  444. dns_rdata_freestruct(&sig);
  445. if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
  446. if (wild != NULL)
  447. RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
  448. dns_fixedname_name(&fnewname),
  449. wild, NULL) == ISC_R_SUCCESS);
  450. ret = DNS_R_FROMWILDCARD;
  451. }
  452. return (ret);
  453. }
  454. isc_result_t
  455. dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
  456. isc_boolean_t ignoretime, isc_mem_t *mctx,
  457. dns_rdata_t *sigrdata)
  458. {
  459. isc_result_t result;
  460. result = dns_dnssec_verify2(name, set, key, ignoretime, mctx,
  461. sigrdata, NULL);
  462. if (result == DNS_R_FROMWILDCARD)
  463. result = ISC_R_SUCCESS;
  464. return (result);
  465. }
  466. static isc_boolean_t
  467. key_active(dst_key_t *key, isc_stdtime_t now) {
  468. isc_result_t result;
  469. isc_stdtime_t publish, active, revoke, inactive, delete;
  470. isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
  471. isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
  472. isc_boolean_t delset = ISC_FALSE;
  473. int major, minor;
  474. /* Is this an old-style key? */
  475. result = dst_key_getprivateformat(key, &major, &minor);
  476. RUNTIME_CHECK(result == ISC_R_SUCCESS);
  477. /*
  478. * Smart signing started with key format 1.3; prior to that, all
  479. * keys are assumed active
  480. */
  481. if (major == 1 && minor <= 2)
  482. return (ISC_TRUE);
  483. result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish);
  484. if (result == ISC_R_SUCCESS)
  485. pubset = ISC_TRUE;
  486. result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active);
  487. if (result == ISC_R_SUCCESS)
  488. actset = ISC_TRUE;
  489. result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke);
  490. if (result == ISC_R_SUCCESS)
  491. revset = ISC_TRUE;
  492. result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive);
  493. if (result == ISC_R_SUCCESS)
  494. inactset = ISC_TRUE;
  495. result = dst_key_gettime(key, DST_TIME_DELETE, &delete);
  496. if (result == ISC_R_SUCCESS)
  497. delset = ISC_TRUE;
  498. if ((inactset && inactive <= now) || (delset && delete <= now))
  499. return (ISC_FALSE);
  500. if (revset && revoke <= now && pubset && publish <= now)
  501. return (ISC_TRUE);
  502. if (actset && active <= now)
  503. return (ISC_TRUE);
  504. return (ISC_FALSE);
  505. }
  506. #define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
  507. == DNS_KEYOWNER_ZONE)
  508. isc_result_t
  509. dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
  510. dns_dbnode_t *node, dns_name_t *name,
  511. const char *directory, isc_mem_t *mctx,
  512. unsigned int maxkeys, dst_key_t **keys,
  513. unsigned int *nkeys)
  514. {
  515. dns_rdataset_t rdataset;
  516. dns_rdata_t rdata = DNS_RDATA_INIT;
  517. isc_result_t result;
  518. dst_key_t *pubkey = NULL;
  519. unsigned int count = 0;
  520. isc_stdtime_t now;
  521. REQUIRE(nkeys != NULL);
  522. REQUIRE(keys != NULL);
  523. isc_stdtime_get(&now);
  524. *nkeys = 0;
  525. dns_rdataset_init(&rdataset);
  526. RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
  527. &rdataset, NULL));
  528. RETERR(dns_rdataset_first(&rdataset));
  529. while (result == ISC_R_SUCCESS && count < maxkeys) {
  530. pubkey = NULL;
  531. dns_rdataset_current(&rdataset, &rdata);
  532. RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
  533. if (!is_zone_key(pubkey) ||
  534. (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
  535. goto next;
  536. /* Corrupted .key file? */
  537. if (!dns_name_equal(name, dst_key_name(pubkey)))
  538. goto next;
  539. keys[count] = NULL;
  540. result = dst_key_fromfile(dst_key_name(pubkey),
  541. dst_key_id(pubkey),
  542. dst_key_alg(pubkey),
  543. DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
  544. directory,
  545. mctx, &keys[count]);
  546. /*
  547. * If the key was revoked and the private file
  548. * doesn't exist, maybe it was revoked internally
  549. * by named. Try loading the unrevoked version.
  550. */
  551. if (result == ISC_R_FILENOTFOUND) {
  552. isc_uint32_t flags;
  553. flags = dst_key_flags(pubkey);
  554. if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
  555. dst_key_setflags(pubkey,
  556. flags & ~DNS_KEYFLAG_REVOKE);
  557. result = dst_key_fromfile(dst_key_name(pubkey),
  558. dst_key_id(pubkey),
  559. dst_key_alg(pubkey),
  560. DST_TYPE_PUBLIC|
  561. DST_TYPE_PRIVATE,
  562. directory,
  563. mctx, &keys[count]);
  564. if (result == ISC_R_SUCCESS &&
  565. dst_key_pubcompare(pubkey, keys[count],
  566. ISC_FALSE)) {
  567. dst_key_setflags(keys[count], flags);
  568. }
  569. dst_key_setflags(pubkey, flags);
  570. }
  571. }
  572. if (result != ISC_R_SUCCESS) {
  573. char keybuf[DNS_NAME_FORMATSIZE];
  574. char algbuf[DNS_SECALG_FORMATSIZE];
  575. dns_name_format(dst_key_name(pubkey), keybuf,
  576. sizeof(keybuf));
  577. dns_secalg_format(dst_key_alg(pubkey), algbuf,
  578. sizeof(algbuf));
  579. isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
  580. DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
  581. "dns_dnssec_findzonekeys2: error "
  582. "reading private key file %s/%s/%d: %s",
  583. keybuf, algbuf, dst_key_id(pubkey),
  584. isc_result_totext(result));
  585. }
  586. if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
  587. keys[count] = pubkey;
  588. pubkey = NULL;
  589. count++;
  590. goto next;
  591. }
  592. if (result != ISC_R_SUCCESS)
  593. goto failure;
  594. /*
  595. * If a key is marked inactive, skip it
  596. */
  597. if (!key_active(keys[count], now)) {
  598. dst_key_free(&keys[count]);
  599. keys[count] = pubkey;
  600. pubkey = NULL;
  601. count++;
  602. goto next;
  603. }
  604. if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
  605. /* We should never get here. */
  606. dst_key_free(&keys[count]);
  607. goto next;
  608. }
  609. count++;
  610. next:
  611. if (pubkey != NULL)
  612. dst_key_free(&pubkey);
  613. dns_rdata_reset(&rdata);
  614. result = dns_rdataset_next(&rdataset);
  615. }
  616. if (result != ISC_R_NOMORE)
  617. goto failure;
  618. if (count == 0)
  619. result = ISC_R_NOTFOUND;
  620. else
  621. result = ISC_R_SUCCESS;
  622. failure:
  623. if (dns_rdataset_isassociated(&rdataset))
  624. dns_rdataset_disassociate(&rdataset);
  625. if (pubkey != NULL)
  626. dst_key_free(&pubkey);
  627. if (result != ISC_R_SUCCESS)
  628. while (count > 0)
  629. dst_key_free(&keys[--count]);
  630. *nkeys = count;
  631. return (result);
  632. }
  633. isc_result_t
  634. dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver,
  635. dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx,
  636. unsigned int maxkeys, dst_key_t **keys,
  637. unsigned int *nkeys)
  638. {
  639. return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx,
  640. maxkeys, keys, nkeys));
  641. }
  642. isc_result_t
  643. dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
  644. dns_rdata_sig_t sig; /* SIG(0) */
  645. unsigned char data[512];
  646. unsigned char header[DNS_MESSAGE_HEADERLEN];
  647. isc_buffer_t headerbuf, databuf, sigbuf;
  648. unsigned int sigsize;
  649. isc_buffer_t *dynbuf = NULL;
  650. dns_rdata_t *rdata;
  651. dns_rdatalist_t *datalist;
  652. dns_rdataset_t *dataset;
  653. isc_region_t r;
  654. isc_stdtime_t now;
  655. dst_context_t *ctx = NULL;
  656. isc_mem_t *mctx;
  657. isc_result_t result;
  658. isc_boolean_t signeedsfree = ISC_TRUE;
  659. REQUIRE(msg != NULL);
  660. REQUIRE(key != NULL);
  661. if (is_response(msg))
  662. REQUIRE(msg->query.base != NULL);
  663. mctx = msg->mctx;
  664. memset(&sig, 0, sizeof(sig));
  665. sig.mctx = mctx;
  666. sig.common.rdclass = dns_rdataclass_any;
  667. sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */
  668. ISC_LINK_INIT(&sig.common, link);
  669. sig.covered = 0;
  670. sig.algorithm = dst_key_alg(key);
  671. sig.labels = 0; /* the root name */
  672. sig.originalttl = 0;
  673. isc_stdtime_get(&now);
  674. sig.timesigned = now - DNS_TSIG_FUDGE;
  675. sig.timeexpire = now + DNS_TSIG_FUDGE;
  676. sig.keyid = dst_key_id(key);
  677. dns_name_init(&sig.signer, NULL);
  678. dns_name_clone(dst_key_name(key), &sig.signer);
  679. sig.siglen = 0;
  680. sig.signature = NULL;
  681. isc_buffer_init(&databuf, data, sizeof(data));
  682. RETERR(dst_context_create(key, mctx, &ctx));
  683. /*
  684. * Digest the fields of the SIG - we can cheat and use
  685. * dns_rdata_fromstruct. Since siglen is 0, the digested data
  686. * is identical to dns format.
  687. */
  688. RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
  689. dns_rdatatype_sig /* SIG(0) */,
  690. &sig, &databuf));
  691. isc_buffer_usedregion(&databuf, &r);
  692. RETERR(dst_context_adddata(ctx, &r));
  693. /*
  694. * If this is a response, digest the query.
  695. */
  696. if (is_response(msg))
  697. RETERR(dst_context_adddata(ctx, &msg->query));
  698. /*
  699. * Digest the header.
  700. */
  701. isc_buffer_init(&headerbuf, header, sizeof(header));
  702. dns_message_renderheader(msg, &headerbuf);
  703. isc_buffer_usedregion(&headerbuf, &r);
  704. RETERR(dst_context_adddata(ctx, &r));
  705. /*
  706. * Digest the remainder of the message.
  707. */
  708. isc_buffer_usedregion(msg->buffer, &r);
  709. isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
  710. RETERR(dst_context_adddata(ctx, &r));
  711. RETERR(dst_key_sigsize(key, &sigsize));
  712. sig.siglen = sigsize;
  713. sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen);
  714. if (sig.signature == NULL) {
  715. result = ISC_R_NOMEMORY;
  716. goto failure;
  717. }
  718. isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
  719. RETERR(dst_context_sign(ctx, &sigbuf));
  720. dst_context_destroy(&ctx);
  721. rdata = NULL;
  722. RETERR(dns_message_gettemprdata(msg, &rdata));
  723. RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
  724. RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
  725. dns_rdatatype_sig /* SIG(0) */,
  726. &sig, dynbuf));
  727. isc_mem_put(mctx, sig.signature, sig.siglen);
  728. signeedsfree = ISC_FALSE;
  729. dns_message_takebuffer(msg, &dynbuf);
  730. datalist = NULL;
  731. RETERR(dns_message_gettemprdatalist(msg, &datalist));
  732. datalist->rdclass = dns_rdataclass_any;
  733. datalist->type = dns_rdatatype_sig; /* SIG(0) */
  734. datalist->covers = 0;
  735. datalist->ttl = 0;
  736. ISC_LIST_INIT(datalist->rdata);
  737. ISC_LIST_APPEND(datalist->rdata, rdata, link);
  738. dataset = NULL;
  739. RETERR(dns_message_gettemprdataset(msg, &dataset));
  740. dns_rdataset_init(dataset);
  741. RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS);
  742. msg->sig0 = dataset;
  743. return (ISC_R_SUCCESS);
  744. failure:
  745. if (dynbuf != NULL)
  746. isc_buffer_free(&dynbuf);
  747. if (signeedsfree)
  748. isc_mem_put(mctx, sig.signature, sig.siglen);
  749. if (ctx != NULL)
  750. dst_context_destroy(&ctx);
  751. return (result);
  752. }
  753. isc_result_t
  754. dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
  755. dst_key_t *key)
  756. {
  757. dns_rdata_sig_t sig; /* SIG(0) */
  758. unsigned char header[DNS_MESSAGE_HEADERLEN];
  759. dns_rdata_t rdata = DNS_RDATA_INIT;
  760. isc_region_t r, source_r, sig_r, header_r;
  761. isc_stdtime_t now;
  762. dst_context_t *ctx = NULL;
  763. isc_mem_t *mctx;
  764. isc_result_t result;
  765. isc_uint16_t addcount;
  766. isc_boolean_t signeedsfree = ISC_FALSE;
  767. REQUIRE(source != NULL);
  768. REQUIRE(msg != NULL);
  769. REQUIRE(key != NULL);
  770. mctx = msg->mctx;
  771. msg->verify_attempted = 1;
  772. if (is_response(msg)) {
  773. if (msg->query.base == NULL)
  774. return (DNS_R_UNEXPECTEDTSIG);
  775. }
  776. isc_buffer_usedregion(source, &source_r);
  777. RETERR(dns_rdataset_first(msg->sig0));
  778. dns_rdataset_current(msg->sig0, &rdata);
  779. RETERR(dns_rdata_tostruct(&rdata, &sig, NULL));
  780. signeedsfree = ISC_TRUE;
  781. if (sig.labels != 0) {
  782. result = DNS_R_SIGINVALID;
  783. goto failure;
  784. }
  785. if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
  786. result = DNS_R_SIGINVALID;
  787. msg->sig0status = dns_tsigerror_badtime;
  788. goto failure;
  789. }
  790. isc_stdtime_get(&now);
  791. if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) {
  792. result = DNS_R_SIGFUTURE;
  793. msg->sig0status = dns_tsigerror_badtime;
  794. goto failure;
  795. }
  796. else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) {
  797. result = DNS_R_SIGEXPIRED;
  798. msg->sig0status = dns_tsigerror_badtime;
  799. goto failure;
  800. }
  801. if (!dns_name_equal(dst_key_name(key), &sig.signer)) {
  802. result = DNS_R_SIGINVALID;
  803. msg->sig0status = dns_tsigerror_badkey;
  804. goto failure;
  805. }
  806. RETERR(dst_context_create(key, mctx, &ctx));
  807. /*
  808. * Digest the SIG(0) record, except for the signature.
  809. */
  810. dns_rdata_toregion(&rdata, &r);
  811. r.length -= sig.siglen;
  812. RETERR(dst_context_adddata(ctx, &r));
  813. /*
  814. * If this is a response, digest the query.
  815. */
  816. if (is_response(msg))
  817. RETERR(dst_context_adddata(ctx, &msg->query));
  818. /*
  819. * Extract the header.
  820. */
  821. memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN);
  822. /*
  823. * Decrement the additional field counter.
  824. */
  825. memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
  826. addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
  827. memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
  828. /*
  829. * Digest the modified header.
  830. */
  831. header_r.base = (unsigned char *) header;
  832. header_r.length = DNS_MESSAGE_HEADERLEN;
  833. RETERR(dst_context_adddata(ctx, &header_r));
  834. /*
  835. * Digest all non-SIG(0) records.
  836. */
  837. r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
  838. r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
  839. RETERR(dst_context_adddata(ctx, &r));
  840. sig_r.base = sig.signature;
  841. sig_r.length = sig.siglen;
  842. result = dst_context_verify(ctx, &sig_r);
  843. if (result != ISC_R_SUCCESS) {
  844. msg->sig0status = dns_tsigerror_badsig;
  845. goto failure;
  846. }
  847. msg->verified_sig = 1;
  848. dst_context_destroy(&ctx);
  849. dns_rdata_freestruct(&sig);
  850. return (ISC_R_SUCCESS);
  851. failure:
  852. if (signeedsfree)
  853. dns_rdata_freestruct(&sig);
  854. if (ctx != NULL)
  855. dst_context_destroy(&ctx);
  856. return (result);
  857. }
  858. /*%
  859. * Does this key ('rdata') self sign the rrset ('rdataset')?
  860. */
  861. isc_boolean_t
  862. dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
  863. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
  864. isc_boolean_t ignoretime, isc_mem_t *mctx)
  865. {
  866. INSIST(rdataset->type == dns_rdatatype_key ||
  867. rdataset->type == dns_rdatatype_dnskey);
  868. if (rdataset->type == dns_rdatatype_key) {
  869. INSIST(sigrdataset->type == dns_rdatatype_sig);
  870. INSIST(sigrdataset->covers == dns_rdatatype_key);
  871. } else {
  872. INSIST(sigrdataset->type == dns_rdatatype_rrsig);
  873. INSIST(sigrdataset->covers == dns_rdatatype_dnskey);
  874. }
  875. return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset,
  876. ignoretime, mctx));
  877. }
  878. isc_boolean_t
  879. dns_dnssec_signs(dns_rdata_t *rdata, dns_name_t *name,
  880. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
  881. isc_boolean_t ignoretime, isc_mem_t *mctx)
  882. {
  883. dst_key_t *dstkey = NULL;
  884. dns_keytag_t keytag;
  885. dns_rdata_dnskey_t key;
  886. dns_rdata_rrsig_t sig;
  887. dns_rdata_t sigrdata = DNS_RDATA_INIT;
  888. isc_result_t result;
  889. INSIST(sigrdataset->type == dns_rdatatype_rrsig);
  890. if (sigrdataset->covers != rdataset->type)
  891. return (ISC_FALSE);
  892. result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey);
  893. if (result != ISC_R_SUCCESS)
  894. return (ISC_FALSE);
  895. result = dns_rdata_tostruct(rdata, &key, NULL);
  896. RUNTIME_CHECK(result == ISC_R_SUCCESS);
  897. keytag = dst_key_id(dstkey);
  898. for (result = dns_rdataset_first(sigrdataset);
  899. result == ISC_R_SUCCESS;
  900. result = dns_rdataset_next(sigrdataset))
  901. {
  902. dns_rdata_reset(&sigrdata);
  903. dns_rdataset_current(sigrdataset, &sigrdata);
  904. result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
  905. RUNTIME_CHECK(result == ISC_R_SUCCESS);
  906. if (sig.algorithm == key.algorithm &&
  907. sig.keyid == keytag) {
  908. result = dns_dnssec_verify2(name, rdataset, dstkey,
  909. ignoretime, mctx,
  910. &sigrdata, NULL);
  911. if (result == ISC_R_SUCCESS) {
  912. dst_key_free(&dstkey);
  913. return (ISC_TRUE);
  914. }
  915. }
  916. }
  917. dst_key_free(&dstkey);
  918. return (ISC_FALSE);
  919. }
  920. isc_result_t
  921. dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
  922. dns_dnsseckey_t **dkp)
  923. {
  924. isc_result_t result;
  925. dns_dnsseckey_t *dk;
  926. int major, minor;
  927. REQUIRE(dkp != NULL && *dkp == NULL);
  928. dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
  929. if (dk == NULL)
  930. return (ISC_R_NOMEMORY);
  931. dk->key = *dstkey;
  932. *dstkey = NULL;
  933. dk->force_publish = ISC_FALSE;
  934. dk->force_sign = ISC_FALSE;
  935. dk->hint_publish = ISC_FALSE;
  936. dk->hint_sign = ISC_FALSE;
  937. dk->hint_remove = ISC_FALSE;
  938. dk->first_sign = ISC_FALSE;
  939. dk->is_active = ISC_FALSE;
  940. dk->prepublish = 0;
  941. dk->source = dns_keysource_unknown;
  942. dk->index = 0;
  943. /* KSK or ZSK? */
  944. dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
  945. /* Is this an old-style key? */
  946. result = dst_key_getprivateformat(dk->key, &major, &minor);
  947. INSIST(result == ISC_R_SUCCESS);
  948. /* Smart signing started with key format 1.3 */
  949. dk->legacy = ISC_TF(major == 1 && minor <= 2);
  950. ISC_LINK_INIT(dk, link);
  951. *dkp = dk;
  952. return (ISC_R_SUCCESS);
  953. }
  954. void
  955. dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
  956. dns_dnsseckey_t *dk;
  957. REQUIRE(dkp != NULL && *dkp != NULL);
  958. dk = *dkp;
  959. if (dk->key != NULL)
  960. dst_key_free(&dk->key);
  961. isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
  962. *dkp = NULL;
  963. }
  964. static void
  965. get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) {
  966. isc_result_t result;
  967. isc_stdtime_t publish, active, revoke, inactive, delete;
  968. isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
  969. isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
  970. isc_boolean_t delset = ISC_FALSE;
  971. REQUIRE(key != NULL && key->key != NULL);
  972. result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish);
  973. if (result == ISC_R_SUCCESS)
  974. pubset = ISC_TRUE;
  975. result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
  976. if (result == ISC_R_SUCCESS)
  977. actset = ISC_TRUE;
  978. result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke);
  979. if (result == ISC_R_SUCCESS)
  980. revset = ISC_TRUE;
  981. result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive);
  982. if (result == ISC_R_SUCCESS)
  983. inactset = ISC_TRUE;
  984. result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete);
  985. if (result == ISC_R_SUCCESS)
  986. delset = ISC_TRUE;
  987. /* Metadata says publish (but possibly not activate) */
  988. if (pubset && publish <= now)
  989. key->hint_publish = ISC_TRUE;
  990. /* Metadata says activate (so we must also publish) */
  991. if (actset && active <= now) {
  992. key->hint_sign = ISC_TRUE;
  993. key->hint_publish = ISC_TRUE;
  994. }
  995. /*
  996. * Activation date is set (maybe in the future), but
  997. * publication date isn't. Most likely the user wants to
  998. * publish now and activate later.
  999. */
  1000. if (actset && !pubset)
  1001. key->hint_publish = ISC_TRUE;
  1002. /*
  1003. * If activation date is in the future, make note of how far off
  1004. */
  1005. if (key->hint_publish && actset && active > now) {
  1006. key->prepublish = active - now;
  1007. }
  1008. /*
  1009. * Key has been marked inactive: we can continue publishing,
  1010. * but don't sign.
  1011. */
  1012. if (key->hint_publish && inactset && inactive <= now) {
  1013. key->hint_sign = ISC_FALSE;
  1014. }
  1015. /*
  1016. * Metadata says revoke. If the key is published,
  1017. * we *have to* sign with it per RFC5011--even if it was
  1018. * not active before.
  1019. *
  1020. * If it hasn't already been done, we should also revoke it now.
  1021. */
  1022. if (key->hint_publish && (revset && revoke <= now)) {
  1023. isc_uint32_t flags;
  1024. key->hint_sign = ISC_TRUE;
  1025. flags = dst_key_flags(key->key);
  1026. if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
  1027. flags |= DNS_KEYFLAG_REVOKE;
  1028. dst_key_setflags(key->key, flags);
  1029. }
  1030. }
  1031. /*
  1032. * Metadata says delete, so don't publish this key or sign with it.
  1033. */
  1034. if (delset && delete <= now) {
  1035. key->hint_publish = ISC_FALSE;
  1036. key->hint_sign = ISC_FALSE;
  1037. key->hint_remove = ISC_TRUE;
  1038. }
  1039. }
  1040. /*%
  1041. * Get a list of DNSSEC keys from the key repository
  1042. */
  1043. isc_result_t
  1044. dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
  1045. isc_mem_t *mctx, dns_dnsseckeylist_t *keylist)
  1046. {
  1047. isc_result_t result = ISC_R_SUCCESS;
  1048. isc_boolean_t dir_open = ISC_FALSE;
  1049. dns_dnsseckeylist_t list;
  1050. isc_dir_t dir;
  1051. dns_dnsseckey_t *key = NULL;
  1052. dst_key_t *dstkey = NULL;
  1053. char namebuf[DNS_NAME_FORMATSIZE], *p;
  1054. isc_buffer_t b;
  1055. unsigned int len;
  1056. isc_stdtime_t now;
  1057. REQUIRE(keylist != NULL);
  1058. ISC_LIST_INIT(list);
  1059. isc_dir_init(&dir);
  1060. isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
  1061. RETERR(dns_name_tofilenametext(origin, ISC_FALSE, &b));
  1062. len = isc_buffer_usedlength(&b);
  1063. namebuf[len] = '\0';
  1064. if (directory == NULL)
  1065. directory = ".";
  1066. RETERR(isc_dir_open(&dir, directory));
  1067. dir_open = ISC_TRUE;
  1068. isc_stdtime_get(&now);
  1069. while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
  1070. if (dir.entry.name[0] == 'K' &&
  1071. dir.entry.length > len + 1 &&
  1072. dir.entry.name[len + 1] == '+' &&
  1073. strncasecmp(dir.entry.name + 1, namebuf, len) == 0) {
  1074. p = strrchr(dir.entry.name, '.');
  1075. if (p != NULL && strcmp(p, ".private") != 0)
  1076. continue;
  1077. dstkey = NULL;
  1078. result = dst_key_fromnamedfile(dir.entry.name,
  1079. directory,
  1080. DST_TYPE_PUBLIC |
  1081. DST_TYPE_PRIVATE,
  1082. mctx, &dstkey);
  1083. if (result != ISC_R_SUCCESS) {
  1084. isc_log_write(dns_lctx,
  1085. DNS_LOGCATEGORY_GENERAL,
  1086. DNS_LOGMODULE_DNSSEC,
  1087. ISC_LOG_WARNING,
  1088. "dns_dnssec_findmatchingkeys: "
  1089. "error reading key file %s: %s",
  1090. dir.entry.name,
  1091. isc_result_totext(result));
  1092. continue;
  1093. }
  1094. RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
  1095. key->source = dns_keysource_repository;
  1096. get_hints(key, now);
  1097. if (key->legacy) {
  1098. dns_dnsseckey_destroy(mctx, &key);
  1099. } else {
  1100. ISC_LIST_APPEND(list, key, link);
  1101. key = NULL;
  1102. }
  1103. }
  1104. }
  1105. if (!ISC_LIST_EMPTY(list))
  1106. ISC_LIST_APPENDLIST(*keylist, list, link);
  1107. else
  1108. result = ISC_R_NOTFOUND;
  1109. failure:
  1110. if (dir_open)
  1111. isc_dir_close(&dir);
  1112. INSIST(key == NULL);
  1113. while ((key = ISC_LIST_HEAD(list)) != NULL) {
  1114. ISC_LIST_UNLINK(list, key, link);
  1115. INSIST(key->key != NULL);
  1116. dst_key_free(&key->key);
  1117. dns_dnsseckey_destroy(mctx, &key);
  1118. }
  1119. if (dstkey != NULL)
  1120. dst_key_free(&dstkey);
  1121. return (result);
  1122. }
  1123. /*%
  1124. * Add 'newkey' to 'keylist' if it's not already there.
  1125. *
  1126. * If 'savekeys' is ISC_TRUE, then we need to preserve all
  1127. * the keys in the keyset, regardless of whether they have
  1128. * metadata indicating they should be deactivated or removed.
  1129. */
  1130. static void
  1131. addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
  1132. isc_boolean_t savekeys, isc_mem_t *mctx)
  1133. {
  1134. dns_dnsseckey_t *key;
  1135. /* Skip duplicates */
  1136. for (key = ISC_LIST_HEAD(*keylist);
  1137. key != NULL;
  1138. key = ISC_LIST_NEXT(key, link)) {
  1139. if (dst_key_id(key->key) == dst_key_id(*newkey) &&
  1140. dst_key_alg(key->key) == dst_key_alg(*newkey) &&
  1141. dns_name_equal(dst_key_name(key->key),
  1142. dst_key_name(*newkey)))
  1143. break;
  1144. }
  1145. if (key != NULL) {
  1146. /*
  1147. * Found a match. If the old key was only public and the
  1148. * new key is private, replace the old one; otherwise
  1149. * leave it. But either way, mark the key as having
  1150. * been found in the zone.
  1151. */
  1152. if (dst_key_isprivate(key->key)) {
  1153. dst_key_free(newkey);
  1154. } else if (dst_key_isprivate(*newkey)) {
  1155. dst_key_free(&key->key);
  1156. key->key = *newkey;
  1157. }
  1158. key->source = dns_keysource_zoneapex;
  1159. return;
  1160. }
  1161. dns_dnsseckey_create(mctx, newkey, &key);
  1162. if (key->legacy || savekeys) {
  1163. key->force_publish = ISC_TRUE;
  1164. key->force_sign = dst_key_isprivate(key->key);
  1165. }
  1166. key->source = dns_keysource_zoneapex;
  1167. ISC_LIST_APPEND(*keylist, key, link);
  1168. *newkey = NULL;
  1169. }
  1170. /*%
  1171. * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
  1172. * for future reference.
  1173. */
  1174. static isc_result_t
  1175. mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
  1176. isc_result_t result = ISC_R_SUCCESS;
  1177. dns_rdata_t rdata = DNS_RDATA_INIT;
  1178. dns_rdataset_t sigs;
  1179. dns_dnsseckey_t *key;
  1180. REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
  1181. dns_rdataset_init(&sigs);
  1182. dns_rdataset_clone(rrsigs, &sigs);
  1183. for (key = ISC_LIST_HEAD(*keylist);
  1184. key != NULL;
  1185. key = ISC_LIST_NEXT(key, link)) {
  1186. isc_uint16_t keyid, sigid;
  1187. dns_secalg_t keyalg, sigalg;
  1188. keyid = dst_key_id(key->key);
  1189. keyalg = dst_key_alg(key->key);
  1190. for (result = dns_rdataset_first(&sigs);
  1191. result == ISC_R_SUCCESS;
  1192. result = dns_rdataset_next(&sigs)) {
  1193. dns_rdata_rrsig_t sig;
  1194. dns_rdata_reset(&rdata);
  1195. dns_rdataset_current(&sigs, &rdata);
  1196. result = dns_rdata_tostruct(&rdata, &sig, NULL);
  1197. RUNTIME_CHECK(result == ISC_R_SUCCESS);
  1198. sigalg = sig.algorithm;
  1199. sigid = sig.keyid;
  1200. if (keyid == sigid && keyalg == sigalg) {
  1201. key->is_active = ISC_TRUE;
  1202. break;
  1203. }
  1204. }
  1205. }
  1206. if (result == ISC_R_NOMORE)
  1207. result = ISC_R_SUCCESS;
  1208. if (dns_rdataset_isassociated(&sigs))
  1209. dns_rdataset_disassociate(&sigs);
  1210. return (result);
  1211. }
  1212. /*%
  1213. * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
  1214. */
  1215. isc_result_t
  1216. dns_dnssec_keylistfromrdataset(dns_name_t *origin,
  1217. const char *directory, isc_mem_t *mctx,
  1218. dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
  1219. dns_rdataset_t *soasigs, isc_boolean_t savekeys,
  1220. isc_boolean_t public,
  1221. dns_dnsseckeylist_t *keylist)
  1222. {
  1223. dns_rdataset_t keys;
  1224. dns_rdata_t rdata = DNS_RDATA_INIT;
  1225. dst_key_t *pubkey = NULL, *privkey = NULL;
  1226. isc_result_t result;
  1227. REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
  1228. dns_rdataset_init(&keys);
  1229. dns_rdataset_clone(keyset, &keys);
  1230. for (result = dns_rdataset_first(&keys);
  1231. result == ISC_R_SUCCESS;
  1232. result = dns_rdataset_next(&keys)) {
  1233. dns_rdata_reset(&rdata);
  1234. dns_rdataset_current(&keys, &rdata);
  1235. RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey));
  1236. if (!is_zone_key(pubkey) ||
  1237. (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
  1238. goto skip;
  1239. /* Corrupted .key file? */
  1240. if (!dns_name_equal(origin, dst_key_name(pubkey)))
  1241. goto skip;
  1242. if (public) {
  1243. addkey(keylist, &pubkey, savekeys, mctx);
  1244. goto skip;
  1245. }
  1246. result = dst_key_fromfile(dst_key_name(pubkey),
  1247. dst_key_id(pubkey),
  1248. dst_key_alg(pubkey),
  1249. DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
  1250. directory, mctx, &privkey);
  1251. /*
  1252. * If the key was revoked and the private file
  1253. * doesn't exist, maybe it was revoked internally
  1254. * by named. Try loading the unrevoked version.
  1255. */
  1256. if (result == ISC_R_FILENOTFOUND) {
  1257. isc_uint32_t flags;
  1258. flags = dst_key_flags(pubkey);
  1259. if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
  1260. dst_key_setflags(pubkey,
  1261. flags & ~DNS_KEYFLAG_REVOKE);
  1262. result = dst_key_fromfile(dst_key_name(pubkey),
  1263. dst_key_id(pubkey),
  1264. dst_key_alg(pubkey),
  1265. DST_TYPE_PUBLIC|
  1266. DST_TYPE_PRIVATE,
  1267. directory,
  1268. mctx, &privkey);
  1269. if (result == ISC_R_SUCCESS &&
  1270. dst_key_pubcompare(pubkey, privkey,
  1271. ISC_FALSE)) {
  1272. dst_key_setflags(privkey, flags);
  1273. }
  1274. dst_key_setflags(pubkey, flags);
  1275. }
  1276. }
  1277. if (result != ISC_R_SUCCESS) {
  1278. char keybuf[DNS_NAME_FORMATSIZE];
  1279. char algbuf[DNS_SECALG_FORMATSIZE];
  1280. dns_name_format(dst_key_name(pubkey), keybuf,
  1281. sizeof(keybuf));
  1282. dns_secalg_format(dst_key_alg(pubkey), algbuf,
  1283. sizeof(algbuf));
  1284. isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
  1285. DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
  1286. "dns_dnssec_keylistfromrdataset: error "
  1287. "reading private key file %s/%s/%d: %s",
  1288. keybuf, algbuf, dst_key_id(pubkey),
  1289. isc_result_totext(result));
  1290. }
  1291. if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
  1292. addkey(keylist, &pubkey, savekeys, mctx);
  1293. goto skip;
  1294. }
  1295. RETERR(result);
  1296. /* This should never happen. */
  1297. if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0)
  1298. goto skip;
  1299. addkey(keylist, &privkey, savekeys, mctx);
  1300. skip:
  1301. if (pubkey != NULL)
  1302. dst_key_free(&pubkey);
  1303. if (privkey != NULL)
  1304. dst_key_free(&privkey);
  1305. }
  1306. if (result != ISC_R_NOMORE)
  1307. RETERR(result);
  1308. if (keysigs != NULL && dns_rdataset_isassociated(keysigs))
  1309. RETERR(mark_active_keys(keylist, keysigs));
  1310. if (soasigs != NULL && dns_rdataset_isassociated(soasigs))
  1311. RETERR(mark_active_keys(keylist, soasigs));
  1312. result = ISC_R_SUCCESS;
  1313. failure:
  1314. if (dns_rdataset_isassociated(&keys))
  1315. dns_rdataset_disassociate(&keys);
  1316. if (pubkey != NULL)
  1317. dst_key_free(&pubkey);
  1318. if (privkey != NULL)
  1319. dst_key_free(&privkey);
  1320. return (result);
  1321. }
  1322. static isc_result_t
  1323. make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
  1324. dns_rdata_t *target)
  1325. {
  1326. isc_result_t result;
  1327. isc_buffer_t b;
  1328. isc_region_t r;
  1329. isc_buffer_init(&b, buf, bufsize);
  1330. result = dst_key_todns(key, &b);
  1331. if (result != ISC_R_SUCCESS)
  1332. return (result);
  1333. dns_rdata_reset(target);
  1334. isc_buffer_usedregion(&b, &r);
  1335. dns_rdata_fromregion(target, dst_key_class(key),
  1336. dns_rdatatype_dnskey, &r);
  1337. return (ISC_R_SUCCESS);
  1338. }
  1339. static isc_result_t
  1340. publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
  1341. dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk,
  1342. void (*report)(const char *, ...))
  1343. {
  1344. isc_result_t result;
  1345. dns_difftuple_t *tuple = NULL;
  1346. unsigned char buf[DST_KEY_MAXSIZE];
  1347. dns_rdata_t dnskey = DNS_RDATA_INIT;
  1348. char alg[80];
  1349. dns_rdata_reset(&dnskey);
  1350. RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
  1351. dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
  1352. report("Fetching %s %d/%s from key %s.",
  1353. key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK",
  1354. dst_key_id(key->key), alg,
  1355. key->source == dns_keysource_user ? "file" : "repository");
  1356. if (key->prepublish && ttl > key->prepublish) {
  1357. char keystr[DST_KEY_FORMATSIZE];
  1358. isc_stdtime_t now;
  1359. dst_key_format(key->key, keystr, sizeof(keystr));
  1360. report("Key %s: Delaying activation to match the DNSKEY TTL.\n",
  1361. keystr, ttl);
  1362. isc_stdtime_get(&now);
  1363. dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl);
  1364. }
  1365. /* publish key */
  1366. RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl,
  1367. &dnskey, &tuple));
  1368. dns_diff_appendminimal(diff, &tuple);
  1369. result = ISC_R_SUCCESS;
  1370. failure:
  1371. return (result);
  1372. }
  1373. static isc_result_t
  1374. remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
  1375. dns_ttl_t ttl, isc_mem_t *mctx, const char *reason,
  1376. void (*report)(const char *, ...))
  1377. {
  1378. isc_result_t result;
  1379. dns_difftuple_t *tuple = NULL;
  1380. unsigned char buf[DST_KEY_MAXSIZE];
  1381. dns_rdata_t dnskey = DNS_RDATA_INIT;
  1382. char alg[80];
  1383. dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
  1384. report("Removing %s key %d/%s from DNSKEY RRset.",
  1385. reason, dst_key_id(key->key), alg);
  1386. RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
  1387. RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey,
  1388. &tuple));
  1389. dns_diff_appendminimal(diff, &tuple);
  1390. result = ISC_R_SUCCESS;
  1391. failure:
  1392. return (result);
  1393. }
  1394. /*
  1395. * Update 'keys' with information from 'newkeys'.
  1396. *
  1397. * If 'removed' is not NULL, any keys that are being removed from
  1398. * the zone will be added to the list for post-removal processing.
  1399. */
  1400. isc_result_t
  1401. dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
  1402. dns_dnsseckeylist_t *removed, dns_name_t *origin,
  1403. dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk,
  1404. isc_mem_t *mctx, void (*report)(const char *, ...))
  1405. {
  1406. isc_result_t result;
  1407. dns_dnsseckey_t *key, *key1, *key2, *next;
  1408. /*
  1409. * First, look through the existing key list to find keys
  1410. * supplied from the command line which are not in the zone.
  1411. * Update the zone to include them.
  1412. */
  1413. for (key = ISC_LIST_HEAD(*keys);
  1414. key != NULL;
  1415. key = ISC_LIST_NEXT(key, link)) {
  1416. if (key->source == dns_keysource_user &&
  1417. (key->hint_publish || key->force_publish)) {
  1418. RETERR(publish_key(diff, key, origin, ttl,
  1419. mctx, allzsk, report));
  1420. }
  1421. }
  1422. /*
  1423. * Second, scan the list of newly found keys looking for matches
  1424. * with known keys, and update accordingly.
  1425. */
  1426. for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
  1427. isc_boolean_t key_revoked = ISC_FALSE;
  1428. next = ISC_LIST_NEXT(key1, link);
  1429. for (key2 = ISC_LIST_HEAD(*keys);
  1430. key2 != NULL;
  1431. key2 = ISC_LIST_NEXT(key2, link)) {
  1432. if (dst_key_pubcompare(key1->key, key2->key,
  1433. ISC_TRUE)) {
  1434. int r1, r2;
  1435. r1 = dst_key_flags(key1->key) &
  1436. DNS_KEYFLAG_REVOKE;
  1437. r2 = dst_key_flags(key2->key) &
  1438. DNS_KEYFLAG_REVOKE;
  1439. key_revoked = ISC_TF(r1 != r2);
  1440. break;
  1441. }
  1442. }
  1443. /* No match found in keys; add the new key. */
  1444. if (key2 == NULL) {
  1445. ISC_LIST_UNLINK(*newkeys, key1, link);
  1446. ISC_LIST_APPEND(*keys, key1, link);
  1447. if (key1->source != dns_keysource_zoneapex &&
  1448. (key1->hint_publish || key1->force_publish)) {
  1449. RETERR(publish_key(diff, key1, origin, ttl,
  1450. mctx, allzsk, report));
  1451. if (key1->hint_sign || key1->force_sign)
  1452. key1->first_sign = ISC_TRUE;
  1453. }
  1454. continue;
  1455. }
  1456. /* Match found: remove or update it as needed */
  1457. if (key1->hint_remove) {
  1458. RETERR(remove_key(diff, key2, origin, ttl, mctx,
  1459. "expired", report));
  1460. ISC_LIST_UNLINK(*keys, key2, link);
  1461. if (removed != NULL)
  1462. ISC_LIST_APPEND(*removed, key2, link);
  1463. else
  1464. dns_dnsseckey_destroy(mctx, &key2);
  1465. } else if (key_revoked &&
  1466. (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) {
  1467. /*
  1468. * A previously valid key has been revoked.
  1469. * We need to remove the old version and pull
  1470. * in the new one.
  1471. */
  1472. RETERR(remove_key(diff, key2, origin, ttl, mctx,
  1473. "revoked", report));
  1474. ISC_LIST_UNLINK(*keys, key2, link);
  1475. if (removed != NULL)
  1476. ISC_LIST_APPEND(*removed, key2, link);
  1477. else
  1478. dns_dnsseckey_destroy(mctx, &key2);
  1479. RETERR(publish_key(diff, key1, origin, ttl,
  1480. mctx, allzsk, report));
  1481. ISC_LIST_UNLINK(*newkeys, key1, link);
  1482. ISC_LIST_APPEND(*keys, key1, link);
  1483. /*
  1484. * XXX: The revoke flag is only defined for trust
  1485. * anchors. Setting the flag on a non-KSK is legal,
  1486. * but not defined in any RFC. It seems reasonable
  1487. * to treat it the same as a KSK: keep it in the
  1488. * zone, sign the DNSKEY set with it, but not
  1489. * sign other records with it.
  1490. */
  1491. key1->ksk = ISC_TRUE;
  1492. continue;
  1493. } else {
  1494. if (!key2->is_active &&
  1495. (key1->hint_sign || key1->force_sign))
  1496. key2->first_sign = ISC_TRUE;
  1497. key2->hint_sign = key1->hint_sign;
  1498. key2->hint_publish = key1->hint_publish;
  1499. }
  1500. }
  1501. /* Free any leftover keys in newkeys */
  1502. while (!ISC_LIST_EMPTY(*newkeys)) {
  1503. key1 = ISC_LIST_HEAD(*newkeys);
  1504. ISC_LIST_UNLINK(*newkeys, key1, link);
  1505. dns_dnsseckey_destroy(mctx, &key1);
  1506. }
  1507. result = ISC_R_SUCCESS;
  1508. failure:
  1509. return (result);
  1510. }