From 1083ef30279a38d26eae5df98a0d66bc96917526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Fri, 10 Apr 2026 12:51:31 +0200 Subject: [PATCH] Fix output token and GSS context leaks in TKEY/GSS-API error paths In dst_gssapi_acceptctx(), rename outtoken to outtokenp (matching BIND convention for output pointer parameters) and free the allocated output token buffer on error in the cleanup path. In process_gsstkey(), route the empty-principal error path through cleanup via CLEANUP() instead of returning early, so that the output token, GSS context, and TSIG key are all freed consistently by the existing cleanup block. --- lib/dns/gssapictx.c | 12 ++++++++---- lib/dns/tkey.c | 15 +++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c index bbfebb9acc..a2d55de3e0 100644 --- a/lib/dns/gssapictx.c +++ b/lib/dns/gssapictx.c @@ -378,7 +378,7 @@ cleanup: isc_result_t dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken, - isc_buffer_t **outtoken, dns_gss_ctx_id_t *ctxout, + isc_buffer_t **outtokenp, dns_gss_ctx_id_t *ctxout, dns_name_t *principal, isc_mem_t *mctx) { isc_region_t r; isc_buffer_t namebuf; @@ -390,7 +390,7 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken, isc_result_t result; char buf[1024]; - REQUIRE(outtoken != NULL && *outtoken == NULL); + REQUIRE(outtokenp != NULL && *outtokenp == NULL); REQUIRE(*ctxout == NULL); REGION_TO_GBUFFER(*intoken, gintoken); @@ -470,10 +470,10 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken, } if (gouttoken.length > 0U) { - isc_buffer_allocate(mctx, outtoken, + isc_buffer_allocate(mctx, outtokenp, (unsigned int)gouttoken.length); GBUFFER_TO_REGION(gouttoken, r); - CHECK(isc_buffer_copyregion(*outtoken, &r)); + CHECK(isc_buffer_copyregion(*outtokenp, &r)); (void)gss_release_buffer(&minor, &gouttoken); } @@ -510,6 +510,10 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken, *ctxout = context; cleanup: + if (result != ISC_R_SUCCESS && *outtokenp != NULL) { + isc_buffer_free(outtokenp); + } + if (result != ISC_R_SUCCESS && context != GSS_C_NO_CONTEXT) { (void)gss_delete_sec_context(&minor, &context, NULL); } diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 38bdbd3ad7..b22fed78a4 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -182,12 +182,9 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin, result = dst_gssapi_acceptctx(tctx->gssapi_keytab, &intoken, &outtoken, &gss_ctx, principal, tctx->mctx); if (result != ISC_R_SUCCESS) { - if (tsigkey != NULL) { - dns_tsigkey_detach(&tsigkey); - } tkeyout->error = dns_tsigerror_badkey; tkey_log("process_gsstkey(): dns_tsigerror_badkey"); - return ISC_R_SUCCESS; + CLEANUP(ISC_R_SUCCESS); } /* @@ -196,14 +193,10 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin, * negotiation is complete and the principal must be set. */ if (dns_name_countlabels(principal) == 0U) { - if (tsigkey != NULL) { - dns_tsigkey_detach(&tsigkey); - } - dst_gssapi_deletectx(tctx->mctx, &gss_ctx); tkeyout->error = dns_tsigerror_badkey; tkey_log("process_gsstkey(): " "completed context with empty principal"); - return ISC_R_SUCCESS; + CLEANUP(ISC_R_SUCCESS); } else if (tsigkey == NULL) { #if HAVE_GSSAPI OM_uint32 gret, minor, lifetime; @@ -282,7 +275,9 @@ cleanup: isc_buffer_free(&outtoken); } - tkey_log("process_gsstkey(): %s", isc_result_totext(result)); + if (result != ISC_R_SUCCESS) { + tkey_log("process_gsstkey(): %s", isc_result_totext(result)); + } return result; }