PageRenderTime 53ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/bind9/lib/dns/tsig.c

https://bitbucket.org/freebsd/freebsd-head/
C | 1857 lines | 1459 code | 232 blank | 166 comment | 524 complexity | f1e6eeeab52c057958c6131f0fc8092c MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2002 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/mem.h>
  25. #include <isc/print.h>
  26. #include <isc/refcount.h>
  27. #include <isc/serial.h>
  28. #include <isc/string.h> /* Required for HP/UX (and others?) */
  29. #include <isc/util.h>
  30. #include <isc/time.h>
  31. #include <dns/keyvalues.h>
  32. #include <dns/log.h>
  33. #include <dns/message.h>
  34. #include <dns/fixedname.h>
  35. #include <dns/rbt.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>
  42. #include <dst/result.h>
  43. #define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
  44. #define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
  45. #ifndef DNS_TSIG_MAXGENERATEDKEYS
  46. #define DNS_TSIG_MAXGENERATEDKEYS 4096
  47. #endif
  48. #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
  49. #define algname_is_allocated(algname) \
  50. ((algname) != dns_tsig_hmacmd5_name && \
  51. (algname) != dns_tsig_hmacsha1_name && \
  52. (algname) != dns_tsig_hmacsha224_name && \
  53. (algname) != dns_tsig_hmacsha256_name && \
  54. (algname) != dns_tsig_hmacsha384_name && \
  55. (algname) != dns_tsig_hmacsha512_name && \
  56. (algname) != dns_tsig_gssapi_name && \
  57. (algname) != dns_tsig_gssapims_name)
  58. #define BADTIMELEN 6
  59. static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
  60. static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
  61. static dns_name_t hmacmd5 = {
  62. DNS_NAME_MAGIC,
  63. hmacmd5_ndata, 26, 5,
  64. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  65. hmacmd5_offsets, NULL,
  66. {(void *)-1, (void *)-1},
  67. {NULL, NULL}
  68. };
  69. dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
  70. static unsigned char gsstsig_ndata[] = "\010gss-tsig";
  71. static unsigned char gsstsig_offsets[] = { 0, 9 };
  72. static dns_name_t gsstsig = {
  73. DNS_NAME_MAGIC,
  74. gsstsig_ndata, 10, 2,
  75. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  76. gsstsig_offsets, NULL,
  77. {(void *)-1, (void *)-1},
  78. {NULL, NULL}
  79. };
  80. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
  81. /*
  82. * Since Microsoft doesn't follow its own standard, we will use this
  83. * alternate name as a second guess.
  84. */
  85. static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
  86. static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
  87. static dns_name_t gsstsigms = {
  88. DNS_NAME_MAGIC,
  89. gsstsigms_ndata, 19, 4,
  90. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  91. gsstsigms_offsets, NULL,
  92. {(void *)-1, (void *)-1},
  93. {NULL, NULL}
  94. };
  95. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
  96. static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
  97. static unsigned char hmacsha1_offsets[] = { 0, 10 };
  98. static dns_name_t hmacsha1 = {
  99. DNS_NAME_MAGIC,
  100. hmacsha1_ndata, 11, 2,
  101. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  102. hmacsha1_offsets, NULL,
  103. {(void *)-1, (void *)-1},
  104. {NULL, NULL}
  105. };
  106. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
  107. static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
  108. static unsigned char hmacsha224_offsets[] = { 0, 12 };
  109. static dns_name_t hmacsha224 = {
  110. DNS_NAME_MAGIC,
  111. hmacsha224_ndata, 13, 2,
  112. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  113. hmacsha224_offsets, NULL,
  114. {(void *)-1, (void *)-1},
  115. {NULL, NULL}
  116. };
  117. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
  118. static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
  119. static unsigned char hmacsha256_offsets[] = { 0, 12 };
  120. static dns_name_t hmacsha256 = {
  121. DNS_NAME_MAGIC,
  122. hmacsha256_ndata, 13, 2,
  123. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  124. hmacsha256_offsets, NULL,
  125. {(void *)-1, (void *)-1},
  126. {NULL, NULL}
  127. };
  128. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
  129. static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
  130. static unsigned char hmacsha384_offsets[] = { 0, 12 };
  131. static dns_name_t hmacsha384 = {
  132. DNS_NAME_MAGIC,
  133. hmacsha384_ndata, 13, 2,
  134. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  135. hmacsha384_offsets, NULL,
  136. {(void *)-1, (void *)-1},
  137. {NULL, NULL}
  138. };
  139. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
  140. static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
  141. static unsigned char hmacsha512_offsets[] = { 0, 12 };
  142. static dns_name_t hmacsha512 = {
  143. DNS_NAME_MAGIC,
  144. hmacsha512_ndata, 13, 2,
  145. DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  146. hmacsha512_offsets, NULL,
  147. {(void *)-1, (void *)-1},
  148. {NULL, NULL}
  149. };
  150. LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
  151. static isc_result_t
  152. tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
  153. static void
  154. tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
  155. ISC_FORMAT_PRINTF(3, 4);
  156. static void
  157. cleanup_ring(dns_tsig_keyring_t *ring);
  158. static void
  159. tsigkey_free(dns_tsigkey_t *key);
  160. static void
  161. tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
  162. va_list ap;
  163. char message[4096];
  164. char namestr[DNS_NAME_FORMATSIZE];
  165. char creatorstr[DNS_NAME_FORMATSIZE];
  166. if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
  167. return;
  168. if (key != NULL)
  169. dns_name_format(&key->name, namestr, sizeof(namestr));
  170. else
  171. strcpy(namestr, "<null>");
  172. if (key != NULL && key->generated && key->creator)
  173. dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
  174. else
  175. strcpy(creatorstr, "<null>");
  176. va_start(ap, fmt);
  177. vsnprintf(message, sizeof(message), fmt, ap);
  178. va_end(ap);
  179. if (key != NULL && key->generated)
  180. isc_log_write(dns_lctx,
  181. DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
  182. level, "tsig key '%s' (%s): %s",
  183. namestr, creatorstr, message);
  184. else
  185. isc_log_write(dns_lctx,
  186. DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
  187. level, "tsig key '%s': %s", namestr, message);
  188. }
  189. static void
  190. remove_fromring(dns_tsigkey_t *tkey) {
  191. if (tkey->generated) {
  192. ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
  193. tkey->ring->generated--;
  194. }
  195. (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
  196. }
  197. static void
  198. adjust_lru(dns_tsigkey_t *tkey) {
  199. if (tkey->generated) {
  200. RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
  201. /*
  202. * We may have been removed from the LRU list between
  203. * removing the read lock and aquiring the write lock.
  204. */
  205. if (ISC_LINK_LINKED(tkey, link)) {
  206. ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
  207. ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
  208. }
  209. RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
  210. }
  211. }
  212. /*
  213. * A supplemental routine just to add a key to ring. Note that reference
  214. * counter should be counted separately because we may be adding the key
  215. * as part of creation of the key, in which case the reference counter was
  216. * already initialized. Also note we don't need RWLOCK for the reference
  217. * counter: it's protected by a separate lock.
  218. */
  219. static isc_result_t
  220. keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
  221. dns_tsigkey_t *tkey)
  222. {
  223. isc_result_t result;
  224. RWLOCK(&ring->lock, isc_rwlocktype_write);
  225. ring->writecount++;
  226. /*
  227. * Do on the fly cleaning. Find some nodes we might not
  228. * want around any more.
  229. */
  230. if (ring->writecount > 10) {
  231. cleanup_ring(ring);
  232. ring->writecount = 0;
  233. }
  234. result = dns_rbt_addname(ring->keys, name, tkey);
  235. if (tkey->generated) {
  236. /*
  237. * Add the new key to the LRU list and remove the least
  238. * recently used key if there are too many keys on the list.
  239. */
  240. ISC_LIST_INITANDAPPEND(ring->lru, tkey, link);
  241. if (ring->generated++ > ring->maxgenerated)
  242. remove_fromring(ISC_LIST_HEAD(ring->lru));
  243. }
  244. RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  245. return (result);
  246. }
  247. isc_result_t
  248. dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
  249. dst_key_t *dstkey, isc_boolean_t generated,
  250. dns_name_t *creator, isc_stdtime_t inception,
  251. isc_stdtime_t expire, isc_mem_t *mctx,
  252. dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
  253. {
  254. dns_tsigkey_t *tkey;
  255. isc_result_t ret;
  256. unsigned int refs = 0;
  257. REQUIRE(key == NULL || *key == NULL);
  258. REQUIRE(name != NULL);
  259. REQUIRE(algorithm != NULL);
  260. REQUIRE(mctx != NULL);
  261. REQUIRE(key != NULL || ring != NULL);
  262. tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
  263. if (tkey == NULL)
  264. return (ISC_R_NOMEMORY);
  265. dns_name_init(&tkey->name, NULL);
  266. ret = dns_name_dup(name, mctx, &tkey->name);
  267. if (ret != ISC_R_SUCCESS)
  268. goto cleanup_key;
  269. (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
  270. if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
  271. tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
  272. if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
  273. ret = DNS_R_BADALG;
  274. goto cleanup_name;
  275. }
  276. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
  277. tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
  278. if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
  279. ret = DNS_R_BADALG;
  280. goto cleanup_name;
  281. }
  282. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
  283. tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
  284. if (dstkey != NULL &&
  285. dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
  286. ret = DNS_R_BADALG;
  287. goto cleanup_name;
  288. }
  289. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
  290. tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
  291. if (dstkey != NULL &&
  292. dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
  293. ret = DNS_R_BADALG;
  294. goto cleanup_name;
  295. }
  296. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
  297. tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
  298. if (dstkey != NULL &&
  299. dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
  300. ret = DNS_R_BADALG;
  301. goto cleanup_name;
  302. }
  303. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
  304. tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
  305. if (dstkey != NULL &&
  306. dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
  307. ret = DNS_R_BADALG;
  308. goto cleanup_name;
  309. }
  310. } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
  311. tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
  312. if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
  313. ret = DNS_R_BADALG;
  314. goto cleanup_name;
  315. }
  316. } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  317. tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
  318. if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
  319. ret = DNS_R_BADALG;
  320. goto cleanup_name;
  321. }
  322. } else {
  323. if (dstkey != NULL) {
  324. ret = DNS_R_BADALG;
  325. goto cleanup_name;
  326. }
  327. tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
  328. if (tkey->algorithm == NULL) {
  329. ret = ISC_R_NOMEMORY;
  330. goto cleanup_name;
  331. }
  332. dns_name_init(tkey->algorithm, NULL);
  333. ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
  334. if (ret != ISC_R_SUCCESS)
  335. goto cleanup_algorithm;
  336. (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
  337. NULL);
  338. }
  339. if (creator != NULL) {
  340. tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
  341. if (tkey->creator == NULL) {
  342. ret = ISC_R_NOMEMORY;
  343. goto cleanup_algorithm;
  344. }
  345. dns_name_init(tkey->creator, NULL);
  346. ret = dns_name_dup(creator, mctx, tkey->creator);
  347. if (ret != ISC_R_SUCCESS) {
  348. isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
  349. goto cleanup_algorithm;
  350. }
  351. } else
  352. tkey->creator = NULL;
  353. tkey->key = NULL;
  354. if (dstkey != NULL)
  355. dst_key_attach(dstkey, &tkey->key);
  356. tkey->ring = ring;
  357. if (key != NULL)
  358. refs = 1;
  359. if (ring != NULL)
  360. refs++;
  361. ret = isc_refcount_init(&tkey->refs, refs);
  362. if (ret != ISC_R_SUCCESS)
  363. goto cleanup_creator;
  364. tkey->generated = generated;
  365. tkey->inception = inception;
  366. tkey->expire = expire;
  367. tkey->mctx = NULL;
  368. isc_mem_attach(mctx, &tkey->mctx);
  369. tkey->magic = TSIG_MAGIC;
  370. if (ring != NULL) {
  371. ret = keyring_add(ring, name, tkey);
  372. if (ret != ISC_R_SUCCESS)
  373. goto cleanup_refs;
  374. }
  375. /*
  376. * Ignore this if it's a GSS key, since the key size is meaningless.
  377. */
  378. if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
  379. !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
  380. !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  381. char namestr[DNS_NAME_FORMATSIZE];
  382. dns_name_format(name, namestr, sizeof(namestr));
  383. isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
  384. DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
  385. "the key '%s' is too short to be secure",
  386. namestr);
  387. }
  388. if (key != NULL)
  389. *key = tkey;
  390. return (ISC_R_SUCCESS);
  391. cleanup_refs:
  392. tkey->magic = 0;
  393. while (refs-- > 0)
  394. isc_refcount_decrement(&tkey->refs, NULL);
  395. isc_refcount_destroy(&tkey->refs);
  396. cleanup_creator:
  397. if (tkey->key != NULL)
  398. dst_key_free(&tkey->key);
  399. if (tkey->creator != NULL) {
  400. dns_name_free(tkey->creator, mctx);
  401. isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
  402. }
  403. cleanup_algorithm:
  404. if (algname_is_allocated(tkey->algorithm)) {
  405. if (dns_name_dynamic(tkey->algorithm))
  406. dns_name_free(tkey->algorithm, mctx);
  407. isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
  408. }
  409. cleanup_name:
  410. dns_name_free(&tkey->name, mctx);
  411. cleanup_key:
  412. isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
  413. return (ret);
  414. }
  415. /*
  416. * Find a few nodes to destroy if possible.
  417. */
  418. static void
  419. cleanup_ring(dns_tsig_keyring_t *ring)
  420. {
  421. isc_result_t result;
  422. dns_rbtnodechain_t chain;
  423. dns_name_t foundname;
  424. dns_fixedname_t fixedorigin;
  425. dns_name_t *origin;
  426. isc_stdtime_t now;
  427. dns_rbtnode_t *node;
  428. dns_tsigkey_t *tkey;
  429. /*
  430. * Start up a new iterator each time.
  431. */
  432. isc_stdtime_get(&now);
  433. dns_name_init(&foundname, NULL);
  434. dns_fixedname_init(&fixedorigin);
  435. origin = dns_fixedname_name(&fixedorigin);
  436. again:
  437. dns_rbtnodechain_init(&chain, ring->mctx);
  438. result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
  439. origin);
  440. if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  441. dns_rbtnodechain_invalidate(&chain);
  442. return;
  443. }
  444. for (;;) {
  445. node = NULL;
  446. dns_rbtnodechain_current(&chain, &foundname, origin, &node);
  447. tkey = node->data;
  448. if (tkey != NULL) {
  449. if (tkey->generated
  450. && isc_refcount_current(&tkey->refs) == 1
  451. && tkey->inception != tkey->expire
  452. && tkey->expire < now) {
  453. tsig_log(tkey, 2, "tsig expire: deleting");
  454. /* delete the key */
  455. dns_rbtnodechain_invalidate(&chain);
  456. remove_fromring(tkey);
  457. goto again;
  458. }
  459. }
  460. result = dns_rbtnodechain_next(&chain, &foundname,
  461. origin);
  462. if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  463. dns_rbtnodechain_invalidate(&chain);
  464. return;
  465. }
  466. }
  467. }
  468. static void
  469. destroyring(dns_tsig_keyring_t *ring) {
  470. dns_rbt_destroy(&ring->keys);
  471. isc_rwlock_destroy(&ring->lock);
  472. isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
  473. }
  474. static unsigned int
  475. dst_alg_fromname(dns_name_t *algorithm) {
  476. if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
  477. return (DST_ALG_HMACMD5);
  478. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
  479. return (DST_ALG_HMACSHA1);
  480. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
  481. return (DST_ALG_HMACSHA224);
  482. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
  483. return (DST_ALG_HMACSHA256);
  484. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
  485. return (DST_ALG_HMACSHA384);
  486. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
  487. return (DST_ALG_HMACSHA512);
  488. } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
  489. return (DST_ALG_GSSAPI);
  490. } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  491. return (DST_ALG_GSSAPI);
  492. } else
  493. return (0);
  494. }
  495. static isc_result_t
  496. restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
  497. dst_key_t *dstkey = NULL;
  498. char namestr[1024];
  499. char creatorstr[1024];
  500. char algorithmstr[1024];
  501. char keystr[4096];
  502. unsigned int inception, expire;
  503. int n;
  504. isc_buffer_t b;
  505. dns_name_t *name, *creator, *algorithm;
  506. dns_fixedname_t fname, fcreator, falgorithm;
  507. isc_result_t result;
  508. unsigned int dstalg;
  509. n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
  510. creatorstr, &inception, &expire, algorithmstr, keystr);
  511. if (n == EOF)
  512. return (ISC_R_NOMORE);
  513. if (n != 6)
  514. return (ISC_R_FAILURE);
  515. if (isc_serial_lt(expire, now))
  516. return (DNS_R_EXPIRED);
  517. dns_fixedname_init(&fname);
  518. name = dns_fixedname_name(&fname);
  519. isc_buffer_init(&b, namestr, strlen(namestr));
  520. isc_buffer_add(&b, strlen(namestr));
  521. result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
  522. if (result != ISC_R_SUCCESS)
  523. return (result);
  524. dns_fixedname_init(&fcreator);
  525. creator = dns_fixedname_name(&fcreator);
  526. isc_buffer_init(&b, creatorstr, strlen(creatorstr));
  527. isc_buffer_add(&b, strlen(creatorstr));
  528. result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
  529. if (result != ISC_R_SUCCESS)
  530. return (result);
  531. dns_fixedname_init(&falgorithm);
  532. algorithm = dns_fixedname_name(&falgorithm);
  533. isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
  534. isc_buffer_add(&b, strlen(algorithmstr));
  535. result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
  536. if (result != ISC_R_SUCCESS)
  537. return (result);
  538. dstalg = dst_alg_fromname(algorithm);
  539. if (dstalg == 0)
  540. return (DNS_R_BADALG);
  541. result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
  542. DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
  543. ring->mctx, keystr, &dstkey);
  544. if (result != ISC_R_SUCCESS)
  545. return (result);
  546. result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
  547. ISC_TRUE, creator, inception,
  548. expire, ring->mctx, ring, NULL);
  549. if (dstkey != NULL)
  550. dst_key_free(&dstkey);
  551. return (result);
  552. }
  553. static void
  554. dump_key(dns_tsigkey_t *tkey, FILE *fp)
  555. {
  556. char *buffer = NULL;
  557. int length = 0;
  558. char namestr[DNS_NAME_FORMATSIZE];
  559. char creatorstr[DNS_NAME_FORMATSIZE];
  560. char algorithmstr[DNS_NAME_FORMATSIZE];
  561. isc_result_t result;
  562. dns_name_format(&tkey->name, namestr, sizeof(namestr));
  563. dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
  564. dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
  565. result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
  566. if (result == ISC_R_SUCCESS)
  567. fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
  568. tkey->inception, tkey->expire, algorithmstr,
  569. length, buffer);
  570. if (buffer != NULL)
  571. isc_mem_put(tkey->mctx, buffer, length);
  572. }
  573. isc_result_t
  574. dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
  575. isc_result_t result;
  576. dns_rbtnodechain_t chain;
  577. dns_name_t foundname;
  578. dns_fixedname_t fixedorigin;
  579. dns_name_t *origin;
  580. isc_stdtime_t now;
  581. dns_rbtnode_t *node;
  582. dns_tsigkey_t *tkey;
  583. dns_tsig_keyring_t *ring;
  584. unsigned int references;
  585. REQUIRE(ringp != NULL && *ringp != NULL);
  586. ring = *ringp;
  587. *ringp = NULL;
  588. RWLOCK(&ring->lock, isc_rwlocktype_write);
  589. INSIST(ring->references > 0);
  590. ring->references--;
  591. references = ring->references;
  592. RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  593. if (references != 0)
  594. return (DNS_R_CONTINUE);
  595. isc_stdtime_get(&now);
  596. dns_name_init(&foundname, NULL);
  597. dns_fixedname_init(&fixedorigin);
  598. origin = dns_fixedname_name(&fixedorigin);
  599. dns_rbtnodechain_init(&chain, ring->mctx);
  600. result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
  601. origin);
  602. if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  603. dns_rbtnodechain_invalidate(&chain);
  604. goto destroy;
  605. }
  606. for (;;) {
  607. node = NULL;
  608. dns_rbtnodechain_current(&chain, &foundname, origin, &node);
  609. tkey = node->data;
  610. if (tkey != NULL && tkey->generated && tkey->expire >= now)
  611. dump_key(tkey, fp);
  612. result = dns_rbtnodechain_next(&chain, &foundname,
  613. origin);
  614. if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
  615. dns_rbtnodechain_invalidate(&chain);
  616. if (result == ISC_R_NOMORE)
  617. result = ISC_R_SUCCESS;
  618. goto destroy;
  619. }
  620. }
  621. destroy:
  622. destroyring(ring);
  623. return (result);
  624. }
  625. isc_result_t
  626. dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
  627. unsigned char *secret, int length, isc_boolean_t generated,
  628. dns_name_t *creator, isc_stdtime_t inception,
  629. isc_stdtime_t expire, isc_mem_t *mctx,
  630. dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
  631. {
  632. dst_key_t *dstkey = NULL;
  633. isc_result_t result;
  634. REQUIRE(length >= 0);
  635. if (length > 0)
  636. REQUIRE(secret != NULL);
  637. if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
  638. if (secret != NULL) {
  639. isc_buffer_t b;
  640. isc_buffer_init(&b, secret, length);
  641. isc_buffer_add(&b, length);
  642. result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
  643. DNS_KEYOWNER_ENTITY,
  644. DNS_KEYPROTO_DNSSEC,
  645. dns_rdataclass_in,
  646. &b, mctx, &dstkey);
  647. if (result != ISC_R_SUCCESS)
  648. return (result);
  649. }
  650. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
  651. if (secret != NULL) {
  652. isc_buffer_t b;
  653. isc_buffer_init(&b, secret, length);
  654. isc_buffer_add(&b, length);
  655. result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
  656. DNS_KEYOWNER_ENTITY,
  657. DNS_KEYPROTO_DNSSEC,
  658. dns_rdataclass_in,
  659. &b, mctx, &dstkey);
  660. if (result != ISC_R_SUCCESS)
  661. return (result);
  662. }
  663. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
  664. if (secret != NULL) {
  665. isc_buffer_t b;
  666. isc_buffer_init(&b, secret, length);
  667. isc_buffer_add(&b, length);
  668. result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
  669. DNS_KEYOWNER_ENTITY,
  670. DNS_KEYPROTO_DNSSEC,
  671. dns_rdataclass_in,
  672. &b, mctx, &dstkey);
  673. if (result != ISC_R_SUCCESS)
  674. return (result);
  675. }
  676. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
  677. if (secret != NULL) {
  678. isc_buffer_t b;
  679. isc_buffer_init(&b, secret, length);
  680. isc_buffer_add(&b, length);
  681. result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
  682. DNS_KEYOWNER_ENTITY,
  683. DNS_KEYPROTO_DNSSEC,
  684. dns_rdataclass_in,
  685. &b, mctx, &dstkey);
  686. if (result != ISC_R_SUCCESS)
  687. return (result);
  688. }
  689. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
  690. if (secret != NULL) {
  691. isc_buffer_t b;
  692. isc_buffer_init(&b, secret, length);
  693. isc_buffer_add(&b, length);
  694. result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
  695. DNS_KEYOWNER_ENTITY,
  696. DNS_KEYPROTO_DNSSEC,
  697. dns_rdataclass_in,
  698. &b, mctx, &dstkey);
  699. if (result != ISC_R_SUCCESS)
  700. return (result);
  701. }
  702. } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
  703. if (secret != NULL) {
  704. isc_buffer_t b;
  705. isc_buffer_init(&b, secret, length);
  706. isc_buffer_add(&b, length);
  707. result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
  708. DNS_KEYOWNER_ENTITY,
  709. DNS_KEYPROTO_DNSSEC,
  710. dns_rdataclass_in,
  711. &b, mctx, &dstkey);
  712. if (result != ISC_R_SUCCESS)
  713. return (result);
  714. }
  715. } else if (length > 0)
  716. return (DNS_R_BADALG);
  717. result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
  718. generated, creator,
  719. inception, expire, mctx, ring, key);
  720. if (dstkey != NULL)
  721. dst_key_free(&dstkey);
  722. return (result);
  723. }
  724. void
  725. dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
  726. REQUIRE(VALID_TSIG_KEY(source));
  727. REQUIRE(targetp != NULL && *targetp == NULL);
  728. isc_refcount_increment(&source->refs, NULL);
  729. *targetp = source;
  730. }
  731. static void
  732. tsigkey_free(dns_tsigkey_t *key) {
  733. REQUIRE(VALID_TSIG_KEY(key));
  734. key->magic = 0;
  735. dns_name_free(&key->name, key->mctx);
  736. if (algname_is_allocated(key->algorithm)) {
  737. dns_name_free(key->algorithm, key->mctx);
  738. isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
  739. }
  740. if (key->key != NULL)
  741. dst_key_free(&key->key);
  742. if (key->creator != NULL) {
  743. dns_name_free(key->creator, key->mctx);
  744. isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
  745. }
  746. isc_refcount_destroy(&key->refs);
  747. isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
  748. }
  749. void
  750. dns_tsigkey_detach(dns_tsigkey_t **keyp) {
  751. dns_tsigkey_t *key;
  752. unsigned int refs;
  753. REQUIRE(keyp != NULL);
  754. REQUIRE(VALID_TSIG_KEY(*keyp));
  755. key = *keyp;
  756. isc_refcount_decrement(&key->refs, &refs);
  757. if (refs == 0)
  758. tsigkey_free(key);
  759. *keyp = NULL;
  760. }
  761. void
  762. dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
  763. REQUIRE(VALID_TSIG_KEY(key));
  764. REQUIRE(key->ring != NULL);
  765. RWLOCK(&key->ring->lock, isc_rwlocktype_write);
  766. remove_fromring(key);
  767. RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
  768. }
  769. isc_result_t
  770. dns_tsig_sign(dns_message_t *msg) {
  771. dns_tsigkey_t *key;
  772. dns_rdata_any_tsig_t tsig, querytsig;
  773. unsigned char data[128];
  774. isc_buffer_t databuf, sigbuf;
  775. isc_buffer_t *dynbuf;
  776. dns_name_t *owner;
  777. dns_rdata_t *rdata = NULL;
  778. dns_rdatalist_t *datalist;
  779. dns_rdataset_t *dataset;
  780. isc_region_t r;
  781. isc_stdtime_t now;
  782. isc_mem_t *mctx;
  783. dst_context_t *ctx = NULL;
  784. isc_result_t ret;
  785. unsigned char badtimedata[BADTIMELEN];
  786. unsigned int sigsize = 0;
  787. isc_boolean_t response = is_response(msg);
  788. REQUIRE(msg != NULL);
  789. REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
  790. /*
  791. * If this is a response, there should be a query tsig.
  792. */
  793. if (response && msg->querytsig == NULL)
  794. return (DNS_R_EXPECTEDTSIG);
  795. dynbuf = NULL;
  796. mctx = msg->mctx;
  797. key = dns_message_gettsigkey(msg);
  798. tsig.mctx = mctx;
  799. tsig.common.rdclass = dns_rdataclass_any;
  800. tsig.common.rdtype = dns_rdatatype_tsig;
  801. ISC_LINK_INIT(&tsig.common, link);
  802. dns_name_init(&tsig.algorithm, NULL);
  803. dns_name_clone(key->algorithm, &tsig.algorithm);
  804. isc_stdtime_get(&now);
  805. tsig.timesigned = now + msg->timeadjust;
  806. tsig.fudge = DNS_TSIG_FUDGE;
  807. tsig.originalid = msg->id;
  808. isc_buffer_init(&databuf, data, sizeof(data));
  809. if (response)
  810. tsig.error = msg->querytsigstatus;
  811. else
  812. tsig.error = dns_rcode_noerror;
  813. if (tsig.error != dns_tsigerror_badtime) {
  814. tsig.otherlen = 0;
  815. tsig.other = NULL;
  816. } else {
  817. isc_buffer_t otherbuf;
  818. tsig.otherlen = BADTIMELEN;
  819. tsig.other = badtimedata;
  820. isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
  821. isc_buffer_putuint48(&otherbuf, tsig.timesigned);
  822. }
  823. if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
  824. unsigned char header[DNS_MESSAGE_HEADERLEN];
  825. isc_buffer_t headerbuf;
  826. isc_uint16_t digestbits;
  827. ret = dst_context_create(key->key, mctx, &ctx);
  828. if (ret != ISC_R_SUCCESS)
  829. return (ret);
  830. /*
  831. * If this is a response, digest the query signature.
  832. */
  833. if (response) {
  834. dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
  835. ret = dns_rdataset_first(msg->querytsig);
  836. if (ret != ISC_R_SUCCESS)
  837. goto cleanup_context;
  838. dns_rdataset_current(msg->querytsig, &querytsigrdata);
  839. ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
  840. NULL);
  841. if (ret != ISC_R_SUCCESS)
  842. goto cleanup_context;
  843. isc_buffer_putuint16(&databuf, querytsig.siglen);
  844. if (isc_buffer_availablelength(&databuf) <
  845. querytsig.siglen) {
  846. ret = ISC_R_NOSPACE;
  847. goto cleanup_context;
  848. }
  849. isc_buffer_putmem(&databuf, querytsig.signature,
  850. querytsig.siglen);
  851. isc_buffer_usedregion(&databuf, &r);
  852. ret = dst_context_adddata(ctx, &r);
  853. if (ret != ISC_R_SUCCESS)
  854. goto cleanup_context;
  855. }
  856. /*
  857. * Digest the header.
  858. */
  859. isc_buffer_init(&headerbuf, header, sizeof(header));
  860. dns_message_renderheader(msg, &headerbuf);
  861. isc_buffer_usedregion(&headerbuf, &r);
  862. ret = dst_context_adddata(ctx, &r);
  863. if (ret != ISC_R_SUCCESS)
  864. goto cleanup_context;
  865. /*
  866. * Digest the remainder of the message.
  867. */
  868. isc_buffer_usedregion(msg->buffer, &r);
  869. isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
  870. ret = dst_context_adddata(ctx, &r);
  871. if (ret != ISC_R_SUCCESS)
  872. goto cleanup_context;
  873. if (msg->tcp_continuation == 0) {
  874. /*
  875. * Digest the name, class, ttl, alg.
  876. */
  877. dns_name_toregion(&key->name, &r);
  878. ret = dst_context_adddata(ctx, &r);
  879. if (ret != ISC_R_SUCCESS)
  880. goto cleanup_context;
  881. isc_buffer_clear(&databuf);
  882. isc_buffer_putuint16(&databuf, dns_rdataclass_any);
  883. isc_buffer_putuint32(&databuf, 0); /* ttl */
  884. isc_buffer_usedregion(&databuf, &r);
  885. ret = dst_context_adddata(ctx, &r);
  886. if (ret != ISC_R_SUCCESS)
  887. goto cleanup_context;
  888. dns_name_toregion(&tsig.algorithm, &r);
  889. ret = dst_context_adddata(ctx, &r);
  890. if (ret != ISC_R_SUCCESS)
  891. goto cleanup_context;
  892. }
  893. /* Digest the timesigned and fudge */
  894. isc_buffer_clear(&databuf);
  895. if (tsig.error == dns_tsigerror_badtime) {
  896. INSIST(response);
  897. tsig.timesigned = querytsig.timesigned;
  898. }
  899. isc_buffer_putuint48(&databuf, tsig.timesigned);
  900. isc_buffer_putuint16(&databuf, tsig.fudge);
  901. isc_buffer_usedregion(&databuf, &r);
  902. ret = dst_context_adddata(ctx, &r);
  903. if (ret != ISC_R_SUCCESS)
  904. goto cleanup_context;
  905. if (msg->tcp_continuation == 0) {
  906. /*
  907. * Digest the error and other data length.
  908. */
  909. isc_buffer_clear(&databuf);
  910. isc_buffer_putuint16(&databuf, tsig.error);
  911. isc_buffer_putuint16(&databuf, tsig.otherlen);
  912. isc_buffer_usedregion(&databuf, &r);
  913. ret = dst_context_adddata(ctx, &r);
  914. if (ret != ISC_R_SUCCESS)
  915. goto cleanup_context;
  916. /*
  917. * Digest other data.
  918. */
  919. if (tsig.otherlen > 0) {
  920. r.length = tsig.otherlen;
  921. r.base = tsig.other;
  922. ret = dst_context_adddata(ctx, &r);
  923. if (ret != ISC_R_SUCCESS)
  924. goto cleanup_context;
  925. }
  926. }
  927. ret = dst_key_sigsize(key->key, &sigsize);
  928. if (ret != ISC_R_SUCCESS)
  929. goto cleanup_context;
  930. tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
  931. if (tsig.signature == NULL) {
  932. ret = ISC_R_NOMEMORY;
  933. goto cleanup_context;
  934. }
  935. isc_buffer_init(&sigbuf, tsig.signature, sigsize);
  936. ret = dst_context_sign(ctx, &sigbuf);
  937. if (ret != ISC_R_SUCCESS)
  938. goto cleanup_signature;
  939. dst_context_destroy(&ctx);
  940. digestbits = dst_key_getbits(key->key);
  941. if (digestbits != 0) {
  942. unsigned int bytes = (digestbits + 1) / 8;
  943. if (response && bytes < querytsig.siglen)
  944. bytes = querytsig.siglen;
  945. if (bytes > isc_buffer_usedlength(&sigbuf))
  946. bytes = isc_buffer_usedlength(&sigbuf);
  947. tsig.siglen = bytes;
  948. } else
  949. tsig.siglen = isc_buffer_usedlength(&sigbuf);
  950. } else {
  951. tsig.siglen = 0;
  952. tsig.signature = NULL;
  953. }
  954. ret = dns_message_gettemprdata(msg, &rdata);
  955. if (ret != ISC_R_SUCCESS)
  956. goto cleanup_signature;
  957. ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
  958. if (ret != ISC_R_SUCCESS)
  959. goto cleanup_rdata;
  960. ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
  961. dns_rdatatype_tsig, &tsig, dynbuf);
  962. if (ret != ISC_R_SUCCESS)
  963. goto cleanup_dynbuf;
  964. dns_message_takebuffer(msg, &dynbuf);
  965. if (tsig.signature != NULL) {
  966. isc_mem_put(mctx, tsig.signature, sigsize);
  967. tsig.signature = NULL;
  968. }
  969. owner = NULL;
  970. ret = dns_message_gettempname(msg, &owner);
  971. if (ret != ISC_R_SUCCESS)
  972. goto cleanup_rdata;
  973. dns_name_init(owner, NULL);
  974. ret = dns_name_dup(&key->name, msg->mctx, owner);
  975. if (ret != ISC_R_SUCCESS)
  976. goto cleanup_owner;
  977. datalist = NULL;
  978. ret = dns_message_gettemprdatalist(msg, &datalist);
  979. if (ret != ISC_R_SUCCESS)
  980. goto cleanup_owner;
  981. dataset = NULL;
  982. ret = dns_message_gettemprdataset(msg, &dataset);
  983. if (ret != ISC_R_SUCCESS)
  984. goto cleanup_rdatalist;
  985. datalist->rdclass = dns_rdataclass_any;
  986. datalist->type = dns_rdatatype_tsig;
  987. datalist->covers = 0;
  988. datalist->ttl = 0;
  989. ISC_LIST_INIT(datalist->rdata);
  990. ISC_LIST_APPEND(datalist->rdata, rdata, link);
  991. dns_rdataset_init(dataset);
  992. RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
  993. == ISC_R_SUCCESS);
  994. msg->tsig = dataset;
  995. msg->tsigname = owner;
  996. /* Windows does not like the tsig name being compressed. */
  997. msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
  998. return (ISC_R_SUCCESS);
  999. cleanup_rdatalist:
  1000. dns_message_puttemprdatalist(msg, &datalist);
  1001. cleanup_owner:
  1002. dns_message_puttempname(msg, &owner);
  1003. goto cleanup_rdata;
  1004. cleanup_dynbuf:
  1005. isc_buffer_free(&dynbuf);
  1006. cleanup_rdata:
  1007. dns_message_puttemprdata(msg, &rdata);
  1008. cleanup_signature:
  1009. if (tsig.signature != NULL)
  1010. isc_mem_put(mctx, tsig.signature, sigsize);
  1011. cleanup_context:
  1012. if (ctx != NULL)
  1013. dst_context_destroy(&ctx);
  1014. return (ret);
  1015. }
  1016. isc_result_t
  1017. dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
  1018. dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
  1019. {
  1020. dns_rdata_any_tsig_t tsig, querytsig;
  1021. isc_region_t r, source_r, header_r, sig_r;
  1022. isc_buffer_t databuf;
  1023. unsigned char data[32];
  1024. dns_name_t *keyname;
  1025. dns_rdata_t rdata = DNS_RDATA_INIT;
  1026. isc_stdtime_t now;
  1027. isc_result_t ret;
  1028. dns_tsigkey_t *tsigkey;
  1029. dst_key_t *key = NULL;
  1030. unsigned char header[DNS_MESSAGE_HEADERLEN];
  1031. dst_context_t *ctx = NULL;
  1032. isc_mem_t *mctx;
  1033. isc_uint16_t addcount, id;
  1034. unsigned int siglen;
  1035. unsigned int alg;
  1036. isc_boolean_t response;
  1037. REQUIRE(source != NULL);
  1038. REQUIRE(DNS_MESSAGE_VALID(msg));
  1039. tsigkey = dns_message_gettsigkey(msg);
  1040. response = is_response(msg);
  1041. REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
  1042. msg->verify_attempted = 1;
  1043. if (msg->tcp_continuation) {
  1044. if (tsigkey == NULL || msg->querytsig == NULL)
  1045. return (DNS_R_UNEXPECTEDTSIG);
  1046. return (tsig_verify_tcp(source, msg));
  1047. }
  1048. /*
  1049. * There should be a TSIG record...
  1050. */
  1051. if (msg->tsig == NULL)
  1052. return (DNS_R_EXPECTEDTSIG);
  1053. /*
  1054. * If this is a response and there's no key or query TSIG, there
  1055. * shouldn't be one on the response.
  1056. */
  1057. if (response && (tsigkey == NULL || msg->querytsig == NULL))
  1058. return (DNS_R_UNEXPECTEDTSIG);
  1059. mctx = msg->mctx;
  1060. /*
  1061. * If we're here, we know the message is well formed and contains a
  1062. * TSIG record.
  1063. */
  1064. keyname = msg->tsigname;
  1065. ret = dns_rdataset_first(msg->tsig);
  1066. if (ret != ISC_R_SUCCESS)
  1067. return (ret);
  1068. dns_rdataset_current(msg->tsig, &rdata);
  1069. ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
  1070. if (ret != ISC_R_SUCCESS)
  1071. return (ret);
  1072. dns_rdata_reset(&rdata);
  1073. if (response) {
  1074. ret = dns_rdataset_first(msg->querytsig);
  1075. if (ret != ISC_R_SUCCESS)
  1076. return (ret);
  1077. dns_rdataset_current(msg->querytsig, &rdata);
  1078. ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
  1079. if (ret != ISC_R_SUCCESS)
  1080. return (ret);
  1081. }
  1082. /*
  1083. * Do the key name and algorithm match that of the query?
  1084. */
  1085. if (response &&
  1086. (!dns_name_equal(keyname, &tsigkey->name) ||
  1087. !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
  1088. msg->tsigstatus = dns_tsigerror_badkey;
  1089. tsig_log(msg->tsigkey, 2,
  1090. "key name and algorithm do not match");
  1091. return (DNS_R_TSIGVERIFYFAILURE);
  1092. }
  1093. /*
  1094. * Get the current time.
  1095. */
  1096. isc_stdtime_get(&now);
  1097. /*
  1098. * Find dns_tsigkey_t based on keyname.
  1099. */
  1100. if (tsigkey == NULL) {
  1101. ret = ISC_R_NOTFOUND;
  1102. if (ring1 != NULL)
  1103. ret = dns_tsigkey_find(&tsigkey, keyname,
  1104. &tsig.algorithm, ring1);
  1105. if (ret == ISC_R_NOTFOUND && ring2 != NULL)
  1106. ret = dns_tsigkey_find(&tsigkey, keyname,
  1107. &tsig.algorithm, ring2);
  1108. if (ret != ISC_R_SUCCESS) {
  1109. msg->tsigstatus = dns_tsigerror_badkey;
  1110. ret = dns_tsigkey_create(keyname, &tsig.algorithm,
  1111. NULL, 0, ISC_FALSE, NULL,
  1112. now, now,
  1113. mctx, NULL, &msg->tsigkey);
  1114. if (ret != ISC_R_SUCCESS)
  1115. return (ret);
  1116. tsig_log(msg->tsigkey, 2, "unknown key");
  1117. return (DNS_R_TSIGVERIFYFAILURE);
  1118. }
  1119. msg->tsigkey = tsigkey;
  1120. }
  1121. key = tsigkey->key;
  1122. /*
  1123. * Is the time ok?
  1124. */
  1125. if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
  1126. msg->tsigstatus = dns_tsigerror_badtime;
  1127. tsig_log(msg->tsigkey, 2, "signature has expired");
  1128. return (DNS_R_CLOCKSKEW);
  1129. } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
  1130. msg->tsigstatus = dns_tsigerror_badtime;
  1131. tsig_log(msg->tsigkey, 2, "signature is in the future");
  1132. return (DNS_R_CLOCKSKEW);
  1133. }
  1134. /*
  1135. * Check digest length.
  1136. */
  1137. alg = dst_key_alg(key);
  1138. ret = dst_key_sigsize(key, &siglen);
  1139. if (ret != ISC_R_SUCCESS)
  1140. return (ret);
  1141. if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
  1142. alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
  1143. alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
  1144. isc_uint16_t digestbits = dst_key_getbits(key);
  1145. if (tsig.siglen > siglen) {
  1146. tsig_log(msg->tsigkey, 2, "signature length to big");
  1147. return (DNS_R_FORMERR);
  1148. }
  1149. if (tsig.siglen > 0 &&
  1150. (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
  1151. tsig_log(msg->tsigkey, 2,
  1152. "signature length below minimum");
  1153. return (DNS_R_FORMERR);
  1154. }
  1155. if (tsig.siglen > 0 && digestbits != 0 &&
  1156. tsig.siglen < ((digestbits + 1) / 8)) {
  1157. msg->tsigstatus = dns_tsigerror_badtrunc;
  1158. tsig_log(msg->tsigkey, 2,
  1159. "truncated signature length too small");
  1160. return (DNS_R_TSIGVERIFYFAILURE);
  1161. }
  1162. if (tsig.siglen > 0 && digestbits == 0 &&
  1163. tsig.siglen < siglen) {
  1164. msg->tsigstatus = dns_tsigerror_badtrunc;
  1165. tsig_log(msg->tsigkey, 2, "signature length too small");
  1166. return (DNS_R_TSIGVERIFYFAILURE);
  1167. }
  1168. }
  1169. if (tsig.siglen > 0) {
  1170. sig_r.base = tsig.signature;
  1171. sig_r.length = tsig.siglen;
  1172. ret = dst_context_create(key, mctx, &ctx);
  1173. if (ret != ISC_R_SUCCESS)
  1174. return (ret);
  1175. if (response) {
  1176. isc_buffer_init(&databuf, data, sizeof(data));
  1177. isc_buffer_putuint16(&databuf, querytsig.siglen);
  1178. isc_buffer_usedregion(&databuf, &r);
  1179. ret = dst_context_adddata(ctx, &r);
  1180. if (ret != ISC_R_SUCCESS)
  1181. goto cleanup_context;
  1182. if (querytsig.siglen > 0) {
  1183. r.length = querytsig.siglen;
  1184. r.base = querytsig.signature;
  1185. ret = dst_context_adddata(ctx, &r);
  1186. if (ret != ISC_R_SUCCESS)
  1187. goto cleanup_context;
  1188. }
  1189. }
  1190. /*
  1191. * Extract the header.
  1192. */
  1193. isc_buffer_usedregion(source, &r);
  1194. memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
  1195. isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
  1196. /*
  1197. * Decrement the additional field counter.
  1198. */
  1199. memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
  1200. addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
  1201. memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
  1202. /*
  1203. * Put in the original id.
  1204. */
  1205. id = htons(tsig.originalid);
  1206. memcpy(&header[0], &id, 2);
  1207. /*
  1208. * Digest the modified header.
  1209. */
  1210. header_r.base = (unsigned char *) header;
  1211. header_r.length = DNS_MESSAGE_HEADERLEN;
  1212. ret = dst_context_adddata(ctx, &header_r);
  1213. if (ret != ISC_R_SUCCESS)
  1214. goto cleanup_context;
  1215. /*
  1216. * Digest all non-TSIG records.
  1217. */
  1218. isc_buffer_usedregion(source, &source_r);
  1219. r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
  1220. r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
  1221. ret = dst_context_adddata(ctx, &r);
  1222. if (ret != ISC_R_SUCCESS)
  1223. goto cleanup_context;
  1224. /*
  1225. * Digest the key name.
  1226. */
  1227. dns_name_toregion(&tsigkey->name, &r);
  1228. ret = dst_context_adddata(ctx, &r);
  1229. if (ret != ISC_R_SUCCESS)
  1230. goto cleanup_context;
  1231. isc_buffer_init(&databuf, data, sizeof(data));
  1232. isc_buffer_putuint16(&databuf, tsig.common.rdclass);
  1233. isc_buffer_putuint32(&databuf, msg->tsig->ttl);
  1234. isc_buffer_usedregion(&databuf, &r);
  1235. ret = dst_context_adddata(ctx, &r);
  1236. if (ret != ISC_R_SUCCESS)
  1237. goto cleanup_context;
  1238. /*
  1239. * Digest the key algorithm.
  1240. */
  1241. dns_name_toregion(tsigkey->algorithm, &r);
  1242. ret = dst_context_adddata(ctx, &r);
  1243. if (ret != ISC_R_SUCCESS)
  1244. goto cleanup_context;
  1245. isc_buffer_clear(&databuf);
  1246. isc_buffer_putuint48(&databuf, tsig.timesigned);
  1247. isc_buffer_putuint16(&databuf, tsig.fudge);
  1248. isc_buffer_putuint16(&databuf, tsig.error);
  1249. isc_buffer_putuint16(&databuf, tsig.otherlen);
  1250. isc_buffer_usedregion(&databuf, &r);
  1251. ret = dst_context_adddata(ctx, &r);
  1252. if (ret != ISC_R_SUCCESS)
  1253. goto cleanup_context;
  1254. if (tsig.otherlen > 0) {
  1255. r.base = tsig.other;
  1256. r.length = tsig.otherlen;
  1257. ret = dst_context_adddata(ctx, &r);
  1258. if (ret != ISC_R_SUCCESS)
  1259. goto cleanup_context;
  1260. }
  1261. ret = dst_context_verify(ctx, &sig_r);
  1262. if (ret == DST_R_VERIFYFAILURE) {
  1263. msg->tsigstatus = dns_tsigerror_badsig;
  1264. ret = DNS_R_TSIGVERIFYFAILURE;
  1265. tsig_log(msg->tsigkey, 2,
  1266. "signature failed to verify(1)");
  1267. goto cleanup_context;
  1268. } else if (ret != ISC_R_SUCCESS)
  1269. goto cleanup_context;
  1270. dst_context_destroy(&ctx);
  1271. } else if (tsig.error != dns_tsigerror_badsig &&
  1272. tsig.error != dns_tsigerror_badkey) {
  1273. msg->tsigstatus = dns_tsigerror_badsig;
  1274. tsig_log(msg->tsigkey, 2, "signature was empty");
  1275. return (DNS_R_TSIGVERIFYFAILURE);
  1276. }
  1277. msg->tsigstatus = dns_rcode_noerror;
  1278. if (tsig.error != dns_rcode_noerror) {
  1279. if (tsig.error == dns_tsigerror_badtime)
  1280. return (DNS_R_CLOCKSKEW);
  1281. else
  1282. return (DNS_R_TSIGERRORSET);
  1283. }
  1284. msg->verified_sig = 1;
  1285. return (ISC_R_SUCCESS);
  1286. cleanup_context:
  1287. if (ctx != NULL)
  1288. dst_context_destroy(&ctx);
  1289. return (ret);
  1290. }
  1291. static isc_result_t
  1292. tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
  1293. dns_rdata_any_tsig_t tsig, querytsig;
  1294. isc_region_t r, source_r, header_r, sig_r;
  1295. isc_buffer_t databuf;
  1296. unsigned char data[32];
  1297. dns_name_t *keyname;
  1298. dns_rdata_t rdata = DNS_RDATA_INIT;
  1299. isc_stdtime_t now;
  1300. isc_result_t ret;
  1301. dns_tsigkey_t *tsigkey;
  1302. dst_key_t *key = NULL;
  1303. unsigned char header[DNS_MESSAGE_HEADERLEN];
  1304. isc_uint16_t addcount, id;
  1305. isc_boolean_t has_tsig = ISC_FALSE;
  1306. isc_mem_t *mctx;
  1307. REQUIRE(source != NULL);
  1308. REQUIRE(msg != NULL);
  1309. REQUIRE(dns_message_gettsigkey(msg) != NULL);
  1310. REQUIRE(msg->tcp_continuation == 1);
  1311. REQUIRE(msg->querytsig != NULL);
  1312. if (!is_response(msg))
  1313. return (DNS_R_EXPECTEDRESPONSE);
  1314. mctx = msg->mctx;
  1315. tsigkey = dns_message_gettsigkey(msg);
  1316. /*
  1317. * Extract and parse the previous TSIG
  1318. */
  1319. ret = dns_rdataset_first(msg->querytsig);
  1320. if (ret != ISC_R_SUCCESS)
  1321. return (ret);
  1322. dns_rdataset_current(msg->querytsig, &rdata);
  1323. ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
  1324. if (ret != ISC_R_SUCCESS)
  1325. return (ret);
  1326. dns_rdata_reset(&rdata);
  1327. /*
  1328. * If there is a TSIG in this message, do some checks.
  1329. */
  1330. if (msg->tsig != NULL) {
  1331. has_tsig = ISC_TRUE;
  1332. keyname = msg->tsigname;
  1333. ret = dns_rdataset_first(msg->tsig);
  1334. if (ret != ISC_R_SUCCESS)
  1335. goto cleanup_querystruct;
  1336. dns_rdataset_current(msg->tsig, &rdata);
  1337. ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
  1338. if (ret != ISC_R_SUCCESS)
  1339. goto cleanup_querystruct;
  1340. /*
  1341. * Do the key name and algorithm match that of the query?
  1342. */
  1343. if (!dns_name_equal(keyname, &tsigkey->name) ||
  1344. !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
  1345. msg->tsigstatus = dns_tsigerror_badkey;
  1346. ret = DNS_R_TSIGVERIFYFAILURE;
  1347. tsig_log(msg->tsigkey, 2,
  1348. "key name and algorithm do not match");
  1349. goto cleanup_querystruct;
  1350. }
  1351. /*
  1352. * Is the time ok?
  1353. */
  1354. isc_stdtime_get(&now);
  1355. if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
  1356. msg->tsigstatus = dns_tsigerror_badtime;
  1357. tsig_log(msg->tsigkey, 2, "signature has expired");
  1358. ret = DNS_R_CLOCKSKEW;
  1359. goto cleanup_querystruct;
  1360. } else if (now + msg->timeadjust <
  1361. tsig.timesigned - tsig.fudge) {
  1362. msg->tsigstatus = dns_tsigerror_badtime;
  1363. tsig_log(msg->tsigkey, 2,
  1364. "signature is in the future");
  1365. ret = DNS_R_CLOCKSKEW;
  1366. goto cleanup_querystruct;
  1367. }
  1368. }
  1369. key = tsigkey->key;
  1370. if (msg->tsigctx == NULL) {
  1371. ret = dst_context_create(key, mctx, &msg->tsigctx);
  1372. if (ret != ISC_R_SUCCESS)
  1373. goto cleanup_querystruct;
  1374. /*
  1375. * Digest the length of the query signature
  1376. */
  1377. isc_buffer_init(&databuf, data, sizeof(data));
  1378. isc_buffer_putuint16(&databuf, querytsig.siglen);
  1379. isc_buffer_usedregion(&databuf, &r);
  1380. ret = dst_context_adddata(msg->tsigctx, &r);
  1381. if (ret != ISC_R_SUCCESS)
  1382. goto cleanup_context;
  1383. /*
  1384. * Digest the data of the query signature
  1385. */
  1386. if (querytsig.siglen > 0) {
  1387. r.length = querytsig.siglen;
  1388. r.base = querytsig.signature;
  1389. ret = dst_context_adddata(msg->tsigctx, &r);
  1390. if (ret != ISC_R_SUCCESS)
  1391. goto cleanup_context;
  1392. }
  1393. }
  1394. /*
  1395. * Extract the header.
  1396. */
  1397. isc_buffer_usedregion(source, &r);
  1398. memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
  1399. isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
  1400. /*
  1401. * Decrement the additional field counter if necessary.
  1402. */
  1403. if (has_tsig) {
  1404. memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
  1405. addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
  1406. memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
  1407. }
  1408. /*
  1409. * Put in the original id.
  1410. */
  1411. /* XXX Can TCP transfers be forwarded? How would that work? */
  1412. if (has_tsig) {
  1413. id = htons(tsig.originalid);
  1414. memcpy(&header[0], &id, 2);
  1415. }
  1416. /*
  1417. * Digest the modified header.
  1418. */
  1419. header_r.base = (unsigned char *) header;
  1420. header_r.length = DNS_MESSAGE_HEADERLEN;
  1421. ret = dst_context_adddata(msg->tsigctx, &header_r);
  1422. if (ret != ISC_R_SUCCESS)
  1423. goto cleanup_context;
  1424. /*
  1425. * Digest all non-TSIG records.
  1426. */
  1427. isc_buffer_usedregion(source, &source_r);
  1428. r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
  1429. if (has_tsig)
  1430. r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
  1431. else
  1432. r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
  1433. ret = dst_context_adddata(msg->tsigctx, &r);
  1434. if (ret != ISC_R_SUCCESS)
  1435. goto cleanup_context;
  1436. /*
  1437. * Digest the time signed and fudge.
  1438. */
  1439. if (has_tsig) {
  1440. isc_buffer_init(&databuf, data, sizeof(data));
  1441. isc_buffer_putuint48(&databuf, tsig.timesigned);
  1442. isc_buffer_putuint16(&databuf, tsig.fudge);
  1443. isc_buffer_usedregion(&databuf, &r);
  1444. ret = dst_context_adddata(msg->tsigctx, &r);
  1445. if (ret != ISC_R_SUCCESS)
  1446. goto cleanup_context;
  1447. sig_r.base = tsig.signature;
  1448. sig_r.length = tsig.siglen;
  1449. if (tsig.siglen == 0) {
  1450. if (tsig.error != dns_rcode_noerror) {
  1451. if (tsig.error == dns_tsigerror_badtime)
  1452. ret = DNS_R_CLOCKSKEW;
  1453. else
  1454. ret = DNS_R_TSIGERRORSET;
  1455. } else {
  1456. tsig_log(msg->tsigkey, 2,
  1457. "signature is empty");
  1458. ret = DNS_R_TSIGVERIFYFAILURE;
  1459. }
  1460. goto cleanup_context;
  1461. }
  1462. ret = dst_context_verify(msg->tsigctx, &sig_r);
  1463. if (ret == DST_R_VERIFYFAILURE) {
  1464. msg->tsigstatus = dns_tsigerror_badsig;
  1465. tsig_log(msg->tsigkey, 2,
  1466. "signature failed to verify(2)");
  1467. ret = DNS_R_TSIGVERIFYFAILURE;
  1468. goto cleanup_context;
  1469. }
  1470. else if (ret != ISC_R_SUCCESS)
  1471. goto cleanup_context;
  1472. dst_context_destroy(&msg->tsigctx);
  1473. }
  1474. msg->tsigstatus = dns_rcode_noerror;
  1475. return (ISC_R_SUCCESS);
  1476. cleanup_context:
  1477. dst_context_destroy(&msg->tsigctx);
  1478. cleanup_querystruct:
  1479. dns_rdata_freestruct(&querytsig);
  1480. return (ret);
  1481. }
  1482. isc_result_t
  1483. dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
  1484. dns_name_t *algorithm, dns_tsig_keyring_t *ring)
  1485. {
  1486. dns_tsigkey_t *key;
  1487. isc_stdtime_t now;
  1488. isc_result_t result;
  1489. REQUIRE(tsigkey != NULL);
  1490. REQUIRE(*tsigkey == NULL);
  1491. REQUIRE(name != NULL);
  1492. REQUIRE(ring != NULL);
  1493. RWLOCK(&ring->lock, isc_rwlocktype_write);
  1494. cleanup_ring(ring);
  1495. RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  1496. isc_stdtime_get(&now);
  1497. RWLOCK(&ring->lock, isc_rwlocktype_read);
  1498. key = NULL;
  1499. result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
  1500. if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
  1501. RWUNLOCK(&ring->lock, isc_rwlocktype_read);
  1502. return (ISC_R_NOTFOUND);
  1503. }
  1504. if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
  1505. RWUNLOCK(&ring->lock, isc_rwlocktype_read);
  1506. return (ISC_R_NOTFOUND);
  1507. }
  1508. if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
  1509. /*
  1510. * The key has expired.
  1511. */
  1512. RWUNLOCK(&ring->lock, isc_rwlocktype_read);
  1513. RWLOCK(&ring->lock, isc_rwlocktype_write);
  1514. remove_fromring(key);
  1515. RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  1516. return (ISC_R_NOTFOUND);
  1517. }
  1518. #if 0
  1519. /*
  1520. * MPAXXX We really should look at the inception time.
  1521. */
  1522. if (key->inception != key->expire &&
  1523. isc_serial_lt(key->inception, now)) {
  1524. RWUNLOCK(&ring->lock, isc_rwlocktype_read);
  1525. adjust_lru(key);
  1526. return (ISC_R_NOTFOUND);
  1527. }
  1528. #endif
  1529. isc_refcount_increment(&key->refs, NULL);
  1530. RWUNLOCK(&ring->lock, isc_rwlocktype_read);
  1531. adjust_lru(key);
  1532. *tsigkey = key;
  1533. return (ISC_R_SUCCESS);
  1534. }
  1535. static void
  1536. free_tsignode(void *node, void *_unused) {
  1537. dns_tsigkey_t *key;
  1538. UNUSED(_unused);
  1539. REQUIRE(node != NULL);
  1540. key = node;
  1541. dns_tsigkey_detach(&key);
  1542. }
  1543. isc_result_t
  1544. dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
  1545. isc_result_t result;
  1546. dns_tsig_keyring_t *ring;
  1547. REQUIRE(mctx != NULL);
  1548. REQUIRE(ringp != NULL);
  1549. REQUIRE(*ringp == NULL);
  1550. ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
  1551. if (ring == NULL)
  1552. return (ISC_R_NOMEMORY);
  1553. result = isc_rwlock_init(&ring->lock, 0, 0);
  1554. if (result != ISC_R_SUCCESS) {
  1555. isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
  1556. return (result);
  1557. }
  1558. ring->keys = NULL;
  1559. result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
  1560. if (result != ISC_R_SUCCESS) {
  1561. isc_rwlock_destroy(&ring->lock);
  1562. isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
  1563. return (result);
  1564. }
  1565. ring->writecount = 0;
  1566. ring->mctx = NULL;
  1567. ring->generated = 0;
  1568. ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
  1569. ISC_LIST_INIT(ring->lru);
  1570. isc_mem_attach(mctx, &ring->mctx);
  1571. ring->references = 1;
  1572. *ringp = ring;
  1573. return (ISC_R_SUCCESS);
  1574. }
  1575. isc_result_t
  1576. dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
  1577. dns_tsigkey_t *tkey)
  1578. {
  1579. isc_result_t result;
  1580. result = keyring_add(ring, name, tkey);
  1581. if (result == ISC_R_SUCCESS)
  1582. isc_refcount_increment(&tkey->refs, NULL);
  1583. return (result);
  1584. }
  1585. void
  1586. dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
  1587. {
  1588. REQUIRE(source != NULL);
  1589. REQUIRE(target != NULL && *target == NULL);
  1590. RWLOCK(&source->lock, isc_rwlocktype_write);
  1591. INSIST(source->references > 0);
  1592. source->references++;
  1593. INSIST(source->references > 0);
  1594. *target = source;
  1595. RWUNLOCK(&source->lock, isc_rwlocktype_write);
  1596. }
  1597. void
  1598. dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
  1599. dns_tsig_keyring_t *ring;
  1600. unsigned int references;
  1601. REQUIRE(ringp != NULL);
  1602. REQUIRE(*ringp != NULL);
  1603. ring = *ringp;
  1604. *ringp = NULL;
  1605. RWLOCK(&ring->lock, isc_rwlocktype_write);
  1606. INSIST(ring->references > 0);
  1607. ring->references--;
  1608. references = ring->references;
  1609. RWUNLOCK(&ring->lock, isc_rwlocktype_write);
  1610. if (references == 0)
  1611. destroyring(ring);
  1612. }
  1613. void
  1614. dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
  1615. isc_stdtime_t now;
  1616. isc_result_t result;
  1617. isc_stdtime_get(&now);
  1618. do {
  1619. result = restore_key(ring, now, fp);
  1620. if (result == ISC_R_NOMORE)
  1621. return;
  1622. if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
  1623. result = ISC_R_SUCCESS;
  1624. } while (result == ISC_R_SUCCESS);
  1625. }