summaryrefslogtreecommitdiff
path: root/usr.sbin/bind/lib/dns/gssapictx.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bind/lib/dns/gssapictx.c')
-rw-r--r--usr.sbin/bind/lib/dns/gssapictx.c886
1 files changed, 0 insertions, 886 deletions
diff --git a/usr.sbin/bind/lib/dns/gssapictx.c b/usr.sbin/bind/lib/dns/gssapictx.c
deleted file mode 100644
index d26b7d9d5bb..00000000000
--- a/usr.sbin/bind/lib/dns/gssapictx.c
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* $Id: gssapictx.c,v 1.5 2020/01/09 13:47:12 florian Exp $ */
-
-#include <config.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <isc/buffer.h>
-#include <isc/dir.h>
-#include <isc/entropy.h>
-#include <isc/file.h>
-#include <isc/lex.h>
-#include <isc/mem.h>
-#include <isc/once.h>
-
-#include <isc/platform.h>
-#include <isc/random.h>
-#include <isc/string.h>
-#include <isc/time.h>
-#include <isc/util.h>
-
-#include <dns/fixedname.h>
-#include <dns/name.h>
-#include <dns/rdata.h>
-#include <dns/rdataclass.h>
-#include <dns/result.h>
-#include <dns/types.h>
-#include <dns/keyvalues.h>
-#include <dns/log.h>
-
-#include <dst/gssapi.h>
-#include <dst/result.h>
-
-#include "dst_internal.h"
-
-/*
- * If we're using our own SPNEGO implementation (see configure.in),
- * pull it in now. Otherwise, we just use whatever GSSAPI supplies.
- */
-#if defined(GSSAPI) && defined(USE_ISC_SPNEGO)
-#include "spnego.h"
-#define gss_accept_sec_context gss_accept_sec_context_spnego
-#define gss_init_sec_context gss_init_sec_context_spnego
-#endif
-
-/*
- * Solaris8 apparently needs an explicit OID set, and Solaris10 needs
- * one for anything but Kerberos. Supplying an explicit OID set
- * doesn't appear to hurt anything in other implementations, so we
- * always use one. If we're not using our own SPNEGO implementation,
- * we include SPNEGO's OID.
- */
-#ifdef GSSAPI
-#include ISC_PLATFORM_KRB5HEADER
-
-static unsigned char krb5_mech_oid_bytes[] = {
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
-};
-
-#ifndef USE_ISC_SPNEGO
-static unsigned char spnego_mech_oid_bytes[] = {
- 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
-};
-#endif
-
-static gss_OID_desc mech_oid_set_array[] = {
- { sizeof(krb5_mech_oid_bytes), krb5_mech_oid_bytes },
-#ifndef USE_ISC_SPNEGO
- { sizeof(spnego_mech_oid_bytes), spnego_mech_oid_bytes },
-#endif
-};
-
-static gss_OID_set_desc mech_oid_set = {
- sizeof(mech_oid_set_array) / sizeof(*mech_oid_set_array),
- mech_oid_set_array
-};
-
-#endif
-
-#define REGION_TO_GBUFFER(r, gb) \
- do { \
- (gb).length = (r).length; \
- (gb).value = (r).base; \
- } while (0)
-
-#define GBUFFER_TO_REGION(gb, r) \
- do { \
- (r).length = (unsigned int)(gb).length; \
- (r).base = (gb).value; \
- } while (0)
-
-
-#define RETERR(x) do { \
- result = (x); \
- if (result != ISC_R_SUCCESS) \
- goto out; \
- } while (0)
-
-#ifdef GSSAPI
-static inline void
-name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
- gss_buffer_desc *gbuffer)
-{
- dns_name_t tname, *namep;
- isc_region_t r;
- isc_result_t result;
-
- if (!dns_name_isabsolute(name))
- namep = name;
- else
- {
- unsigned int labels;
- dns_name_init(&tname, NULL);
- labels = dns_name_countlabels(name);
- dns_name_getlabelsequence(name, 0, labels - 1, &tname);
- namep = &tname;
- }
-
- result = dns_name_toprincipal(namep, buffer);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc_buffer_putuint8(buffer, 0);
- isc_buffer_usedregion(buffer, &r);
- REGION_TO_GBUFFER(r, *gbuffer);
-}
-
-static void
-log_cred(const gss_cred_id_t cred) {
- OM_uint32 gret, minor, lifetime;
- gss_name_t gname;
- gss_buffer_desc gbuffer;
- gss_cred_usage_t usage;
- const char *usage_text;
- char buf[1024];
-
- gret = gss_inquire_cred(&minor, cred, &gname, &lifetime, &usage, NULL);
- if (gret != GSS_S_COMPLETE) {
- gss_log(3, "failed gss_inquire_cred: %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- return;
- }
-
- gret = gss_display_name(&minor, gname, &gbuffer, NULL);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_display_name: %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- else {
- switch (usage) {
- case GSS_C_BOTH:
- usage_text = "GSS_C_BOTH";
- break;
- case GSS_C_INITIATE:
- usage_text = "GSS_C_INITIATE";
- break;
- case GSS_C_ACCEPT:
- usage_text = "GSS_C_ACCEPT";
- break;
- default:
- usage_text = "???";
- }
- gss_log(3, "gss cred: \"%s\", %s, %lu", (char *)gbuffer.value,
- usage_text, (unsigned long)lifetime);
- }
-
- if (gret == GSS_S_COMPLETE) {
- if (gbuffer.length != 0U) {
- gret = gss_release_buffer(&minor, &gbuffer);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_release_buffer: %s",
- gss_error_tostring(gret, minor, buf,
- sizeof(buf)));
- }
- }
-
- gret = gss_release_name(&minor, &gname);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_release_name: %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
-}
-#endif
-
-#ifdef GSSAPI
-/*
- * check for the most common configuration errors.
- *
- * The errors checked for are:
- * - tkey-gssapi-credential doesn't start with DNS/
- * - the default realm in /etc/krb5.conf and the
- * tkey-gssapi-credential bind config option don't match
- *
- * Note that if tkey-gssapi-keytab is set then these configure checks
- * are not performed, and runtime errors from gssapi are used instead
- */
-static void
-check_config(const char *gss_name) {
- const char *p;
- krb5_context krb5_ctx;
- char *krb5_realm_name = NULL;
-
- if (strncasecmp(gss_name, "DNS/", 4) != 0) {
- gss_log(ISC_LOG_ERROR, "tkey-gssapi-credential (%s) "
- "should start with 'DNS/'", gss_name);
- return;
- }
-
- if (krb5_init_context(&krb5_ctx) != 0) {
- gss_log(ISC_LOG_ERROR, "Unable to initialise krb5 context");
- return;
- }
- if (krb5_get_default_realm(krb5_ctx, &krb5_realm_name) != 0) {
- gss_log(ISC_LOG_ERROR, "Unable to get krb5 default realm");
- krb5_free_context(krb5_ctx);
- return;
- }
- p = strchr(gss_name, '@');
- if (p == NULL) {
- gss_log(ISC_LOG_ERROR, "badly formatted "
- "tkey-gssapi-credentials (%s)", gss_name);
- krb5_free_context(krb5_ctx);
- return;
- }
- if (strcasecmp(p + 1, krb5_realm_name) != 0) {
- gss_log(ISC_LOG_ERROR, "default realm from krb5.conf (%s) "
- "does not match tkey-gssapi-credential (%s)",
- krb5_realm_name, gss_name);
- krb5_free_context(krb5_ctx);
- return;
- }
- krb5_free_context(krb5_ctx);
-}
-#endif
-
-isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
- gss_cred_id_t *cred)
-{
-#ifdef GSSAPI
- isc_result_t result;
- isc_buffer_t namebuf;
- gss_name_t gname;
- gss_buffer_desc gnamebuf;
- unsigned char array[DNS_NAME_MAXTEXT + 1];
- OM_uint32 gret, minor;
- OM_uint32 lifetime;
- gss_cred_usage_t usage;
- char buf[1024];
-
- REQUIRE(cred != NULL && *cred == NULL);
-
- /*
- * XXXSRA In theory we could use GSS_C_NT_HOSTBASED_SERVICE
- * here when we're in the acceptor role, which would let us
- * default the hostname and use a compiled in default service
- * name of "DNS", giving one less thing to configure in
- * named.conf. Unfortunately, this creates a circular
- * dependency due to DNS-based realm lookup in at least one
- * GSSAPI implementation (Heimdal). Oh well.
- */
- if (name != NULL) {
- isc_buffer_init(&namebuf, array, sizeof(array));
- name_to_gbuffer(name, &namebuf, &gnamebuf);
- gret = gss_import_name(&minor, &gnamebuf,
- GSS_C_NO_OID, &gname);
- if (gret != GSS_S_COMPLETE) {
- check_config((char *)array);
-
- gss_log(3, "failed gss_import_name: %s",
- gss_error_tostring(gret, minor, buf,
- sizeof(buf)));
- return (ISC_R_FAILURE);
- }
- } else
- gname = NULL;
-
- /* Get the credentials. */
- if (gname != NULL)
- gss_log(3, "acquiring credentials for %s",
- (char *)gnamebuf.value);
- else {
- /* XXXDCL does this even make any sense? */
- gss_log(3, "acquiring credentials for ?");
- }
-
- if (initiate)
- usage = GSS_C_INITIATE;
- else
- usage = GSS_C_ACCEPT;
-
- gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
- &mech_oid_set, usage, cred, NULL, &lifetime);
-
- if (gret != GSS_S_COMPLETE) {
- gss_log(3, "failed to acquire %s credentials for %s: %s",
- initiate ? "initiate" : "accept",
- (gname != NULL) ? (char *)gnamebuf.value : "?",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- if (gname != NULL)
- check_config((char *)array);
- result = ISC_R_FAILURE;
- goto cleanup;
- }
-
- gss_log(4, "acquired %s credentials for %s",
- initiate ? "initiate" : "accept",
- (gname != NULL) ? (char *)gnamebuf.value : "?");
-
- log_cred(*cred);
- result = ISC_R_SUCCESS;
-
-cleanup:
- if (gname != NULL) {
- gret = gss_release_name(&minor, &gname);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_release_name: %s",
- gss_error_tostring(gret, minor, buf,
- sizeof(buf)));
- }
-
- return (result);
-#else
- REQUIRE(cred != NULL && *cred == NULL);
-
- UNUSED(name);
- UNUSED(initiate);
- UNUSED(cred);
-
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-isc_boolean_t
-dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
- dns_name_t *realm)
-{
-#ifdef GSSAPI
- char sbuf[DNS_NAME_FORMATSIZE];
- char nbuf[DNS_NAME_FORMATSIZE];
- char rbuf[DNS_NAME_FORMATSIZE];
- char *sname;
- char *rname;
- isc_buffer_t buffer;
- isc_result_t result;
-
- /*
- * It is far, far easier to write the names we are looking at into
- * a string, and do string operations on them.
- */
- isc_buffer_init(&buffer, sbuf, sizeof(sbuf));
- result = dns_name_toprincipal(signer, &buffer);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc_buffer_putuint8(&buffer, 0);
- if (name != NULL)
- dns_name_format(name, nbuf, sizeof(nbuf));
- dns_name_format(realm, rbuf, sizeof(rbuf));
-
- /*
- * Find the realm portion. This is the part after the @. If it
- * does not exist, we don't have something we like, so we fail our
- * compare.
- */
- rname = strchr(sbuf, '@');
- if (rname == NULL)
- return (isc_boolean_false);
- *rname = '\0';
- rname++;
-
- /*
- * Find the host portion of the signer's name. We do this by
- * searching for the first / character. We then check to make
- * certain the instance name is "host"
- *
- * This will work for
- * host/example.com@EXAMPLE.COM
- */
- sname = strchr(sbuf, '/');
- if (sname == NULL)
- return (isc_boolean_false);
- *sname = '\0';
- sname++;
- if (strcmp(sbuf, "host") != 0)
- return (isc_boolean_false);
-
- /*
- * Now, we do a simple comparison between the name and the realm.
- */
- if (name != NULL) {
- if ((strcasecmp(sname, nbuf) == 0)
- && (strcmp(rname, rbuf) == 0))
- return (isc_boolean_true);
- } else {
- if (strcmp(rname, rbuf) == 0)
- return (isc_boolean_true);
- }
-
- return (isc_boolean_false);
-#else
- UNUSED(signer);
- UNUSED(name);
- UNUSED(realm);
- return (isc_boolean_false);
-#endif
-}
-
-isc_boolean_t
-dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
- dns_name_t *realm)
-{
-#ifdef GSSAPI
- char sbuf[DNS_NAME_FORMATSIZE];
- char nbuf[DNS_NAME_FORMATSIZE];
- char rbuf[DNS_NAME_FORMATSIZE];
- char *sname;
- char *nname;
- char *rname;
- isc_buffer_t buffer;
- isc_result_t result;
-
- /*
- * It is far, far easier to write the names we are looking at into
- * a string, and do string operations on them.
- */
- isc_buffer_init(&buffer, sbuf, sizeof(sbuf));
- result = dns_name_toprincipal(signer, &buffer);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc_buffer_putuint8(&buffer, 0);
- if (name != NULL)
- dns_name_format(name, nbuf, sizeof(nbuf));
- dns_name_format(realm, rbuf, sizeof(rbuf));
-
- /*
- * Find the realm portion. This is the part after the @. If it
- * does not exist, we don't have something we like, so we fail our
- * compare.
- */
- rname = strchr(sbuf, '@');
- if (rname == NULL)
- return (isc_boolean_false);
- sname = strchr(sbuf, '$');
- if (sname == NULL)
- return (isc_boolean_false);
-
- /*
- * Verify that the $ and @ follow one another.
- */
- if (rname - sname != 1)
- return (isc_boolean_false);
-
- /*
- * Find the host portion of the signer's name. Zero out the $ so
- * it terminates the signer's name, and skip past the @ for
- * the realm.
- *
- * All service principals in Microsoft format seem to be in
- * machinename$@EXAMPLE.COM
- * format.
- */
- rname++;
- *sname = '\0';
- sname = sbuf;
-
- /*
- * Find the first . in the target name, and make it the end of
- * the string. The rest of the name has to match the realm.
- */
- if (name != NULL) {
- nname = strchr(nbuf, '.');
- if (nname == NULL)
- return (isc_boolean_false);
- *nname++ = '\0';
- }
-
- /*
- * Now, we do a simple comparison between the name and the realm.
- */
- if (name != NULL) {
- if ((strcasecmp(sname, nbuf) == 0)
- && (strcmp(rname, rbuf) == 0)
- && (strcasecmp(nname, rbuf) == 0))
- return (isc_boolean_true);
- } else {
- if (strcmp(rname, rbuf) == 0)
- return (isc_boolean_true);
- }
-
-
- return (isc_boolean_false);
-#else
- UNUSED(signer);
- UNUSED(name);
- UNUSED(realm);
- return (isc_boolean_false);
-#endif
-}
-
-isc_result_t
-dst_gssapi_releasecred(gss_cred_id_t *cred) {
-#ifdef GSSAPI
- OM_uint32 gret, minor;
- char buf[1024];
-
- REQUIRE(cred != NULL && *cred != NULL);
-
- gret = gss_release_cred(&minor, cred);
- if (gret != GSS_S_COMPLETE) {
- /* Log the error, but still free the credential's memory */
- gss_log(3, "failed releasing credential: %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- }
- *cred = NULL;
-
- return(ISC_R_SUCCESS);
-#else
- UNUSED(cred);
-
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-#ifdef GSSAPI
-/*
- * Format a gssapi error message info into a char ** on the given memory
- * context. This is used to return gssapi error messages back up the
- * call chain for reporting to the user.
- */
-static void
-gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor,
- char **err_message)
-{
- char buf[1024];
- char *estr;
-
- if (err_message == NULL || mctx == NULL) {
- /* the caller doesn't want any error messages */
- return;
- }
-
- estr = gss_error_tostring(major, minor, buf, sizeof(buf));
- if (estr != NULL)
- (*err_message) = isc_mem_strdup(mctx, estr);
-}
-#endif
-
-isc_result_t
-dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
- isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
- isc_mem_t *mctx, char **err_message)
-{
-#ifdef GSSAPI
- isc_region_t r;
- isc_buffer_t namebuf;
- gss_name_t gname;
- OM_uint32 gret, minor, ret_flags, flags;
- gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
- isc_result_t result;
- gss_buffer_desc gnamebuf;
- unsigned char array[DNS_NAME_MAXTEXT + 1];
-
- /* Client must pass us a valid gss_ctx_id_t here */
- REQUIRE(gssctx != NULL);
- REQUIRE(mctx != NULL);
-
- isc_buffer_init(&namebuf, array, sizeof(array));
- name_to_gbuffer(name, &namebuf, &gnamebuf);
-
- /* Get the name as a GSS name */
- gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
- if (gret != GSS_S_COMPLETE) {
- gss_err_message(mctx, gret, minor, err_message);
- result = ISC_R_FAILURE;
- goto out;
- }
-
- if (intoken != NULL) {
- /* Don't call gss_release_buffer for gintoken! */
- REGION_TO_GBUFFER(*intoken, gintoken);
- gintokenp = &gintoken;
- } else {
- gintokenp = NULL;
- }
-
- /*
- * Note that we don't set GSS_C_SEQUENCE_FLAG as Windows DNS
- * servers don't like it.
- */
- flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;
-
- gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
- gname, GSS_SPNEGO_MECHANISM, flags,
- 0, NULL, gintokenp,
- NULL, &gouttoken, &ret_flags, NULL);
-
- if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
- gss_err_message(mctx, gret, minor, err_message);
- if (err_message != NULL && *err_message != NULL)
- gss_log(3, "Failure initiating security context: %s",
- *err_message);
- else
- gss_log(3, "Failure initiating security context");
-
- result = ISC_R_FAILURE;
- goto out;
- }
-
- /*
- * XXXSRA Not handled yet: RFC 3645 3.1.1: check ret_flags
- * MUTUAL and INTEG flags, fail if either not set.
- */
-
- /*
- * RFC 2744 states the a valid output token has a non-zero length.
- */
- if (gouttoken.length != 0U) {
- GBUFFER_TO_REGION(gouttoken, r);
- RETERR(isc_buffer_copyregion(outtoken, &r));
- }
-
- if (gret == GSS_S_COMPLETE)
- result = ISC_R_SUCCESS;
- else
- result = DNS_R_CONTINUE;
-
- out:
- if (gouttoken.length != 0U)
- (void)gss_release_buffer(&minor, &gouttoken);
- (void)gss_release_name(&minor, &gname);
- return (result);
-#else
- UNUSED(name);
- UNUSED(intoken);
- UNUSED(outtoken);
- UNUSED(gssctx);
- UNUSED(mctx);
- UNUSED(err_message);
-
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-isc_result_t
-dst_gssapi_acceptctx(gss_cred_id_t cred,
- const char *gssapi_keytab,
- isc_region_t *intoken, isc_buffer_t **outtoken,
- gss_ctx_id_t *ctxout, dns_name_t *principal,
- isc_mem_t *mctx)
-{
-#ifdef GSSAPI
- isc_region_t r;
- isc_buffer_t namebuf;
- gss_buffer_desc gnamebuf = GSS_C_EMPTY_BUFFER, gintoken,
- gouttoken = GSS_C_EMPTY_BUFFER;
- OM_uint32 gret, minor;
- gss_ctx_id_t context = GSS_C_NO_CONTEXT;
- gss_name_t gname = NULL;
- isc_result_t result;
- char buf[1024];
-
- REQUIRE(outtoken != NULL && *outtoken == NULL);
-
- REGION_TO_GBUFFER(*intoken, gintoken);
-
- if (*ctxout == NULL)
- context = GSS_C_NO_CONTEXT;
- else
- context = *ctxout;
-
- if (gssapi_keytab != NULL) {
-#if defined(ISC_PLATFORM_GSSAPI_KRB5_HEADER) || defined(WIN32)
- gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
- if (gret != GSS_S_COMPLETE) {
- gss_log(3, "failed "
- "gsskrb5_register_acceptor_identity(%s): %s",
- gssapi_keytab,
- gss_error_tostring(gret, 0, buf, sizeof(buf)));
- return (DNS_R_INVALIDTKEY);
- }
-#else
- /*
- * Minimize memory leakage by only setting KRB5_KTNAME
- * if it needs to change.
- */
- const char *old = getenv("KRB5_KTNAME");
- if (old == NULL || strcmp(old, gssapi_keytab) != 0) {
- size_t size;
- char *kt;
-
- size = strlen(gssapi_keytab) + 13;
- kt = malloc(size);
- if (kt == NULL)
- return (ISC_R_NOMEMORY);
- snprintf(kt, size, "KRB5_KTNAME=%s", gssapi_keytab);
- if (putenv(kt) != 0)
- return (ISC_R_NOMEMORY);
- }
-#endif
- }
-
- log_cred(cred);
-
- gret = gss_accept_sec_context(&minor, &context, cred, &gintoken,
- GSS_C_NO_CHANNEL_BINDINGS, &gname,
- NULL, &gouttoken, NULL, NULL, NULL);
-
- result = ISC_R_FAILURE;
-
- switch (gret) {
- case GSS_S_COMPLETE:
- case GSS_S_CONTINUE_NEEDED:
- break;
- case GSS_S_DEFECTIVE_TOKEN:
- case GSS_S_DEFECTIVE_CREDENTIAL:
- case GSS_S_BAD_SIG:
- case GSS_S_DUPLICATE_TOKEN:
- case GSS_S_OLD_TOKEN:
- case GSS_S_NO_CRED:
- case GSS_S_CREDENTIALS_EXPIRED:
- case GSS_S_BAD_BINDINGS:
- case GSS_S_NO_CONTEXT:
- case GSS_S_BAD_MECH:
- case GSS_S_FAILURE:
- result = DNS_R_INVALIDTKEY;
- /* fall through */
- default:
- gss_log(3, "failed gss_accept_sec_context: %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- return (result);
- }
-
- if (gouttoken.length > 0U) {
- RETERR(isc_buffer_allocate(mctx, outtoken,
- (unsigned int)gouttoken.length));
- GBUFFER_TO_REGION(gouttoken, r);
- RETERR(isc_buffer_copyregion(*outtoken, &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)));
- RETERR(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);
-
- RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
- 0, NULL));
-
- if (gnamebuf.length != 0U) {
- gret = gss_release_buffer(&minor, &gnamebuf);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_release_buffer: %s",
- gss_error_tostring(gret, minor, buf,
- sizeof(buf)));
- }
- } else
- result = DNS_R_CONTINUE;
-
- *ctxout = context;
-
- out:
- if (gname != NULL) {
- gret = gss_release_name(&minor, &gname);
- if (gret != GSS_S_COMPLETE)
- gss_log(3, "failed gss_release_name: %s",
- gss_error_tostring(gret, minor, buf,
- sizeof(buf)));
- }
-
- return (result);
-#else
- UNUSED(cred);
- UNUSED(gssapi_keytab);
- UNUSED(intoken);
- UNUSED(outtoken);
- UNUSED(ctxout);
- UNUSED(principal);
- UNUSED(mctx);
-
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-isc_result_t
-dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx)
-{
-#ifdef GSSAPI
- OM_uint32 gret, minor;
- char buf[1024];
-
- UNUSED(mctx);
-
- REQUIRE(gssctx != NULL && *gssctx != NULL);
-
- /* Delete the context from the GSS provider */
- gret = gss_delete_sec_context(&minor, gssctx, GSS_C_NO_BUFFER);
- if (gret != GSS_S_COMPLETE) {
- /* Log the error, but still free the context's memory */
- gss_log(3, "Failure deleting security context %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- }
- return(ISC_R_SUCCESS);
-#else
- UNUSED(mctx);
- UNUSED(gssctx);
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-char *
-gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
- char *buf, size_t buflen) {
-#ifdef GSSAPI
- gss_buffer_desc msg_minor = GSS_C_EMPTY_BUFFER,
- msg_major = GSS_C_EMPTY_BUFFER;
- OM_uint32 msg_ctx, minor_stat;
-
- /* Handle major status */
- msg_ctx = 0;
- (void)gss_display_status(&minor_stat, major, GSS_C_GSS_CODE,
- GSS_C_NULL_OID, &msg_ctx, &msg_major);
-
- /* Handle minor status */
- msg_ctx = 0;
- (void)gss_display_status(&minor_stat, minor, GSS_C_MECH_CODE,
- GSS_C_NULL_OID, &msg_ctx, &msg_minor);
-
- snprintf(buf, buflen, "GSSAPI error: Major = %s, Minor = %s.",
- (char *)msg_major.value, (char *)msg_minor.value);
-
- if (msg_major.length != 0U)
- (void)gss_release_buffer(&minor_stat, &msg_major);
- if (msg_minor.length != 0U)
- (void)gss_release_buffer(&minor_stat, &msg_minor);
- return(buf);
-#else
- snprintf(buf, buflen, "GSSAPI error: Major = %u, Minor = %u.",
- major, minor);
-
- return (buf);
-#endif
-}
-
-void
-gss_log(int level, const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
- DNS_LOGMODULE_TKEY, ISC_LOG_DEBUG(level), fmt, ap);
- va_end(ap);
-}
-
-/*! \file */