/contrib/bind9/lib/dns/tkey.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1455 lines · 1130 code · 210 blank · 115 comment · 291 complexity · 5cc7df35bf707573f7502b345fa2a265 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2001, 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 <isc/buffer.h>
  23. #include <isc/entropy.h>
  24. #include <isc/md5.h>
  25. #include <isc/mem.h>
  26. #include <isc/string.h>
  27. #include <isc/util.h>
  28. #include <dns/dnssec.h>
  29. #include <dns/fixedname.h>
  30. #include <dns/keyvalues.h>
  31. #include <dns/log.h>
  32. #include <dns/message.h>
  33. #include <dns/name.h>
  34. #include <dns/rdata.h>
  35. #include <dns/rdatalist.h>
  36. #include <dns/rdataset.h>
  37. #include <dns/rdatastruct.h>
  38. #include <dns/result.h>
  39. #include <dns/tkey.h>
  40. #include <dns/tsig.h>
  41. #include <dst/dst.h>
  42. #include <dst/gssapi.h>
  43. #define TKEY_RANDOM_AMOUNT 16
  44. #define RETERR(x) do { \
  45. result = (x); \
  46. if (result != ISC_R_SUCCESS) \
  47. goto failure; \
  48. } while (0)
  49. static void
  50. tkey_log(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2);
  51. static void
  52. tkey_log(const char *fmt, ...) {
  53. va_list ap;
  54. va_start(ap, fmt);
  55. isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
  56. DNS_LOGMODULE_REQUEST, ISC_LOG_DEBUG(4), fmt, ap);
  57. va_end(ap);
  58. }
  59. static void
  60. _dns_tkey_dumpmessage(dns_message_t *msg) {
  61. isc_buffer_t outbuf;
  62. unsigned char output[4096];
  63. isc_result_t result;
  64. isc_buffer_init(&outbuf, output, sizeof(output));
  65. result = dns_message_totext(msg, &dns_master_style_debug, 0,
  66. &outbuf);
  67. if (result != ISC_R_SUCCESS)
  68. fprintf(stderr, "Warning: dns_message_totext returned: %s\n",
  69. dns_result_totext(result));
  70. fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&outbuf),
  71. (char *)isc_buffer_base(&outbuf));
  72. }
  73. isc_result_t
  74. dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
  75. {
  76. dns_tkeyctx_t *tctx;
  77. REQUIRE(mctx != NULL);
  78. REQUIRE(ectx != NULL);
  79. REQUIRE(tctxp != NULL && *tctxp == NULL);
  80. tctx = isc_mem_get(mctx, sizeof(dns_tkeyctx_t));
  81. if (tctx == NULL)
  82. return (ISC_R_NOMEMORY);
  83. tctx->mctx = NULL;
  84. isc_mem_attach(mctx, &tctx->mctx);
  85. tctx->ectx = NULL;
  86. isc_entropy_attach(ectx, &tctx->ectx);
  87. tctx->dhkey = NULL;
  88. tctx->domain = NULL;
  89. tctx->gsscred = NULL;
  90. tctx->gssapi_keytab = NULL;
  91. *tctxp = tctx;
  92. return (ISC_R_SUCCESS);
  93. }
  94. void
  95. dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
  96. isc_mem_t *mctx;
  97. dns_tkeyctx_t *tctx;
  98. REQUIRE(tctxp != NULL && *tctxp != NULL);
  99. tctx = *tctxp;
  100. mctx = tctx->mctx;
  101. if (tctx->dhkey != NULL)
  102. dst_key_free(&tctx->dhkey);
  103. if (tctx->domain != NULL) {
  104. if (dns_name_dynamic(tctx->domain))
  105. dns_name_free(tctx->domain, mctx);
  106. isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
  107. }
  108. if (tctx->gssapi_keytab != NULL) {
  109. isc_mem_free(mctx, tctx->gssapi_keytab);
  110. }
  111. if (tctx->gsscred != NULL)
  112. dst_gssapi_releasecred(&tctx->gsscred);
  113. isc_entropy_detach(&tctx->ectx);
  114. isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
  115. isc_mem_detach(&mctx);
  116. *tctxp = NULL;
  117. }
  118. static isc_result_t
  119. add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
  120. isc_uint32_t ttl, dns_namelist_t *namelist)
  121. {
  122. isc_result_t result;
  123. isc_region_t r, newr;
  124. dns_rdata_t *newrdata = NULL;
  125. dns_name_t *newname = NULL;
  126. dns_rdatalist_t *newlist = NULL;
  127. dns_rdataset_t *newset = NULL;
  128. isc_buffer_t *tmprdatabuf = NULL;
  129. RETERR(dns_message_gettemprdata(msg, &newrdata));
  130. dns_rdata_toregion(rdata, &r);
  131. RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length));
  132. isc_buffer_availableregion(tmprdatabuf, &newr);
  133. memcpy(newr.base, r.base, r.length);
  134. dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
  135. dns_message_takebuffer(msg, &tmprdatabuf);
  136. RETERR(dns_message_gettempname(msg, &newname));
  137. dns_name_init(newname, NULL);
  138. RETERR(dns_name_dup(name, msg->mctx, newname));
  139. RETERR(dns_message_gettemprdatalist(msg, &newlist));
  140. newlist->rdclass = newrdata->rdclass;
  141. newlist->type = newrdata->type;
  142. newlist->covers = 0;
  143. newlist->ttl = ttl;
  144. ISC_LIST_INIT(newlist->rdata);
  145. ISC_LIST_APPEND(newlist->rdata, newrdata, link);
  146. RETERR(dns_message_gettemprdataset(msg, &newset));
  147. dns_rdataset_init(newset);
  148. RETERR(dns_rdatalist_tordataset(newlist, newset));
  149. ISC_LIST_INIT(newname->list);
  150. ISC_LIST_APPEND(newname->list, newset, link);
  151. ISC_LIST_APPEND(*namelist, newname, link);
  152. return (ISC_R_SUCCESS);
  153. failure:
  154. if (newrdata != NULL) {
  155. if (ISC_LINK_LINKED(newrdata, link)) {
  156. INSIST(newlist != NULL);
  157. ISC_LIST_UNLINK(newlist->rdata, newrdata, link);
  158. }
  159. dns_message_puttemprdata(msg, &newrdata);
  160. }
  161. if (newname != NULL)
  162. dns_message_puttempname(msg, &newname);
  163. if (newset != NULL) {
  164. dns_rdataset_disassociate(newset);
  165. dns_message_puttemprdataset(msg, &newset);
  166. }
  167. if (newlist != NULL)
  168. dns_message_puttemprdatalist(msg, &newlist);
  169. return (result);
  170. }
  171. static void
  172. free_namelist(dns_message_t *msg, dns_namelist_t *namelist) {
  173. dns_name_t *name;
  174. dns_rdataset_t *set;
  175. while (!ISC_LIST_EMPTY(*namelist)) {
  176. name = ISC_LIST_HEAD(*namelist);
  177. ISC_LIST_UNLINK(*namelist, name, link);
  178. while (!ISC_LIST_EMPTY(name->list)) {
  179. set = ISC_LIST_HEAD(name->list);
  180. ISC_LIST_UNLINK(name->list, set, link);
  181. dns_message_puttemprdataset(msg, &set);
  182. }
  183. dns_message_puttempname(msg, &name);
  184. }
  185. }
  186. static isc_result_t
  187. compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness,
  188. isc_region_t *serverrandomness, isc_buffer_t *secret)
  189. {
  190. isc_md5_t md5ctx;
  191. isc_region_t r, r2;
  192. unsigned char digests[32];
  193. unsigned int i;
  194. isc_buffer_usedregion(shared, &r);
  195. /*
  196. * MD5 ( query data | DH value ).
  197. */
  198. isc_md5_init(&md5ctx);
  199. isc_md5_update(&md5ctx, queryrandomness->base,
  200. queryrandomness->length);
  201. isc_md5_update(&md5ctx, r.base, r.length);
  202. isc_md5_final(&md5ctx, digests);
  203. /*
  204. * MD5 ( server data | DH value ).
  205. */
  206. isc_md5_init(&md5ctx);
  207. isc_md5_update(&md5ctx, serverrandomness->base,
  208. serverrandomness->length);
  209. isc_md5_update(&md5ctx, r.base, r.length);
  210. isc_md5_final(&md5ctx, &digests[ISC_MD5_DIGESTLENGTH]);
  211. /*
  212. * XOR ( DH value, MD5-1 | MD5-2).
  213. */
  214. isc_buffer_availableregion(secret, &r);
  215. isc_buffer_usedregion(shared, &r2);
  216. if (r.length < sizeof(digests) || r.length < r2.length)
  217. return (ISC_R_NOSPACE);
  218. if (r2.length > sizeof(digests)) {
  219. memcpy(r.base, r2.base, r2.length);
  220. for (i = 0; i < sizeof(digests); i++)
  221. r.base[i] ^= digests[i];
  222. isc_buffer_add(secret, r2.length);
  223. } else {
  224. memcpy(r.base, digests, sizeof(digests));
  225. for (i = 0; i < r2.length; i++)
  226. r.base[i] ^= r2.base[i];
  227. isc_buffer_add(secret, sizeof(digests));
  228. }
  229. return (ISC_R_SUCCESS);
  230. }
  231. static isc_result_t
  232. process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
  233. dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
  234. dns_rdata_tkey_t *tkeyout,
  235. dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
  236. {
  237. isc_result_t result = ISC_R_SUCCESS;
  238. dns_name_t *keyname, ourname;
  239. dns_rdataset_t *keyset = NULL;
  240. dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT;
  241. isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
  242. dst_key_t *pubkey = NULL;
  243. isc_buffer_t ourkeybuf, *shared = NULL;
  244. isc_region_t r, r2, ourkeyr;
  245. unsigned char keydata[DST_KEY_MAXSIZE];
  246. unsigned int sharedsize;
  247. isc_buffer_t secret;
  248. unsigned char *randomdata = NULL, secretdata[256];
  249. dns_ttl_t ttl = 0;
  250. if (tctx->dhkey == NULL) {
  251. tkey_log("process_dhtkey: tkey-dhkey not defined");
  252. tkeyout->error = dns_tsigerror_badalg;
  253. return (DNS_R_REFUSED);
  254. }
  255. if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) {
  256. tkey_log("process_dhtkey: algorithms other than "
  257. "hmac-md5 are not supported");
  258. tkeyout->error = dns_tsigerror_badalg;
  259. return (ISC_R_SUCCESS);
  260. }
  261. /*
  262. * Look for a DH KEY record that will work with ours.
  263. */
  264. for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
  265. result == ISC_R_SUCCESS && !found_key;
  266. result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
  267. keyname = NULL;
  268. dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
  269. keyset = NULL;
  270. result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
  271. &keyset);
  272. if (result != ISC_R_SUCCESS)
  273. continue;
  274. for (result = dns_rdataset_first(keyset);
  275. result == ISC_R_SUCCESS && !found_key;
  276. result = dns_rdataset_next(keyset)) {
  277. dns_rdataset_current(keyset, &keyrdata);
  278. pubkey = NULL;
  279. result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
  280. msg->mctx, &pubkey);
  281. if (result != ISC_R_SUCCESS) {
  282. dns_rdata_reset(&keyrdata);
  283. continue;
  284. }
  285. if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
  286. if (dst_key_paramcompare(pubkey, tctx->dhkey))
  287. {
  288. found_key = ISC_TRUE;
  289. ttl = keyset->ttl;
  290. break;
  291. } else
  292. found_incompatible = ISC_TRUE;
  293. }
  294. dst_key_free(&pubkey);
  295. dns_rdata_reset(&keyrdata);
  296. }
  297. }
  298. if (!found_key) {
  299. if (found_incompatible) {
  300. tkey_log("process_dhtkey: found an incompatible key");
  301. tkeyout->error = dns_tsigerror_badkey;
  302. return (ISC_R_SUCCESS);
  303. } else {
  304. tkey_log("process_dhtkey: failed to find a key");
  305. return (DNS_R_FORMERR);
  306. }
  307. }
  308. RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist));
  309. isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata));
  310. RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
  311. isc_buffer_usedregion(&ourkeybuf, &ourkeyr);
  312. dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any,
  313. dns_rdatatype_key, &ourkeyr);
  314. dns_name_init(&ourname, NULL);
  315. dns_name_clone(dst_key_name(tctx->dhkey), &ourname);
  316. /*
  317. * XXXBEW The TTL should be obtained from the database, if it exists.
  318. */
  319. RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist));
  320. RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize));
  321. RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize));
  322. result = dst_key_computesecret(pubkey, tctx->dhkey, shared);
  323. if (result != ISC_R_SUCCESS) {
  324. tkey_log("process_dhtkey: failed to compute shared secret: %s",
  325. isc_result_totext(result));
  326. goto failure;
  327. }
  328. dst_key_free(&pubkey);
  329. isc_buffer_init(&secret, secretdata, sizeof(secretdata));
  330. randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT);
  331. if (randomdata == NULL)
  332. goto failure;
  333. result = isc_entropy_getdata(tctx->ectx, randomdata,
  334. TKEY_RANDOM_AMOUNT, NULL, 0);
  335. if (result != ISC_R_SUCCESS) {
  336. tkey_log("process_dhtkey: failed to obtain entropy: %s",
  337. isc_result_totext(result));
  338. goto failure;
  339. }
  340. r.base = randomdata;
  341. r.length = TKEY_RANDOM_AMOUNT;
  342. r2.base = tkeyin->key;
  343. r2.length = tkeyin->keylen;
  344. RETERR(compute_secret(shared, &r2, &r, &secret));
  345. isc_buffer_free(&shared);
  346. RETERR(dns_tsigkey_create(name, &tkeyin->algorithm,
  347. isc_buffer_base(&secret),
  348. isc_buffer_usedlength(&secret),
  349. ISC_TRUE, signer, tkeyin->inception,
  350. tkeyin->expire, ring->mctx, ring, NULL));
  351. /* This key is good for a long time */
  352. tkeyout->inception = tkeyin->inception;
  353. tkeyout->expire = tkeyin->expire;
  354. tkeyout->key = randomdata;
  355. tkeyout->keylen = TKEY_RANDOM_AMOUNT;
  356. return (ISC_R_SUCCESS);
  357. failure:
  358. if (!ISC_LIST_EMPTY(*namelist))
  359. free_namelist(msg, namelist);
  360. if (shared != NULL)
  361. isc_buffer_free(&shared);
  362. if (pubkey != NULL)
  363. dst_key_free(&pubkey);
  364. if (randomdata != NULL)
  365. isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT);
  366. return (result);
  367. }
  368. static isc_result_t
  369. process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
  370. dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
  371. dns_tsig_keyring_t *ring)
  372. {
  373. isc_result_t result = ISC_R_SUCCESS;
  374. dst_key_t *dstkey = NULL;
  375. dns_tsigkey_t *tsigkey = NULL;
  376. dns_fixedname_t principal;
  377. isc_stdtime_t now;
  378. isc_region_t intoken;
  379. isc_buffer_t *outtoken = NULL;
  380. gss_ctx_id_t gss_ctx = NULL;
  381. /*
  382. * You have to define either a gss credential (principal) to
  383. * accept with tkey-gssapi-credential, or you have to
  384. * configure a specific keytab (with tkey-gssapi-keytab) in
  385. * order to use gsstkey
  386. */
  387. if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
  388. tkey_log("process_gsstkey(): no tkey-gssapi-credential "
  389. "or tkey-gssapi-keytab configured");
  390. return (ISC_R_NOPERM);
  391. }
  392. if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
  393. !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
  394. tkeyout->error = dns_tsigerror_badalg;
  395. tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
  396. return (ISC_R_SUCCESS);
  397. }
  398. /*
  399. * XXXDCL need to check for key expiry per 4.1.1
  400. * XXXDCL need a way to check fully established, perhaps w/key_flags
  401. */
  402. intoken.base = tkeyin->key;
  403. intoken.length = tkeyin->keylen;
  404. result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
  405. if (result == ISC_R_SUCCESS)
  406. gss_ctx = dst_key_getgssctx(tsigkey->key);
  407. dns_fixedname_init(&principal);
  408. /*
  409. * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
  410. */
  411. result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
  412. &intoken,
  413. &outtoken, &gss_ctx,
  414. dns_fixedname_name(&principal),
  415. tctx->mctx);
  416. if (result == DNS_R_INVALIDTKEY) {
  417. if (tsigkey != NULL)
  418. dns_tsigkey_detach(&tsigkey);
  419. tkeyout->error = dns_tsigerror_badkey;
  420. tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
  421. return (ISC_R_SUCCESS);
  422. }
  423. if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
  424. goto failure;
  425. /*
  426. * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
  427. */
  428. isc_stdtime_get(&now);
  429. if (tsigkey == NULL) {
  430. #ifdef GSSAPI
  431. OM_uint32 gret, minor, lifetime;
  432. #endif
  433. isc_uint32_t expire;
  434. RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx,
  435. &dstkey, &intoken));
  436. /*
  437. * Limit keys to 1 hour or the context's lifetime whichever
  438. * is smaller.
  439. */
  440. expire = now + 3600;
  441. #ifdef GSSAPI
  442. gret = gss_context_time(&minor, gss_ctx, &lifetime);
  443. if (gret == GSS_S_COMPLETE && now + lifetime < expire)
  444. expire = now + lifetime;
  445. #endif
  446. RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
  447. dstkey, ISC_TRUE,
  448. dns_fixedname_name(&principal),
  449. now, expire, ring->mctx, ring,
  450. NULL));
  451. dst_key_free(&dstkey);
  452. tkeyout->inception = now;
  453. tkeyout->expire = expire;
  454. } else {
  455. tkeyout->inception = tsigkey->inception;
  456. tkeyout->expire = tsigkey->expire;
  457. dns_tsigkey_detach(&tsigkey);
  458. }
  459. if (outtoken) {
  460. tkeyout->key = isc_mem_get(tkeyout->mctx,
  461. isc_buffer_usedlength(outtoken));
  462. if (tkeyout->key == NULL) {
  463. result = ISC_R_NOMEMORY;
  464. goto failure;
  465. }
  466. tkeyout->keylen = isc_buffer_usedlength(outtoken);
  467. memcpy(tkeyout->key, isc_buffer_base(outtoken),
  468. isc_buffer_usedlength(outtoken));
  469. isc_buffer_free(&outtoken);
  470. } else {
  471. tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
  472. if (tkeyout->key == NULL) {
  473. result = ISC_R_NOMEMORY;
  474. goto failure;
  475. }
  476. tkeyout->keylen = tkeyin->keylen;
  477. memcpy(tkeyout->key, tkeyin->key, tkeyin->keylen);
  478. }
  479. tkeyout->error = dns_rcode_noerror;
  480. tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
  481. return (ISC_R_SUCCESS);
  482. failure:
  483. if (tsigkey != NULL)
  484. dns_tsigkey_detach(&tsigkey);
  485. if (dstkey != NULL)
  486. dst_key_free(&dstkey);
  487. if (outtoken != NULL)
  488. isc_buffer_free(&outtoken);
  489. tkey_log("process_gsstkey(): %s",
  490. isc_result_totext(result)); /* XXXSRA */
  491. return (result);
  492. }
  493. static isc_result_t
  494. process_deletetkey(dns_name_t *signer, dns_name_t *name,
  495. dns_rdata_tkey_t *tkeyin, dns_rdata_tkey_t *tkeyout,
  496. dns_tsig_keyring_t *ring)
  497. {
  498. isc_result_t result;
  499. dns_tsigkey_t *tsigkey = NULL;
  500. dns_name_t *identity;
  501. result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
  502. if (result != ISC_R_SUCCESS) {
  503. tkeyout->error = dns_tsigerror_badname;
  504. return (ISC_R_SUCCESS);
  505. }
  506. /*
  507. * Only allow a delete if the identity that created the key is the
  508. * same as the identity that signed the message.
  509. */
  510. identity = dns_tsigkey_identity(tsigkey);
  511. if (identity == NULL || !dns_name_equal(identity, signer)) {
  512. dns_tsigkey_detach(&tsigkey);
  513. return (DNS_R_REFUSED);
  514. }
  515. /*
  516. * Set the key to be deleted when no references are left. If the key
  517. * was not generated with TKEY and is in the config file, it may be
  518. * reloaded later.
  519. */
  520. dns_tsigkey_setdeleted(tsigkey);
  521. /* Release the reference */
  522. dns_tsigkey_detach(&tsigkey);
  523. return (ISC_R_SUCCESS);
  524. }
  525. isc_result_t
  526. dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
  527. dns_tsig_keyring_t *ring)
  528. {
  529. isc_result_t result = ISC_R_SUCCESS;
  530. dns_rdata_tkey_t tkeyin, tkeyout;
  531. isc_boolean_t freetkeyin = ISC_FALSE;
  532. dns_name_t *qname, *name, *keyname, *signer, tsigner;
  533. dns_fixedname_t fkeyname;
  534. dns_rdataset_t *tkeyset;
  535. dns_rdata_t rdata;
  536. dns_namelist_t namelist;
  537. char tkeyoutdata[512];
  538. isc_buffer_t tkeyoutbuf;
  539. REQUIRE(msg != NULL);
  540. REQUIRE(tctx != NULL);
  541. REQUIRE(ring != NULL);
  542. ISC_LIST_INIT(namelist);
  543. /*
  544. * Interpret the question section.
  545. */
  546. result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
  547. if (result != ISC_R_SUCCESS)
  548. return (DNS_R_FORMERR);
  549. qname = NULL;
  550. dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname);
  551. /*
  552. * Look for a TKEY record that matches the question.
  553. */
  554. tkeyset = NULL;
  555. name = NULL;
  556. result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname,
  557. dns_rdatatype_tkey, 0, &name, &tkeyset);
  558. if (result != ISC_R_SUCCESS) {
  559. /*
  560. * Try the answer section, since that's where Win2000
  561. * puts it.
  562. */
  563. if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
  564. dns_rdatatype_tkey, 0, &name,
  565. &tkeyset) != ISC_R_SUCCESS) {
  566. result = DNS_R_FORMERR;
  567. tkey_log("dns_tkey_processquery: couldn't find a TKEY "
  568. "matching the question");
  569. goto failure;
  570. }
  571. }
  572. result = dns_rdataset_first(tkeyset);
  573. if (result != ISC_R_SUCCESS) {
  574. result = DNS_R_FORMERR;
  575. goto failure;
  576. }
  577. dns_rdata_init(&rdata);
  578. dns_rdataset_current(tkeyset, &rdata);
  579. RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL));
  580. freetkeyin = ISC_TRUE;
  581. if (tkeyin.error != dns_rcode_noerror) {
  582. result = DNS_R_FORMERR;
  583. goto failure;
  584. }
  585. /*
  586. * Before we go any farther, verify that the message was signed.
  587. * GSSAPI TKEY doesn't require a signature, the rest do.
  588. */
  589. dns_name_init(&tsigner, NULL);
  590. result = dns_message_signer(msg, &tsigner);
  591. if (result != ISC_R_SUCCESS) {
  592. if (tkeyin.mode == DNS_TKEYMODE_GSSAPI &&
  593. result == ISC_R_NOTFOUND)
  594. signer = NULL;
  595. else {
  596. tkey_log("dns_tkey_processquery: query was not "
  597. "properly signed - rejecting");
  598. result = DNS_R_FORMERR;
  599. goto failure;
  600. }
  601. } else
  602. signer = &tsigner;
  603. tkeyout.common.rdclass = tkeyin.common.rdclass;
  604. tkeyout.common.rdtype = tkeyin.common.rdtype;
  605. ISC_LINK_INIT(&tkeyout.common, link);
  606. tkeyout.mctx = msg->mctx;
  607. dns_name_init(&tkeyout.algorithm, NULL);
  608. dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm);
  609. tkeyout.inception = tkeyout.expire = 0;
  610. tkeyout.mode = tkeyin.mode;
  611. tkeyout.error = 0;
  612. tkeyout.keylen = tkeyout.otherlen = 0;
  613. tkeyout.key = tkeyout.other = NULL;
  614. /*
  615. * A delete operation must have a fully specified key name. If this
  616. * is not a delete, we do the following:
  617. * if (qname != ".")
  618. * keyname = qname + defaultdomain
  619. * else
  620. * keyname = <random hex> + defaultdomain
  621. */
  622. if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
  623. dns_tsigkey_t *tsigkey = NULL;
  624. if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
  625. tkey_log("dns_tkey_processquery: tkey-domain not set");
  626. result = DNS_R_REFUSED;
  627. goto failure;
  628. }
  629. dns_fixedname_init(&fkeyname);
  630. keyname = dns_fixedname_name(&fkeyname);
  631. if (!dns_name_equal(qname, dns_rootname)) {
  632. unsigned int n = dns_name_countlabels(qname);
  633. RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL)
  634. == ISC_R_SUCCESS);
  635. dns_name_getlabelsequence(keyname, 0, n - 1, keyname);
  636. } else {
  637. static char hexdigits[16] = {
  638. '0', '1', '2', '3', '4', '5', '6', '7',
  639. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  640. unsigned char randomdata[16];
  641. char randomtext[32];
  642. isc_buffer_t b;
  643. unsigned int i, j;
  644. result = isc_entropy_getdata(tctx->ectx,
  645. randomdata,
  646. sizeof(randomdata),
  647. NULL, 0);
  648. if (result != ISC_R_SUCCESS)
  649. goto failure;
  650. for (i = 0, j = 0; i < sizeof(randomdata); i++) {
  651. unsigned char val = randomdata[i];
  652. randomtext[j++] = hexdigits[val >> 4];
  653. randomtext[j++] = hexdigits[val & 0xF];
  654. }
  655. isc_buffer_init(&b, randomtext, sizeof(randomtext));
  656. isc_buffer_add(&b, sizeof(randomtext));
  657. result = dns_name_fromtext(keyname, &b, NULL, 0, NULL);
  658. if (result != ISC_R_SUCCESS)
  659. goto failure;
  660. }
  661. if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
  662. /* Yup. This is a hack */
  663. result = dns_name_concatenate(keyname, dns_rootname,
  664. keyname, NULL);
  665. if (result != ISC_R_SUCCESS)
  666. goto failure;
  667. } else {
  668. result = dns_name_concatenate(keyname, tctx->domain,
  669. keyname, NULL);
  670. if (result != ISC_R_SUCCESS)
  671. goto failure;
  672. }
  673. result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
  674. if (result == ISC_R_SUCCESS) {
  675. tkeyout.error = dns_tsigerror_badname;
  676. dns_tsigkey_detach(&tsigkey);
  677. goto failure_with_tkey;
  678. } else if (result != ISC_R_NOTFOUND)
  679. goto failure;
  680. } else
  681. keyname = qname;
  682. switch (tkeyin.mode) {
  683. case DNS_TKEYMODE_DIFFIEHELLMAN:
  684. tkeyout.error = dns_rcode_noerror;
  685. RETERR(process_dhtkey(msg, signer, keyname, &tkeyin,
  686. tctx, &tkeyout, ring,
  687. &namelist));
  688. break;
  689. case DNS_TKEYMODE_GSSAPI:
  690. tkeyout.error = dns_rcode_noerror;
  691. RETERR(process_gsstkey(keyname, &tkeyin, tctx,
  692. &tkeyout, ring));
  693. break;
  694. case DNS_TKEYMODE_DELETE:
  695. tkeyout.error = dns_rcode_noerror;
  696. RETERR(process_deletetkey(signer, keyname, &tkeyin,
  697. &tkeyout, ring));
  698. break;
  699. case DNS_TKEYMODE_SERVERASSIGNED:
  700. case DNS_TKEYMODE_RESOLVERASSIGNED:
  701. result = DNS_R_NOTIMP;
  702. goto failure;
  703. default:
  704. tkeyout.error = dns_tsigerror_badmode;
  705. }
  706. failure_with_tkey:
  707. dns_rdata_init(&rdata);
  708. isc_buffer_init(&tkeyoutbuf, tkeyoutdata, sizeof(tkeyoutdata));
  709. result = dns_rdata_fromstruct(&rdata, tkeyout.common.rdclass,
  710. tkeyout.common.rdtype, &tkeyout,
  711. &tkeyoutbuf);
  712. if (freetkeyin) {
  713. dns_rdata_freestruct(&tkeyin);
  714. freetkeyin = ISC_FALSE;
  715. }
  716. if (tkeyout.key != NULL)
  717. isc_mem_put(tkeyout.mctx, tkeyout.key, tkeyout.keylen);
  718. if (tkeyout.other != NULL)
  719. isc_mem_put(tkeyout.mctx, tkeyout.other, tkeyout.otherlen);
  720. if (result != ISC_R_SUCCESS)
  721. goto failure;
  722. RETERR(add_rdata_to_list(msg, keyname, &rdata, 0, &namelist));
  723. RETERR(dns_message_reply(msg, ISC_TRUE));
  724. name = ISC_LIST_HEAD(namelist);
  725. while (name != NULL) {
  726. dns_name_t *next = ISC_LIST_NEXT(name, link);
  727. ISC_LIST_UNLINK(namelist, name, link);
  728. dns_message_addname(msg, name, DNS_SECTION_ANSWER);
  729. name = next;
  730. }
  731. return (ISC_R_SUCCESS);
  732. failure:
  733. if (freetkeyin)
  734. dns_rdata_freestruct(&tkeyin);
  735. if (!ISC_LIST_EMPTY(namelist))
  736. free_namelist(msg, &namelist);
  737. return (result);
  738. }
  739. static isc_result_t
  740. buildquery(dns_message_t *msg, dns_name_t *name,
  741. dns_rdata_tkey_t *tkey, isc_boolean_t win2k)
  742. {
  743. dns_name_t *qname = NULL, *aname = NULL;
  744. dns_rdataset_t *question = NULL, *tkeyset = NULL;
  745. dns_rdatalist_t *tkeylist = NULL;
  746. dns_rdata_t *rdata = NULL;
  747. isc_buffer_t *dynbuf = NULL;
  748. isc_result_t result;
  749. REQUIRE(msg != NULL);
  750. REQUIRE(name != NULL);
  751. REQUIRE(tkey != NULL);
  752. RETERR(dns_message_gettempname(msg, &qname));
  753. RETERR(dns_message_gettempname(msg, &aname));
  754. RETERR(dns_message_gettemprdataset(msg, &question));
  755. dns_rdataset_init(question);
  756. dns_rdataset_makequestion(question, dns_rdataclass_any,
  757. dns_rdatatype_tkey);
  758. RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 4096));
  759. RETERR(dns_message_gettemprdata(msg, &rdata));
  760. RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
  761. dns_rdatatype_tkey, tkey, dynbuf));
  762. dns_message_takebuffer(msg, &dynbuf);
  763. RETERR(dns_message_gettemprdatalist(msg, &tkeylist));
  764. tkeylist->rdclass = dns_rdataclass_any;
  765. tkeylist->type = dns_rdatatype_tkey;
  766. tkeylist->covers = 0;
  767. tkeylist->ttl = 0;
  768. ISC_LIST_INIT(tkeylist->rdata);
  769. ISC_LIST_APPEND(tkeylist->rdata, rdata, link);
  770. RETERR(dns_message_gettemprdataset(msg, &tkeyset));
  771. dns_rdataset_init(tkeyset);
  772. RETERR(dns_rdatalist_tordataset(tkeylist, tkeyset));
  773. dns_name_init(qname, NULL);
  774. dns_name_clone(name, qname);
  775. dns_name_init(aname, NULL);
  776. dns_name_clone(name, aname);
  777. ISC_LIST_APPEND(qname->list, question, link);
  778. ISC_LIST_APPEND(aname->list, tkeyset, link);
  779. dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
  780. /*
  781. * Windows 2000 needs this in the answer section, not the additional
  782. * section where the RFC specifies.
  783. */
  784. if (win2k)
  785. dns_message_addname(msg, aname, DNS_SECTION_ANSWER);
  786. else
  787. dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
  788. return (ISC_R_SUCCESS);
  789. failure:
  790. if (qname != NULL)
  791. dns_message_puttempname(msg, &qname);
  792. if (aname != NULL)
  793. dns_message_puttempname(msg, &aname);
  794. if (question != NULL) {
  795. dns_rdataset_disassociate(question);
  796. dns_message_puttemprdataset(msg, &question);
  797. }
  798. if (dynbuf != NULL)
  799. isc_buffer_free(&dynbuf);
  800. printf("buildquery error\n");
  801. return (result);
  802. }
  803. isc_result_t
  804. dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
  805. dns_name_t *algorithm, isc_buffer_t *nonce,
  806. isc_uint32_t lifetime)
  807. {
  808. dns_rdata_tkey_t tkey;
  809. dns_rdata_t *rdata = NULL;
  810. isc_buffer_t *dynbuf = NULL;
  811. isc_region_t r;
  812. dns_name_t keyname;
  813. dns_namelist_t namelist;
  814. isc_result_t result;
  815. isc_stdtime_t now;
  816. REQUIRE(msg != NULL);
  817. REQUIRE(key != NULL);
  818. REQUIRE(dst_key_alg(key) == DNS_KEYALG_DH);
  819. REQUIRE(dst_key_isprivate(key));
  820. REQUIRE(name != NULL);
  821. REQUIRE(algorithm != NULL);
  822. tkey.common.rdclass = dns_rdataclass_any;
  823. tkey.common.rdtype = dns_rdatatype_tkey;
  824. ISC_LINK_INIT(&tkey.common, link);
  825. tkey.mctx = msg->mctx;
  826. dns_name_init(&tkey.algorithm, NULL);
  827. dns_name_clone(algorithm, &tkey.algorithm);
  828. isc_stdtime_get(&now);
  829. tkey.inception = now;
  830. tkey.expire = now + lifetime;
  831. tkey.mode = DNS_TKEYMODE_DIFFIEHELLMAN;
  832. if (nonce != NULL)
  833. isc_buffer_usedregion(nonce, &r);
  834. else {
  835. r.base = isc_mem_get(msg->mctx, 0);
  836. r.length = 0;
  837. }
  838. tkey.error = 0;
  839. tkey.key = r.base;
  840. tkey.keylen = r.length;
  841. tkey.other = NULL;
  842. tkey.otherlen = 0;
  843. RETERR(buildquery(msg, name, &tkey, ISC_FALSE));
  844. if (nonce == NULL)
  845. isc_mem_put(msg->mctx, r.base, 0);
  846. RETERR(dns_message_gettemprdata(msg, &rdata));
  847. RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
  848. RETERR(dst_key_todns(key, dynbuf));
  849. isc_buffer_usedregion(dynbuf, &r);
  850. dns_rdata_fromregion(rdata, dns_rdataclass_any,
  851. dns_rdatatype_key, &r);
  852. dns_message_takebuffer(msg, &dynbuf);
  853. dns_name_init(&keyname, NULL);
  854. dns_name_clone(dst_key_name(key), &keyname);
  855. ISC_LIST_INIT(namelist);
  856. RETERR(add_rdata_to_list(msg, &keyname, rdata, 0, &namelist));
  857. dns_message_addname(msg, ISC_LIST_HEAD(namelist),
  858. DNS_SECTION_ADDITIONAL);
  859. return (ISC_R_SUCCESS);
  860. failure:
  861. if (dynbuf != NULL)
  862. isc_buffer_free(&dynbuf);
  863. return (result);
  864. }
  865. isc_result_t
  866. dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
  867. isc_buffer_t *intoken, isc_uint32_t lifetime,
  868. gss_ctx_id_t *context, isc_boolean_t win2k,
  869. isc_mem_t *mctx, char **err_message)
  870. {
  871. dns_rdata_tkey_t tkey;
  872. isc_result_t result;
  873. isc_stdtime_t now;
  874. isc_buffer_t token;
  875. unsigned char array[4096];
  876. UNUSED(intoken);
  877. REQUIRE(msg != NULL);
  878. REQUIRE(name != NULL);
  879. REQUIRE(gname != NULL);
  880. REQUIRE(context != NULL);
  881. REQUIRE(mctx != NULL);
  882. isc_buffer_init(&token, array, sizeof(array));
  883. result = dst_gssapi_initctx(gname, NULL, &token, context,
  884. mctx, err_message);
  885. if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
  886. return (result);
  887. tkey.common.rdclass = dns_rdataclass_any;
  888. tkey.common.rdtype = dns_rdatatype_tkey;
  889. ISC_LINK_INIT(&tkey.common, link);
  890. tkey.mctx = NULL;
  891. dns_name_init(&tkey.algorithm, NULL);
  892. if (win2k)
  893. dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
  894. else
  895. dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
  896. isc_stdtime_get(&now);
  897. tkey.inception = now;
  898. tkey.expire = now + lifetime;
  899. tkey.mode = DNS_TKEYMODE_GSSAPI;
  900. tkey.error = 0;
  901. tkey.key = isc_buffer_base(&token);
  902. tkey.keylen = isc_buffer_usedlength(&token);
  903. tkey.other = NULL;
  904. tkey.otherlen = 0;
  905. RETERR(buildquery(msg, name, &tkey, win2k));
  906. return (ISC_R_SUCCESS);
  907. failure:
  908. return (result);
  909. }
  910. isc_result_t
  911. dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key) {
  912. dns_rdata_tkey_t tkey;
  913. REQUIRE(msg != NULL);
  914. REQUIRE(key != NULL);
  915. tkey.common.rdclass = dns_rdataclass_any;
  916. tkey.common.rdtype = dns_rdatatype_tkey;
  917. ISC_LINK_INIT(&tkey.common, link);
  918. tkey.mctx = msg->mctx;
  919. dns_name_init(&tkey.algorithm, NULL);
  920. dns_name_clone(key->algorithm, &tkey.algorithm);
  921. tkey.inception = tkey.expire = 0;
  922. tkey.mode = DNS_TKEYMODE_DELETE;
  923. tkey.error = 0;
  924. tkey.keylen = tkey.otherlen = 0;
  925. tkey.key = tkey.other = NULL;
  926. return (buildquery(msg, &key->name, &tkey, ISC_FALSE));
  927. }
  928. static isc_result_t
  929. find_tkey(dns_message_t *msg, dns_name_t **name, dns_rdata_t *rdata,
  930. int section)
  931. {
  932. dns_rdataset_t *tkeyset;
  933. isc_result_t result;
  934. result = dns_message_firstname(msg, section);
  935. while (result == ISC_R_SUCCESS) {
  936. *name = NULL;
  937. dns_message_currentname(msg, section, name);
  938. tkeyset = NULL;
  939. result = dns_message_findtype(*name, dns_rdatatype_tkey, 0,
  940. &tkeyset);
  941. if (result == ISC_R_SUCCESS) {
  942. result = dns_rdataset_first(tkeyset);
  943. if (result != ISC_R_SUCCESS)
  944. return (result);
  945. dns_rdataset_current(tkeyset, rdata);
  946. return (ISC_R_SUCCESS);
  947. }
  948. result = dns_message_nextname(msg, section);
  949. }
  950. if (result == ISC_R_NOMORE)
  951. return (ISC_R_NOTFOUND);
  952. return (result);
  953. }
  954. isc_result_t
  955. dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
  956. dst_key_t *key, isc_buffer_t *nonce,
  957. dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring)
  958. {
  959. dns_rdata_t qtkeyrdata = DNS_RDATA_INIT, rtkeyrdata = DNS_RDATA_INIT;
  960. dns_name_t keyname, *tkeyname, *theirkeyname, *ourkeyname, *tempname;
  961. dns_rdataset_t *theirkeyset = NULL, *ourkeyset = NULL;
  962. dns_rdata_t theirkeyrdata = DNS_RDATA_INIT;
  963. dst_key_t *theirkey = NULL;
  964. dns_rdata_tkey_t qtkey, rtkey;
  965. unsigned char secretdata[256];
  966. unsigned int sharedsize;
  967. isc_buffer_t *shared = NULL, secret;
  968. isc_region_t r, r2;
  969. isc_result_t result;
  970. isc_boolean_t freertkey = ISC_FALSE;
  971. REQUIRE(qmsg != NULL);
  972. REQUIRE(rmsg != NULL);
  973. REQUIRE(key != NULL);
  974. REQUIRE(dst_key_alg(key) == DNS_KEYALG_DH);
  975. REQUIRE(dst_key_isprivate(key));
  976. if (outkey != NULL)
  977. REQUIRE(*outkey == NULL);
  978. if (rmsg->rcode != dns_rcode_noerror)
  979. return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
  980. RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
  981. RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
  982. freertkey = ISC_TRUE;
  983. RETERR(find_tkey(qmsg, &tempname, &qtkeyrdata,
  984. DNS_SECTION_ADDITIONAL));
  985. RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
  986. if (rtkey.error != dns_rcode_noerror ||
  987. rtkey.mode != DNS_TKEYMODE_DIFFIEHELLMAN ||
  988. rtkey.mode != qtkey.mode ||
  989. !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
  990. rmsg->rcode != dns_rcode_noerror) {
  991. tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
  992. "or error set(1)");
  993. result = DNS_R_INVALIDTKEY;
  994. dns_rdata_freestruct(&qtkey);
  995. goto failure;
  996. }
  997. dns_rdata_freestruct(&qtkey);
  998. dns_name_init(&keyname, NULL);
  999. dns_name_clone(dst_key_name(key), &keyname);
  1000. ourkeyname = NULL;
  1001. ourkeyset = NULL;
  1002. RETERR(dns_message_findname(rmsg, DNS_SECTION_ANSWER, &keyname,
  1003. dns_rdatatype_key, 0, &ourkeyname,
  1004. &ourkeyset));
  1005. result = dns_message_firstname(rmsg, DNS_SECTION_ANSWER);
  1006. while (result == ISC_R_SUCCESS) {
  1007. theirkeyname = NULL;
  1008. dns_message_currentname(rmsg, DNS_SECTION_ANSWER,
  1009. &theirkeyname);
  1010. if (dns_name_equal(theirkeyname, ourkeyname))
  1011. goto next;
  1012. theirkeyset = NULL;
  1013. result = dns_message_findtype(theirkeyname, dns_rdatatype_key,
  1014. 0, &theirkeyset);
  1015. if (result == ISC_R_SUCCESS) {
  1016. RETERR(dns_rdataset_first(theirkeyset));
  1017. break;
  1018. }
  1019. next:
  1020. result = dns_message_nextname(rmsg, DNS_SECTION_ANSWER);
  1021. }
  1022. if (theirkeyset == NULL) {
  1023. tkey_log("dns_tkey_processdhresponse: failed to find server "
  1024. "key");
  1025. result = ISC_R_NOTFOUND;
  1026. goto failure;
  1027. }
  1028. dns_rdataset_current(theirkeyset, &theirkeyrdata);
  1029. RETERR(dns_dnssec_keyfromrdata(theirkeyname, &theirkeyrdata,
  1030. rmsg->mctx, &theirkey));
  1031. RETERR(dst_key_secretsize(key, &sharedsize));
  1032. RETERR(isc_buffer_allocate(rmsg->mctx, &shared, sharedsize));
  1033. RETERR(dst_key_computesecret(theirkey, key, shared));
  1034. isc_buffer_init(&secret, secretdata, sizeof(secretdata));
  1035. r.base = rtkey.key;
  1036. r.length = rtkey.keylen;
  1037. if (nonce != NULL)
  1038. isc_buffer_usedregion(nonce, &r2);
  1039. else {
  1040. r2.base = isc_mem_get(rmsg->mctx, 0);
  1041. r2.length = 0;
  1042. }
  1043. RETERR(compute_secret(shared, &r2, &r, &secret));
  1044. if (nonce == NULL)
  1045. isc_mem_put(rmsg->mctx, r2.base, 0);
  1046. isc_buffer_usedregion(&secret, &r);
  1047. result = dns_tsigkey_create(tkeyname, &rtkey.algorithm,
  1048. r.base, r.length, ISC_TRUE,
  1049. NULL, rtkey.inception, rtkey.expire,
  1050. rmsg->mctx, ring, outkey);
  1051. isc_buffer_free(&shared);
  1052. dns_rdata_freestruct(&rtkey);
  1053. dst_key_free(&theirkey);
  1054. return (result);
  1055. failure:
  1056. if (shared != NULL)
  1057. isc_buffer_free(&shared);
  1058. if (theirkey != NULL)
  1059. dst_key_free(&theirkey);
  1060. if (freertkey)
  1061. dns_rdata_freestruct(&rtkey);
  1062. return (result);
  1063. }
  1064. isc_result_t
  1065. dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
  1066. dns_name_t *gname, gss_ctx_id_t *context,
  1067. isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
  1068. dns_tsig_keyring_t *ring, char **err_message)
  1069. {
  1070. dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
  1071. dns_name_t *tkeyname;
  1072. dns_rdata_tkey_t rtkey, qtkey;
  1073. dst_key_t *dstkey = NULL;
  1074. isc_buffer_t intoken;
  1075. isc_result_t result;
  1076. unsigned char array[1024];
  1077. REQUIRE(outtoken != NULL);
  1078. REQUIRE(qmsg != NULL);
  1079. REQUIRE(rmsg != NULL);
  1080. REQUIRE(gname != NULL);
  1081. REQUIRE(ring != NULL);
  1082. if (outkey != NULL)
  1083. REQUIRE(*outkey == NULL);
  1084. if (rmsg->rcode != dns_rcode_noerror)
  1085. return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
  1086. RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
  1087. RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
  1088. /*
  1089. * Win2k puts the item in the ANSWER section, while the RFC
  1090. * specifies it should be in the ADDITIONAL section. Check first
  1091. * where it should be, and then where it may be.
  1092. */
  1093. result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
  1094. DNS_SECTION_ADDITIONAL);
  1095. if (result == ISC_R_NOTFOUND)
  1096. result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
  1097. DNS_SECTION_ANSWER);
  1098. if (result != ISC_R_SUCCESS)
  1099. goto failure;
  1100. RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
  1101. if (rtkey.error != dns_rcode_noerror ||
  1102. rtkey.mode != DNS_TKEYMODE_GSSAPI ||
  1103. !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm)) {
  1104. tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
  1105. "or error set(2) %d", rtkey.error);
  1106. _dns_tkey_dumpmessage(qmsg);
  1107. _dns_tkey_dumpmessage(rmsg);
  1108. result = DNS_R_INVALIDTKEY;
  1109. goto failure;
  1110. }
  1111. isc_buffer_init(outtoken, array, sizeof(array));
  1112. isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
  1113. RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context,
  1114. ring->mctx, err_message));
  1115. RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
  1116. &dstkey, NULL));
  1117. RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
  1118. dstkey, ISC_FALSE, NULL,
  1119. rtkey.inception, rtkey.expire,
  1120. ring->mctx, ring, outkey));
  1121. dst_key_free(&dstkey);
  1122. dns_rdata_freestruct(&rtkey);
  1123. return (result);
  1124. failure:
  1125. /*
  1126. * XXXSRA This probably leaks memory from rtkey and qtkey.
  1127. */
  1128. if (dstkey != NULL)
  1129. dst_key_free(&dstkey);
  1130. return (result);
  1131. }
  1132. isc_result_t
  1133. dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
  1134. dns_tsig_keyring_t *ring)
  1135. {
  1136. dns_rdata_t qtkeyrdata = DNS_RDATA_INIT, rtkeyrdata = DNS_RDATA_INIT;
  1137. dns_name_t *tkeyname, *tempname;
  1138. dns_rdata_tkey_t qtkey, rtkey;
  1139. dns_tsigkey_t *tsigkey = NULL;
  1140. isc_result_t result;
  1141. REQUIRE(qmsg != NULL);
  1142. REQUIRE(rmsg != NULL);
  1143. if (rmsg->rcode != dns_rcode_noerror)
  1144. return(ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
  1145. RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
  1146. RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
  1147. RETERR(find_tkey(qmsg, &tempname, &qtkeyrdata,
  1148. DNS_SECTION_ADDITIONAL));
  1149. RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
  1150. if (rtkey.error != dns_rcode_noerror ||
  1151. rtkey.mode != DNS_TKEYMODE_DELETE ||
  1152. rtkey.mode != qtkey.mode ||
  1153. !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
  1154. rmsg->rcode != dns_rcode_noerror) {
  1155. tkey_log("dns_tkey_processdeleteresponse: tkey mode invalid "
  1156. "or error set(3)");
  1157. result = DNS_R_INVALIDTKEY;
  1158. dns_rdata_freestruct(&qtkey);
  1159. dns_rdata_freestruct(&rtkey);
  1160. goto failure;
  1161. }
  1162. dns_rdata_freestruct(&qtkey);
  1163. RETERR(dns_tsigkey_find(&tsigkey, tkeyname, &rtkey.algorithm, ring));
  1164. dns_rdata_freestruct(&rtkey);
  1165. /*
  1166. * Mark the key as deleted.
  1167. */
  1168. dns_tsigkey_setdeleted(tsigkey);
  1169. /*
  1170. * Release the reference.
  1171. */
  1172. dns_tsigkey_detach(&tsigkey);
  1173. failure:
  1174. return (result);
  1175. }
  1176. isc_result_t
  1177. dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
  1178. dns_name_t *server, gss_ctx_id_t *context,
  1179. dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
  1180. isc_boolean_t win2k, char **err_message)
  1181. {
  1182. dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
  1183. dns_name_t *tkeyname;
  1184. dns_rdata_tkey_t rtkey, qtkey;
  1185. isc_buffer_t intoken, outtoken;
  1186. dst_key_t *dstkey = NULL;
  1187. isc_result_t result;
  1188. unsigned char array[1024];
  1189. REQUIRE(qmsg != NULL);
  1190. REQUIRE(rmsg != NULL);
  1191. REQUIRE(server != NULL);
  1192. if (outkey != NULL)
  1193. REQUIRE(*outkey == NULL);
  1194. if (rmsg->rcode != dns_rcode_noerror)
  1195. return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
  1196. RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
  1197. RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
  1198. if (win2k == ISC_TRUE)
  1199. RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
  1200. DNS_SECTION_ANSWER));
  1201. else
  1202. RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
  1203. DNS_SECTION_ADDITIONAL));
  1204. RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
  1205. if (rtkey.error != dns_rcode_noerror ||
  1206. rtkey.mode != DNS_TKEYMODE_GSSAPI ||
  1207. !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm))
  1208. {
  1209. tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
  1210. "or error set(4)");
  1211. result = DNS_R_INVALIDTKEY;
  1212. goto failure;
  1213. }
  1214. isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
  1215. isc_buffer_init(&outtoken, array, sizeof(array));
  1216. result = dst_gssapi_initctx(server, &intoken, &outtoken, context,
  1217. ring->mctx, err_message);
  1218. if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
  1219. return (result);
  1220. RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
  1221. &dstkey, NULL));
  1222. /*
  1223. * XXXSRA This seems confused. If we got CONTINUE from initctx,
  1224. * the GSS negotiation hasn't completed yet, so we can't sign
  1225. * anything yet.
  1226. */
  1227. RETERR(dns_tsigkey_createfromkey(tkeyname,
  1228. (win2k
  1229. ? DNS_TSIG_GSSAPIMS_NAME
  1230. : DNS_TSIG_GSSAPI_NAME),
  1231. dstkey, ISC_TRUE, NULL,
  1232. rtkey.inception, rtkey.expire,
  1233. ring->mctx, ring, outkey));
  1234. dst_key_free(&dstkey);
  1235. dns_rdata_freestruct(&rtkey);
  1236. return (result);
  1237. failure:
  1238. /*
  1239. * XXXSRA This probably leaks memory from qtkey.
  1240. */
  1241. dns_rdata_freestruct(&rtkey);
  1242. if (dstkey != NULL)
  1243. dst_key_free(&dstkey);
  1244. return (result);
  1245. }