mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-27 20:25:55 -04:00
[CVE-2026-3039] sec: usr: Fix GSS-API resource leak
Fixed a memory leak where each GSS-API TKEY negotiation leaked a security context inside the GSS library. An unauthenticated attacker could exhaust server memory by sending repeated TKEY queries to a server with tkey-gssapi-keytab configured. The leaked memory was allocated by the GSS library, bypassing BIND's memory accounting. Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is now rejected, as BIND never supported it correctly and Kerberos/SPNEGO completes in a single round. Closes: https://gitlab.isc.org/isc-projects/bind9/-/issues/5752 Merge branch '5752-fix-memory-leak-in-TKEY-negotiation' into 'security-main' See merge request isc-private/bind9!965
This commit is contained in:
commit
01bdb7abeb
9 changed files with 318 additions and 75 deletions
BIN
bin/tests/system/tkeyleak/ns1/dns.keytab
Normal file
BIN
bin/tests/system/tkeyleak/ns1/dns.keytab
Normal file
Binary file not shown.
21
bin/tests/system/tkeyleak/ns1/example.db.in
Normal file
21
bin/tests/system/tkeyleak/ns1/example.db.in
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; 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/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300
|
||||
@ IN SOA ns.example. admin.example. (
|
||||
1 ; serial
|
||||
3600 ; refresh
|
||||
900 ; retry
|
||||
604800 ; expire
|
||||
300 ; minimum
|
||||
)
|
||||
@ IN NS ns.example.
|
||||
ns IN A 10.53.0.1
|
||||
39
bin/tests/system/tkeyleak/ns1/named.conf.j2
Normal file
39
bin/tests/system/tkeyleak/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* 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/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
tkey-gssapi-keytab "dns.keytab";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
type primary;
|
||||
file "example.db";
|
||||
};
|
||||
21
bin/tests/system/tkeyleak/prereq.sh
Normal file
21
bin/tests/system/tkeyleak/prereq.sh
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
$FEATURETEST --gssapi || {
|
||||
echo_i "gssapi not supported - skipping tkeyleak test"
|
||||
exit 255
|
||||
}
|
||||
|
||||
exit 0
|
||||
17
bin/tests/system/tkeyleak/setup.sh
Normal file
17
bin/tests/system/tkeyleak/setup.sh
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../conf.sh
|
||||
|
||||
cp ns1/example.db.in ns1/example.db
|
||||
145
bin/tests/system/tkeyleak/tests_tkeyleak.py
Normal file
145
bin/tests/system/tkeyleak/tests_tkeyleak.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
"""
|
||||
Regression test for GSS-API context leak via repeated TKEY queries.
|
||||
|
||||
An unauthenticated attacker could exhaust server memory by sending
|
||||
repeated TKEY queries with crafted SPNEGO NegTokenInit tokens.
|
||||
Each query triggers gss_accept_sec_context() which returns
|
||||
GSS_S_CONTINUE_NEEDED and allocates a GSS context. On the unfixed
|
||||
code path, the context handle in process_gsstkey() is never stored
|
||||
or freed, leaking ~520 bytes per query.
|
||||
|
||||
The fix rejects GSS_S_CONTINUE_NEEDED in dst_gssapi_acceptctx() and
|
||||
deletes the context immediately.
|
||||
|
||||
The key distinguishing signal in the TKEY response:
|
||||
- CONTINUE (vulnerable): error=0, output token present, no TSIG
|
||||
- BADKEY (fixed): error=17, no output token
|
||||
"""
|
||||
|
||||
import struct
|
||||
import time
|
||||
|
||||
import dns.name
|
||||
import dns.query
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rdtypes.ANY.TKEY
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*/*.db",
|
||||
]
|
||||
)
|
||||
|
||||
TKEY_NAME = dns.name.from_text("test.key.")
|
||||
GSSAPI_ALGORITHM = dns.name.from_text("gss-tsig.")
|
||||
TKEY_MODE_GSSAPI = 3
|
||||
|
||||
# OID 1.2.840.113554.1.2.2 (Kerberos 5)
|
||||
KRB5_OID = b"\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
|
||||
|
||||
# OID 1.3.6.1.5.5.2 (SPNEGO)
|
||||
SPNEGO_OID = b"\x06\x06\x2b\x06\x01\x05\x05\x02"
|
||||
|
||||
|
||||
def der_encode(tag, data):
|
||||
"""Encode data in ASN.1 DER TLV format."""
|
||||
length = len(data)
|
||||
if length < 128:
|
||||
return tag + bytes([length]) + data
|
||||
if length < 256:
|
||||
return tag + b"\x81" + bytes([length]) + data
|
||||
return tag + b"\x82" + struct.pack(">H", length) + data
|
||||
|
||||
|
||||
def spnego_negtokeninit():
|
||||
"""Build a SPNEGO NegTokenInit proposing krb5 without a mechToken.
|
||||
|
||||
This forces gss_accept_sec_context() to return GSS_S_CONTINUE_NEEDED
|
||||
because the acceptor recognizes the krb5 mechanism but has not
|
||||
received an actual AP-REQ token yet.
|
||||
"""
|
||||
# MechTypeList ::= SEQUENCE OF MechType
|
||||
mechtype_list = der_encode(b"\x30", KRB5_OID)
|
||||
# [0] mechTypes
|
||||
mechtypes = der_encode(b"\xa0", mechtype_list)
|
||||
# NegTokenInit ::= SEQUENCE { mechTypes, ... }
|
||||
negtokeninit = der_encode(b"\x30", mechtypes)
|
||||
# [0] CONSTRUCTED (wrapping NegTokenInit)
|
||||
wrapped = der_encode(b"\xa0", negtokeninit)
|
||||
# APPLICATION 0 CONSTRUCTED (SPNEGO OID + body)
|
||||
return der_encode(b"\x60", SPNEGO_OID + wrapped)
|
||||
|
||||
|
||||
def make_tkey_query(token):
|
||||
"""Build a TKEY query with a GSS-API token in the additional section."""
|
||||
now = int(time.time())
|
||||
tkey_rdata = dns.rdtypes.ANY.TKEY.TKEY(
|
||||
rdclass=dns.rdataclass.ANY,
|
||||
rdtype=dns.rdatatype.TKEY,
|
||||
algorithm=GSSAPI_ALGORITHM,
|
||||
inception=now,
|
||||
expiration=now + 86400,
|
||||
mode=TKEY_MODE_GSSAPI,
|
||||
error=0,
|
||||
key=token,
|
||||
other=b"",
|
||||
)
|
||||
|
||||
msg = isctest.query.create(TKEY_NAME, dns.rdatatype.TKEY, dns.rdataclass.ANY)
|
||||
rrset = msg.find_rrset(
|
||||
msg.additional,
|
||||
TKEY_NAME,
|
||||
dns.rdataclass.ANY,
|
||||
dns.rdatatype.TKEY,
|
||||
create=True,
|
||||
)
|
||||
rrset.add(tkey_rdata)
|
||||
return msg
|
||||
|
||||
|
||||
def test_tkey_gssapi_no_continuation(ns1):
|
||||
"""TKEY with a SPNEGO NegTokenInit must be rejected, not continued.
|
||||
|
||||
On unfixed code, gss_accept_sec_context() returns CONTINUE_NEEDED
|
||||
and the response has error=0 with an output token (the leaked path).
|
||||
On fixed code, CONTINUE_NEEDED is rejected and the response has
|
||||
error=BADKEY(17) with no output token.
|
||||
"""
|
||||
port = ns1.ports.dns
|
||||
ip = ns1.ip
|
||||
|
||||
msg = make_tkey_query(spnego_negtokeninit())
|
||||
res = dns.query.tcp(msg, ip, port=port, timeout=5)
|
||||
|
||||
assert res is not None
|
||||
|
||||
tkey = get_tkey_answer(res)
|
||||
assert tkey is not None, "server did not return a TKEY answer"
|
||||
assert (
|
||||
tkey.error != 0
|
||||
), "server returned error=0 (GSS_S_CONTINUE_NEEDED not rejected)"
|
||||
assert len(tkey.key) == 0, "server returned a continuation token"
|
||||
|
||||
|
||||
def get_tkey_answer(response):
|
||||
"""Extract TKEY rdata from a DNS response, or None."""
|
||||
for rrset in response.answer:
|
||||
if rrset.rdtype == dns.rdatatype.TKEY:
|
||||
for rdata in rrset:
|
||||
return rdata
|
||||
return None
|
||||
|
|
@ -336,7 +336,14 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
|||
GSS_SPNEGO_MECHANISM, flags, 0, NULL, gintokenp, NULL,
|
||||
&gouttoken, &ret_flags, NULL);
|
||||
|
||||
if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
|
||||
switch (gret) {
|
||||
case GSS_S_COMPLETE:
|
||||
result = ISC_R_SUCCESS;
|
||||
break;
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
result = DNS_R_CONTINUE;
|
||||
break;
|
||||
default:
|
||||
gss_err_message(mctx, gret, minor, err_message);
|
||||
if (err_message != NULL && *err_message != NULL) {
|
||||
gss_log(3, "Failure initiating security context: %s",
|
||||
|
|
@ -361,12 +368,6 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
|||
CHECK(isc_buffer_copyregion(outtoken, &r));
|
||||
}
|
||||
|
||||
if (gret == GSS_S_COMPLETE) {
|
||||
result = ISC_R_SUCCESS;
|
||||
} else {
|
||||
result = DNS_R_CONTINUE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (gouttoken.length != 0U) {
|
||||
(void)gss_release_buffer(&minor, &gouttoken);
|
||||
|
|
@ -377,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;
|
||||
|
|
@ -389,16 +390,11 @@ 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);
|
||||
|
||||
if (*ctxout == NULL) {
|
||||
context = GSS_C_NO_CONTEXT;
|
||||
} else {
|
||||
context = *ctxout;
|
||||
}
|
||||
|
||||
if (gssapi_keytab != NULL) {
|
||||
#if HAVE_GSSAPI_GSSAPI_KRB5_H || HAVE_GSSAPI_KRB5_H
|
||||
gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
|
||||
|
|
@ -442,8 +438,15 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
|
||||
switch (gret) {
|
||||
case GSS_S_COMPLETE:
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
break;
|
||||
/*
|
||||
* RFC 3645 4.1.3: we don't handle GSS_S_CONTINUE_NEEDED
|
||||
* Multi-round GSS-API negotiation is not supported.
|
||||
*/
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
gss_log(3, "multi-round GSS-API negotiation not supported");
|
||||
(void)gss_delete_sec_context(&minor, &context, NULL);
|
||||
FALLTHROUGH;
|
||||
case GSS_S_DEFECTIVE_TOKEN:
|
||||
case GSS_S_DEFECTIVE_CREDENTIAL:
|
||||
case GSS_S_BAD_SIG:
|
||||
|
|
@ -456,7 +459,7 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
case GSS_S_BAD_MECH:
|
||||
case GSS_S_FAILURE:
|
||||
result = DNS_R_INVALIDTKEY;
|
||||
/* fall through */
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
gss_log(3, "failed gss_accept_sec_context: %s",
|
||||
gss_error_tostring(gret, minor, buf, sizeof(buf)));
|
||||
|
|
@ -467,49 +470,54 @@ 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);
|
||||
}
|
||||
|
||||
if (gret == GSS_S_COMPLETE) {
|
||||
gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
gss_log(3, "failed gss_display_name: %s",
|
||||
gss_error_tostring(gret, minor, buf,
|
||||
sizeof(buf)));
|
||||
CLEANUP(ISC_R_FAILURE);
|
||||
}
|
||||
INSIST(gret == GSS_S_COMPLETE);
|
||||
|
||||
/*
|
||||
* Compensate for a bug in Solaris8's implementation
|
||||
* of gss_display_name(). Should be harmless in any
|
||||
* case, since principal names really should not
|
||||
* contain null characters.
|
||||
*/
|
||||
if (gnamebuf.length > 0U &&
|
||||
((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
|
||||
{
|
||||
gnamebuf.length--;
|
||||
}
|
||||
|
||||
gss_log(3, "gss-api source name (accept) is %.*s",
|
||||
(int)gnamebuf.length, (char *)gnamebuf.value);
|
||||
|
||||
GBUFFER_TO_REGION(gnamebuf, r);
|
||||
isc_buffer_init(&namebuf, r.base, r.length);
|
||||
isc_buffer_add(&namebuf, r.length);
|
||||
|
||||
CHECK(dns_name_fromtext(principal, &namebuf, dns_rootname, 0));
|
||||
} else {
|
||||
result = DNS_R_CONTINUE;
|
||||
gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
gss_log(3, "failed gss_display_name: %s",
|
||||
gss_error_tostring(gret, minor, buf, sizeof(buf)));
|
||||
CLEANUP(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compensate for a bug in Solaris8's implementation
|
||||
* of gss_display_name(). Should be harmless in any
|
||||
* case, since principal names really should not
|
||||
* contain null characters.
|
||||
*/
|
||||
if (gnamebuf.length > 0U &&
|
||||
((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
|
||||
{
|
||||
gnamebuf.length--;
|
||||
}
|
||||
|
||||
gss_log(3, "gss-api source name (accept) is %.*s", (int)gnamebuf.length,
|
||||
(char *)gnamebuf.value);
|
||||
|
||||
GBUFFER_TO_REGION(gnamebuf, r);
|
||||
isc_buffer_init(&namebuf, r.base, r.length);
|
||||
isc_buffer_add(&namebuf, r.length);
|
||||
|
||||
CHECK(dns_name_fromtext(principal, &namebuf, dns_rootname, 0));
|
||||
|
||||
*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);
|
||||
}
|
||||
|
||||
if (gnamebuf.length != 0U) {
|
||||
gret = gss_release_buffer(&minor, &gnamebuf);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
|
|
|
|||
|
|
@ -71,18 +71,17 @@ dst_gssapi_acceptctx(const char *gssapi_keytab, isc_region_t *intoken,
|
|||
* generated by gss_accept_sec_context() to be sent to the
|
||||
* initiator
|
||||
* 'context' is a valid pointer to receive the generated context handle.
|
||||
* On the initial call, it should be a pointer to NULL, which
|
||||
* will be allocated as a dns_gss_ctx_id_t. Subsequent calls
|
||||
* should pass in the handle generated on the first call.
|
||||
*
|
||||
* Requires:
|
||||
* 'outtoken' to != NULL && *outtoken == NULL.
|
||||
* 'outtoken' != NULL && *outtoken == NULL.
|
||||
* 'context' != NULL && *context == NULL.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS msg was successfully updated to include the
|
||||
* query to be sent
|
||||
* DNS_R_CONTINUE transaction still in progress
|
||||
* other an error occurred while building the message
|
||||
* ISC_R_SUCCESS msg was successfully updated to include
|
||||
* the query to be sent
|
||||
* DNS_R_INVALIDTKEY an error occurred while accepting the
|
||||
* context
|
||||
* ISC_R_FAILURE other error occurred
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
|
|
|
|||
|
|
@ -181,30 +181,22 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
|
|||
intoken = (isc_region_t){ tkeyin->key, tkeyin->keylen };
|
||||
result = dst_gssapi_acceptctx(tctx->gssapi_keytab, &intoken, &outtoken,
|
||||
&gss_ctx, principal, tctx->mctx);
|
||||
if (result == DNS_R_INVALIDTKEY) {
|
||||
if (tsigkey != NULL) {
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
tkeyout->error = dns_tsigerror_badkey;
|
||||
tkey_log("process_gsstkey(): dns_tsigerror_badkey");
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
|
||||
CHECK(result);
|
||||
CLEANUP(ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
|
||||
* Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is
|
||||
* rejected in dst_gssapi_acceptctx(), so if we reach here the
|
||||
* 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;
|
||||
|
|
@ -283,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;
|
||||
}
|
||||
|
||||
|
|
@ -678,9 +672,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
|
|||
NULL));
|
||||
|
||||
/*
|
||||
* XXXSRA This seems confused. If we got CONTINUE from initctx,
|
||||
* the GSS negotiation hasn't completed yet, so we can't sign
|
||||
* anything yet.
|
||||
* GSS negotiation is complete (CONTINUE returned earlier).
|
||||
* Create the TSIG key from the established context.
|
||||
*/
|
||||
CHECK(dns_tsigkey_createfromkey(tkeyname, DST_ALG_GSSAPI, dstkey, true,
|
||||
false, NULL, rtkey.inception,
|
||||
|
|
|
|||
Loading…
Reference in a new issue