diff options
author | Simo Sorce <simo@redhat.com> | 2012-03-02 23:11:32 -0500 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2012-07-20 14:02:35 -0400 |
commit | 721f9565de4f5ae4c13e152218d5261c0cdbb620 (patch) | |
tree | dfd150ca473a8ee84a9b01e2f364068f8d29ef6c | |
parent | 25ee704e83c2c63d4b5ecd12ea31c1979239041e (diff) | |
download | krb5-721f9565de4f5ae4c13e152218d5261c0cdbb620.tar.gz krb5-721f9565de4f5ae4c13e152218d5261c0cdbb620.tar.xz krb5-721f9565de4f5ae4c13e152218d5261c0cdbb620.zip |
Implement credential store support for krb5 mech
-rw-r--r-- | src/lib/gssapi/krb5/Makefile.in | 3 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/acquire_cred.c | 125 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/cred_store.c | 50 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/gssapiP_krb5.h | 34 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/gssapi_krb5.c | 2 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/store_cred.c | 76 |
6 files changed, 263 insertions, 27 deletions
diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in index 5998fc08c..ddd9ef999 100644 --- a/src/lib/gssapi/krb5/Makefile.in +++ b/src/lib/gssapi/krb5/Makefile.in @@ -43,6 +43,7 @@ SRCS = \ $(srcdir)/compare_name.c \ $(srcdir)/context_time.c \ $(srcdir)/copy_ccache.c \ + $(srcdir)/cred_store.c \ $(srcdir)/delete_sec_context.c \ $(srcdir)/disp_name.c \ $(srcdir)/disp_status.c \ @@ -93,6 +94,7 @@ OBJS = \ $(OUTPRE)compare_name.$(OBJEXT) \ $(OUTPRE)context_time.$(OBJEXT) \ $(OUTPRE)copy_ccache.$(OBJEXT) \ + $(OUTPRE)cred_store.$(OBJEXT) \ $(OUTPRE)delete_sec_context.$(OBJEXT) \ $(OUTPRE)disp_name.$(OBJEXT) \ $(OUTPRE)disp_status.$(OBJEXT) \ @@ -146,6 +148,7 @@ STLIBOBJS = \ compare_name.o \ context_time.o \ copy_ccache.o \ + cred_store.o \ delete_sec_context.o \ disp_name.o \ disp_status.o \ diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c index 0527d1320..258ec7440 100644 --- a/src/lib/gssapi/krb5/acquire_cred.c +++ b/src/lib/gssapi/krb5/acquire_cred.c @@ -716,13 +716,13 @@ error: } static OM_uint32 -acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, - gss_buffer_t password, OM_uint32 time_req, - gss_cred_usage_t cred_usage, krb5_ccache ccache, - krb5_keytab keytab, krb5_boolean iakerb, - gss_cred_id_t *output_cred_handle, OM_uint32 *time_rec) +acquire_cred_context(krb5_context context, OM_uint32 *minor_status, + gss_name_t desired_name, gss_buffer_t password, + OM_uint32 time_req, gss_cred_usage_t cred_usage, + krb5_ccache ccache, krb5_keytab keytab, + krb5_boolean iakerb, gss_cred_id_t *output_cred_handle, + OM_uint32 *time_rec) { - krb5_context context = NULL; krb5_gss_cred_id_t cred = NULL; krb5_gss_name_t name = (krb5_gss_name_t)desired_name; OM_uint32 ret; @@ -733,14 +733,6 @@ acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, if (time_rec) *time_rec = 0; - code = gss_krb5int_initialize_library(); - if (code) - goto krb_error_out; - - code = krb5_gss_init_context(&context); - if (code) - goto krb_error_out; - /* create the gss cred structure */ cred = k5alloc(sizeof(krb5_gss_cred_id_rec), &code); if (cred == NULL) @@ -821,7 +813,6 @@ acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, *minor_status = 0; *output_cred_handle = (gss_cred_id_t) cred; - krb5_free_context(context); return GSS_S_COMPLETE; krb_error_out: @@ -844,6 +835,39 @@ error_out: xfree(cred); } save_error_info(*minor_status, context); + return ret; +} + +static OM_uint32 +acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, + gss_buffer_t password, OM_uint32 time_req, + gss_cred_usage_t cred_usage, krb5_ccache ccache, + krb5_keytab keytab, krb5_boolean iakerb, + gss_cred_id_t *output_cred_handle, OM_uint32 *time_rec) +{ + krb5_context context = NULL; + krb5_error_code code = 0; + OM_uint32 ret; + + code = gss_krb5int_initialize_library(); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + ret = acquire_cred_context(context, minor_status, desired_name, password, + time_req, cred_usage, ccache, keytab, iakerb, + output_cred_handle, time_rec); + +out: krb5_free_context(context); return ret; } @@ -1092,3 +1116,74 @@ gss_krb5int_import_cred(OM_uint32 *minor_status, k5_mutex_destroy(&name.lock); return code; } + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + krb5_context context = NULL; + krb5_error_code code = 0; + krb5_keytab keytab = NULL; + krb5_ccache ccache = NULL; + const char *value; + OM_uint32 ret; + + code = gss_krb5int_initialize_library(); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_CCACHE_URN, &value); + if (GSS_ERROR(ret)) + goto out; + + if (value) { + code = krb5_cc_resolve(context, value, &ccache); + if (code != 0) { + *minor_status = code; + ret = GSS_S_CRED_UNAVAIL; + goto out; + } + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_KEYTAB_URN, &value); + if (GSS_ERROR(ret)) + goto out; + + if (value) { + code = krb5_kt_resolve(context, value, &keytab); + if (code != 0) { + *minor_status = code; + ret = GSS_S_CRED_UNAVAIL; + goto out; + } + } + + ret = acquire_cred_context(context, minor_status, desired_name, NULL, + time_req, cred_usage, ccache, keytab, 0, + output_cred_handle, time_rec); + +out: + if (ccache != NULL) + krb5_cc_close(context, ccache); + if (keytab != NULL) + krb5_kt_close(context, keytab); + krb5_free_context(context); + return ret; +} diff --git a/src/lib/gssapi/krb5/cred_store.c b/src/lib/gssapi/krb5/cred_store.c new file mode 100644 index 000000000..008dd208b --- /dev/null +++ b/src/lib/gssapi/krb5/cred_store.c @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2011 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 "gssapiP_krb5.h" + +OM_uint32 +kg_value_from_cred_store(gss_const_key_value_set_t cred_store, + const char *type, const char **value) +{ + OM_uint32 i; + + if (value == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *value = NULL; + + if (cred_store == GSS_C_NO_CRED_STORE) + return GSS_S_COMPLETE; + + for (i = 0; i < cred_store->count; i++) { + if (strcmp(cred_store->elements[i].key, type) == 0) { + if (*value != NULL) + return GSS_S_DUPLICATE_ELEMENT; + *value = cred_store->elements[i].value; + } + } + + return GSS_S_COMPLETE; +} diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index 9b0d6cc37..56b025b76 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -1224,4 +1224,38 @@ data_to_gss(krb5_data *input_k5data, gss_buffer_t output_buffer) #define KRB5_GSS_EXTS_IAKERB_FINISHED 1 + +/* Credential store extensions */ + +#define KRB5_CS_KEYTAB_URN "keytab" +#define KRB5_CS_CCACHE_URN "ccache" + +OM_uint32 +kg_value_from_cred_store(gss_const_key_value_set_t cred_store, + const char *type, const char **value); + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_from( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_const_key_value_set_t, /* cred_store */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_store_cred_into( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + const gss_OID, /* desired_mech */ + OM_uint32, /* overwrite_cred */ + OM_uint32, /* default_cred */ + gss_const_key_value_set_t, /* cred_store */ + gss_OID_set *, /* elements_stored */ + gss_cred_usage_t *); /* cred_usage_stored */ + #endif /* _GSSAPIP_KRB5_H_ */ diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index 068af434d..e94b90c04 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -897,6 +897,8 @@ static struct gss_config krb5_mechanism = { krb5_gss_inquire_saslname_for_mech, krb5_gss_inquire_mech_for_saslname, krb5_gss_inquire_attrs_for_mech, + krb5_gss_acquire_cred_from, + krb5_gss_store_cred_into, }; static struct gss_config_ext krb5_mechanism_ext = { diff --git a/src/lib/gssapi/krb5/store_cred.c b/src/lib/gssapi/krb5/store_cred.c index d58758978..0a020d757 100644 --- a/src/lib/gssapi/krb5/store_cred.c +++ b/src/lib/gssapi/krb5/store_cred.c @@ -32,7 +32,8 @@ static int has_unexpired_creds(krb5_gss_cred_id_t kcred, const gss_OID desired_mech, - int default_cred) + int default_cred, + gss_const_key_value_set_t cred_store) { OM_uint32 major_status, minor; gss_name_t cred_name; @@ -48,9 +49,10 @@ has_unexpired_creds(krb5_gss_cred_id_t kcred, else cred_name = (gss_name_t)kcred->name; - major_status = krb5_gss_acquire_cred(&minor, cred_name, 0, - &desired_mechs, GSS_C_INITIATE, - &tmp_cred, NULL, &time_rec); + major_status = krb5_gss_acquire_cred_from(&minor, cred_name, 0, + &desired_mechs, GSS_C_INITIATE, + cred_store, &tmp_cred, NULL, + &time_rec); krb5_gss_release_cred(&minor, &tmp_cred); @@ -62,15 +64,19 @@ copy_initiator_creds(OM_uint32 *minor_status, gss_cred_id_t input_cred_handle, const gss_OID desired_mech, OM_uint32 overwrite_cred, - OM_uint32 default_cred) + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store) { OM_uint32 major_status; krb5_error_code code; krb5_gss_cred_id_t kcred = NULL; krb5_context context = NULL; krb5_ccache ccache = NULL; + const char *ccache_name; - if (!default_cred) { + *minor_status = 0; + + if (!default_cred && cred_store == GSS_C_NO_CRED_STORE) { *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; major_status = GSS_S_FAILURE; goto cleanup; @@ -98,16 +104,44 @@ copy_initiator_creds(OM_uint32 *minor_status, } if (!overwrite_cred && - has_unexpired_creds(kcred, desired_mech, default_cred)) { + has_unexpired_creds(kcred, desired_mech, default_cred, cred_store)) { major_status = GSS_S_DUPLICATE_ELEMENT; goto cleanup; } - code = krb5int_cc_default(context, &ccache); - if (code != 0) { - *minor_status = code; - major_status = GSS_S_FAILURE; + major_status = kg_value_from_cred_store(cred_store, + KRB5_CS_CCACHE_URN, &ccache_name); + if (GSS_ERROR(major_status)) goto cleanup; + + if (ccache_name != NULL) { + code = krb5_cc_resolve(context, ccache_name, &ccache); + if (code != 0) { + *minor_status = code; + major_status = GSS_S_CRED_UNAVAIL; + goto cleanup; + } + code = krb5_cc_initialize(context, ccache, + kcred->name->princ); + if (code != 0) { + *minor_status = code; + major_status = GSS_S_CRED_UNAVAIL; + goto cleanup; + } + } + + if (ccache == NULL) { + if (!default_cred) { + *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP; + major_status = GSS_S_FAILURE; + goto cleanup; + } + code = krb5int_cc_default(context, &ccache); + if (code != 0) { + *minor_status = code; + major_status = GSS_S_FAILURE; + goto cleanup; + } } code = krb5_cc_copy_creds(context, kcred->ccache, ccache); @@ -140,6 +174,24 @@ krb5_gss_store_cred(OM_uint32 *minor_status, gss_OID_set *elements_stored, gss_cred_usage_t *cred_usage_stored) { + return krb5_gss_store_cred_into(minor_status, input_cred_handle, + cred_usage, desired_mech, + overwrite_cred, default_cred, + GSS_C_NO_CRED_STORE, + elements_stored, cred_usage_stored); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_store_cred_into(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ OM_uint32 major_status; gss_cred_usage_t actual_usage; OM_uint32 lifetime; @@ -173,7 +225,7 @@ krb5_gss_store_cred(OM_uint32 *minor_status, major_status = copy_initiator_creds(minor_status, input_cred_handle, desired_mech, overwrite_cred, - default_cred); + default_cred, cred_store); if (GSS_ERROR(major_status)) return major_status; |