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:
parent
f445b6d9c2
commit
3cc4067ab1
@ -60,6 +60,7 @@ AuthCacheEntry*
|
||||
CreateAuthTokenCacheEntry(
|
||||
IN const char *pCacheKey,
|
||||
IN const char *pGroupOrHostName,
|
||||
IN const ATSHostEntry *pATSHost,
|
||||
IN CasaStatus status,
|
||||
IN char *pToken,
|
||||
IN int entryLifetime, // seconds (0 == Lives forever)
|
||||
@ -81,7 +82,7 @@ CreateAuthTokenCacheEntry(
|
||||
SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"};
|
||||
SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"};
|
||||
uint32_t entrySize, keySize;
|
||||
size_t tokenSize, wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen;
|
||||
size_t tokenSize, wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen, hostAndPortStrLen;
|
||||
WrapperAuthCacheEntry *pWrapperEntry = NULL;
|
||||
AuthCacheEntry *pEntry = NULL;
|
||||
char *pKey;
|
||||
@ -145,43 +146,97 @@ CreateAuthTokenCacheEntry(
|
||||
cacheKeyStrLen = strlen(pCacheKey);
|
||||
groupOrHostNameStrLen = strlen(pGroupOrHostName);
|
||||
|
||||
// Verify that keySize will not overflow
|
||||
if ((cacheKeyStrLen + groupOrHostNameStrLen + 2) <= UINT32_MAX)
|
||||
// Build the cache entry key based on the status
|
||||
if (status == CASA_STATUS_SUCCESS)
|
||||
{
|
||||
keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + 2);
|
||||
|
||||
pKey = malloc(keySize);
|
||||
if (pKey)
|
||||
// Successful cache entries have a key of the form
|
||||
// cachekey@group_or_host_name.
|
||||
//
|
||||
// Verify that keySize will not overflow
|
||||
if ((cacheKeyStrLen + groupOrHostNameStrLen + 2) <= UINT32_MAX)
|
||||
{
|
||||
strncpy(pKey, pCacheKey, keySize);
|
||||
strncat(pKey, "@", keySize);
|
||||
strncat(pKey, pGroupOrHostName, keySize);
|
||||
keySize = (uint32_t) (cacheKeyStrLen + groupOrHostNameStrLen + 2);
|
||||
|
||||
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)
|
||||
pKey = malloc(keySize);
|
||||
if (pKey)
|
||||
{
|
||||
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
|
||||
{
|
||||
DbgTrace(0, "-CreateAuthTokenCacheEntry- Memory allocation failure\n", 0);
|
||||
DbgTrace(0, "-CreateAuthTokenCacheEntry- keySize overflow prevented\n", 0);
|
||||
}
|
||||
}
|
||||
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
|
||||
@ -543,6 +598,7 @@ AuthCacheEntry*
|
||||
FindAuthTokenEntryInCache(
|
||||
IN const char *pCacheKey,
|
||||
IN const char *pGroupOrHostName,
|
||||
IN const ATSHostEntry *pATSHost,
|
||||
IN void *pCredStoreScope
|
||||
)
|
||||
//
|
||||
@ -561,7 +617,7 @@ FindAuthTokenEntryInCache(
|
||||
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;
|
||||
size_t wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen;
|
||||
size_t wrapperEntrySize, cacheKeyStrLen, groupOrHostNameStrLen, hostAndPortStrLen;
|
||||
WrapperAuthCacheEntry *pWrapperEntry = NULL;
|
||||
AuthCacheEntry *pEntry = NULL;
|
||||
char *pKey;
|
||||
@ -571,15 +627,18 @@ FindAuthTokenEntryInCache(
|
||||
|
||||
cacheKeyStrLen = strlen(pCacheKey);
|
||||
groupOrHostNameStrLen = strlen(pGroupOrHostName);
|
||||
hostAndPortStrLen = strlen(pATSHost->pNameAndPort);
|
||||
|
||||
// Verify that keySize will not overflow
|
||||
if ((cacheKeyStrLen + groupOrHostNameStrLen + 2) <= UINT32_MAX)
|
||||
// Verify that the worst case keySize will not overflow
|
||||
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);
|
||||
if (pKey)
|
||||
{
|
||||
// First try to read entry using key for successful cache entries
|
||||
strncpy(pKey, pCacheKey, keySize);
|
||||
strncat(pKey, "@", keySize);
|
||||
strncat(pKey, pGroupOrHostName, keySize);
|
||||
@ -592,7 +651,7 @@ FindAuthTokenEntryInCache(
|
||||
&sessionKeyChain,
|
||||
&sharedId,
|
||||
(SS_UTF8_T*) pKey,
|
||||
keySize,
|
||||
strlen(pKey) + 1,
|
||||
NULL,
|
||||
&valueLength,
|
||||
(SSCS_PASSWORD_T*) NULL,
|
||||
@ -615,7 +674,7 @@ FindAuthTokenEntryInCache(
|
||||
&sessionKeyChain,
|
||||
&sharedId,
|
||||
(SS_UTF8_T*) pKey,
|
||||
keySize,
|
||||
strlen(pKey) + 1,
|
||||
(uint8_t *) pEntry,
|
||||
&valueLength,
|
||||
(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);
|
||||
}
|
||||
|
@ -6,28 +6,23 @@
|
||||
#######################################################
|
||||
|
||||
#
|
||||
# ATS-hostname setting.
|
||||
# ATSHostList setting.
|
||||
#
|
||||
# Description: Used to configure the address of the
|
||||
# ATS that should be used for obtaining
|
||||
# authentication tokens.
|
||||
# Description: Used to configure the addresses of the
|
||||
# ATSs that should be used for obtaining
|
||||
# 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
|
||||
# assummes that the ATS resides in the same
|
||||
# host as the authentication token consuming
|
||||
# services.
|
||||
# Note that the client will try all of the
|
||||
# ATSs on this list in the specified order
|
||||
# in addition to the host for which an
|
||||
# Authentication Token has been requested.
|
||||
#
|
||||
#ATS-hostname hostname or IP address
|
||||
|
||||
#
|
||||
# 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
|
||||
#ATSHostList hostname1:2645;ip_address:443;hosname2
|
||||
|
||||
#
|
||||
# DisableSecureConnections setting.
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
//===[ 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"
|
||||
|
||||
@ -51,8 +53,7 @@ char *g_pDebugLogFilePath = NULL;
|
||||
//
|
||||
bool g_bInitialized = false;
|
||||
long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
||||
char *g_pATSHostName = NULL;
|
||||
uint16_t g_ATSPort = 2645;
|
||||
LIST_ENTRY g_ATSHostList;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
@ -298,6 +299,7 @@ ObtainAuthTokenFromServer(
|
||||
IN const char *pServiceName,
|
||||
IN const char *pHostName,
|
||||
IN const char *pNormalizedHostName,
|
||||
IN const ATSHostEntry *pATSHost,
|
||||
IN const void *pCredStoreScope,
|
||||
INOUT char **ppAuthToken,
|
||||
INOUT int *pTokenLifetime,
|
||||
@ -324,8 +326,8 @@ ObtainAuthTokenFromServer(
|
||||
*pAdvisedToRetry = false;
|
||||
|
||||
// Open Rpc Session to the auth service at the specified host
|
||||
pRpcSession = OpenRpcSession((g_pATSHostName != NULL) ? g_pATSHostName : pHostName,
|
||||
g_ATSPort);
|
||||
pRpcSession = OpenRpcSession(pATSHost->pName,
|
||||
pATSHost->port);
|
||||
if (pRpcSession)
|
||||
{
|
||||
char *pReqMsg = NULL;
|
||||
@ -337,7 +339,15 @@ ObtainAuthTokenFromServer(
|
||||
char *pSessionToken = NULL;
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Issue rpc
|
||||
@ -367,15 +377,24 @@ ObtainAuthTokenFromServer(
|
||||
// Now try to obtain a session token
|
||||
retStatus = ObtainSessionToken(pRpcSession,
|
||||
pAuthPolicy,
|
||||
(g_pATSHostName != NULL) ? g_pATSHostName : pHostName,
|
||||
(const char*) pATSHost->pName,
|
||||
pCredStoreScope,
|
||||
&pSessionToken,
|
||||
&pSessionTokenAuthContext);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Request auth token for the service
|
||||
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)
|
||||
{
|
||||
// Free the previous response msg buffer
|
||||
@ -620,16 +639,16 @@ ObtainAuthTokenInt(
|
||||
// Make sure we are fully initialized
|
||||
if (g_bInitialized == false)
|
||||
{
|
||||
retStatus = InitializeLibrary();
|
||||
retStatus = InitializeLibrary();
|
||||
|
||||
if (retStatus == CASA_STATUS_SUCCESS)
|
||||
{
|
||||
g_bInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
if (retStatus == CASA_STATUS_SUCCESS)
|
||||
{
|
||||
g_bInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Release our synchronization mutex
|
||||
@ -639,116 +658,202 @@ ObtainAuthTokenInt(
|
||||
pNormalizedHostName = NormalizeHostName(pHostName);
|
||||
if (pNormalizedHostName)
|
||||
{
|
||||
bool setupHostEntries = true;
|
||||
char *pHostNameAnd443 = NULL;
|
||||
char *pHostNameAnd2645 = NULL;
|
||||
ATSHostEntry serviceHostEntry443 = {};
|
||||
ATSHostEntry serviceHostEntry2645 = {};
|
||||
LIST_ENTRY *pListEntry;
|
||||
ATSHostEntry *pHostEntryInUse;
|
||||
|
||||
// Start user process synchronization
|
||||
AcquireUserMutex(hUserMutex);
|
||||
|
||||
// Try to find a cache entry for the service
|
||||
pCacheEntry = FindAuthTokenEntryInCache(pServiceName,
|
||||
pNormalizedHostName,
|
||||
pCredStoreScope);
|
||||
if (pCacheEntry == NULL)
|
||||
// Determine if we should setup host entries for the
|
||||
// host where the service resides.
|
||||
pListEntry = g_ATSHostList.Flink;
|
||||
while(pListEntry != &g_ATSHostList)
|
||||
{
|
||||
// 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,
|
||||
pHostName,
|
||||
pNormalizedHostName,
|
||||
pCredStoreScope,
|
||||
&pToken,
|
||||
&cacheEntryLifetime,
|
||||
&advisedToRetry);
|
||||
|
||||
// Retry if not successful and if advised to do so
|
||||
if (!CASA_SUCCESS(retStatus)
|
||||
&& advisedToRetry)
|
||||
pHostEntryInUse = CONTAINING_RECORD(pListEntry, ATSHostEntry, listEntry);
|
||||
if (strcmp(pHostEntryInUse->pName, pHostName) == 0
|
||||
|| strcmp(pHostEntryInUse->pName, pNormalizedHostName) == 0)
|
||||
{
|
||||
// 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,
|
||||
pHostName,
|
||||
pNormalizedHostName,
|
||||
pHostEntryInUse,
|
||||
pCredStoreScope,
|
||||
&pToken,
|
||||
&cacheEntryLifetime,
|
||||
&advisedToRetry);
|
||||
}
|
||||
|
||||
// Add the entry to the cache if successful or if the reason that we failed
|
||||
// was because the server was un-available.
|
||||
if (CASA_SUCCESS(retStatus)
|
||||
|| CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE)
|
||||
{
|
||||
pCacheEntry = CreateAuthTokenCacheEntry(pServiceName,
|
||||
pNormalizedHostName,
|
||||
retStatus,
|
||||
pToken,
|
||||
cacheEntryLifetime,
|
||||
pCredStoreScope);
|
||||
if (pCacheEntry)
|
||||
// Retry if not successful and if advised to do so
|
||||
if (!CASA_SUCCESS(retStatus)
|
||||
&& advisedToRetry)
|
||||
{
|
||||
// Release the cache entry if the resulting status is not successful
|
||||
if (!CASA_SUCCESS(retStatus))
|
||||
retStatus = ObtainAuthTokenFromServer(pServiceName,
|
||||
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
|
||||
if (pToken)
|
||||
{
|
||||
// Clear the memory before releasing the buffer since it contains
|
||||
// security sensitive data.
|
||||
memset(pToken, 0, strlen(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);
|
||||
// Release authentication token if present
|
||||
if (pToken)
|
||||
{
|
||||
// Clear the memory before releasing the buffer since it contains
|
||||
// security sensitive data.
|
||||
memset(pToken, 0, strlen(pToken));
|
||||
free(pToken);
|
||||
}
|
||||
}
|
||||
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
|
||||
*pAuthTokenBufLen = tokenLen;
|
||||
// Try to return auth token if we have one to return
|
||||
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
|
||||
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);
|
||||
}
|
||||
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
|
||||
InitializeLibrary(void)
|
||||
@ -948,14 +1111,16 @@ InitializeLibrary(void)
|
||||
ConfigIf *pClientConfigIf;
|
||||
char *pDebugLevelSetting;
|
||||
char *pDebugLogFolderPathSetting;
|
||||
char *pATSPortSetting;
|
||||
char *pATSHostNameSetting;
|
||||
char *pATSHostListSetting;
|
||||
char *pDisableSecureConnections;
|
||||
char *pAllowInvalidCerts;
|
||||
char *pUsersCannotAllowInvalidCerts;
|
||||
|
||||
DbgTrace(1, "-InitializeLibrary- Start\n", 0);
|
||||
|
||||
// Initialize the ATSHostList
|
||||
InitializeListHead(&g_ATSHostList);
|
||||
|
||||
// Try to obtain client configuration settings
|
||||
getConfigStatus = GetConfigInterface(clientConfigFolder,
|
||||
"client",
|
||||
@ -998,25 +1163,59 @@ InitializeLibrary(void)
|
||||
pClientConfigIf->freeValueString(pClientConfigIf, pDebugLogFolderPathSetting);
|
||||
}
|
||||
|
||||
// Check if an ATS hostname has been configured
|
||||
pATSHostNameSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-hostname");
|
||||
if (pATSHostNameSetting != NULL)
|
||||
// Check if an ATS Host List has been configured
|
||||
pATSHostListSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATSHostList");
|
||||
if (pATSHostListSetting != NULL)
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- ATS hostname configured = %s\n", pATSHostNameSetting);
|
||||
char *pSavePtr;
|
||||
char *pHostAndPort;
|
||||
|
||||
// Remember the ATS host name
|
||||
g_pATSHostName = malloc(strlen(pATSHostNameSetting) + 1);
|
||||
if (g_pATSHostName)
|
||||
DbgTrace(0, "-InitializeLibrary- ATSHostList configured = %s\n", pATSHostListSetting);
|
||||
|
||||
// Go through all configured host addresses
|
||||
pHostAndPort = strtok_r(pATSHostListSetting, ";", &pSavePtr);
|
||||
while (pHostAndPort != NULL)
|
||||
{
|
||||
strcpy(g_pATSHostName, pATSHostNameSetting);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InitializeLibrary- Failed to allocate buffer for ATS host name\n", 0);
|
||||
char *pSavePtr2;
|
||||
char *pHostName;
|
||||
|
||||
// Check if the host address includes the listen port number.
|
||||
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
|
||||
pClientConfigIf->freeValueString(pClientConfigIf, pATSHostNameSetting);
|
||||
// Free the buffer holding the ats host list setting
|
||||
pClientConfigIf->freeValueString(pClientConfigIf, pATSHostListSetting);
|
||||
}
|
||||
|
||||
// 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
|
||||
pClientConfigIf->releaseReference(pClientConfigIf);
|
||||
}
|
||||
@ -1108,22 +1294,6 @@ InitializeLibrary(void)
|
||||
retStatus = InitializeHostNameNormalization();
|
||||
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
|
||||
retStatus = InitializeAuthCache();
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
@ -1161,6 +1331,9 @@ UnInitializeLibrary(void)
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
LIST_ENTRY *pListEntry;
|
||||
ATSHostEntry *pHostEntry;
|
||||
|
||||
DbgTrace(1, "-UnInitializeLibrary- Start\n", 0);
|
||||
|
||||
// Un-initialize the host name normalization
|
||||
@ -1180,8 +1353,16 @@ UnInitializeLibrary(void)
|
||||
free(pBuffer);
|
||||
}
|
||||
|
||||
if (g_pATSHostName)
|
||||
free(g_pATSHostName);
|
||||
pListEntry = g_ATSHostList.Flink;
|
||||
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);
|
||||
}
|
||||
|
@ -41,6 +41,19 @@
|
||||
|
||||
#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
|
||||
//
|
||||
@ -270,6 +283,7 @@ AuthCacheEntry*
|
||||
CreateAuthTokenCacheEntry(
|
||||
IN const char *pCacheKey,
|
||||
IN const char *pHostName,
|
||||
IN const ATSHostEntry *pATSHost,
|
||||
IN CasaStatus status,
|
||||
IN char *pToken,
|
||||
IN int entryLifetime,
|
||||
@ -291,6 +305,7 @@ AuthCacheEntry*
|
||||
FindAuthTokenEntryInCache(
|
||||
IN const char *pCacheKey,
|
||||
IN const char *pGroupOrHostName,
|
||||
IN const ATSHostEntry *pATSHost,
|
||||
IN void *pCredStoreScope);
|
||||
|
||||
extern
|
||||
|
Loading…
Reference in New Issue
Block a user