From: Simo Sorce Date: Mon, 11 Jun 2012 15:50:26 +0000 (-0400) Subject: Add primitives for using interposed mechanisms X-Git-Tag: krb5-1.11-alpha1~150 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=acc8f98c9be4d10f325367cbdb3b0521fbdb3afa;p=thirdparty%2Fkrb5.git Add primitives for using interposed mechanisms Add gssint_select_mechanism() to determine what mechanism to use for a caller-specified OID, gssint_get_public_oid() to determine what mechanism to expose to the caller, and gssint_make_public_oid_set to translate an array of mech OIDs into a set of public OIDs. In gssint_get_mechanism(), match interposed OIDs as well as real ones. [ghudson@mit.edu: Stylistic changes, commit squashing, commit message] --- diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index dc6b8eaf67..fbd0b07e63 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -75,6 +75,7 @@ static void getRegKeyValue(HKEY key, const char *keyPath, const char *valueName, static void loadConfigFromRegistry(HKEY keyBase, const char *keyPath); #endif static void updateMechList(void); +static void initMechList(void); static void loadInterMech(gss_mech_info aMech); static void freeMechList(void); @@ -457,6 +458,19 @@ updateMechList(void) } } /* updateMechList */ +/* Update the mech list from system configuration if we have never done so. + * Must be invoked with the g_mechListLock mutex held. */ +static void +initMechList(void) +{ + static int lazy_init = 0; + + if (lazy_init == 0) { + updateMechList(); + lazy_init = 1; + } +} + static void releaseMechInfo(gss_mech_info *pCf) { @@ -884,6 +898,124 @@ freeMechList(void) } } +/* + * Determine the mechanism to use for a caller-specified mech OID. For the + * real mech OID of an interposed mech, return the interposed OID. For an + * interposed mech OID (which an interposer mech uses when re-entering the + * mechglue), return the real mech OID. The returned OID is an alias and + * should not be modified or freed. + */ +OM_uint32 +gssint_select_mech_type(OM_uint32 *minor, gss_const_OID oid, + gss_OID *selected_oid) +{ + gss_mech_info minfo; + OM_uint32 status; + + *selected_oid = GSS_C_NO_OID; + + if (gssint_mechglue_initialize_library() != 0) + return GSS_S_FAILURE; + + if (k5_mutex_lock(&g_mechListLock) != 0) + return GSS_S_FAILURE; + + /* Read conf file at least once so that interposer plugins have a + * chance of getting initialized. */ + initMechList(); + + minfo = g_mechList; + if (oid == GSS_C_NULL_OID) + oid = minfo->mech_type; + while (minfo != NULL) { + if (g_OID_equal(minfo->mech_type, oid)) { + if (minfo->int_mech_type != GSS_C_NO_OID) + *selected_oid = minfo->int_mech_type; + else + *selected_oid = minfo->mech_type; + status = GSS_S_COMPLETE; + goto done; + } else if ((minfo->int_mech_type != GSS_C_NO_OID) && + (g_OID_equal(minfo->int_mech_type, oid))) { + *selected_oid = minfo->mech_type; + status = GSS_S_COMPLETE; + goto done; + } + minfo = minfo->next; + } + status = GSS_S_BAD_MECH; + +done: + (void)k5_mutex_unlock(&g_mechListLock); + return status; +} + +/* If oid is an interposed OID, return the corresponding real mech OID. If + * it's a real mech OID, return it unmodified. Otherwised return null. */ +gss_OID +gssint_get_public_oid(gss_const_OID oid) +{ + gss_mech_info minfo; + gss_OID public_oid = GSS_C_NO_OID; + + /* if oid is null -> then get default which is the first in the list */ + if (oid == GSS_C_NO_OID) + return GSS_C_NO_OID; + + if (gssint_mechglue_initialize_library() != 0) + return GSS_C_NO_OID; + + if (k5_mutex_lock(&g_mechListLock) != 0) + return GSS_C_NO_OID; + + for (minfo = g_mechList; minfo != NULL; minfo = minfo->next) { + if (minfo->is_interposer) + continue; + if (g_OID_equal(minfo->mech_type, oid) || + ((minfo->int_mech_type != GSS_C_NO_OID) && + (g_OID_equal(minfo->int_mech_type, oid)))) { + public_oid = minfo->mech_type; + break; + } + } + + (void)k5_mutex_unlock(&g_mechListLock); + return public_oid; +} + +/* Translate a vector of oids (as from a union cred struct) into a set of + * public OIDs using gssint_get_public_oid. */ +OM_uint32 +gssint_make_public_oid_set(OM_uint32 *minor_status, gss_OID oids, int count, + gss_OID_set *public_set) +{ + OM_uint32 status, tmpmin; + gss_OID_set set; + gss_OID public_oid; + int i; + + *public_set = GSS_C_NO_OID_SET; + + status = generic_gss_create_empty_oid_set(minor_status, &set); + if (GSS_ERROR(status)) + return status; + + for (i = 0; i < count; i++) { + public_oid = gssint_get_public_oid(&oids[i]); + if (public_oid == GSS_C_NO_OID) + continue; + status = generic_gss_add_oid_set_member(minor_status, + public_oid, &set); + if (GSS_ERROR(status)) { + (void) generic_gss_release_oid_set(&tmpmin, &set); + return status; + } + } + + *public_set = set; + return GSS_S_COMPLETE; +} + /* * Register a mechanism. Called with g_mechListLock held. */ @@ -908,10 +1040,21 @@ gssint_get_mechanism(gss_const_OID oid) if (k5_mutex_lock(&g_mechListLock) != 0) return NULL; - /* check if the mechanism is already loaded */ - if ((aMech = searchMechList(oid)) != NULL && aMech->mech) { - (void) k5_mutex_unlock(&g_mechListLock); - return (aMech->mech); + + /* Check if the mechanism is already loaded. */ + aMech = g_mechList; + if (oid == GSS_C_NULL_OID) + oid = aMech->mech_type; + while (aMech != NULL) { + if (g_OID_equal(aMech->mech_type, oid) && aMech->mech) { + (void)k5_mutex_unlock(&g_mechListLock); + return aMech->mech; + } else if (aMech->int_mech_type != GSS_C_NO_OID && + g_OID_equal(aMech->int_mech_type, oid)) { + (void)k5_mutex_unlock(&g_mechListLock); + return aMech->int_mech; + } + aMech = aMech->next; } /* diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index 21eefdb7b9..2d0fd4a834 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -682,6 +682,11 @@ int gssint_mechglue_init(void); void gssint_mechglue_fini(void); #endif +OM_uint32 gssint_select_mech_type(OM_uint32 *minor, gss_const_OID in_oid, + gss_OID *selected_oid); +gss_OID gssint_get_public_oid(gss_const_OID internal_oid); +OM_uint32 gssint_make_public_oid_set(OM_uint32 *minor_status, gss_OID oids, + int count, gss_OID_set *public_set); gss_mechanism gssint_get_mechanism (gss_const_OID); OM_uint32 gssint_get_mech_type (gss_OID, gss_buffer_t); char *gssint_get_kmodName(const gss_OID);