tkey.c revision f879d3ee27d172ed7913bc0d6c36c610a3e48329
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 1999 Internet Software Consortium.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * Permission to use, copy, modify, and distribute this software for any
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * purpose with or without fee is hereby granted, provided that the above
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15a44745412679c30a6d022733925af70a38b715David Lawrence * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15a44745412679c30a6d022733925af70a38b715David Lawrence * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15a44745412679c30a6d022733925af70a38b715David Lawrence * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * $Id: tkey.c,v 1.4 1999/10/26 21:57:52 bwelling Exp $
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Principal Author: Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington#define RETERR(x) do { \
4cd765650776027d05fe7fca248478918e02e63bDavid Lawrencedns_tkey_init(isc_log_t *lctx, dns_c_ctx_t *cfg, isc_mem_t *mctx) {
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence result = dns_c_ctx_gettkeydhkey(lctx, cfg, &s, &n);
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence RETERR(dst_key_fromfile(s, n, DNS_KEYALG_DH, DST_TYPE_PRIVATE,
b435b1ded3def3159f597953d21dffc1615cb250Brian Wellington RETERR(dns_c_ctx_gettkeydomain(lctx, cfg, &s));
94b166ffa58ef0ff263563c0550d0b30eb9f7772David Lawrence tkey_domain = (dns_name_t *) isc_mem_get(mctx, sizeof(dns_name_t));
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson isc_buffer_init(&b, s, strlen(s), ISC_BUFFERTYPE_TEXT);
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson RETERR(isc_buffer_allocate(mctx, &namebuf, 1024,
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson RETERR(dns_name_fromtext(tkey_domain, &b, dns_rootname, ISC_FALSE,
94b166ffa58ef0ff263563c0550d0b30eb9f7772David Lawrence isc_mem_put(mctx, tkey_domain, sizeof(dns_name_t));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonadd_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_uint32_t ttl, dns_namelist_t *namelist)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_buffer_t *tmprdatabuf = NULL, *tmpnamebuf = NULL;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_message_gettemprdata(msg, &newrdata));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_message_gettempname(msg, &newname));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(isc_buffer_allocate(msg->mctx, &tmpnamebuf, r.length,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_message_gettemprdatalist(msg, &newlist));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington ISC_LIST_APPEND(newlist->rdata, newrdata, link);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_message_gettemprdataset(msg, &newset));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_rdatalist_tordataset(newlist, newset));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington ISC_LIST_APPEND(newname->list, newset, link);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington dns_message_puttemprdatalist(msg, &newlist);
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellingtonprocess_dhtkey(dns_message_t *msg, dns_name_t *name,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington dns_rdata_generic_tkey_t *tkeyout, dns_namelist_t *namelist)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_buffer_t ourkeybuf, ournamein, ournameout, *secret = NULL;
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence /* Look for a DH KEY record that will work with ours */
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(add_rdata_to_list(msg, keyname, &keyrdata, keyset->ttl,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata),
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dst_key_todns(tkey_dhkey, &ourkeybuf));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_in,
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington isc_buffer_init(&ournamein, dst_key_name(tkey_dhkey),
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington strlen(dst_key_name(tkey_dhkey)), ISC_BUFFERTYPE_TEXT);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_buffer_add(&ournamein, strlen(dst_key_name(tkey_dhkey)));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington isc_buffer_init(&ournameout, namedata, sizeof(namedata),
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_name_fromtext(&ourname, &ournamein, dns_rootname, ISC_FALSE,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington /* Not sure how to do this without a view... */
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington result = dns_dbtable_find(client->view->dbtable, &ourname, &db);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington result = dns_db_find(db, &ourname, NULL, dns_rdatatype_key,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, ourttl,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dst_secret_size(tkey_dhkey, &secretsize));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(isc_buffer_allocate(msg->mctx, &secret, secretsize,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington result = dst_computesecret(pubkey, tkey_dhkey, secret);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington result = dns_tsigkey_create(name, &tkeyin->algorithm, r.base, r.length,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington /* This key is good for a long time */
504f7802d4c9b43db4820f496c4d00e078effa18David Lawrence dns_name_t *tname = ISC_LIST_HEAD(*namelist);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence dns_name_t *next = ISC_LIST_NEXT(tname, link);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrenceprocess_deletetkey(dns_message_t *msg, dns_name_t *name,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington /* Unused variables */
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm);
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * Only allow a delete if the message is signed by the key to
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * be deleted or a key with the same creator.
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington if (!dns_name_equal(&msg->tsigkey->name, name)) {
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington !dst_key_compare(msg->tsigkey->creator, tsigkey->creator))
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson /* If tsigkey->creator is NULL, log a warning here... */
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * Set the key to be deleted when no references are left. If the key
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * was not generated with TKEY and is in the config file, it may be
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * reloaded later.
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence /* Release the reference */
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence /* Need to do this to determine if this should be freed later */
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence memset(&tkeyin, 0, sizeof(dns_rdata_generic_tkey_t));
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence /* Interpret the question section */
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname);
3db78e0855a8dfc162180880cd70d9c1a03d9301David Lawrence /* Look for a TKEY record that matches the question */
30a4d5b0c23eb7a73d9635a98250560437a42d59David Lawrence result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname,
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence RETERR(dns_rdata_tostruct(&tkeyrdata, &tkeyin, msg->mctx));
f96b41064bcd427d8125a096fd646c1f068d8ed7David Lawrence tkeyout.common.rdclass = tkeyin.common.rdclass;
f96b41064bcd427d8125a096fd646c1f068d8ed7David Lawrence tkeyout.common.rdtype = tkeyin.common.rdtype;
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington RETERR(dns_name_dup(&tkeyin.algorithm, msg->mctx, &tkeyout.algorithm));
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * A delete operation must have a fully specified key name. If not,
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * we do the following:
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * if qname is a subdomain of defaultdomain
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * keyname = qname.
3db78e0855a8dfc162180880cd70d9c1a03d9301David Lawrence * else if (qname != ".")
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * keyname = qname + defaultdomain
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * keyname = <random hex> + defaultdomain
3db78e0855a8dfc162180880cd70d9c1a03d9301David Lawrence result = dns_message_gettempname(msg, &keyname);
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington RETERR(isc_buffer_allocate(msg->mctx, &buf, 256,
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington if (!dns_name_equal(qname, dns_rootname)) {
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington unsigned int n = dns_name_countlabels(qname);
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington dns_name_getlabelsequence(qname, 0, n - 1, &prefix);
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington static char hexdigits[16] = "0123456789ABCDEF";
5096958739769958dd7a6b69356bf41260033873David Lawrence isc_buffer_init(&b, randomtext, sizeof(randomtext),
5096958739769958dd7a6b69356bf41260033873David Lawrence result = dst_random_get(sizeof(randomtext)/2, &b);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington for (i = sizeof(randomtext) - 2; i >= 0; i -= 2) {
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence isc_buffer_init(&b, randomtext, sizeof(randomtext),
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington result = dns_name_fromtext(&prefix, &b, NULL,
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington result = dns_name_concatenate(&prefix, tkey_domain,
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington result = dns_tsigkey_find(&tsigkey, keyname, NULL);
947295d8868c24f75a858e42b579a271c1d2c3d2David Lawrence if (!dns_name_equal(&tkeyin.algorithm, DNS_TSIG_HMACMD5_NAME)) {
d7ba3622ffa20c653ef6c8cfae42d8cd26465b7fBrian Wellington RETERR(process_dhtkey(msg, keyname, &tkeyin,
5c3efef92647e208dd887afeacec02b9104d1516Brian Wellington RETERR(process_deletetkey(msg, keyname, &tkeyin,
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson RETERR(dns_message_gettemprdata(msg, &rdata));
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 128,
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson result = dns_rdata_fromstruct(rdata, tkeyout.common.rdclass,
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson tkeyout.common.rdtype, &tkeyout, dynbuf);
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson RETERR(add_rdata_to_list(msg, keyname, rdata, 0, &namelist));
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson RETERR(dns_message_reply(msg, ISC_TRUE));
984ca288f1291c7b7bda9b3809a7af714e3ec82aAndreas Gustafsson dns_name_t *next = ISC_LIST_NEXT(name, link);
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellington if (tkeyin.common.rdtype == dns_rdatatype_tkey)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonbuildquery(dns_message_t *msg, dns_name_t *name,
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington dns_rdataset_t *question = NULL, *tkeyset = NULL;
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence msg->id = 10; /* XXX should use isc_random_get */
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence RETERR(dns_message_gettempname(msg, &qname));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington RETERR(dns_message_gettempname(msg, &aname));
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence RETERR(dns_message_gettemprdataset(msg, &question));
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence dns_rdataset_makequestion(question, dns_rdataclass_in /**/,
return (ISC_R_SUCCESS);
return (result);
isc_region_t r;
dns_rdatatype_key, &r);
dynbuf));
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
&tkeyset);
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
return (result);
unsigned int secretsize;
isc_region_t r;
goto failure;
&ourkeyset));
&theirkeyname);
goto next;
0, &theirkeyset);
next:
goto failure;
goto failure;
return (result);
return (result);
goto failure;
return (result);