From 0f80bfec687db08a6e6ce945ef1d818da06c7ca9 Mon Sep 17 00:00:00 2001 From: Brian Wellington Date: Tue, 30 May 2000 23:14:57 +0000 Subject: [PATCH] The message code now has functions to manipulate TSIG and SIG(0), and the callers use these functions. Also a lot of TSIG cleanup. --- bin/named/xfrout.c | 36 ++-- lib/dns/include/dns/message.h | 90 +++++++++- lib/dns/message.c | 302 +++++++++++++++++++++++++++++----- lib/dns/request.c | 20 +-- lib/dns/resolver.c | 46 ++++-- lib/dns/tsig.c | 238 +++++++++++++-------------- lib/dns/xfrin.c | 40 ++--- 7 files changed, 522 insertions(+), 250 deletions(-) diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index 2065770f86..a22ddd4779 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: xfrout.c,v 1.63 2000/05/26 00:16:35 bwelling Exp $ */ +/* $Id: xfrout.c,v 1.64 2000/05/30 23:14:48 bwelling Exp $ */ #include @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -741,7 +742,7 @@ typedef struct { unsigned int txmemlen; unsigned int nmsg; /* Number of messages sent */ dns_tsigkey_t *tsigkey; /* Key used to create TSIG */ - dns_rdata_any_tsig_t *lasttsig; /* the last TSIG */ + isc_buffer_t *lasttsig; /* the last TSIG */ isc_boolean_t many_answers; int sends; /* Send in progress */ isc_boolean_t shuttingdown; @@ -752,7 +753,7 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, dns_tsigkey_t *tsigkey, - dns_rdata_any_tsig_t *lasttsig, + isc_buffer_t *lasttsig, unsigned int maxtime, unsigned int idletime, isc_boolean_t many_answers, @@ -810,6 +811,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { dns_transfer_format_t format = client->view->transfer_format; isc_netaddr_t na; dns_peer_t *peer = NULL; + isc_buffer_t *tsigbuf = NULL; switch (reqtype) { case dns_rdatatype_axfr: @@ -1022,13 +1024,15 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { data_stream = NULL; have_stream: + CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf)); /* * Create the xfrout context object. This transfers the ownership * of "stream", "db", "ver", and "quota" to the xfrout context object. */ CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, db, ver, quota, stream, - dns_message_gettsigkey(request), request->tsig, + dns_message_gettsigkey(request), + tsigbuf, dns_zone_getmaxxfrout(zone), dns_zone_getidleout(zone), (format == dns_many_answers) ? @@ -1084,7 +1088,7 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, dns_tsigkey_t *tsigkey, - dns_rdata_any_tsig_t *lasttsig, unsigned int maxtime, + isc_buffer_t *lasttsig, unsigned int maxtime, unsigned int idletime, isc_boolean_t many_answers, xfrout_ctx_t **xfrp) { @@ -1215,7 +1219,9 @@ sendstream(xfrout_ctx_t *xfr) { if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) msg->flags |= DNS_MESSAGEFLAG_RA; dns_message_settsigkey(msg, xfr->tsigkey); - msg->querytsig = xfr->lasttsig; + CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); + if (xfr->lasttsig != NULL) + isc_buffer_free(&xfr->lasttsig); /* * Include a question section in the first message only. @@ -1384,17 +1390,7 @@ sendstream(xfrout_ctx_t *xfr) { } /* Advance lasttsig to be the last TSIG generated */ - xfr->lasttsig = msg->tsig; - - /* Clear this field so the TSIG is not destroyed */ - msg->tsig = NULL; - - /* - * If this is the first message, clear this too, since this is - * also pointed to by the request. - */ - if (xfr->nmsg == 0) - msg->querytsig = NULL; + CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); xfr->nmsg++; @@ -1426,10 +1422,8 @@ xfrout_ctx_destroy(xfrout_ctx_t **xfrp) { isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length); if (xfr->txmem != NULL) isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen); - if (xfr->lasttsig != NULL) { - dns_rdata_freestruct(xfr->lasttsig); - isc_mem_put(xfr->mctx, xfr->lasttsig, sizeof(*xfr->lasttsig)); - } + if (xfr->lasttsig != NULL) + isc_buffer_free(&xfr->lasttsig); if (xfr->quota != NULL) isc_quota_detach(&xfr->quota); if (xfr->ver != NULL) diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 263eddb583..29eac06c9d 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -178,6 +177,7 @@ struct dns_message { unsigned int verify_attempted : 1; unsigned int opt_reserved; + unsigned int sig_reserved; unsigned int reserved; /* reserved space (render) */ isc_buffer_t *buffer; @@ -199,8 +199,7 @@ struct dns_message { dns_rcode_t tsigstatus; dns_rcode_t querytsigstatus; dns_name_t *tsigname; - dns_rdata_any_tsig_t *tsig; - dns_rdata_any_tsig_t *querytsig; + dns_rdataset_t *querytsigset; dns_tsigkey_t *tsigkey; void *tsigctx; int sigstart; @@ -952,7 +951,7 @@ dns_message_gettsig(dns_message_t *msg, dns_name_t **owner); * The TSIG rdataset of 'msg', or NULL if there isn't one. */ -void +isc_result_t dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key); /* * Set the tsig key for 'msg'. This is only necessary for when rendering a @@ -961,8 +960,16 @@ dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key); * * Requires: * - * 'msg' is a valid message + * 'msg' is a valid message with rendering intent, + * dns_message_renderbegin() has been called, and no sections have been + * rendered. * 'key' is a valid tsig key or NULL. + * + * Returns: + * + * ISC_R_SUCCESS -- all is well. + * + * ISC_R_NOSPACE -- there is no space for the TSIG record. */ dns_tsigkey_t * @@ -975,6 +982,50 @@ dns_message_gettsigkey(dns_message_t *msg); * 'msg' is a valid message */ +isc_result_t +dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig); +/* + * Indicates that 'querytsig' is the TSIG from the signed query for which + * 'msg' is the response. This is also used for chained TSIGs in TCP + * responses. + * + * Requires: + * + * 'querytsig' is a valid buffer as returned by dns_message_getquerytsig() + * or NULL + * + * 'msg' is a valid message + * + * Returns: + * + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + */ + +isc_result_t +dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, + isc_buffer_t **querytsig); +/* + * Gets the tsig from the TSIG from the signed query 'msg'. This is also used + * for chained TSIGs in TCP responses. Unlike dns_message_gettsig, this makes + * a copy of the data, so can be used if the message is destroyed. + * + * Requires: + * + * 'msg' is a valid signed message + * 'mctx' is a valid memory context + * querytsig != NULL && *querytsig == NULL + * + * Returns: + * + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + * + * Ensures: + * 'tsig' points to NULL or an allocated buffer which must be freed + * by the caller. + */ + dns_rdataset_t * dns_message_getsig0(dns_message_t *msg, dns_name_t **owner); /* @@ -990,6 +1041,35 @@ dns_message_getsig0(dns_message_t *msg, dns_name_t **owner); * The SIG(0) rdataset of 'msg', or NULL if there isn't one. */ +isc_result_t +dns_message_setsig0key(dns_message_t *msg, dst_key_t *key); +/* + * Set the SIG(0) key for 'msg'. + * + * Requires: + * + * 'msg' is a valid message with rendering intent, + * dns_message_renderbegin() has been called, and no sections have been + * rendered. + * 'key' is a valid sig key or NULL. + * + * Returns: + * + * ISC_R_SUCCESS -- all is well. + * + * ISC_R_NOSPACE -- there is no space for the SIG(0) record. + */ + +dst_key_t * +dns_message_getsig0key(dns_message_t *msg); +/* + * Gets the SIG(0) key for 'msg'. + * + * Requires: + * + * 'msg' is a valid message + */ + void dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer); /* diff --git a/lib/dns/message.c b/lib/dns/message.c index 6167f8dd58..f37b73b43f 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,7 @@ msginitprivate(dns_message_t *m) { m->tsigname = NULL; m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */ m->opt_reserved = 0; + m->sig_reserved = 0; m->reserved = 0; m->buffer = NULL; m->need_cctx_cleanup = 0; @@ -332,8 +334,8 @@ msginitprivate(dns_message_t *m) { static inline void msginittsig(dns_message_t *m) { - m->tsigstatus = m->querytsigstatus = dns_rcode_noerror; - m->tsig = m->querytsig = NULL; + m->tsigstatus = dns_rcode_noerror; + m->querytsigstatus = dns_rcode_noerror; m->tsigkey = NULL; m->tsigctx = NULL; m->sigstart = -1; @@ -341,6 +343,7 @@ msginittsig(dns_message_t *m) { m->sig0status = dns_rcode_noerror; m->query = NULL; m->saved = NULL; + m->querytsigset = NULL; } /* @@ -406,12 +409,26 @@ msgresetopt(dns_message_t *msg) } static void -msgresetsigs(dns_message_t *msg) { +msgresetsigs(dns_message_t *msg, isc_boolean_t replying) { + if (msg->sig_reserved > 0) { + dns_message_renderrelease(msg, msg->sig_reserved); + msg->sig_reserved = 0; + } if (msg->tsigset != NULL) { INSIST(dns_rdataset_isassociated(msg->tsigset)); INSIST(msg->namepool != NULL); - dns_rdataset_disassociate(msg->tsigset); - isc_mempool_put(msg->rdspool, msg->tsigset); + if (replying) { + INSIST(msg->querytsigset == NULL); + msg->querytsigset = msg->tsigset; + } else { + dns_rdataset_disassociate(msg->tsigset); + isc_mempool_put(msg->rdspool, msg->tsigset); + if (msg->querytsigset != NULL) { + dns_rdataset_disassociate(msg->querytsigset); + isc_mempool_put(msg->rdspool, + msg->querytsigset); + } + } isc_mempool_put(msg->namepool, msg->tsigname); msg->tsigset = NULL; msg->tsigname = NULL; @@ -440,7 +457,7 @@ msgreset(dns_message_t *msg, isc_boolean_t everything) { msgresetnames(msg, 0); msgresetopt(msg); - msgresetsigs(msg); + msgresetsigs(msg, ISC_FALSE); /* * Clean up linked lists. @@ -507,20 +524,6 @@ msgreset(dns_message_t *msg, isc_boolean_t everything) { if (msg->need_cctx_cleanup == 1) dns_compress_invalidate(&msg->cctx); - if (msg->tsig != NULL) { - dns_rdata_freestruct(msg->tsig); - isc_mem_put(msg->mctx, msg->tsig, - sizeof(dns_rdata_any_tsig_t)); - msg->tsig = NULL; - } - - if (msg->querytsig != NULL) { - dns_rdata_freestruct(msg->querytsig); - isc_mem_put(msg->mctx, msg->querytsig, - sizeof(dns_rdata_any_tsig_t)); - msg->querytsig = NULL; - } - if (msg->tsigkey != NULL) { dns_tsigkey_detach(&msg->tsigkey); msg->tsigkey = NULL; @@ -556,6 +559,43 @@ msgreset(dns_message_t *msg, isc_boolean_t everything) { msginit(msg); } +static unsigned int +spacefortsig(dns_tsigkey_t *key, int otherlen) { + isc_region_t r1, r2; + unsigned int x; + isc_result_t result; + + /* + * The space required for an TSIG record is: + * + * n1 bytes for the name + * 2 bytes for the type + * 2 bytes for the class + * 4 bytes for the ttl + * 6 bytes for the time signed + * 2 bytes for the fudge + * 2 bytes for the MAC size + * x bytes for the MAC + * 2 bytes for the original id + * 2 bytes for the error + * 2 bytes for the other data length + * y bytes for the other data (at most) + * --------------------------------- + * 30 + n1 + n2 + x + y bytes + */ + + dns_name_toregion(&key->name, &r1); + dns_name_toregion(&key->algorithm, &r2); + if (key->key == NULL) + x = 0; + else { + result = dst_key_sigsize(key->key, &x); + if (result != ISC_R_SUCCESS) + x = 0; + } + return (24 + r1.length + r2.length + x + otherlen); +} + isc_result_t dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) { @@ -1486,6 +1526,9 @@ dns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer) { isc_buffer_availableregion(buffer, &r); REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); + if (r.length < msg->reserved) + return (ISC_R_NOSPACE); + result = dns_compress_init(&msg->cctx, -1, msg->mctx); if (result != ISC_R_SUCCESS) return (result); @@ -1533,7 +1576,6 @@ dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { void dns_message_renderrelease(dns_message_t *msg, unsigned int space) { REQUIRE(DNS_MESSAGE_VALID(msg)); - REQUIRE(msg->buffer != NULL); REQUIRE(space <= msg->reserved); msg->reserved -= space; @@ -1544,11 +1586,12 @@ dns_message_renderreserve(dns_message_t *msg, unsigned int space) { isc_region_t r; REQUIRE(DNS_MESSAGE_VALID(msg)); - REQUIRE(msg->buffer != NULL); - isc_buffer_availableregion(msg->buffer, &r); - if (r.length < (space + msg->reserved)) - return (ISC_R_NOSPACE); + if (msg->buffer != NULL) { + isc_buffer_availableregion(msg->buffer, &r); + if (r.length < (space + msg->reserved)) + return (ISC_R_NOSPACE); + } msg->reserved += space; @@ -1772,7 +1815,8 @@ dns_message_renderend(dns_message_t *msg) { } if (msg->tsigkey != NULL) { - REQUIRE(msg->tsig == NULL); + dns_message_renderrelease(msg, msg->sig_reserved); + msg->sig_reserved = 0; result = dns_tsig_sign(msg); if (result != ISC_R_SUCCESS) return (result); @@ -1785,6 +1829,8 @@ dns_message_renderend(dns_message_t *msg) { } else if (msg->sig0key != NULL) { + dns_message_renderrelease(msg, msg->sig_reserved); + msg->sig_reserved = 0; result = dns_dnssec_signmessage(msg, msg->sig0key); if (result != ISC_R_SUCCESS) return (result); @@ -2100,6 +2146,7 @@ dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, isc_result_t dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { unsigned int first_section; + isc_result_t result; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); @@ -2118,7 +2165,7 @@ dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; msgresetnames(msg, first_section); msgresetopt(msg); - msgresetsigs(msg); + msgresetsigs(msg, ISC_TRUE); msginitprivate(msg); /* * We now clear most flags and then set QR, ensuring that the @@ -2128,15 +2175,21 @@ dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { msg->flags |= DNS_MESSAGEFLAG_QR; /* - * This saves the query TSIG information for later use, if there is - * any. This only happens once - that is, if dns_message_reply - * has already moved the variables, this has no effect. + * This saves the query TSIG status, if the query was signed, and + * reserves space in the reply for the TSIG. */ - if (msg->tsig != NULL) { - msg->querytsig = msg->tsig; - msg->tsig = NULL; + if (msg->querytsigset != NULL) { + unsigned int otherlen = 0; msg->querytsigstatus = msg->tsigstatus; msg->tsigstatus = dns_rcode_noerror; + if (msg->querytsigstatus == dns_tsigerror_badtime) + otherlen = 6; + msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); + result = dns_message_renderreserve(msg, msg->sig_reserved); + if (result != ISC_R_SUCCESS) { + msg->sig_reserved = 0; + return (result); + } } if (msg->saved != NULL) { msg->query = msg->saved; @@ -2188,7 +2241,6 @@ dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { REQUIRE(msg->state == DNS_SECTION_ANY); msgresetopt(msg); - msgresetsigs(msg); result = dns_rdataset_first(opt); if (result != ISC_R_SUCCESS) @@ -2220,18 +2272,31 @@ dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { return (msg->tsigset); } -void +isc_result_t dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { + isc_result_t result; /* * Set the TSIG key for 'msg' */ REQUIRE(DNS_MESSAGE_VALID(msg)); - REQUIRE(msg->tsigkey == NULL); + REQUIRE(msg->state == DNS_SECTION_ANY); + REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); - if (key != NULL) + if (key != NULL) { dns_tsigkey_attach(key, &msg->tsigkey); + if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { + msg->sig_reserved = spacefortsig(msg->tsigkey, 0); + result = dns_message_renderreserve(msg, + msg->sig_reserved); + if (result != ISC_R_SUCCESS) { + msg->sig_reserved = 0; + return (result); + } + } + } + return (ISC_R_SUCCESS); } dns_tsigkey_t * @@ -2246,6 +2311,88 @@ dns_message_gettsigkey(dns_message_t *msg) { return (msg->tsigkey); } +isc_result_t +dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { + dns_rdata_t *rdata = NULL; + dns_rdatalist_t *list = NULL; + dns_rdataset_t *set = NULL; + isc_buffer_t *buf = NULL; + isc_region_t r; + isc_result_t result; + + REQUIRE(DNS_MESSAGE_VALID(msg)); + REQUIRE(msg->querytsigset == NULL); + + if (querytsig == NULL) + return (ISC_R_SUCCESS); + + result = dns_message_gettemprdata(msg, &rdata); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdatalist(msg, &list); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdataset(msg, &set); + if (result != ISC_R_SUCCESS) + goto cleanup; + + isc_buffer_usedregion(querytsig, &r); + result = isc_buffer_allocate(msg->mctx, &buf, r.length); + if (result != ISC_R_SUCCESS) + goto cleanup; + isc_buffer_putmem(buf, r.base, r.length); + isc_buffer_usedregion(buf, &r); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); + dns_message_takebuffer(msg, &buf); + ISC_LIST_INIT(list->rdata); + ISC_LIST_APPEND(list->rdata, rdata, link); + result = dns_rdatalist_tordataset(list, set); + if (result != ISC_R_SUCCESS) + goto cleanup; + + msg->querytsigset = set; + + return (result); + + cleanup: + if (rdata != NULL) + dns_message_puttemprdata(msg, &rdata); + if (list != NULL) + dns_message_puttemprdatalist(msg, &list); + if (set != NULL) + dns_message_puttemprdataset(msg, &set); + return (ISC_R_NOMEMORY); +} + +isc_result_t +dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, + isc_buffer_t **querytsig) { + isc_result_t result; + dns_rdata_t rdata; + isc_region_t r; + + REQUIRE(DNS_MESSAGE_VALID(msg)); + REQUIRE(mctx != NULL); + REQUIRE(querytsig != NULL && *querytsig == NULL); + + if (msg->tsigset == NULL) + return (ISC_R_SUCCESS); + + result = dns_rdataset_first(msg->tsigset); + if (result != ISC_R_SUCCESS) + return (result); + dns_rdataset_current(msg->tsigset, &rdata); + dns_rdata_toregion(&rdata, &r); + + result = isc_buffer_allocate(mctx, querytsig, r.length); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_putmem(*querytsig, r.base, r.length); + return (ISC_R_SUCCESS); +} + dns_rdataset_t * dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { @@ -2272,6 +2419,71 @@ dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { } } +isc_result_t +dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { + isc_region_t r; + unsigned int x; + isc_result_t result; + + /* + * Set the SIG(0) key for 'msg' + */ + + /* + * The space required for an SIG(0) record is: + * + * 1 byte for the name + * 2 bytes for the type + * 2 bytes for the class + * 4 bytes for the ttl + * 2 bytes for the type covered + * 1 byte for the algorithm + * 1 bytes for the labels + * 4 bytes for the original ttl + * 4 bytes for the signature expiration + * 4 bytes for the signature inception + * 2 bytes for the key tag + * n bytes for the signer's name + * x bytes for the signature + * --------------------------------- + * 27 + n + x bytes + */ + REQUIRE(DNS_MESSAGE_VALID(msg)); + REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); + REQUIRE(msg->buffer != NULL); + REQUIRE(msg->state == DNS_SECTION_ANY); + REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); + + msg->sig0key = key; + if (key != NULL) { + dns_name_toregion(dst_key_name(key), &r); + result = dst_key_sigsize(key, &x); + if (result != ISC_R_SUCCESS) { + msg->sig_reserved = 0; + return (result); + } + msg->sig_reserved = 27 + r.length + x; + result = dns_message_renderreserve(msg, msg->sig_reserved); + if (result != ISC_R_SUCCESS) { + msg->sig_reserved = 0; + return (result); + } + } + return (ISC_R_SUCCESS); +} + +dst_key_t * +dns_message_getsig0key(dns_message_t *msg) { + + /* + * Get the SIG(0) key for 'msg' + */ + + REQUIRE(DNS_MESSAGE_VALID(msg)); + + return (msg->sig0key); +} + void dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { REQUIRE(DNS_MESSAGE_VALID(msg)); @@ -2286,12 +2498,13 @@ isc_result_t dns_message_signer(dns_message_t *msg, dns_name_t *signer) { isc_region_t r; isc_result_t result = ISC_R_SUCCESS; + dns_rdata_t rdata; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(signer != NULL); REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); - if ((msg->tsig == NULL || msg->tsigkey == NULL) && msg->sig0 == NULL) + if (msg->tsigset == NULL && msg->sig0 == NULL) return (ISC_R_NOTFOUND); if (msg->verify_attempted == 0) @@ -2307,14 +2520,13 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) { } if (msg->sig0 != NULL) { - dns_rdata_t rdata; dns_rdata_sig_t sig; result = dns_rdataset_first(msg->sig0); INSIST(result == ISC_R_SUCCESS); dns_rdataset_current(msg->sig0, &rdata); - result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); + result = dns_rdata_tostruct(&rdata, &sig, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -2328,9 +2540,16 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) { } else { dns_name_t *identity; + dns_rdata_any_tsig_t tsig; + + result = dns_rdataset_first(msg->tsigset); + INSIST(result == ISC_R_SUCCESS); + dns_rdataset_current(msg->tsigset, &rdata); + + result = dns_rdata_tostruct(&rdata, &tsig, NULL); if (msg->tsigstatus != dns_rcode_noerror) result = DNS_R_TSIGVERIFYFAILURE; - else if (msg->tsig->error != dns_rcode_noerror) + else if (tsig.error != dns_rcode_noerror) result = DNS_R_TSIGERRORSET; else result = ISC_R_SUCCESS; @@ -2342,6 +2561,7 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) { } dns_name_toregion(identity, &r); dns_name_fromregion(signer, &r); + dns_rdata_freestruct(&tsig); } return (result); diff --git a/lib/dns/request.c b/lib/dns/request.c index 89b5957f79..24adc24dca 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -78,7 +78,7 @@ struct dns_request { dns_dispentry_t *dispentry; isc_timer_t *timer; dns_requestmgr_t *requestmgr; - dns_rdata_any_tsig_t *tsig; + isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; }; @@ -539,8 +539,6 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, message->id = id; dns_message_settsigkey(message, request->tsigkey); result = req_render(message, &request->query, mctx); - request->tsig = message->tsig; - message->tsig = NULL; if (result == DNS_R_USETCP && (options & DNS_REQUESTOPT_TCP) == 0) { /* @@ -556,7 +554,11 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, } if (result != ISC_R_SUCCESS && result != DNS_R_USETCP) goto cleanup; - + + result = dns_message_getquerytsig(message, mctx, &request->tsig); + if (result != ISC_R_SUCCESS) + goto cleanup; + isc_mem_attach(mctx, &request->mctx); LOCK(&requestmgr->lock); if (requestmgr->exiting) { @@ -722,8 +724,7 @@ dns_request_getresponse(dns_request_t *request, dns_message_t *message, req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p", request); - message->querytsig = request->tsig; - request->tsig = NULL; + dns_message_setquerytsig(message, request->tsig); dns_message_settsigkey(message, request->tsigkey); return (dns_message_parse(message, request->answer, preserve_order)); } @@ -900,11 +901,8 @@ req_destroy(dns_request_t *request) { dns_dispatch_detach(&request->dispatch); if (request->timer != NULL) isc_timer_detach(&request->timer); - if (request->tsig != NULL) { - dns_rdata_freestruct(request->tsig); - isc_mem_put(request->mctx, request->tsig, - sizeof(*request->tsig)); - } + if (request->tsig != NULL) + isc_buffer_free(&request->tsig); requestmgr_detach(&request->requestmgr); mctx = request->mctx; isc_mem_put(mctx, request, sizeof(*request)); diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 3d4170c6a3..a15551aa46 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -103,7 +104,7 @@ typedef struct query { dns_dispentry_t * dispentry; ISC_LINK(struct query) link; isc_buffer_t buffer; - dns_rdata_any_tsig_t *tsig; + isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; unsigned int options; unsigned int attributes; @@ -384,11 +385,8 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, if (query->dispentry != NULL) dns_dispatch_removeresponse(&query->dispentry, deventp); ISC_LIST_UNLINK(fctx->queries, query, link); - if (query->tsig != NULL) { - dns_rdata_freestruct(query->tsig); - isc_mem_put(query->fctx->res->mctx, query->tsig, - sizeof(*query->tsig)); - } + if (query->tsig != NULL) + isc_buffer_free(&query->tsig); if (RESQUERY_CONNECTING(query)) { /* * Cancel the connect. @@ -933,8 +931,11 @@ resquery_send(resquery_t *query) { if (dns_message_gettsigkey(fctx->qmessage) != NULL) { dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage), &query->tsigkey); - query->tsig = fctx->qmessage->tsig; - fctx->qmessage->tsig = NULL; + result = dns_message_getquerytsig(fctx->qmessage, + fctx->res->mctx, + &query->tsig); + if (result != ISC_R_SUCCESS) + goto cleanup_message; } /* @@ -3473,6 +3474,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { isc_time_t tnow, *finish; dns_adbaddrinfo_t *addrinfo; unsigned int options; + dns_name_t *tsigowner = NULL; REQUIRE(VALID_QUERY(query)); fctx = query->fctx; @@ -3534,10 +3536,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) { message = fctx->rmessage; - /* BEW - clean this up at some point */ - message->querytsig = query->tsig; - dns_message_settsigkey(message, query->tsigkey); - query->tsig = NULL; + if (query->tsig != NULL) { + result = dns_message_setquerytsig(message, query->tsig); + if (result != ISC_R_SUCCESS) + goto done; + } result = dns_message_parse(message, &devent->buffer, ISC_FALSE); if (result != ISC_R_SUCCESS) { @@ -3623,10 +3626,21 @@ resquery_response(isc_task_t *task, isc_event_t *event) { result = dns_message_checksig(message, fctx->res->view); if (result != ISC_R_SUCCESS) goto done; - if (message->tsig != NULL && message->tsig->error != dns_rcode_noerror) - { - result = DNS_R_FORMERR; /* BEW - good enough for now */ - goto done; + if (dns_message_gettsig(message, &tsigowner) != NULL) { + dns_rdata_any_tsig_t tsig; + dns_rdata_t rdata; + + result = dns_rdataset_first(message->tsigset); + if (result != ISC_R_SUCCESS) + goto done; + dns_rdataset_current(message->tsigset, &rdata); + result = dns_rdata_tostruct(&rdata, &tsig, NULL); + if (result != ISC_R_SUCCESS) + goto done; + if (tsig.error != dns_rcode_noerror) { + result = DNS_R_FORMERR; /* BEW - good enough for now */ + goto done; + } } /* diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index b237a2ceb6..5f4a2e3bbc 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -16,13 +16,14 @@ */ /* - * $Id: tsig.c,v 1.65 2000/05/27 00:24:07 bwelling Exp $ + * $Id: tsig.c,v 1.66 2000/05/30 23:14:54 bwelling Exp $ * Principal Author: Brian Wellington */ #include #include /* Required for abs(). */ +#include #include #include #include /* Required for HP/UX (and others?) */ @@ -33,6 +34,7 @@ #include #include #include +#include #include #include @@ -238,7 +240,7 @@ dns_tsigkey_setdeleted(dns_tsigkey_t *key) { isc_result_t dns_tsig_sign(dns_message_t *msg) { dns_tsigkey_t *key; - dns_rdata_any_tsig_t tsig; + dns_rdata_any_tsig_t tsig, querytsig; unsigned char data[128]; isc_buffer_t databuf, sigbuf; isc_buffer_t *dynbuf; @@ -251,16 +253,14 @@ dns_tsig_sign(dns_message_t *msg) { dst_context_t ctx; isc_mem_t *mctx; isc_result_t ret; - isc_boolean_t algfreed = ISC_FALSE; REQUIRE(msg != NULL); REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); - REQUIRE(msg->tsig == NULL); /* * If this is a response, there should be a query tsig. */ - if (is_response(msg) && msg->querytsig == NULL) + if (is_response(msg) && msg->querytsigset == NULL) return (DNS_R_EXPECTEDTSIG); dynbuf = NULL; @@ -273,9 +273,7 @@ dns_tsig_sign(dns_message_t *msg) { tsig.common.rdtype = dns_rdatatype_tsig; ISC_LINK_INIT(&tsig.common, link); dns_name_init(&tsig.algorithm, NULL); - ret = dns_name_dup(&key->algorithm, mctx, &tsig.algorithm); - if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + dns_name_clone(&key->algorithm, &tsig.algorithm); isc_stdtime_get(&now); tsig.timesigned = now; @@ -318,24 +316,37 @@ dns_tsig_sign(dns_message_t *msg) { ret = dst_key_sign(DST_SIGMODE_INIT, key->key, &ctx, NULL, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_algorithm; + goto cleanup_other; /* * If this is a response, digest the query signature. */ if (is_response(msg)) { - isc_buffer_putuint16(&databuf, msg->querytsig->siglen); - isc_buffer_availableregion(&databuf, &r); - if (r.length < msg->querytsig->siglen) - return (ISC_R_NOSPACE); - memcpy(r.base, msg->querytsig->signature, - msg->querytsig->siglen); - isc_buffer_add(&databuf, msg->querytsig->siglen); + dns_rdata_t querytsigrdata; + + ret = dns_rdataset_first(msg->querytsigset); + if (ret != ISC_R_SUCCESS) + goto cleanup_other; + dns_rdataset_current(msg->querytsigset, + &querytsigrdata); + ret = dns_rdata_tostruct(&querytsigrdata, &querytsig, + NULL); + if (ret != ISC_R_SUCCESS) + goto cleanup_other; + isc_buffer_putuint16(&databuf, querytsig.siglen); + if (isc_buffer_availablelength(&databuf) < + querytsig.siglen) + { + ret = ISC_R_NOSPACE; + goto cleanup_other; + } + isc_buffer_putmem(&databuf, querytsig.signature, + querytsig.siglen); isc_buffer_usedregion(&databuf, &r); ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, &r, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_algorithm; + goto cleanup_other; } /* @@ -396,7 +407,7 @@ dns_tsig_sign(dns_message_t *msg) { 0xFFFFFFFF)); } else { - isc_uint64_t querysigned = msg->querytsig->timesigned; + isc_uint64_t querysigned = querytsig.timesigned; isc_buffer_putuint16(&databuf, (isc_uint16_t)(querysigned >> 32)); @@ -472,6 +483,8 @@ dns_tsig_sign(dns_message_t *msg) { if (ret != ISC_R_SUCCESS) goto cleanup_dynbuf; + dns_message_takebuffer(msg, &dynbuf); + if (tsig.signature != NULL) { isc_mem_put(mctx, tsig.signature, tsig.siglen); tsig.signature = NULL; @@ -480,29 +493,16 @@ dns_tsig_sign(dns_message_t *msg) { isc_mem_put(mctx, tsig.other, tsig.otherlen); tsig.other = NULL; } - dns_name_free(&tsig.algorithm, mctx); - algfreed = ISC_TRUE; - - msg->tsig = isc_mem_get(mctx, sizeof(dns_rdata_any_tsig_t)); - if (msg->tsig == NULL) { - ret = ISC_R_NOMEMORY; - goto cleanup_dynbuf; - } - ret = dns_rdata_tostruct(rdata, msg->tsig, mctx); - if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; - - dns_message_takebuffer(msg, &dynbuf); owner = NULL; ret = dns_message_gettempname(msg, &owner); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; dns_name_toregion(&key->name, &r); dynbuf = NULL; ret = isc_buffer_allocate(mctx, &dynbuf, r.length); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; isc_buffer_availableregion(dynbuf, &r2); memcpy(r2.base, r.base, r.length); dns_name_init(owner, NULL); @@ -512,7 +512,7 @@ dns_tsig_sign(dns_message_t *msg) { datalist = NULL; ret = dns_message_gettemprdatalist(msg, &datalist); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; datalist->rdclass = dns_rdataclass_any; datalist->type = dns_rdatatype_tsig; datalist->covers = 0; @@ -522,7 +522,7 @@ dns_tsig_sign(dns_message_t *msg) { dataset = NULL; ret = dns_message_gettemprdataset(msg, &dataset); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; dns_rdataset_init(dataset); dns_rdatalist_tordataset(datalist, dataset); msg->tsigset = dataset; @@ -530,9 +530,6 @@ dns_tsig_sign(dns_message_t *msg) { return (ISC_R_SUCCESS); -cleanup_tsig: - dns_rdata_freestruct(msg->tsig); - isc_mem_put(mctx, msg->tsig, sizeof *msg->tsig); cleanup_dynbuf: if (dynbuf != NULL) isc_buffer_free(&dynbuf); @@ -542,11 +539,6 @@ cleanup_signature: cleanup_other: if (tsig.other != NULL) isc_mem_put(mctx, tsig.other, tsig.otherlen); -cleanup_algorithm: - if (!algfreed) - dns_name_free(&tsig.algorithm, mctx); -cleanup_struct: - msg->tsig = NULL; return (ret); } @@ -555,7 +547,7 @@ isc_result_t dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, dns_tsig_keyring_t *sring, dns_tsig_keyring_t *dring) { - dns_rdata_any_tsig_t *tsig; + dns_rdata_any_tsig_t tsig, querytsig; isc_region_t r, source_r, header_r, sig_r; isc_buffer_t databuf; unsigned char data[32]; @@ -572,7 +564,6 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, REQUIRE(source != NULL); REQUIRE(DNS_MESSAGE_VALID(msg)); - REQUIRE(msg->tsig == NULL); tsigkey = dns_message_gettsigkey(msg); REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey)); @@ -592,7 +583,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, * shouldn't be one on the response. */ if (is_response(msg) && - (tsigkey == NULL || msg->querytsig == NULL)) + (tsigkey == NULL || msg->querytsigset == NULL)) return (DNS_R_UNEXPECTEDTSIG); mctx = msg->mctx; @@ -607,21 +598,25 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, if (ret != ISC_R_SUCCESS) return (ret); dns_rdataset_current(msg->tsigset, &rdata); - tsig = (dns_rdata_any_tsig_t *) - isc_mem_get(mctx, sizeof(dns_rdata_any_tsig_t)); - if (tsig == NULL) - return (ISC_R_NOMEMORY); - msg->tsig = tsig; - ret = dns_rdata_tostruct(&rdata, tsig, mctx); + ret = dns_rdata_tostruct(&rdata, &tsig, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_emptystruct; + return (ret); + if (is_response(msg)) { + ret = dns_rdataset_first(msg->querytsigset); + if (ret != ISC_R_SUCCESS) + return (ret); + dns_rdataset_current(msg->querytsigset, &rdata); + ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); + if (ret != ISC_R_SUCCESS) + return (ret); + } /* * Do the key name and algorithm match that of the query? */ if (is_response(msg) && (!dns_name_equal(keyname, &tsigkey->name) || - !dns_name_equal(&tsig->algorithm, &msg->querytsig->algorithm))) + !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) { msg->tsigstatus = dns_tsigerror_badkey; return (DNS_R_TSIGVERIFYFAILURE); @@ -639,22 +634,20 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, ret = ISC_R_NOTFOUND; if (sring != NULL) ret = dns_tsigkey_find(&tsigkey, keyname, - &tsig->algorithm, sring); + &tsig.algorithm, sring); if (ret == ISC_R_NOTFOUND && dring != NULL) ret = dns_tsigkey_find(&tsigkey, keyname, - &tsig->algorithm, dring); + &tsig.algorithm, dring); if (ret != ISC_R_SUCCESS) { - if (dring == NULL) { - ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_struct; - } + if (dring == NULL) + return (DNS_R_TSIGVERIFYFAILURE); msg->tsigstatus = dns_tsigerror_badkey; - ret = dns_tsigkey_create(keyname, &tsig->algorithm, + ret = dns_tsigkey_create(keyname, &tsig.algorithm, NULL, 0, ISC_FALSE, NULL, now, now, mctx, dring, &msg->tsigkey); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); return (DNS_R_TSIGVERIFYFAILURE); } msg->tsigkey = tsigkey; @@ -665,14 +658,14 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, /* * Is the time ok? */ - if (abs(now - tsig->timesigned) > tsig->fudge) { + if (abs(now - tsig.timesigned) > tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; return (DNS_R_TSIGVERIFYFAILURE); } - if (tsig->siglen > 0) { - sig_r.base = tsig->signature; - sig_r.length = tsig->siglen; + if (tsig.siglen > 0) { + sig_r.base = tsig.signature; + sig_r.length = tsig.siglen; ret = dst_key_verify(DST_SIGMODE_INIT, key, &ctx, NULL, &sig_r); @@ -681,15 +674,15 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, if (is_response(msg)) { isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, msg->querytsig->siglen); + isc_buffer_putuint16(&databuf, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, NULL); if (ret != ISC_R_SUCCESS) goto cleanup_key; - if (msg->querytsig->siglen > 0) { - r.length = msg->querytsig->siglen; - r.base = msg->querytsig->signature; + if (querytsig.siglen > 0) { + r.length = querytsig.siglen; + r.base = querytsig.signature; ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, NULL); if (ret != ISC_R_SUCCESS) @@ -714,7 +707,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, /* * Put in the original id. */ - id = htons(tsig->originalid); + id = htons(tsig.originalid); memcpy(&header[0], &id, 2); /* @@ -748,7 +741,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, goto cleanup_key; isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, tsig->common.rdclass); + isc_buffer_putuint16(&databuf, tsig.common.rdclass); isc_buffer_putuint32(&databuf, msg->tsigset->ttl); isc_buffer_usedregion(&databuf, &r); ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, @@ -766,20 +759,20 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, goto cleanup_key; isc_buffer_clear(&databuf); - isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig->timesigned + isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig.timesigned >> 32)); - isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig->timesigned + isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig.timesigned & 0xFFFFFFFF)); - isc_buffer_putuint16(&databuf, tsig->fudge); - isc_buffer_putuint16(&databuf, tsig->error); - isc_buffer_putuint16(&databuf, tsig->otherlen); + isc_buffer_putuint16(&databuf, tsig.fudge); + isc_buffer_putuint16(&databuf, tsig.error); + isc_buffer_putuint16(&databuf, tsig.otherlen); isc_buffer_usedregion(&databuf, &r); ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); - if (tsig->otherlen > 0) { - r.base = tsig->other; - r.length = tsig->otherlen; + if (tsig.otherlen > 0) { + r.base = tsig.other; + r.length = tsig.otherlen; ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); if (ret != ISC_R_SUCCESS) @@ -795,8 +788,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, else if (ret != ISC_R_SUCCESS) goto cleanup_key; } - else if (tsig->error != dns_tsigerror_badsig && - tsig->error != dns_tsigerror_badkey) + else if (tsig.error != dns_tsigerror_badsig && + tsig.error != dns_tsigerror_badkey) { msg->tsigstatus = dns_tsigerror_badsig; return (DNS_R_TSIGVERIFYFAILURE); @@ -804,7 +797,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, msg->tsigstatus = dns_rcode_noerror; - if (tsig->error != dns_rcode_noerror) { + if (tsig.error != dns_rcode_noerror) { if (is_response(msg)) { /* XXXBEW Log a message */ return (ISC_R_SUCCESS); @@ -820,17 +813,13 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, cleanup_key: if (dns_tsigkey_empty(tsigkey)) dns_tsigkey_detach(&tsigkey); -cleanup_struct: - dns_rdata_freestruct(tsig); -cleanup_emptystruct: - msg->tsig = NULL; - isc_mem_put(mctx, tsig, sizeof(dns_rdata_any_tsig_t)); + return (ret); } static isc_result_t dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - dns_rdata_any_tsig_t *tsig = NULL; + dns_rdata_any_tsig_t tsig, querytsig; isc_region_t r, source_r, header_r, sig_r; isc_buffer_t databuf; unsigned char data[32]; @@ -847,11 +836,10 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { REQUIRE(source != NULL); REQUIRE(msg != NULL); - REQUIRE(msg->tsig == NULL); REQUIRE(dns_message_gettsigkey(msg) != NULL); REQUIRE(msg->tcp_continuation == 1); REQUIRE(is_response(msg)); - REQUIRE(msg->querytsig != NULL); + REQUIRE(msg->querytsigset != NULL); mctx = msg->mctx; @@ -865,21 +853,22 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { if (ret != ISC_R_SUCCESS) return (ret); dns_rdataset_current(msg->tsigset, &rdata); - tsig = (dns_rdata_any_tsig_t *) - isc_mem_get(mctx, sizeof(dns_rdata_any_tsig_t)); - if (tsig == NULL) - return (ISC_R_NOMEMORY); - msg->tsig = tsig; - ret = dns_rdata_tostruct(&rdata, tsig, mctx); + ret = dns_rdata_tostruct(&rdata, &tsig, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_emptystruct; + return (ret); + ret = dns_rdataset_first(msg->querytsigset); + if (ret != ISC_R_SUCCESS) + return (ret); + dns_rdataset_current(msg->querytsigset, &rdata); + ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); + if (ret != ISC_R_SUCCESS) + return (ret); /* * Do the key name and algorithm match that of the query? */ if (!dns_name_equal(keyname, &tsigkey->name) || - !dns_name_equal(&tsig->algorithm, - &msg->querytsig->algorithm)) + !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) { msg->tsigstatus = dns_tsigerror_badkey; return (DNS_R_TSIGVERIFYFAILURE); @@ -889,7 +878,7 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { * Is the time ok? */ isc_stdtime_get(&now); - if (abs(now - tsig->timesigned) > tsig->fudge) { + if (abs(now - tsig.timesigned) > tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; return (DNS_R_TSIGVERIFYFAILURE); } @@ -901,22 +890,22 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { ret = dst_key_verify(DST_SIGMODE_INIT, key, &msg->tsigctx, NULL, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, msg->querytsig->siglen); + isc_buffer_putuint16(&databuf, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &r, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; - if (msg->querytsig->siglen > 0) { - r.length = msg->querytsig->siglen; - r.base = msg->querytsig->signature; + return (ret); + if (querytsig.siglen > 0) { + r.length = querytsig.siglen; + r.base = querytsig.signature; ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &r, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); } } @@ -940,8 +929,8 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { * Put in the original id. */ /* XXX Can TCP transfers be forwarded? How would that work? */ - if (tsig != NULL) { - id = htons(tsig->originalid); + if (has_tsig) { + id = htons(tsig.originalid); memcpy(&header[0], &id, 2); } @@ -953,7 +942,7 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &header_r, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); /* * Digest all non-TSIG records. @@ -966,30 +955,30 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { r.length = source_r.length - DNS_MESSAGE_HEADERLEN; ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &r, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); /* * Digest the time signed and fudge. */ if (has_tsig) { isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig->timesigned + isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig.timesigned >> 32)); - isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig->timesigned + isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig.timesigned & 0xFFFFFFFF)); - isc_buffer_putuint16(&databuf, tsig->fudge); + isc_buffer_putuint16(&databuf, tsig.fudge); isc_buffer_usedregion(&databuf, &r); ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &r, NULL); - sig_r.base = tsig->signature; - sig_r.length = tsig->siglen; - if (tsig->siglen == 0) { - if (tsig->error != dns_rcode_noerror) + sig_r.base = tsig.signature; + sig_r.length = tsig.siglen; + if (tsig.siglen == 0) { + if (tsig.error != dns_rcode_noerror) ret = DNS_R_TSIGERRORSET; else ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_struct; + return (ret); } ret = dst_key_verify(DST_SIGMODE_FINAL, key, &msg->tsigctx, @@ -999,20 +988,13 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { return (DNS_R_TSIGVERIFYFAILURE); } else if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); msg->tsigctx = NULL; } msg->tsigstatus = dns_rcode_noerror; return (ISC_R_SUCCESS); - -cleanup_struct: - dns_rdata_freestruct(tsig); -cleanup_emptystruct: - msg->tsig = NULL; - isc_mem_put(mctx, tsig, sizeof(dns_rdata_any_tsig_t)); - return (ret); } isc_result_t diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index 1cbfdd7c6d..4e23e4822e 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: xfrin.c,v 1.73 2000/05/26 00:38:12 gson Exp $ */ +/* $Id: xfrin.c,v 1.74 2000/05/30 23:14:55 bwelling Exp $ */ #include @@ -132,7 +132,7 @@ struct dns_xfrin_ctx { unsigned int nmsg; /* Number of messages recvd */ dns_tsigkey_t *tsigkey; /* Key used to create TSIG */ - dns_rdata_any_tsig_t *lasttsig; /* The last TSIG */ + isc_buffer_t *lasttsig; /* The last TSIG */ void *tsigctx; /* TSIG verification context */ unsigned int sincetsig; /* recvd since the last TSIG */ dns_xfrindone_t done; @@ -853,8 +853,7 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) { /* * Save the query TSIG and don't let message_destroy free it. */ - xfr->lasttsig = msg->tsig; - msg->tsig = NULL; + CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); isc_buffer_usedregion(&xfr->qbuffer, ®ion); INSIST(region.length <= 65535); @@ -946,6 +945,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { dns_message_t *msg = NULL; dns_name_t *name; dns_tcpmsg_t *tcpmsg; + dns_name_t *tsigowner = NULL; REQUIRE(VALID_XFRIN(xfr)); @@ -971,7 +971,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg)); dns_message_settsigkey(msg, xfr->tsigkey); - msg->querytsig = xfr->lasttsig; + dns_message_setquerytsig(msg, xfr->lasttsig); msg->tsigctx = xfr->tsigctx; if (xfr->nmsg > 0) msg->tcp_continuation = 1; @@ -1030,7 +1030,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { if (result != ISC_R_NOMORE) goto failure; - if (msg->tsig != NULL) { + if (dns_message_gettsig(msg, &tsigowner) != NULL) { /* * Reset the counter. */ @@ -1039,21 +1039,14 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { /* * Free the last tsig, if there is one. */ - if (xfr->lasttsig != NULL) { - dns_rdata_freestruct(xfr->lasttsig); - isc_mem_put(xfr->mctx, xfr->lasttsig, - sizeof(*xfr->lasttsig)); - } + if (xfr->lasttsig != NULL) + isc_buffer_free(&xfr->lasttsig); /* * Update the last tsig pointer. */ - xfr->lasttsig = msg->tsig; + CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); - /* - * Reset msg->tsig so it doesn't get freed. - */ - msg->tsig = NULL; } else if (dns_message_gettsigkey(msg) != NULL) { xfr->sincetsig++; if (xfr->sincetsig > 100 || @@ -1069,11 +1062,6 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { */ xfr->nmsg++; - /* - * Reset msg->querytsig so it doesn't get freed. - */ - msg->querytsig = NULL; - /* * Copy the context back. */ @@ -1110,10 +1098,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { return; failure: - if (msg != NULL) { - msg->querytsig = NULL; + if (msg != NULL) dns_message_destroy(&msg); - } if (result != ISC_R_SUCCESS) xfrin_fail(xfr, result, "receiving responses"); } @@ -1153,10 +1139,8 @@ maybe_free(dns_xfrin_ctx_t *xfr) { if (xfr->task != NULL) isc_task_detach(&xfr->task); - if (xfr->lasttsig != NULL) { - dns_rdata_freestruct(xfr->lasttsig); - isc_mem_put(xfr->mctx, xfr->lasttsig, sizeof(*xfr->lasttsig)); - } + if (xfr->lasttsig != NULL) + isc_buffer_free(&xfr->lasttsig); dns_diff_clear(&xfr->diff);