[28967] in CVS-changelog-for-Kerberos-V5

home help back first fref pref prev next nref lref last post

krb5 commit: Allow gss_inquire_context on partial krb5 contexts

daemon@ATHENA.MIT.EDU (Greg Hudson)
Mon Jun 29 23:02:08 2015

Date: Mon, 29 Jun 2015 23:01:58 -0400
From: Greg Hudson <ghudson@mit.edu>
Message-Id: <201506300301.t5U31w1K030763@drugstore.mit.edu>
To: cvs-krb5@mit.edu
Reply-To: krbdev@mit.edu
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu

https://github.com/krb5/krb5/commit/9f095e1aab582e5a94c93d587f6d09e9d8f7479e
commit 9f095e1aab582e5a94c93d587f6d09e9d8f7479e
Author: Solly Ross <sross@redhat.com>
Date:   Mon Jun 8 14:06:18 2015 -0400

    Allow gss_inquire_context on partial krb5 contexts
    
    RFC 2743 states that gss_inquire_context() must always return flags,
    locally_initiated, and open even if a context is not yet fully
    established.  Additionally, a partially established context may also
    return mech_type.
    
    Previously, the krb5 mech raised an error for inquire_context on
    partially completed contexts.  It now follows the rules layed out in
    RFC 2743.
    
    Add a new test program to verify that gss_inquire_context() works
    correctly on both in-progress and established contexts.
    
    [ghudson@mit.edu: minor style changes and commit message edits]
    
    ticket: 8025

 .gitignore                              |    1 +
 src/lib/gssapi/krb5/inq_context.c       |   90 ++++++++++++---------
 src/lib/gssapi/mechglue/g_inq_context.c |    5 +-
 src/tests/gssapi/Makefile.in            |   17 +++--
 src/tests/gssapi/t_gssapi.py            |    4 +
 src/tests/gssapi/t_inq_ctx.c            |  131 +++++++++++++++++++++++++++++++
 6 files changed, 202 insertions(+), 46 deletions(-)

diff --git a/.gitignore b/.gitignore
index c70cc29..d9ceb21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -307,6 +307,7 @@ testlog
 /src/tests/gssapi/t_s4u2proxy_krb5
 /src/tests/gssapi/t_saslname
 /src/tests/gssapi/t_spnego
+/src/tests/gssapi/t_inq_ctx
 
 /src/tests/hammer/kdc5_hammer
 
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index 096df2a..cc06a93 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -104,55 +104,66 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
         *acceptor_name = (gss_name_t) NULL;
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
-
-    if (ctx->terminated || !ctx->established) {
-        *minor_status = KG_CTX_INCOMPLETE;
-        return(GSS_S_NO_CONTEXT);
-    }
-
-    initiator = NULL;
-    acceptor = NULL;
     context = ctx->k5_context;
 
