diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/inq_context.c | 90 | ||||
-rw-r--r-- | src/lib/gssapi/mechglue/g_inq_context.c | 5 | ||||
-rw-r--r-- | src/tests/gssapi/Makefile.in | 17 | ||||
-rwxr-xr-x | src/tests/gssapi/t_gssapi.py | 4 | ||||
-rw-r--r-- | src/tests/gssapi/t_inq_ctx.c | 131 |
6 files changed, 202 insertions, 46 deletions
@@ -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; +} |