Match Heimdal behavior for channel bindings
This commit is contained in:
parent
feaafc07b2
commit
e326a52474
419
Add-channel-bindings-tests.patch
Normal file
419
Add-channel-bindings-tests.patch
Normal file
@ -0,0 +1,419 @@
|
||||
From 3e92520c1417f22447751cd9172d5ab30c2e0ad8 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Fri, 20 Mar 2020 00:17:28 +0100
|
||||
Subject: [PATCH] Add channel bindings tests
|
||||
|
||||
[ghudson@mit.edu: adjusted test program to output channel-bound state
|
||||
instead of optionally enforcing it; adjusted tests to check program
|
||||
output; split out tests into separate Python script; made cosmetic
|
||||
changes]
|
||||
|
||||
ticket: 8900
|
||||
(cherry picked from commit b0b21b6d25b06f3e2b365dfe9dd4c99b3d43bf57)
|
||||
[rharwood@redhat.com: .gitignore]
|
||||
---
|
||||
src/plugins/gssapi/negoextest/main.c | 18 +++++
|
||||
src/tests/gssapi/Makefile.in | 49 ++++++------
|
||||
src/tests/gssapi/common.c | 25 ++++--
|
||||
src/tests/gssapi/common.h | 9 +++
|
||||
src/tests/gssapi/deps | 4 +
|
||||
src/tests/gssapi/t_bindings.c | 111 +++++++++++++++++++++++++++
|
||||
src/tests/gssapi/t_bindings.py | 43 +++++++++++
|
||||
src/tests/gssapi/t_negoex.py | 7 ++
|
||||
8 files changed, 237 insertions(+), 29 deletions(-)
|
||||
create mode 100644 src/tests/gssapi/t_bindings.c
|
||||
create mode 100644 src/tests/gssapi/t_bindings.py
|
||||
|
||||
diff --git a/src/plugins/gssapi/negoextest/main.c b/src/plugins/gssapi/negoextest/main.c
|
||||
index 6c340f41b..72fc5273a 100644
|
||||
--- a/src/plugins/gssapi/negoextest/main.c
|
||||
+++ b/src/plugins/gssapi/negoextest/main.c
|
||||
@@ -57,6 +57,15 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
const char *envstr;
|
||||
uint8_t hops, mech_last_octet;
|
||||
|
||||
+ envstr = getenv("GSS_INIT_BINDING");
|
||||
+ if (envstr != NULL) {
|
||||
+ assert(strlen(envstr) > 0);
|
||||
+ assert(input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS);
|
||||
+ assert(strlen(envstr) == input_chan_bindings->application_data.length);
|
||||
+ assert(strcmp((char *)input_chan_bindings->application_data.value,
|
||||
+ envstr) == 0);
|
||||
+ }
|
||||
+
|
||||
if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
|
||||
envstr = getenv("HOPS");
|
||||
hops = (envstr != NULL) ? atoi(envstr) : 1;
|
||||
@@ -112,6 +121,15 @@ gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle,
|
||||
uint8_t hops, mech_last_octet;
|
||||
const char *envstr;
|
||||
|
||||
+ envstr = getenv("GSS_ACCEPT_BINDING");
|
||||
+ if (envstr != NULL) {
|
||||
+ assert(strlen(envstr) > 0);
|
||||
+ assert(input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS);
|
||||
+ assert(strlen(envstr) == input_chan_bindings->application_data.length);
|
||||
+ assert(strcmp((char *)input_chan_bindings->application_data.value,
|
||||
+ envstr) == 0);
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* The unwrapped token sits at the end and is just one byte giving the
|
||||
* remaining number of hops. The final octet of the mech encoding should
|
||||
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
|
||||
index 5cc1e0f58..68c132b79 100644
|
||||
--- a/src/tests/gssapi/Makefile.in
|
||||
+++ b/src/tests/gssapi/Makefile.in
|
||||
@@ -9,33 +9,33 @@ LOCALINCLUDES = -I$(srcdir)/../../lib/gssapi/mechglue \
|
||||
-I../../lib/gssapi/generic
|
||||
|
||||
SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
|
||||
- $(srcdir)/t_accname.c $(srcdir)/t_add_cred.c $(srcdir)/t_ccselect.c \
|
||||
- $(srcdir)/t_ciflags.c $(srcdir)/t_context.c $(srcdir)/t_credstore.c \
|
||||
- $(srcdir)/t_enctypes.c $(srcdir)/t_err.c $(srcdir)/t_export_cred.c \
|
||||
- $(srcdir)/t_export_name.c $(srcdir)/t_gssexts.c \
|
||||
- $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c $(srcdir)/t_invalid.c \
|
||||
- $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \
|
||||
+ $(srcdir)/t_accname.c $(srcdir)/t_add_cred.c $(srcdir)/t_bindings.c \
|
||||
+ $(srcdir)/t_ccselect.c $(srcdir)/t_ciflags.c $(srcdir)/t_context.c \
|
||||
+ $(srcdir)/t_credstore.c $(srcdir)/t_enctypes.c $(srcdir)/t_err.c \
|
||||
+ $(srcdir)/t_export_cred.c $(srcdir)/t_export_name.c \
|
||||
+ $(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \
|
||||
+ $(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \
|
||||
$(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \
|
||||
$(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \
|
||||
$(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \
|
||||
$(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \
|
||||
$(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c
|
||||
|
||||
-OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_add_cred.o t_ccselect.o \
|
||||
- t_ciflags.o t_context.o t_credstore.o t_enctypes.o t_err.o \
|
||||
- t_export_cred.o t_export_name.o t_gssexts.o t_imp_cred.o t_imp_name.o \
|
||||
- t_invalid.o t_inq_cred.o t_inq_ctx.o t_inq_mechs_name.o t_iov.o \
|
||||
- t_lifetime.o t_namingexts.o t_oid.o t_pcontok.o t_prf.o t_s4u.o \
|
||||
- t_s4u2proxy_krb5.o t_saslname.o t_spnego.o t_srcattrs.o
|
||||
+OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_add_cred.o t_bindings.o \
|
||||
+ t_ccselect.o t_ciflags.o t_context.o t_credstore.o t_enctypes.o \
|
||||
+ t_err.o t_export_cred.o t_export_name.o t_gssexts.o t_imp_cred.o \
|
||||
+ t_imp_name.o t_invalid.o t_inq_cred.o t_inq_ctx.o t_inq_mechs_name.o \
|
||||
+ t_iov.o t_lifetime.o t_namingexts.o t_oid.o t_pcontok.o t_prf.o \
|
||||
+ t_s4u.o t_s4u2proxy_krb5.o t_saslname.o t_spnego.o t_srcattrs.o
|
||||
|
||||
COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
|
||||
COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
|
||||
|
||||
-all: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags t_context \
|
||||
- t_credstore t_enctypes t_err t_export_cred t_export_name t_gssexts \
|
||||
- t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name \
|
||||
- t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u \
|
||||
- t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs
|
||||
+all: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect t_ciflags \
|
||||
+ t_context t_credstore t_enctypes t_err t_export_cred t_export_name \
|
||||
+ t_gssexts t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx \
|
||||
+ t_inq_mechs_name t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf \
|
||||
+ t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs
|
||||
|
||||
check-unix: t_oid
|
||||
$(RUN_TEST) ./t_invalid
|
||||
@@ -43,11 +43,12 @@ check-unix: t_oid
|
||||
$(RUN_TEST) ./t_prf
|
||||
$(RUN_TEST) ./t_imp_name
|
||||
|
||||
-check-pytests: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags \
|
||||
- t_context t_credstore t_enctypes t_err t_export_cred t_export_name \
|
||||
- t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \
|
||||
- t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs
|
||||
+check-pytests: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect \
|
||||
+ t_ciflags t_context t_credstore t_enctypes t_err t_export_cred \
|
||||
+ t_export_name t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov \
|
||||
+ t_lifetime t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs
|
||||
$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
|
||||
+ $(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS)
|
||||
$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
|
||||
$(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS)
|
||||
$(RUNPYTEST) $(srcdir)/t_enctypes.py $(PYTESTFLAGS)
|
||||
@@ -64,6 +65,8 @@ t_accname: t_accname.o $(COMMON_DEPS)
|
||||
$(CC_LINK) -o $@ t_accname.o $(COMMON_LIBS)
|
||||
t_add_cred: t_add_cred.o $(COMMON_DEPS)
|
||||
$(CC_LINK) -o $@ t_add_cred.o $(COMMON_LIBS)
|
||||
+t_bindings: t_bindings.o $(COMMON_DEPS)
|
||||
+ $(CC_LINK) -o $@ t_bindings.o $(COMMON_LIBS)
|
||||
t_ccselect: t_ccselect.o $(COMMON_DEPS)
|
||||
$(CC_LINK) -o $@ t_ccselect.o $(COMMON_LIBS)
|
||||
t_ciflags: t_ciflags.o $(COMMON_DEPS)
|
||||
@@ -118,8 +121,8 @@ t_srcattrs: t_srcattrs.o $(COMMON_DEPS)
|
||||
$(CC_LINK) -o $@ t_srcattrs.o $(COMMON_LIBS)
|
||||
|
||||
clean:
|
||||
- $(RM) ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags
|
||||
- $(RM) t_context t_credstore t_enctypes t_err t_export_cred
|
||||
+ $(RM) ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect
|
||||
+ $(RM) t_ciflags t_context t_credstore t_enctypes t_err t_export_cred
|
||||
$(RM) t_export_name t_gssexts t_imp_cred t_imp_name t_invalid
|
||||
$(RM) t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime
|
||||
$(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5
|
||||
diff --git a/src/tests/gssapi/common.c b/src/tests/gssapi/common.c
|
||||
index 83e9d9bb8..7ba72f7b2 100644
|
||||
--- a/src/tests/gssapi/common.c
|
||||
+++ b/src/tests/gssapi/common.c
|
||||
@@ -115,6 +115,20 @@ establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
|
||||
gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
|
||||
gss_ctx_id_t *actx, gss_name_t *src_name, gss_OID *amech,
|
||||
gss_cred_id_t *deleg_cred)
|
||||
+{
|
||||
+ return establish_contexts_ex(imech, icred, acred, tname, flags, ictx, actx,
|
||||
+ GSS_C_NO_CHANNEL_BINDINGS,
|
||||
+ GSS_C_NO_CHANNEL_BINDINGS, NULL, src_name,
|
||||
+ amech, deleg_cred);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
|
||||
+ gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
|
||||
+ gss_ctx_id_t *actx, gss_channel_bindings_t icb,
|
||||
+ gss_channel_bindings_t acb, OM_uint32 *aret_flags,
|
||||
+ gss_name_t *src_name, gss_OID *amech,
|
||||
+ gss_cred_id_t *deleg_cred)
|
||||
{
|
||||
OM_uint32 minor, imaj, amaj;
|
||||
gss_buffer_desc itok, atok;
|
||||
@@ -126,17 +140,16 @@ establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
|
||||
for (;;) {
|
||||
(void)gss_release_buffer(&minor, &itok);
|
||||
imaj = gss_init_sec_context(&minor, icred, ictx, tname, imech, flags,
|
||||
- GSS_C_INDEFINITE,
|
||||
- GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL,
|
||||
- &itok, NULL, NULL);
|
||||
+ GSS_C_INDEFINITE, icb, &atok, NULL, &itok,
|
||||
+ NULL, NULL);
|
||||
check_gsserr("gss_init_sec_context", imaj, minor);
|
||||
if (amaj == GSS_S_COMPLETE)
|
||||
break;
|
||||
|
||||
(void)gss_release_buffer(&minor, &atok);
|
||||
- amaj = gss_accept_sec_context(&minor, actx, acred, &itok,
|
||||
- GSS_C_NO_CHANNEL_BINDINGS, src_name,
|
||||
- amech, &atok, NULL, NULL, deleg_cred);
|
||||
+ amaj = gss_accept_sec_context(&minor, actx, acred, &itok, acb,
|
||||
+ src_name, amech, &atok, aret_flags, NULL,
|
||||
+ deleg_cred);
|
||||
check_gsserr("gss_accept_sec_context", amaj, minor);
|
||||
(void)gss_release_buffer(&minor, &itok);
|
||||
if (imaj == GSS_S_COMPLETE)
|
||||
diff --git a/src/tests/gssapi/common.h b/src/tests/gssapi/common.h
|
||||
index ae11b51d4..a5c8f87e6 100644
|
||||
--- a/src/tests/gssapi/common.h
|
||||
+++ b/src/tests/gssapi/common.h
|
||||
@@ -62,6 +62,15 @@ void establish_contexts(gss_OID imech, gss_cred_id_t icred,
|
||||
gss_name_t *src_name, gss_OID *amech,
|
||||
gss_cred_id_t *deleg_cred);
|
||||
|
||||
+/* Establish contexts with channel bindings. */
|
||||
+void establish_contexts_ex(gss_OID imech, gss_cred_id_t icred,
|
||||
+ gss_cred_id_t acred, gss_name_t tname,
|
||||
+ OM_uint32 flags, gss_ctx_id_t *ictx,
|
||||
+ gss_ctx_id_t *actx, gss_channel_bindings_t icb,
|
||||
+ gss_channel_bindings_t acb, OM_uint32 *aret_flags,
|
||||
+ gss_name_t *src_name, gss_OID *amech,
|
||||
+ gss_cred_id_t *deleg_cred);
|
||||
+
|
||||
/* Export *cred to a token, then release *cred and replace it by re-importing
|
||||
* the token. */
|
||||
void export_import_cred(gss_cred_id_t *cred);
|
||||
diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps
|
||||
index acd0e96f8..73e4d9a74 100644
|
||||
--- a/src/tests/gssapi/deps
|
||||
+++ b/src/tests/gssapi/deps
|
||||
@@ -33,6 +33,10 @@ $(OUTPRE)t_add_cred.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
|
||||
$(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
|
||||
$(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
|
||||
common.h t_add_cred.c
|
||||
+$(OUTPRE)t_bindings.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
|
||||
+ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
|
||||
+ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
|
||||
+ common.h t_bindings.c
|
||||
$(OUTPRE)t_ccselect.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
|
||||
$(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \
|
||||
$(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
|
||||
diff --git a/src/tests/gssapi/t_bindings.c b/src/tests/gssapi/t_bindings.c
|
||||
new file mode 100644
|
||||
index 000000000..e8906715b
|
||||
--- /dev/null
|
||||
+++ b/src/tests/gssapi/t_bindings.c
|
||||
@@ -0,0 +1,111 @@
|
||||
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
+/*
|
||||
+ * Copyright (C) 2020 by Red Hat, Inc.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ *
|
||||
+ * * Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * * 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.
|
||||
+ *
|
||||
+ * 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 HOLDER 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.
|
||||
+ */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+
|
||||
+/*
|
||||
+ * Establish contexts (without and with GSS_C_DCE_STYLE) with the default
|
||||
+ * initiator name, a specified principal name as target name, initiator
|
||||
+ * bindings, and acceptor bindings. If any call is unsuccessful, display an
|
||||
+ * error message. Output "yes" or "no" to indicate whether the contexts were
|
||||
+ * reported as channel-bound on the acceptor. Exit with status 0 if all
|
||||
+ * operations are successful, or 1 if not.
|
||||
+ *
|
||||
+ * Usage: ./t_bindings [-s] targetname icb acb
|
||||
+ *
|
||||
+ * An icb or abc value of "-" will not specify channel bindings.
|
||||
+ */
|
||||
+
|
||||
+int
|
||||
+main(int argc, char *argv[])
|
||||
+{
|
||||
+ OM_uint32 minor, flags1, flags2;
|
||||
+ gss_name_t target_name;
|
||||
+ gss_ctx_id_t ictx, actx;
|
||||
+ struct gss_channel_bindings_struct icb_data = {0}, acb_data = {0};
|
||||
+ gss_channel_bindings_t icb = GSS_C_NO_CHANNEL_BINDINGS;
|
||||
+ gss_channel_bindings_t acb = GSS_C_NO_CHANNEL_BINDINGS;
|
||||
+ gss_OID_desc *mech;
|
||||
+
|
||||
+ argv++;
|
||||
+ argc--;
|
||||
+ if (*argv != NULL && strcmp(*argv, "-s") == 0) {
|
||||
+ mech = &mech_spnego;
|
||||
+ argv++;
|
||||
+ argc--;
|
||||
+ } else {
|
||||
+ mech = &mech_krb5;
|
||||
+ }
|
||||
+
|
||||
+ if (argc != 3) {
|
||||
+ fprintf(stderr, "Usage: t_bindings [-s] targetname icb acb\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ target_name = import_name(argv[0]);
|
||||
+
|
||||
+ if (strcmp(argv[1], "-") != 0) {
|
||||
+ icb_data.application_data.length = strlen(argv[1]);
|
||||
+ icb_data.application_data.value = argv[1];
|
||||
+ icb = &icb_data;
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(argv[2], "-") != 0) {
|
||||
+ acb_data.application_data.length = strlen(argv[2]);
|
||||
+ acb_data.application_data.value = argv[2];
|
||||
+ acb = &acb_data;
|
||||
+ }
|
||||
+
|
||||
+ establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
|
||||
+ target_name, 0, &ictx, &actx, icb, acb, &flags1,
|
||||
+ NULL, NULL, NULL);
|
||||
+
|
||||
+ /* Try again with GSS_C_DCE_STYLE */
|
||||
+ (void)gss_delete_sec_context(&minor, &ictx, NULL);
|
||||
+ (void)gss_delete_sec_context(&minor, &actx, NULL);
|
||||
+
|
||||
+ establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
|
||||
+ target_name, GSS_C_DCE_STYLE, &ictx, &actx, icb, acb,
|
||||
+ &flags2, NULL, NULL, NULL);
|
||||
+ assert((flags1 & GSS_C_CHANNEL_BOUND_FLAG) ==
|
||||
+ (flags2 & GSS_C_CHANNEL_BOUND_FLAG));
|
||||
+ printf("%s\n", (flags1 & GSS_C_CHANNEL_BOUND_FLAG) ? "yes" : "no");
|
||||
+
|
||||
+ (void)gss_delete_sec_context(&minor, &ictx, NULL);
|
||||
+ (void)gss_delete_sec_context(&minor, &actx, NULL);
|
||||
+ (void)gss_release_name(&minor, &target_name);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/tests/gssapi/t_bindings.py b/src/tests/gssapi/t_bindings.py
|
||||
new file mode 100644
|
||||
index 000000000..f377977b6
|
||||
--- /dev/null
|
||||
+++ b/src/tests/gssapi/t_bindings.py
|
||||
@@ -0,0 +1,43 @@
|
||||
+from k5test import *
|
||||
+
|
||||
+realm = K5Realm()
|
||||
+server = 'p:' + realm.host_princ
|
||||
+
|
||||
+mark('krb5 channel bindings')
|
||||
+realm.run(['./t_bindings', server, '-', '-'], expected_msg='no')
|
||||
+realm.run(['./t_bindings', server, 'a', '-'], expected_msg='no')
|
||||
+realm.run(['./t_bindings', server, 'a', 'a'], expected_msg='yes')
|
||||
+realm.run(['./t_bindings', server, '-', 'a'], expected_msg='no')
|
||||
+realm.run(['./t_bindings', server, 'a', 'x'],
|
||||
+ expected_code=1, expected_msg='Incorrect channel bindings')
|
||||
+
|
||||
+mark('SPNEGO channel bindings')
|
||||
+realm.run(['./t_bindings', '-s', server, '-', '-'], expected_msg='no')
|
||||
+realm.run(['./t_bindings', '-s', server, 'a', '-'], expected_msg='no')
|
||||
+realm.run(['./t_bindings', '-s', server, 'a', 'a'], expected_msg='yes')
|
||||
+realm.run(['./t_bindings', '-s', server, '-', 'a'], expected_msg='no')
|
||||
+realm.run(['./t_bindings', '-s', server, 'a', 'x'],
|
||||
+ expected_code=1, expected_msg='Incorrect channel bindings')
|
||||
+
|
||||
+client_aware_conf = {'libdefaults': {'client_aware_channel_bindings': 'true'}}
|
||||
+e = realm.special_env('cb_aware', False, krb5_conf=client_aware_conf)
|
||||
+
|
||||
+mark('krb5 client_aware_channel_bindings')
|
||||
+realm.run(['./t_bindings', server, '-', '-'], env=e, expected_msg='no')
|
||||
+realm.run(['./t_bindings', server, 'a', '-'], env=e, expected_msg='no')
|
||||
+realm.run(['./t_bindings', server, 'a', 'a'], env=e, expected_msg='yes')
|
||||
+realm.run(['./t_bindings', server, '-', 'a'], env=e,
|
||||
+ expected_code=1, expected_msg='Incorrect channel bindings')
|
||||
+realm.run(['./t_bindings', server, 'a', 'x'], env=e,
|
||||
+ expected_code=1, expected_msg='Incorrect channel bindings')
|
||||
+
|
||||
+mark('SPNEGO client_aware_channel_bindings')
|
||||
+realm.run(['./t_bindings', '-s', server, '-', '-'], env=e, expected_msg='no')
|
||||
+realm.run(['./t_bindings', '-s', server, 'a', '-'], env=e, expected_msg='no')
|
||||
+realm.run(['./t_bindings', '-s', server, 'a', 'a'], env=e, expected_msg='yes')
|
||||
+realm.run(['./t_bindings', '-s', server, '-', 'a'], env=e,
|
||||
+ expected_code=1, expected_msg='Incorrect channel bindings')
|
||||
+realm.run(['./t_bindings', '-s', server, 'a', 'x'], env=e,
|
||||
+ expected_code=1, expected_msg='Incorrect channel bindings')
|
||||
+
|
||||
+success('channel bindings tests')
|
||||
diff --git a/src/tests/gssapi/t_negoex.py b/src/tests/gssapi/t_negoex.py
|
||||
index 88470d2fa..a218899c4 100644
|
||||
--- a/src/tests/gssapi/t_negoex.py
|
||||
+++ b/src/tests/gssapi/t_negoex.py
|
||||
@@ -139,4 +139,11 @@ msgs = ('sending [3]AP_REQUEST', 'sending [7]CHALLENGE', 'sending [8]VERIFY',
|
||||
'sending [11]CHALLENGE', 'sending [12]VERIFY', 'sending [13]VERIFY')
|
||||
test({'HOPS': '4', 'KEY': 'accept-always'}, expected_trace=())
|
||||
|
||||
+mark('channel bindings')
|
||||
+e = realm.env.copy()
|
||||
+e.update({'HOPS': '1', 'GSS_INIT_BINDING': 'a', 'GSS_ACCEPT_BINDING': 'b'})
|
||||
+# The test mech will verify that the bindings are communicated to the
|
||||
+# mech, but does not set the channel-bound flag.
|
||||
+realm.run(['./t_bindings', '-s', 'h:host', 'a', 'b'], env=e, expected_msg='no')
|
||||
+
|
||||
success('NegoEx tests')
|
264
Add-client_aware_channel_bindings-option.patch
Normal file
264
Add-client_aware_channel_bindings-option.patch
Normal file
@ -0,0 +1,264 @@
|
||||
From 2a08fe3d2d1972df4ffe37d4bb64b161889ff988 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Tue, 10 Mar 2020 13:13:17 +0100
|
||||
Subject: [PATCH] Add client_aware_channel_bindings option
|
||||
|
||||
Add client support for KERB_AP_OPTIONS_CBT in the form of a profile
|
||||
option "client_aware_gss_bindings". Adjust the make_etype_list()
|
||||
helper so that enctype negotiation and AP_OPTIONS can be included in
|
||||
the same IF-RELEVANT wrapper.
|
||||
|
||||
[ghudson@mit.edu: refactored; edited documentation; wrote commit
|
||||
message]
|
||||
|
||||
ticket: 8900
|
||||
(cherry picked from commit 225e6ef7f021cd1a8ef2a054af0ca58b7288fd81)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 6 +
|
||||
src/include/k5-int.h | 1 +
|
||||
src/lib/krb5/krb/mk_req_ext.c | 177 +++++++++++++++--------------
|
||||
3 files changed, 98 insertions(+), 86 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index a7e7a29d1..7f2879640 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -382,6 +382,12 @@ The libdefaults section may contain any of the following relations:
|
||||
credentials will fail if the client machine does not have a
|
||||
keytab. The default value is false.
|
||||
|
||||
+**client_aware_channel_bindings**
|
||||
+ If this flag is true, then all application protocol authentication
|
||||
+ requests will be flagged to indicate that the application supports
|
||||
+ channel bindings when operating over a secure channel. The
|
||||
+ default value is false.
|
||||
+
|
||||
.. _realms:
|
||||
|
||||
[realms]
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index 0d9af3d95..eb18a4cd6 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -299,6 +299,7 @@ typedef unsigned char u_char;
|
||||
#define KRB5_CONF_V4_INSTANCE_CONVERT "v4_instance_convert"
|
||||
#define KRB5_CONF_V4_REALM "v4_realm"
|
||||
#define KRB5_CONF_VERIFY_AP_REQ_NOFAIL "verify_ap_req_nofail"
|
||||
+#define KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS "client_aware_channel_bindings"
|
||||
|
||||
/* Cache configuration variables */
|
||||
#define KRB5_CC_CONF_FAST_AVAIL "fast_avail"
|
||||
diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c
|
||||
index 9fc6a0e52..08504860c 100644
|
||||
--- a/src/lib/krb5/krb/mk_req_ext.c
|
||||
+++ b/src/lib/krb5/krb/mk_req_ext.c
|
||||
@@ -68,10 +68,9 @@
|
||||
*/
|
||||
|
||||
static krb5_error_code
|
||||
-make_etype_list(krb5_context context,
|
||||
- krb5_enctype *desired_etypes,
|
||||
- krb5_enctype tkt_enctype,
|
||||
- krb5_authdata ***authdata);
|
||||
+make_ap_authdata(krb5_context context, krb5_enctype *desired_enctypes,
|
||||
+ krb5_enctype tkt_enctype, krb5_boolean client_aware_cb,
|
||||
+ krb5_authdata ***authdata_out);
|
||||
|
||||
static krb5_error_code
|
||||
generate_authenticator(krb5_context,
|
||||
@@ -263,7 +262,8 @@ generate_authenticator(krb5_context context, krb5_authenticator *authent,
|
||||
krb5_enctype tkt_enctype)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
- krb5_authdata **ext_authdata = NULL;
|
||||
+ krb5_authdata **ext_authdata = NULL, **ap_authdata, **combined;
|
||||
+ int client_aware_cb;
|
||||
|
||||
authent->client = client;
|
||||
authent->checksum = cksum;
|
||||
@@ -297,99 +297,104 @@ generate_authenticator(krb5_context context, krb5_authenticator *authent,
|
||||
krb5_free_authdata(context, ext_authdata);
|
||||
}
|
||||
|
||||
- /* Only send EtypeList if we prefer another enctype to tkt_enctype */
|
||||
- if (desired_etypes != NULL && desired_etypes[0] != tkt_enctype) {
|
||||
- TRACE_MK_REQ_ETYPES(context, desired_etypes);
|
||||
- retval = make_etype_list(context, desired_etypes, tkt_enctype,
|
||||
- &authent->authorization_data);
|
||||
+ retval = profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS,
|
||||
+ KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS, NULL,
|
||||
+ FALSE, &client_aware_cb);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+
|
||||
+ /* Add etype negotiation or channel-binding awareness authdata to the
|
||||
+ * front, if appropriate. */
|
||||
+ retval = make_ap_authdata(context, desired_etypes, tkt_enctype,
|
||||
+ client_aware_cb, &ap_authdata);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+ if (ap_authdata != NULL) {
|
||||
+ retval = krb5_merge_authdata(context, ap_authdata,
|
||||
+ authent->authorization_data, &combined);
|
||||
+ krb5_free_authdata(context, ap_authdata);
|
||||
if (retval)
|
||||
return retval;
|
||||
+ krb5_free_authdata(context, authent->authorization_data);
|
||||
+ authent->authorization_data = combined;
|
||||
}
|
||||
|
||||
return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));
|
||||
}
|
||||
|
||||
-/* RFC 4537 */
|
||||
+/* Set *out to a DER-encoded RFC 4537 etype list, or to NULL if no etype list
|
||||
+ * should be sent. */
|
||||
static krb5_error_code
|
||||
-make_etype_list(krb5_context context,
|
||||
- krb5_enctype *desired_etypes,
|
||||
- krb5_enctype tkt_enctype,
|
||||
- krb5_authdata ***authdata)
|
||||
+make_etype_list(krb5_context context, krb5_enctype *desired_enctypes,
|
||||
+ krb5_enctype tkt_enctype, krb5_data **out)
|
||||
{
|
||||
- krb5_error_code code;
|
||||
- krb5_etype_list etypes;
|
||||
- krb5_data *enc_etype_list;
|
||||
- krb5_data *ad_if_relevant;
|
||||
- krb5_authdata *etype_adata[2], etype_adatum, **adata;
|
||||
- int i;
|
||||
+ krb5_etype_list etlist;
|
||||
+ int count;
|
||||
|
||||
- etypes.etypes = desired_etypes;
|
||||
+ *out = NULL;
|
||||
|
||||
- for (etypes.length = 0;
|
||||
- etypes.etypes[etypes.length] != ENCTYPE_NULL;
|
||||
- etypes.length++)
|
||||
- {
|
||||
- /*
|
||||
- * RFC 4537:
|
||||
- *
|
||||
- * If the enctype of the ticket session key is included in the enctype
|
||||
- * list sent by the client, it SHOULD be the last on the list;
|
||||
- */
|
||||
- if (etypes.length && etypes.etypes[etypes.length - 1] == tkt_enctype)
|
||||
+ /* Only send a list if we prefer another enctype to tkt_enctype. */
|
||||
+ if (desired_enctypes == NULL || desired_enctypes[0] == tkt_enctype)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Count elements of desired_etypes, stopping at tkt_enctypes if present.
|
||||
+ * (Per RFC 4537, it must be the last option if it is included.) */
|
||||
+ for (count = 0; desired_enctypes[count] != ENCTYPE_NULL; count++) {
|
||||
+ if (count > 0 && desired_enctypes[count - 1] == tkt_enctype)
|
||||
break;
|
||||
}
|
||||
|
||||
- code = encode_krb5_etype_list(&etypes, &enc_etype_list);
|
||||
- if (code) {
|
||||
- return code;
|
||||
- }
|
||||
-
|
||||
- etype_adatum.magic = KV5M_AUTHDATA;
|
||||
- etype_adatum.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION;
|
||||
- etype_adatum.length = enc_etype_list->length;
|
||||
- etype_adatum.contents = (krb5_octet *)enc_etype_list->data;
|
||||
-
|
||||
- etype_adata[0] = &etype_adatum;
|
||||
- etype_adata[1] = NULL;
|
||||
-
|
||||
- /* Wrap in AD-IF-RELEVANT container */
|
||||
- code = encode_krb5_authdata(etype_adata, &ad_if_relevant);
|
||||
- if (code) {
|
||||
- krb5_free_data(context, enc_etype_list);
|
||||
- return code;
|
||||
- }
|
||||
-
|
||||
- krb5_free_data(context, enc_etype_list);
|
||||
-
|
||||
- adata = *authdata;
|
||||
- if (adata == NULL) {
|
||||
- adata = (krb5_authdata **)calloc(2, sizeof(krb5_authdata *));
|
||||
- i = 0;
|
||||
- } else {
|
||||
- for (i = 0; adata[i] != NULL; i++)
|
||||
- ;
|
||||
-
|
||||
- adata = (krb5_authdata **)realloc(*authdata,
|
||||
- (i + 2) * sizeof(krb5_authdata *));
|
||||
- }
|
||||
- if (adata == NULL) {
|
||||
- krb5_free_data(context, ad_if_relevant);
|
||||
- return ENOMEM;
|
||||
- }
|
||||
- *authdata = adata;
|
||||
-
|
||||
- adata[i] = (krb5_authdata *)malloc(sizeof(krb5_authdata));
|
||||
- if (adata[i] == NULL) {
|
||||
- krb5_free_data(context, ad_if_relevant);
|
||||
- return ENOMEM;
|
||||
- }
|
||||
- adata[i]->magic = KV5M_AUTHDATA;
|
||||
- adata[i]->ad_type = KRB5_AUTHDATA_IF_RELEVANT;
|
||||
- adata[i]->length = ad_if_relevant->length;
|
||||
- adata[i]->contents = (krb5_octet *)ad_if_relevant->data;
|
||||
- free(ad_if_relevant); /* contents owned by adata[i] */
|
||||
-
|
||||
- adata[i + 1] = NULL;
|
||||
-
|
||||
- return 0;
|
||||
+ etlist.etypes = desired_enctypes;
|
||||
+ etlist.length = count;
|
||||
+ return encode_krb5_etype_list(&etlist, out);
|
||||
+}
|
||||
+
|
||||
+/* Set *authdata_out to appropriate authenticator authdata for the request,
|
||||
+ * encoded in a single AD_IF_RELEVANT element. */
|
||||
+static krb5_error_code
|
||||
+make_ap_authdata(krb5_context context, krb5_enctype *desired_enctypes,
|
||||
+ krb5_enctype tkt_enctype, krb5_boolean client_aware_cb,
|
||||
+ krb5_authdata ***authdata_out)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_authdata etypes_ad, flags_ad, *list[3];
|
||||
+ krb5_data *der_etypes = NULL;
|
||||
+ size_t count = 0;
|
||||
+ uint8_t flagbuf[4];
|
||||
+ const uint32_t KERB_AP_OPTIONS_CBT = 0x4000;
|
||||
+
|
||||
+ *authdata_out = NULL;
|
||||
+
|
||||
+ /* Include an ETYPE_NEGOTIATION element if appropriate. */
|
||||
+ ret = make_etype_list(context, desired_enctypes, tkt_enctype, &der_etypes);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ if (der_etypes != NULL) {
|
||||
+ etypes_ad.magic = KV5M_AUTHDATA;
|
||||
+ etypes_ad.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION;
|
||||
+ etypes_ad.length = der_etypes->length;
|
||||
+ etypes_ad.contents = (uint8_t *)der_etypes->data;
|
||||
+ list[count++] = &etypes_ad;
|
||||
+ }
|
||||
+
|
||||
+ /* Include an AP_OPTIONS element if the CBT flag is configured. */
|
||||
+ if (client_aware_cb != 0) {
|
||||
+ store_32_le(KERB_AP_OPTIONS_CBT, flagbuf);
|
||||
+ flags_ad.magic = KV5M_AUTHDATA;
|
||||
+ flags_ad.ad_type = KRB5_AUTHDATA_AP_OPTIONS;
|
||||
+ flags_ad.length = 4;
|
||||
+ flags_ad.contents = flagbuf;
|
||||
+ list[count++] = &flags_ad;
|
||||
+ }
|
||||
+
|
||||
+ if (count > 0) {
|
||||
+ list[count] = NULL;
|
||||
+ ret = krb5_encode_authdata_container(context,
|
||||
+ KRB5_AUTHDATA_IF_RELEVANT,
|
||||
+ list, authdata_out);
|
||||
+ }
|
||||
+
|
||||
+cleanup:
|
||||
+ krb5_free_data(context, der_etypes);
|
||||
+ return ret;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
From d003b4aa8dce14967725d6607c54ceb884b3647c Mon Sep 17 00:00:00 2001
|
||||
From 07179e38e5ee72e82ebc77a1c8d73e34905268b7 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Wed, 27 May 2020 18:48:35 -0400
|
||||
Subject: [PATCH] Default dns_canonicalize_hostname to "fallback"
|
||||
|
91
Implement-GSS_C_CHANNEL_BOUND_FLAG.patch
Normal file
91
Implement-GSS_C_CHANNEL_BOUND_FLAG.patch
Normal file
@ -0,0 +1,91 @@
|
||||
From 3ea1d6296ced3a998e79356f9be212e4c5e6a5d5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Scheel <ascheel@redhat.com>
|
||||
Date: Wed, 5 Jul 2017 11:38:30 -0400
|
||||
Subject: [PATCH] Implement GSS_C_CHANNEL_BOUND_FLAG
|
||||
|
||||
Define a new channel-bound GSS return flag, and set it in the krb5
|
||||
mech if the initiator sent channel bindings matching the acceptor's.
|
||||
Do not error out if the acceptor specifies channel bindings and the
|
||||
initiator does not send them.
|
||||
|
||||
[ghudson@mit.edu: simplified code changes; fleshed out commit message]
|
||||
|
||||
[iboukris: cherry-picked from another PR and reduced in scope]
|
||||
|
||||
ticket: 8899 (new)
|
||||
(cherry picked from commit 429a31146083fac21958631c2af572b08ec91022)
|
||||
---
|
||||
src/lib/gssapi/generic/gssapi_ext.h | 2 ++
|
||||
src/lib/gssapi/krb5/accept_sec_context.c | 18 +++++++++++++-----
|
||||
2 files changed, 15 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
|
||||
index 218456e44..c675e8ebb 100644
|
||||
--- a/src/lib/gssapi/generic/gssapi_ext.h
|
||||
+++ b/src/lib/gssapi/generic/gssapi_ext.h
|
||||
@@ -595,6 +595,8 @@ gss_store_cred_into(
|
||||
* attribute (along with any applicable RFC 5587 attributes).
|
||||
*/
|
||||
|
||||
+#define GSS_C_CHANNEL_BOUND_FLAG 2048 /* 0x00000800 */
|
||||
+
|
||||
OM_uint32 KRB5_CALLCONV
|
||||
gssspi_query_meta_data(
|
||||
OM_uint32 *minor_status,
|
||||
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
index 70dd7fc0c..9d3e2f4fe 100644
|
||||
--- a/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
@@ -427,6 +427,9 @@ kg_process_extension(krb5_context context,
|
||||
GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE | \
|
||||
GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG)
|
||||
|
||||
+/* A zero-value channel binding, for comparison */
|
||||
+static const uint8_t null_cb[CB_MD5_LEN];
|
||||
+
|
||||
/*
|
||||
* The krb5 GSS mech appropriates the authenticator checksum field from RFC
|
||||
* 4120 to store structured data instead of a checksum, indicated with checksum
|
||||
@@ -435,9 +438,10 @@ kg_process_extension(krb5_context context,
|
||||
*
|
||||
* Interpret the checksum. Read delegated creds into *deleg_out if it is not
|
||||
* NULL. Set *flags_out to the allowed subset of token flags, plus
|
||||
- * GSS_C_DELEG_FLAG if a delegated credential was present. Process any
|
||||
- * extensions found using exts. On error, set *code_out to a krb5_error code
|
||||
- * for use as a minor status value.
|
||||
+ * GSS_C_DELEG_FLAG if a delegated credential was present and
|
||||
+ * GSS_C_CHANNEL_BOUND_FLAG if matching channel bindings are present. Process
|
||||
+ * any extensions found using exts. On error, set *code_out to a krb5_error
|
||||
+ * code for use as a minor status value.
|
||||
*/
|
||||
static OM_uint32
|
||||
process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
@@ -450,7 +454,7 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
krb5_error_code code = 0;
|
||||
OM_uint32 status, option_id, token_flags;
|
||||
size_t cb_len, option_len;
|
||||
- krb5_boolean valid;
|
||||
+ krb5_boolean valid, token_cb_present = FALSE, cb_match = FALSE;
|
||||
krb5_key subkey;
|
||||
krb5_data option, empty = empty_data();
|
||||
krb5_checksum cb_cksum;
|
||||
@@ -516,7 +520,9 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
goto fail;
|
||||
}
|
||||
assert(cb_cksum.length == cb_len);
|
||||
- if (k5_bcmp(token_cb, cb_cksum.contents, cb_len) != 0) {
|
||||
+ token_cb_present = (k5_bcmp(token_cb, null_cb, cb_len) != 0);
|
||||
+ cb_match = (k5_bcmp(token_cb, cb_cksum.contents, cb_len) == 0);
|
||||
+ if (token_cb_present && !cb_match) {
|
||||
status = GSS_S_BAD_BINDINGS;
|
||||
goto fail;
|
||||
}
|
||||
@@ -525,6 +531,8 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
/* Read the token flags and accept some of them as context flags. */
|
||||
token_flags = k5_input_get_uint32_le(&in);
|
||||
*flags_out = token_flags & INITIATOR_FLAGS;
|
||||
+ if (cb_match)
|
||||
+ *flags_out |= GSS_C_CHANNEL_BOUND_FLAG;
|
||||
|
||||
/* Read the delegated credential if present. */
|
||||
if (in.len >= 4 && (token_flags & GSS_C_DELEG_FLAG)) {
|
102
Implement-KERB_AP_OPTIONS_CBT-server-side.patch
Normal file
102
Implement-KERB_AP_OPTIONS_CBT-server-side.patch
Normal file
@ -0,0 +1,102 @@
|
||||
From 6407bf087fe53088d91efd09df736e979cd4e8db Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Mon, 9 Mar 2020 16:04:21 +0100
|
||||
Subject: [PATCH] Implement KERB_AP_OPTIONS_CBT (server side)
|
||||
|
||||
Add server support for Microsoft's KERB_AP_OPTIONS_CBT as described in
|
||||
MS-KILE. If the client includes the AP option in the authenticator
|
||||
authdata and the server passed channel bindings, require the bindings
|
||||
to match.
|
||||
|
||||
[ghudson@mit.edu: refactored to put more logic in the helper function;
|
||||
added a comment; clarified commit message]
|
||||
|
||||
ticket: 8900 (new)
|
||||
(cherry picked from commit 4f7c77b64a048ca5e3199b26b31493698c777a9c)
|
||||
---
|
||||
src/include/krb5/krb5.hin | 1 +
|
||||
src/lib/gssapi/krb5/accept_sec_context.c | 45 +++++++++++++++++++++++-
|
||||
2 files changed, 45 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||
index f8269fb17..9264bede1 100644
|
||||
--- a/src/include/krb5/krb5.hin
|
||||
+++ b/src/include/krb5/krb5.hin
|
||||
@@ -1915,6 +1915,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
|
||||
#define KRB5_AUTHDATA_SIGNTICKET 512 /**< formerly 142 in krb5 1.8 */
|
||||
#define KRB5_AUTHDATA_FX_ARMOR 71
|
||||
#define KRB5_AUTHDATA_AUTH_INDICATOR 97
|
||||
+#define KRB5_AUTHDATA_AP_OPTIONS 143
|
||||
/** @} */ /* end of KRB5_AUTHDATA group */
|
||||
|
||||
/* password change constants */
|
||||
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
index 9d3e2f4fe..175a24c4e 100644
|
||||
--- a/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
@@ -430,6 +430,32 @@ kg_process_extension(krb5_context context,
|
||||
/* A zero-value channel binding, for comparison */
|
||||
static const uint8_t null_cb[CB_MD5_LEN];
|
||||
|
||||
+/* Look for AP_OPTIONS in authdata. If present and the options include
|
||||
+ * KERB_AP_OPTIONS_CBT, set *cbt_out to true. */
|
||||
+static krb5_error_code
|
||||
+check_cbt(krb5_context context, krb5_authdata **authdata,
|
||||
+ krb5_boolean *cbt_out)
|
||||
+{
|
||||
+ krb5_error_code code;
|
||||
+ uint32_t ad_ap_options;
|
||||
+ const uint32_t KERB_AP_OPTIONS_CBT = 0x4000;
|
||||
+
|
||||
+ *cbt_out = FALSE;
|
||||
+
|
||||
+ code = krb5_find_authdata(context, NULL, authdata,
|
||||
+ KRB5_AUTHDATA_AP_OPTIONS, &authdata);
|
||||
+ if (code || authdata == NULL)
|
||||
+ return code;
|
||||
+ if (authdata[1] != NULL || authdata[0]->length != 4)
|
||||
+ return KRB5KRB_AP_ERR_MSG_TYPE;
|
||||
+
|
||||
+ ad_ap_options = load_32_le(authdata[0]->contents);
|
||||
+ if (ad_ap_options & KERB_AP_OPTIONS_CBT)
|
||||
+ *cbt_out = TRUE;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* The krb5 GSS mech appropriates the authenticator checksum field from RFC
|
||||
* 4120 to store structured data instead of a checksum, indicated with checksum
|
||||
@@ -454,7 +480,7 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
krb5_error_code code = 0;
|
||||
OM_uint32 status, option_id, token_flags;
|
||||
size_t cb_len, option_len;
|
||||
- krb5_boolean valid, token_cb_present = FALSE, cb_match = FALSE;
|
||||
+ krb5_boolean valid, client_cbt, token_cb_present = FALSE, cb_match = FALSE;
|
||||
krb5_key subkey;
|
||||
krb5_data option, empty = empty_data();
|
||||
krb5_checksum cb_cksum;
|
||||
@@ -582,6 +608,23 @@ process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
}
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * If the client asserts the KERB_AP_OPTIONS_CBT flag (from MS-KILE) in the
|
||||
+ * authenticator authdata, and the acceptor passed channel bindings,
|
||||
+ * require matching channel bindings from the client. The intent is to
|
||||
+ * prevent an authenticator generated for use outside of a TLS channel from
|
||||
+ * being used inside of one.
|
||||
+ */
|
||||
+ code = check_cbt(context, authenticator->authorization_data, &client_cbt);
|
||||
+ if (code) {
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (client_cbt && acceptor_cb != GSS_C_NO_CHANNEL_BINDINGS && !cb_match) {
|
||||
+ status = GSS_S_BAD_BINDINGS;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
status = GSS_S_COMPLETE;
|
||||
|
||||
fail:
|
30
Improve-negoex_parse_token-code-hygiene.patch
Normal file
30
Improve-negoex_parse_token-code-hygiene.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From c726a72c68244129eb08b840b92144acfa776573 Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Tue, 9 Jun 2020 16:23:37 -0400
|
||||
Subject: [PATCH] Improve negoex_parse_token() code hygiene
|
||||
|
||||
If the while loop in negoex_parse_token() runs for zero iterations,
|
||||
major will be used initialized. Currently this cannot happen, but
|
||||
only because both of the call sites check for zero-length tokens.
|
||||
Initialize major for safety.
|
||||
|
||||
[ghudson@mit.edu: rewrote commit message]
|
||||
|
||||
(cherry picked from commit 4f91b6f8fa6fe1de662b3fdac0d59b7758ec642a)
|
||||
---
|
||||
src/lib/gssapi/spnego/negoex_util.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/spnego/negoex_util.c b/src/lib/gssapi/spnego/negoex_util.c
|
||||
index 700368456..99580fd79 100644
|
||||
--- a/src/lib/gssapi/spnego/negoex_util.c
|
||||
+++ b/src/lib/gssapi/spnego/negoex_util.c
|
||||
@@ -454,7 +454,7 @@ negoex_parse_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx,
|
||||
gss_const_buffer_t token,
|
||||
struct negoex_message **messages_out, size_t *count_out)
|
||||
{
|
||||
- OM_uint32 major;
|
||||
+ OM_uint32 major = GSS_S_COMPLETE;
|
||||
size_t count = 0;
|
||||
struct k5input in;
|
||||
struct negoex_message *messages = NULL, *newptr;
|
@ -1,4 +1,4 @@
|
||||
From 086de78292b8ae89aba8a72926831124da44205d Mon Sep 17 00:00:00 2001
|
||||
From c36e826c70cb5b3bff8bd4371d47884cea30b3f4 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Sat, 6 Jun 2020 11:03:37 +0200
|
||||
Subject: [PATCH] Omit PA_FOR_USER if we can't compute its checksum
|
||||
|
@ -1,4 +1,4 @@
|
||||
From dd82ae2d390c4de1b8a7737a918d80d6829366dd Mon Sep 17 00:00:00 2001
|
||||
From ee79bd43005245d3e5a2d3ec6d61146945e77717 Mon Sep 17 00:00:00 2001
|
||||
From: Isaac Boukris <iboukris@gmail.com>
|
||||
Date: Tue, 28 Apr 2020 18:15:55 +0200
|
||||
Subject: [PATCH] Pass channel bindings through SPNEGO
|
||||
|
479
Refactor-krb5-GSS-checksum-handling.patch
Normal file
479
Refactor-krb5-GSS-checksum-handling.patch
Normal file
@ -0,0 +1,479 @@
|
||||
From a34b7c50e62c19f80d39ece6a72017dac781df64 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Scheel <ascheel@redhat.com>
|
||||
Date: Fri, 30 Jun 2017 16:03:01 -0400
|
||||
Subject: [PATCH] Refactor krb5 GSS checksum handling
|
||||
|
||||
Separate out checksum handling from kg_accept_krb5() into a new helper
|
||||
process_checksum().
|
||||
|
||||
[ghudson@mit.edu: simplified checksum processing and made it use
|
||||
k5-input.h instead of TREAD_ macros; moved more flag handling into
|
||||
helper]
|
||||
|
||||
[iboukris: adjusted helper function arguments, allowing access to the
|
||||
full authenticator for subsequent changes]
|
||||
|
||||
(cherry picked from commit 64d56233f9816a2a93f6e8d3030c8ed6ce397735)
|
||||
[rharwood@redhat.com: problem with typo fix commit, I think]
|
||||
---
|
||||
src/lib/gssapi/krb5/accept_sec_context.c | 383 +++++++++++------------
|
||||
1 file changed, 179 insertions(+), 204 deletions(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
index c5bddb1e8..70dd7fc0c 100644
|
||||
--- a/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
|
||||
@@ -98,6 +98,7 @@
|
||||
*/
|
||||
|
||||
#include "k5-int.h"
|
||||
+#include "k5-input.h"
|
||||
#include "gssapiP_krb5.h"
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
@@ -413,6 +414,174 @@ kg_process_extension(krb5_context context,
|
||||
return code;
|
||||
}
|
||||
|
||||
+/* The length of the MD5 channel bindings in an 0x8003 checksum */
|
||||
+#define CB_MD5_LEN 16
|
||||
+
|
||||
+/* The minimum length of an 0x8003 checksum value (4-byte channel bindings
|
||||
+ * length, 16-byte channel bindings, 4-byte flags) */
|
||||
+#define MIN_8003_LEN (4 + CB_MD5_LEN + 4)
|
||||
+
|
||||
+/* The flags we accept from the initiator's authenticator checksum. */
|
||||
+#define INITIATOR_FLAGS (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | \
|
||||
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \
|
||||
+ GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE | \
|
||||
+ GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG)
|
||||
+
|
||||
+/*
|
||||
+ * The krb5 GSS mech appropriates the authenticator checksum field from RFC
|
||||
+ * 4120 to store structured data instead of a checksum, indicated with checksum
|
||||
+ * type 0x8003 (see RFC 4121 section 4.1.1). Some implementations instead send
|
||||
+ * no checksum, or a regular checksum over empty data.
|
||||
+ *
|
||||
+ * Interpret the checksum. Read delegated creds into *deleg_out if it is not
|
||||
+ * NULL. Set *flags_out to the allowed subset of token flags, plus
|
||||
+ * GSS_C_DELEG_FLAG if a delegated credential was present. Process any
|
||||
+ * extensions found using exts. On error, set *code_out to a krb5_error code
|
||||
+ * for use as a minor status value.
|
||||
+ */
|
||||
+static OM_uint32
|
||||
+process_checksum(OM_uint32 *minor_status, krb5_context context,
|
||||
+ gss_channel_bindings_t acceptor_cb,
|
||||
+ krb5_auth_context auth_context, krb5_flags ap_req_options,
|
||||
+ krb5_authenticator *authenticator, krb5_gss_ctx_ext_t exts,
|
||||
+ krb5_gss_cred_id_t *deleg_out, krb5_ui_4 *flags_out,
|
||||
+ krb5_error_code *code_out)
|
||||
+{
|
||||
+ krb5_error_code code = 0;
|
||||
+ OM_uint32 status, option_id, token_flags;
|
||||
+ size_t cb_len, option_len;
|
||||
+ krb5_boolean valid;
|
||||
+ krb5_key subkey;
|
||||
+ krb5_data option, empty = empty_data();
|
||||
+ krb5_checksum cb_cksum;
|
||||
+ const uint8_t *token_cb, *option_bytes;
|
||||
+ struct k5input in;
|
||||
+ const krb5_checksum *cksum = authenticator->checksum;
|
||||
+
|
||||
+ cb_cksum.contents = NULL;
|
||||
+
|
||||
+ if (cksum == NULL) {
|
||||
+ /*
|
||||
+ * Some SMB client implementations use handcrafted GSSAPI code that
|
||||
+ * does not provide a checksum. MS-KILE documents that the Microsoft
|
||||
+ * implementation considers a missing checksum acceptable; the server
|
||||
+ * assumes all flags are unset in this case, and does not check channel
|
||||
+ * bindings.
|
||||
+ */
|
||||
+ *flags_out = 0;
|
||||
+ } else if (cksum->checksum_type != CKSUMTYPE_KG_CB) {
|
||||
+ /* Samba sends a regular checksum. */
|
||||
+ code = krb5_auth_con_getkey_k(context, auth_context, &subkey);
|
||||
+ if (code) {
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Verifying the checksum ensures that this authenticator wasn't
|
||||
+ * replayed from one with a checksum over actual data. */
|
||||
+ code = krb5_k_verify_checksum(context, subkey,
|
||||
+ KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, &empty,
|
||||
+ cksum, &valid);
|
||||
+ krb5_k_free_key(context, subkey);
|
||||
+ if (code || !valid) {
|
||||
+ status = GSS_S_BAD_SIG;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Use ap_options from the request to guess the mutual flag. */
|
||||
+ *flags_out = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
|
||||
+ if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED)
|
||||
+ *flags_out |= GSS_C_MUTUAL_FLAG;
|
||||
+ } else {
|
||||
+ /* The checksum must contain at least a fixed 24-byte part. */
|
||||
+ if (cksum->length < MIN_8003_LEN) {
|
||||
+ status = GSS_S_BAD_BINDINGS;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ k5_input_init(&in, cksum->contents, cksum->length);
|
||||
+ cb_len = k5_input_get_uint32_le(&in);
|
||||
+ if (cb_len != CB_MD5_LEN) {
|
||||
+ code = KG_BAD_LENGTH;
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ token_cb = k5_input_get_bytes(&in, cb_len);
|
||||
+ if (acceptor_cb != GSS_C_NO_CHANNEL_BINDINGS) {
|
||||
+ code = kg_checksum_channel_bindings(context, acceptor_cb,
|
||||
+ &cb_cksum);
|
||||
+ if (code) {
|
||||
+ status = GSS_S_BAD_BINDINGS;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ assert(cb_cksum.length == cb_len);
|
||||
+ if (k5_bcmp(token_cb, cb_cksum.contents, cb_len) != 0) {
|
||||
+ status = GSS_S_BAD_BINDINGS;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Read the token flags and accept some of them as context flags. */
|
||||
+ token_flags = k5_input_get_uint32_le(&in);
|
||||
+ *flags_out = token_flags & INITIATOR_FLAGS;
|
||||
+
|
||||
+ /* Read the delegated credential if present. */
|
||||
+ if (in.len >= 4 && (token_flags & GSS_C_DELEG_FLAG)) {
|
||||
+ option_id = k5_input_get_uint16_le(&in);
|
||||
+ option_len = k5_input_get_uint16_le(&in);
|
||||
+ option_bytes = k5_input_get_bytes(&in, option_len);
|
||||
+ option = make_data((uint8_t *)option_bytes, option_len);
|
||||
+ if (in.status) {
|
||||
+ code = KG_BAD_LENGTH;
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Store the delegated credential. */
|
||||
+ code = rd_and_store_for_creds(context, auth_context, &option,
|
||||
+ deleg_out);
|
||||
+ if (code) {
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ *flags_out |= GSS_C_DELEG_FLAG;
|
||||
+ }
|
||||
+
|
||||
+ /* Process any extensions at the end of the checksum. Extensions use
|
||||
+ * 4-byte big-endian tag and length instead of 2-byte little-endian. */
|
||||
+ while (in.len > 0) {
|
||||
+ option_id = k5_input_get_uint32_be(&in);
|
||||
+ option_len = k5_input_get_uint32_be(&in);
|
||||
+ option_bytes = k5_input_get_bytes(&in, option_len);
|
||||
+ option = make_data((uint8_t *)option_bytes, option_len);
|
||||
+ if (in.status) {
|
||||
+ code = KG_BAD_LENGTH;
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ code = kg_process_extension(context, auth_context, option_id,
|
||||
+ &option, exts);
|
||||
+ if (code) {
|
||||
+ status = GSS_S_FAILURE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ status = GSS_S_COMPLETE;
|
||||
+
|
||||
+fail:
|
||||
+ free(cb_cksum.contents);
|
||||
+ *code_out = code;
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
static OM_uint32
|
||||
kg_accept_krb5(minor_status, context_handle,
|
||||
verifier_cred_handle, input_token,
|
||||
@@ -433,17 +602,13 @@ kg_accept_krb5(minor_status, context_handle,
|
||||
krb5_gss_ctx_ext_t exts;
|
||||
{
|
||||
krb5_context context;
|
||||
- unsigned char *ptr, *ptr2;
|
||||
+ unsigned char *ptr;
|
||||
char *sptr;
|
||||
- OM_uint32 tmp;
|
||||
- size_t md5len;
|
||||
krb5_gss_cred_id_t cred = 0;
|
||||
krb5_data ap_rep, ap_req;
|
||||
- unsigned int i;
|
||||
krb5_error_code code;
|
||||
krb5_address addr, *paddr;
|
||||
krb5_authenticator *authdat = 0;
|
||||
- krb5_checksum reqcksum;
|
||||
krb5_gss_name_t name = NULL;
|
||||
krb5_ui_4 gss_flags = 0;
|
||||
krb5_gss_ctx_id_rec *ctx = NULL;
|
||||
@@ -451,8 +616,6 @@ kg_accept_krb5(minor_status, context_handle,
|
||||
gss_buffer_desc token;
|
||||
krb5_auth_context auth_context = NULL;
|
||||
krb5_ticket * ticket = NULL;
|
||||
- int option_id;
|
||||
- krb5_data option;
|
||||
const gss_OID_desc *mech_used = NULL;
|
||||
OM_uint32 major_status = GSS_S_FAILURE;
|
||||
OM_uint32 tmp_minor_status;
|
||||
@@ -463,7 +626,6 @@ kg_accept_krb5(minor_status, context_handle,
|
||||
krb5int_access kaccess;
|
||||
int cred_rcache = 0;
|
||||
int no_encap = 0;
|
||||
- int token_deleg_flag = 0;
|
||||
krb5_flags ap_req_options = 0;
|
||||
krb5_enctype negotiated_etype;
|
||||
krb5_authdata_context ad_context = NULL;
|
||||
@@ -489,7 +651,6 @@ kg_accept_krb5(minor_status, context_handle,
|
||||
output_token->length = 0;
|
||||
output_token->value = NULL;
|
||||
token.value = 0;
|
||||
- reqcksum.contents = 0;
|
||||
ap_req.data = 0;
|
||||
ap_rep.data = 0;
|
||||
|
||||
@@ -654,195 +815,16 @@ kg_accept_krb5(minor_status, context_handle,
|
||||
|
||||
krb5_auth_con_getauthenticator(context, auth_context, &authdat);
|
||||
|
||||
- if (authdat->checksum == NULL) {
|
||||
- /*
|
||||
- * Some SMB client implementations use handcrafted GSSAPI code that
|
||||
- * does not provide a checksum. MS-KILE documents that the Microsoft
|
||||
- * implementation considers a missing checksum acceptable; the server
|
||||
- * assumes all flags are unset in this case, and does not check channel
|
||||
- * bindings.
|
||||
- */
|
||||
- gss_flags = 0;
|
||||
- } else if (authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) {
|
||||
- /* Samba does not send 0x8003 GSS-API checksums */
|
||||
- krb5_boolean valid;
|
||||
- krb5_key subkey;
|
||||
- krb5_data zero;
|
||||
+ major_status = process_checksum(minor_status, context, input_chan_bindings,
|
||||
+ auth_context, ap_req_options,
|
||||
+ authdat, exts,
|
||||
+ delegated_cred_handle ? &deleg_cred : NULL,
|
||||
+ &gss_flags, &code);
|
||||
|
||||
- code = krb5_auth_con_getkey_k(context, auth_context, &subkey);
|
||||
- if (code) {
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
+ if (major_status != GSS_S_COMPLETE)
|
||||
+ goto fail;
|
||||
|
||||
- zero.length = 0;
|
||||
- zero.data = "";
|
||||
-
|
||||
- code = krb5_k_verify_checksum(context,
|
||||
- subkey,
|
||||
- KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
|
||||
- &zero,
|
||||
- authdat->checksum,
|
||||
- &valid);
|
||||
- krb5_k_free_key(context, subkey);
|
||||
- if (code || !valid) {
|
||||
- major_status = GSS_S_BAD_SIG;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- /* Use ap_options from the request to guess the mutual flag. */
|
||||
- gss_flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
|
||||
- if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED)
|
||||
- gss_flags |= GSS_C_MUTUAL_FLAG;
|
||||
- } else {
|
||||
- /* gss krb5 v1 */
|
||||
-
|
||||
- /* stash this now, for later. */
|
||||
- code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &md5len);
|
||||
- if (code) {
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- /* verify that the checksum is correct */
|
||||
-
|
||||
- /*
|
||||
- The checksum may be either exactly 24 bytes, in which case
|
||||
- no options are specified, or greater than 24 bytes, in which case
|
||||
- one or more options are specified. Currently, the only valid
|
||||
- option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
|
||||
- */
|
||||
-
|
||||
- if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
|
||||
- (authdat->checksum->length < 24)) {
|
||||
- code = 0;
|
||||
- major_status = GSS_S_BAD_BINDINGS;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- ptr = (unsigned char *) authdat->checksum->contents;
|
||||
-
|
||||
- TREAD_INT(ptr, tmp, 0);
|
||||
-
|
||||
- if (tmp != md5len) {
|
||||
- code = KG_BAD_LENGTH;
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- The following section of code attempts to implement the
|
||||
- optional channel binding facility as described in RFC2743.
|
||||
-
|
||||
- Since this facility is optional channel binding may or may
|
||||
- not have been provided by either the client or the server.
|
||||
-
|
||||
- If the server has specified input_chan_bindings equal to
|
||||
- GSS_C_NO_CHANNEL_BINDINGS then we skip the check. If
|
||||
- the server does provide channel bindings then we compute
|
||||
- a checksum and compare against those provided by the
|
||||
- client. */
|
||||
-
|
||||
- if ((code = kg_checksum_channel_bindings(context,
|
||||
- input_chan_bindings,
|
||||
- &reqcksum))) {
|
||||
- major_status = GSS_S_BAD_BINDINGS;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- /* Always read the clients bindings - eventhough we might ignore them */
|
||||
- TREAD_STR(ptr, ptr2, reqcksum.length);
|
||||
-
|
||||
- if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) {
|
||||
- if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
|
||||
- xfree(reqcksum.contents);
|
||||
- reqcksum.contents = 0;
|
||||
- code = 0;
|
||||
- major_status = GSS_S_BAD_BINDINGS;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- }
|
||||
-
|
||||
- xfree(reqcksum.contents);
|
||||
- reqcksum.contents = 0;
|
||||
-
|
||||
- /* Read the token flags. Remember if GSS_C_DELEG_FLAG was set, but
|
||||
- * mask it out until we actually read a delegated credential. */
|
||||
- TREAD_INT(ptr, gss_flags, 0);
|
||||
- token_deleg_flag = (gss_flags & GSS_C_DELEG_FLAG);
|
||||
- gss_flags &= ~GSS_C_DELEG_FLAG;
|
||||
-
|
||||
- /* if the checksum length > 24, there are options to process */
|
||||
-
|
||||
- i = authdat->checksum->length - 24;
|
||||
- if (i && token_deleg_flag) {
|
||||
- if (i >= 4) {
|
||||
- TREAD_INT16(ptr, option_id, 0);
|
||||
- TREAD_INT16(ptr, option.length, 0);
|
||||
- i -= 4;
|
||||
-
|
||||
- if (i < option.length) {
|
||||
- code = KG_BAD_LENGTH;
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- /* have to use ptr2, since option.data is wrong type and
|
||||
- macro uses ptr as both lvalue and rvalue */
|
||||
-
|
||||
- TREAD_STR(ptr, ptr2, option.length);
|
||||
- option.data = (char *) ptr2;
|
||||
-
|
||||
- i -= option.length;
|
||||
-
|
||||
- if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- /* store the delegated credential */
|
||||
-
|
||||
- code = rd_and_store_for_creds(context, auth_context, &option,
|
||||
- (delegated_cred_handle) ?
|
||||
- &deleg_cred : NULL);
|
||||
- if (code) {
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- gss_flags |= GSS_C_DELEG_FLAG;
|
||||
- } /* if i >= 4 */
|
||||
- /* ignore any additional trailing data, for now */
|
||||
- }
|
||||
- while (i > 0) {
|
||||
- /* Process Type-Length-Data options */
|
||||
- if (i < 8) {
|
||||
- code = KG_BAD_LENGTH;
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
- TREAD_INT(ptr, option_id, 1);
|
||||
- TREAD_INT(ptr, option.length, 1);
|
||||
- i -= 8;
|
||||
- if (i < option.length) {
|
||||
- code = KG_BAD_LENGTH;
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
- TREAD_STR(ptr, ptr2, option.length);
|
||||
- option.data = (char *)ptr2;
|
||||
-
|
||||
- i -= option.length;
|
||||
-
|
||||
- code = kg_process_extension(context, auth_context,
|
||||
- option_id, &option, exts);
|
||||
- if (code != 0) {
|
||||
- major_status = GSS_S_FAILURE;
|
||||
- goto fail;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ major_status = GSS_S_FAILURE;
|
||||
|
||||
if (exts->iakerb.conv && !exts->iakerb.verified) {
|
||||
major_status = GSS_S_BAD_SIG;
|
||||
@@ -869,12 +851,7 @@ kg_accept_krb5(minor_status, context_handle,
|
||||
ctx->mech_used = (gss_OID) mech_used;
|
||||
ctx->auth_context = auth_context;
|
||||
ctx->initiate = 0;
|
||||
- ctx->gss_flags = (GSS_C_TRANS_FLAG |
|
||||
- ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
|
||||
- GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
|
||||
- GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG |
|
||||
- GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG |
|
||||
- GSS_C_EXTENDED_ERROR_FLAG)));
|
||||
+ ctx->gss_flags = gss_flags | GSS_C_TRANS_FLAG;
|
||||
ctx->seed_init = 0;
|
||||
ctx->cred_rcache = cred_rcache;
|
||||
|
||||
@@ -1161,8 +1138,6 @@ fail:
|
||||
|
||||
krb5_auth_con_free(context, auth_context);
|
||||
}
|
||||
- if (reqcksum.contents)
|
||||
- xfree(reqcksum.contents);
|
||||
if (ap_rep.data)
|
||||
krb5_free_data_contents(context, &ap_rep);
|
||||
if (major_status == GSS_S_COMPLETE ||
|
@ -1,4 +1,4 @@
|
||||
From c21bb26abc4799298726124d73f0c968430a87bd Mon Sep 17 00:00:00 2001
|
||||
From 85bb5fe5a11708b78e9f0bd3a3b34999b6c888a7 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Thu, 28 May 2020 18:41:02 -0400
|
||||
Subject: [PATCH] Remove resolver test utility
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 5af211200d6c2ac82872435556f5b39edcaba541 Mon Sep 17 00:00:00 2001
|
||||
From a12fc355a034e5b1d23bdb23db9735d4eaa396d8 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Sat, 15 Feb 2020 20:34:23 -0500
|
||||
Subject: [PATCH] Replace gssrpc tests with a Python script
|
||||
|
13
krb5.spec
13
krb5.spec
@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
|
||||
Name: krb5
|
||||
Version: 1.18.2
|
||||
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
|
||||
Release: 7%{?dist}
|
||||
Release: 8%{?dist}
|
||||
|
||||
# rharwood has trust path to signing key and verifies on check-in
|
||||
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
|
||||
@ -56,11 +56,17 @@ Patch16: Do-expiration-warnings-for-all-init_creds-APIs.patch
|
||||
Patch17: Pass-gss_localname-through-SPNEGO.patch
|
||||
Patch18: Omit-KDC-indicator-check-for-S4U2Self-requests.patch
|
||||
Patch19: Fix-typo-in-in-in-the-ksu-man-page.patch
|
||||
Patch20: Pass-channel-bindings-through-SPNEGO.patch
|
||||
Patch21: Replace-gssrpc-tests-with-a-Python-script.patch
|
||||
Patch22: Default-dns_canonicalize_hostname-to-fallback.patch
|
||||
Patch23: Remove-resolver-test-utility.patch
|
||||
Patch24: Omit-PA_FOR_USER-if-we-can-t-compute-its-checksum.patch
|
||||
Patch25: Improve-negoex_parse_token-code-hygiene.patch
|
||||
Patch26: Refactor-krb5-GSS-checksum-handling.patch
|
||||
Patch27: Implement-GSS_C_CHANNEL_BOUND_FLAG.patch
|
||||
Patch28: Implement-KERB_AP_OPTIONS_CBT-server-side.patch
|
||||
Patch29: Add-client_aware_channel_bindings-option.patch
|
||||
Patch30: Pass-channel-bindings-through-SPNEGO.patch
|
||||
Patch31: Add-channel-bindings-tests.patch
|
||||
|
||||
License: MIT
|
||||
URL: https://web.mit.edu/kerberos/www/
|
||||
@ -615,6 +621,9 @@ exit 0
|
||||
%{_libdir}/libkadm5srv_mit.so.*
|
||||
|
||||
%changelog
|
||||
* Mon Jun 15 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-8
|
||||
- Match Heimdal behavior for channel bindings
|
||||
|
||||
* Mon Jun 08 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-7
|
||||
- Fix test suite by removing wrapper workarounds
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user