Modified client to try to authenticate a user against a list of

configured ATSs instead of only utilizing a single configured ATS.
The client also tries to contact the ATS using port 443 as well as
port 2645 if the port number is not hard configured.
This commit is contained in:
Juan Carlos Luciani 2007-05-29 22:59:50 +00:00
parent f445b6d9c2
commit 3cc4067ab1
4 changed files with 521 additions and 195 deletions

View File

@ -60,6 +60,7 @@ AuthCacheEntry*
CreateAuthTokenCacheEntry( CreateAuthTokenCacheEntry(
IN const char *pCacheKey, IN const char *pCacheKey,
IN const char *pGroupOrHostName, IN const char *pGroupOrHostName,
IN const ATSHostEntry *pATSHost,
IN CasaStatus status, IN CasaStatus status,
IN char *pToken, IN char *pToken,
IN int entryLifetime, // seconds (0 == Lives forever) IN int entryLifetime, // seconds (0 == Lives forever)
@ -81,7 +82,7 @@ CreateAuthTokenCacheEntry(
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"}; SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"}; SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"};
uint32_t entrySize, keySize; uint32_t entrySize, keySize;
size_t tokenSize, wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen; size_t tokenSize, wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen, hostAndPortStrLen;
WrapperAuthCacheEntry *pWrapperEntry = NULL; WrapperAuthCacheEntry *pWrapperEntry = NULL;
AuthCacheEntry *pEntry = NULL; AuthCacheEntry *pEntry = NULL;
char *pKey; char *pKey;
@ -145,43 +146,97 @@ CreateAuthTokenCacheEntry(
cacheKeyStrLen = strlen(pCacheKey); cacheKeyStrLen = strlen(pCacheKey);
groupOrHostNameStrLen = strlen(pGroupOrHostName); groupOrHostNameStrLen = strlen(pGroupOrHostName);
// Verify that keySize will not overflow // Build the cache entry key based on the status
if ((cacheKeyStrLen + groupOrHostNameStrLen + 2) <= UINT32_MAX) if (status == CASA_STATUS_SUCCESS)
{ {
keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + 2); // Successful cache entries have a key of the form
// cachekey@group_or_host_name.
pKey = malloc(keySize); //
if (pKey) // Verify that keySize will not overflow
if ((cacheKeyStrLen + groupOrHostNameStrLen + 2) <= UINT32_MAX)
{ {
strncpy(pKey, pCacheKey, keySize); keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + 2);
strncat(pKey, "@", keySize);
strncat(pKey, pGroupOrHostName, keySize);
miCasaStatus = miCASAWriteBinaryKey(g_hCASAContext, pKey = malloc(keySize);
CASA_SECRET_DO_NOT_PERSIST_FLAG, if (pKey)
&sessionKeyChain,
&sharedId,
(SS_UTF8_T*) pKey,
keySize,
(uint8_t *) pEntry,
&entrySize,
NULL,
(SSCS_EXT_T*) pCredStoreScope);
if (miCasaStatus != NSSCS_SUCCESS)
{ {
DbgTrace(0, "-CreateAuthTokenCacheEntry- miCASAWriteBinaryKey failure, status = %0X\n", miCasaStatus); strncpy(pKey, pCacheKey, keySize);
} strncat(pKey, "@", keySize);
strncat(pKey, pGroupOrHostName, keySize);
free(pKey); miCasaStatus = miCASAWriteBinaryKey(g_hCASAContext,
CASA_SECRET_DO_NOT_PERSIST_FLAG,
&sessionKeyChain,
&sharedId,
(SS_UTF8_T*) pKey,
keySize,
(uint8_t *) pEntry,
&entrySize,
NULL,
(SSCS_EXT_T*) pCredStoreScope);
if (miCasaStatus != NSSCS_SUCCESS)
{
DbgTrace(0, "-CreateAuthTokenCacheEntry- miCASAWriteBinaryKey failure, status = %0X\n", miCasaStatus);
}
free(pKey);
}
else
{
DbgTrace(0, "-CreateAuthTokenCacheEntry- Memory allocation failure\n", 0);
}
} }
else else
{ {
DbgTrace(0, "-CreateAuthTokenCacheEntry- Memory allocation failure\n", 0); DbgTrace(0, "-CreateAuthTokenCacheEntry- keySize overflow prevented\n", 0);
} }
} }
else else
{ {
DbgTrace(0, "-CreateAuthTokenCacheEntry- keySize overflow prevented\n", 0); // Unsuccessful cache entries have a key of the form
// cachekey@group_or_host_name@ATSHostAddress.
//
// Verify that keySize will not overflow
hostAndPortStrLen = strlen(pATSHost->pNameAndPort);
if ((cacheKeyStrLen + groupOrHostNameStrLen + hostAndPortStrLen + 3) <= UINT32_MAX)
{
keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + hostAndPortStrLen + 3);
pKey = malloc(keySize);
if (pKey)
{
strncpy(pKey, pCacheKey, keySize);
strncat(pKey, "@", keySize);
strncat(pKey, pGroupOrHostName, keySize);
strncat(pKey, "@", keySize);
strncat(pKey, pATSHost->pNameAndPort, keySize);
miCasaStatus = miCASAWriteBinaryKey(g_hCASAContext,
CASA_SECRET_DO_NOT_PERSIST_FLAG,
&sessionKeyChain,
&sharedId,
(SS_UTF8_T*) pKey,
keySize,
(uint8_t *) pEntry,
&entrySize,
NULL,
(SSCS_EXT_T*) pCredStoreScope);
if (miCasaStatus != NSSCS_SUCCESS)
{
DbgTrace(0, "-CreateAuthTokenCacheEntry- miCASAWriteBinaryKey failure, status = %0X\n", miCasaStatus);
}
free(pKey);
}
else
{
DbgTrace(0, "-CreateAuthTokenCacheEntry- Memory allocation failure\n", 0);
}
}
else
{
DbgTrace(0, "-CreateAuthTokenCacheEntry- keySize overflow prevented\n", 0);
}
} }
} }
else else
@ -543,6 +598,7 @@ AuthCacheEntry*
FindAuthTokenEntryInCache( FindAuthTokenEntryInCache(
IN const char *pCacheKey, IN const char *pCacheKey,
IN const char *pGroupOrHostName, IN const char *pGroupOrHostName,
IN const ATSHostEntry *pATSHost,
IN void *pCredStoreScope IN void *pCredStoreScope
) )
// //
@ -561,7 +617,7 @@ FindAuthTokenEntryInCache(
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"}; SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"}; SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"};
uint32_t valueLength, bytesRequired, keySize; uint32_t valueLength, bytesRequired, keySize;
size_t wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen; size_t wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen, hostAndPortStrLen;
WrapperAuthCacheEntry *pWrapperEntry = NULL; WrapperAuthCacheEntry *pWrapperEntry = NULL;
AuthCacheEntry *pEntry = NULL; AuthCacheEntry *pEntry = NULL;
char *pKey; char *pKey;
@ -571,15 +627,18 @@ FindAuthTokenEntryInCache(
cacheKeyStrLen = strlen(pCacheKey); cacheKeyStrLen = strlen(pCacheKey);
groupOrHostNameStrLen = strlen(pGroupOrHostName); groupOrHostNameStrLen = strlen(pGroupOrHostName);
hostAndPortStrLen = strlen(pATSHost->pNameAndPort);
// Verify that keySize will not overflow // Verify that the worst case keySize will not overflow
if ((cacheKeyStrLen + groupOrHostNameStrLen + 2) <= UINT32_MAX) if ((cacheKeyStrLen + groupOrHostNameStrLen + hostAndPortStrLen + 3) <= UINT32_MAX)
{ {
keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + 2); // Allocate space for the worst case key
keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + hostAndPortStrLen + 3);
pKey = malloc(keySize); pKey = malloc(keySize);
if (pKey) if (pKey)
{ {
// First try to read entry using key for successful cache entries
strncpy(pKey, pCacheKey, keySize); strncpy(pKey, pCacheKey, keySize);
strncat(pKey, "@", keySize); strncat(pKey, "@", keySize);
strncat(pKey, pGroupOrHostName, keySize); strncat(pKey, pGroupOrHostName, keySize);
@ -592,7 +651,7 @@ FindAuthTokenEntryInCache(
&sessionKeyChain, &sessionKeyChain,
&sharedId, &sharedId,
(SS_UTF8_T*) pKey, (SS_UTF8_T*) pKey,
keySize, strlen(pKey) + 1,
NULL, NULL,
&valueLength, &valueLength,
(SSCS_PASSWORD_T*) NULL, (SSCS_PASSWORD_T*) NULL,
@ -615,7 +674,7 @@ FindAuthTokenEntryInCache(
&sessionKeyChain, &sessionKeyChain,
&sharedId, &sharedId,
(SS_UTF8_T*) pKey, (SS_UTF8_T*) pKey,
keySize, strlen(pKey) + 1,
(uint8_t *) pEntry, (uint8_t *) pEntry,
&valueLength, &valueLength,
(SSCS_PASSWORD_T*) NULL, (SSCS_PASSWORD_T*) NULL,
@ -652,6 +711,82 @@ FindAuthTokenEntryInCache(
} }
} }
} }
else
{
// We failed to obtain a cache entry using key for successful cache entry, try for using key for
// unsuccessful cache entry.
strncat(pKey, "@", keySize);
strncat(pKey, pATSHost->pNameAndPort, keySize);
valueLength = 0;
bytesRequired = 0;
miCasaStatus = miCASAReadBinaryKey(g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
(SS_UTF8_T*) pKey,
keySize,
NULL,
&valueLength,
(SSCS_PASSWORD_T*) NULL,
&bytesRequired,
(SSCS_EXT_T*) pCredStoreScope);
if (miCasaStatus == NSSCS_E_ENUM_BUFF_TOO_SHORT
&& bytesRequired != 0)
{
wrapperEntrySize = bytesRequired + sizeof(WrapperAuthCacheEntry) - sizeof(AuthCacheEntry);
pWrapperEntry = (WrapperAuthCacheEntry*) malloc(wrapperEntrySize);
if (pWrapperEntry)
{
pWrapperEntry->size = wrapperEntrySize;
pEntry = &pWrapperEntry->entry;
valueLength = bytesRequired;
bytesRequired = 0;
miCasaStatus = miCASAReadBinaryKey(g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
(SS_UTF8_T*) pKey,
keySize,
(uint8_t *) pEntry,
&valueLength,
(SSCS_PASSWORD_T*) NULL,
&bytesRequired,
(SSCS_EXT_T*) pCredStoreScope);
if (miCasaStatus == NSSCS_SUCCESS)
{
if (pEntry->doesNotExpire == false
&& CacheEntryLifetimeExpired(pEntry->creationTime, pEntry->expirationTime))
{
// Remove the entry from the cache
miCasaStatus = miCASARemoveKey(g_hCASAContext,
0,
&sessionKeyChain,
&sharedId,
(SS_UTF8_T*) pKey,
keySize,
(SSCS_PASSWORD_T*) NULL,
(SSCS_EXT_T*) pCredStoreScope);
if (miCasaStatus != NSSCS_SUCCESS)
{
DbgTrace(0, "-FindAuthTokenEntryInCache- miCASARemoveKey error = %0X\n", miCasaStatus);
}
FreeAuthCacheEntry(pEntry);
pEntry = NULL;
}
}
else
{
DbgTrace(0, "-FindAuthTokenEntryInCache- miCASAReadBinaryKey error = %0X\n", miCasaStatus);
FreeAuthCacheEntry(pEntry);
pEntry = NULL;
}
}
}
}
free(pKey); free(pKey);
} }

