/*********************************************************************** * * Copyright (C) 2006 Novell, Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, Novell, Inc. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * * Author: Juan Carlos Luciani * ***********************************************************************/ //===[ Include files ]===================================================== #include "internal.h" //===[ Type definitions ]================================================== // // Identity Token Module definition // typedef struct _IdenTokenProviderModule { LIST_ENTRY listEntry; char *pTypeName; int typeNameLen; void *libHandle; IdenTokenProviderIf *pIdenTokenProviderIf; } IdenTokenProviderModule, *PIdenTokenProviderModule; // // Platform Mutex structure // typedef struct _PlatformMutex { pthread_mutex_t mutex; } PlatformMutex, *PPlatformMutex; //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== // // Module synchronization mutex // pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER; // // IdenTokenProviderModule list and syncronization mutex // static LIST_ENTRY g_IdenTokenProviderModuleListHead = {&g_IdenTokenProviderModuleListHead, &g_IdenTokenProviderModuleListHead}; static pthread_mutex_t g_IdenTokenProviderModuleMutex = PTHREAD_MUTEX_INITIALIZER; //++======================================================================= CasaStatus GetIdenTokenProviderInterface( IN const char *pIdenTokenTypeName, INOUT IdenTokenProviderIf **ppIdenTokenProviderIf) // // Arguments: // // Returns: // // Abstract: // // Notes: // // Environment: // // L2 //=======================================================================-- { CasaStatus retStatus; ConfigIf *pModuleConfigIf; DbgTrace(2, "-GetIdenTokenProviderInterface- Start\n", 0); // Get the configuration for the module retStatus = GetConfigInterface("/etc/opt/novell/CASA/authtoken.d/modules.d", pIdenTokenTypeName, &pModuleConfigIf); if (CASA_SUCCESS(retStatus) && CasaStatusCode(retStatus) != CASA_STATUS_OBJECT_NOT_FOUND) { LIST_ENTRY *pListEntry; IdenTokenProviderModule *pIdenTokenProviderModule = NULL; int32_t idenTokenTypeNameLen = strlen(pIdenTokenTypeName); // Gain exclusive access to our mutex pthread_mutex_lock(&g_IdenTokenProviderModuleMutex); // Look if we already have the module in our list pListEntry = g_IdenTokenProviderModuleListHead.Flink; while (pListEntry != &g_IdenTokenProviderModuleListHead) { // Get pointer to the current entry pIdenTokenProviderModule = CONTAINING_RECORD(pListEntry, IdenTokenProviderModule, listEntry); // Check if this is the module that we need if (pIdenTokenProviderModule->typeNameLen == idenTokenTypeNameLen && memcmp(pIdenTokenTypeName, pIdenTokenProviderModule->pTypeName, idenTokenTypeNameLen) == 0) { // This is the module that we need, stop looking. break; } else { // This is not the module that we are looking for pIdenTokenProviderModule = NULL; } // Advance to the next entry pListEntry = pListEntry->Flink; } // Proceed based on whether or not a module was found if (pIdenTokenProviderModule) { // Module found in our list, provide the caller with its IdenTokenProviderIf // instance after we have incremented its reference count. pIdenTokenProviderModule->pIdenTokenProviderIf->addReference(pIdenTokenProviderModule->pIdenTokenProviderIf); *ppIdenTokenProviderIf = pIdenTokenProviderModule->pIdenTokenProviderIf; // Success retStatus = CASA_STATUS_SUCCESS; } else { // Needed module not found in our list, create an entry. pIdenTokenProviderModule = malloc(sizeof(*pIdenTokenProviderModule)); if (pIdenTokenProviderModule) { // Allocate buffer to contain the authentication type name within the module entry pIdenTokenProviderModule->pTypeName = malloc(idenTokenTypeNameLen + 1); if (pIdenTokenProviderModule->pTypeName) { char *pLibraryName; // Initialize the library handle field pIdenTokenProviderModule->libHandle = NULL; // Save the auth type name within the entry strcpy(pIdenTokenProviderModule->pTypeName, pIdenTokenTypeName); pIdenTokenProviderModule->typeNameLen = idenTokenTypeNameLen; // Obtain the name of the library that we must load pLibraryName = pModuleConfigIf->getEntryValue(pModuleConfigIf, "LibraryName"); if (pLibraryName) { // Load the library pIdenTokenProviderModule->libHandle = dlopen(pLibraryName, RTLD_LAZY); if (pIdenTokenProviderModule->libHandle) { PFN_GetIdenTokenProviderIfRtn pGetIdenTokenProviderIfRtn; // Library has been loaded, now get a pointer to its GetIdenTokenProviderProviderInterface routine pGetIdenTokenProviderIfRtn = dlsym(pIdenTokenProviderModule->libHandle, GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN_SYMBOL); if (pGetIdenTokenProviderIfRtn) { // Now, obtain the modules IdenTokenProviderIf. retStatus = (pGetIdenTokenProviderIfRtn)(pModuleConfigIf, &pIdenTokenProviderModule->pIdenTokenProviderIf); } else { DbgTrace(0, "-GetIdenTokenProviderInterface- dlsym error = %s\n", dlerror()); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_LIBRARY_LOAD_FAILURE); } } else { DbgTrace(0, "-GetIdenTokenProviderInterface- dlopen error = %s\n", dlerror()); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_LIBRARY_LOAD_FAILURE); } // Free the buffer holding the library name free(pLibraryName); } else { DbgTrace(0, "-GetIdenTokenProviderInterface- Library name not configured\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_CONFIGURATION_ERROR); } // Check if we were successful at obtaining the IdenTokenProviderIf instance for the // module. if (CASA_SUCCESS(retStatus)) { // Insert the entry in the list, provide the caller with its IdenTokenProviderIf // instance after we have incremented its reference count. InsertTailList(&g_IdenTokenProviderModuleListHead, &pIdenTokenProviderModule->listEntry); pIdenTokenProviderModule->pIdenTokenProviderIf->addReference(pIdenTokenProviderModule->pIdenTokenProviderIf); *ppIdenTokenProviderIf = pIdenTokenProviderModule->pIdenTokenProviderIf; } else { // Failed, free resources. free(pIdenTokenProviderModule->pTypeName); if (pIdenTokenProviderModule->libHandle) dlclose(pIdenTokenProviderModule->libHandle); free(pIdenTokenProviderModule); } } else { DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to allocate buffer\n", 0); // Free buffer allocated for entry free(pIdenTokenProviderModule); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } } else { DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to allocate buffer\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } } // Release exclusive access to our mutex pthread_mutex_unlock(&g_IdenTokenProviderModuleMutex); // Release config interface instance pModuleConfigIf->releaseReference(pModuleConfigIf); } else { DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to obtain config interface\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_CONFIGURATION_ERROR); } DbgTrace(2, "-GetIdenTokenProviderInterface- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= HANDLE PlatAllocMutex(void) // // Arguments: // // Returns: // // Abstract: // // Notes: // // Environment: // // L2 //=======================================================================-- { PlatformMutex *pPlatMutex; pthread_mutexattr_t mutexAttr = {PTHREAD_MUTEX_RECURSIVE}; DbgTrace(2, "-PlatAllocMutex- Start\n", 0); // Allocate space for our mutex structure pPlatMutex = malloc(sizeof(*pPlatMutex)); if (pPlatMutex) { // Finish initializing the mutex pthread_mutex_init(&pPlatMutex->mutex, &mutexAttr); } else { DbgTrace(0, "-PlatAllocMutex- Memory allocation failure\n", 0); } DbgTrace(2, "-PlatAllocMutex- End, retHandle = %08X\n", (unsigned int) pPlatMutex); return (HANDLE) pPlatMutex; } //++======================================================================= void PlatDestroyMutex(HANDLE hMutex) // // Arguments: // // Returns: // // Abstract: // // Notes: // // Environment: // // L2 //=======================================================================-- { PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; DbgTrace(2, "-PlatDestroyMutex- Start\n", 0); // Free the resources associated with the mutex pthread_mutex_destroy(&pPlatMutex->mutex); free(pPlatMutex); DbgTrace(2, "-PlatDestroyMutex- End\n", 0); } //++======================================================================= void PlatAcquireMutex(HANDLE hMutex) // // Arguments: // // Returns: // // Abstract: // // Notes: // // Environment: // // L2 //=======================================================================-- { PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; DbgTrace(2, "-PlatAcquireMutex- Start\n", 0); // Acquire the mutex pthread_mutex_lock(&pPlatMutex->mutex); DbgTrace(2, "-PlatAcquireMutex- End\n", 0); } //++======================================================================= void PlatReleaseMutex(HANDLE hMutex) // // Arguments: // // Returns: // // Abstract: // // Notes: // // Environment: // // L2 //=======================================================================-- { PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; DbgTrace(2, "-PlatReleaseMutex- Start\n", 0); // Release the mutex pthread_mutex_unlock(&pPlatMutex->mutex); DbgTrace(2, "-PlatRelease- End\n", 0); } //++======================================================================= //++======================================================================= //++=======================================================================