CASA/CASA-auth-token/client/cache.c
Todd Throne fc7f88c01d Changed storage of tokens from registry to CASA wallet.
Broke out storage of Session tokens and Authentication tokens.
2006-06-20 20:33:11 +00:00

616 lines
14 KiB
C

/***********************************************************************
*
* 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 <jluciani@novell.com>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include "internal.h"
#include <micasa.h>
//===[ Type definitions ]==================================================
//
// Registry Key/Value defines used in the AuthCache
//
#define CASA_AUTH_CACHE_REG_KEY "CASA_Auth_Cache"
#define CREATION_TIME_REG_VALUE "CreationTime"
#define EXPIRATION_TIME_REG_VALUE "ExpirationTime"
#define DOES_NOT_EXPIRE_REG_VALUE "DoesNotExpire"
#define STATUS_REG_VALUE "Status"
#define TOKEN_REG_VALUE "Token"
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Non-host specific key name
static
char g_allHosts[] = "AllHosts";
static
int g_cacheEntryCount = 0;
HANDLE g_hCASAContext;
//++=======================================================================
AuthCacheEntry*
CreateAuthTokenCacheEntry(
IN const char *pCacheKey,
IN const char *pGroupOrHostName,
IN CasaStatus status,
IN unsigned char *pToken,
IN int entryLifetime // seconds (0 == Lives forever)
)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"};
uint32_t tokenSize, entrySize, keySize;
AuthCacheEntry *pEntry = NULL;
unsigned char *pKey;
DbgTrace(1, "-CreateAuthTokenCacheEntry- Start\n", 0);
if (status == CASA_STATUS_SUCCESS)
{
tokenSize = (uint32_t)strlen(pToken);
}
else
{
tokenSize = 0;
}
entrySize = tokenSize + sizeof(AuthCacheEntry);
// Allocate space for the entry
// The AuthCacheEntry structure contains room for the tokens NULL terminator
pEntry = (AuthCacheEntry*) malloc(entrySize);
if (pEntry)
{
// Set the status
pEntry->status = status;
if (pEntry->status == CASA_STATUS_SUCCESS)
{
memcpy(&pEntry->token[0], pToken, tokenSize);
}
pEntry->token[tokenSize] = '\0';
// Set the time when the entry was added to the cache
pEntry->creationTime = GetTickCount();
// First determine the time when the entry is due to expire
if (entryLifetime != 0)
{
pEntry->expirationTime = pEntry->creationTime + (entryLifetime * 1000);
pEntry->doesNotExpire = FALSE;
}
else
{
// The entry does not expire
pEntry->expirationTime = 0;
pEntry->doesNotExpire = TRUE;
}
keySize = (uint32_t)strlen(pCacheKey) + (uint32_t)strlen(pGroupOrHostName) + 2;
pKey = malloc(keySize);
if (pKey)
{
strncpy(pKey, pCacheKey, keySize);
strncat(pKey, "@", keySize);
strncat(pKey, pGroupOrHostName, keySize);
retStatus = miCASAWriteBinaryKey(
g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
pKey,
keySize,
(uint8_t *)pEntry,
&entrySize,
NULL,
NULL);
free(pKey);
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
DbgTrace(1, "-CreateAuthTokenCacheEntry- End, pEntry = %08X\n", pEntry);
return pEntry;
}
//++=======================================================================
AuthCacheEntry*
CreateSessionTokenCacheEntry(
IN const char *pCacheKey,
IN CasaStatus status,
IN unsigned char *pToken,
IN int entryLifetime // seconds (0 == Lives forever)
)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
SSCS_SECRET_ID_T sharedId = {20, "CASA_SESSION_TOKENS"};
uint32_t tokenSize, entrySize;
AuthCacheEntry *pEntry = NULL;
DbgTrace(1, "-CreateSessionTokenCacheEntry- Start\n", 0);
if (status == CASA_STATUS_SUCCESS)
{
tokenSize = (uint32_t)strlen(pToken);
}
else
{
tokenSize = 0;
}
entrySize = tokenSize + sizeof(AuthCacheEntry);
// Allocate space for the entry
// The AuthCacheEntry structure contains room for the tokens NULL terminator
pEntry = (AuthCacheEntry*) malloc(entrySize);
if (pEntry)
{
// Set the status
pEntry->status = status;
if (pEntry->status == CASA_STATUS_SUCCESS)
{
memcpy(&pEntry->token[0], pToken, tokenSize);
}
pEntry->token[tokenSize] = '\0';
// Set the time when the entry was added to the cache
pEntry->creationTime = GetTickCount();
// First determine the time when the entry is due to expire
if (entryLifetime != 0)
{
pEntry->expirationTime = pEntry->creationTime + (entryLifetime * 1000);
pEntry->doesNotExpire = FALSE;
}
else
{
// The entry does not expire
pEntry->expirationTime = 0;
pEntry->doesNotExpire = TRUE;
}
retStatus = miCASAWriteBinaryKey(
g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
(char *)pCacheKey,
(uint32_t)strlen(pCacheKey) + 1,
(uint8_t *)pEntry,
&entrySize,
NULL,
NULL);
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
DbgTrace(1, "-CreateSessionTokenCacheEntry- End, pEntry = %08X\n", pEntry);
return pEntry;
}
//++=======================================================================
void
FreeAuthCacheEntry(
IN AuthCacheEntry *pEntry
)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "-FreeAuthCacheEntry- Start, pEntry = %08X\n", pEntry);
// Free the entry
free(pEntry);
DbgTrace(1, "-FreeAuthCacheEntry- End\n", 0);
}
//++=======================================================================
static
BOOL
CacheEntryLifetimeExpired(
IN DWORD creationTime,
IN DWORD expirationTime
)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DWORD currentTime = GetTickCount();
BOOL expired = FALSE;
DbgTrace(2, "-CacheEntryLifetimeExpired- Start\n", 0);
// Check if the clock has wrapped
if (currentTime >= creationTime)
{
// The clock has not wrapped, check if the
// expiration time has wrapped.
if (expirationTime > creationTime)
{
// The expiration time also has not wrapped,
// do a straight compare against the current
// time.
if (currentTime >= expirationTime)
{
// It has expired
expired = TRUE;
}
}
}
else
{
// The clock has wrapped, check if the expiration
// time also wrapped.
if (expirationTime > creationTime)
{
// The expiration time did not wrap, therefore
// it has been exceeded since the clock wrapped.
expired = TRUE;
}
else
{
// The expiration time also wrapped, do a straight
// compare against the current time.
if (currentTime >= expirationTime)
{
// It has expired
expired = TRUE;
}
}
}
DbgTrace(2, "-CacheEntryLifetimeExpired- End, result = %08X\n", expired);
return expired;
}
//++=======================================================================
AuthCacheEntry*
FindSessionTokenEntryInCache(
IN const char *pCacheKey
)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
SSCS_SECRET_ID_T sharedId = {20, "CASA_SESSION_TOKENS"};
uint32_t valueLength, bytesRequired;
AuthCacheEntry *pEntry = NULL;
DbgTrace(1, "-FindSessionTokenEntryInCache- Start\n", 0);
valueLength = 0;
bytesRequired = 0;
retStatus = miCASAReadBinaryKey(
g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
(char *)pCacheKey,
(uint32_t)strlen(pCacheKey) + 1,
NULL,
&valueLength,
NULL,
&bytesRequired,
NULL);
if (retStatus == NSSCS_E_ENUM_BUFF_TOO_SHORT
&& bytesRequired != 0)
{
pEntry = (AuthCacheEntry*) malloc(bytesRequired);
if (pEntry)
{
valueLength = bytesRequired;
bytesRequired = 0;
retStatus = miCASAReadBinaryKey(
g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
(char *)pCacheKey,
(uint32_t)strlen(pCacheKey) + 1,
(uint8_t *)pEntry,
&valueLength,
NULL,
&bytesRequired,
NULL);
if (CASA_SUCCESS(retStatus))
{
if (pEntry->doesNotExpire == FALSE
&& CacheEntryLifetimeExpired(pEntry->creationTime, pEntry->expirationTime))
{
// Remove the entry ???
//miCASARemoveBinaryKey();
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
if (!CASA_SUCCESS(retStatus))
{
FreeAuthCacheEntry(pEntry);
pEntry = NULL;
}
}
}
DbgTrace(1, "-FindSessionTokenEntryInCache- End, pEntry = %08X\n", pEntry);
return pEntry;
}
//++=======================================================================
AuthCacheEntry*
FindAuthTokenEntryInCache(
IN const char *pCacheKey,
IN const char *pGroupOrHostName
)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"};
uint32_t valueLength, bytesRequired, keySize;
AuthCacheEntry *pEntry = NULL;
unsigned char *pKey;
DbgTrace(1, "-FindAuthTokenEntryInCache- Start\n", 0);
keySize = (uint32_t)strlen(pCacheKey) + (uint32_t)strlen(pGroupOrHostName) + 2;
pKey = malloc(keySize);
if (pKey)
{
strncpy(pKey, pCacheKey, keySize);
strncat(pKey, "@", keySize);
strncat(pKey, pGroupOrHostName, keySize);
valueLength = 0;
bytesRequired = 0;
retStatus = miCASAReadBinaryKey(
g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
pKey,
keySize,
NULL,
&valueLength,
NULL,
&bytesRequired,
NULL);
if (retStatus == NSSCS_E_ENUM_BUFF_TOO_SHORT
&& bytesRequired != 0)
{
pEntry = (AuthCacheEntry*) malloc(bytesRequired);
if (pEntry)
{
valueLength = bytesRequired;
bytesRequired = 0;
retStatus = miCASAReadBinaryKey(
g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
pKey,
keySize,
(uint8_t *)pEntry,
&valueLength,
NULL,
&bytesRequired,
NULL);
if (CASA_SUCCESS(retStatus))
{
if (pEntry->doesNotExpire == FALSE
&& CacheEntryLifetimeExpired(pEntry->creationTime, pEntry->expirationTime))
{
// Remove the entry ???
//miCASARemoveBinaryKey();
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
if (!CASA_SUCCESS(retStatus))
{
FreeAuthCacheEntry(pEntry);
pEntry = NULL;
}
}
}
free(pKey);
}
DbgTrace(1, "-FindAuthTokenEntryInCache- End, pEntry = %08X\n", pEntry);
return pEntry;
}
//++=======================================================================
CasaStatus
InitializeAuthCache()
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
SSCS_SECRETSTORE_T ssId;
DbgTrace(1, "-InitializeAuthCache- Start\n", 0);
ssId.version = NSSCS_VERSION_NUMBER;
strcpy((char *)ssId.ssName, (char *)SSCS_DEFAULT_SECRETSTORE_ID);
g_hCASAContext = miCASAOpenSecretStoreCache(
&ssId,
0,
NULL);
if (!g_hCASAContext)
{
retStatus = CasaStatusBuild(
CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
else
{
retStatus = CASA_STATUS_SUCCESS;
}
DbgTrace(1, "-InitializeAuthCache- End, retStatus = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================