From f73c4edf696d018326e34d9e1648ce2f420a48da Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Thu, 19 Mar 2015 12:30:26 -0500 Subject: [PATCH] Fix gss_store_cred() --- lib/gssapi/Makefile.am | 4 +- lib/gssapi/krb5/store_cred.c | 80 +++++++++++++++++++++++++++--------- tests/gss/check-basic.in | 19 +++++---- 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am index 074ee7841..3158bb022 100644 --- a/lib/gssapi/Makefile.am +++ b/lib/gssapi/Makefile.am @@ -302,12 +302,14 @@ test_cfx_SOURCES = krb5/test_cfx.c check_PROGRAMS = test_acquire_cred $(TESTS) bin_PROGRAMS = gsstool -noinst_PROGRAMS = test_cred test_kcred test_context test_ntlm +noinst_PROGRAMS = test_cred test_kcred test_context test_ntlm test_add_store_cred test_context_SOURCES = test_context.c test_common.c test_common.h test_ntlm_SOURCES = test_ntlm.c test_common.c test_common.h test_acquire_cred_SOURCES = test_acquire_cred.c test_common.c test_common.h +test_add_store_cred_SOURCES = test_add_store_cred.c + test_ntlm_LDADD = \ $(top_builddir)/lib/ntlm/libheimntlm.la \ $(LDADD) diff --git a/lib/gssapi/krb5/store_cred.c b/lib/gssapi/krb5/store_cred.c index 7e93e9cb3..40b75771d 100644 --- a/lib/gssapi/krb5/store_cred.c +++ b/lib/gssapi/krb5/store_cred.c @@ -46,8 +46,11 @@ _gsskrb5_store_cred(OM_uint32 *minor_status, krb5_context context; krb5_error_code ret; gsskrb5_cred cred; - krb5_ccache id; - int destroy = 0; + krb5_ccache id = NULL; + krb5_ccache def_ccache = NULL; + const char *def_type = NULL; + time_t exp_current; + time_t exp_new; *minor_status = 0; @@ -70,48 +73,87 @@ _gsskrb5_store_cred(OM_uint32 *minor_status, if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = GSS_KRB5_S_G_BAD_USAGE; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_lifetime(context, cred->ccache, &exp_new); + if (ret) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ret; + return GSS_S_NO_CRED; } if (cred->principal == NULL) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = GSS_KRB5_S_KG_TGT_MISSING; - return(GSS_S_FAILURE); + return GSS_S_FAILURE; } - /* write out cred to credential cache */ + ret = krb5_cc_default(context, &def_ccache); + if (ret == 0) { + def_type = krb5_cc_get_type(context, def_ccache); + krb5_cc_close(context, def_ccache); + } + def_ccache = NULL; + /* write out cred to credential cache */ ret = krb5_cc_cache_match(context, cred->principal, &id); if (ret) { - ret = krb5_cc_new_unique(context, NULL, NULL, &id); - if (ret) { - HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); - *minor_status = ret; - return(GSS_S_FAILURE); - } - destroy = 1; + if (default_cred) { + ret = krb5_cc_default(context, &id); + if (ret) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ret; + return GSS_S_FAILURE; + } + } else { + if (def_type == NULL || + !krb5_cc_support_switch(context, def_type)) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = 0; /* XXX */ + return GSS_S_NO_CRED; /* XXX */ + } + ret = krb5_cc_new_unique(context, def_type, NULL, &id); + if (ret) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ret; + return GSS_S_FAILURE; + } + overwrite_cred = 1; + } + } + + if (!overwrite_cred) { + /* If current creds are expired or near it, overwrite */ + ret = krb5_cc_get_lifetime(context, id, &exp_current); + if (ret != 0 || exp_new > exp_current) + overwrite_cred = 1; + } + + if (!overwrite_cred) { + /* Nothing to do */ + krb5_cc_close(context, id); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = 0; + return GSS_S_DUPLICATE_ELEMENT; } ret = krb5_cc_initialize(context, id, cred->principal); if (ret == 0) ret = krb5_cc_copy_match_f(context, cred->ccache, id, NULL, NULL, NULL); if (ret) { - if (destroy) - krb5_cc_destroy(context, id); - else - krb5_cc_close(context, id); + krb5_cc_close(context, id); HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = ret; return(GSS_S_FAILURE); } - if (default_cred) + if (default_cred && def_type != NULL && + krb5_cc_support_switch(context, def_type)) krb5_cc_switch(context, id); krb5_cc_close(context, id); - HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); - *minor_status = 0; return GSS_S_COMPLETE; } diff --git a/tests/gss/check-basic.in b/tests/gss/check-basic.in index fca02235f..031fdcff1 100644 --- a/tests/gss/check-basic.in +++ b/tests/gss/check-basic.in @@ -34,9 +34,12 @@ # $Id$ # +env_setup="@env_setup@" srcdir="@srcdir@" objdir="@objdir@" +. ${env_setup} + # If there is no useful db support compile in, disable test ../db/have-db || exit 77 @@ -51,14 +54,12 @@ cache="FILE:krb5ccfile" cache2="FILE:krb5ccfile2" nocache="FILE:no-such-cache" -kinit="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cache ${afs_no_afslog}" -kdestroy="${TESTS_ENVIRONMENT} ../../kuser/kdestroy -c $cache ${afs_no_unlog}" -klist="${TESTS_ENVIRONMENT} ../../kuser/klist -c $cache" -kadmin="${TESTS_ENVIRONMENT} ../../kadmin/kadmin -l -r $R" -kdc="${TESTS_ENVIRONMENT} ../../kdc/kdc --addresses=localhost -P $port" +kadmin="${kadmin} -l -r $R" +kdc="${kdc} --addresses=localhost -P $port" acquire_cred="${TESTS_ENVIRONMENT} ../../lib/gssapi/test_acquire_cred" test_kcred="${TESTS_ENVIRONMENT} ../../lib/gssapi/test_kcred" +test_add_store_cred="${TESTS_ENVIRONMENT} ../../lib/gssapi/test_add_store_cred" KRB5_CONFIG="${objdir}/krb5.conf" export KRB5_CONFIG @@ -107,7 +108,11 @@ trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT exitcode=0 echo "initial ticket" -${kinit} --password-file=${objdir}/foopassword user@${R} || exitcode=1 +${kinit} -c ${cache} --password-file=${objdir}/foopassword user@${R} || exitcode=1 + +echo "copy ccache with gss_store_cred" +${test_add_store_cred} ${cache} ${cache2} || exit 1 +${klist} -c ${cache2} || exit 1 echo "keytab" ${acquire_cred} \ @@ -188,7 +193,7 @@ KRB5_KTNAME=${nokeytab} echo "kcred" ${test_kcred} || exit 1 -${kdestroy} +${kdestroy} -c ${cache} KRB5_KTNAME="${keytab}"