krb5_error_code k5glue_ser_init(krb5_context);
-static OM_uint32 k5glue_release_oid
+static OM_uint32 k5glue_internal_release_oid
(void *, OM_uint32 *, /* minor_status */
gss_OID * /* oid */
);
);
#endif
+/*
+ * The krb5 mechanism provides two mech OIDs; use this initializer to
+ * ensure that both dispatch tables contain identical function
+ * pointers.
+ */
+#define KRB5_GSS_CONFIG_INIT \
+ NULL, \
+ k5glue_acquire_cred, \
+ k5glue_release_cred, \
+ k5glue_init_sec_context, \
+ k5glue_accept_sec_context, \
+ k5glue_process_context_token, \
+ k5glue_delete_sec_context, \
+ k5glue_context_time, \
+ k5glue_sign, \
+ k5glue_verify, \
+ k5glue_seal, \
+ k5glue_unseal, \
+ k5glue_display_status, \
+ k5glue_indicate_mechs, \
+ k5glue_compare_name, \
+ k5glue_display_name, \
+ k5glue_import_name, \
+ k5glue_release_name, \
+ k5glue_inquire_cred, \
+ k5glue_add_cred, \
+ k5glue_export_sec_context, \
+ k5glue_import_sec_context, \
+ k5glue_inquire_cred_by_mech, \
+ k5glue_inquire_names_for_mech, \
+ k5glue_inquire_context, \
+ k5glue_internal_release_oid, \
+ k5glue_wrap_size_limit, \
+ NULL, /* pname_to_uid */ \
+ NULL, /* userok */ \
+ k5glue_export_name, \
+ NULL /* store_cred */
+
struct gss_config krb5_mechanism = {
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
- NULL,
- k5glue_acquire_cred,
- k5glue_release_cred,
- k5glue_init_sec_context,
- k5glue_accept_sec_context,
- k5glue_process_context_token,
- k5glue_delete_sec_context,
- k5glue_context_time,
- k5glue_sign,
- k5glue_verify,
- k5glue_seal,
- k5glue_unseal,
- k5glue_display_status,
- k5glue_indicate_mechs,
- k5glue_compare_name,
- k5glue_display_name,
- k5glue_import_name,
- k5glue_release_name,
- k5glue_inquire_cred,
- k5glue_add_cred,
- k5glue_export_sec_context,
- k5glue_import_sec_context,
- k5glue_inquire_cred_by_mech,
- k5glue_inquire_names_for_mech,
- k5glue_inquire_context,
- k5glue_release_oid,
- k5glue_wrap_size_limit,
- NULL, /* pname_to_uid */
- NULL, /* userok */
- k5glue_export_name,
- NULL /* store_cred */
+ KRB5_GSS_CONFIG_INIT
+};
+
+struct gss_config krb5_mechanism_old = {
+ { GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID },
+ KRB5_GSS_CONFIG_INIT
};
#ifdef KRB5_MECH_MODULE
gss_mechanism
gss_mech_initialize(const gss_OID oid)
{
- if (oid == NULL ||
- !g_OID_equal(oid, &krb5_mechanism.mech_type)) {
+ if (oid == NULL)
return NULL;
- }
- return &krb5_mechanism;
+
+ if (g_OID_equal(oid, &krb5_mechanism.mech_type))
+ return &krb5_mechanism;
+
+ if (g_OID_equal(oid, &krb5_mechanism_old.mech_type))
+ return &krb5_mechanism_old;
+
+ return NULL;
}
#endif
/* V2 */
static OM_uint32
-k5glue_release_oid(ctx, minor_status, oid)
+k5glue_internal_release_oid(ctx, minor_status, oid)
void *ctx;
OM_uint32 *minor_status;
gss_OID *oid;
{
- return(krb5_gss_release_oid(minor_status, oid));
+ return(krb5_gss_internal_release_oid(minor_status, oid));
}
#if 0
gss_union_ctx_id_t uctx;
uctx = (gss_union_ctx_id_t)context_handle;
- if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type))
+ if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type) &&
+ !g_OID_equal(uctx->mech_type, &krb5_mechanism_old.mech_type))
return GSS_S_BAD_MECH;
return gss_krb5int_get_tkt_flags(minor_status, uctx->internal_ctx_id,
ticket_flags);
gss_cred_id_t mcred;
ucred = (gss_union_cred_t)cred_handle;
+
mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism.mech_type);
- if (mcred == NULL)
- return GSS_S_DEFECTIVE_CREDENTIAL;
- return gss_krb5int_copy_ccache(minor_status, mcred, out_ccache);
+ if (mcred != GSS_C_NO_CREDENTIAL)
+ return gss_krb5int_copy_ccache(minor_status, mcred, out_ccache);
+
+ mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism_old.mech_type);
+ if (mcred != GSS_C_NO_CREDENTIAL)
+ return gss_krb5int_copy_ccache(minor_status, mcred, out_ccache);
+
+ return GSS_S_DEFECTIVE_CREDENTIAL;
}
/* XXX need to delete mechglue ctx too */
gss_union_ctx_id_t uctx;
uctx = (gss_union_ctx_id_t)*context_handle;
- if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type))
+ if (!g_OID_equal(uctx->mech_type, &krb5_mechanism.mech_type) &&
+ !g_OID_equal(uctx->mech_type, &krb5_mechanism_old.mech_type))
return GSS_S_BAD_MECH;
return gss_krb5int_export_lucid_sec_context(minor_status,
&uctx->internal_ctx_id,
ucred = (gss_union_cred_t)cred;
mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism.mech_type);
- if (mcred == NULL)
- return GSS_S_DEFECTIVE_CREDENTIAL;
- return gss_krb5int_set_allowable_enctypes(minor_status, mcred,
- num_ktypes, ktypes);
+ if (mcred != GSS_C_NO_CREDENTIAL)
+ return gss_krb5int_set_allowable_enctypes(minor_status, mcred,
+ num_ktypes, ktypes);
+
+ mcred = gssint_get_mechanism_cred(ucred, &krb5_mechanism_old.mech_type);
+ if (mcred != GSS_C_NO_CREDENTIAL)
+ return gss_krb5int_set_allowable_enctypes(minor_status, mcred,
+ num_ktypes, ktypes);
+
+ return GSS_S_DEFECTIVE_CREDENTIAL;
}
#include "k5-thread.h"
-extern gss_mechanism krb5_gss_initialize();
-
-static int _gss_initialized = 0;
-
-static struct gss_config null_mech = {
- {0,NULL}};
-
-gss_mechanism *gssint_mechs_array = NULL;
-
/* Local functions */
static gss_mech_info searchMechList(const gss_OID);
static void loadConfigFile(const char *);
static void updateMechList(void);
+static OM_uint32 build_mechSet(void);
static void init_hardcoded(void);
/*
gss_OID *oid;
{
OM_uint32 major;
- gss_mech_info aMech = g_mechList;
+ gss_mech_info aMech;
if (minor_status == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
*minor_status = 0;
+ k5_mutex_lock(&g_mechListLock);
+ aMech = g_mechList;
while (aMech != NULL) {
/*
* the OID was recognized as an internal mechanism OID. if no
* mechanisms recognize the OID, then call the generic version.
*/
-
- /*
- * we can walk the mechanism list without a mutex, because we
- * are only looking at fields which once read will never change.
- * Mechanism entries are always added to the end, and as
- * complete entries.
- */
if (aMech->mech && aMech->mech->gss_internal_release_oid) {
major = aMech->mech->gss_internal_release_oid(
aMech->mech->context,
minor_status, oid);
- if (major == GSS_S_COMPLETE)
+ if (major == GSS_S_COMPLETE) {
+ k5_mutex_unlock(&g_mechListLock);
return (GSS_S_COMPLETE);
+ }
}
aMech = aMech->next;
} /* while */
+ k5_mutex_unlock(&g_mechListLock);
return (generic_gss_release_oid(minor_status, oid));
} /* gss_release_oid */
OM_uint32 *minorStatus;
gss_OID_set *mechSet;
{
- gss_mech_info mList;
char *fileName;
struct stat fileInfo;
- int count, i, j;
+ int i, j;
gss_OID curItem;
if (!minorStatus)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ if (gssint_initialize_library())
+ return GSS_S_FAILURE;
*minorStatus = 0;
fileName = MECH_CONF;
+#if 0
/*
* If we have already computed the mechanisms supported and if it
* is still valid; make a copy and return to caller,
*/
if ((stat(fileName, &fileInfo) == 0 &&
fileInfo.st_mtime > g_mechSetTime)) {
- /*
- * lock the mutex since we will be updating
- * the mechList structure
- * we need to keep the lock while we build the mechanism list
- * since we are accessing parts of the mechList which could be
- * modified.
- */
- (void) k5_mutex_lock(&g_mechListLock);
-
- /*
- * this checks for the case when we need to re-construct the
- * g_mechSet structure, but the mechanism list is upto date
- * (because it has been read by someone calling
- * gssint_get_mechanism)
- */
- if (fileInfo.st_mtime > g_confFileModTime)
- {
- g_confFileModTime = fileInfo.st_mtime;
- loadConfigFile(fileName);
- }
-
- /*
- * we need to lock the mech set so that no one else will
- * try to read it as we are re-creating it
- */
- (void) k5_mutex_lock(&g_mechSetLock);
-
- /* if the oid list already exists we must free it first */
- if (g_mechSet.count != 0) {
- for (i = 0; i < g_mechSet.count; i++)
- free(g_mechSet.elements[i].elements);
- free(g_mechSet.elements);
- g_mechSet.elements = NULL;
- g_mechSet.count = 0;
- }
-
- /* determine how many elements to have in the list */
- mList = g_mechList;
- count = 0;
- while (mList != NULL) {
- count++;
- mList = mList->next;
- }
-
- /* this should always be true, but.... */
- if (count > 0) {
- g_mechSet.elements =
- (gss_OID) calloc(count, sizeof (gss_OID_desc));
- if (g_mechSet.elements == NULL) {
- (void) k5_mutex_unlock(&g_mechSetLock);
- (void) k5_mutex_unlock(&g_mechListLock);
- return (GSS_S_FAILURE);
- }
-
- (void) memset(g_mechSet.elements, 0,
- count * sizeof (gss_OID_desc));
-
- /* now copy each oid element */
- g_mechSet.count = count;
- count = 0;
- mList = g_mechList;
- while (mList != NULL) {
- curItem = &(g_mechSet.elements[count]);
- curItem->elements = (void*)
- malloc(mList->mech_type->length);
- if (curItem->elements == NULL) {
- /*
- * this is nasty - we must delete the
- * part of the array already copied
- */
- for (i = 0; i < count; i++) {
- free(g_mechSet.elements[i].
- elements);
- }
- free(g_mechSet.elements);
- g_mechSet.count = 0;
- g_mechSet.elements = NULL;
- (void) k5_mutex_unlock(&g_mechSetLock);
- (void) k5_mutex_unlock(&g_mechListLock);
- return (GSS_S_FAILURE);
- }
- g_OID_copy(curItem, mList->mech_type);
- count++;
- mList = mList->next;
- }
- }
-
- g_mechSetTime = fileInfo.st_mtime;
- (void) k5_mutex_unlock(&g_mechSetLock);
- (void) k5_mutex_unlock(&g_mechListLock);
} /* if g_mechSet is out of date or not initialized */
+#endif
+ if (build_mechSet())
+ return GSS_S_FAILURE;
/*
* the mech set is created and it is up to date
return (GSS_S_COMPLETE);
} /* gss_indicate_mechs */
+
+static OM_uint32
+build_mechSet(void)
+{
+ gss_mech_info mList;
+ int i, count;
+ gss_OID curItem;
+
+ /*
+ * lock the mutex since we will be updating
+ * the mechList structure
+ * we need to keep the lock while we build the mechanism list
+ * since we are accessing parts of the mechList which could be
+ * modified.
+ */
+ (void) k5_mutex_lock(&g_mechListLock);
+
+#if 0
+ /*
+ * this checks for the case when we need to re-construct the
+ * g_mechSet structure, but the mechanism list is upto date
+ * (because it has been read by someone calling
+ * gssint_get_mechanism)
+ */
+ if (fileInfo.st_mtime > g_confFileModTime)
+ {
+ g_confFileModTime = fileInfo.st_mtime;
+ loadConfigFile(fileName);
+ }
+#endif
+
+ updateMechList();
+
+ /*
+ * we need to lock the mech set so that no one else will
+ * try to read it as we are re-creating it
+ */
+ (void) k5_mutex_lock(&g_mechSetLock);
+
+ /* if the oid list already exists we must free it first */
+ if (g_mechSet.count != 0) {
+ for (i = 0; i < g_mechSet.count; i++)
+ free(g_mechSet.elements[i].elements);
+ free(g_mechSet.elements);
+ g_mechSet.elements = NULL;
+ g_mechSet.count = 0;
+ }
+
+ /* determine how many elements to have in the list */
+ mList = g_mechList;
+ count = 0;
+ while (mList != NULL) {
+ count++;
+ mList = mList->next;
+ }
+
+ /* this should always be true, but.... */
+ if (count > 0) {
+ g_mechSet.elements =
+ (gss_OID) calloc(count, sizeof (gss_OID_desc));
+ if (g_mechSet.elements == NULL) {
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return (GSS_S_FAILURE);
+ }
+
+ (void) memset(g_mechSet.elements, 0,
+ count * sizeof (gss_OID_desc));
+
+ /* now copy each oid element */
+ g_mechSet.count = count;
+ count = 0;
+ mList = g_mechList;
+ while (mList != NULL) {
+ curItem = &(g_mechSet.elements[count]);
+ curItem->elements = (void*)
+ malloc(mList->mech_type->length);
+ if (curItem->elements == NULL) {
+ /*
+ * this is nasty - we must delete the
+ * part of the array already copied
+ */
+ for (i = 0; i < count; i++) {
+ free(g_mechSet.elements[i].
+ elements);
+ }
+ free(g_mechSet.elements);
+ g_mechSet.count = 0;
+ g_mechSet.elements = NULL;
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ (void) k5_mutex_unlock(&g_mechListLock);
+ return (GSS_S_FAILURE);
+ }
+ g_OID_copy(curItem, mList->mech_type);
+ count++;
+ mList = mList->next;
+ }
+ }
+
+#if 0
+ g_mechSetTime = fileInfo.st_mtime;
+#endif
+ (void) k5_mutex_unlock(&g_mechSetLock);
+ (void) k5_mutex_unlock(&g_mechListLock);
+}
+
+
/*
* this function has been added for use by modules that need to
* know what (if any) optional parameters are supplied in the
/* make sure we have fresh data */
(void) k5_mutex_lock(&g_mechListLock);
updateMechList();
- (void) k5_mutex_unlock(&g_mechListLock);
- /* searching the list does not require a lock */
if ((aMech = searchMechList(oid)) == NULL ||
aMech->optionStr == NULL) {
+ (void) k5_mutex_unlock(&g_mechListLock);
return (NULL);
}
- /*
- * need to obtain a lock on this structure in case someone else
- * will try to update it during the copy
- */
- (void) k5_mutex_lock(&g_mechListLock);
if (aMech->optionStr)
modOptions = strdup(aMech->optionStr);
(void) k5_mutex_unlock(&g_mechListLock);
/* ensure we have fresh data */
(void) k5_mutex_lock(&g_mechListLock);
updateMechList();
+ aMech = searchMechList(oid);
(void) k5_mutex_unlock(&g_mechListLock);
- if ((aMech = searchMechList(oid)) == NULL)
+ if (aMech == NULL)
return (NULL);
return (aMech->mechNameStr);
init_hardcoded();
fileName = MECH_CONF;
+#if 0
/* check if mechList needs updating */
if (stat(fileName, &fileInfo) == 0 &&
(fileInfo.st_mtime > g_confFileModTime)) {
loadConfigFile(fileName);
g_confFileModTime = fileInfo.st_mtime;
}
+#endif
} /* updateMechList */
-
+/*
+ * Initialize the hardcoded mechanisms. This function is called with
+ * g_mechListLock held.
+ */
static void
init_hardcoded(void)
{
extern struct gss_config krb5_mechanism;
+ extern struct gss_config krb5_mechanism_old;
+ extern struct gss_config spnego_mechanism;
+ static int inited;
gss_mech_info cf;
- if (g_mechList != NULL)
+ if (inited)
return;
+
cf = malloc(sizeof(*cf));
if (cf == NULL)
return;
cf->mech = &krb5_mechanism;
cf->next = NULL;
g_mechList = cf;
+
+ cf = malloc(sizeof(*cf));
+ if (cf == NULL)
+ return;
+ memset(cf, 0, sizeof(*cf));
+ cf->uLibName = strdup("<hardcoded internal>");
+ cf->mechNameStr = "kerberos_v5 (old)";
+ cf->mech_type = &krb5_mechanism_old.mech_type;
+ cf->mech = &krb5_mechanism_old;
+ cf->next = NULL;
+ g_mechList->next = cf;
+
+ cf = malloc(sizeof(*cf));
+ if (cf == NULL)
+ return;
+ memset(cf, 0, sizeof(*cf));
+ cf->uLibName = strdup("<hardcoded internal>");
+ cf->mechNameStr = "spnego";
+ cf->mech_type = &spnego_mechanism.mech_type;
+ cf->mech = &spnego_mechanism;
+ cf->next = NULL;
+ g_mechList->next->next = cf;
+
+ inited = 1;
}
void *dl;
if (gssint_initialize_library())
- return GSS_S_FAILURE;
+ return NULL;
+ (void) k5_mutex_lock(&g_mechListLock);
/* check if the mechanism is already loaded */
if ((aMech = searchMechList(oid)) != NULL && aMech->mech) {
+ (void) k5_mutex_unlock(&g_mechListLock);
return (aMech->mech);
}
* might need to re-read the configuration file before loading
* the mechanism to ensure we have the latest info.
*/
- (void) k5_mutex_lock(&g_mechListLock);
updateMechList();
aMech = searchMechList(oid);
/*
* this routine is used for searching the list of mechanism data.
- * it needs not be mutex protected because we only add new structures
- * from the end and they are fully initialized before being added.
+ *
+ * this needs to be called with g_mechListLock held.
*/
static gss_mech_info searchMechList(oid)
const gss_OID oid;
continue;
}
+ k5_mutex_lock(&g_mechListLock);
aMech = searchMechList(mechOid);
if (aMech && aMech->mech) {
free(mechOid->elements);
free(mechOid);
+ k5_mutex_unlock(&g_mechListLock);
continue;
}
+ k5_mutex_unlock(&g_mechListLock);
/* Find the start of the shared lib name */
for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib);
} /* while */
(void) fclose(confFile);
} /* loadConfigFile */
-
-
-#ifdef USE_SOLARIS_SHARED_LIBRARIES
-/*
- * read the configuration file to find out what mechanisms to
- * load, load them, and then load the mechanism defitions in
- * and add the mechanisms
- */
-static void solaris_initialize ()
-{
- char buffer[BUFSIZ], *filename, *symname, *endp;
- FILE *conffile;
- void *dl;
- gss_mechanism (*sym)(void), mech;
-
- if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)
- filename = MECH_CONF;
-
- if ((conffile = fopen(filename, "r")) == NULL)
- return;
-
- while (fgets (buffer, BUFSIZ, conffile) != NULL) {
- /* ignore lines beginning with # */
- if (*buffer == '#')
- continue;
-
- /* find the first white-space character after the filename */
- for (symname = buffer; *symname && !isspace(*symname); symname++);
-
- /* Now find the first non-white-space character */
- if (*symname) {
- *symname = '\0';
- symname++;
- while (*symname && isspace(*symname))
- symname++;
- }
-
- if (! *symname)
- symname = MECH_SYM;
- else {
- /* Find the end of the symname and make sure it is NULL-terminated */
- for (endp = symname; *endp && !isspace(*endp); endp++);
- if (*endp)
- *endp = '\0';
- }
-
- if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) {
- /* for debugging only */
- fprintf(stderr,"can't open %s: %s\n",buffer, dlerror());
- continue;
- }
-
- if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) {
- dlclose(dl);
- continue;
- }
-
- /* Call the symbol to get the mechanism table */
- mech = sym();
-
- /* And add the mechanism (or close the shared library) */
- if (mech)
- add_mechanism (mech, 1);
- else
- dlclose(dl);
-
- } /* while */
-
- return;
-}
-#endif /* USE_SOLARIS_SHARED_LIBRARIES */
*
*/
-#pragma ident "@(#)spnego_mech.c 1.7 04/09/28 SMI"
+/* #pragma ident "@(#)spnego_mech.c 1.7 04/09/28 SMI" */
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <krb5.h>
#include "gssapiP_spnego.h"
#include <mglueP.h>
* { iso(1) org(3) dod(6) internet(1) security(5)
* mechanism(5) spnego(2) }
*/
-static struct gss_config spnego_mechanism =
+struct gss_config spnego_mechanism =
{{SPNEGO_OID_LENGTH, SPNEGO_OID},
NULL,
spnego_gss_acquire_cred,
spnego_gss_release_cred,
spnego_gss_init_sec_context,
spnego_gss_accept_sec_context,
-/* EXPORT DELETE START */ /* CRYPT DELETE START */
- spnego_gss_unseal, /* gss_unseal */
-/* EXPORT DELETE END */ /* CRYPT DELETE END */
NULL, /* gss_process_context_token */
spnego_gss_delete_sec_context, /* gss_delete_sec_context */
spnego_gss_context_time, /* gss_context_time */
+ spnego_gss_sign, /* gss_sign */
+ spnego_gss_verify, /* gss_verify */
+ spnego_gss_seal, /* gss_seal */
+ spnego_gss_unseal, /* gss_unseal */
spnego_gss_display_status,
NULL, /* gss_indicate_mechs */
NULL, /* gss_compare_name */
spnego_gss_release_name,
NULL, /* gss_inquire_cred */
NULL, /* gss_add_cred */
-/* EXPORT DELETE START */ /* CRYPT DELETE START */
- spnego_gss_seal, /* gss_seal */
-/* EXPORT DELETE END */ /* CRYPT DELETE END */
spnego_gss_export_sec_context, /* gss_export_sec_context */
spnego_gss_import_sec_context, /* gss_import_sec_context */
NULL, /* gss_inquire_cred_by_mech */
NULL, /* gss_pname_to_uid */
NULL, /* gssint_userok */
NULL, /* gss_export_name */
-/* EXPORT DELETE START */
-/* CRYPT DELETE START */
-#if 0
-/* CRYPT DELETE END */
- spnego_gss_seal,
- spnego_gss_unseal,
-/* CRYPT DELETE START */
-#endif
-/* CRYPT DELETE END */
-/* EXPORT DELETE END */
- spnego_gss_sign, /* gss_sign */
- spnego_gss_verify, /* gss_verify */
NULL, /* gss_store_cred */
};
+#if 0
gss_mechanism
gss_mech_initialize(const gss_OID oid)
{
dsyslog("Leaving gss_mech_initialize\n");
return (&spnego_mechanism);
}
+#endif
/*ARGSUSED*/
OM_uint32