-    if ((code = krb5_timeofday(context, &now))) {
-        *minor_status = code;
-        save_error_info(*minor_status, context);
-        return(GSS_S_FAILURE);
-    }
-
-    if ((lifetime = ctx->krb_times.endtime - now) < 0)
-        lifetime = 0;
+    /* RFC 2743 states that a partially completed context must return
+     * flags, locally_initiated, and open, and *may* return mech_type. */
+    if (ctx->established) {
+        initiator = NULL;
+        acceptor = NULL;
 
-    if (initiator_name) {
-        if ((code = kg_duplicate_name(context,
-                                      ctx->initiate ? ctx->here : ctx->there,
-                                      &initiator))) {
+        if ((code = krb5_timeofday(context, &now))) {
             *minor_status = code;
             save_error_info(*minor_status, context);
             return(GSS_S_FAILURE);
         }
-    }
 
-    if (acceptor_name) {
-        if ((code = kg_duplicate_name(context,
-                                      ctx->initiate ? ctx->there : ctx->here,
-                                      &acceptor))) {
-            if (initiator)
-                kg_release_name(context, &initiator);
-            *minor_status = code;
-            save_error_info(*minor_status, context);
-            return(GSS_S_FAILURE);
+        if ((lifetime = ctx->krb_times.endtime - now) < 0)
+            lifetime = 0;
+
+        if (initiator_name) {
+            code = kg_duplicate_name(context,
+                                     ctx->initiate ? ctx->here : ctx->there,
+                                     &initiator);
+            if (code) {
+                *minor_status = code;
+                save_error_info(*minor_status, context);
+                return(GSS_S_FAILURE);
+            }
         }
-    }
 
-    if (initiator_name)
-        *initiator_name = (gss_name_t) initiator;
+        if (acceptor_name) {
+            code = kg_duplicate_name(context,
+                                     ctx->initiate ? ctx->there : ctx->here,
+                                     &acceptor);
+            if (code) {
+                if (initiator)
+                    kg_release_name(context, &initiator);
+                *minor_status = code;
+                save_error_info(*minor_status, context);
+                return(GSS_S_FAILURE);
+            }
+        }
 
-    if (acceptor_name)
-        *acceptor_name = (gss_name_t) acceptor;
+        if (initiator_name)
+            *initiator_name = (gss_name_t) initiator;
 
-    if (lifetime_rec)
-        *lifetime_rec = lifetime;
+        if (acceptor_name)
+            *acceptor_name = (gss_name_t) acceptor;
+
+        if (lifetime_rec)
+            *lifetime_rec = lifetime;
+    } else {
+        lifetime = 0;
+        if (initiator_name)
+            *initiator_name = GSS_C_NO_NAME;
+
+        if (acceptor_name)
+            *acceptor_name = GSS_C_NO_NAME;
+
+        if (lifetime_rec)
+            *lifetime_rec = 0;
+    }
 
     if (mech_type)
         *mech_type = (gss_OID) ctx->mech_used;
@@ -167,7 +178,10 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
         *opened = ctx->established;
 
     *minor_status = 0;
-    return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
+    if (ctx->established)
+        return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
+    else
+        return GSS_S_COMPLETE;
 }
 
 OM_uint32
diff --git a/src/lib/gssapi/mechglue/g_inq_context.c b/src/lib/gssapi/mechglue/g_inq_context.c
index d3fb343..6f1c71e 100644
--- a/src/lib/gssapi/mechglue/g_inq_context.c
+++ b/src/lib/gssapi/mechglue/g_inq_context.c
@@ -130,6 +130,7 @@ gss_inquire_context(
     /* need to convert names */
 
     if (src_name) {
+	if (localSourceName) {
 	    status = gssint_convert_name_to_union_name(minor_status, mech,
 						      localSourceName, src_name);
 
@@ -138,7 +139,9 @@ gss_inquire_context(
 		    mech->gss_release_name(&temp_minor, &localTargName);
 		return (status);
 	    }
-
+	} else {
+	    *src_name = GSS_C_NO_NAME;
+	}
     }
 
     if (targ_name) {
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index a04cbb1..9fe5ed5 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -13,7 +13,7 @@ SRCS=	$(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.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_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \
 	$(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.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 \
@@ -22,16 +22,16 @@ SRCS=	$(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
 OBJS=	ccinit.o ccrefresh.o common.o t_accname.o t_ccselect.o t_ciflags.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_mechs_name.o t_iov.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_inq_ctx.o t_inq_mechs_name.o t_iov.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
 
 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_ciflags 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_mechs_name t_iov t_namingexts t_oid \
-	t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego
+	t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_namingexts \
+	t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego
 
 check-unix:: t_oid
 	$(RUN_SETUP) $(VALGRIND) ./t_invalid
@@ -40,7 +40,8 @@ check-unix:: t_oid
 
 check-pytests:: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore \
 	t_enctypes t_err t_export_cred t_export_name t_imp_cred t_inq_cred \
-	t_inq_mechs_name t_iov t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego
+	t_inq_ctx t_inq_mechs_name t_iov t_pcontok 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)
@@ -78,6 +79,8 @@ t_invalid: t_invalid.o $(COMMON_DEPS)
 	$(CC_LINK) -o $@ t_invalid.o $(COMMON_LIBS)
 t_inq_cred: t_inq_cred.o $(COMMON_DEPS)
 	$(CC_LINK) -o $@ t_inq_cred.o $(COMMON_LIBS)
+t_inq_ctx: t_inq_ctx.o $(COMMON_DEPS)
+	$(CC_LINK) -o $@ t_inq_ctx.o $(COMMON_LIBS)
 t_inq_mechs_name: t_inq_mechs_name.o $(COMMON_DEPS)
 	$(CC_LINK) -o $@ t_inq_mechs_name.o $(COMMON_LIBS)
 t_iov: t_iov.o $(COMMON_DEPS)
@@ -102,6 +105,6 @@ t_spnego: t_spnego.o $(COMMON_DEPS)
 clean::
 	$(RM) ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore
 	$(RM) t_enctypes t_err t_export_cred t_export_name t_gssexts t_imp_cred
-	$(RM) t_imp_name t_invalid t_inq_cred t_inq_mechs_name t_iov
+	$(RM) t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov
 	$(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5
 	$(RM) t_saslname t_spnego
diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
index c8c9034..8093c3d 100755
--- a/src/tests/gssapi/t_gssapi.py
+++ b/src/tests/gssapi/t_gssapi.py
@@ -216,4 +216,8 @@ realm.run(['./t_err', 'p:' + realm.host_princ])
 # Test the GSS_KRB5_CRED_NO_CI_FLAGS_X cred option.
 realm.run(['./t_ciflags', 'p:' + realm.host_princ])
 
+# Test that inquire_context works properly, even on incomplete
+# contexts.
+realm.run(['./t_inq_ctx', 'p:%s' % realm.host_princ])
+
 success('GSSAPI tests')
diff --git a/src/tests/gssapi/t_inq_ctx.c b/src/tests/gssapi/t_inq_ctx.c
new file mode 100644
index 0000000..6575b7c
--- /dev/null
+++ b/src/tests/gssapi/t_inq_ctx.c
@@ -0,0 +1,131 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 2015 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "common.h"
+
+
+/*
+ * Test program for inquiring about a security context, intented to be run from
+ * a Python test script.  Partially establishes a context to test inquiring
+ * about an incomplete context, and then establishes full contexts and inquires
+ * them.  Exits with status 0 if all operations are successful, or 1 if not.
+ *
+ * Usage: ./t_inq_ctx target_name
+ */
+
+static void
+check_inq_context(const char *header, gss_ctx_id_t context,
+                      int incomplete, OM_uint32 expected_flags,
+                      int expected_locally_init)
+{
+    OM_uint32 major, minor;
+    gss_name_t out_init_name, out_accept_name;
+    OM_uint32 out_lifetime;
+    gss_OID out_mech_type;
+    OM_uint32 out_flags;
+    int out_locally_init;
+    int out_open;
+    int mech_is_member;
+
+    major = gss_inquire_context(&minor, context, &out_init_name,
+                                &out_accept_name, &out_lifetime,
+                                &out_mech_type, &out_flags, &out_locally_init,
+                                &out_open);
+    check_gsserr("gss_inquire_context", major, minor);
+
+    major = gss_test_oid_set_member(&minor, out_mech_type, &mechset_krb5,
+                                    &mech_is_member);
+    check_gsserr("gss_test_oid_set_member", major, minor);
+
+    assert(out_flags & expected_flags);
+    assert(mech_is_member);
+    assert(out_locally_init == expected_locally_init);
+    if (incomplete) {
+        assert(!out_open);
+        assert(out_lifetime == 0);
+        assert(out_init_name == GSS_C_NO_NAME);
+        assert(out_accept_name == GSS_C_NO_NAME);
+    } else {
+        assert(out_open);
+        assert(out_lifetime > 0);
+        assert(out_init_name != GSS_C_NO_NAME);
+        assert(out_accept_name != GSS_C_NO_NAME);
+    }
+
+    (void)gss_release_name(&minor, &out_accept_name);
+    (void)gss_release_name(&minor, &out_init_name);
+}
+
+/* Call gss_init_sec_context() once to create an initiator context (which will
+ * be partial if flags includes GSS_C_MUTUAL_FLAG and the mech is krb5). */
+static void
+start_init_context(gss_OID mech, gss_cred_id_t cred, gss_name_t tname,
+                   OM_uint32 flags, gss_ctx_id_t *ctx)
+{
+    OM_uint32 major, minor;
+    gss_buffer_desc itok = GSS_C_EMPTY_BUFFER;
+
+    *ctx = GSS_C_NO_CONTEXT;
+    major = gss_init_sec_context(&minor, cred, ctx, tname, mech, flags,
+                                 GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS,
+                                 NULL, NULL, &itok, NULL, NULL);
+    check_gsserr("gss_init_sec_context", major, minor);
+    (void)gss_release_buffer(&minor, &itok);
+}
+
+int
+main(int argc, char *argv[])
+{
+    OM_uint32 minor, flags;
+    gss_name_t tname;
+    gss_ctx_id_t ictx, actx;
+
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s targetname\n", argv[0]);
+        return 1;
+    }
+    tname = import_name(argv[1]);
+
+    flags = GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
+    start_init_context(&mech_krb5, GSS_C_NO_CREDENTIAL, tname, flags, &ictx);
+    check_inq_context("Partial initiator", ictx, 1, flags, 1);
+    (void)gss_delete_sec_context(&minor, &ictx, NULL);
+
+    establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
+                       tname, flags, &ictx, &actx, NULL, NULL, NULL);
+
+    check_inq_context("Complete initiator", ictx, 0, flags, 1);
+    check_inq_context("Complete acceptor", actx, 0, flags, 0);
+
+    (void)gss_delete_sec_context(&minor, &ictx, NULL);
+    (void)gss_delete_sec_context(&minor, &actx, NULL);
+
+    (void)gss_release_name(&minor, &tname);
+    return 0;
+}
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5

home help back first fref pref prev next nref lref last post