2c8668479c
to be able to deliver the client component onto distributions targeting desktops without having to deliver the server components. This commit is for the resulting client project.
589 lines
18 KiB
C
589 lines
18 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 ]==================================================
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
HANDLE g_hCASAContext;
|
|
|
|
|
|
//++=======================================================================
|
|
AuthCacheEntry*
|
|
CreateAuthTokenCacheEntry(
|
|
IN const char *pCacheKey,
|
|
IN const char *pGroupOrHostName,
|
|
IN CasaStatus status,
|
|
IN char *pToken,
|
|
IN int entryLifetime, // seconds (0 == Lives forever)
|
|
IN void *pCredStoreScope
|
|
)
|
|
//
|
|
// 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"};
|
|
int32_t tokenSize, entrySize, keySize;
|
|
AuthCacheEntry *pEntry = NULL;
|
|
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,
|
|
(SS_UTF8_T*) pKey,
|
|
keySize,
|
|
(uint8_t *) pEntry,
|
|
(uint32_t*) &entrySize,
|
|
NULL,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
|
|
|
|
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 = %0lX\n", (long) pEntry);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
AuthCacheEntry*
|
|
CreateSessionTokenCacheEntry(
|
|
IN const char *pCacheKey,
|
|
IN CasaStatus status,
|
|
IN char *pToken,
|
|
IN int entryLifetime, // seconds (0 == Lives forever)
|
|
IN void *pCredStoreScope
|
|
)
|
|
//
|
|
// 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"};
|
|
int32_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,
|
|
(SS_UTF8_T*) pCacheKey,
|
|
(uint32_t) strlen(pCacheKey) + 1,
|
|
(uint8_t *) pEntry,
|
|
(uint32_t*) &entrySize,
|
|
NULL,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
}
|
|
else
|
|
{
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
DbgTrace(1, "-CreateSessionTokenCacheEntry- End, pEntry = %0lX\n", (long) pEntry);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void
|
|
FreeAuthCacheEntry(
|
|
IN AuthCacheEntry *pEntry
|
|
)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
DbgTrace(1, "-FreeAuthCacheEntry- Start, pEntry = %0lX\n", (long) 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,
|
|
IN void *pCredStoreScope
|
|
)
|
|
//
|
|
// 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"};
|
|
int32_t valueLength, bytesRequired;
|
|
AuthCacheEntry *pEntry = NULL;
|
|
|
|
|
|
DbgTrace(1, "-FindSessionTokenEntryInCache- Start\n", 0);
|
|
|
|
valueLength = 0;
|
|
bytesRequired = 0;
|
|
|
|
retStatus = miCASAReadBinaryKey(g_hCASAContext,
|
|
0,
|
|
&sessionKeyChain,
|
|
&sharedId,
|
|
(SS_UTF8_T*) pCacheKey,
|
|
(uint32_t) strlen(pCacheKey) + 1,
|
|
NULL,
|
|
(uint32_t*) &valueLength,
|
|
(SSCS_PASSWORD_T*) NULL,
|
|
(uint32_t*) &bytesRequired,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
|
|
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,
|
|
(SS_UTF8_T*) pCacheKey,
|
|
(uint32_t) strlen(pCacheKey) + 1,
|
|
(uint8_t *) pEntry,
|
|
(uint32_t*) &valueLength,
|
|
(SSCS_PASSWORD_T*) NULL,
|
|
(uint32_t*) &bytesRequired,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
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 = %0lX\n", (long) pEntry);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
//++=======================================================================
|
|
AuthCacheEntry*
|
|
FindAuthTokenEntryInCache(
|
|
IN const char *pCacheKey,
|
|
IN const char *pGroupOrHostName,
|
|
IN void *pCredStoreScope
|
|
)
|
|
//
|
|
// 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"};
|
|
int32_t valueLength, bytesRequired, keySize;
|
|
AuthCacheEntry *pEntry = NULL;
|
|
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,
|
|
(SS_UTF8_T*) pKey,
|
|
keySize,
|
|
NULL,
|
|
(uint32_t*) &valueLength,
|
|
(SSCS_PASSWORD_T*) NULL,
|
|
(uint32_t*) &bytesRequired,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
|
|
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,
|
|
(SS_UTF8_T*) pKey,
|
|
keySize,
|
|
(uint8_t *) pEntry,
|
|
(uint32_t*) &valueLength,
|
|
(SSCS_PASSWORD_T*) NULL,
|
|
(uint32_t*) &bytesRequired,
|
|
(SSCS_EXT_T*) pCredStoreScope);
|
|
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 = %0lX\n", (long) 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;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|