/*********************************************************************** * * 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" #include //===[ 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; } //++======================================================================= //++======================================================================= //++=======================================================================