📄 tkey.c
字号:
isc_region_t intoken; unsigned char array[1024]; isc_buffer_t outtoken; UNUSED(namelist); if (tctx->gsscred == NULL) return (ISC_R_NOPERM); if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkeyout->error = dns_tsigerror_badalg; return (ISC_R_SUCCESS); } intoken.base = tkeyin->key; intoken.length = tkeyin->keylen; isc_buffer_init(&outtoken, array, sizeof(array)); RETERR(dst_gssapi_acceptctx(name, tctx->gsscred, &intoken, &outtoken, &gssctx)); dstkey = NULL; RETERR(dst_key_fromgssapi(name, gssctx, msg->mctx, &dstkey)); result = dns_tsigkey_createfromkey(name, &tkeyin->algorithm, dstkey, ISC_TRUE, signer, tkeyin->inception, tkeyin->expire, msg->mctx, ring, NULL); if (result != ISC_R_SUCCESS) goto failure; if (result == ISC_R_NOTFOUND) { tkeyout->error = dns_tsigerror_badalg; return (ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS) goto failure; /* This key is good for a long time */ isc_stdtime_get(&now); tkeyout->inception = tkeyin->inception; tkeyout->expire = tkeyin->expire; tkeyout->key = isc_mem_get(msg->mctx, isc_buffer_usedlength(&outtoken)); if (tkeyout->key == NULL) { result = ISC_R_NOMEMORY; goto failure; } tkeyout->keylen = isc_buffer_usedlength(&outtoken); memcpy(tkeyout->key, isc_buffer_base(&outtoken), tkeyout->keylen); return (ISC_R_SUCCESS); failure: if (dstkey != NULL) dst_key_free(&dstkey); return (result);}static isc_result_tprocess_deletetkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_rdata_tkey_t *tkeyout, dns_tsig_keyring_t *ring, dns_namelist_t *namelist){ isc_result_t result; dns_tsigkey_t *tsigkey = NULL; dns_name_t *identity; UNUSED(msg); UNUSED(namelist); result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring); if (result != ISC_R_SUCCESS) { tkeyout->error = dns_tsigerror_badname; return (ISC_R_SUCCESS); } /* * Only allow a delete if the identity that created the key is the * same as the identity that signed the message. */ identity = dns_tsigkey_identity(tsigkey); if (identity == NULL || !dns_name_equal(identity, signer)) { dns_tsigkey_detach(&tsigkey); return (DNS_R_REFUSED); } /* * Set the key to be deleted when no references are left. If the key * was not generated with TKEY and is in the config file, it may be * reloaded later. */ dns_tsigkey_setdeleted(tsigkey); /* Release the reference */ dns_tsigkey_detach(&tsigkey); return (ISC_R_SUCCESS);}isc_result_tdns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, dns_tsig_keyring_t *ring){ isc_result_t result = ISC_R_SUCCESS; dns_rdata_tkey_t tkeyin, tkeyout; isc_boolean_t freetkeyin = ISC_FALSE; dns_name_t *qname, *name, *keyname, *signer, tsigner; dns_fixedname_t fkeyname; dns_rdataset_t *tkeyset; dns_rdata_t rdata; dns_namelist_t namelist; char tkeyoutdata[512]; isc_buffer_t tkeyoutbuf; REQUIRE(msg != NULL); REQUIRE(tctx != NULL); REQUIRE(ring != NULL); ISC_LIST_INIT(namelist); /* * Interpret the question section. */ result = dns_message_firstname(msg, DNS_SECTION_QUESTION); if (result != ISC_R_SUCCESS) return (DNS_R_FORMERR); qname = NULL; dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname); /* * Look for a TKEY record that matches the question. */ tkeyset = NULL; name = NULL; result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname, dns_rdatatype_tkey, 0, &name, &tkeyset); if (result != ISC_R_SUCCESS) { /* * Try the answer section, since that's where Win2000 * puts it. */ if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_tkey, 0, &name, &tkeyset) != ISC_R_SUCCESS) { result = DNS_R_FORMERR; tkey_log("dns_tkey_processquery: couldn't find a TKEY " "matching the question"); goto failure; } } result = dns_rdataset_first(tkeyset); if (result != ISC_R_SUCCESS) { result = DNS_R_FORMERR; goto failure; } dns_rdata_init(&rdata); dns_rdataset_current(tkeyset, &rdata); RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL)); freetkeyin = ISC_TRUE; if (tkeyin.error != dns_rcode_noerror) { result = DNS_R_FORMERR; goto failure; } /* * Before we go any farther, verify that the message was signed. * GSSAPI TKEY doesn't require a signature, the rest do. */ dns_name_init(&tsigner, NULL); result = dns_message_signer(msg, &tsigner); if (result != ISC_R_SUCCESS) { if (tkeyin.mode == DNS_TKEYMODE_GSSAPI && result == ISC_R_NOTFOUND) signer = NULL; else { tkey_log("dns_tkey_processquery: query was not " "properly signed - rejecting"); result = DNS_R_FORMERR; goto failure; } } else signer = &tsigner; tkeyout.common.rdclass = tkeyin.common.rdclass; tkeyout.common.rdtype = tkeyin.common.rdtype; ISC_LINK_INIT(&tkeyout.common, link); tkeyout.mctx = msg->mctx; dns_name_init(&tkeyout.algorithm, NULL); dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm); tkeyout.inception = tkeyout.expire = 0; tkeyout.mode = tkeyin.mode; tkeyout.error = 0; tkeyout.keylen = tkeyout.otherlen = 0; tkeyout.key = tkeyout.other = NULL; /* * A delete operation must have a fully specified key name. If this * is not a delete, we do the following: * if (qname != ".") * keyname = qname + defaultdomain * else * keyname = <random hex> + defaultdomain */ if (tkeyin.mode != DNS_TKEYMODE_DELETE) { dns_tsigkey_t *tsigkey = NULL; if (tctx->domain == NULL) { tkey_log("dns_tkey_processquery: tkey-domain not set"); result = DNS_R_REFUSED; goto failure; } dns_fixedname_init(&fkeyname); keyname = dns_fixedname_name(&fkeyname); if (!dns_name_equal(qname, dns_rootname)) { unsigned int n = dns_name_countlabels(qname); RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL) == ISC_R_SUCCESS); dns_name_getlabelsequence(keyname, 0, n - 1, keyname); } else { static char hexdigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; unsigned char randomdata[16]; char randomtext[32]; isc_buffer_t b; unsigned int i, j; result = isc_entropy_getdata(tctx->ectx, randomdata, sizeof(randomdata), NULL, 0); if (result != ISC_R_SUCCESS) goto failure; for (i = 0, j = 0; i < sizeof(randomdata); i++) { unsigned char val = randomdata[i]; randomtext[j++] = hexdigits[val >> 4]; randomtext[j++] = hexdigits[val & 0xF]; } isc_buffer_init(&b, randomtext, sizeof(randomtext)); isc_buffer_add(&b, sizeof(randomtext)); result = dns_name_fromtext(keyname, &b, NULL, ISC_FALSE, NULL); if (result != ISC_R_SUCCESS) goto failure; } result = dns_name_concatenate(keyname, tctx->domain, keyname, NULL); if (result != ISC_R_SUCCESS) goto failure; result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring); if (result == ISC_R_SUCCESS) { tkeyout.error = dns_tsigerror_badname; dns_tsigkey_detach(&tsigkey); goto failure_with_tkey; } else if (result != ISC_R_NOTFOUND) goto failure; } else keyname = qname; switch (tkeyin.mode) { case DNS_TKEYMODE_DIFFIEHELLMAN: tkeyout.error = dns_rcode_noerror; RETERR(process_dhtkey(msg, signer, keyname, &tkeyin, tctx, &tkeyout, ring, &namelist)); break; case DNS_TKEYMODE_GSSAPI: tkeyout.error = dns_rcode_noerror; RETERR(process_gsstkey(msg, signer, keyname, &tkeyin, tctx, &tkeyout, ring, &namelist)); break; case DNS_TKEYMODE_DELETE: tkeyout.error = dns_rcode_noerror; RETERR(process_deletetkey(msg, signer, keyname, &tkeyin, &tkeyout, ring, &namelist)); break; case DNS_TKEYMODE_SERVERASSIGNED: case DNS_TKEYMODE_RESOLVERASSIGNED: result = DNS_R_NOTIMP; goto failure; default: tkeyout.error = dns_tsigerror_badmode; } failure_with_tkey: dns_rdata_init(&rdata); isc_buffer_init(&tkeyoutbuf, tkeyoutdata, sizeof(tkeyoutdata)); result = dns_rdata_fromstruct(&rdata, tkeyout.common.rdclass, tkeyout.common.rdtype, &tkeyout, &tkeyoutbuf); if (freetkeyin) { dns_rdata_freestruct(&tkeyin); freetkeyin = ISC_FALSE; } if (tkeyout.key != NULL) isc_mem_put(msg->mctx, tkeyout.key, tkeyout.keylen); if (tkeyout.other != NULL) isc_mem_put(msg->mctx, tkeyout.other, tkeyout.otherlen); if (result != ISC_R_SUCCESS) goto failure; RETERR(add_rdata_to_list(msg, keyname, &rdata, 0, &namelist)); RETERR(dns_message_reply(msg, ISC_TRUE)); name = ISC_LIST_HEAD(namelist); while (name != NULL) { dns_name_t *next = ISC_LIST_NEXT(name, link); ISC_LIST_UNLINK(namelist, name, link); dns_message_addname(msg, name, DNS_SECTION_ANSWER); name = next; } return (ISC_R_SUCCESS); failure: if (freetkeyin) dns_rdata_freestruct(&tkeyin); if (!ISC_LIST_EMPTY(namelist)) free_namelist(msg, &namelist); return (result);}static isc_result_tbuildquery(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkey){ dns_name_t *qname = NULL, *aname = NULL; dns_rdataset_t *question = NULL, *tkeyset = NULL; dns_rdatalist_t *tkeylist = NULL; dns_rdata_t *rdata = NULL; isc_buffer_t *dynbuf = NULL; isc_result_t result; REQUIRE(msg != NULL); REQUIRE(name != NULL); REQUIRE(tkey != NULL); RETERR(dns_message_gettempname(msg, &qname)); RETERR(dns_message_gettempname(msg, &aname)); RETERR(dns_message_gettemprdataset(msg, &question)); dns_rdataset_init(question); dns_rdataset_makequestion(question, dns_rdataclass_any, dns_rdatatype_tkey); RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 512)); RETERR(dns_message_gettemprdata(msg, &rdata)); RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, dns_rdatatype_tkey, tkey, dynbuf)); dns_message_takebuffer(msg, &dynbuf); RETERR(dns_message_gettemprdatalist(msg, &tkeylist)); tkeylist->rdclass = dns_rdataclass_any; tkeylist->type = dns_rdatatype_tkey; tkeylist->covers = 0; tkeylist->ttl = 0; ISC_LIST_INIT(tkeylist->rdata); ISC_LIST_APPEND(tkeylist->rdata, rdata, link); RETERR(dns_message_gettemprdataset(msg, &tkeyset)); dns_rdataset_init(tkeyset); RETERR(dns_rdatalist_tordataset(tkeylist, tkeyset)); dns_name_init(qname, NULL); dns_name_clone(name, qname); dns_name_init(aname, NULL); dns_name_clone(name, aname); ISC_LIST_APPEND(qname->list, question, link); ISC_LIST_APPEND(aname->list, tkeyset, link); dns_message_addname(msg, qname, DNS_SECTION_QUESTION); dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL); return (ISC_R_SUCCESS); failure: if (qname != NULL) dns_message_puttempname(msg, &qname); if (aname != NULL) dns_message_puttempname(msg, &aname); if (question != NULL) { dns_rdataset_disassociate(question); dns_message_puttemprdataset(msg, &question); } if (dynbuf != NULL) isc_buffer_free(&dynbuf); return (result);}isc_result_tdns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -