diff options
Diffstat (limited to 'usr.sbin/bind/lib/dns')
-rw-r--r-- | usr.sbin/bind/lib/dns/Makefile.in | 8 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/dst_api.c | 71 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/dst_internal.h | 5 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/gssapi_link.c | 395 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/gssapictx.c | 886 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dns/tkey.h | 74 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dns/tsig.h | 6 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dns/types.h | 9 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dst/Makefile.in | 4 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dst/dst.h | 39 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/include/dst/gssapi.h | 206 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/spnego.c | 1828 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/spnego.h | 71 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/spnego_asn1.pl | 200 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/ssu.c | 19 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/tkey.c | 473 | ||||
-rw-r--r-- | usr.sbin/bind/lib/dns/tsig.c | 42 |
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); } |