summaryrefslogtreecommitdiff
path: root/usr.sbin/bind/lib/dns
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bind/lib/dns')
-rw-r--r--usr.sbin/bind/lib/dns/Makefile.in8
-rw-r--r--usr.sbin/bind/lib/dns/dst_api.c71
-rw-r--r--usr.sbin/bind/lib/dns/dst_internal.h5
-rw-r--r--usr.sbin/bind/lib/dns/gssapi_link.c395
-rw-r--r--usr.sbin/bind/lib/dns/gssapictx.c886
-rw-r--r--usr.sbin/bind/lib/dns/include/dns/tkey.h74
-rw-r--r--usr.sbin/bind/lib/dns/include/dns/tsig.h6
-rw-r--r--usr.sbin/bind/lib/dns/include/dns/types.h9
-rw-r--r--usr.sbin/bind/lib/dns/include/dst/Makefile.in4
-rw-r--r--usr.sbin/bind/lib/dns/include/dst/dst.h39
-rw-r--r--usr.sbin/bind/lib/dns/include/dst/gssapi.h206
-rw-r--r--usr.sbin/bind/lib/dns/spnego.c1828
-rw-r--r--usr.sbin/bind/lib/dns/spnego.h71
-rw-r--r--usr.sbin/bind/lib/dns/spnego_asn1.pl200
-rw-r--r--usr.sbin/bind/lib/dns/ssu.c19
-rw-r--r--usr.sbin/bind/lib/dns/tkey.c473
-rw-r--r--usr.sbin/bind/lib/dns/tsig.c42
17 files changed, 28 insertions, 4308 deletions
diff --git a/usr.sbin/bind/lib/dns/Makefile.in b/usr.sbin/bind/lib/dns/Makefile.in
index 433c2c06154..faeeb75268b 100644
--- a/usr.sbin/bind/lib/dns/Makefile.in
+++ b/usr.sbin/bind/lib/dns/Makefile.in
@@ -32,9 +32,9 @@ VERSION=@BIND9_VERSION@
USE_ISC_SPNEGO = @USE_ISC_SPNEGO@
CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} \
- ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+ ${ISC_INCLUDES} @DST_OPENSSL_INC@
-CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ ${USE_ISC_SPNEGO}
+CDEFINES = -DUSE_MD5 @CRYPTO@ ${USE_ISC_SPNEGO}
CWARNINGS =
@@ -55,7 +55,7 @@ OPENSSLLINKOBJS = openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \
DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \
dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
- gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@
+ hmac_link.@O@ key.@O@
# Alphabetically
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
@@ -90,7 +90,7 @@ OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \
DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \
dst_api.c dst_lib.c dst_parse.c \
- dst_result.c gssapi_link.c gssapictx.c \
+ dst_result.c \
hmac_link.c key.c
DNSSRCS = acache.c acl.c adb.c byaddr.c \
diff --git a/usr.sbin/bind/lib/dns/dst_api.c b/usr.sbin/bind/lib/dns/dst_api.c
index 90407cbb70b..15d3a1e6364 100644
--- a/usr.sbin/bind/lib/dns/dst_api.c
+++ b/usr.sbin/bind/lib/dns/dst_api.c
@@ -33,7 +33,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.11 2020/01/09 13:52:23 florian Exp $
+ * $Id: dst_api.c,v 1.12 2020/01/09 13:56:37 florian Exp $
*/
/*! \file */
@@ -84,8 +84,6 @@ static isc_entropy_t *dst_entropy_pool = NULL;
static unsigned int dst_entropy_flags = 0;
static isc_boolean_t dst_initialized = ISC_FALSE;
-void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
-
isc_mem_t *dst__memory_pool = NULL;
/*
@@ -231,9 +229,6 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448]));
#endif
#endif /* if OPENSSL */
-#ifdef GSSAPI
- RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
-#endif
dst_initialized = ISC_TRUE;
return (ISC_R_SUCCESS);
@@ -773,46 +768,6 @@ dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
return (result);
}
-gss_ctx_id_t
-dst_key_getgssctx(const dst_key_t *key)
-{
- REQUIRE(key != NULL);
-
- return (key->keydata.gssctx);
-}
-
-isc_result_t
-dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
- dst_key_t **keyp, isc_region_t *intoken)
-{
- dst_key_t *key;
- isc_result_t result;
-
- REQUIRE(gssctx != NULL);
- REQUIRE(keyp != NULL && *keyp == NULL);
-
- key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
- 0, dns_rdataclass_in, 0, mctx);
- if (key == NULL)
- return (ISC_R_NOMEMORY);
-
- if (intoken != NULL) {
- /*
- * Keep the token for use by external ssu rules. They may need
- * to examine the PAC in the kerberos ticket.
- */
- RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
- intoken->length));
- RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
- }
-
- key->keydata.gssctx = gssctx;
- *keyp = key;
- result = ISC_R_SUCCESS;
-out:
- return result;
-}
-
isc_result_t
dst_key_buildinternal(dns_name_t *name, unsigned int alg,
unsigned int bits, unsigned int flags,
@@ -1239,9 +1194,6 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
case DST_ALG_HMACSHA512:
*n = ISC_SHA512_DIGESTLENGTH;
break;
- case DST_ALG_GSSAPI:
- *n = 128; /*%< XXX */
- break;
default:
return (DST_R_UNSUPPORTEDALG);
}
@@ -1548,7 +1500,6 @@ issymmetric(const dst_key_t *key) {
case DST_ALG_HMACSHA256:
case DST_ALG_HMACSHA384:
case DST_ALG_HMACSHA512:
- case DST_ALG_GSSAPI:
return (ISC_TRUE);
default:
return (ISC_FALSE);
@@ -1864,26 +1815,6 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
unsigned int
dst__entropy_status(void) {
-#ifdef GSSAPI
- unsigned int flags = dst_entropy_flags;
- isc_result_t ret;
- unsigned char buf[32];
- static isc_boolean_t first = ISC_TRUE;
-
- if (dst_entropy_pool == NULL)
- return (0);
-
- if (first) {
- /* Someone believes RAND_status() initializes the PRNG */
- flags &= ~ISC_ENTROPY_GOODONLY;
- ret = isc_entropy_getdata(dst_entropy_pool, buf,
- sizeof(buf), NULL, flags);
- INSIST(ret == ISC_R_SUCCESS);
- isc_entropy_putdata(dst_entropy_pool, buf,
- sizeof(buf), 2 * sizeof(buf));
- first = ISC_FALSE;
- }
-#endif
return (isc_entropy_status(dst_entropy_pool));
}
diff --git a/usr.sbin/bind/lib/dns/dst_internal.h b/usr.sbin/bind/lib/dns/dst_internal.h
index fd20f2e2227..46f9464a2ad 100644
--- a/usr.sbin/bind/lib/dns/dst_internal.h
+++ b/usr.sbin/bind/lib/dns/dst_internal.h
@@ -31,7 +31,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_internal.h,v 1.4 2020/01/09 13:52:23 florian Exp $ */
+/* $Id: dst_internal.h,v 1.5 2020/01/09 13:56:37 florian Exp $ */
#ifndef DST_DST_INTERNAL_H
#define DST_DST_INTERNAL_H 1
@@ -111,7 +111,6 @@ struct dst_key {
char *label; /*%< engine label (HSM) */
union {
void *generic;
- gss_ctx_id_t gssctx;
#ifdef OPENSSL
#if !defined(USE_EVP) || !USE_EVP
RSA *rsa;
@@ -149,7 +148,6 @@ struct dst_context {
isc_logcategory_t *category;
union {
void *generic;
- dst_gssapi_signverifyctx_t *gssctx;
isc_sha1_t *sha1ctx;
isc_sha256_t *sha256ctx;
isc_sha512_t *sha512ctx;
@@ -222,7 +220,6 @@ isc_result_t dst__hmacsha384_init(struct dst_func **funcp);
isc_result_t dst__hmacsha512_init(struct dst_func **funcp);
isc_result_t dst__opensslrsa_init(struct dst_func **funcp,
unsigned char algorithm);
-isc_result_t dst__gssapi_init(struct dst_func **funcp);
#ifdef HAVE_OPENSSL_ECDSA
isc_result_t dst__opensslecdsa_init(struct dst_func **funcp);
#endif
diff --git a/usr.sbin/bind/lib/dns/gssapi_link.c b/usr.sbin/bind/lib/dns/gssapi_link.c
deleted file mode 100644
index 3b6ad2e8061..00000000000
--- a/usr.sbin/bind/lib/dns/gssapi_link.c
+++ /dev/null
@@ -1,395 +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: gssapi_link.c,v 1.4 2020/01/09 13:47:12 florian Exp $
- */
-
-#include <config.h>
-
-#ifdef GSSAPI
-
-#include <isc/base64.h>
-#include <isc/buffer.h>
-#include <isc/mem.h>
-
-#include <isc/string.h>
-#include <isc/util.h>
-
-#include <dst/result.h>
-
-#include "dst_internal.h"
-#include "dst_parse.h"
-
-#include <dst/gssapi.h>
-
-#define INITIAL_BUFFER_SIZE 1024
-#define BUFFER_EXTRA 1024
-
-#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)
-
-
-struct dst_gssapi_signverifyctx {
- isc_buffer_t *buffer;
-};
-
-/*%
- * Allocate a temporary "context" for use in gathering data for signing
- * or verifying.
- */
-static isc_result_t
-gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
- dst_gssapi_signverifyctx_t *ctx;
- isc_result_t result;
-
- UNUSED(key);
-
- ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
- if (ctx == NULL)
- return (ISC_R_NOMEMORY);
- ctx->buffer = NULL;
- result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
- INITIAL_BUFFER_SIZE);
- if (result != ISC_R_SUCCESS) {
- isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
- return (result);
- }
-
- dctx->ctxdata.gssctx = ctx;
-
- return (ISC_R_SUCCESS);
-}
-
-/*%
- * Destroy the temporary sign/verify context.
- */
-static void
-gssapi_destroy_signverify_ctx(dst_context_t *dctx) {
- dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
-
- if (ctx != NULL) {
- if (ctx->buffer != NULL)
- isc_buffer_free(&ctx->buffer);
- isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
- dctx->ctxdata.gssctx = NULL;
- }
-}
-
-/*%
- * Add data to our running buffer of data we will be signing or verifying.
- * This code will see if the new data will fit in our existing buffer, and
- * copy it in if it will. If not, it will attempt to allocate a larger
- * buffer and copy old+new into it, and free the old buffer.
- */
-static isc_result_t
-gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
- dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
- isc_buffer_t *newbuffer = NULL;
- isc_region_t r;
- unsigned int length;
- isc_result_t result;
-
- result = isc_buffer_copyregion(ctx->buffer, data);
- if (result == ISC_R_SUCCESS)
- return (ISC_R_SUCCESS);
-
- length = isc_buffer_length(ctx->buffer) + data->length + BUFFER_EXTRA;
-
- result = isc_buffer_allocate(dctx->mctx, &newbuffer, length);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- isc_buffer_usedregion(ctx->buffer, &r);
- (void)isc_buffer_copyregion(newbuffer, &r);
- (void)isc_buffer_copyregion(newbuffer, data);
-
- isc_buffer_free(&ctx->buffer);
- ctx->buffer = newbuffer;
-
- return (ISC_R_SUCCESS);
-}
-
-/*%
- * Sign.
- */
-static isc_result_t
-gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
- isc_region_t message;
- gss_buffer_desc gmessage, gsig;
- OM_uint32 minor, gret;
- gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
- char buf[1024];
-
- /*
- * Convert the data we wish to sign into a structure gssapi can
- * understand.
- */
- isc_buffer_usedregion(ctx->buffer, &message);
- REGION_TO_GBUFFER(message, gmessage);
-
- /*
- * Generate the signature.
- */
- gret = gss_get_mic(&minor, gssctx, GSS_C_QOP_DEFAULT, &gmessage,
- &gsig);
-
- /*
- * If it did not complete, we log the result and return a generic
- * failure code.
- */
- if (gret != GSS_S_COMPLETE) {
- gss_log(3, "GSS sign error: %s",
- gss_error_tostring(gret, minor, buf, sizeof(buf)));
- return (ISC_R_FAILURE);
- }
-
- /*
- * If it will not fit in our allocated buffer, return that we need
- * more space.
- */
- if (gsig.length > isc_buffer_availablelength(sig)) {
- gss_release_buffer(&minor, &gsig);
- return (ISC_R_NOSPACE);
- }
-
- /*
- * Copy the output into our buffer space, and release the gssapi
- * allocated space.
- */
- isc_buffer_putmem(sig, gsig.value, (unsigned int)gsig.length);
- if (gsig.length != 0U)
- gss_release_buffer(&minor, &gsig);
-
- return (ISC_R_SUCCESS);
-}
-
-/*%
- * Verify.
- */
-static isc_result_t
-gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
- dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
- isc_region_t message, r;
- gss_buffer_desc gmessage, gsig;
- OM_uint32 minor, gret;
- gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
- unsigned char *buf;
- char err[1024];
-
- /*
- * Convert the data we wish to sign into a structure gssapi can
- * understand.
- */
- isc_buffer_usedregion(ctx->buffer, &message);
- REGION_TO_GBUFFER(message, gmessage);
-
- /*
- * XXXMLG
- * It seem that gss_verify_mic() modifies the signature buffer,
- * at least on Heimdal's implementation. Copy it here to an allocated
- * buffer.
- */
- buf = isc_mem_allocate(dst__memory_pool, sig->length);
- if (buf == NULL)
- return (ISC_R_FAILURE);
- memmove(buf, sig->base, sig->length);
- r.base = buf;
- r.length = sig->length;
- REGION_TO_GBUFFER(r, gsig);
-
- /*
- * Verify the data.
- */
- gret = gss_verify_mic(&minor, gssctx, &gmessage, &gsig, NULL);
-
- isc_mem_free(dst__memory_pool, buf);
-
- /*
- * Convert return codes into something useful to us.
- */
- if (gret != GSS_S_COMPLETE) {
- gss_log(3, "GSS verify error: %s",
- gss_error_tostring(gret, minor, err, sizeof(err)));
- if (gret == GSS_S_DEFECTIVE_TOKEN ||
- gret == GSS_S_BAD_SIG ||
- gret == GSS_S_DUPLICATE_TOKEN ||
- gret == GSS_S_OLD_TOKEN ||
- gret == GSS_S_UNSEQ_TOKEN ||
- gret == GSS_S_GAP_TOKEN ||
- gret == GSS_S_CONTEXT_EXPIRED ||
- gret == GSS_S_NO_CONTEXT ||
- gret == GSS_S_FAILURE)
- return(DST_R_VERIFYFAILURE);
- else
- return (ISC_R_FAILURE);
- }
-
- return (ISC_R_SUCCESS);
-}
-
-static isc_boolean_t
-gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
- gss_ctx_id_t gsskey1 = key1->keydata.gssctx;
- gss_ctx_id_t gsskey2 = key2->keydata.gssctx;
-
- /* No idea */
- return (ISC_TF(gsskey1 == gsskey2));
-}
-
-static isc_result_t
-gssapi_generate(dst_key_t *key, int unused, void (*callback)(int)) {
- UNUSED(key);
- UNUSED(unused);
- UNUSED(callback);
-
- /* No idea */
- return (ISC_R_FAILURE);
-}
-
-static isc_boolean_t
-gssapi_isprivate(const dst_key_t *key) {
- UNUSED(key);
- return (ISC_TRUE);
-}
-
-static void
-gssapi_destroy(dst_key_t *key) {
- REQUIRE(key != NULL);
- dst_gssapi_deletectx(key->mctx, &key->keydata.gssctx);
- key->keydata.gssctx = NULL;
-}
-
-static isc_result_t
-gssapi_restore(dst_key_t *key, const char *keystr) {
- OM_uint32 major, minor;
- unsigned int len;
- isc_buffer_t *b = NULL;
- isc_region_t r;
- gss_buffer_desc gssbuffer;
- isc_result_t result;
-
- len = strlen(keystr);
- if ((len % 4) != 0U)
- return (ISC_R_BADBASE64);
-
- len = (len / 4) * 3;
-
- result = isc_buffer_allocate(key->mctx, &b, len);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- result = isc_base64_decodestring(keystr, b);
- if (result != ISC_R_SUCCESS) {
- isc_buffer_free(&b);
- return (result);
- }
-
- isc_buffer_remainingregion(b, &r);
- REGION_TO_GBUFFER(r, gssbuffer);
- major = gss_import_sec_context(&minor, &gssbuffer,
- &key->keydata.gssctx);
- if (major != GSS_S_COMPLETE) {
- isc_buffer_free(&b);
- return (ISC_R_FAILURE);
- }
-
- isc_buffer_free(&b);
- return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
- OM_uint32 major, minor;
- gss_buffer_desc gssbuffer;
- size_t len;
- char *buf;
- isc_buffer_t b;
- isc_region_t r;
- isc_result_t result;
-
- major = gss_export_sec_context(&minor, &key->keydata.gssctx,
- &gssbuffer);
- if (major != GSS_S_COMPLETE) {
- fprintf(stderr, "gss_export_sec_context -> %d, %d\n",
- major, minor);
- return (ISC_R_FAILURE);
- }
- if (gssbuffer.length == 0U)
- return (ISC_R_FAILURE);
- len = ((gssbuffer.length + 2)/3) * 4;
- buf = isc_mem_get(mctx, len);
- if (buf == NULL) {
- gss_release_buffer(&minor, &gssbuffer);
- return (ISC_R_NOMEMORY);
- }
- isc_buffer_init(&b, buf, (unsigned int)len);
- GBUFFER_TO_REGION(gssbuffer, r);
- result = isc_base64_totext(&r, 0, "", &b);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- gss_release_buffer(&minor, &gssbuffer);
- *buffer = buf;
- *length = (int)len;
- return (ISC_R_SUCCESS);
-}
-
-static dst_func_t gssapi_functions = {
- gssapi_create_signverify_ctx,
- NULL, /*%< createctx2 */
- gssapi_destroy_signverify_ctx,
- gssapi_adddata,
- gssapi_sign,
- gssapi_verify,
- NULL, /*%< verify2 */
- NULL, /*%< computesecret */
- gssapi_compare,
- NULL, /*%< paramcompare */
- gssapi_generate,
- gssapi_isprivate,
- gssapi_destroy,
- NULL, /*%< todns */
- NULL, /*%< fromdns */
- NULL, /*%< tofile */
- NULL, /*%< parse */
- NULL, /*%< cleanup */
- NULL, /*%< fromlabel */
- gssapi_dump,
- gssapi_restore,
-};
-
-isc_result_t
-dst__gssapi_init(dst_func_t **funcp) {
- REQUIRE(funcp != NULL);
- if (*funcp == NULL)
- *funcp = &gssapi_functions;
- return (ISC_R_SUCCESS);
-}
-
-#else
-int gssapi_link_unneeded = 1;
-#endif
-
-/*! \file */
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 */
diff --git a/usr.sbin/bind/lib/dns/include/dns/tkey.h b/usr.sbin/bind/lib/dns/include/dns/tkey.h
index 01b87bf7815..64ccde8bf37 100644
--- a/usr.sbin/bind/lib/dns/include/dns/tkey.h
+++ b/usr.sbin/bind/lib/dns/include/dns/tkey.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tkey.h,v 1.3 2019/12/17 01:46:32 sthen Exp $ */
+/* $Id: tkey.h,v 1.4 2020/01/09 13:56:37 florian Exp $ */
#ifndef DNS_TKEY_H
#define DNS_TKEY_H 1
@@ -26,24 +26,20 @@
#include <dns/types.h>
#include <dst/dst.h>
-#include <dst/gssapi.h>
ISC_LANG_BEGINDECLS
/* Key agreement modes */
#define DNS_TKEYMODE_SERVERASSIGNED 1
#define DNS_TKEYMODE_DIFFIEHELLMAN 2
-#define DNS_TKEYMODE_GSSAPI 3
#define DNS_TKEYMODE_RESOLVERASSIGNED 4
#define DNS_TKEYMODE_DELETE 5
struct dns_tkeyctx {
dst_key_t *dhkey;
dns_name_t *domain;
- gss_cred_id_t gsscred;
isc_mem_t *mctx;
isc_entropy_t *ectx;
- char *gssapi_keytab;
};
isc_result_t
@@ -121,32 +117,6 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
*/
isc_result_t
-dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
- isc_buffer_t *intoken, isc_uint32_t lifetime,
- gss_ctx_id_t *context, isc_boolean_t win2k,
- isc_mem_t *mctx, char **err_message);
-/*%<
- * Builds a query containing a TKEY that will generate a GSSAPI context.
- * The key is requested to have the specified lifetime (in seconds).
- *
- * Requires:
- *\li 'msg' is a valid message
- *\li 'name' is a valid name
- *\li 'gname' is a valid name
- *\li 'context' is a pointer to a valid gss_ctx_id_t
- * (which may have the value GSS_C_NO_CONTEXT)
- *\li 'win2k' when true says to turn on some hacks to work
- * with the non-standard GSS-TSIG of Windows 2000
- *
- * Returns:
- *\li ISC_R_SUCCESS msg was successfully updated to include the
- * query to be sent
- *\li other an error occurred while building the message
- *\li *err_message optional error message
- */
-
-
-isc_result_t
dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
/*%<
* Builds a query containing a TKEY record that will delete the
@@ -186,15 +156,6 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
*/
isc_result_t
-dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *gname, gss_ctx_id_t *context,
- isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
- dns_tsig_keyring_t *ring, char **err_message);
-/*%<
- * XXX
- */
-
-isc_result_t
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dns_tsig_keyring_t *ring);
/*%<
@@ -213,39 +174,6 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
* component of the query or response
*/
-isc_result_t
-dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *server, gss_ctx_id_t *context,
- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
- isc_boolean_t win2k, char **err_message);
-
-/*
- * Client side negotiation of GSS-TSIG. Process the response
- * to a TKEY, and establish a TSIG key if negotiation was successful.
- * Build a response to the input TKEY message. Can take multiple
- * calls to successfully establish the context.
- *
- * Requires:
- * 'qmsg' is a valid message, the original TKEY request;
- * it will be filled with the new message to send
- * 'rmsg' is a valid message, the incoming TKEY message
- * 'server' is the server name
- * 'context' is the input context handle
- * 'outkey' receives the established key, if non-NULL;
- * if non-NULL must point to NULL
- * 'ring' is the keyring in which to establish the key,
- * or NULL
- * 'win2k' when true says to turn on some hacks to work
- * with the non-standard GSS-TSIG of Windows 2000
- *
- * Returns:
- * ISC_R_SUCCESS context was successfully established
- * ISC_R_NOTFOUND couldn't find a needed part of the query
- * or response
- * DNS_R_CONTINUE additional context negotiation is required;
- * send the new qmsg to the server
- */
-
ISC_LANG_ENDDECLS
#endif /* DNS_TKEY_H */
diff --git a/usr.sbin/bind/lib/dns/include/dns/tsig.h b/usr.sbin/bind/lib/dns/include/dns/tsig.h
index c67b1b9b5a5..32f512dd059 100644
--- a/usr.sbin/bind/lib/dns/include/dns/tsig.h
+++ b/usr.sbin/bind/lib/dns/include/dns/tsig.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsig.h,v 1.4 2020/01/09 13:52:23 florian Exp $ */
+/* $Id: tsig.h,v 1.5 2020/01/09 13:56:37 florian Exp $ */
#ifndef DNS_TSIG_H
#define DNS_TSIG_H 1
@@ -37,10 +37,6 @@
/*
* Algorithms.
*/
-LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_gssapi_name;
-#define DNS_TSIG_GSSAPI_NAME dns_tsig_gssapi_name
-LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_gssapims_name;
-#define DNS_TSIG_GSSAPIMS_NAME dns_tsig_gssapims_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha1_name;
#define DNS_TSIG_HMACSHA1_NAME dns_tsig_hmacsha1_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha224_name;
diff --git a/usr.sbin/bind/lib/dns/include/dns/types.h b/usr.sbin/bind/lib/dns/include/dns/types.h
index 916260d6d9d..790f4c52a6d 100644
--- a/usr.sbin/bind/lib/dns/include/dns/types.h
+++ b/usr.sbin/bind/lib/dns/include/dns/types.h
@@ -139,15 +139,6 @@ typedef ISC_LIST(dns_zone_t) dns_zonelist_t;
typedef struct dns_zonemgr dns_zonemgr_t;
typedef struct dns_zt dns_zt_t;
-/*
- * If we are not using GSSAPI, define the types we use as opaque types here.
- */
-#ifndef GSSAPI
-typedef struct not_defined_gss_cred_id *gss_cred_id_t;
-typedef struct not_defined_gss_ctx *gss_ctx_id_t;
-#endif
-typedef struct dst_gssapi_signverifyctx dst_gssapi_signverifyctx_t;
-
typedef enum {
dns_hash_sha1 = 1
} dns_hash_t;
diff --git a/usr.sbin/bind/lib/dns/include/dst/Makefile.in b/usr.sbin/bind/lib/dns/include/dst/Makefile.in
index 07dad5715b5..20b011b905c 100644
--- a/usr.sbin/bind/lib/dns/include/dst/Makefile.in
+++ b/usr.sbin/bind/lib/dns/include/dst/Makefile.in
@@ -12,7 +12,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.3 2019/12/17 01:46:33 sthen Exp $
+# $Id: Makefile.in,v 1.4 2020/01/09 13:56:37 florian Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -20,7 +20,7 @@ top_srcdir = @top_srcdir@
VERSION=@BIND9_VERSION@
-HEADERS = dst.h gssapi.h lib.h result.h
+HEADERS = dst.h lib.h result.h
SUBDIRS =
TARGETS =
diff --git a/usr.sbin/bind/lib/dns/include/dst/dst.h b/usr.sbin/bind/lib/dns/include/dst/dst.h
index 80ab56d5216..3c13b6f83fc 100644
--- a/usr.sbin/bind/lib/dns/include/dst/dst.h
+++ b/usr.sbin/bind/lib/dns/include/dst/dst.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst.h,v 1.3 2019/12/17 01:46:33 sthen Exp $ */
+/* $Id: dst.h,v 1.4 2020/01/09 13:56:37 florian Exp $ */
#ifndef DST_DST_H
#define DST_DST_H 1
@@ -31,8 +31,6 @@
#include <dns/ds.h>
#include <dns/dsdigest.h>
-#include <dst/gssapi.h>
-
ISC_LANG_BEGINDECLS
/***
@@ -66,7 +64,6 @@ typedef struct dst_context dst_context_t;
#define DST_ALG_ED25519 15
#define DST_ALG_ED448 16
#define DST_ALG_HMACMD5 157
-#define DST_ALG_GSSAPI 160
#define DST_ALG_HMACSHA1 161 /* XXXMPA */
#define DST_ALG_HMACSHA224 162 /* XXXMPA */
#define DST_ALG_HMACSHA256 163 /* XXXMPA */
@@ -494,40 +491,6 @@ dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer);
*\li If successful, key will contain a valid private key.
*/
-gss_ctx_id_t
-dst_key_getgssctx(const dst_key_t *key);
-/*%<
- * Returns the opaque key data.
- * Be cautions when using this value unless you know what you are doing.
- *
- * Requires:
- *\li "key" is not NULL.
- *
- * Returns:
- *\li gssctx key data, possibly NULL.
- */
-
-isc_result_t
-dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
- dst_key_t **keyp, isc_region_t *intoken);
-/*%<
- * Converts a GSSAPI opaque context id into a DST key.
- *
- * Requires:
- *\li "name" is a valid absolute dns name.
- *\li "gssctx" is a GSSAPI context id.
- *\li "mctx" is a valid memory context.
- *\li "keyp" is not NULL and "*keyp" is NULL.
- *
- * Returns:
- *\li ISC_R_SUCCESS
- * \li any other result indicates failure
- *
- * Ensures:
- *\li If successful, *keyp will contain a valid key and be responsible for
- * the context id.
- */
-
#ifdef DST_KEY_INTERNAL
isc_result_t
dst_key_buildinternal(dns_name_t *name, unsigned int alg,
diff --git a/usr.sbin/bind/lib/dns/include/dst/gssapi.h b/usr.sbin/bind/lib/dns/include/dst/gssapi.h
deleted file mode 100644
index 41a2d4ae22c..00000000000
--- a/usr.sbin/bind/lib/dns/include/dst/gssapi.h
+++ /dev/null
@@ -1,206 +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: gssapi.h,v 1.4 2020/01/07 19:09:26 florian Exp $ */
-
-#ifndef DST_GSSAPI_H
-#define DST_GSSAPI_H 1
-
-/*! \file dst/gssapi.h */
-
-#include <isc/formatcheck.h>
-#include <isc/lang.h>
-#include <isc/platform.h>
-#include <isc/types.h>
-#include <dns/types.h>
-
-#ifdef GSSAPI
-#include ISC_PLATFORM_GSSAPIHEADER
-#ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER
-#include ISC_PLATFORM_GSSAPI_KRB5_HEADER
-#endif
-#ifndef GSS_SPNEGO_MECHANISM
-#define GSS_SPNEGO_MECHANISM ((void*)0)
-#endif
-#endif
-
-ISC_LANG_BEGINDECLS
-
-/***
- *** Types
- ***/
-
-/***
- *** Functions
- ***/
-
-isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
- gss_cred_id_t *cred);
-/*
- * Acquires GSS credentials.
- *
- * Requires:
- * 'name' is a valid name, preferably one known by the GSS provider
- * 'initiate' indicates whether the credentials are for initiating or
- * accepting contexts
- * 'cred' is a pointer to NULL, which will be allocated with the
- * credential handle. Call dst_gssapi_releasecred to free
- * the memory.
- *
- * Returns:
- * ISC_R_SUCCESS msg was successfully updated to include the
- * query to be sent
- * other an error occurred while building the message
- */
-
-isc_result_t
-dst_gssapi_releasecred(gss_cred_id_t *cred);
-/*
- * Releases GSS credentials. Calling this function does release the
- * memory allocated for the credential in dst_gssapi_acquirecred()
- *
- * Requires:
- * 'mctx' is a valid memory context
- * 'cred' is a pointer to the credential to be released
- *
- * Returns:
- * ISC_R_SUCCESS credential was released successfully
- * other an error occurred while releaseing
- * the credential
- */
-
-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);
-/*
- * Initiates a GSS context.
- *
- * Requires:
- * 'name' is a valid name, preferably one known by the GSS
- * provider
- * 'intoken' is a token received from the acceptor, or NULL if
- * there isn't one
- * 'outtoken' is a buffer to receive the token generated by
- * gss_init_sec_context() to be sent to the acceptor
- * 'context' is a pointer to a valid gss_ctx_id_t
- * (which may have the value GSS_C_NO_CONTEXT)
- *
- * Returns:
- * ISC_R_SUCCESS msg was successfully updated to include the
- * query to be sent
- * other an error occurred while building the message
- * *err_message optional error message
- */
-
-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 *context, dns_name_t *principal,
- isc_mem_t *mctx);
-/*
- * Accepts a GSS context.
- *
- * Requires:
- * 'mctx' is a valid memory context
- * 'cred' is the acceptor's valid GSS credential handle
- * 'intoken' is a token received from the initiator
- * 'outtoken' is a pointer a buffer pointer used to return the token
- * 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 gss_ctx_id_t. Subsequent calls
- * should pass in the handle generated on the first call.
- * Call dst_gssapi_releasecred to delete the context and free
- * the memory.
- *
- * Requires:
- * 'outtoken' to != NULL && *outtoken == 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_result_t
-dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx);
-/*
- * Destroys a GSS context. This function deletes the context from the GSS
- * provider and then frees the memory used by the context pointer.
- *
- * Requires:
- * 'mctx' is a valid memory context
- * 'context' is a valid GSS context
- *
- * Returns:
- * ISC_R_SUCCESS
- */
-
-
-void
-gss_log(int level, const char *fmt, ...)
-ISC_FORMAT_PRINTF(2, 3);
-/*
- * Logging function for GSS.
- *
- * Requires
- * 'level' is the log level to be used, as an integer
- * 'fmt' is a printf format specifier
- */
-
-char *
-gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
- char *buf, size_t buflen);
-/*
- * Render a GSS major status/minor status pair into a string
- *
- * Requires:
- * 'major' is a GSS major status code
- * 'minor' is a GSS minor status code
- *
- * Returns:
- * A string containing the text representation of the error codes.
- * Users should copy the string if they wish to keep it.
- */
-
-isc_boolean_t
-dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
- dns_name_t *realm);
-/*
- * Compare a "signer" (in the format of a Kerberos-format Kerberos5
- * principal: host/example.com@EXAMPLE.COM) to the realm name stored
- * in "name" (which represents the realm name).
- *
- */
-
-isc_boolean_t
-dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
- dns_name_t *realm);
-/*
- * Compare a "signer" (in the format of a Kerberos-format Kerberos5
- * principal: host/example.com@EXAMPLE.COM) to the realm name stored
- * in "name" (which represents the realm name).
- *
- */
-
-ISC_LANG_ENDDECLS
-
-#endif /* DST_GSSAPI_H */
diff --git a/usr.sbin/bind/lib/dns/spnego.c b/usr.sbin/bind/lib/dns/spnego.c
deleted file mode 100644
index d4740ee10fd..00000000000
--- a/usr.sbin/bind/lib/dns/spnego.c
+++ /dev/null
@@ -1,1828 +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.
- */
-
-/*! \file
- * \brief
- * Portable SPNEGO implementation.
- *
- * This is part of a portable implementation of the SPNEGO protocol
- * (RFCs 2478 and 4178). This implementation uses the RFC 4178 ASN.1
- * module but is not a full implementation of the RFC 4178 protocol;
- * at the moment, we only support GSS-TSIG with Kerberos
- * authentication, so we only need enough of the SPNEGO protocol to
- * support that.
- *
- * The files that make up this portable SPNEGO implementation are:
- * \li spnego.c (this file)
- * \li spnego.h (API SPNEGO exports to the rest of lib/dns)
- * \li spnego.asn1 (SPNEGO ASN.1 module)
- * \li spnego_asn1.c (routines generated from spngo.asn1)
- * \li spnego_asn1.pl (perl script to generate spnego_asn1.c)
- *
- * Everything but the functions exported in spnego.h is static, to
- * avoid possible conflicts with other libraries (particularly Heimdal,
- * since much of this code comes from Heimdal by way of mod_auth_kerb).
- *
- * spnego_asn1.c is shipped as part of lib/dns because generating it
- * requires both Perl and the Heimdal ASN.1 compiler. See
- * spnego_asn1.pl for further details. We've tried to eliminate all
- * compiler warnings from the generated code, but you may see a few
- * when using a compiler version we haven't tested yet.
- */
-
-/*
- * Portions of this code were derived from mod_auth_kerb and Heimdal.
- * These packages are available from:
- *
- * http://modauthkerb.sourceforge.net/
- * http://www.pdc.kth.se/heimdal/
- *
- * and were released under the following licenses:
- *
- * ----------------------------------------------------------------
- *
- * Copyright (c) 2004 Masarykova universita
- * (Masaryk University, Brno, Czech Republic)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the University nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * ----------------------------------------------------------------
- *
- * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * XXXSRA We should omit this file entirely in Makefile.in via autoconf,
- * but this will keep it from generating errors until that's written.
- */
-
-#ifdef GSSAPI
-
-/*
- * XXXSRA Some of the following files are almost certainly unnecessary,
- * but using this list (borrowed from gssapictx.c) gets rid of some
- * whacky compilation errors when building with MSVC and should be
- * harmless in any case.
- */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include <isc/buffer.h>
-#include <isc/dir.h>
-#include <isc/entropy.h>
-#include <isc/lex.h>
-#include <isc/mem.h>
-#include <isc/once.h>
-#include <isc/random.h>
-#include <isc/safe.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"
-
-/*
- * The API we export
- */
-#include "spnego.h"
-
-/* asn1_err.h */
-/* Generated from ../../../lib/asn1/asn1_err.et */
-
-#ifndef ERROR_TABLE_BASE_asn1
-/* these may be brought in already via gssapi_krb5.h */
-typedef enum asn1_error_number {
- ASN1_BAD_TIMEFORMAT = 1859794432,
- ASN1_MISSING_FIELD = 1859794433,
- ASN1_MISPLACED_FIELD = 1859794434,
- ASN1_TYPE_MISMATCH = 1859794435,
- ASN1_OVERFLOW = 1859794436,
- ASN1_OVERRUN = 1859794437,
- ASN1_BAD_ID = 1859794438,
- ASN1_BAD_LENGTH = 1859794439,
- ASN1_BAD_FORMAT = 1859794440,
- ASN1_PARSE_ERROR = 1859794441
-} asn1_error_number;
-
-#define ERROR_TABLE_BASE_asn1 1859794432
-#endif
-
-#define __asn1_common_definitions__
-
-typedef struct octet_string {
- size_t length;
- void *data;
-} octet_string;
-
-typedef char *general_string;
-
-typedef char *utf8_string;
-
-typedef struct oid {
- size_t length;
- unsigned *components;
-} oid;
-
-/* der.h */
-
-typedef enum {
- ASN1_C_UNIV = 0, ASN1_C_APPL = 1,
- ASN1_C_CONTEXT = 2, ASN1_C_PRIVATE = 3
-} Der_class;
-
-typedef enum {
- PRIM = 0, CONS = 1
-} Der_type;
-
-/* Universal tags */
-
-enum {
- UT_Boolean = 1,
- UT_Integer = 2,
- UT_BitString = 3,
- UT_OctetString = 4,
- UT_Null = 5,
- UT_OID = 6,
- UT_Enumerated = 10,
- UT_Sequence = 16,
- UT_Set = 17,
- UT_PrintableString = 19,
- UT_IA5String = 22,
- UT_UTCTime = 23,
- UT_GeneralizedTime = 24,
- UT_VisibleString = 26,
- UT_GeneralString = 27
-};
-
-#define ASN1_INDEFINITE 0xdce0deed
-
-static int
-der_get_length(const unsigned char *p, size_t len,
- size_t * val, size_t * size);
-
-static int
-der_get_octet_string(const unsigned char *p, size_t len,
- octet_string * data, size_t * size);
-static int
-der_get_oid(const unsigned char *p, size_t len,
- oid * data, size_t * size);
-static int
-der_get_tag(const unsigned char *p, size_t len,
- Der_class * xclass, Der_type * type,
- int *tag, size_t * size);
-
-static int
-der_match_tag(const unsigned char *p, size_t len,
- Der_class xclass, Der_type type,
- int tag, size_t * size);
-static int
-der_match_tag_and_length(const unsigned char *p, size_t len,
- Der_class xclass, Der_type type, int tag,
- size_t * length_ret, size_t * size);
-
-static int
-decode_oid(const unsigned char *p, size_t len,
- oid * k, size_t * size);
-
-static int
-decode_enumerated(const unsigned char *p, size_t len, void *num, size_t *size);
-
-static int
-decode_octet_string(const unsigned char *, size_t, octet_string *, size_t *);
-
-static int
-der_put_int(unsigned char *p, size_t len, int val, size_t *);
-
-static int
-der_put_length(unsigned char *p, size_t len, size_t val, size_t *);
-
-static int
-der_put_octet_string(unsigned char *p, size_t len,
- const octet_string * data, size_t *);
-static int
-der_put_oid(unsigned char *p, size_t len,
- const oid * data, size_t * size);
-static int
-der_put_tag(unsigned char *p, size_t len, Der_class xclass, Der_type type,
- int tag, size_t *);
-static int
-der_put_length_and_tag(unsigned char *, size_t, size_t,
- Der_class, Der_type, int, size_t *);
-
-static int
-encode_enumerated(unsigned char *p, size_t len, const void *data, size_t *);
-
-static int
-encode_octet_string(unsigned char *p, size_t len,
- const octet_string * k, size_t *);
-static int
-encode_oid(unsigned char *p, size_t len,
- const oid * k, size_t *);
-
-static void
-free_octet_string(octet_string * k);
-
-static void
-free_oid (oid * k);
-
-static size_t
-length_len(size_t len);
-
-static int
-fix_dce(size_t reallen, size_t * len);
-
-/*
- * Include stuff generated by the ASN.1 compiler.
- */
-
-#include "spnego_asn1.c"
-
-/*
- * Force the oid arrays to be isc_uint64_t aligned to silence warnings
- * about the arrays not being properly aligned for (void *).
- */
-typedef union { unsigned char b[8]; isc_uint64_t _align; } aligned8;
-typedef union { unsigned char b[16]; isc_uint64_t _align[2]; } aligned16;
-
-static aligned16 gss_krb5_mech_oid_bytes = {
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 }
-};
-
-static gss_OID_desc gss_krb5_mech_oid_desc = {
- 9, gss_krb5_mech_oid_bytes.b
-};
-
-static gss_OID GSS_KRB5_MECH = &gss_krb5_mech_oid_desc;
-
-static aligned16 gss_mskrb5_mech_oid_bytes = {
- { 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02 }
-};
-
-static gss_OID_desc gss_mskrb5_mech_oid_desc = {
- 9, gss_mskrb5_mech_oid_bytes.b
-};
-
-static gss_OID GSS_MSKRB5_MECH = &gss_mskrb5_mech_oid_desc;
-
-static aligned8 gss_spnego_mech_oid_bytes = {
- { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02 }
-};
-
-static gss_OID_desc gss_spnego_mech_oid_desc = {
- 6, gss_spnego_mech_oid_bytes.b
-};
-
-static gss_OID GSS_SPNEGO_MECH = &gss_spnego_mech_oid_desc;
-
-/* spnegokrb5_locl.h */
-
-static OM_uint32
-gssapi_spnego_encapsulate(OM_uint32 *,
- unsigned char *,
- size_t,
- gss_buffer_t,
- const gss_OID);
-
-static OM_uint32
-gssapi_spnego_decapsulate(OM_uint32 *,
- gss_buffer_t,
- unsigned char **,
- size_t *,
- const gss_OID);
-
-/* mod_auth_kerb.c */
-
-static int
-cmp_gss_type(gss_buffer_t token, gss_OID gssoid)
-{
- unsigned char *p;
- size_t len;
-
- if (token->length == 0U)
- return (GSS_S_DEFECTIVE_TOKEN);
-
- p = token->value;
- if (*p++ != 0x60)
- return (GSS_S_DEFECTIVE_TOKEN);
- len = *p++;
- if (len & 0x80) {
- if ((len & 0x7f) > 4U)
- return (GSS_S_DEFECTIVE_TOKEN);
- p += len & 0x7f;
- }
- if (*p++ != 0x06)
- return (GSS_S_DEFECTIVE_TOKEN);
-
- if (((OM_uint32) *p++) != gssoid->length)
- return (GSS_S_DEFECTIVE_TOKEN);
-
- return (isc_safe_memcompare(p, gssoid->elements, gssoid->length));
-}
-
-/* accept_sec_context.c */
-/*
- * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
- * based on Heimdal code)
- */
-
-static OM_uint32
-code_NegTokenArg(OM_uint32 * minor_status,
- const NegTokenResp * resp,
- unsigned char **outbuf,
- size_t * outbuf_size)
-{
- OM_uint32 ret;
- u_char *buf;
- size_t buf_size, buf_len = 0;
-
- buf_size = 1024;
- buf = malloc(buf_size);
- if (buf == NULL) {
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- do {
- ret = encode_NegTokenResp(buf + buf_size - 1,
- buf_size,
- resp, &buf_len);
- if (ret == 0) {
- size_t tmp;
-
- ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
- buf_size - buf_len,
- buf_len,
- ASN1_C_CONTEXT,
- CONS,
- 1,
- &tmp);
- if (ret == 0)
- buf_len += tmp;
- }
- if (ret) {
- if (ret == ASN1_OVERFLOW) {
- u_char *tmp;
-
- buf_size *= 2;
- tmp = realloc(buf, buf_size);
- if (tmp == NULL) {
- *minor_status = ENOMEM;
- free(buf);
- return (GSS_S_FAILURE);
- }
- buf = tmp;
- } else {
- *minor_status = ret;
- free(buf);
- return (GSS_S_FAILURE);
- }
- }
- } while (ret == ASN1_OVERFLOW);
-
- *outbuf = malloc(buf_len);
- if (*outbuf == NULL) {
- *minor_status = ENOMEM;
- free(buf);
- return (GSS_S_FAILURE);
- }
- memmove(*outbuf, buf + buf_size - buf_len, buf_len);
- *outbuf_size = buf_len;
-
- free(buf);
-
- return (GSS_S_COMPLETE);
-}
-
-static OM_uint32
-send_reject(OM_uint32 * minor_status,
- gss_buffer_t output_token)
-{
- NegTokenResp resp;
- OM_uint32 ret;
-
- resp.negState = malloc(sizeof(*resp.negState));
- if (resp.negState == NULL) {
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- *(resp.negState) = reject;
-
- resp.supportedMech = NULL;
- resp.responseToken = NULL;
- resp.mechListMIC = NULL;
-
- ret = code_NegTokenArg(minor_status, &resp,
- (unsigned char **)&output_token->value,
- &output_token->length);
- free_NegTokenResp(&resp);
- if (ret)
- return (ret);
-
- return (GSS_S_BAD_MECH);
-}
-
-static OM_uint32
-send_accept(OM_uint32 * minor_status,
- gss_buffer_t output_token,
- gss_buffer_t mech_token,
- const gss_OID pref)
-{
- NegTokenResp resp;
- OM_uint32 ret;
-
- memset(&resp, 0, sizeof(resp));
- resp.negState = malloc(sizeof(*resp.negState));
- if (resp.negState == NULL) {
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- *(resp.negState) = accept_completed;
-
- resp.supportedMech = malloc(sizeof(*resp.supportedMech));
- if (resp.supportedMech == NULL) {
- free_NegTokenResp(&resp);
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- ret = der_get_oid(pref->elements,
- pref->length,
- resp.supportedMech,
- NULL);
- if (ret) {
- free_NegTokenResp(&resp);
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- if (mech_token != NULL && mech_token->length != 0U) {
- resp.responseToken = malloc(sizeof(*resp.responseToken));
- if (resp.responseToken == NULL) {
- free_NegTokenResp(&resp);
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- resp.responseToken->length = mech_token->length;
- resp.responseToken->data = mech_token->value;
- }
-
- ret = code_NegTokenArg(minor_status, &resp,
- (unsigned char **)&output_token->value,
- &output_token->length);
- if (resp.responseToken != NULL) {
- free(resp.responseToken);
- resp.responseToken = NULL;
- }
- free_NegTokenResp(&resp);
- if (ret)
- return (ret);
-
- return (GSS_S_COMPLETE);
-}
-
-OM_uint32
-gss_accept_sec_context_spnego(OM_uint32 *minor_status,
- gss_ctx_id_t *context_handle,
- const gss_cred_id_t acceptor_cred_handle,
- const gss_buffer_t input_token_buffer,
- const gss_channel_bindings_t input_chan_bindings,
- gss_name_t *src_name,
- gss_OID *mech_type,
- gss_buffer_t output_token,
- OM_uint32 *ret_flags,
- OM_uint32 *time_rec,
- gss_cred_id_t *delegated_cred_handle)
-{
- NegTokenInit init_token;
- OM_uint32 major_status = GSS_S_COMPLETE;
- OM_uint32 minor_status2;
- gss_buffer_desc ibuf, obuf;
- gss_buffer_t ot = NULL;
- gss_OID pref = GSS_KRB5_MECH;
- unsigned char *buf;
- size_t buf_size;
- size_t len, taglen, ni_len;
- int found = 0;
- int ret;
- unsigned i;
-
- /*
- * Before doing anything else, see whether this is a SPNEGO
- * PDU. If not, dispatch to the GSSAPI library and get out.
- */
-
- if (cmp_gss_type(input_token_buffer, GSS_SPNEGO_MECH))
- return (gss_accept_sec_context(minor_status,
- context_handle,
- acceptor_cred_handle,
- input_token_buffer,
- input_chan_bindings,
- src_name,
- mech_type,
- output_token,
- ret_flags,
- time_rec,
- delegated_cred_handle));
-
- /*
- * If we get here, it's SPNEGO.
- */
-
- memset(&init_token, 0, sizeof(init_token));
-
- ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
- &buf, &buf_size, GSS_SPNEGO_MECH);
- if (ret)
- return (ret);
-
- ret = der_match_tag_and_length(buf, buf_size, ASN1_C_CONTEXT, CONS,
- 0, &len, &taglen);
- if (ret)
- return (ret);
-
- ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
- if (ret) {
- *minor_status = EINVAL; /* XXX */
- return (GSS_S_DEFECTIVE_TOKEN);
- }
-
- for (i = 0; !found && i < init_token.mechTypes.len; ++i) {
- unsigned char mechbuf[17];
- size_t mech_len;
-
- ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1,
- sizeof(mechbuf),
- &init_token.mechTypes.val[i],
- &mech_len);
- if (ret) {
- free_NegTokenInit(&init_token);
- return (GSS_S_DEFECTIVE_TOKEN);
- }
- if (mech_len == GSS_KRB5_MECH->length &&
- isc_safe_memequal(GSS_KRB5_MECH->elements,
- mechbuf + sizeof(mechbuf) - mech_len,
- mech_len))
- {
- found = 1;
- break;
- }
- if (mech_len == GSS_MSKRB5_MECH->length &&
- isc_safe_memequal(GSS_MSKRB5_MECH->elements,
- mechbuf + sizeof(mechbuf) - mech_len,
- mech_len))
- {
- found = 1;
- if (i == 0)
- pref = GSS_MSKRB5_MECH;
- break;
- }
- }
-
- if (!found) {
- free_NegTokenInit(&init_token);
- return (send_reject(minor_status, output_token));
- }
-
- if (i == 0 && init_token.mechToken != NULL) {
- ibuf.length = init_token.mechToken->length;
- ibuf.value = init_token.mechToken->data;
-
- major_status = gss_accept_sec_context(minor_status,
- context_handle,
- acceptor_cred_handle,
- &ibuf,
- input_chan_bindings,
- src_name,
- mech_type,
- &obuf,
- ret_flags,
- time_rec,
- delegated_cred_handle);
- if (GSS_ERROR(major_status)) {
- free_NegTokenInit(&init_token);
- send_reject(&minor_status2, output_token);
- return (major_status);
- }
- ot = &obuf;
- }
- ret = send_accept(&minor_status2, output_token, ot, pref);
- free_NegTokenInit(&init_token);
- if (ot != NULL && ot->length != 0U)
- gss_release_buffer(&minor_status2, ot);
-
- return (ret != GSS_S_COMPLETE ? (OM_uint32) ret : major_status);
-}
-
-/* decapsulate.c */
-
-static OM_uint32
-gssapi_verify_mech_header(u_char ** str,
- size_t total_len,
- const gss_OID mech)
-{
- size_t len, len_len, mech_len, foo;
- int e;
- u_char *p = *str;
-
- if (total_len < 1U)
- return (GSS_S_DEFECTIVE_TOKEN);
- if (*p++ != 0x60)
- return (GSS_S_DEFECTIVE_TOKEN);
- e = der_get_length(p, total_len - 1, &len, &len_len);
- if (e || 1 + len_len + len != total_len)
- return (GSS_S_DEFECTIVE_TOKEN);
- p += len_len;
- if (*p++ != 0x06)
- return (GSS_S_DEFECTIVE_TOKEN);
- e = der_get_length(p, total_len - 1 - len_len - 1,
- &mech_len, &foo);
- if (e)
- return (GSS_S_DEFECTIVE_TOKEN);
- p += foo;
- if (mech_len != mech->length)
- return (GSS_S_BAD_MECH);
- if (!isc_safe_memequal(p, mech->elements, mech->length))
- return (GSS_S_BAD_MECH);
- p += mech_len;
- *str = p;
- return (GSS_S_COMPLETE);
-}
-
-/*
- * Remove the GSS-API wrapping from `in_token' giving `buf and buf_size' Does
- * not copy data, so just free `in_token'.
- */
-
-static OM_uint32
-gssapi_spnego_decapsulate(OM_uint32 *minor_status,
- gss_buffer_t input_token_buffer,
- unsigned char **buf,
- size_t *buf_len,
- const gss_OID mech)
-{
- u_char *p;
- OM_uint32 ret;
-
- p = input_token_buffer->value;
- ret = gssapi_verify_mech_header(&p,
- input_token_buffer->length,
- mech);
- if (ret) {
- *minor_status = ret;
- return (GSS_S_FAILURE);
- }
- *buf_len = input_token_buffer->length -
- (p - (u_char *) input_token_buffer->value);
- *buf = p;
- return (GSS_S_COMPLETE);
-}
-
-/* der_free.c */
-
-static void
-free_octet_string(octet_string *k)
-{
- free(k->data);
- k->data = NULL;
-}
-
-static void
-free_oid(oid *k)
-{
- free(k->components);
- k->components = NULL;
-}
-
-/* der_get.c */
-
-/*
- * All decoding functions take a pointer `p' to first position in which to
- * read, from the left, `len' which means the maximum number of characters we
- * are able to read, `ret' were the value will be returned and `size' where
- * the number of used bytes is stored. Either 0 or an error code is returned.
- */
-
-static int
-der_get_unsigned(const unsigned char *p, size_t len,
- unsigned *ret, size_t *size)
-{
- unsigned val = 0;
- size_t oldlen = len;
-
- while (len--)
- val = val * 256 + *p++;
- *ret = val;
- if (size)
- *size = oldlen;
- return (0);
-}
-
-static int
-der_get_int(const unsigned char *p, size_t len,
- int *ret, size_t *size)
-{
- int val = 0;
- size_t oldlen = len;
-
- if (len > 0U) {
- val = (signed char)*p++;
- while (--len)
- val = val * 256 + *p++;
- }
- *ret = val;
- if (size)
- *size = oldlen;
- return (0);
-}
-
-static int
-der_get_length(const unsigned char *p, size_t len,
- size_t *val, size_t *size)
-{
- size_t v;
-
- if (len <= 0U)
- return (ASN1_OVERRUN);
- --len;
- v = *p++;
- if (v < 128U) {
- *val = v;
- if (size)
- *size = 1;
- } else {
- int e;
- size_t l;
- unsigned tmp;
-
- if (v == 0x80U) {
- *val = ASN1_INDEFINITE;
- if (size)
- *size = 1;
- return (0);
- }
- v &= 0x7F;
- if (len < v)
- return (ASN1_OVERRUN);
- e = der_get_unsigned(p, v, &tmp, &l);
- if (e)
- return (e);
- *val = tmp;
- if (size)
- *size = l + 1;
- }
- return (0);
-}
-
-static int
-der_get_octet_string(const unsigned char *p, size_t len,
- octet_string *data, size_t *size)
-{
- data->length = len;
- if (len != 0U) {
- data->data = malloc(len);
- if (data->data == NULL)
- return (ENOMEM);
- memmove(data->data, p, len);
- } else
- data->data = NULL;
- if (size)
- *size = len;
- return (0);
-}
-
-static int
-der_get_oid(const unsigned char *p, size_t len, oid *data, size_t *size) {
- int n;
- size_t oldlen = len;
-
- data->components = NULL;
- data->length = 0;
- if (len < 1U) {
- return (ASN1_OVERRUN);
- }
-
- data->components = malloc(len * sizeof(*data->components));
- if (data->components == NULL) {
- return (ENOMEM);
- }
- data->components[0] = (*p) / 40;
- data->components[1] = (*p) % 40;
- --len;
- ++p;
- for (n = 2; len > 0U; ++n) {
- unsigned u = 0;
-
- do {
- --len;
- u = u * 128 + (*p++ % 128);
- } while (len > 0U && p[-1] & 0x80);
- data->components[n] = u;
- }
- if (p[-1] & 0x80) {
- free_oid(data);
- return (ASN1_OVERRUN);
- }
- data->length = n;
- if (size) {
- *size = oldlen;
- }
- return (0);
-}
-
-static int
-der_get_tag(const unsigned char *p, size_t len,
- Der_class *xclass, Der_type *type,
- int *tag, size_t *size)
-{
- if (len < 1U)
- return (ASN1_OVERRUN);
- *xclass = (Der_class) (((*p) >> 6) & 0x03);
- *type = (Der_type) (((*p) >> 5) & 0x01);
- *tag = (*p) & 0x1F;
- if (size)
- *size = 1;
- return (0);
-}
-
-static int
-der_match_tag(const unsigned char *p, size_t len,
- Der_class xclass, Der_type type,
- int tag, size_t *size)
-{
- size_t l;
- Der_class thisclass;
- Der_type thistype;
- int thistag;
- int e;
-
- e = der_get_tag(p, len, &thisclass, &thistype, &thistag, &l);
- if (e)
- return (e);
- if (xclass != thisclass || type != thistype)
- return (ASN1_BAD_ID);
- if (tag > thistag)
- return (ASN1_MISPLACED_FIELD);
- if (tag < thistag)
- return (ASN1_MISSING_FIELD);
- if (size)
- *size = l;
- return (0);
-}
-
-static int
-der_match_tag_and_length(const unsigned char *p, size_t len,
- Der_class xclass, Der_type type, int tag,
- size_t *length_ret, size_t *size)
-{
- size_t l, ret = 0;
- int e;
-
- e = der_match_tag(p, len, xclass, type, tag, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
- e = der_get_length(p, len, length_ret, &l);
- if (e)
- return (e);
- /* p += l; */
- len -= l;
- POST(len);
- ret += l;
- if (size)
- *size = ret;
- return (0);
-}
-
-static int
-decode_enumerated(const unsigned char *p, size_t len, void *num, size_t *size)
-{
- size_t ret = 0;
- size_t l, reallen;
- int e;
-
- e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
- e = der_get_length(p, len, &reallen, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
- e = der_get_int(p, reallen, num, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- if (size)
- *size = ret;
- return (0);
-}
-
-static int
-decode_octet_string(const unsigned char *p, size_t len,
- octet_string *k, size_t *size)
-{
- size_t ret = 0;
- size_t l;
- int e;
- size_t slen;
-
- k->data = NULL;
- k->length = 0;
-
- e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
-
- e = der_get_length(p, len, &slen, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
- if (len < slen)
- return (ASN1_OVERRUN);
-
- e = der_get_octet_string(p, slen, k, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- if (size)
- *size = ret;
- return (0);
-}
-
-static int
-decode_oid(const unsigned char *p, size_t len,
- oid *k, size_t *size)
-{
- size_t ret = 0;
- size_t l;
- int e;
- size_t slen;
-
- e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
-
- e = der_get_length(p, len, &slen, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- ret += l;
- if (len < slen)
- return (ASN1_OVERRUN);
-
- e = der_get_oid(p, slen, k, &l);
- if (e)
- return (e);
- p += l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- if (size)
- *size = ret;
- return (0);
-}
-
-static int
-fix_dce(size_t reallen, size_t *len)
-{
- if (reallen == ASN1_INDEFINITE)
- return (1);
- if (*len < reallen)
- return (-1);
- *len = reallen;
- return (0);
-}
-
-/* der_length.c */
-
-static size_t
-len_unsigned(unsigned val)
-{
- size_t ret = 0;
-
- do {
- ++ret;
- val /= 256;
- } while (val);
- return (ret);
-}
-
-static size_t
-length_len(size_t len)
-{
- if (len < 128U)
- return (1);
- else
- return (len_unsigned((unsigned int)len) + 1);
-}
-
-
-/* der_put.c */
-
-/*
- * All encoding functions take a pointer `p' to first position in which to
- * write, from the right, `len' which means the maximum number of characters
- * we are able to write. The function returns the number of characters
- * written in `size' (if non-NULL). The return value is 0 or an error.
- */
-
-static int
-der_put_unsigned(unsigned char *p, size_t len, unsigned val, size_t *size)
-{
- unsigned char *base = p;
-
- if (val) {
- while (len > 0U && val) {
- *p-- = val % 256;
- val /= 256;
- --len;
- }
- if (val != 0)
- return (ASN1_OVERFLOW);
- else {
- *size = base - p;
- return (0);
- }
- } else if (len < 1U)
- return (ASN1_OVERFLOW);
- else {
- *p = 0;
- *size = 1;
- return (0);
- }
-}
-
-static int
-der_put_int(unsigned char *p, size_t len, int val, size_t *size)
-{
- unsigned char *base = p;
-
- if (val >= 0) {
- do {
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = val % 256;
- len--;
- val /= 256;
- } while (val);
- if (p[1] >= 128) {
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = 0;
- len--;
- POST(len);
- }
- } else {
- val = ~val;
- do {
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = ~(val % 256);
- len--;
- val /= 256;
- } while (val);
- if (p[1] < 128) {
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = 0xff;
- len--;
- POST(len);
- }
- }
- *size = base - p;
- return (0);
-}
-
-static int
-der_put_length(unsigned char *p, size_t len, size_t val, size_t *size)
-{
- if (len < 1U)
- return (ASN1_OVERFLOW);
- if (val < 128U) {
- *p = (unsigned char)val;
- *size = 1;
- return (0);
- } else {
- size_t l;
- int e;
-
- e = der_put_unsigned(p, len - 1, (unsigned int)val, &l);
- if (e)
- return (e);
- p -= l;
- *p = 0x80 | (unsigned char)l;
- *size = l + 1;
- return (0);
- }
-}
-
-static int
-der_put_octet_string(unsigned char *p, size_t len,
- const octet_string *data, size_t *size)
-{
- if (len < data->length)
- return (ASN1_OVERFLOW);
- p -= data->length;
- len -= data->length;
- POST(len);
- memmove(p + 1, data->data, data->length);
- *size = data->length;
- return (0);
-}
-
-static int
-der_put_oid(unsigned char *p, size_t len,
- const oid *data, size_t *size)
-{
- unsigned char *base = p;
- size_t n;
-
- for (n = data->length; n >= 3u; --n) {
- unsigned u = data->components[n - 1];
-
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = u % 128;
- u /= 128;
- --len;
- while (u > 0) {
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = 128 + u % 128;
- u /= 128;
- --len;
- }
- }
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p-- = 40 * data->components[0] + data->components[1];
- *size = base - p;
- return (0);
-}
-
-static int
-der_put_tag(unsigned char *p, size_t len, Der_class xclass, Der_type type,
- int tag, size_t *size)
-{
- if (len < 1U)
- return (ASN1_OVERFLOW);
- *p = (xclass << 6) | (type << 5) | tag; /* XXX */
- *size = 1;
- return (0);
-}
-
-static int
-der_put_length_and_tag(unsigned char *p, size_t len, size_t len_val,
- Der_class xclass, Der_type type, int tag, size_t *size)
-{
- size_t ret = 0;
- size_t l;
- int e;
-
- e = der_put_length(p, len, len_val, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- ret += l;
- e = der_put_tag(p, len, xclass, type, tag, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- *size = ret;
- return (0);
-}
-
-static int
-encode_enumerated(unsigned char *p, size_t len, const void *data, size_t *size)
-{
- unsigned num = *(const unsigned *)data;
- size_t ret = 0;
- size_t l;
- int e;
-
- e = der_put_int(p, len, num, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- ret += l;
- e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- *size = ret;
- return (0);
-}
-
-static int
-encode_octet_string(unsigned char *p, size_t len,
- const octet_string *k, size_t *size)
-{
- size_t ret = 0;
- size_t l;
- int e;
-
- e = der_put_octet_string(p, len, k, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- ret += l;
- e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- *size = ret;
- return (0);
-}
-
-static int
-encode_oid(unsigned char *p, size_t len,
- const oid *k, size_t *size)
-{
- size_t ret = 0;
- size_t l;
- int e;
-
- e = der_put_oid(p, len, k, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- ret += l;
- e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
- if (e)
- return (e);
- p -= l;
- len -= l;
- POST(p); POST(len);
- ret += l;
- *size = ret;
- return (0);
-}
-
-
-/* encapsulate.c */
-
-static void
-gssapi_encap_length(size_t data_len,
- size_t *len,
- size_t *total_len,
- const gss_OID mech)
-{
- size_t len_len;
-
- *len = 1 + 1 + mech->length + data_len;
-
- len_len = length_len(*len);
-
- *total_len = 1 + len_len + *len;
-}
-
-static u_char *
-gssapi_mech_make_header(u_char *p,
- size_t len,
- const gss_OID mech)
-{
- int e;
- size_t len_len, foo;
-
- *p++ = 0x60;
- len_len = length_len(len);
- e = der_put_length(p + len_len - 1, len_len, len, &foo);
- if (e || foo != len_len)
- return (NULL);
- p += len_len;
- *p++ = 0x06;
- *p++ = mech->length;
- memmove(p, mech->elements, mech->length);
- p += mech->length;
- return (p);
-}
-
-/*
- * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
- */
-
-static OM_uint32
-gssapi_spnego_encapsulate(OM_uint32 * minor_status,
- unsigned char *buf,
- size_t buf_size,
- gss_buffer_t output_token,
- const gss_OID mech)
-{
- size_t len, outer_len;
- u_char *p;
-
- gssapi_encap_length(buf_size, &len, &outer_len, mech);
-
- output_token->length = outer_len;
- output_token->value = malloc(outer_len);
- if (output_token->value == NULL) {
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
- p = gssapi_mech_make_header(output_token->value, len, mech);
- if (p == NULL) {
- if (output_token->length != 0U)
- gss_release_buffer(minor_status, output_token);
- return (GSS_S_FAILURE);
- }
- memmove(p, buf, buf_size);
- return (GSS_S_COMPLETE);
-}
-
-/* init_sec_context.c */
-/*
- * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
- * based on Heimdal code)
- */
-
-static int
-add_mech(MechTypeList * mech_list, gss_OID mech)
-{
- MechType *tmp;
- int ret;
-
- tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
- if (tmp == NULL)
- return (ENOMEM);
- mech_list->val = tmp;
-
- ret = der_get_oid(mech->elements, mech->length,
- &mech_list->val[mech_list->len], NULL);
- if (ret)
- return (ret);
-
- mech_list->len++;
- return (0);
-}
-
-/*
- * return the length of the mechanism in token or -1
- * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
- */
-
-static ssize_t
-gssapi_krb5_get_mech(const u_char *ptr,
- size_t total_len,
- const u_char **mech_ret)
-{
- size_t len, len_len, mech_len, foo;
- const u_char *p = ptr;
- int e;
-
- if (total_len < 1U)
- return (-1);
- if (*p++ != 0x60)
- return (-1);
- e = der_get_length (p, total_len - 1, &len, &len_len);
- if (e || 1 + len_len + len != total_len)
- return (-1);
- p += len_len;
- if (*p++ != 0x06)
- return (-1);
- e = der_get_length (p, total_len - 1 - len_len - 1,
- &mech_len, &foo);
- if (e)
- return (-1);
- p += foo;
- *mech_ret = p;
- return (mech_len);
-}
-
-static OM_uint32
-spnego_initial(OM_uint32 *minor_status,
- const gss_cred_id_t initiator_cred_handle,
- gss_ctx_id_t *context_handle,
- const gss_name_t target_name,
- const gss_OID mech_type,
- OM_uint32 req_flags,
- OM_uint32 time_req,
- const gss_channel_bindings_t input_chan_bindings,
- const gss_buffer_t input_token,
- gss_OID *actual_mech_type,
- gss_buffer_t output_token,
- OM_uint32 *ret_flags,
- OM_uint32 *time_rec)
-{
- NegTokenInit token_init;
- OM_uint32 major_status, minor_status2;
- gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
- unsigned char *buf = NULL;
- size_t buf_size;
- size_t len;
- int ret;
-
- (void)mech_type;
-
- memset(&token_init, 0, sizeof(token_init));
-
- ret = add_mech(&token_init.mechTypes, GSS_KRB5_MECH);
- if (ret) {
- *minor_status = ret;
- ret = GSS_S_FAILURE;
- goto end;
- }
-
- major_status = gss_init_sec_context(minor_status,
- initiator_cred_handle,
- context_handle,
- target_name,
- GSS_KRB5_MECH,
- req_flags,
- time_req,
- input_chan_bindings,
- input_token,
- actual_mech_type,
- &krb5_output_token,
- ret_flags,
- time_rec);
- if (GSS_ERROR(major_status)) {
- ret = major_status;
- goto end;
- }
- if (krb5_output_token.length > 0U) {
- token_init.mechToken = malloc(sizeof(*token_init.mechToken));
- if (token_init.mechToken == NULL) {
- *minor_status = ENOMEM;
- ret = GSS_S_FAILURE;
- goto end;
- }
- token_init.mechToken->data = krb5_output_token.value;
- token_init.mechToken->length = krb5_output_token.length;
- }
- /*
- * The MS implementation of SPNEGO seems to not like the mechListMIC
- * field, so we omit it (it's optional anyway)
- */
-
- buf_size = 1024;
- buf = malloc(buf_size);
- if (buf == NULL) {
- *minor_status = ENOMEM;
- ret = GSS_S_FAILURE;
- goto end;
- }
-
- do {
- ret = encode_NegTokenInit(buf + buf_size - 1,
- buf_size,
- &token_init, &len);
- if (ret == 0) {
- size_t tmp;
-
- ret = der_put_length_and_tag(buf + buf_size - len - 1,
- buf_size - len,
- len,
- ASN1_C_CONTEXT,
- CONS,
- 0,
- &tmp);
- if (ret == 0)
- len += tmp;
- }
- if (ret) {
- if (ret == ASN1_OVERFLOW) {
- u_char *tmp;
-
- buf_size *= 2;
- tmp = realloc(buf, buf_size);
- if (tmp == NULL) {
- *minor_status = ENOMEM;
- ret = GSS_S_FAILURE;
- goto end;
- }
- buf = tmp;
- } else {
- *minor_status = ret;
- ret = GSS_S_FAILURE;
- goto end;
- }
- }
- } while (ret == ASN1_OVERFLOW);
-
- ret = gssapi_spnego_encapsulate(minor_status,
- buf + buf_size - len, len,
- output_token, GSS_SPNEGO_MECH);
- if (ret == GSS_S_COMPLETE)
- ret = major_status;
-
-end:
- if (token_init.mechToken != NULL) {
- free(token_init.mechToken);
- token_init.mechToken = NULL;
- }
- free_NegTokenInit(&token_init);
- if (krb5_output_token.length != 0U)
- gss_release_buffer(&minor_status2, &krb5_output_token);
- if (buf)
- free(buf);
-
- return (ret);
-}
-
-static OM_uint32
-spnego_reply(OM_uint32 *minor_status,
- const gss_cred_id_t initiator_cred_handle,
- gss_ctx_id_t *context_handle,
- const gss_name_t target_name,
- const gss_OID mech_type,
- OM_uint32 req_flags,
- OM_uint32 time_req,
- const gss_channel_bindings_t input_chan_bindings,
- const gss_buffer_t input_token,
- gss_OID *actual_mech_type,
- gss_buffer_t output_token,
- OM_uint32 *ret_flags,
- OM_uint32 *time_rec)
-{
- OM_uint32 ret;
- NegTokenResp resp;
- unsigned char *buf;
- size_t buf_size;
- u_char oidbuf[17];
- size_t oidlen;
- gss_buffer_desc sub_token;
- ssize_t mech_len;
- const u_char *p;
- size_t len, taglen;
-
- (void)mech_type;
-
- output_token->length = 0;
- output_token->value = NULL;
-
- /*
- * SPNEGO doesn't include gss wrapping on SubsequentContextToken
- * like the Kerberos 5 mech does. But lets check for it anyway.
- */
-
- mech_len = gssapi_krb5_get_mech(input_token->value,
- input_token->length,
- &p);
-
- if (mech_len < 0) {
- buf = input_token->value;
- buf_size = input_token->length;
- } else if ((size_t)mech_len == GSS_KRB5_MECH->length &&
- isc_safe_memequal(GSS_KRB5_MECH->elements, p, mech_len))
- return (gss_init_sec_context(minor_status,
- initiator_cred_handle,
- context_handle,
- target_name,
- GSS_KRB5_MECH,
- req_flags,
- time_req,
- input_chan_bindings,
- input_token,
- actual_mech_type,
- output_token,
- ret_flags,
- time_rec));
- else if ((size_t)mech_len == GSS_SPNEGO_MECH->length &&
- isc_safe_memequal(GSS_SPNEGO_MECH->elements, p, mech_len)) {
- ret = gssapi_spnego_decapsulate(minor_status,
- input_token,
- &buf,
- &buf_size,
- GSS_SPNEGO_MECH);
- if (ret)
- return (ret);
- } else
- return (GSS_S_BAD_MECH);
-
- ret = der_match_tag_and_length(buf, buf_size,
- ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
- if (ret)
- return (ret);
-
- if(len > buf_size - taglen)
- return (ASN1_OVERRUN);
-
- ret = decode_NegTokenResp(buf + taglen, len, &resp, NULL);
- if (ret) {
- free_NegTokenResp(&resp);
- *minor_status = ENOMEM;
- return (GSS_S_FAILURE);
- }
-
- if (resp.negState == NULL ||
- *(resp.negState) == reject ||
- resp.supportedMech == NULL) {
- free_NegTokenResp(&resp);
- return (GSS_S_BAD_MECH);
- }
-
- ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1,
- sizeof(oidbuf),
- resp.supportedMech,
- &oidlen);
- if (ret || oidlen != GSS_KRB5_MECH->length ||
- !isc_safe_memequal(oidbuf + sizeof(oidbuf) - oidlen,
- GSS_KRB5_MECH->elements, oidlen))
- {
- free_NegTokenResp(&resp);
- return GSS_S_BAD_MECH;
- }
-
- if (resp.responseToken != NULL) {
- sub_token.length = resp.responseToken->length;
- sub_token.value = resp.responseToken->data;
- } else {
- sub_token.length = 0;
- sub_token.value = NULL;
- }
-
- ret = gss_init_sec_context(minor_status,
- initiator_cred_handle,
- context_handle,
- target_name,
- GSS_KRB5_MECH,
- req_flags,
- time_req,
- input_chan_bindings,
- &sub_token,
- actual_mech_type,
- output_token,
- ret_flags,
- time_rec);
- if (ret) {
- free_NegTokenResp(&resp);
- return (ret);
- }
-
- /*
- * XXXSRA I don't think this limited implementation ever needs
- * to check the MIC -- our preferred mechanism (Kerberos)
- * authenticates its own messages and is the only mechanism
- * we'll accept, so if the mechanism negotiation completes
- * successfully, we don't need the MIC. See RFC 4178.
- */
-
- free_NegTokenResp(&resp);
- return (ret);
-}
-
-
-
-OM_uint32
-gss_init_sec_context_spnego(OM_uint32 *minor_status,
- const gss_cred_id_t initiator_cred_handle,
- gss_ctx_id_t *context_handle,
- const gss_name_t target_name,
- const gss_OID mech_type,
- OM_uint32 req_flags,
- OM_uint32 time_req,
- const gss_channel_bindings_t input_chan_bindings,
- const gss_buffer_t input_token,
- gss_OID *actual_mech_type,
- gss_buffer_t output_token,
- OM_uint32 *ret_flags,
- OM_uint32 *time_rec)
-{
- /* Dirty trick to suppress compiler warnings */
-
- /* Figure out whether we're starting over or processing a reply */
-
- if (input_token == GSS_C_NO_BUFFER || input_token->length == 0U)
- return (spnego_initial(minor_status,
- initiator_cred_handle,
- context_handle,
- target_name,
- mech_type,
- req_flags,
- time_req,
- input_chan_bindings,
- input_token,
- actual_mech_type,
- output_token,
- ret_flags,
- time_rec));
- else
- return (spnego_reply(minor_status,
- initiator_cred_handle,
- context_handle,
- target_name,
- mech_type,
- req_flags,
- time_req,
- input_chan_bindings,
- input_token,
- actual_mech_type,
- output_token,
- ret_flags,
- time_rec));
-}
-
-#endif /* GSSAPI */
diff --git a/usr.sbin/bind/lib/dns/spnego.h b/usr.sbin/bind/lib/dns/spnego.h
deleted file mode 100644
index c517be740e4..00000000000
--- a/usr.sbin/bind/lib/dns/spnego.h
+++ /dev/null
@@ -1,71 +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: spnego.h,v 1.2 2019/12/17 01:46:32 sthen Exp $ */
-
-/*! \file
- * \brief
- * Entry points into portable SPNEGO implementation.
- * See spnego.c for information on the SPNEGO implementation itself.
- */
-
-#ifndef _SPNEGO_H_
-#define _SPNEGO_H_
-
-/*%
- * Wrapper for GSSAPI gss_init_sec_context(), using portable SPNEGO
- * implementation instead of the one that's part of the GSSAPI
- * library. Takes arguments identical to the standard GSSAPI
- * function, uses standard gss_init_sec_context() to handle
- * everything inside the SPNEGO wrapper.
- */
-OM_uint32
-gss_init_sec_context_spnego(OM_uint32 *,
- const gss_cred_id_t,
- gss_ctx_id_t *,
- const gss_name_t,
- const gss_OID,
- OM_uint32,
- OM_uint32,
- const gss_channel_bindings_t,
- const gss_buffer_t,
- gss_OID *,
- gss_buffer_t,
- OM_uint32 *,
- OM_uint32 *);
-
-/*%
- * Wrapper for GSSAPI gss_accept_sec_context(), using portable SPNEGO
- * implementation instead of the one that's part of the GSSAPI
- * library. Takes arguments identical to the standard GSSAPI
- * function. Checks the OID of the input token to see if it's SPNEGO;
- * if so, processes it, otherwise hands the call off to the standard
- * gss_accept_sec_context() function.
- */
-OM_uint32 gss_accept_sec_context_spnego(OM_uint32 *,
- gss_ctx_id_t *,
- const gss_cred_id_t,
- const gss_buffer_t,
- const gss_channel_bindings_t,
- gss_name_t *,
- gss_OID *,
- gss_buffer_t,
- OM_uint32 *,
- OM_uint32 *,
- gss_cred_id_t *);
-
-
-#endif
diff --git a/usr.sbin/bind/lib/dns/spnego_asn1.pl b/usr.sbin/bind/lib/dns/spnego_asn1.pl
deleted file mode 100644
index aba081abf8d..00000000000
--- a/usr.sbin/bind/lib/dns/spnego_asn1.pl
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/bin/bin/perl -w
-#
-# 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: spnego_asn1.pl,v 1.2 2019/12/17 01:46:32 sthen Exp $
-
-# Our SPNEGO implementation uses some functions generated by the
-# Heimdal ASN.1 compiler, which this script then whacks a bit to make
-# them work properly in this stripped down implementation. We don't
-# want to require our users to have a copy of the compiler, so we ship
-# the output of this script, but we need to keep the script around in
-# any case to cope with future changes to the SPNEGO ASN.1 code, so we
-# might as well supply the script for users who want it.
-
-# Overall plan: run the ASN.1 compiler, run each of its output files
-# through indent, fix up symbols and whack everything to be static.
-# We use indent for two reasons: (1) to whack the Heimdal compiler's
-# output into something closer to ISC's coding standard, and (2) to
-# make it easier for this script to parse the result.
-
-# Output from this script is C code which we expect to be #included
-# into another C file, which is why everything generated by this
-# script is marked "static". The intent is to minimize the number of
-# extern symbols exported by the SPNEGO implementation, to avoid
-# potential conflicts with the GSSAPI libraries.
-
-###
-
-# Filename of the ASN.1 specification. Hardcoded for the moment
-# since this script is intended for compiling exactly one module.
-
-my $asn1_source = $ENV{ASN1_SOURCE} || "spnego.asn1";
-
-# Heimdal ASN.1 compiler. This script was written using the version
-# from Heimdal 0.7.1. To build this, download a copy of
-# heimdal-0.7.1.tar.gz, configure and build with the default options,
-# then look for the compiler in heimdal-0.7.1/lib/asn1/asn1_compile.
-
-my $asn1_compile = $ENV{ASN1_COMPILE} || "asn1_compile";
-
-# BSD indent program. This script was written using the version of
-# indent that comes with FreeBSD 4.11-STABLE. The GNU project, as
-# usual, couldn't resist the temptation to monkey with indent's
-# command line syntax, so this probably won't work with GNU indent.
-
-my $indent = $ENV{INDENT} || "indent";
-
-###
-
-# Step 1: run the compiler. Input is the ASN.1 file. Outputs are a
-# header file (name specified on command line without the .h suffix),
-# a file called "asn1_files" listing the names of the other output
-# files, and a set of files containing C code generated by the
-# compiler for each data type that the compiler found.
-
-if (! -r $asn1_source || system($asn1_compile, $asn1_source, "asn1")) {
- die("Couldn't compile ASN.1 source file $asn1_source\n");
-}
-
-my @files = ("asn1.h");
-
-open(F, "asn1_files")
- or die("Couldn't open asn1_files: $!\n");
-push(@files, split)
- while (<F>);
-close(F);
-
-unlink("asn1_files");
-
-###
-
-# Step 2: generate header block.
-
-print(q~/*
- * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
- *
- * Permission to use, copy, modify, and 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: spnego_asn1.pl,v 1.2 2019/12/17 01:46:32 sthen Exp $ */
-
-/*! \file
- * \brief Method routines generated from SPNEGO ASN.1 module.
- * See spnego_asn1.pl for details. Do not edit.
- */
-
-~);
-
-###
-
-# Step 3: read and process each generated file, then delete it.
-
-my $output;
-
-for my $file (@files) {
-
- my $is_static = 0;
-
- system($indent, "-di1", "-ldi1", $file) == 0
- or die("Couldn't indent $file");
-
- unlink("$file.BAK");
-
- open(F, $file)
- or die("Couldn't open $file: $!");
-
- while (<F>) {
-
- # Symbol name fixups
-
- s/heim_general_string/general_string/g;
- s/heim_octet_string/octet_string/g;
- s/heim_oid/oid/g;
- s/heim_utf8_string/utf8_string/g;
-
- # Convert all externs to statics
-
- if (/^static/) {
- $is_static = 1;
- }
-
- if (!/^typedef/ &&
- !$is_static &&
- /^[A-Za-z_][0-9A-Za-z_]*[ \t]*($|[^:0-9A-Za-z_])/) {
- $_ = "static " . $_;
- $is_static = 1;
- }
-
- if (/[{};]/) {
- $is_static = 0;
- }
-
- # Suppress file inclusion, pass anything else through
-
- if (!/#include/) {
- $output .= $_;
- }
- }
-
- close(F);
- unlink($file);
-}
-
-# Step 4: Delete unused stuff to avoid code bloat and compiler warnings.
-
-my @unused_functions = qw(ContextFlags2int
- int2ContextFlags
- asn1_ContextFlags_units
- length_NegTokenInit
- copy_NegTokenInit
- length_NegTokenResp
- copy_NegTokenResp
- length_MechTypeList
- length_MechType
- copy_MechTypeList
- length_ContextFlags
- copy_ContextFlags
- copy_MechType);
-
-$output =~ s<^static [^\n]+\n$_\(.+?^}></* unused function: $_ */\n>ms
- foreach (@unused_functions);
-
-$output =~ s<^static .+$_\(.*\);$></* unused declaration: $_ */>m
- foreach (@unused_functions);
-
-$output =~ s<^static struct units ContextFlags_units\[\].+?^};>
- </* unused variable: ContextFlags_units */>ms;
-
-$output =~ s<^static int asn1_NegotiationToken_dummy_holder = 1;>
- </* unused variable: asn1_NegotiationToken_dummy_holder */>ms;
-
-$output =~ s<^static void\nfree_ContextFlags\(ContextFlags \* data\)\n{\n>
- <$&\t(void)data;\n>ms;
-
-# Step 5: Write the result.
-
-print($output);
-
diff --git a/usr.sbin/bind/lib/dns/ssu.c b/usr.sbin/bind/lib/dns/ssu.c
index f540b77dafa..8d52027240d 100644
--- a/usr.sbin/bind/lib/dns/ssu.c
+++ b/usr.sbin/bind/lib/dns/ssu.c
@@ -16,7 +16,7 @@
/*! \file */
/*
- * $Id: ssu.c,v 1.3 2019/12/17 01:46:32 sthen Exp $
+ * $Id: ssu.c,v 1.4 2020/01/09 13:56:37 florian Exp $
* Principal Author: Brian Wellington
*/
@@ -34,7 +34,6 @@
#include <dns/name.h>
#include <dns/ssu.h>
-#include <dst/gssapi.h>
#include <dst/dst.h>
#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
@@ -471,28 +470,20 @@ dns_ssutable_checkrules2(dns_ssutable_t *table, dns_name_t *signer,
continue;
break;
case DNS_SSUMATCHTYPE_SELFKRB5:
- if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
- rule->identity))
- continue;
+ continue;
break;
case DNS_SSUMATCHTYPE_SELFMS:
- if (!dst_gssapi_identitymatchesrealmms(signer, name,
- rule->identity))
- continue;
+ continue;
break;
case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
if (!dns_name_issubdomain(name, rule->name))
continue;
- if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
- rule->identity))
- continue;
+ continue;
break;
case DNS_SSUMATCHTYPE_SUBDOMAINMS:
if (!dns_name_issubdomain(name, rule->name))
continue;
- if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
- rule->identity))
- continue;
+ continue;
break;
case DNS_SSUMATCHTYPE_TCPSELF:
dns_fixedname_init(&fixed);
diff --git a/usr.sbin/bind/lib/dns/tkey.c b/usr.sbin/bind/lib/dns/tkey.c
index bc1cf124c49..815569ba3f0 100644
--- a/usr.sbin/bind/lib/dns/tkey.c
+++ b/usr.sbin/bind/lib/dns/tkey.c
@@ -42,7 +42,6 @@
#include <dns/tsig.h>
#include <dst/dst.h>
-#include <dst/gssapi.h>
#include "dst_internal.h"
@@ -68,41 +67,6 @@ tkey_log(const char *fmt, ...) {
va_end(ap);
}
-static void
-dumpmessage(dns_message_t *msg) {
- isc_buffer_t outbuf;
- unsigned char *output;
- int len = TEMP_BUFFER_SZ;
- isc_result_t result;
-
- for (;;) {
- output = isc_mem_get(msg->mctx, len);
- if (output == NULL)
- return;
-
- isc_buffer_init(&outbuf, output, len);
- result = dns_message_totext(msg, &dns_master_style_debug,
- 0, &outbuf);
- if (result == ISC_R_NOSPACE) {
- isc_mem_put(msg->mctx, output, len);
- len *= 2;
- continue;
- }
-
- if (result == ISC_R_SUCCESS)
- tkey_log("%.*s",
- (int)isc_buffer_usedlength(&outbuf),
- (char *)isc_buffer_base(&outbuf));
- else
- tkey_log("Warning: dns_message_totext: %s",
- dns_result_totext(result));
- break;
- }
-
- if (output != NULL)
- isc_mem_put(msg->mctx, output, len);
-}
-
isc_result_t
dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
{
@@ -121,8 +85,6 @@ dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
isc_entropy_attach(ectx, &tctx->ectx);
tctx->dhkey = NULL;
tctx->domain = NULL;
- tctx->gsscred = NULL;
- tctx->gssapi_keytab = NULL;
*tctxp = tctx;
return (ISC_R_SUCCESS);
@@ -145,11 +107,6 @@ dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
dns_name_free(tctx->domain, mctx);
isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
}
- if (tctx->gssapi_keytab != NULL) {
- isc_mem_free(mctx, tctx->gssapi_keytab);
- }
- if (tctx->gsscred != NULL)
- dst_gssapi_releasecred(&tctx->gsscred);
isc_entropy_detach(&tctx->ectx);
isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
isc_mem_detach(&mctx);
@@ -392,153 +349,6 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
}
static isc_result_t
-process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
- dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
- dns_tsig_keyring_t *ring)
-{
- isc_result_t result = ISC_R_SUCCESS;
- dst_key_t *dstkey = NULL;
- dns_tsigkey_t *tsigkey = NULL;
- dns_fixedname_t fixed;
- dns_name_t *principal;
- isc_stdtime_t now;
- isc_region_t intoken;
- isc_buffer_t *outtoken = NULL;
- gss_ctx_id_t gss_ctx = NULL;
-
- /*
- * 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
- * order to use gsstkey
- */
- if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
- tkey_log("process_gsstkey(): no tkey-gssapi-credential "
- "or tkey-gssapi-keytab configured");
- return (ISC_R_NOPERM);
- }
-
- if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
- !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
- tkeyout->error = dns_tsigerror_badalg;
- tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
- return (ISC_R_SUCCESS);
- }
-
- /*
- * XXXDCL need to check for key expiry per 4.1.1
- * XXXDCL need a way to check fully established, perhaps w/key_flags
- */
-
- intoken.base = tkeyin->key;
- intoken.length = tkeyin->keylen;
-
- result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
- if (result == ISC_R_SUCCESS)
- gss_ctx = dst_key_getgssctx(tsigkey->key);
-
- dns_fixedname_init(&fixed);
- principal = dns_fixedname_name(&fixed);
-
- /*
- * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
- */
- result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
- &intoken, &outtoken, &gss_ctx,
- principal, tctx->mctx);
- if (result == DNS_R_INVALIDTKEY) {
- if (tsigkey != NULL)
- dns_tsigkey_detach(&tsigkey);
- tkeyout->error = dns_tsigerror_badkey;
- tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
- return (ISC_R_SUCCESS);
- }
- if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
- goto failure;
- /*
- * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
- */
-
- isc_stdtime_get(&now);
-
- if (dns_name_countlabels(principal) == 0U) {
- if (tsigkey != NULL)
- dns_tsigkey_detach(&tsigkey);
- } else if (tsigkey == NULL) {
-#ifdef GSSAPI
- OM_uint32 gret, minor, lifetime;
-#endif
- isc_uint32_t expire;
-
- RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx,
- &dstkey, &intoken));
- /*
- * Limit keys to 1 hour or the context's lifetime whichever
- * is smaller.
- */
- expire = now + 3600;
-#ifdef GSSAPI
- gret = gss_context_time(&minor, gss_ctx, &lifetime);
- if (gret == GSS_S_COMPLETE && now + lifetime < expire)
- expire = now + lifetime;
-#endif
- RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
- dstkey, ISC_TRUE, principal,
- now, expire, ring->mctx, ring,
- NULL));
- dst_key_free(&dstkey);
- tkeyout->inception = now;
- tkeyout->expire = expire;
- } else {
- tkeyout->inception = tsigkey->inception;
- tkeyout->expire = tsigkey->expire;
- dns_tsigkey_detach(&tsigkey);
- }
-
- if (outtoken) {
- tkeyout->key = isc_mem_get(tkeyout->mctx,
- isc_buffer_usedlength(outtoken));
- if (tkeyout->key == NULL) {
- result = ISC_R_NOMEMORY;
- goto failure;
- }
- tkeyout->keylen = isc_buffer_usedlength(outtoken);
- memmove(tkeyout->key, isc_buffer_base(outtoken),
- isc_buffer_usedlength(outtoken));
- isc_buffer_free(&outtoken);
- } else {
- tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
- if (tkeyout->key == NULL) {
- result = ISC_R_NOMEMORY;
- goto failure;
- }
- tkeyout->keylen = tkeyin->keylen;
- memmove(tkeyout->key, tkeyin->key, tkeyin->keylen);
- }
-
- tkeyout->error = dns_rcode_noerror;
-
- tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
-
- return (ISC_R_SUCCESS);
-
-failure:
- if (tsigkey != NULL)
- dns_tsigkey_detach(&tsigkey);
-
- if (dstkey != NULL)
- dst_key_free(&dstkey);
-
- if (outtoken != NULL)
- isc_buffer_free(&outtoken);
-
- tkey_log("process_gsstkey(): %s",
- isc_result_totext(result)); /* XXXSRA */
-
- return (result);
-}
-
-static isc_result_t
process_deletetkey(dns_name_t *signer, dns_name_t *name,
dns_rdata_tkey_t *tkeyin, dns_rdata_tkey_t *tkeyout,
dns_tsig_keyring_t *ring)
@@ -647,20 +457,14 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
/*
* Before we go any farther, verify that the message was signed.
- * GSSAPI TKEY doesn't require a signature, the rest do.
*/
dns_name_init(&tsigner, NULL);
result = dns_message_signer(msg, &tsigner);
if (result != ISC_R_SUCCESS) {
- if (tkeyin.mode == DNS_TKEYMODE_GSSAPI &&
- result == ISC_R_NOTFOUND)
- signer = NULL;
- else {
- tkey_log("dns_tkey_processquery: query was not "
- "properly signed - rejecting");
- result = DNS_R_FORMERR;
- goto failure;
- }
+ tkey_log("dns_tkey_processquery: query was not "
+ "properly signed - rejecting");
+ result = DNS_R_FORMERR;
+ goto failure;
} else
signer = &tsigner;
@@ -689,7 +493,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
dns_tsigkey_t *tsigkey = NULL;
- if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
+ if (tctx->domain == NULL) {
tkey_log("dns_tkey_processquery: tkey-domain not set");
result = DNS_R_REFUSED;
goto failure;
@@ -731,18 +535,10 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
goto failure;
}
- if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
- /* Yup. This is a hack */
- result = dns_name_concatenate(keyname, dns_rootname,
- keyname, NULL);
- if (result != ISC_R_SUCCESS)
- goto failure;
- } else {
- result = dns_name_concatenate(keyname, tctx->domain,
- keyname, NULL);
- if (result != ISC_R_SUCCESS)
- goto failure;
- }
+ result = dns_name_concatenate(keyname, tctx->domain,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
@@ -762,11 +558,6 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
tctx, &tkeyout, ring,
&namelist));
break;
- case DNS_TKEYMODE_GSSAPI:
- tkeyout.error = dns_rcode_noerror;
- RETERR(process_gsstkey(keyname, &tkeyin, tctx,
- &tkeyout, ring));
- break;
case DNS_TKEYMODE_DELETE:
tkeyout.error = dns_rcode_noerror;
RETERR(process_deletetkey(signer, keyname, &tkeyin,
@@ -980,56 +771,6 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
}
isc_result_t
-dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
- isc_buffer_t *intoken, isc_uint32_t lifetime,
- gss_ctx_id_t *context, isc_boolean_t win2k,
- isc_mem_t *mctx, char **err_message)
-{
- dns_rdata_tkey_t tkey;
- isc_result_t result;
- isc_stdtime_t now;
- isc_buffer_t token;
- unsigned char array[TEMP_BUFFER_SZ];
-
- UNUSED(intoken);
-
- REQUIRE(msg != NULL);
- REQUIRE(name != NULL);
- REQUIRE(gname != NULL);
- REQUIRE(context != NULL);
- REQUIRE(mctx != NULL);
-
- isc_buffer_init(&token, array, sizeof(array));
- result = dst_gssapi_initctx(gname, NULL, &token, context,
- mctx, err_message);
- if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
- return (result);
-
- tkey.common.rdclass = dns_rdataclass_any;
- tkey.common.rdtype = dns_rdatatype_tkey;
- ISC_LINK_INIT(&tkey.common, link);
- tkey.mctx = NULL;
- dns_name_init(&tkey.algorithm, NULL);
-
- if (win2k)
- dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
- else
- dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
-
- isc_stdtime_get(&now);
- tkey.inception = now;
- tkey.expire = now + lifetime;
- tkey.mode = DNS_TKEYMODE_GSSAPI;
- tkey.error = 0;
- tkey.key = isc_buffer_base(&token);
- tkey.keylen = isc_buffer_usedlength(&token);
- tkey.other = NULL;
- tkey.otherlen = 0;
-
- return (buildquery(msg, name, &tkey, win2k));
-}
-
-isc_result_t
dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key) {
dns_rdata_tkey_t tkey;
@@ -1208,84 +949,6 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
}
isc_result_t
-dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *gname, gss_ctx_id_t *context,
- isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
- dns_tsig_keyring_t *ring, char **err_message)
-{
- dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
- dns_name_t *tkeyname;
- dns_rdata_tkey_t rtkey, qtkey;
- dst_key_t *dstkey = NULL;
- isc_buffer_t intoken;
- isc_result_t result;
- unsigned char array[TEMP_BUFFER_SZ];
-
- REQUIRE(outtoken != NULL);
- REQUIRE(qmsg != NULL);
- REQUIRE(rmsg != NULL);
- REQUIRE(gname != NULL);
- REQUIRE(ring != NULL);
- if (outkey != NULL)
- REQUIRE(*outkey == NULL);
-
- if (rmsg->rcode != dns_rcode_noerror)
- return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
- RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
- RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
-
- /*
- * Win2k puts the item in the ANSWER section, while the RFC
- * specifies it should be in the ADDITIONAL section. Check first
- * where it should be, and then where it may be.
- */
- result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
- DNS_SECTION_ADDITIONAL);
- if (result == ISC_R_NOTFOUND)
- result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
- DNS_SECTION_ANSWER);
- if (result != ISC_R_SUCCESS)
- goto failure;
-
- 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)) {
- tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
- "or error set(2) %d", rtkey.error);
- dumpmessage(qmsg);
- dumpmessage(rmsg);
- result = DNS_R_INVALIDTKEY;
- goto failure;
- }
-
- isc_buffer_init(outtoken, array, sizeof(array));
- isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
- RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context,
- ring->mctx, err_message));
-
- RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
- &dstkey, NULL));
-
- RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
- dstkey, ISC_FALSE, NULL,
- rtkey.inception, rtkey.expire,
- ring->mctx, ring, outkey));
- dst_key_free(&dstkey);
- dns_rdata_freestruct(&rtkey);
- return (result);
-
- failure:
- /*
- * XXXSRA This probably leaks memory from rtkey and qtkey.
- */
- if (dstkey != NULL)
- dst_key_free(&dstkey);
- return (result);
-}
-
-isc_result_t
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dns_tsig_keyring_t *ring)
{
@@ -1339,121 +1002,3 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
failure:
return (result);
}
-
-isc_result_t
-dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *server, gss_ctx_id_t *context,
- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
- isc_boolean_t win2k, char **err_message)
-{
- dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
- dns_name_t *tkeyname;
- dns_rdata_tkey_t rtkey, qtkey, tkey;
- isc_buffer_t intoken, outtoken;
- dst_key_t *dstkey = NULL;
- isc_result_t result;
- unsigned char array[TEMP_BUFFER_SZ];
- isc_boolean_t freertkey = ISC_FALSE;
-
- REQUIRE(qmsg != NULL);
- REQUIRE(rmsg != NULL);
- REQUIRE(server != NULL);
- if (outkey != NULL)
- REQUIRE(*outkey == NULL);
-
- if (rmsg->rcode != dns_rcode_noerror)
- return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
-
- RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
- RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
- freertkey = ISC_TRUE;
-
- if (win2k == ISC_TRUE)
- RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
- DNS_SECTION_ANSWER));
- else
- RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
- DNS_SECTION_ADDITIONAL));
-
- 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))
- {
- tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
- "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));
-
- result = dst_gssapi_initctx(server, &intoken, &outtoken, context,
- ring->mctx, err_message);
- if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
- return (result);
-
- if (result == DNS_R_CONTINUE) {
- dns_fixedname_t fixed;
-
- dns_fixedname_init(&fixed);
- dns_name_copy(tkeyname, dns_fixedname_name(&fixed), NULL);
- tkeyname = dns_fixedname_name(&fixed);
-
- tkey.common.rdclass = dns_rdataclass_any;
- tkey.common.rdtype = dns_rdatatype_tkey;
- ISC_LINK_INIT(&tkey.common, link);
- tkey.mctx = NULL;
- dns_name_init(&tkey.algorithm, NULL);
-
- if (win2k)
- dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
- else
- dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
-
- tkey.inception = qtkey.inception;
- tkey.expire = qtkey.expire;
- tkey.mode = DNS_TKEYMODE_GSSAPI;
- tkey.error = 0;
- tkey.key = isc_buffer_base(&outtoken);
- tkey.keylen = isc_buffer_usedlength(&outtoken);
- tkey.other = NULL;
- tkey.otherlen = 0;
-
- dns_message_reset(qmsg, DNS_MESSAGE_INTENTRENDER);
- RETERR(buildquery(qmsg, tkeyname, &tkey, win2k));
- return (DNS_R_CONTINUE);
- }
-
- RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
- &dstkey, 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.
- */
-
- RETERR(dns_tsigkey_createfromkey(tkeyname,
- (win2k
- ? DNS_TSIG_GSSAPIMS_NAME
- : DNS_TSIG_GSSAPI_NAME),
- dstkey, ISC_TRUE, NULL,
- rtkey.inception, rtkey.expire,
- ring->mctx, ring, outkey));
- dst_key_free(&dstkey);
- dns_rdata_freestruct(&rtkey);
- return (result);
-
- failure:
- /*
- * XXXSRA This probably leaks memory from qtkey.
- */
- if (freertkey)
- dns_rdata_freestruct(&rtkey);
- if (dstkey != NULL)
- dst_key_free(&dstkey);
- return (result);
-}
diff --git a/usr.sbin/bind/lib/dns/tsig.c b/usr.sbin/bind/lib/dns/tsig.c
index 1d8c824d681..0daff38d530 100644
--- a/usr.sbin/bind/lib/dns/tsig.c
+++ b/usr.sbin/bind/lib/dns/tsig.c
@@ -15,7 +15,7 @@
*/
/*
- * $Id: tsig.c,v 1.10 2020/01/09 13:52:23 florian Exp $
+ * $Id: tsig.c,v 1.11 2020/01/09 13:56:37 florian Exp $
*/
/*! \file */
#include <config.h>
@@ -59,9 +59,7 @@
(algname) != dns_tsig_hmacsha224_name && \
(algname) != dns_tsig_hmacsha256_name && \
(algname) != dns_tsig_hmacsha384_name && \
- (algname) != dns_tsig_hmacsha512_name && \
- (algname) != dns_tsig_gssapi_name && \
- (algname) != dns_tsig_gssapims_name)
+ (algname) != dns_tsig_hmacsha512_name)
#ifndef DNS_NAME_INITABSOLUTE
#define DNS_NAME_INITABSOLUTE(A,B) { \
@@ -75,22 +73,6 @@
#define BADTIMELEN 6
-static unsigned char gsstsig_ndata[] = "\010gss-tsig";
-static unsigned char gsstsig_offsets[] = { 0, 9 };
-static dns_name_t gsstsig =
- DNS_NAME_INITABSOLUTE(gsstsig_ndata, gsstsig_offsets);
-LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
-
-/*
- * Since Microsoft doesn't follow its own standard, we will use this
- * alternate name as a second guess.
- */
-static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
-static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
-static dns_name_t gsstsigms =
- DNS_NAME_INITABSOLUTE(gsstsigms_ndata, gsstsigms_offsets);
-LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
-
static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
static unsigned char hmacsha1_offsets[] = { 0, 10 };
static dns_name_t hmacsha1 =
@@ -297,18 +279,6 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
ret = DNS_R_BADALG;
goto cleanup_name;
}
- } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
- tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
- if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
- ret = DNS_R_BADALG;
- goto cleanup_name;
- }
- } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
- tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
- if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
- ret = DNS_R_BADALG;
- goto cleanup_name;
- }
} else {
if (dstkey != NULL) {
ret = DNS_R_BADALG;
@@ -373,9 +343,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
/*
* Ignore this if it's a GSS key, since the key size is meaningless.
*/
- if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
- !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
- !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
+ if (dstkey != NULL && dst_key_size(dstkey) < 64) {
char namestr[DNS_NAME_FORMATSIZE];
dns_name_format(name, namestr, sizeof(namestr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
@@ -491,10 +459,6 @@ dst_alg_fromname(dns_name_t *algorithm) {
return (DST_ALG_HMACSHA384);
} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
return (DST_ALG_HMACSHA512);
- } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
- return (DST_ALG_GSSAPI);
- } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
- return (DST_ALG_GSSAPI);
} else
return (0);
}