summaryrefslogtreecommitdiffstats
path: root/src/tests/gssapi
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2013-10-08 17:07:34 -0400
committerGreg Hudson <ghudson@mit.edu>2013-10-14 23:52:52 -0400
commitc547bc16f2ab6ee66c076ef944c3fbac8a66f5d4 (patch)
treee63cdbda0e8e88563c923a0e67dbf41e79b34078 /src/tests/gssapi
parente547a515f837a7c59c0fe73d192a374593b70263 (diff)
downloadkrb5-c547bc16f2ab6ee66c076ef944c3fbac8a66f5d4.tar.gz
krb5-c547bc16f2ab6ee66c076ef944c3fbac8a66f5d4.tar.xz
krb5-c547bc16f2ab6ee66c076ef944c3fbac8a66f5d4.zip
Fix gss_accept_sec_context error tokens
A GSS krb5 error response contains a KRB-ERROR message, which is required to have a server principal name, although few recipients actually use it. Starting in 1.3, accept_sec_context would fail to encode the error in the GSS_C_NO_NAME/GSS_C_NO_CREDENTIAL case (introduced by #1370) because cred->princ (which became cred->name->princ in 1.8) is unset. This problem got worse in 1.10 because we stopped setting the server field in all cases due to the changes for #6855. In 1.11 the problem got worse again when a misguided change to the mechglue started discarding output tokens when the mechanism returns an error; the mechglue should only do so when it itself causes the error. Fix krb5 gss_accept_sec_context by unconditionally decoding the AP-REQ and using krb5_rd_req_decoded, and then using the requested ticket server in the KRB-ERROR message. Fix the mechglue gss_accept_sec_context by reverting that part of commit 56feee187579905c9101b0cdbdd8c6a850adcfc9. Add a test program which artificially induces a replay cache failure (the easiest failure we can produce which has an associated RFC 4120 error code) and checks that this can be communicated back to the initiator via an error token. ticket: 1445 target_version: 1.12 tags: pullup
Diffstat (limited to 'src/tests/gssapi')
-rw-r--r--src/tests/gssapi/Makefile.in19
-rw-r--r--src/tests/gssapi/t_err.c121
-rwxr-xr-xsrc/tests/gssapi/t_gssapi.py4
3 files changed, 136 insertions, 8 deletions
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 5f554e19b8..0bf5bc8e05 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -4,7 +4,7 @@ DEFINES = -DUSE_AUTOCONF_H
SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
$(srcdir)/t_accname.c $(srcdir)/t_ccselect.c $(srcdir)/t_credstore.c \
- $(srcdir)/t_enctypes.c $(srcdir)/t_export_cred.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_inq_cred.c \
$(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \
@@ -13,14 +13,15 @@ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
$(srcdir)/t_spnego.c
OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_ccselect.o t_credstore.o \
- t_enctypes.o t_export_cred.o t_export_name.o t_gssexts.o t_imp_cred.o \
- t_imp_name.o t_inq_cred.o t_inq_mechs_name.o t_iov.o t_namingexts.o \
- t_oid.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o t_spnego.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_inq_cred.o t_inq_mechs_name.o t_iov.o \
+ t_namingexts.o t_oid.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \
+ t_spnego.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_ccselect t_credstore t_enctypes \
+all:: ccinit ccrefresh t_accname t_ccselect t_credstore t_enctypes t_err \
t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name \
t_inq_cred t_inq_mechs_name t_iov t_namingexts t_oid t_s4u \
t_s4u2proxy_krb5 t_saslname t_spnego
@@ -29,8 +30,8 @@ check-unix:: t_oid
$(RUN_SETUP) $(VALGRIND) ./t_oid
check-pytests:: ccinit ccrefresh t_accname t_ccselect t_credstore t_enctypes \
- t_export_cred t_export_name t_imp_cred t_inq_cred t_inq_mechs_name \
- t_iov t_s4u t_s4u2proxy_krb5 t_spnego
+ t_err t_export_cred t_export_name t_imp_cred t_inq_cred \
+ t_inq_mechs_name t_iov t_s4u t_s4u2proxy_krb5 t_spnego
$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS)
@@ -50,6 +51,8 @@ t_credstore: t_credstore.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_credstore.o $(COMMON_LIBS)
t_enctypes: t_enctypes.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_enctypes.o $(COMMON_LIBS)
+t_err: t_err.o $(COMMON_DEPS)
+ $(CC_LINK) -o $@ t_err.o $(COMMON_LIBS)
t_export_cred: t_export_cred.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_export_cred.o $(COMMON_LIBS)
t_export_name: t_export_name.o $(COMMON_DEPS)
@@ -81,6 +84,6 @@ t_spnego: t_spnego.o $(COMMON_DEPS)
clean::
$(RM) ccinit ccrefresh t_accname t_ccselect t_credstore t_enctypes
- $(RM) t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name
+ $(RM) t_err t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name
$(RM) t_inq_cred t_inq_mechs_name t_iov t_namingexts t_oid t_s4u
$(RM) t_s4u2proxy_krb5 t_saslname t_spnego
diff --git a/src/tests/gssapi/t_err.c b/src/tests/gssapi/t_err.c
new file mode 100644
index 0000000000..b7c32b463f
--- /dev/null
+++ b/src/tests/gssapi/t_err.c
@@ -0,0 +1,121 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/gssapi/t_err.c - Test accept_sec_context error generation */
+/*
+ * Copyright (C) 2013 by the Massachusetts Institute of Technology.
+ * 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.
+ */
+
+/*
+ * This test program verifies that the krb5 gss_accept_sec_context can produce
+ * error tokens and that gss_init_sec_context can interpret them.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "common.h"
+
+static void
+check_replay_error(const char *msg, OM_uint32 major, OM_uint32 minor)
+{
+ OM_uint32 tmpmin, msg_ctx = 0;
+ const char *replay = "Request is a replay";
+ gss_buffer_desc m;
+
+ if (major != GSS_S_FAILURE) {
+ fprintf(stderr, "%s: expected major code GSS_S_FAILURE\n", msg);
+ check_gsserr(msg, major, minor);
+ exit(1);
+ }
+
+ (void)gss_display_status(&tmpmin, minor, GSS_C_MECH_CODE, GSS_C_NULL_OID,
+ &msg_ctx, &m);
+ if (m.length != strlen(replay) || memcmp(m.value, replay, m.length) != 0) {
+ fprintf(stderr, "%s: expected replay error; got %.*s\n", msg,
+ (int)m.length, (char *)m.value);
+ exit(1);
+ }
+ (void)gss_release_buffer(&tmpmin, &m);
+}
+
+int
+main(int argc, char *argv[])
+{
+ OM_uint32 minor, major, flags;
+ gss_OID mech = &mech_krb5;
+ gss_name_t tname;
+ gss_buffer_desc itok, atok;
+ gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s targetname\n", argv[0]);
+ return 1;
+ }
+ tname = import_name(argv[1]);
+
+ /* Get the initial context token. */
+ flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
+ major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname,
+ mech, flags, GSS_C_INDEFINITE,
+ GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER,
+ NULL, &itok, NULL, NULL);
+ check_gsserr("gss_init_sec_context(1)", major, minor);
+ assert(major == GSS_S_CONTINUE_NEEDED);
+
+ /* Process this token into an acceptor context, then discard it. */
+ major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok,
+ GSS_C_NO_CHANNEL_BINDINGS, NULL,
+ NULL, &atok, NULL, NULL, NULL);
+ check_gsserr("gss_accept_sec_context(1)", major, minor);
+ (void)gss_release_buffer(&minor, &atok);
+ (void)gss_delete_sec_context(&minor, &actx, NULL);
+
+ /* Process the same token again, producing a replay error. */
+ major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok,
+ GSS_C_NO_CHANNEL_BINDINGS, NULL,
+ NULL, &atok, NULL, NULL, NULL);
+ check_replay_error("gss_accept_sec_context(2)", major, minor);
+ assert(atok.length != 0);
+
+ /* Send the error token back the initiator. */
+ (void)gss_release_buffer(&minor, &itok);
+ major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname,
+ mech, flags, GSS_C_INDEFINITE,
+ GSS_C_NO_CHANNEL_BINDINGS, &atok,
+ NULL, &itok, NULL, NULL);
+ check_replay_error("gss_init_sec_context(2)", major, minor);
+
+ (void)gss_release_name(&minor, &tname);
+ (void)gss_release_buffer(&minor, &itok);
+ (void)gss_release_buffer(&minor, &atok);
+ (void)gss_delete_sec_context(&minor, &ictx, NULL);
+ (void)gss_delete_sec_context(&minor, &actx, NULL);
+ return 0;
+}
diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
index 2b86d3eafc..74139e464e 100755
--- a/src/tests/gssapi/t_gssapi.py
+++ b/src/tests/gssapi/t_gssapi.py
@@ -194,4 +194,8 @@ out = realm.run(['./t_inq_mechs_name', 'h:host'])
if krb5_mech not in out or spnego_mech not in out:
fail('t_inq_mecs_name (hostbased)')
+# Test that accept_sec_context can produce an error token and
+# init_sec_context can interpret it.
+realm.run(['./t_err', 'p:' + realm.host_princ])
+
success('GSSAPI tests')