697 lines
22 KiB
C
697 lines
22 KiB
C
/***********************************************************************
|
|
*
|
|
* Copyright (C) 2005-2006 Novell, Inc. 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.
|
|
*
|
|
***********************************************************************/
|
|
|
|
|
|
//===[ Include files ]=====================================================
|
|
|
|
#include "internal.h"
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
//
|
|
// Config Key object
|
|
//
|
|
typedef struct _ConfigKey
|
|
{
|
|
LIST_ENTRY listEntry;
|
|
char *pKeyName;
|
|
int keyNameLen;
|
|
char *pValue;
|
|
int valueLen;
|
|
|
|
} ConfigKey, *pConfigKey;
|
|
|
|
//
|
|
// Config Interface instance data
|
|
//
|
|
typedef struct _ConfigIfInstance
|
|
{
|
|
LIST_ENTRY listEntry;
|
|
int refCount;
|
|
char *pConfigFolder;
|
|
int configFolderLen;
|
|
char *pConfigName;
|
|
int configNameLen;
|
|
LIST_ENTRY configKeyListHead;
|
|
ConfigIf configIf;
|
|
|
|
} ConfigIfInstance, *PConfigIfInstance;
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
// ConfigIf synchronization mutex and variables
|
|
static
|
|
pthread_mutex_t g_configIfMutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static
|
|
LIST_ENTRY g_configIfListHead = {&g_configIfListHead, &g_configIfListHead};
|
|
|
|
static
|
|
int g_numConfigIfObjs = 0;
|
|
|
|
|
|
//++=======================================================================
|
|
static void
|
|
RemoveWhiteSpaceFromTheEnd(
|
|
IN const char *pInString)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
char *pLineEnd = (char*) pInString + strlen(pInString) - 1;
|
|
|
|
|
|
DbgTrace(3, "auth_token -RemoveWhiteSpaceFromTheEnd- Start\n", 0);
|
|
|
|
while (pLineEnd != pInString)
|
|
{
|
|
if (*pLineEnd == '\n'
|
|
|| *pLineEnd == ' '
|
|
|| *pLineEnd == '\t')
|
|
{
|
|
// Strike this character
|
|
*pLineEnd = '\0';
|
|
pLineEnd --;
|
|
}
|
|
else
|
|
{
|
|
// Found a non-white character
|
|
break;
|
|
}
|
|
}
|
|
|
|
DbgTrace(3, "auth_token -RemoveWhiteSpaceFromTheEnd- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static char*
|
|
SkipWhiteSpace(
|
|
IN const char *pInString)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
char *pOutString = (char*) pInString;
|
|
|
|
DbgTrace(3, "auth_token -SkipWhiteSpace- Start\n", 0);
|
|
|
|
while (*pOutString != '\0')
|
|
{
|
|
if (*pOutString == '\n'
|
|
|| *pOutString == ' '
|
|
|| *pOutString == '\t')
|
|
{
|
|
// Skip this character
|
|
pOutString ++;
|
|
}
|
|
else
|
|
{
|
|
// Found a non-white character
|
|
break;
|
|
}
|
|
}
|
|
|
|
DbgTrace(3, "auth_token -SkipWhiteSpace- End\n", 0);
|
|
|
|
return pOutString;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static char*
|
|
SkipNonWhiteSpace(
|
|
IN const char *pInString)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
char *pOutString;
|
|
|
|
DbgTrace(3, "auth_token -SkipNonWhiteSpace- Start\n", 0);
|
|
|
|
while (*pOutString != '\0')
|
|
{
|
|
if (*pOutString == '\n'
|
|
|| *pOutString == ' '
|
|
|| *pOutString == '\t')
|
|
{
|
|
// Found a white character
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Skip this character
|
|
pOutString ++;
|
|
}
|
|
}
|
|
|
|
DbgTrace(3, "auth_token -SkipNonWhiteSpace- End\n", 0);
|
|
|
|
return pOutString;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static void
|
|
LowerCaseString(
|
|
IN char *pDestString,
|
|
IN const char *pSrcString)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int i;
|
|
|
|
DbgTrace(3, "auth_token -LowerCaseString- Start\n", 0);
|
|
|
|
// Copy the string as lower case
|
|
for (i = 0; pSrcString[i] != '\0'; i++)
|
|
{
|
|
if (isalpha(pSrcString[i]))
|
|
pDestString[i] = tolower(pSrcString[i]);
|
|
else
|
|
pDestString[i] = pSrcString[i];
|
|
}
|
|
|
|
// Null terminate the destination string
|
|
pDestString[i] = '\0';
|
|
|
|
DbgTrace(3, "auth_token -LowerCaseString- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
int SSCS_CALL
|
|
ConfigIf_AddReference(
|
|
IN const void *pIfInstance)
|
|
//
|
|
// Arguments:
|
|
// pIfInstance -
|
|
// Pointer to interface object.
|
|
//
|
|
// Returns:
|
|
// Interface reference count.
|
|
//
|
|
// Description:
|
|
// Increases interface reference count.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int refCount;
|
|
ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf);
|
|
|
|
DbgTrace(2, "auth_token -ConfigIf_AddReference- Start\n", 0);
|
|
|
|
// Increment the reference count on the object
|
|
pthread_mutex_lock(&g_configIfMutex);
|
|
pConfigIfInstance->refCount ++;
|
|
refCount = pConfigIfInstance->refCount;
|
|
pthread_mutex_unlock(&g_configIfMutex);
|
|
|
|
DbgTrace(2, "auth_token -ConfigIf_AddReference- End, refCount = %08X\n", refCount);
|
|
|
|
return refCount;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void SSCS_CALL
|
|
ConfigIf_ReleaseReference(
|
|
IN const void *pIfInstance)
|
|
//
|
|
// Arguments:
|
|
// pIfInstance -
|
|
// Pointer to interface object.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
// Description:
|
|
// Decreases interface reference count. The interface is deallocated if
|
|
// the reference count becomes zero.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
bool freeObj = false;
|
|
ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf);
|
|
|
|
DbgTrace(2, "auth_token -ConfigIf_ReleaseReference- Start\n", 0);
|
|
|
|
// Decrement the reference count on the object and determine if it needs to
|
|
// be released.
|
|
pthread_mutex_lock(&g_configIfMutex);
|
|
pConfigIfInstance->refCount --;
|
|
if (pConfigIfInstance->refCount == 0)
|
|
{
|
|
// The object needs to be released, forget about it.
|
|
freeObj = true;
|
|
g_numConfigIfObjs --;
|
|
RemoveEntryList(&pConfigIfInstance->listEntry);
|
|
}
|
|
pthread_mutex_unlock(&g_configIfMutex);
|
|
|
|
// Free object if necessary
|
|
if (freeObj)
|
|
{
|
|
// Free all of the config key objects associated with this configuration
|
|
// interface instance.
|
|
while (!IsListEmpty(&pConfigIfInstance->configKeyListHead))
|
|
{
|
|
LIST_ENTRY *pListEntry;
|
|
ConfigKey *pConfigKey;
|
|
|
|
// Get reference to entry at the head of the list
|
|
pListEntry = pConfigIfInstance->configKeyListHead.Flink;
|
|
pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry);
|
|
|
|
// Free the buffers associated with the ConfigKey
|
|
free(pConfigKey->pKeyName);
|
|
free(pConfigKey->pValue);
|
|
|
|
// Remove the entry from the list
|
|
RemoveEntryList(&pConfigKey->listEntry);
|
|
|
|
// Finish freeing the ConfigKey
|
|
free(pConfigKey);
|
|
}
|
|
|
|
// Free the rest of the buffers associated with the interface instance data
|
|
free(pConfigIfInstance->pConfigFolder);
|
|
free(pConfigIfInstance->pConfigName);
|
|
free(pConfigIfInstance);
|
|
}
|
|
|
|
DbgTrace(2, "auth_token -ConfigIf_ReleaseReference- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
char* SSCS_CALL
|
|
ConfigIf__GetEntryValue(
|
|
IN const void *pIfInstance,
|
|
IN const char *pKeyName)
|
|
//
|
|
// Arguments:
|
|
// pIfInstance -
|
|
// Pointer to interface object.
|
|
//
|
|
// pKeyName -
|
|
// Pointer to NULL terminated string that contains the
|
|
// name of the key whose value is being requested.
|
|
//
|
|
// Returns:
|
|
// Pointer to NULL terminated string with value being requested or NULL.
|
|
//
|
|
// Description:
|
|
// Gets value associated with a key for the configuration object.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf);
|
|
char *pValue = NULL;
|
|
LIST_ENTRY *pListEntry;
|
|
ConfigKey *pConfigKey;
|
|
int keyNameLen = strlen(pKeyName);
|
|
char *pKeyNameLowercase;
|
|
|
|
DbgTrace(2, "auth_token -ConfigIf_GetEntryValue- Start\n", 0);
|
|
|
|
// Allocate enough space to hold lower case version of the key name
|
|
pKeyNameLowercase = malloc(keyNameLen);
|
|
if (pKeyNameLowercase)
|
|
{
|
|
// Lower case the key name
|
|
LowerCaseString(pKeyNameLowercase, pKeyName);
|
|
|
|
// Try to find matching ConfigKey
|
|
pListEntry = pConfigIfInstance->configKeyListHead.Flink;
|
|
while (pListEntry != &pConfigIfInstance->configKeyListHead)
|
|
{
|
|
// Get pointer to the current entry
|
|
pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry);
|
|
|
|
// Check if we have a match
|
|
if (pConfigKey->keyNameLen == keyNameLen
|
|
&& memcmp(pKeyNameLowercase, pConfigKey->pKeyName, keyNameLen) == 0)
|
|
{
|
|
// We found it, return its value.
|
|
pValue = malloc(pConfigKey->valueLen + 1);
|
|
if (pValue)
|
|
{
|
|
strcpy(pValue, pConfigKey->pValue);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -ConfigIf_GetEntryValue- Buffer allocation failure\n", 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Advance to the next entry
|
|
pListEntry = pListEntry->Flink;
|
|
}
|
|
|
|
// Free the lower case version of the key name
|
|
free(pKeyNameLowercase);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -ConfigIf_GetEntryValue- Buffer allocation failure\n", 0);
|
|
}
|
|
|
|
DbgTrace(2, "auth_token -ConfigIf_GetEntryValue- End, pValue = %08X\n", (unsigned int) pValue);
|
|
|
|
return pValue;
|
|
}
|
|
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus SSCS_CALL
|
|
GetConfigInterface(
|
|
IN const char *pConfigFolder,
|
|
IN const char *pConfigName,
|
|
INOUT ConfigIf **ppConfigIf)
|
|
//
|
|
// Arguments:
|
|
// pConfigFolder -
|
|
// Pointer to NULL terminated string that contains the name of
|
|
// the folder containing the configuration file.
|
|
//
|
|
// pConfigName -
|
|
// Pointer to NULL terminated string containing the name of the
|
|
// configuration entry.
|
|
//
|
|
// ppConfigIf -
|
|
// Pointer to variable that will receive pointer to ConfigIf
|
|
// instance.
|
|
//
|
|
// Returns:
|
|
// Casa Status
|
|
//
|
|
// Description:
|
|
// Get configuration interface to specified configuration entry.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int configFolderLen = strlen(pConfigFolder);
|
|
int configNameLen = strlen(pConfigName);
|
|
ConfigIfInstance *pConfigIfInstance;
|
|
LIST_ENTRY *pListEntry;
|
|
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_OBJECT_NOT_FOUND);
|
|
|
|
DbgTrace(2, "auth_token -GetConfigInterface- Start\n", 0);
|
|
|
|
// Obtain exclusive access to our mutex
|
|
pthread_mutex_lock(&g_configIfMutex);
|
|
|
|
// Check if we already have an entry in our list for the configuration
|
|
pListEntry = g_configIfListHead.Flink;
|
|
while (pListEntry != &g_configIfListHead)
|
|
{
|
|
// Get pointer to the current entry
|
|
pConfigIfInstance = CONTAINING_RECORD(pListEntry, ConfigIfInstance, listEntry);
|
|
|
|
// Check if we have a match
|
|
if (pConfigIfInstance->configFolderLen == configFolderLen
|
|
&& pConfigIfInstance->configNameLen == configNameLen
|
|
&& memcmp(pConfigFolder, pConfigIfInstance->pConfigFolder, configFolderLen) == 0
|
|
&& memcmp(pConfigName, pConfigIfInstance->pConfigName, configNameLen) == 0)
|
|
{
|
|
// We found it, return the ConfigIf associated with the instance data
|
|
// after incrementing its reference count.
|
|
pConfigIfInstance->refCount ++;
|
|
*ppConfigIf = &pConfigIfInstance->configIf;
|
|
|
|
// Success
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
// Advance to the next entry
|
|
pListEntry = pListEntry->Flink;
|
|
}
|
|
|
|
// Proceed to create interface instance data for the configuration if none was found
|
|
if (retStatus != CASA_STATUS_SUCCESS)
|
|
{
|
|
char *pFilePath;
|
|
|
|
// Build a string containing the configuration file path
|
|
pFilePath = malloc(configFolderLen + 1 + configNameLen + sizeof(".conf"));
|
|
if (pFilePath)
|
|
{
|
|
FILE *pConfigFile;
|
|
|
|
strcpy(pFilePath, pConfigFolder);
|
|
strcat(pFilePath, "/");
|
|
strcat(pFilePath, pConfigName);
|
|
strcat(pFilePath, ".conf");
|
|
|
|
// Open the configuration file for reading
|
|
pConfigFile = fopen(pFilePath, "r");
|
|
if (pConfigFile)
|
|
{
|
|
// Opened the file, create a ConfigIfInstance object for it.
|
|
pConfigIfInstance = malloc(sizeof(*pConfigIfInstance));
|
|
if (pConfigIfInstance)
|
|
{
|
|
// Initialize the list head within the instance data
|
|
InitializeListHead(&pConfigIfInstance->configKeyListHead);
|
|
|
|
// Initialize the ConfigIf within the instance data
|
|
pConfigIfInstance->configIf.addReference = ConfigIf_AddReference;
|
|
pConfigIfInstance->configIf.releaseReference = ConfigIf_ReleaseReference;
|
|
pConfigIfInstance->configIf.getEntryValue = ConfigIf__GetEntryValue;
|
|
|
|
// Save the ConfigFolder and ConfigName information within the instance data
|
|
pConfigIfInstance->pConfigFolder = malloc(configFolderLen + 1);
|
|
if (pConfigIfInstance->pConfigFolder)
|
|
{
|
|
strcpy(pConfigIfInstance->pConfigFolder, pConfigFolder);
|
|
pConfigIfInstance->configFolderLen = configFolderLen;
|
|
|
|
pConfigIfInstance->pConfigName = malloc(configNameLen + 1);
|
|
if (pConfigIfInstance->pConfigName)
|
|
{
|
|
strcpy(pConfigIfInstance->pConfigName, pConfigName);
|
|
pConfigIfInstance->configNameLen = configNameLen;
|
|
|
|
// Add the instance data into our list and bump up its reference count
|
|
// since we did that.
|
|
InsertTailList(&g_configIfListHead, &pConfigIfInstance->listEntry);
|
|
pConfigIfInstance->refCount = 1;
|
|
|
|
// At this point we want to return success to the caller even if we
|
|
// experience a read error.
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
|
|
// Return the ConfigIf associated with the instance data after
|
|
// incrementing its reference count.
|
|
pConfigIfInstance->refCount ++;
|
|
*ppConfigIf = &pConfigIfInstance->configIf;
|
|
|
|
// Now update the instance data with the information present in the file
|
|
if (fseek(pConfigFile, 0, SEEK_SET) == 0)
|
|
{
|
|
char line[512];
|
|
|
|
while (fgets(line, sizeof(line), pConfigFile) != NULL)
|
|
{
|
|
int lineLength;
|
|
|
|
RemoveWhiteSpaceFromTheEnd(line);
|
|
|
|
lineLength = strlen(line);
|
|
if (lineLength != 0)
|
|
{
|
|
char *pKey;
|
|
char *pKeyEnd;
|
|
char *pValue;
|
|
ConfigKey *pConfigKey;
|
|
|
|
// Attempt to find the key
|
|
pKey = SkipWhiteSpace(line);
|
|
|
|
// Make sure that we are not dealing with an empty line or a comment
|
|
if (*pKey == '\0' || *pKey == '#')
|
|
continue;
|
|
|
|
// Go past the key
|
|
pKeyEnd = SkipNonWhiteSpace(pKey);
|
|
|
|
// Protect against a malformed line
|
|
if (*pKeyEnd == '\0')
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Key found without value\n", 0);
|
|
continue;
|
|
}
|
|
|
|
// Attempt to find the value
|
|
pValue = SkipWhiteSpace(pKeyEnd);
|
|
|
|
// Protect against a malformed line
|
|
if (*pValue == '\0')
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Key found without value\n", 0);
|
|
continue;
|
|
}
|
|
|
|
// Delineate the key
|
|
*pKeyEnd = '\0';
|
|
|
|
// Create a ConfigKey object for this key/value pair
|
|
pConfigKey = malloc(sizeof(*pConfigKey));
|
|
if (pConfigKey)
|
|
{
|
|
pConfigKey->keyNameLen = strlen(pKey);
|
|
pConfigKey->pKeyName = malloc(pConfigKey->keyNameLen + 1);
|
|
if (pConfigKey->pKeyName)
|
|
{
|
|
// Save the key name in lower case
|
|
LowerCaseString(pConfigKey->pKeyName, pKey);
|
|
|
|
pConfigKey->valueLen = strlen(pValue);
|
|
pConfigKey->pValue = malloc(pConfigKey->valueLen + 1);
|
|
if (pConfigKey->pValue)
|
|
{
|
|
strcpy(pConfigKey->pValue, pValue);
|
|
|
|
// The entry is ready, now associate it with the instance data.
|
|
InsertTailList(&pConfigIfInstance->configKeyListHead, &pConfigKey->listEntry);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation failure\n", 0);
|
|
free(pConfigKey->pKeyName);
|
|
free(pConfigKey);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation failure\n", 0);
|
|
free(pConfigKey);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation failure\n", 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- File seek error, errno = %d\n", errno);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation failure\n", 0);
|
|
|
|
// Free the buffers associated with the instance data
|
|
free(pConfigIfInstance->pConfigFolder);
|
|
free(pConfigIfInstance);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation failure\n", 0);
|
|
|
|
// Free the buffer allocated for the instance data
|
|
free(pConfigIfInstance);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation failure\n", 0);
|
|
}
|
|
|
|
// Close the file
|
|
fclose(pConfigFile);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(1, "auth_token -GetConfigInterface- Unable to open config file, errno = %d\n", errno);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "auth_token -GetConfigInterface- Buffer allocation error\n", 0);
|
|
}
|
|
}
|
|
|
|
// Release exclusive access to our mutex
|
|
pthread_mutex_unlock(&g_configIfMutex);
|
|
|
|
DbgTrace(2, "auth_token -GetConfigInterface- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|