1999-10-26 15:39:59 +00:00
|
|
|
/*
|
2011-01-08 23:47:01 +00:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
1999-10-26 15:39:59 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
1999-10-26 15:39:59 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
1999-10-26 15:39:59 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
|
2018-08-07 16:46:53 +02:00
|
|
|
#if HAVE_GSSAPI_GSSAPI_H
|
|
|
|
#include <gssapi/gssapi.h>
|
|
|
|
#elif HAVE_GSSAPI_H
|
|
|
|
#include <gssapi.h>
|
|
|
|
#endif
|
|
|
|
|
2000-05-30 22:28:37 +00:00
|
|
|
#include <isc/buffer.h>
|
2023-04-13 17:46:49 -07:00
|
|
|
#include <isc/hex.h>
|
2018-06-01 09:31:59 +02:00
|
|
|
#include <isc/md.h>
|
2000-01-21 20:18:41 +00:00
|
|
|
#include <isc/mem.h>
|
2018-05-28 15:22:23 +02:00
|
|
|
#include <isc/nonce.h>
|
2018-04-22 14:56:28 +02:00
|
|
|
#include <isc/random.h>
|
2021-10-04 17:14:53 +02:00
|
|
|
#include <isc/result.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
#include <dns/dnssec.h>
|
2001-02-14 00:43:10 +00:00
|
|
|
#include <dns/fixedname.h>
|
1999-10-26 15:39:59 +00:00
|
|
|
#include <dns/keyvalues.h>
|
2000-06-23 01:51:35 +00:00
|
|
|
#include <dns/log.h>
|
1999-10-26 15:39:59 +00:00
|
|
|
#include <dns/message.h>
|
2000-05-30 22:28:37 +00:00
|
|
|
#include <dns/name.h>
|
1999-10-26 15:39:59 +00:00
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdatalist.h>
|
|
|
|
#include <dns/rdataset.h>
|
2000-05-30 22:28:37 +00:00
|
|
|
#include <dns/rdatastruct.h>
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/result.h>
|
1999-10-26 15:39:59 +00:00
|
|
|
#include <dns/tkey.h>
|
|
|
|
#include <dns/tsig.h>
|
|
|
|
|
2000-10-06 17:08:15 +00:00
|
|
|
#include <dst/dst.h>
|
|
|
|
#include <dst/gssapi.h>
|
2020-03-09 16:17:26 +01:00
|
|
|
|
|
|
|
#include "dst_internal.h"
|
2023-04-11 19:01:31 -07:00
|
|
|
#include "tsig_p.h"
|
2014-01-14 15:40:56 -08:00
|
|
|
|
2015-08-14 08:20:01 +10:00
|
|
|
#define TEMP_BUFFER_SZ 8192
|
1999-10-28 20:00:04 +00:00
|
|
|
#define TKEY_RANDOM_AMOUNT 16
|
|
|
|
|
1999-10-26 17:25:07 +00:00
|
|
|
#define RETERR(x) \
|
|
|
|
do { \
|
1999-10-26 15:39:59 +00:00
|
|
|
result = (x); \
|
|
|
|
if (result != ISC_R_SUCCESS) \
|
|
|
|
goto failure; \
|
|
|
|
} while (0)
|
|
|
|
|
2001-08-08 22:54:55 +00:00
|
|
|
static void
|
|
|
|
tkey_log(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2);
|
|
|
|
|
2000-06-23 01:51:35 +00:00
|
|
|
static void
|
|
|
|
tkey_log(const char *fmt, ...) {
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_vwrite(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_REQUEST,
|
2000-06-23 01:51:35 +00:00
|
|
|
ISC_LOG_DEBUG(4), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
isc_result_t
|
2018-04-22 14:56:28 +02:00
|
|
|
dns_tkeyctx_create(isc_mem_t *mctx, dns_tkeyctx_t **tctxp) {
|
1999-10-26 15:39:59 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
2000-06-09 22:33:08 +00:00
|
|
|
REQUIRE(tctxp != NULL && *tctxp == NULL);
|
2000-01-21 20:18:41 +00:00
|
|
|
|
2023-02-28 16:05:34 +01:00
|
|
|
dns_tkeyctx_t *tctx = isc_mem_get(mctx, sizeof(*tctx));
|
|
|
|
*tctx = (dns_tkeyctx_t){
|
|
|
|
.mctx = NULL,
|
|
|
|
};
|
2000-06-09 22:33:08 +00:00
|
|
|
isc_mem_attach(mctx, &tctx->mctx);
|
|
|
|
|
|
|
|
*tctxp = tctx;
|
1999-10-26 15:39:59 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-11-05 16:53:47 +00:00
|
|
|
void
|
2000-06-09 22:33:08 +00:00
|
|
|
dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
|
2023-04-13 01:22:09 -07:00
|
|
|
isc_mem_t *mctx = NULL;
|
|
|
|
dns_tkeyctx_t *tctx = NULL;
|
2000-01-21 20:18:41 +00:00
|
|
|
|
2000-06-09 22:33:08 +00:00
|
|
|
REQUIRE(tctxp != NULL && *tctxp != NULL);
|
|
|
|
|
|
|
|
tctx = *tctxp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*tctxp = NULL;
|
2000-06-09 22:33:08 +00:00
|
|
|
mctx = tctx->mctx;
|
2000-01-21 20:18:41 +00:00
|
|
|
|
2000-06-09 22:33:08 +00:00
|
|
|
if (tctx->domain != NULL) {
|
2000-10-12 00:40:52 +00:00
|
|
|
if (dns_name_dynamic(tctx->domain)) {
|
|
|
|
dns_name_free(tctx->domain, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-09 22:33:08 +00:00
|
|
|
isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
|
|
|
|
}
|
2010-12-18 01:56:23 +00:00
|
|
|
if (tctx->gssapi_keytab != NULL) {
|
|
|
|
isc_mem_free(mctx, tctx->gssapi_keytab);
|
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
if (tctx->gsscred != NULL) {
|
|
|
|
dst_gssapi_releasecred(&tctx->gsscred);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-07-23 17:16:57 -04:00
|
|
|
isc_mem_putanddetach(&mctx, tctx, sizeof(dns_tkeyctx_t));
|
1999-11-05 16:53:47 +00:00
|
|
|
}
|
|
|
|
|
2022-07-29 12:40:45 +00:00
|
|
|
static void
|
1999-10-26 15:39:59 +00:00
|
|
|
add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t ttl, dns_namelist_t *namelist) {
|
1999-10-26 15:39:59 +00:00
|
|
|
isc_region_t r, newr;
|
|
|
|
dns_rdata_t *newrdata = NULL;
|
|
|
|
dns_name_t *newname = NULL;
|
|
|
|
dns_rdatalist_t *newlist = NULL;
|
|
|
|
dns_rdataset_t *newset = NULL;
|
2000-10-07 00:09:28 +00:00
|
|
|
isc_buffer_t *tmprdatabuf = NULL;
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettemprdata(msg, &newrdata);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
dns_rdata_toregion(rdata, &r);
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_availableregion(tmprdatabuf, &newr);
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(newr.base, r.base, r.length);
|
1999-10-26 15:39:59 +00:00
|
|
|
dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
|
|
|
|
dns_message_takebuffer(msg, &tmprdatabuf);
|
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettempname(msg, &newname);
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(name, newname);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettemprdatalist(msg, &newlist);
|
1999-10-26 15:39:59 +00:00
|
|
|
newlist->rdclass = newrdata->rdclass;
|
|
|
|
newlist->type = newrdata->type;
|
|
|
|
newlist->ttl = ttl;
|
|
|
|
ISC_LIST_APPEND(newlist->rdata, newrdata, link);
|
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettemprdataset(msg, &newset);
|
2022-07-29 12:40:45 +00:00
|
|
|
dns_rdatalist_tordataset(newlist, newset);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
ISC_LIST_INIT(newname->list);
|
|
|
|
ISC_LIST_APPEND(newname->list, newset, link);
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(*namelist, newname, link);
|
|
|
|
}
|
|
|
|
|
2001-01-11 04:23:39 +00:00
|
|
|
static void
|
|
|
|
free_namelist(dns_message_t *msg, dns_namelist_t *namelist) {
|
2023-04-13 01:22:09 -07:00
|
|
|
dns_name_t *name = NULL;
|
2001-01-11 04:23:39 +00:00
|
|
|
|
2023-04-13 17:46:49 -07:00
|
|
|
while ((name = ISC_LIST_HEAD(*namelist)) != NULL) {
|
|
|
|
dns_rdataset_t *set = NULL;
|
2001-01-11 04:23:39 +00:00
|
|
|
ISC_LIST_UNLINK(*namelist, name, link);
|
2023-04-13 17:46:49 -07:00
|
|
|
while ((set = ISC_LIST_HEAD(name->list)) != NULL) {
|
2001-01-11 04:23:39 +00:00
|
|
|
ISC_LIST_UNLINK(name->list, set, link);
|
2021-12-21 12:44:17 +11:00
|
|
|
if (dns_rdataset_isassociated(set)) {
|
|
|
|
dns_rdataset_disassociate(set);
|
|
|
|
}
|
2001-01-11 04:23:39 +00:00
|
|
|
dns_message_puttemprdataset(msg, &set);
|
|
|
|
}
|
|
|
|
dns_message_puttempname(msg, &name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-10-06 17:08:15 +00:00
|
|
|
static isc_result_t
|
2019-01-29 18:10:27 +01:00
|
|
|
process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
|
2010-12-02 23:22:42 +00:00
|
|
|
dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
|
2023-04-11 11:35:01 -07:00
|
|
|
dns_tsigkeyring_t *ring) {
|
2000-10-06 17:08:15 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
dst_key_t *dstkey = NULL;
|
2006-12-04 01:54:53 +00:00
|
|
|
dns_tsigkey_t *tsigkey = NULL;
|
2023-04-13 01:22:09 -07:00
|
|
|
dns_fixedname_t fprincipal;
|
|
|
|
dns_name_t *principal = dns_fixedname_initname(&fprincipal);
|
2023-03-30 21:13:41 +02:00
|
|
|
isc_stdtime_t now = isc_stdtime_now();
|
2000-10-06 17:08:15 +00:00
|
|
|
isc_region_t intoken;
|
2006-12-05 21:59:12 +00:00
|
|
|
isc_buffer_t *outtoken = NULL;
|
2021-02-11 14:40:59 +01:00
|
|
|
dns_gss_ctx_id_t gss_ctx = NULL;
|
2000-10-06 17:08:15 +00:00
|
|
|
|
2010-12-18 23:47:11 +00:00
|
|
|
/*
|
2010-12-18 01:56:23 +00:00
|
|
|
* You have to define either a gss credential (principal) to
|
|
|
|
* accept with tkey-gssapi-credential, or you have to
|
|
|
|
* configure a specific keytab (with tkey-gssapi-keytab) in
|
2019-01-29 18:10:27 +01:00
|
|
|
* order to use gsstkey.
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
|
|
|
if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
|
|
|
|
tkey_log("process_gsstkey(): no tkey-gssapi-credential "
|
|
|
|
"or tkey-gssapi-keytab configured");
|
2023-07-27 08:34:45 +10:00
|
|
|
return (DNS_R_REFUSED);
|
2010-12-18 01:56:23 +00:00
|
|
|
}
|
2010-12-18 23:47:11 +00:00
|
|
|
|
2023-04-14 12:56:24 -07:00
|
|
|
if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME)) {
|
2000-10-06 17:08:15 +00:00
|
|
|
tkeyout->error = dns_tsigerror_badalg;
|
2023-04-14 12:56:24 -07:00
|
|
|
tkey_log("process_gsstkey(): dns_tsigerror_badalg");
|
2000-10-06 17:08:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
/*
|
|
|
|
* XXXDCL need to check for key expiry per 4.1.1
|
|
|
|
* XXXDCL need a way to check fully established, perhaps w/key_flags
|
|
|
|
*/
|
|
|
|
result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
gss_ctx = dst_key_getgssctx(tsigkey->key);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-10-06 17:08:15 +00:00
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
/*
|
2010-12-18 23:47:11 +00:00
|
|
|
* Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
|
2010-12-18 01:56:23 +00:00
|
|
|
*/
|
2023-04-13 01:22:09 -07:00
|
|
|
intoken = (isc_region_t){ tkeyin->key, tkeyin->keylen };
|
2010-12-18 01:56:23 +00:00
|
|
|
result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
|
2016-07-14 15:06:28 +10:00
|
|
|
&intoken, &outtoken, &gss_ctx, principal,
|
|
|
|
tctx->mctx);
|
2006-12-04 01:54:53 +00:00
|
|
|
if (result == DNS_R_INVALIDTKEY) {
|
2010-07-09 05:13:15 +00:00
|
|
|
if (tsigkey != NULL) {
|
|
|
|
dns_tsigkey_detach(&tsigkey);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
tkeyout->error = dns_tsigerror_badkey;
|
2023-04-13 01:22:09 -07:00
|
|
|
tkey_log("process_gsstkey(): dns_tsigerror_badkey");
|
2000-10-06 17:08:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2012-03-29 09:49:58 +11:00
|
|
|
}
|
|
|
|
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
|
2000-10-06 17:08:15 +00:00
|
|
|
goto failure;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-04-13 01:22:09 -07:00
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
/*
|
|
|
|
* XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
|
|
|
|
*/
|
2016-07-14 15:06:28 +10:00
|
|
|
if (dns_name_countlabels(principal) == 0U) {
|
2019-01-30 15:42:04 -08:00
|
|
|
if (tsigkey != NULL) {
|
2016-07-14 15:06:28 +10:00
|
|
|
dns_tsigkey_detach(&tsigkey);
|
2019-01-30 15:42:04 -08:00
|
|
|
}
|
2016-07-14 15:06:28 +10:00
|
|
|
} else if (tsigkey == NULL) {
|
2018-08-07 16:46:53 +02:00
|
|
|
#if HAVE_GSSAPI
|
2010-07-09 05:13:15 +00:00
|
|
|
OM_uint32 gret, minor, lifetime;
|
2018-08-07 16:46:53 +02:00
|
|
|
#endif /* HAVE_GSSAPI */
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t expire;
|
2010-07-09 05:13:15 +00:00
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, &dstkey,
|
|
|
|
&intoken));
|
2010-07-09 05:13:15 +00:00
|
|
|
/*
|
|
|
|
* Limit keys to 1 hour or the context's lifetime whichever
|
|
|
|
* is smaller.
|
|
|
|
*/
|
|
|
|
expire = now + 3600;
|
2018-08-07 16:46:53 +02:00
|
|
|
#if HAVE_GSSAPI
|
2010-07-09 05:13:15 +00:00
|
|
|
gret = gss_context_time(&minor, gss_ctx, &lifetime);
|
|
|
|
if (gret == GSS_S_COMPLETE && now + lifetime < expire) {
|
|
|
|
expire = now + lifetime;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-08-07 16:46:53 +02:00
|
|
|
#endif /* HAVE_GSSAPI */
|
2006-12-04 01:54:53 +00:00
|
|
|
RETERR(dns_tsigkey_createfromkey(
|
2023-04-11 19:01:31 -07:00
|
|
|
name, dns__tsig_algfromname(&tkeyin->algorithm), dstkey,
|
|
|
|
true, false, principal, now, expire, ring->mctx,
|
|
|
|
&tsigkey));
|
2023-04-12 00:14:04 -07:00
|
|
|
RETERR(dns_tsigkeyring_add(ring, tsigkey));
|
2010-12-09 00:54:34 +00:00
|
|
|
dst_key_free(&dstkey);
|
2010-07-09 05:13:15 +00:00
|
|
|
tkeyout->inception = now;
|
|
|
|
tkeyout->expire = expire;
|
|
|
|
} else {
|
|
|
|
tkeyout->inception = tsigkey->inception;
|
2011-03-11 06:11:27 +00:00
|
|
|
tkeyout->expire = tsigkey->expire;
|
2006-12-04 01:54:53 +00:00
|
|
|
}
|
2000-10-06 17:08:15 +00:00
|
|
|
|
2023-04-13 01:22:09 -07:00
|
|
|
if (outtoken != NULL) {
|
2006-12-05 21:59:12 +00:00
|
|
|
tkeyout->key = isc_mem_get(tkeyout->mctx,
|
|
|
|
isc_buffer_usedlength(outtoken));
|
|
|
|
tkeyout->keylen = isc_buffer_usedlength(outtoken);
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(tkeyout->key, isc_buffer_base(outtoken),
|
2006-12-05 21:59:12 +00:00
|
|
|
isc_buffer_usedlength(outtoken));
|
|
|
|
isc_buffer_free(&outtoken);
|
2006-12-04 01:54:53 +00:00
|
|
|
} else {
|
2006-12-05 21:59:12 +00:00
|
|
|
tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
|
2006-12-04 01:54:53 +00:00
|
|
|
tkeyout->keylen = tkeyin->keylen;
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(tkeyout->key, tkeyin->key, tkeyin->keylen);
|
2000-10-06 17:08:15 +00:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2019-01-29 18:10:27 +01:00
|
|
|
/*
|
2019-01-30 11:12:49 +01:00
|
|
|
* We found a TKEY to respond with. If the request is not TSIG signed,
|
|
|
|
* we need to make sure the response is signed (see RFC 3645, Section
|
|
|
|
* 2.2).
|
2019-01-29 18:10:27 +01:00
|
|
|
*/
|
2019-01-30 15:42:04 -08:00
|
|
|
if (tsigkey != NULL) {
|
|
|
|
if (msg->tsigkey == NULL && msg->sig0key == NULL) {
|
|
|
|
dns_message_settsigkey(msg, tsigkey);
|
|
|
|
}
|
|
|
|
dns_tsigkey_detach(&tsigkey);
|
2019-01-29 11:39:06 -08:00
|
|
|
}
|
|
|
|
|
2000-10-06 17:08:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
failure:
|
2010-07-09 05:13:15 +00:00
|
|
|
if (tsigkey != NULL) {
|
|
|
|
dns_tsigkey_detach(&tsigkey);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-10-06 17:08:15 +00:00
|
|
|
if (dstkey != NULL) {
|
|
|
|
dst_key_free(&dstkey);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-05 21:59:12 +00:00
|
|
|
if (outtoken != NULL) {
|
|
|
|
isc_buffer_free(&outtoken);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2023-04-13 01:22:09 -07:00
|
|
|
tkey_log("process_gsstkey(): %s", isc_result_totext(result));
|
2000-10-06 17:08:15 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-26 15:39:59 +00:00
|
|
|
static isc_result_t
|
2010-12-02 23:22:42 +00:00
|
|
|
process_deletetkey(dns_name_t *signer, dns_name_t *name,
|
|
|
|
dns_rdata_tkey_t *tkeyin, dns_rdata_tkey_t *tkeyout,
|
2023-04-11 11:35:01 -07:00
|
|
|
dns_tsigkeyring_t *ring) {
|
1999-10-26 15:39:59 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_tsigkey_t *tsigkey = NULL;
|
2023-04-13 01:22:09 -07:00
|
|
|
const dns_name_t *identity = NULL;
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2000-01-21 20:18:41 +00:00
|
|
|
result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
|
2001-06-08 18:29:31 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-10-26 15:39:59 +00:00
|
|
|
tkeyout->error = dns_tsigerror_badname;
|
2001-06-08 18:29:31 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
/*
|
1999-11-03 16:53:56 +00:00
|
|
|
* Only allow a delete if the identity that created the key is the
|
|
|
|
* same as the identity that signed the message.
|
1999-10-26 15:39:59 +00:00
|
|
|
*/
|
2000-03-08 20:15:16 +00:00
|
|
|
identity = dns_tsigkey_identity(tsigkey);
|
2001-02-14 00:43:10 +00:00
|
|
|
if (identity == NULL || !dns_name_equal(identity, signer)) {
|
|
|
|
dns_tsigkey_detach(&tsigkey);
|
1999-10-26 15:39:59 +00:00
|
|
|
return (DNS_R_REFUSED);
|
2001-02-14 00:43:10 +00:00
|
|
|
}
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-04-11 11:35:01 -07:00
|
|
|
dns_tsigkey_delete(tsigkey);
|
2001-02-14 00:43:10 +00:00
|
|
|
|
1999-10-26 15:39:59 +00:00
|
|
|
/* Release the reference */
|
2000-05-26 00:16:46 +00:00
|
|
|
dns_tsigkey_detach(&tsigkey);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
1999-11-05 16:53:47 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-10-26 15:39:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2000-06-09 22:33:08 +00:00
|
|
|
dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
|
2023-04-11 11:35:01 -07:00
|
|
|
dns_tsigkeyring_t *ring) {
|
1999-10-26 15:39:59 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2000-04-28 02:08:37 +00:00
|
|
|
dns_rdata_tkey_t tkeyin, tkeyout;
|
2023-04-13 01:22:09 -07:00
|
|
|
dns_name_t *qname = NULL, *name = NULL;
|
|
|
|
dns_name_t *keyname = NULL, *signer = NULL;
|
|
|
|
dns_name_t tsigner = DNS_NAME_INITEMPTY;
|
2001-02-14 00:43:10 +00:00
|
|
|
dns_fixedname_t fkeyname;
|
2023-04-13 01:22:09 -07:00
|
|
|
dns_rdataset_t *tkeyset = NULL;
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
|
dns_namelist_t namelist = ISC_LIST_INITIALIZER;
|
2001-02-14 00:43:10 +00:00
|
|
|
char tkeyoutdata[512];
|
|
|
|
isc_buffer_t tkeyoutbuf;
|
2023-04-13 17:46:49 -07:00
|
|
|
dns_tsigkey_t *tsigkey = NULL;
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2000-01-21 20:18:41 +00:00
|
|
|
REQUIRE(msg != NULL);
|
|
|
|
REQUIRE(tctx != NULL);
|
|
|
|
REQUIRE(ring != NULL);
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Interpret the question section.
|
|
|
|
*/
|
1999-10-26 15:39:59 +00:00
|
|
|
result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
|
2000-10-06 17:08:15 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (DNS_R_FORMERR);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname);
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Look for a TKEY record that matches the question.
|
|
|
|
*/
|
1999-10-26 15:39:59 +00:00
|
|
|
result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname,
|
|
|
|
dns_rdatatype_tkey, 0, &name, &tkeyset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-04-14 12:56:24 -07:00
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
tkey_log("dns_tkey_processquery: couldn't find a TKEY "
|
|
|
|
"matching the question");
|
|
|
|
goto failure;
|
1999-10-26 15:39:59 +00:00
|
|
|
}
|
2023-04-13 01:22:09 -07:00
|
|
|
|
1999-10-26 15:39:59 +00:00
|
|
|
result = dns_rdataset_first(tkeyset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2023-04-13 01:22:09 -07:00
|
|
|
dns_rdataset_current(tkeyset, &rdata);
|
2001-02-14 00:43:10 +00:00
|
|
|
RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL));
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
if (tkeyin.error != dns_rcode_noerror) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2000-03-08 20:15:16 +00:00
|
|
|
/*
|
|
|
|
* Before we go any farther, verify that the message was signed.
|
2023-04-13 17:46:49 -07:00
|
|
|
* DNS_TKEYMODE_GSSAPI doesn't require a signature, but other
|
|
|
|
* modes do.
|
2000-03-08 20:15:16 +00:00
|
|
|
*/
|
2000-10-06 17:08:15 +00:00
|
|
|
result = dns_message_signer(msg, &tsigner);
|
2023-04-13 01:22:09 -07:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2000-10-06 17:08:15 +00:00
|
|
|
signer = &tsigner;
|
2023-04-13 01:22:09 -07:00
|
|
|
} else if (result != ISC_R_NOTFOUND ||
|
|
|
|
tkeyin.mode != DNS_TKEYMODE_GSSAPI)
|
|
|
|
{
|
|
|
|
tkey_log("dns_tkey_processquery: query was not "
|
|
|
|
"properly signed - rejecting");
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto failure;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-03-08 20:15:16 +00:00
|
|
|
|
2023-04-13 01:22:09 -07:00
|
|
|
tkeyout = (dns_rdata_tkey_t){
|
|
|
|
.common.rdclass = tkeyin.common.rdclass,
|
|
|
|
.common.rdtype = tkeyin.common.rdtype,
|
|
|
|
.common.link = ISC_LINK_INITIALIZER,
|
|
|
|
.mctx = msg->mctx,
|
|
|
|
.algorithm = DNS_NAME_INITEMPTY,
|
|
|
|
.mode = tkeyin.mode,
|
|
|
|
};
|
2001-02-14 00:43:10 +00:00
|
|
|
dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2023-04-13 17:46:49 -07:00
|
|
|
switch (tkeyin.mode) {
|
|
|
|
case DNS_TKEYMODE_DELETE:
|
|
|
|
/*
|
|
|
|
* A delete operation uses the fully specified qname.
|
|
|
|
*/
|
|
|
|
RETERR(process_deletetkey(signer, qname, &tkeyin, &tkeyout,
|
|
|
|
ring));
|
|
|
|
break;
|
|
|
|
case DNS_TKEYMODE_GSSAPI:
|
|
|
|
/*
|
|
|
|
* For non-delete operations we do this:
|
|
|
|
*
|
|
|
|
* if (qname != ".")
|
|
|
|
* keyname = qname + defaultdomain
|
|
|
|
* else
|
|
|
|
* keyname = <random hex> + defaultdomain
|
|
|
|
*/
|
2006-12-04 01:54:53 +00:00
|
|
|
if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI)
|
|
|
|
{
|
2001-02-14 00:43:10 +00:00
|
|
|
tkey_log("dns_tkey_processquery: tkey-domain not set");
|
|
|
|
result = DNS_R_REFUSED;
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
keyname = dns_fixedname_initname(&fkeyname);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
if (!dns_name_equal(qname, dns_rootname)) {
|
|
|
|
unsigned int n = dns_name_countlabels(qname);
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(qname, keyname);
|
2001-10-09 17:26:33 +00:00
|
|
|
dns_name_getlabelsequence(keyname, 0, n - 1, keyname);
|
2001-12-03 19:44:08 +00:00
|
|
|
} else {
|
2001-02-14 00:43:10 +00:00
|
|
|
unsigned char randomdata[16];
|
|
|
|
char randomtext[32];
|
|
|
|
isc_buffer_t b;
|
2023-04-13 17:46:49 -07:00
|
|
|
isc_region_t r = {
|
|
|
|
.base = randomdata,
|
|
|
|
.length = sizeof(randomdata),
|
|
|
|
};
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2018-05-28 15:22:23 +02:00
|
|
|
isc_nonce_buf(randomdata, sizeof(randomdata));
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&b, randomtext, sizeof(randomtext));
|
2023-04-13 17:46:49 -07:00
|
|
|
RETERR(isc_hex_totext(&r, 2, "", &b));
|
|
|
|
RETERR(dns_name_fromtext(keyname, &b, NULL, 0, NULL));
|
2006-12-04 01:54:53 +00:00
|
|
|
}
|
2023-04-13 17:46:49 -07:00
|
|
|
RETERR(dns_name_concatenate(keyname, dns_rootname, keyname,
|
|
|
|
NULL));
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2000-01-21 20:18:41 +00:00
|
|
|
result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
|
1999-10-26 15:39:59 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
tkeyout.error = dns_tsigerror_badname;
|
2000-05-26 00:16:46 +00:00
|
|
|
dns_tsigkey_detach(&tsigkey);
|
2023-04-13 17:46:49 -07:00
|
|
|
break;
|
|
|
|
} else if (result == ISC_R_NOTFOUND) {
|
|
|
|
RETERR(process_gsstkey(msg, keyname, &tkeyin, tctx,
|
|
|
|
&tkeyout, ring));
|
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-04-13 17:46:49 -07:00
|
|
|
goto failure;
|
1999-10-26 15:39:59 +00:00
|
|
|
case DNS_TKEYMODE_SERVERASSIGNED:
|
|
|
|
case DNS_TKEYMODE_RESOLVERASSIGNED:
|
1999-10-26 21:57:53 +00:00
|
|
|
result = DNS_R_NOTIMP;
|
1999-10-26 15:39:59 +00:00
|
|
|
goto failure;
|
|
|
|
default:
|
|
|
|
tkeyout.error = dns_tsigerror_badmode;
|
|
|
|
}
|
|
|
|
|
2001-02-14 00:43:10 +00:00
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
isc_buffer_init(&tkeyoutbuf, tkeyoutdata, sizeof(tkeyoutdata));
|
|
|
|
result = dns_rdata_fromstruct(&rdata, tkeyout.common.rdclass,
|
|
|
|
tkeyout.common.rdtype, &tkeyout,
|
|
|
|
&tkeyoutbuf);
|
2000-05-19 22:11:20 +00:00
|
|
|
if (tkeyout.key != NULL) {
|
2006-12-05 21:59:12 +00:00
|
|
|
isc_mem_put(tkeyout.mctx, tkeyout.key, tkeyout.keylen);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-04-13 17:46:49 -07:00
|
|
|
RETERR(result);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
RETERR(dns_message_reply(msg, true));
|
2023-04-13 17:46:49 -07:00
|
|
|
add_rdata_to_list(msg, keyname, &rdata, 0, &namelist);
|
|
|
|
while ((name = ISC_LIST_HEAD(namelist)) != NULL) {
|
1999-10-26 15:39:59 +00:00
|
|
|
ISC_LIST_UNLINK(namelist, name, link);
|
2000-03-28 03:16:40 +00:00
|
|
|
dns_message_addname(msg, name, DNS_SECTION_ANSWER);
|
1999-10-26 15:39:59 +00:00
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
failure:
|
2023-04-13 17:46:49 -07:00
|
|
|
free_namelist(msg, &namelist);
|
1999-10-26 15:39:59 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2023-04-14 12:56:24 -07:00
|
|
|
buildquery(dns_message_t *msg, const dns_name_t *name, dns_rdata_tkey_t *tkey) {
|
1999-10-26 15:39:59 +00:00
|
|
|
dns_name_t *qname = NULL, *aname = NULL;
|
|
|
|
dns_rdataset_t *question = NULL, *tkeyset = NULL;
|
|
|
|
dns_rdatalist_t *tkeylist = NULL;
|
|
|
|
dns_rdata_t *rdata = NULL;
|
2021-05-19 17:18:22 -07:00
|
|
|
isc_buffer_t *dynbuf = NULL;
|
1999-10-26 15:39:59 +00:00
|
|
|
isc_result_t result;
|
2015-08-14 08:20:01 +10:00
|
|
|
unsigned int len;
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
REQUIRE(msg != NULL);
|
|
|
|
REQUIRE(name != NULL);
|
|
|
|
REQUIRE(tkey != NULL);
|
|
|
|
|
2022-08-11 18:27:11 +00:00
|
|
|
len = 16 + tkey->algorithm.length + tkey->keylen + tkey->otherlen;
|
|
|
|
isc_buffer_allocate(msg->mctx, &dynbuf, len);
|
|
|
|
dns_message_gettemprdata(msg, &rdata);
|
|
|
|
result = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
|
|
|
|
dns_rdatatype_tkey, tkey, dynbuf);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_message_puttemprdata(msg, &rdata);
|
|
|
|
isc_buffer_free(&dynbuf);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
dns_message_takebuffer(msg, &dynbuf);
|
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettempname(msg, &qname);
|
|
|
|
dns_message_gettempname(msg, &aname);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettemprdataset(msg, &question);
|
2000-01-24 22:22:51 +00:00
|
|
|
dns_rdataset_makequestion(question, dns_rdataclass_any,
|
1999-10-26 19:32:37 +00:00
|
|
|
dns_rdatatype_tkey);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettemprdatalist(msg, &tkeylist);
|
2000-01-24 22:22:51 +00:00
|
|
|
tkeylist->rdclass = dns_rdataclass_any;
|
1999-10-26 15:39:59 +00:00
|
|
|
tkeylist->type = dns_rdatatype_tkey;
|
|
|
|
ISC_LIST_APPEND(tkeylist->rdata, rdata, link);
|
|
|
|
|
2022-05-16 13:28:13 +02:00
|
|
|
dns_message_gettemprdataset(msg, &tkeyset);
|
2022-07-29 12:40:45 +00:00
|
|
|
dns_rdatalist_tordataset(tkeylist, tkeyset);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(name, qname);
|
|
|
|
dns_name_copy(name, aname);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
ISC_LIST_APPEND(qname->list, question, link);
|
|
|
|
ISC_LIST_APPEND(aname->list, tkeyset, link);
|
|
|
|
|
|
|
|
dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
|
2023-04-14 12:56:24 -07:00
|
|
|
dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
|
1999-10-26 15:39:59 +00:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-10-06 17:08:15 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_tkey_buildgssquery(dns_message_t *msg, const dns_name_t *name,
|
2023-04-13 01:22:09 -07:00
|
|
|
const dns_name_t *gname, uint32_t lifetime,
|
|
|
|
dns_gss_ctx_id_t *context, isc_mem_t *mctx,
|
|
|
|
char **err_message) {
|
2000-10-06 17:08:15 +00:00
|
|
|
dns_rdata_tkey_t tkey;
|
|
|
|
isc_result_t result;
|
2023-03-30 21:13:41 +02:00
|
|
|
isc_stdtime_t now = isc_stdtime_now();
|
2000-10-06 17:08:15 +00:00
|
|
|
isc_buffer_t token;
|
2015-08-14 08:20:01 +10:00
|
|
|
unsigned char array[TEMP_BUFFER_SZ];
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2000-10-06 17:08:15 +00:00
|
|
|
REQUIRE(msg != NULL);
|
|
|
|
REQUIRE(name != NULL);
|
|
|
|
REQUIRE(gname != NULL);
|
2006-12-04 01:54:53 +00:00
|
|
|
REQUIRE(context != NULL);
|
2010-12-18 01:56:23 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
2000-10-06 17:08:15 +00:00
|
|
|
|
|
|
|
isc_buffer_init(&token, array, sizeof(array));
|
2011-01-08 00:33:12 +00:00
|
|
|
result = dst_gssapi_initctx(gname, NULL, &token, context, mctx,
|
2010-12-18 01:56:23 +00:00
|
|
|
err_message);
|
2000-10-06 17:08:15 +00:00
|
|
|
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-10-06 17:08:15 +00:00
|
|
|
|
2023-04-11 19:01:31 -07:00
|
|
|
tkey = (dns_rdata_tkey_t){
|
|
|
|
.common.rdclass = dns_rdataclass_any,
|
|
|
|
.common.rdtype = dns_rdatatype_tkey,
|
|
|
|
.common.link = ISC_LINK_INITIALIZER,
|
|
|
|
.inception = now,
|
|
|
|
.expire = now + lifetime,
|
2023-04-13 01:22:09 -07:00
|
|
|
.algorithm = DNS_NAME_INITEMPTY,
|
2023-04-11 19:01:31 -07:00
|
|
|
.mode = DNS_TKEYMODE_GSSAPI,
|
|
|
|
.key = isc_buffer_base(&token),
|
|
|
|
.keylen = isc_buffer_usedlength(&token),
|
|
|
|
};
|
2023-04-14 12:56:24 -07:00
|
|
|
dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
|
2000-10-06 17:08:15 +00:00
|
|
|
|
2023-04-14 12:56:24 -07:00
|
|
|
return (buildquery(msg, name, &tkey));
|
2000-10-06 17:08:15 +00:00
|
|
|
}
|
|
|
|
|
1999-10-26 15:39:59 +00:00
|
|
|
static isc_result_t
|
2000-03-28 03:16:40 +00:00
|
|
|
find_tkey(dns_message_t *msg, dns_name_t **name, dns_rdata_t *rdata,
|
|
|
|
int section) {
|
1999-10-26 15:39:59 +00:00
|
|
|
isc_result_t result;
|
|
|
|
|
2000-03-28 03:16:40 +00:00
|
|
|
result = dns_message_firstname(msg, section);
|
1999-10-26 15:39:59 +00:00
|
|
|
while (result == ISC_R_SUCCESS) {
|
2023-04-13 01:22:09 -07:00
|
|
|
dns_rdataset_t *tkeyset = NULL;
|
|
|
|
dns_name_t *cur = NULL;
|
|
|
|
|
|
|
|
dns_message_currentname(msg, section, &cur);
|
|
|
|
result = dns_message_findtype(cur, dns_rdatatype_tkey, 0,
|
1999-10-26 15:39:59 +00:00
|
|
|
&tkeyset);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = dns_rdataset_first(tkeyset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-04-13 01:22:09 -07:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-04-13 01:22:09 -07:00
|
|
|
|
1999-10-26 15:39:59 +00:00
|
|
|
dns_rdataset_current(tkeyset, rdata);
|
2023-04-13 01:22:09 -07:00
|
|
|
*name = cur;
|
1999-10-26 15:39:59 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2000-03-28 03:16:40 +00:00
|
|
|
result = dns_message_nextname(msg, section);
|
1999-10-26 15:39:59 +00:00
|
|
|
}
|
|
|
|
if (result == ISC_R_NOMORE) {
|
|
|
|
return (ISC_R_NOTFOUND);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-26 15:39:59 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
|
2021-02-11 14:40:59 +01:00
|
|
|
const dns_name_t *server, dns_gss_ctx_id_t *context,
|
2023-04-11 11:35:01 -07:00
|
|
|
dns_tsigkey_t **outkey, dns_tsigkeyring_t *ring,
|
2023-04-14 12:56:24 -07:00
|
|
|
char **err_message) {
|
2023-04-13 01:22:09 -07:00
|
|
|
isc_result_t result;
|
2006-12-04 01:54:53 +00:00
|
|
|
dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
|
2023-04-11 16:10:07 -07:00
|
|
|
dns_name_t *tkeyname = NULL;
|
2016-07-14 15:06:28 +10:00
|
|
|
dns_rdata_tkey_t rtkey, qtkey, tkey;
|
2006-12-04 01:54:53 +00:00
|
|
|
isc_buffer_t intoken, outtoken;
|
|
|
|
dst_key_t *dstkey = NULL;
|
2016-07-14 15:06:28 +10:00
|
|
|
unsigned char array[TEMP_BUFFER_SZ];
|
2023-04-11 16:10:07 -07:00
|
|
|
dns_tsigkey_t *tsigkey = NULL;
|
2006-12-04 01:54:53 +00:00
|
|
|
|
|
|
|
REQUIRE(qmsg != NULL);
|
|
|
|
REQUIRE(rmsg != NULL);
|
|
|
|
REQUIRE(server != NULL);
|
2023-04-13 01:22:09 -07:00
|
|
|
REQUIRE(outkey == NULL || *outkey == NULL);
|
2006-12-04 01:54:53 +00:00
|
|
|
|
|
|
|
if (rmsg->rcode != dns_rcode_noerror) {
|
2021-10-04 17:14:53 +02:00
|
|
|
return (dns_result_fromrcode(rmsg->rcode));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
|
|
|
|
RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
|
|
|
|
RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
|
|
|
|
|
2023-04-14 12:56:24 -07:00
|
|
|
RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata, DNS_SECTION_ADDITIONAL));
|
2006-12-04 01:54:53 +00:00
|
|
|
RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
|
|
|
|
|
|
|
|
if (rtkey.error != dns_rcode_noerror ||
|
|
|
|
rtkey.mode != DNS_TKEYMODE_GSSAPI ||
|
|
|
|
!dns_name_equal(&rtkey.algorithm, &qtkey.algorithm))
|
|
|
|
{
|
2023-04-13 01:22:09 -07:00
|
|
|
tkey_log("dns_tkey_gssnegotiate: tkey mode invalid "
|
2006-12-04 01:54:53 +00:00
|
|
|
"or error set(4)");
|
|
|
|
result = DNS_R_INVALIDTKEY;
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
|
|
|
|
isc_buffer_init(&outtoken, array, sizeof(array));
|
|
|
|
|
2010-12-18 01:56:23 +00:00
|
|
|
result = dst_gssapi_initctx(server, &intoken, &outtoken, context,
|
2011-01-08 00:33:12 +00:00
|
|
|
ring->mctx, err_message);
|
2006-12-04 01:54:53 +00:00
|
|
|
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
|
2016-07-14 15:06:28 +10:00
|
|
|
if (result == DNS_R_CONTINUE) {
|
2023-04-13 01:22:09 -07:00
|
|
|
tkey = (dns_rdata_tkey_t){
|
|
|
|
.common.rdclass = dns_rdataclass_any,
|
|
|
|
.common.rdtype = dns_rdatatype_tkey,
|
|
|
|
.common.link = ISC_LINK_INITIALIZER,
|
|
|
|
.inception = qtkey.inception,
|
|
|
|
.expire = qtkey.expire,
|
|
|
|
.algorithm = DNS_NAME_INITEMPTY,
|
|
|
|
.mode = DNS_TKEYMODE_GSSAPI,
|
|
|
|
.key = isc_buffer_base(&outtoken),
|
|
|
|
.keylen = isc_buffer_usedlength(&outtoken),
|
|
|
|
};
|
2016-07-14 15:06:28 +10:00
|
|
|
|
2023-04-14 12:56:24 -07:00
|
|
|
dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
|
2016-07-14 15:06:28 +10:00
|
|
|
|
|
|
|
dns_message_reset(qmsg, DNS_MESSAGE_INTENTRENDER);
|
2023-04-14 12:56:24 -07:00
|
|
|
RETERR(buildquery(qmsg, tkeyname, &tkey));
|
2016-07-14 15:06:28 +10:00
|
|
|
return (DNS_R_CONTINUE);
|
|
|
|
}
|
|
|
|
|
2006-12-04 01:54:53 +00:00
|
|
|
RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx, &dstkey,
|
2010-12-18 01:56:23 +00:00
|
|
|
NULL));
|
2006-12-04 01:54:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXXSRA This seems confused. If we got CONTINUE from initctx,
|
|
|
|
* the GSS negotiation hasn't completed yet, so we can't sign
|
|
|
|
* anything yet.
|
|
|
|
*/
|
2023-04-11 19:01:31 -07:00
|
|
|
RETERR(dns_tsigkey_createfromkey(tkeyname, DST_ALG_GSSAPI, dstkey, true,
|
|
|
|
false, NULL, rtkey.inception,
|
2023-04-11 16:10:07 -07:00
|
|
|
rtkey.expire, ring->mctx, &tsigkey));
|
2023-04-12 00:14:04 -07:00
|
|
|
RETERR(dns_tsigkeyring_add(ring, tsigkey));
|
2023-04-11 16:10:07 -07:00
|
|
|
if (outkey == NULL) {
|
|
|
|
dns_tsigkey_detach(&tsigkey);
|
|
|
|
} else {
|
|
|
|
*outkey = tsigkey;
|
|
|
|
}
|
|
|
|
|
2010-12-09 00:54:34 +00:00
|
|
|
dst_key_free(&dstkey);
|
2006-12-04 01:54:53 +00:00
|
|
|
return (result);
|
|
|
|
|
|
|
|
failure:
|
2023-04-11 16:10:07 -07:00
|
|
|
if (tsigkey != NULL) {
|
|
|
|
dns_tsigkey_detach(&tsigkey);
|
|
|
|
}
|
2010-12-02 23:22:42 +00:00
|
|
|
if (dstkey != NULL) {
|
|
|
|
dst_key_free(&dstkey);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-12-04 01:54:53 +00:00
|
|
|
return (result);
|
|
|
|
}
|