From: Simo Sorce Date: Fri, 2 Mar 2012 23:27:49 +0000 (-0500) Subject: Introduce credential store extensions X-Git-Tag: krb5-1.11-alpha1~393 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25ee704e83c2c63d4b5ecd12ea31c1979239041e;p=thirdparty%2Fkrb5.git Introduce credential store extensions Add new APIs gss_acquire_cred_from, gss_add_cred_from, and gss_store_cred_into, which take additional argments to specify the location of the credential storage using a key-value map, where keys are interpreted by the mechanisms. ticket: 7217 (new) --- diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h index b4f8a77ada..05f1ed7fb4 100644 --- a/src/lib/gssapi/generic/gssapi_ext.h +++ b/src/lib/gssapi/generic/gssapi_ext.h @@ -461,6 +461,62 @@ int KRB5_CALLCONV gss_oid_equal gss_const_OID /* second_oid */ ); +/* Credential store extensions */ + +struct gss_key_value_element_struct { + const char *key; + const char *value; +}; +typedef struct gss_key_value_element_struct gss_key_value_element_desc; + +struct gss_key_value_set_struct { + OM_uint32 count; + gss_key_value_element_desc *elements; +}; +typedef struct gss_key_value_set_struct gss_key_value_set_desc; +typedef const gss_key_value_set_desc *gss_const_key_value_set_t; + +#define GSS_C_NO_CRED_STORE ((gss_const_key_value_set_t) 0) + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_from( + OM_uint32 *, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + 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 +gss_add_cred_from( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_name_t, /* desired_name */ + gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_const_key_value_set_t, /* cred_store */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 *); /* acceptor_time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_store_cred_into( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + 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 */ + #ifdef __cplusplus } #endif diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports index 58111aa63f..a8ee3f2447 100644 --- a/src/lib/gssapi/libgssapi_krb5.exports +++ b/src/lib/gssapi/libgssapi_krb5.exports @@ -148,3 +148,6 @@ krb5_gss_dbg_client_expcreds krb5_gss_register_acceptor_identity krb5_gss_use_kdc_context gss_inquire_name +gss_acquire_cred_from +gss_add_cred_from +gss_store_cred_into diff --git a/src/lib/gssapi/mechglue/g_acquire_cred.c b/src/lib/gssapi/mechglue/g_acquire_cred.c index ad4e99b7e7..c28bf720e3 100644 --- a/src/lib/gssapi/mechglue/g_acquire_cred.c +++ b/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -42,6 +42,7 @@ val_acq_cred_args( OM_uint32 time_req, gss_OID_set desired_mechs, int 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) @@ -79,6 +80,12 @@ val_acq_cred_args( return GSS_S_FAILURE; } + if (cred_store != NULL && cred_store->count == 0) { + *minor_status = EINVAL; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + return (GSS_S_COMPLETE); } @@ -102,6 +109,33 @@ gss_cred_id_t * output_cred_handle; gss_OID_set * actual_mechs; OM_uint32 * time_rec; +{ + return gss_acquire_cred_from(minor_status, desired_name, time_req, + desired_mechs, cred_usage, NULL, + output_cred_handle, actual_mechs, time_rec); +} + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_from(minor_status, + desired_name, + time_req, + desired_mechs, + cred_usage, + cred_store, + output_cred_handle, + actual_mechs, + time_rec) + +OM_uint32 * minor_status; +gss_name_t desired_name; +OM_uint32 time_req; +gss_OID_set desired_mechs; +int 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 major = GSS_S_FAILURE, tmpMinor; OM_uint32 first_major = GSS_S_COMPLETE, first_minor = 0; @@ -115,6 +149,7 @@ OM_uint32 * time_rec; time_req, desired_mechs, cred_usage, + cred_store, output_cred_handle, actual_mechs, time_rec); @@ -150,11 +185,11 @@ OM_uint32 * time_rec; /* for each requested mech attempt to obtain a credential */ for (i = 0, major = GSS_S_UNAVAILABLE; i < mechs->count; i++) { - major = gss_add_cred(&tmpMinor, (gss_cred_id_t)creds, - desired_name, - &mechs->elements[i], - cred_usage, time_req, time_req, NULL, - NULL, &initTimeOut, &acceptTimeOut); + major = gss_add_cred_from(&tmpMinor, (gss_cred_id_t)creds, + desired_name, &mechs->elements[i], + cred_usage, time_req, time_req, + cred_store, NULL, NULL, &initTimeOut, + &acceptTimeOut); if (major == GSS_S_COMPLETE) { /* update the credential's time */ if (cred_usage == GSS_C_ACCEPT) { @@ -226,6 +261,7 @@ val_add_cred_args( gss_name_t desired_name, gss_OID desired_mech, gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, OM_uint32 initiator_time_req, OM_uint32 acceptor_time_req, gss_cred_id_t *output_cred_handle, @@ -270,6 +306,12 @@ val_add_cred_args( return GSS_S_FAILURE; } + if (cred_store != NULL && cred_store->count == 0) { + *minor_status = EINVAL; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + return (GSS_S_COMPLETE); } @@ -292,6 +334,34 @@ gss_add_cred(minor_status, input_cred_handle, gss_OID_set *actual_mechs; OM_uint32 *initiator_time_rec; OM_uint32 *acceptor_time_rec; +{ + return gss_add_cred_from(minor_status, input_cred_handle, desired_name, + desired_mech, cred_usage, initiator_time_req, + acceptor_time_req, NULL, output_cred_handle, + actual_mechs, initiator_time_rec, + acceptor_time_rec); +} + +OM_uint32 KRB5_CALLCONV +gss_add_cred_from(minor_status, input_cred_handle, + desired_name, desired_mech, + cred_usage, + initiator_time_req, acceptor_time_req, + cred_store, + output_cred_handle, actual_mechs, + initiator_time_rec, acceptor_time_rec) + OM_uint32 *minor_status; + gss_cred_id_t input_cred_handle; + gss_name_t desired_name; + gss_OID desired_mech; + gss_cred_usage_t cred_usage; + OM_uint32 initiator_time_req; + OM_uint32 acceptor_time_req; + gss_const_key_value_set_t cred_store; + gss_cred_id_t *output_cred_handle; + gss_OID_set *actual_mechs; + OM_uint32 *initiator_time_rec; + OM_uint32 *acceptor_time_rec; { OM_uint32 status, temp_minor_status; OM_uint32 time_req, time_rec; @@ -309,6 +379,7 @@ gss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech, cred_usage, + cred_store, initiator_time_req, acceptor_time_req, output_cred_handle, @@ -330,15 +401,16 @@ gss_add_cred(minor_status, input_cred_handle, return (GSS_S_FAILURE); (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); - - /* for default credentials we will use GSS_C_NO_NAME */ - internal_name = GSS_C_NO_NAME; } else { union_cred = (gss_union_cred_t)input_cred_handle; if (gssint_get_mechanism_cred(union_cred, desired_mech) != GSS_C_NO_CREDENTIAL) return (GSS_S_DUPLICATE_ELEMENT); + } + /* for default credentials we will use GSS_C_NO_NAME */ + if (input_cred_handle != GSS_C_NO_CREDENTIAL || + cred_store != GSS_C_NO_CRED_STORE) { /* may need to create a mechanism specific name */ if (desired_name) { union_name = (gss_union_name_t)desired_name; @@ -367,10 +439,18 @@ gss_add_cred(minor_status, input_cred_handle, else time_req = 0; - status = mech->gss_acquire_cred(minor_status, - internal_name, time_req, - GSS_C_NULL_OID_SET, cred_usage, - &cred, NULL, &time_rec); + if (mech->gss_acquire_cred_from) { + status = mech->gss_acquire_cred_from(minor_status, internal_name, + time_req, GSS_C_NULL_OID_SET, + cred_usage, cred_store, &cred, + NULL, &time_rec); + } else if (cred_store == GSS_C_NO_CRED_STORE) { + status = mech->gss_acquire_cred(minor_status, internal_name, time_req, + GSS_C_NULL_OID_SET, cred_usage, &cred, + NULL, &time_rec); + } else { + return GSS_S_UNAVAILABLE; + } if (status != GSS_S_COMPLETE) { map_error(minor_status, mech); diff --git a/src/lib/gssapi/mechglue/g_store_cred.c b/src/lib/gssapi/mechglue/g_store_cred.c index f7de1d613a..a68a5878f4 100644 --- a/src/lib/gssapi/mechglue/g_store_cred.c +++ b/src/lib/gssapi/mechglue/g_store_cred.c @@ -11,6 +11,36 @@ #include +static OM_uint32 +store_cred_fallback( + OM_uint32 *minor_status, + gss_mechanism mech, + gss_cred_id_t mech_cred, + gss_cred_usage_t cred_usage, + 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) +{ + if (mech->gss_store_cred_into != NULL) { + return mech->gss_store_cred_into(minor_status, mech_cred, + cred_usage, desired_mech, + overwrite_cred, default_cred, + cred_store, elements_stored, + cred_usage_stored); + } else if (cred_store == GSS_C_NO_CRED_STORE) { + return mech->gss_store_cred(minor_status, mech_cred, + cred_usage, desired_mech, + overwrite_cred, default_cred, + elements_stored, + cred_usage_stored); + } else { + return GSS_S_UNAVAILABLE; + } +} + static OM_uint32 val_store_cred_args( OM_uint32 *minor_status, @@ -19,6 +49,7 @@ val_store_cred_args( 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) { @@ -49,6 +80,12 @@ val_store_cred_args( return GSS_S_FAILURE; } + if (cred_store != NULL && cred_store->count == 0) { + *minor_status = EINVAL; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + return (GSS_S_COMPLETE); } @@ -72,6 +109,34 @@ OM_uint32 default_cred; gss_OID_set *elements_stored; gss_cred_usage_t *cred_usage_stored; +{ + return 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 +gss_store_cred_into(minor_status, + input_cred_handle, + cred_usage, + desired_mech, + overwrite_cred, + default_cred, + cred_store, + elements_stored, + cred_usage_stored) + +OM_uint32 *minor_status; +gss_cred_id_t input_cred_handle; +gss_cred_usage_t cred_usage; +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_S_FAILURE; gss_union_cred_t union_cred; @@ -86,6 +151,7 @@ gss_cred_usage_t *cred_usage_stored; desired_mech, overwrite_cred, default_cred, + cred_store, elements_stored, cred_usage_stored); if (major_status != GSS_S_COMPLETE) @@ -105,22 +171,25 @@ gss_cred_usage_t *cred_usage_stored; if (mech == NULL) return (GSS_S_BAD_MECH); - if (mech->gss_store_cred == NULL) + if (mech->gss_store_cred_into == NULL && + cred_store != GSS_C_NO_CRED_STORE) + return (major_status); + + if (mech->gss_store_cred == NULL && + mech->gss_store_cred_into == NULL) return (major_status); mech_cred = gssint_get_mechanism_cred(union_cred, desired_mech); if (mech_cred == GSS_C_NO_CREDENTIAL) return (GSS_S_NO_CRED); - major_status = mech->gss_store_cred( - minor_status, - (gss_cred_id_t)mech_cred, - cred_usage, - desired_mech, - overwrite_cred, - default_cred, - elements_stored, - cred_usage_stored); + major_status = store_cred_fallback(minor_status, mech, + mech_cred, cred_usage, + desired_mech, + overwrite_cred, + default_cred, cred_store, + elements_stored, + cred_usage_stored); if (major_status != GSS_S_COMPLETE) map_error(minor_status, mech); return major_status; @@ -137,22 +206,23 @@ gss_cred_usage_t *cred_usage_stored; if (mech == NULL) continue; - if (mech->gss_store_cred == NULL) + if (mech->gss_store_cred_into == NULL && + cred_store != GSS_C_NO_CRED_STORE) + continue; + + if (mech->gss_store_cred == NULL && + mech->gss_store_cred_into == NULL) continue; mech_cred = gssint_get_mechanism_cred(union_cred, dmech); if (mech_cred == GSS_C_NO_CREDENTIAL) continue; /* can't happen, but safe to ignore */ - major_status = mech->gss_store_cred( - minor_status, - (gss_cred_id_t)mech_cred, - cred_usage, - dmech, - overwrite_cred, - default_cred, - NULL, - cred_usage_stored); + major_status = store_cred_fallback(minor_status, mech, + mech_cred, cred_usage, + dmech, overwrite_cred, + default_cred, cred_store, + NULL, cred_usage_stored); if (major_status != GSS_S_COMPLETE) { map_error(minor_status, mech); continue; diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index 577f573085..efbb370232 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -605,6 +605,34 @@ typedef struct gss_config { gss_OID_set * /* known_mech_attrs */ /* */); + /* Credential store extensions */ + + OM_uint32 (KRB5_CALLCONV *gss_acquire_cred_from) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + 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 *gss_store_cred_into) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + 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 */ + /* */); + } *gss_mechanism; /* This structure MUST NOT be used by any code outside libgss */