krb5 commit: Add primitives for using interposed mechanisms
Greg Hudson
ghudson at MIT.EDU
Tue Oct 2 00:57:18 EDT 2012
https://github.com/krb5/krb5/commit/acc8f98c9be4d10f325367cbdb3b0521fbdb3afa
commit acc8f98c9be4d10f325367cbdb3b0521fbdb3afa
Author: Simo Sorce <simo at redhat.com>
Date: Mon Jun 11 11:50:26 2012 -0400
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 at mit.edu: Stylistic changes, commit squashing, commit message]
src/lib/gssapi/mechglue/g_initialize.c | 151 +++++++++++++++++++++++++++++++-
src/lib/gssapi/mechglue/mglueP.h | 5 +
2 files changed, 152 insertions(+), 4 deletions(-)
diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
index dc6b8ea..fbd0b07 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)
{
@@ -885,6 +899,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 21eefdb..2d0fd4a 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);
More information about the cvs-krb5
mailing list