View File

@ -6,28 +6,23 @@
####################################################### #######################################################
# #
# ATS-hostname setting. # ATSHostList setting.
# #
# Description: Used to configure the address of the # Description: Used to configure the addresses of the
# ATS that should be used for obtaining # ATSs that should be used for obtaining
# authentication tokens. # authentication tokens. Use semicolons
# and no spaces to separate the host
# entries. To also configure the ports
# utilized by a host specify the
# port number after the hostname using
# a colon to separate the fields.
# #
# If this parameter is not set, the client # Note that the client will try all of the
# assummes that the ATS resides in the same # ATSs on this list in the specified order
# host as the authentication token consuming # in addition to the host for which an
# services. # Authentication Token has been requested.
# #
#ATS-hostname hostname or IP address #ATSHostList hostname1:2645;ip_address:443;hosname2
#
# ATS-port setting.
#
# Description: Used to configure the port utilized by the
# ATS to listen for connections.
#
# If this parameter is not set ....
#
#ATS-port 2645
# #
# DisableSecureConnections setting. # DisableSecureConnections setting.

View File

@ -29,7 +29,9 @@
//===[ Type definitions ]================================================== //===[ Type definitions ]==================================================
#define DEFAULT_RETRY_LIFETIME 5 // seconds #define DEFAULT_RETRY_LIFETIME 300 // seconds
#define DEFAULT_ATS_PORT 2645
#define LOG_FILE_NAME "\\casaauthtoken.log" #define LOG_FILE_NAME "\\casaauthtoken.log"
@ -51,8 +53,7 @@ char *g_pDebugLogFilePath = NULL;
// //
bool g_bInitialized = false; bool g_bInitialized = false;
long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG; long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
char *g_pATSHostName = NULL; LIST_ENTRY g_ATSHostList;
uint16_t g_ATSPort = 2645;
//++======================================================================= //++=======================================================================
@ -298,6 +299,7 @@ ObtainAuthTokenFromServer(
IN const char *pServiceName, IN const char *pServiceName,
IN const char *pHostName, IN const char *pHostName,
IN const char *pNormalizedHostName, IN const char *pNormalizedHostName,
IN const ATSHostEntry *pATSHost,
IN const void *pCredStoreScope, IN const void *pCredStoreScope,
INOUT char **ppAuthToken, INOUT char **ppAuthToken,
INOUT int *pTokenLifetime, INOUT int *pTokenLifetime,
@ -324,8 +326,8 @@ ObtainAuthTokenFromServer(
*pAdvisedToRetry = false; *pAdvisedToRetry = false;
// Open Rpc Session to the auth service at the specified host // Open Rpc Session to the auth service at the specified host
pRpcSession = OpenRpcSession((g_pATSHostName != NULL) ? g_pATSHostName : pHostName, pRpcSession = OpenRpcSession(pATSHost->pName,
g_ATSPort); pATSHost->port);
if (pRpcSession) if (pRpcSession)
{ {
char *pReqMsg = NULL; char *pReqMsg = NULL;
@ -337,7 +339,15 @@ ObtainAuthTokenFromServer(
char *pSessionToken = NULL; char *pSessionToken = NULL;
// Request the auth parameters associated with this service // Request the auth parameters associated with this service
pReqMsg = BuildGetAuthPolicyMsg(pServiceName, "localhost"); // tbd - This will be changed in the future so that we can support services residing in a different host than the ATS if (strcmp(pHostName, pATSHost->pName) == 0
|| strcmp(pNormalizedHostName, pATSHost->pName) == 0)
{
pReqMsg = BuildGetAuthPolicyMsg(pServiceName, "localhost");
}
else
{
pReqMsg = BuildGetAuthPolicyMsg(pServiceName, pNormalizedHostName);
}
if (pReqMsg) if (pReqMsg)
{ {
// Issue rpc // Issue rpc
@ -367,15 +377,24 @@ ObtainAuthTokenFromServer(
// Now try to obtain a session token // Now try to obtain a session token
retStatus = ObtainSessionToken(pRpcSession, retStatus = ObtainSessionToken(pRpcSession,
pAuthPolicy, pAuthPolicy,
(g_pATSHostName != NULL) ? g_pATSHostName : pHostName, (const char*) pATSHost->pName,
pCredStoreScope, pCredStoreScope,
&pSessionToken, &pSessionToken,
&pSessionTokenAuthContext); &pSessionTokenAuthContext);
if (CASA_SUCCESS(retStatus)) if (CASA_SUCCESS(retStatus))
{ {
// Request auth token for the service
free(pReqMsg); free(pReqMsg);
pReqMsg = BuildGetAuthTokenMsg(pServiceName, "localhost", pSessionToken); // tbd - This will be changed in the future so that we can support services residing in a different host than the ATS
// Request auth token for the service
if (strcmp(pHostName, pATSHost->pName) == 0
|| strcmp(pNormalizedHostName, pATSHost->pName) == 0)
{
pReqMsg = BuildGetAuthTokenMsg(pServiceName, "localhost", pSessionToken);
}
else
{
pReqMsg = BuildGetAuthTokenMsg(pServiceName, pNormalizedHostName, pSessionToken);
}
if (pReqMsg) if (pReqMsg)
{ {
// Free the previous response msg buffer // Free the previous response msg buffer
@ -620,16 +639,16 @@ ObtainAuthTokenInt(
// Make sure we are fully initialized // Make sure we are fully initialized
if (g_bInitialized == false) if (g_bInitialized == false)
{ {
retStatus = InitializeLibrary(); retStatus = InitializeLibrary();
if (retStatus == CASA_STATUS_SUCCESS) if (retStatus == CASA_STATUS_SUCCESS)
{ {
g_bInitialized = true; g_bInitialized = true;
} }
else else
{ {
goto exit; goto exit;
} }
} }
// Release our synchronization mutex // Release our synchronization mutex
@ -639,116 +658,202 @@ ObtainAuthTokenInt(
pNormalizedHostName = NormalizeHostName(pHostName); pNormalizedHostName = NormalizeHostName(pHostName);
if (pNormalizedHostName) if (pNormalizedHostName)
{ {
bool setupHostEntries = true;
char *pHostNameAnd443 = NULL;
char *pHostNameAnd2645 = NULL;
ATSHostEntry serviceHostEntry443 = {};
ATSHostEntry serviceHostEntry2645 = {};
LIST_ENTRY *pListEntry;
ATSHostEntry *pHostEntryInUse;
// Start user process synchronization // Start user process synchronization
AcquireUserMutex(hUserMutex); AcquireUserMutex(hUserMutex);
// Try to find a cache entry for the service // Determine if we should setup host entries for the
pCacheEntry = FindAuthTokenEntryInCache(pServiceName, // host where the service resides.
pNormalizedHostName, pListEntry = g_ATSHostList.Flink;
pCredStoreScope); while(pListEntry != &g_ATSHostList)
if (pCacheEntry == NULL)
{ {
// Initialize to retry in case of failure pHostEntryInUse = CONTAINING_RECORD(pListEntry, ATSHostEntry, listEntry);
int cacheEntryLifetime = DEFAULT_RETRY_LIFETIME; if (strcmp(pHostEntryInUse->pName, pHostName) == 0
bool advisedToRetry; || strcmp(pHostEntryInUse->pName, pNormalizedHostName) == 0)
// Cache entry created, now try to obtain auth token from the CASA Server
pToken = NULL;
retStatus = ObtainAuthTokenFromServer(pServiceName,
pHostName,
pNormalizedHostName,
pCredStoreScope,
&pToken,
&cacheEntryLifetime,
&advisedToRetry);
// Retry if not successful and if advised to do so
if (!CASA_SUCCESS(retStatus)
&& advisedToRetry)
{ {
// The service's host is already in our list
setupHostEntries = false;
break;
}
// Advance to the next entry
pListEntry = pListEntry->Flink;
}
// Setup host entries for the service's host if necessary
if (setupHostEntries)
{
// Allocate space for the host name and port strings
pHostNameAnd443 = malloc(strlen(pHostName) + 5);
pHostNameAnd2645 = malloc(strlen(pHostName) + 6);
if (pHostNameAnd443 != NULL
&& pHostNameAnd2645 != NULL)
{
sprintf(pHostNameAnd443, "%s:%d", pHostName, 443);
sprintf(pHostNameAnd2645, "%s:%d", pHostName, 2645);
serviceHostEntry2645.pNameAndPort = pHostNameAnd2645;
serviceHostEntry2645.pName = pHostName;
serviceHostEntry2645.port = 2645;
InsertHeadList(&g_ATSHostList, &serviceHostEntry2645.listEntry);
serviceHostEntry443.pNameAndPort = pHostNameAnd443;
serviceHostEntry443.pName = pHostName;
serviceHostEntry443.port = 443;
InsertHeadList(&g_ATSHostList, &serviceHostEntry443.listEntry);
}
else
{
DbgTrace(0, "-ObtainAuthTokenInt- Buffer allocation failure\n", 0);
setupHostEntries = false; // To keep us from de-linking the entries later
}
}
// Now try to obtain an authentication token using the
// host entries at our disposal.
pListEntry = g_ATSHostList.Flink;
while(pListEntry != &g_ATSHostList)
{
// Get pointer to the host entry
pHostEntryInUse = CONTAINING_RECORD(pListEntry, ATSHostEntry, listEntry);
// Try to find a cache entry for the service
pCacheEntry = FindAuthTokenEntryInCache(pServiceName,
pNormalizedHostName,
pHostEntryInUse,
pCredStoreScope);
if (pCacheEntry == NULL)
{
// Initialize to retry in case of failure
int cacheEntryLifetime = DEFAULT_RETRY_LIFETIME;
bool advisedToRetry;
// Cache entry created, now try to obtain auth token from the CASA Server
pToken = NULL;
retStatus = ObtainAuthTokenFromServer(pServiceName, retStatus = ObtainAuthTokenFromServer(pServiceName,
pHostName, pHostName,
pNormalizedHostName, pNormalizedHostName,
pHostEntryInUse,
pCredStoreScope, pCredStoreScope,
&pToken, &pToken,
&cacheEntryLifetime, &cacheEntryLifetime,
&advisedToRetry); &advisedToRetry);
}
// Add the entry to the cache if successful or if the reason that we failed // Retry if not successful and if advised to do so
// was because the server was un-available. if (!CASA_SUCCESS(retStatus)
if (CASA_SUCCESS(retStatus) && advisedToRetry)
|| CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE)
{
pCacheEntry = CreateAuthTokenCacheEntry(pServiceName,
pNormalizedHostName,
retStatus,
pToken,
cacheEntryLifetime,
pCredStoreScope);
if (pCacheEntry)
{ {
// Release the cache entry if the resulting status is not successful retStatus = ObtainAuthTokenFromServer(pServiceName,
if (!CASA_SUCCESS(retStatus)) pHostName,
pNormalizedHostName,
pHostEntryInUse,
pCredStoreScope,
&pToken,
&cacheEntryLifetime,
&advisedToRetry);
}
// Add the entry to the cache if we did not fail due to authentication
// failure.
if (CasaStatusCode(retStatus) != CASA_STATUS_AUTHENTICATION_FAILURE)
{
pCacheEntry = CreateAuthTokenCacheEntry(pServiceName,
pNormalizedHostName,
pHostEntryInUse,
retStatus,
pToken,
cacheEntryLifetime,
pCredStoreScope);
if (pCacheEntry)
{ {
FreeAuthCacheEntry(pCacheEntry); // Release the cache entry if the resulting status is not successful
if (!CASA_SUCCESS(retStatus))
{
FreeAuthCacheEntry(pCacheEntry);
}
} }
} }
}
// Release authentication token if present // Release authentication token if present
if (pToken) if (pToken)
{ {
// Clear the memory before releasing the buffer since it contains // Clear the memory before releasing the buffer since it contains
// security sensitive data. // security sensitive data.
memset(pToken, 0, strlen(pToken)); memset(pToken, 0, strlen(pToken));
free(pToken); free(pToken);
} }
}
else
{
// Cache entry found, update the return status with the information saved in it
// and release it if its status is not successful.
if (!CASA_SUCCESS(retStatus = pCacheEntry->status))
{
FreeAuthCacheEntry(pCacheEntry);
}
}
// Try to return auth token if we have one to return
if (CASA_SUCCESS(retStatus))
{
int tokenLen = (int) strlen(pCacheEntry->token) + 1;
// We have an authentication token, try to return it to the caller
// after verifying that the supplied buffer is big enough.
if (*pAuthTokenBufLen >= tokenLen)
{
// Return the auth token to the caller
DbgTrace(2, "-ObtainAuthTokenInt- Copying the token into the callers buffer\n", 0);
strcpy(pAuthTokenBuf, pCacheEntry->token);
} }
else else
{ {
if (*pAuthTokenBufLen != 0) // Cache entry found, update the return status with the information saved in it
// and release it if its status is not successful.
if (!CASA_SUCCESS(retStatus = pCacheEntry->status))
{ {
DbgTrace(0, "-ObtainAuthTokenInt- The supplied buffer is not large enough", 0); FreeAuthCacheEntry(pCacheEntry);
} }
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
} }
// Return the token length to the caller // Try to return auth token if we have one to return
*pAuthTokenBufLen = tokenLen; if (CASA_SUCCESS(retStatus))
{
int tokenLen = (int) strlen(pCacheEntry->token) + 1;
FreeAuthCacheEntry(pCacheEntry); // We have an authentication token, try to return it to the caller
// after verifying that the supplied buffer is big enough.
if (*pAuthTokenBufLen >= tokenLen)
{
// Return the auth token to the caller
DbgTrace(2, "-ObtainAuthTokenInt- Copying the token into the callers buffer\n", 0);
strcpy(pAuthTokenBuf, pCacheEntry->token);
}
else
{
if (*pAuthTokenBufLen != 0)
{
DbgTrace(0, "-ObtainAuthTokenInt- The supplied buffer is not large enough", 0);
}
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
// Return the token length to the caller
*pAuthTokenBufLen = tokenLen;
FreeAuthCacheEntry(pCacheEntry);
// No need to loop any longer
break;
}
// Advance to the next host entry
pListEntry = pListEntry->Flink;
}
// Unlink the service host entries if necessary
if (setupHostEntries)
{
RemoveEntryList(&serviceHostEntry2645.listEntry);
RemoveEntryList(&serviceHostEntry443.listEntry);
} }
// Stop user process synchronization // Stop user process synchronization
ReleaseUserMutex(hUserMutex); ReleaseUserMutex(hUserMutex);
// Free the space allocated for the normalized host name // Free the space allocated during processing of the request
if (pHostNameAnd443)
free(pHostNameAnd443);
if (pHostNameAnd2645)
free(pHostNameAnd2645);
free(pNormalizedHostName); free(pNormalizedHostName);
} }
else else
@ -928,6 +1033,64 @@ CleanUpAuthTokenCache(void)
} }
//++=======================================================================
void
CreateATSHostEntry(
IN const char *pHostName,
IN uint16_t port)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "-CreateATSHostEntry- Start\n", 0);
// Create host entry
ATSHostEntry *pHostEntry = malloc(sizeof(ATSHostEntry));
if (pHostEntry != NULL)
{
// Allocate buffers to keep copies of the strings provided
pHostEntry->pNameAndPort = malloc(strlen(pHostName) + 7);
pHostEntry->pName = malloc(strlen(pHostName) + 1);
if (pHostEntry->pNameAndPort != NULL
&& pHostEntry->pName != NULL)
{
// Setup the strings into the corresponding buffers
sprintf(pHostEntry->pNameAndPort, "%s:%d", pHostName, port);
strcpy(pHostEntry->pName, pHostName);
// Save host port in entry
pHostEntry->port = port;
// Insert the entry at the tail of the list
InsertTailList(&g_ATSHostList, &pHostEntry->listEntry);
}
else
{
DbgTrace(0, "-CreateATSHostEntry- Failed to allocate buffer\n", 0);
if (pHostEntry->pNameAndPort)
free(pHostEntry->pNameAndPort);
if (pHostEntry->pName)
free(pHostEntry->pName);
free(pHostEntry);
}
}
else
{
DbgTrace(0, "-CreateATSHostEntry- Failed to allocate buffer for host entry\n", 0);
}
DbgTrace(1, "-CreateATSHostEntry- Exit\n", 0);
}
//++======================================================================= //++=======================================================================
int int
InitializeLibrary(void) InitializeLibrary(void)
@ -948,14 +1111,16 @@ InitializeLibrary(void)
ConfigIf *pClientConfigIf; ConfigIf *pClientConfigIf;
char *pDebugLevelSetting; char *pDebugLevelSetting;
char *pDebugLogFolderPathSetting; char *pDebugLogFolderPathSetting;
char *pATSPortSetting; char *pATSHostListSetting;
char *pATSHostNameSetting;
char *pDisableSecureConnections; char *pDisableSecureConnections;
char *pAllowInvalidCerts; char *pAllowInvalidCerts;
char *pUsersCannotAllowInvalidCerts; char *pUsersCannotAllowInvalidCerts;
DbgTrace(1, "-InitializeLibrary- Start\n", 0); DbgTrace(1, "-InitializeLibrary- Start\n", 0);
// Initialize the ATSHostList
InitializeListHead(&g_ATSHostList);
// Try to obtain client configuration settings // Try to obtain client configuration settings
getConfigStatus = GetConfigInterface(clientConfigFolder, getConfigStatus = GetConfigInterface(clientConfigFolder,
"client", "client",
@ -998,25 +1163,59 @@ InitializeLibrary(void)
pClientConfigIf->freeValueString(pClientConfigIf, pDebugLogFolderPathSetting); pClientConfigIf->freeValueString(pClientConfigIf, pDebugLogFolderPathSetting);
} }
// Check if an ATS hostname has been configured // Check if an ATS Host List has been configured
pATSHostNameSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-hostname"); pATSHostListSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATSHostList");
if (pATSHostNameSetting != NULL) if (pATSHostListSetting != NULL)
{ {
DbgTrace(0, "-InitializeLibrary- ATS hostname configured = %s\n", pATSHostNameSetting); char *pSavePtr;
char *pHostAndPort;
// Remember the ATS host name DbgTrace(0, "-InitializeLibrary- ATSHostList configured = %s\n", pATSHostListSetting);
g_pATSHostName = malloc(strlen(pATSHostNameSetting) + 1);
if (g_pATSHostName) // Go through all configured host addresses
pHostAndPort = strtok_r(pATSHostListSetting, ";", &pSavePtr);
while (pHostAndPort != NULL)
{ {
strcpy(g_pATSHostName, pATSHostNameSetting); char *pSavePtr2;
} char *pHostName;
else
{ // Check if the host address includes the listen port number.
DbgTrace(0, "-InitializeLibrary- Failed to allocate buffer for ATS host name\n", 0); pHostName = strtok_r(pHostAndPort, ":", &pSavePtr2);
if (pHostName != NULL)
{
uint16_t port = 0;
char *pHostPort = strtok_r(NULL, ":", &pSavePtr2);
if (pHostPort != NULL)
{
// Convert the number to hex
port = (uint16_t) dtoul(pHostPort, strlen(pHostPort));
}
// Now create the necessary ATS Host entries
if (port == 0)
{
// The port number was not configured, create an ATS Host entry
// for each possible listen port.
CreateATSHostEntry(pHostName, 443);
CreateATSHostEntry(pHostName, 2645);
}
else
{
// Create ATS Host entry for configured port
CreateATSHostEntry(pHostName, port);
}
}
else
{
DbgTrace(0, "-InitializeLibrary- Error parsing configured host address\n", 0);
}
// Advance to the next entry
pHostAndPort = strtok_r(NULL, ";", &pSavePtr);
} }
// Free the buffer holding the ats host name setting // Free the buffer holding the ats host list setting
pClientConfigIf->freeValueString(pClientConfigIf, pATSHostNameSetting); pClientConfigIf->freeValueString(pClientConfigIf, pATSHostListSetting);
} }
// Check if the DisableSecureConnections setting has been configured // Check if the DisableSecureConnections setting has been configured
@ -1087,19 +1286,6 @@ InitializeLibrary(void)
} }
} }
// Check if an ATS port number has been configured
pATSPortSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-port");
if (pATSPortSetting != NULL)
{
DbgTrace(0, "-InitializeLibrary- ATS port number configured = %s\n", pATSPortSetting);
// Convert the number to hex
g_ATSPort = (int) dtoul(pATSPortSetting, strlen(pATSPortSetting));
// Free the buffer holding the port number
pClientConfigIf->freeValueString(pClientConfigIf, pATSPortSetting);
}
// Release config interface instance // Release config interface instance
pClientConfigIf->releaseReference(pClientConfigIf); pClientConfigIf->releaseReference(pClientConfigIf);
} }
@ -1108,22 +1294,6 @@ InitializeLibrary(void)
retStatus = InitializeHostNameNormalization(); retStatus = InitializeHostNameNormalization();
if (CASA_SUCCESS(retStatus)) if (CASA_SUCCESS(retStatus))
{ {
// Normalize ATS host name if configured
if (g_pATSHostName)
{
char *pNormalizedHostName = NormalizeHostName(g_pATSHostName);
if (pNormalizedHostName)
{
// Use this name instead of the one that we already have
free(g_pATSHostName);
g_pATSHostName = pNormalizedHostName;
}
else
{
DbgTrace(0, "-InitializeLibrary- ATS Hostname normalization failed\n", 0);
}
}
// Initialize the auth cache // Initialize the auth cache
retStatus = InitializeAuthCache(); retStatus = InitializeAuthCache();
if (CASA_SUCCESS(retStatus)) if (CASA_SUCCESS(retStatus))
@ -1161,6 +1331,9 @@ UnInitializeLibrary(void)
// L2 // L2
//=======================================================================-- //=======================================================================--
{ {
LIST_ENTRY *pListEntry;
ATSHostEntry *pHostEntry;
DbgTrace(1, "-UnInitializeLibrary- Start\n", 0); DbgTrace(1, "-UnInitializeLibrary- Start\n", 0);
// Un-initialize the host name normalization // Un-initialize the host name normalization
@ -1180,8 +1353,16 @@ UnInitializeLibrary(void)
free(pBuffer); free(pBuffer);
} }
if (g_pATSHostName) pListEntry = g_ATSHostList.Flink;
free(g_pATSHostName); while (pListEntry != &g_ATSHostList)
{
pHostEntry = CONTAINING_RECORD(pListEntry, ATSHostEntry, listEntry);
RemoveEntryList(pListEntry);
free(pHostEntry->pNameAndPort);
free(pHostEntry->pName);
free(pHostEntry);
pListEntry = g_ATSHostList.Flink;
}
DbgTrace(1, "-UnInitializeLibrary- End\n", 0); DbgTrace(1, "-UnInitializeLibrary- End\n", 0);
} }

View File

@ -41,6 +41,19 @@
#define MAX_RPC_REPLY_SZ (256 * 1024) #define MAX_RPC_REPLY_SZ (256 * 1024)
//
// ATS Host Entry structure
//
typedef struct _ATSHostEntry
{
LIST_ENTRY listEntry;
char *pNameAndPort;
char *pName;
uint16_t port;
} ATSHostEntry, *PATSHostEntry;
// //
// Authentication Context structure // Authentication Context structure
// //
@ -270,6 +283,7 @@ AuthCacheEntry*
CreateAuthTokenCacheEntry( CreateAuthTokenCacheEntry(
IN const char *pCacheKey, IN const char *pCacheKey,
IN const char *pHostName, IN const char *pHostName,
IN const ATSHostEntry *pATSHost,
IN CasaStatus status, IN CasaStatus status,
IN char *pToken, IN char *pToken,
IN int entryLifetime, IN int entryLifetime,
@ -291,6 +305,7 @@ AuthCacheEntry*
FindAuthTokenEntryInCache( FindAuthTokenEntryInCache(
IN const char *pCacheKey, IN const char *pCacheKey,
IN const char *pGroupOrHostName, IN const char *pGroupOrHostName,
IN const ATSHostEntry *pATSHost,
IN void *pCredStoreScope); IN void *pCredStoreScope);
extern extern