diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libgss/g_initialize.c | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libgss/g_initialize.c')
-rw-r--r-- | usr/src/lib/libgss/g_initialize.c | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/usr/src/lib/libgss/g_initialize.c b/usr/src/lib/libgss/g_initialize.c new file mode 100644 index 0000000000..24d70252e5 --- /dev/null +++ b/usr/src/lib/libgss/g_initialize.c @@ -0,0 +1,938 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file contains functions to initialize the gssapi library and + * load mechanism libraries. + * + * It also contain functions requiring direct access to the mechanism's + * list (gss_inidicate_mechs and gss_release_oid) as well as support + * functions which translate the mechanism strings to oids and vise versa. + * + * The mechanism libraries are loaded on demand. This is triggered + * through the get_mechanism function call. + * + * Updates to the mechList are performed with the following restrictions: + * - once a library is loaded, none of the fields are updated + * - existing entiries for non-loaded mechs, will have the + * library and kernel module names updated only + * (i.e. the mech oid and mech name will not be updated) + */ + +#include <mechglueP.h> +#include <stdio.h> +#include <syslog.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <ctype.h> +#include <errno.h> +#include <synch.h> +#include <dlfcn.h> +#include <libintl.h> + + +#ifndef TEXT_DOMAIN +#error TEXT_DOMAIN not defined +#endif + +#define MECH_CONF "/etc/gss/mech" + +#define MECH_LIB_PREFIX1 "/usr/lib/" + +/* + * This #ifdef mess figures out if we are to be compiled into + * a sparcv9/lp64 binary for the purposes of figuring the absolute location + * of gss-api mechanism modules. + */ +#ifdef _LP64 + +#ifdef __sparc + +#define MECH_LIB_PREFIX2 "sparcv9/" + +#elif defined(__amd64) + +#define MECH_LIB_PREFIX2 "amd64/" + +#else /* __sparc */ + +you need to define where under /usr the LP64 libraries live for this platform + +#endif /* __sparc */ + +#else /* _LP64 */ + +#define MECH_LIB_PREFIX2 "" + +#endif /* _LP64 */ + +#define MECH_LIB_DIR "gss/" + +#define MECH_LIB_PREFIX MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR + + +#ifndef MECH_SYM +#define MECH_SYM "gss_mech_initialize" +#endif + +#define M_DEFAULT "default" + +/* Local functions */ +static gss_mech_info searchMechList(const gss_OID); +static void loadConfigFile(const char *); +static void updateMechList(void); + + +/* + * list of mechanism libraries and their entry points. + * the list also maintains state of the mech libraries (loaded or not). + */ +static gss_mech_info g_mechList = NULL; +static gss_mech_info g_mechListTail = NULL; +static mutex_t g_mechListLock; +static time_t g_confFileModTime = (time_t)0; + +/* + * function used to reclaim the memory used by a gss_OID structure. + * This routine requires direct access to the mechList. + */ +OM_uint32 +gss_release_oid(minor_status, oid) +OM_uint32 *minor_status; +gss_OID *oid; +{ + OM_uint32 major; + gss_mech_info aMech = g_mechList; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minor_status = 0; + + while (aMech != NULL) { + + /* + * look through the loaded mechanism libraries for + * gss_internal_release_oid until one returns success. + * gss_internal_release_oid will only return success when + * 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) + return (GSS_S_COMPLETE); + } + aMech = aMech->next; + } /* while */ + + return (generic_gss_release_oid(minor_status, oid)); +} /* gss_release_oid */ + + +/* + * this function will return an oid set indicating available mechanisms. + * The set returned is based on configuration file entries and + * NOT on the loaded mechanisms. This function does not check if any + * of these can actually be loaded. + * This routine needs direct access to the mechanism list. + * To avoid reading the configuration file each call, we will save a + * a mech oid set, and only update it once the file has changed. + */ +static time_t g_mechSetTime = (time_t)0; +static gss_OID_set_desc g_mechSet = { 0, NULL }; +static mutex_t g_mechSetLock; + + +OM_uint32 +gss_indicate_mechs(minorStatus, mechSet) +OM_uint32 *minorStatus; +gss_OID_set *mechSet; +{ + gss_mech_info mList; + char *fileName; + struct stat fileInfo; + int count, i, j; + gss_OID curItem; + + if (!minorStatus) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minorStatus = 0; + + + /* check output parameter */ + if (mechSet == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + fileName = MECH_CONF; + + /* + * If we have already computed the mechanisms supported and if it + * is still valid; make a copy and return to caller, + * otherwise build it first. + */ + 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) 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 + * __gss_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) 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) mutex_unlock(&g_mechSetLock); + (void) 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) mutex_unlock(&g_mechSetLock); + (void) 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) mutex_unlock(&g_mechSetLock); + (void) mutex_unlock(&g_mechListLock); + } /* if g_mechSet is out of date or not initialized */ + + /* + * the mech set is created and it is up to date + * so just copy it to caller + */ + if ((*mechSet = + (gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL) + { + return (GSS_S_FAILURE); + } + + /* + * need to lock the g_mechSet in case someone tries to update it while + * I'm copying it. + */ + (void) mutex_lock(&g_mechSetLock); + + /* allocate space for the oid structures */ + if (((*mechSet)->elements = + (void*) calloc(g_mechSet.count, sizeof (gss_OID_desc))) + == NULL) + { + (void) mutex_unlock(&g_mechSetLock); + free(*mechSet); + *mechSet = NULL; + return (GSS_S_FAILURE); + } + + /* now copy the oid structures */ + (void) memcpy((*mechSet)->elements, g_mechSet.elements, + g_mechSet.count * sizeof (gss_OID_desc)); + + (*mechSet)->count = g_mechSet.count; + + /* still need to copy each of the oid elements arrays */ + for (i = 0; i < (*mechSet)->count; i++) { + curItem = &((*mechSet)->elements[i]); + curItem->elements = + (void *) malloc(g_mechSet.elements[i].length); + if (curItem->elements == NULL) { + (void) mutex_unlock(&g_mechSetLock); + /* + * must still free the allocated elements for + * each allocated gss_OID_desc + */ + for (j = 0; j < i; j++) { + free((*mechSet)->elements[j].elements); + } + free((*mechSet)->elements); + free(mechSet); + *mechSet = NULL; + return (GSS_S_FAILURE); + } + g_OID_copy(curItem, &g_mechSet.elements[i]); + } + (void) mutex_unlock(&g_mechSetLock); + return (GSS_S_COMPLETE); +} /* gss_indicate_mechs */ + +/* + * this function has been added for use by modules that need to + * know what (if any) optional parameters are supplied in the + * config file (MECH_CONF). + * It will return the option string for a specified mechanism. + * caller is responsible for freeing the memory + */ +char * +__gss_get_modOptions(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + char *modOptions = NULL; + + /* make sure we have fresh data */ + (void) mutex_lock(&g_mechListLock); + updateMechList(); + (void) mutex_unlock(&g_mechListLock); + + /* searching the list does not require a lock */ + if ((aMech = searchMechList(oid)) == NULL || + aMech->optionStr == NULL) { + return (NULL); + } + + /* + * need to obtain a lock on this structure in case someone else + * will try to update it during the copy + */ + (void) mutex_lock(&g_mechListLock); + if (aMech->optionStr) + modOptions = strdup(aMech->optionStr); + (void) mutex_unlock(&g_mechListLock); + + return (modOptions); +} /* __gss_get_modOptions */ + +/* + * this function has been added for use by gssd. + * It will return the kernel module name for a specified mechanism. + * caller is responsible for freeing the memory + */ +char * +__gss_get_kmodName(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + char *kmodName = NULL; + + /* make sure we have fresh data */ + (void) mutex_lock(&g_mechListLock); + updateMechList(); + (void) mutex_unlock(&g_mechListLock); + + /* searching the list does not require a lock */ + if ((aMech = searchMechList(oid)) == NULL || aMech->kmodName == NULL) { + return (NULL); + } + + /* + * need to obtain a lock on this structure in case someone else + * will try to update it during the copy + */ + (void) mutex_lock(&g_mechListLock); + if (aMech->kmodName) + kmodName = strdup(aMech->kmodName); + (void) mutex_unlock(&g_mechListLock); + + return (kmodName); +} /* __gss_get_kmodName */ + + +/* + * given a mechanism string return the mechanism oid + */ +OM_uint32 +__gss_mech_to_oid(const char *mechStr, gss_OID* oid) +{ + gss_mech_info aMech; + + if (oid == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *oid = GSS_C_NULL_OID; + + if ((mechStr == NULL) || (strlen(mechStr) == 0) || + (strcasecmp(mechStr, M_DEFAULT) == 0)) + return (GSS_S_COMPLETE); + + /* ensure we have fresh data */ + (void) mutex_lock(&g_mechListLock); + updateMechList(); + (void) mutex_unlock(&g_mechListLock); + + aMech = g_mechList; + + /* no lock required - only looking at fields that are not updated */ + while (aMech != NULL) { + if ((aMech->mechNameStr) && + strcmp(aMech->mechNameStr, mechStr) == 0) { + *oid = aMech->mech_type; + return (GSS_S_COMPLETE); + } + aMech = aMech->next; + } + return (GSS_S_FAILURE); +} /* __gss_mech_to_oid */ + + +/* + * Given the mechanism oid, return the readable mechanism name + * associated with that oid from the mech config file + * (/etc/gss/mech). + */ +const char * +__gss_oid_to_mech(const gss_OID oid) +{ + gss_mech_info aMech; + + if (oid == GSS_C_NULL_OID) + return (M_DEFAULT); + + /* ensure we have fresh data */ + (void) mutex_lock(&g_mechListLock); + updateMechList(); + (void) mutex_unlock(&g_mechListLock); + + if ((aMech = searchMechList(oid)) == NULL) + return (NULL); + + return (aMech->mechNameStr); +} /* __gss_oid_to_mech */ + + +/* + * return a list of mechanism strings supported + * upon return the array is terminated with a NULL entry + */ +OM_uint32 +__gss_get_mechanisms(char *mechArray[], int arrayLen) +{ + gss_mech_info aMech; + int i; + + if (mechArray == NULL || arrayLen < 1) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* ensure we have fresh data */ + (void) mutex_lock(&g_mechListLock); + updateMechList(); + (void) mutex_unlock(&g_mechListLock); + + aMech = g_mechList; + + /* no lock required - only looking at fields that are not updated */ + for (i = 1; i < arrayLen; i++) { + if (aMech != NULL) { + *mechArray = aMech->mechNameStr; + mechArray++; + aMech = aMech->next; + } else + break; + } + *mechArray = NULL; + return (GSS_S_COMPLETE); +} /* gss_get_mechanisms */ + + +/* + * determines if the mechList needs to be updated from file + * and performs the update. + * this functions must be called with a lock of g_mechListLock + */ +static void +updateMechList(void) +{ + char *fileName; + struct stat fileInfo; + + fileName = MECH_CONF; + + /* check if mechList needs updating */ + if (stat(fileName, &fileInfo) == 0 && + (fileInfo.st_mtime > g_confFileModTime)) { + loadConfigFile(fileName); + g_confFileModTime = fileInfo.st_mtime; + } +} /* updateMechList */ + + +/* + * given the mechanism type, return the mechanism structure + * containing the mechanism library entry points. + * will return NULL if mech type is not found + * This function will also trigger the loading of the mechanism + * module if it has not been already loaded. + */ +gss_mechanism +__gss_get_mechanism(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + gss_mechanism (*sym)(const gss_OID); + void *dl; + + /* check if the mechanism is already loaded */ + if ((aMech = searchMechList(oid)) != NULL && aMech->mech) { + return (aMech->mech); + } + + /* + * might need to re-read the configuration file before loading + * the mechanism to ensure we have the latest info. + */ + (void) mutex_lock(&g_mechListLock); + updateMechList(); + + aMech = searchMechList(oid); + + /* is the mechanism present in the list ? */ + if (aMech == NULL) { + (void) mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + /* has another thread loaded the mech */ + if (aMech->mech) { + (void) mutex_unlock(&g_mechListLock); + return (aMech->mech); + } + + /* we found the mechanism, but it is not loaded */ + if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) { + (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n", + aMech->uLibName, dlerror()); + (void) mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM)) + == NULL) { + (void) dlclose(dl); + (void) syslog(LOG_INFO, "unable to initialize mechanism" + " library [%s]\n", aMech->uLibName); + (void) mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + /* Call the symbol to get the mechanism table */ + aMech->mech = (*sym)(aMech->mech_type); + + if (aMech->mech == NULL) { + (void) dlclose(dl); + (void) syslog(LOG_INFO, "unable to initialize mechanism" + " library [%s]\n", aMech->uLibName); + (void) mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + aMech->dl_handle = dl; + + (void) mutex_unlock(&g_mechListLock); + return (aMech->mech); +} /* __gss_get_mechanism */ + +gss_mechanism_ext +__gss_get_mechanism_ext(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + gss_mechanism_ext mech_ext; + + /* check if the mechanism is already loaded */ + if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL) + return (aMech->mech_ext); + + if (__gss_get_mechanism(oid) == NULL) + return (NULL); + + if (aMech->dl_handle == NULL) + return (NULL); + + /* Load the gss_config_ext struct for this mech */ + + mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext)); + + if (mech_ext == NULL) + return (NULL); + + /* + * dlsym() the mech's 'method' functions for the extended APIs + * + * NOTE: Until the void *context argument is removed from the + * SPI method functions' signatures it will be necessary to have + * different function pointer typedefs and function names for + * the SPI methods than for the API. When this argument is + * removed it will be possible to rename gss_*_sfct to gss_*_fct + * and and gssspi_* to gss_*. + */ + mech_ext->gss_acquire_cred_with_password = + (gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle, + "gssspi_acquire_cred_with_password"); + + /* Set aMech->mech_ext */ + (void) mutex_lock(&g_mechListLock); + + if (aMech->mech_ext == NULL) + aMech->mech_ext = mech_ext; + else + free(mech_ext); /* we raced and lost; don't leak */ + + (void) mutex_unlock(&g_mechListLock); + + return (aMech->mech_ext); + +} /* __gss_get_mechanism_ext */ + + +/* + * 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. + */ +static gss_mech_info searchMechList(oid) +const gss_OID oid; +{ + gss_mech_info aMech = g_mechList; + + /* if oid is null -> then get default which is the first in the list */ + if (oid == GSS_C_NULL_OID) + return (aMech); + + while (aMech != NULL) { + if (g_OID_equal(aMech->mech_type, oid)) + return (aMech); + aMech = aMech->next; + } + + /* none found */ + return ((gss_mech_info) NULL); +} /* searchMechList */ + + +/* + * loads the configuration file + * this is called while having a mutex lock on the mechanism list + * entries for libraries that have been loaded can't be modified + * mechNameStr and mech_type fields are not updated during updates + */ +static void loadConfigFile(fileName) +const char *fileName; +{ + char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp; + char *modOptions; + char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ]; + char *tmpStr; + FILE *confFile; + gss_OID mechOid; + gss_mech_info aMech, tmp; + OM_uint32 minor; + gss_buffer_desc oidBuf; + + if ((confFile = fopen(fileName, "r")) == NULL) { + return; + } + + (void) memset(buffer, 0, sizeof (buffer)); + while (fgets(buffer, BUFSIZ, confFile) != NULL) { + + /* ignore lines beginning with # */ + if (*buffer == '#') + continue; + + /* + * find the first white-space character after + * the mechanism name + */ + oidStr = buffer; + for (oid = buffer; *oid && !isspace(*oid); oid++); + + /* Now find the first non-white-space character */ + if (*oid) { + *oid = '\0'; + oid++; + while (*oid && isspace(*oid)) + oid++; + } + + /* + * If that's all, then this is a corrupt entry. Skip it. + */ + if (! *oid) + continue; + + /* Find the end of the oid and make sure it is NULL-ended */ + for (endp = oid; *endp && !isspace(*endp); endp++) + ; + + if (*endp) { + *endp = '\0'; + } + + /* + * check if an entry for this oid already exists + * if it does, and the library is already loaded then + * we can't modify it, so skip it + */ + oidBuf.value = (void *)oid; + oidBuf.length = strlen(oid); + if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid) + != GSS_S_COMPLETE) { + (void) syslog(LOG_INFO, "invalid mechanism oid" + " [%s] in configuration file", oid); + continue; + } + + aMech = searchMechList(mechOid); + if (aMech && aMech->mech) { + free(mechOid->elements); + free(mechOid); + continue; + } + + /* Find the start of the shared lib name */ + for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib); + sharedLib++) + ; + + /* + * If that's all, then this is a corrupt entry. Skip it. + */ + if (! *sharedLib) { + free(mechOid->elements); + free(mechOid); + continue; + } + + /* + * Find the end of the shared lib name and make sure it is + * NULL-terminated. + */ + for (endp = sharedLib; *endp && !isspace(*endp); endp++) + ; + + if (*endp) { + *endp = '\0'; + } + + /* Find the start of the optional kernel module lib name */ + for (kernMod = endp+1; *kernMod && isspace(*kernMod); + kernMod++) + ; + + /* + * If this item starts with a bracket "[", then + * it is not a kernel module, but is a list of + * options for the user module to parse later. + */ + if (*kernMod && *kernMod != '[') { + /* + * Find the end of the shared lib name and make sure + * it is NULL-terminated. + */ + for (endp = kernMod; *endp && !isspace(*endp); endp++) + ; + + if (*endp) { + *endp = '\0'; + } + } else + kernMod = NULL; + + /* Find the start of the optional module options list */ + for (modOptions = endp+1; *modOptions && isspace(*modOptions); + modOptions++); + + if (*modOptions == '[') { + /* move past the opening bracket */ + for (modOptions = modOptions+1; + *modOptions && isspace(*modOptions); + modOptions++); + + /* Find the closing bracket */ + for (endp = modOptions; + *endp && *endp != ']'; endp++); + + if (endp) + *endp = '\0'; + + } else { + modOptions = NULL; + } + + (void) strcpy(sharedPath, MECH_LIB_PREFIX); + (void) strcat(sharedPath, sharedLib); + + /* + * are we creating a new mechanism entry or + * just modifying existing (non loaded) mechanism entry + */ + if (aMech) { + /* + * delete any old values and set new + * mechNameStr and mech_type are not modified + */ + if (aMech->kmodName) { + free(aMech->kmodName); + aMech->kmodName = NULL; + } + + if (aMech->optionStr) { + free(aMech->optionStr); + aMech->optionStr = NULL; + } + + if ((tmpStr = strdup(sharedPath)) != NULL) { + if (aMech->uLibName) + free(aMech->uLibName); + aMech->uLibName = tmpStr; + } + + if (kernMod) /* this is an optional parameter */ + aMech->kmodName = strdup(kernMod); + + if (modOptions) /* optional module options */ + aMech->optionStr = strdup(modOptions); + + /* the oid is already set */ + free(mechOid->elements); + free(mechOid); + continue; + } + + /* adding a new entry */ + aMech = malloc(sizeof (struct gss_mech_config)); + if (aMech == NULL) { + free(mechOid->elements); + free(mechOid); + continue; + } + (void) memset(aMech, 0, sizeof (struct gss_mech_config)); + aMech->mech_type = mechOid; + aMech->uLibName = strdup(sharedPath); + aMech->mechNameStr = strdup(oidStr); + + /* check if any memory allocations failed - bad news */ + if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) { + if (aMech->uLibName) + free(aMech->uLibName); + if (aMech->mechNameStr) + free(aMech->mechNameStr); + free(mechOid->elements); + free(mechOid); + free(aMech); + continue; + } + if (kernMod) /* this is an optional parameter */ + aMech->kmodName = strdup(kernMod); + + if (modOptions) + aMech->optionStr = strdup(modOptions); + /* + * add the new entry to the end of the list - make sure + * that only complete entries are added because other + * threads might currently be searching the list. + */ + tmp = g_mechListTail; + g_mechListTail = aMech; + + if (tmp != NULL) + tmp->next = aMech; + + if (g_mechList == NULL) + g_mechList = aMech; + } /* while */ + (void) fclose(confFile); +} /* loadConfigFile */ |