7cc9385642
server's certificate has been issued using the server's DNS name.
1438 lines
52 KiB
C
1438 lines
52 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"
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
#define DEFAULT_RETRY_LIFETIME 300 // seconds
|
|
|
|
#define BAD_CACHE_TRIGER_TIME 30 // seconds
|
|
|
|
#define DEFAULT_ATS_PORT 2645
|
|
|
|
#define LOG_FILE_NAME "\\casaauthtoken.log"
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
int
|
|
InitializeLibrary(void);
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
//
|
|
// Debug tracing level and debug log file path.
|
|
//
|
|
int DebugLevel = 0;
|
|
char *g_pDebugLogFilePath = NULL;
|
|
|
|
//
|
|
// Operating parameter
|
|
//
|
|
bool g_bInitialized = false;
|
|
long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
|
LIST_ENTRY g_ATSHostList;
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
ObtainSessionToken(
|
|
IN RpcSession *pRpcSession,
|
|
IN AuthPolicy *pAuthPolicy,
|
|
IN const char *pHostName,
|
|
IN void *pCredStoreScope,
|
|
INOUT char **ppSessionToken,
|
|
INOUT AuthContext **ppSessionTokenAuthContext)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_UNSUCCESSFUL);
|
|
LIST_ENTRY *pListEntry;
|
|
AuthCacheEntry *pCacheEntry = NULL;
|
|
AuthContext *pAuthContext = NULL;
|
|
|
|
DbgTrace(1, "-ObtainSessionToken- Start\n", 0);
|
|
|
|
// Initialize output parameter
|
|
*ppSessionToken = NULL;
|
|
|
|
// Look in our cache for an entry that matches one of the auth
|
|
// contexts specified in the AuthPolicy object.
|
|
pListEntry = pAuthPolicy->authContextListHead.Flink;
|
|
while (pListEntry != &pAuthPolicy->authContextListHead)
|
|
{
|
|
// Get pointer to AuthContext structure
|
|
pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry);
|
|
|
|
// Try to find a cache entry for the auth context
|
|
pCacheEntry = FindSessionTokenEntryInCache(pAuthContext->pContext,
|
|
pCredStoreScope);
|
|
if (pCacheEntry != NULL)
|
|
{
|
|
// Cache entry found, check if it is of use to us.
|
|
if (CASA_SUCCESS(pCacheEntry->status))
|
|
{
|
|
// This entry can be used, stop looking.
|
|
retStatus = pCacheEntry->status;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Free the entry
|
|
FreeAuthCacheEntry(pCacheEntry);
|
|
}
|
|
}
|
|
|
|
// Advance to the next entry
|
|
pListEntry = pListEntry->Flink;
|
|
}
|
|
|
|
// If we did not find a cache entry that we can use, then try to create one.
|
|
pListEntry = pAuthPolicy->authContextListHead.Flink;
|
|
while (!CASA_SUCCESS(retStatus)
|
|
&& pListEntry != &pAuthPolicy->authContextListHead)
|
|
{
|
|
char *pAuthMechToken;
|
|
|
|
// Get pointer to AuthContext structure
|
|
pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry);
|
|
|
|
// Only try to create cache entry for the auth context if there is not
|
|
// one already.
|
|
pCacheEntry = FindSessionTokenEntryInCache(pAuthContext->pContext,
|
|
pCredStoreScope);
|
|
if (pCacheEntry == NULL)
|
|
{
|
|
char *pReqMsg = NULL;
|
|
char *pRespMsg = NULL;
|
|
size_t respLen;
|
|
|
|
// Get authentication mechanism token
|
|
retStatus = GetAuthMechToken(pAuthContext,
|
|
pHostName,
|
|
pCredStoreScope,
|
|
&pAuthMechToken);
|
|
if (!CASA_SUCCESS(retStatus))
|
|
{
|
|
// We were not able to obtain an authentication mechanism token
|
|
// for the context.
|
|
//
|
|
// Advance to the next entry
|
|
pListEntry = pListEntry->Flink;
|
|
continue;
|
|
}
|
|
|
|
// Authenticate to the ATS
|
|
pReqMsg = BuildAuthenticateMsg(pAuthContext, pAuthMechToken);
|
|
if (pReqMsg)
|
|
{
|
|
// Issue rpc
|
|
retStatus = Rpc(pRpcSession,
|
|
"Authenticate",
|
|
g_rpcFlags,
|
|
pReqMsg,
|
|
&pRespMsg,
|
|
&respLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
if (pRespMsg
|
|
&& respLen != 0)
|
|
{
|
|
AuthenticateResp *pAuthenticateResp;
|
|
|
|
// Create Authenticate response object
|
|
retStatus = CreateAuthenticateResp(pRespMsg, respLen, &pAuthenticateResp);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Return the auth token to the caller
|
|
pCacheEntry = CreateSessionTokenCacheEntry(pAuthContext->pContext,
|
|
retStatus,
|
|
pAuthenticateResp->pToken,
|
|
pAuthenticateResp->tokenLifetime,
|
|
pCredStoreScope);
|
|
|
|
pAuthenticateResp->pToken = NULL; // To keep us from freeing the buffer
|
|
|
|
// Free the Authenticate response object
|
|
RelAuthenticateResp(pAuthenticateResp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainSessionToken- Did not receive Authenticate Response data\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_SERVER_ERROR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainSessionToken- Authenticate Rpc failure, error = %08X\n", retStatus);
|
|
}
|
|
|
|
// Free resources that may be hanging around
|
|
if (pRespMsg)
|
|
{
|
|
// Clear and free the memory associated with the response since it may contain
|
|
// security sensitive data.
|
|
memset(pRespMsg, 0, respLen);
|
|
free(pRespMsg);
|
|
}
|
|
|
|
// Clear and free the memory associated with the request message since
|
|
// it may contain security sensitive information.
|
|
memset(pReqMsg, 0, strlen(pReqMsg));
|
|
free(pReqMsg);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainSessionToken- Error building Authenticate msg\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
// Add the entry to the cache if the reason that we failed was because
|
|
// the server was unavailable.
|
|
if (CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE)
|
|
{
|
|
pCacheEntry = CreateSessionTokenCacheEntry(pAuthContext->pContext,
|
|
retStatus,
|
|
NULL,
|
|
DEFAULT_RETRY_LIFETIME,
|
|
pCredStoreScope);
|
|
|
|
}
|
|
|
|
// Release the cache entry if the resulting status is not successful
|
|
if (pCacheEntry)
|
|
{
|
|
if (!CASA_SUCCESS(retStatus))
|
|
{
|
|
FreeAuthCacheEntry(pCacheEntry);
|
|
}
|
|
}
|
|
|
|
// Free up the buffer associated with the authentication mechanism token
|
|
// after clearing it since it may contain sensitive information.
|
|
memset(pAuthMechToken, 0, strlen(pAuthMechToken));
|
|
free(pAuthMechToken);
|
|
}
|
|
else
|
|
{
|
|
// Free the entry
|
|
FreeAuthCacheEntry(pCacheEntry);
|
|
}
|
|
|
|
// Advance to the next entry
|
|
pListEntry = pListEntry->Flink;
|
|
}
|
|
|
|
// Return session token if successful
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Allocate a buffer for the return token
|
|
*ppSessionToken = (char*) malloc(strlen(pCacheEntry->token) + 1);
|
|
if (*ppSessionToken)
|
|
{
|
|
// Copy the token onto the allocated buffer
|
|
strcpy(*ppSessionToken, pCacheEntry->token);
|
|
|
|
// Return pointer to AuthContext associated with the session token
|
|
*ppSessionTokenAuthContext = pAuthContext;
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainSessionToken- Buffer allocation failure\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
FreeAuthCacheEntry(pCacheEntry);
|
|
}
|
|
|
|
DbgTrace(1, "-ObtainSessionToken- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
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,
|
|
INOUT bool *pAdvisedToRetry)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
|
RpcSession *pRpcSession;
|
|
|
|
DbgTrace(1, "-ObtainAuthTokenFromServer- Start\n", 0);
|
|
|
|
// Initialize output parameters
|
|
*ppAuthToken = NULL;
|
|
*pAdvisedToRetry = false;
|
|
|
|
// Open Rpc Session to the auth service at the specified host
|
|
pRpcSession = OpenRpcSession(pATSHost->pName,
|
|
pATSHost->port);
|
|
if (pRpcSession)
|
|
{
|
|
char *pReqMsg = NULL;
|
|
char *pRespMsg = NULL;
|
|
size_t respLen;
|
|
AuthPolicy *pAuthPolicy = NULL;
|
|
GetAuthPolicyResp *pGetAuthPolicyResp = NULL;
|
|
GetAuthTokenResp *pGetAuthTokenResp = NULL;
|
|
char *pSessionToken = NULL;
|
|
|
|
// Request the auth parameters associated with this service
|
|
if (strcmp(pHostName, pATSHost->pName) == 0
|
|
|| strcmp(pNormalizedHostName, pATSHost->pName) == 0)
|
|
{
|
|
pReqMsg = BuildGetAuthPolicyMsg(pServiceName, "localhost");
|
|
}
|
|
else
|
|
{
|
|
pReqMsg = BuildGetAuthPolicyMsg(pServiceName, pNormalizedHostName);
|
|
}
|
|
if (pReqMsg)
|
|
{
|
|
// Issue rpc
|
|
retStatus = Rpc(pRpcSession,
|
|
"GetAuthPolicy",
|
|
g_rpcFlags,
|
|
pReqMsg,
|
|
&pRespMsg,
|
|
&respLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
if (pRespMsg
|
|
&& respLen != 0)
|
|
{
|
|
// Create GetAuthPolicy response object
|
|
retStatus = CreateGetAuthPolicyResp(pRespMsg, respLen, &pGetAuthPolicyResp);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Create the AuthPolicy object
|
|
retStatus = CreateAuthPolicy(pGetAuthPolicyResp->pPolicy,
|
|
pGetAuthPolicyResp->policyLen,
|
|
&pAuthPolicy);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
AuthContext *pSessionTokenAuthContext = NULL;
|
|
|
|
// Now try to obtain a session token
|
|
retStatus = ObtainSessionToken(pRpcSession,
|
|
pAuthPolicy,
|
|
(const char*) pATSHost->pName,
|
|
pCredStoreScope,
|
|
&pSessionToken,
|
|
&pSessionTokenAuthContext);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
free(pReqMsg);
|
|
|
|
// 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
|
|
free(pRespMsg);
|
|
pRespMsg = NULL;
|
|
|
|
// Issue rpc
|
|
retStatus = Rpc(pRpcSession,
|
|
"GetAuthToken",
|
|
g_rpcFlags,
|
|
pReqMsg,
|
|
&pRespMsg,
|
|
&respLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
if (pRespMsg
|
|
&& respLen != 0)
|
|
{
|
|
// Create GetAuthPolicy response object
|
|
retStatus = CreateGetAuthTokenResp(pRespMsg, respLen, &pGetAuthTokenResp);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Return the auth token to the caller
|
|
*ppAuthToken = pGetAuthTokenResp->pToken;
|
|
pGetAuthTokenResp->pToken = NULL; // To keep us from freeing the buffer
|
|
*pTokenLifetime = pGetAuthTokenResp->tokenLifetime;
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to create GetAuthTokenResp object, error = %08X\n", retStatus);
|
|
|
|
// Remove the session token from the cache in case that it was due to a bad session token
|
|
if (pSessionTokenAuthContext)
|
|
{
|
|
RemoveSessionTokenEntryInCache(pSessionTokenAuthContext->pContext,
|
|
pCredStoreScope);
|
|
|
|
// Advice that a retry should be attempted
|
|
*pAdvisedToRetry = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Did not receive GetAuthToken Response data\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_SERVER_ERROR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- GetAuthToken Rpc failure, error = %08X\n", retStatus);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_SERVER_ERROR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Error building GetAuthToken msg\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to obtain session token, error = %08X\n", retStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to create AuthPolicy object, error = %08X\n", retStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to create GetAuthPolicyResp object, error = %08X\n", retStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Did not receive GetAuthPolicy Response data\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_SERVER_ERROR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- GetAuthPolicy Rpc failure, error = %08X\n", retStatus);
|
|
}
|
|
|
|
// Free resources that may be hanging around
|
|
if (pReqMsg)
|
|
{
|
|
// Clear the memory before freeing up the request message since it
|
|
// may contain security sensitive data.
|
|
memset(pReqMsg, 0, strlen(pReqMsg));
|
|
free(pReqMsg);
|
|
}
|
|
|
|
if (pRespMsg)
|
|
{
|
|
// Clear the memory before freeing up the response message since it
|
|
// may contain security sensitive data.
|
|
memset(pRespMsg, 0, respLen);
|
|
free(pRespMsg);
|
|
}
|
|
|
|
if (pSessionToken)
|
|
{
|
|
// Clear the memory before freeing up the token since it is
|
|
// security sensitive data.
|
|
memset(pSessionToken, 0, strlen(pSessionToken));
|
|
free(pSessionToken);
|
|
}
|
|
|
|
if (pGetAuthTokenResp)
|
|
RelGetAuthTokenResp(pGetAuthTokenResp);
|
|
|
|
if (pGetAuthPolicyResp)
|
|
RelGetAuthPolicyResp(pGetAuthPolicyResp);
|
|
|
|
if (pAuthPolicy)
|
|
RelAuthPolicy(pAuthPolicy);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Error building GetAuthPolicy msg\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
// Close the Rpc Session
|
|
CloseRpcSession(pRpcSession);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenFromServer- Error opening Rpc session\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
DbgTrace(1, "-ObtainAuthTokenFromServer- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus
|
|
ObtainAuthTokenInt(
|
|
IN const char *pServiceName,
|
|
IN const char *pHostName,
|
|
IN const void *pCredStoreScope,
|
|
INOUT char *pAuthTokenBuf,
|
|
INOUT int *pAuthTokenBufLen)
|
|
//
|
|
// Arguments:
|
|
// pServiceName -
|
|
// Pointer to NULL terminated string that contains the
|
|
// name of the service to which the client is trying to
|
|
// authenticate.
|
|
//
|
|
// pHostName -
|
|
// Pointer to NULL terminated string that contains the
|
|
// name of the host where resides the service to which the
|
|
// client is trying to authenticate. Note that the name
|
|
// can either be a DNS name or a dotted IP address.
|
|
//
|
|
// pCredStoreScope -
|
|
// Pointer to CASA structure for scoping credential store access
|
|
// to specific users. This can only be leveraged by applications
|
|
// running in the context of System.
|
|
//
|
|
// pAuthTokenBuf -
|
|
// Pointer to buffer that will receive the authentication
|
|
// token. The length of this buffer is specified by the
|
|
// pAuthTokenBufLen parameter. Note that the the authentication
|
|
// token will be in the form of a NULL terminated string.
|
|
//
|
|
// pAuthTokenBufLen -
|
|
// Pointer to integer that contains the length of the
|
|
// buffer pointed at by pAuthTokenBuf. Upon return of the
|
|
// function, the integer will contain the actual length
|
|
// of the authentication token if the function successfully
|
|
// completes or the buffer length required if the function
|
|
// fails because the buffer pointed at by pAuthTokenBuf is
|
|
// not large enough.
|
|
//
|
|
// Returns:
|
|
// Casa Status
|
|
//
|
|
// Description:
|
|
// Get authentication token to authenticate user to specified
|
|
// service at host. The user is scoped using the info associated
|
|
// with the magic cookie.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
|
AuthCacheEntry *pCacheEntry;
|
|
char *pNormalizedHostName;
|
|
char *pToken;
|
|
HANDLE hUserMutex = NULL;
|
|
|
|
DbgTrace(1, "-ObtainAuthTokenInt- Start\n", 0);
|
|
|
|
// Verify the input parameters
|
|
if (pServiceName == NULL
|
|
|| pHostName == NULL
|
|
|| pAuthTokenBufLen == NULL
|
|
|| (*pAuthTokenBufLen != 0 && pAuthTokenBuf == NULL))
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenInt- Invalid parameter\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INVALID_PARAMETER);
|
|
goto exit;
|
|
}
|
|
|
|
DbgTrace(1, "-ObtainAuthTokenInt- ServiceName = %s\n", pServiceName);
|
|
DbgTrace(1, "-ObtainAuthTokenInt- HostName = %s\n", pHostName);
|
|
DbgTrace(1, "-ObtainAuthTokenInt- BufferLength = %d\n", *pAuthTokenBufLen);
|
|
|
|
// Obtain our synchronization mutex
|
|
AcquireModuleMutex;
|
|
|
|
// Create user synchronization mutex
|
|
retStatus = CreateUserMutex(&hUserMutex);
|
|
if (retStatus != CASA_STATUS_SUCCESS)
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenInt- Error creating mutex for the user\n", 0);
|
|
goto exit;
|
|
}
|
|
|
|
// Make sure we are fully initialized
|
|
if (g_bInitialized == false)
|
|
{
|
|
retStatus = InitializeLibrary();
|
|
|
|
if (retStatus == CASA_STATUS_SUCCESS)
|
|
{
|
|
g_bInitialized = true;
|
|
}
|
|
else
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Release our synchronization mutex
|
|
ReleaseModuleMutex;
|
|
|
|
// Normalize the host name
|
|
pNormalizedHostName = NormalizeHostName(pHostName);
|
|
if (pNormalizedHostName)
|
|
{
|
|
bool setupHostEntries = true;
|
|
char *pHostNameAnd443 = NULL;
|
|
char *pHostNameAnd2645 = NULL;
|
|
char *pNormalizedHostNameAnd443 = NULL;
|
|
char *pNormalizedHostNameAnd2645 = NULL;
|
|
ATSHostEntry serviceHostEntry443 = {{NULL, NULL}, NULL, NULL, 0};
|
|
ATSHostEntry serviceHostEntry2645 = {{NULL, NULL}, NULL, NULL, 0};
|
|
ATSHostEntry serviceNormalizedHostEntry443 = {{NULL, NULL}, NULL, NULL, 0};
|
|
ATSHostEntry serviceNormalizedHostEntry2645 = {{NULL, NULL}, NULL, NULL, 0};
|
|
LIST_ENTRY *pListEntry;
|
|
ATSHostEntry *pHostEntryInUse;
|
|
|
|
// Start user process synchronization
|
|
AcquireUserMutex(hUserMutex);
|
|
|
|
// Determine if we should setup host entries for the
|
|
// host where the service resides.
|
|
pListEntry = g_ATSHostList.Flink;
|
|
while(pListEntry != &g_ATSHostList)
|
|
{
|
|
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);
|
|
|
|
// Check if we should also setup host entries using the service's
|
|
// normalized host name.
|
|
if (strcmp(pHostName, pNormalizedHostName) != 0)
|
|
{
|
|
// The host name given and the normalized name are different. Let's
|
|
// improve the odds by also trying to utilize the normalized name.
|
|
pNormalizedHostNameAnd443 = malloc(strlen(pNormalizedHostName) + 5);
|
|
pNormalizedHostNameAnd2645 = malloc(strlen(pNormalizedHostName) + 6);
|
|
if (pNormalizedHostNameAnd443 != NULL
|
|
&& pNormalizedHostNameAnd2645 != NULL)
|
|
{
|
|
sprintf(pNormalizedHostNameAnd443, "%s:%d", pNormalizedHostName, 443);
|
|
sprintf(pNormalizedHostNameAnd2645, "%s:%d", pNormalizedHostName, 2645);
|
|
|
|
serviceNormalizedHostEntry2645.pNameAndPort = pNormalizedHostNameAnd2645;
|
|
serviceNormalizedHostEntry2645.pName = pNormalizedHostName;
|
|
serviceNormalizedHostEntry2645.port = 2645;
|
|
InsertHeadList(&g_ATSHostList, &serviceNormalizedHostEntry2645.listEntry);
|
|
|
|
serviceNormalizedHostEntry443.pNameAndPort = pNormalizedHostNameAnd443;
|
|
serviceNormalizedHostEntry443.pName = pNormalizedHostName;
|
|
serviceNormalizedHostEntry443.port = 443;
|
|
InsertHeadList(&g_ATSHostList, &serviceNormalizedHostEntry443.listEntry);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenInt- Buffer allocation failure\n", 0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenInt- Buffer allocation failure\n", 0);
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
DWORD opStartTime = GetTickCount();
|
|
|
|
// 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);
|
|
|
|
// Retry if not successful and if advised to do so
|
|
if (!CASA_SUCCESS(retStatus)
|
|
&& advisedToRetry)
|
|
{
|
|
retStatus = ObtainAuthTokenFromServer(pServiceName,
|
|
pHostName,
|
|
pNormalizedHostName,
|
|
pHostEntryInUse,
|
|
pCredStoreScope,
|
|
&pToken,
|
|
&cacheEntryLifetime,
|
|
&advisedToRetry);
|
|
}
|
|
|
|
// Try to add the entry to the cache if we did not fail due
|
|
// to authentication failure.
|
|
if (CasaStatusCode(retStatus) != CASA_STATUS_AUTHENTICATION_FAILURE)
|
|
{
|
|
DWORD opEndTime = GetTickCount();
|
|
|
|
// We only want to cache bad results if the operation took a
|
|
// considerable amount of time.
|
|
if (CASA_SUCCESS(retStatus)
|
|
|| opEndTime >= (opStartTime + (BAD_CACHE_TRIGER_TIME * 1000)))
|
|
{
|
|
pCacheEntry = CreateAuthTokenCacheEntry(pServiceName,
|
|
pNormalizedHostName,
|
|
pHostEntryInUse,
|
|
retStatus,
|
|
pToken,
|
|
cacheEntryLifetime,
|
|
pCredStoreScope);
|
|
if (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);
|
|
}
|
|
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 (pHostNameAnd443 != NULL
|
|
&& pHostNameAnd2645 != NULL)
|
|
{
|
|
RemoveEntryList(&serviceHostEntry2645.listEntry);
|
|
RemoveEntryList(&serviceHostEntry443.listEntry);
|
|
|
|
if (pNormalizedHostNameAnd443 != NULL
|
|
&& pNormalizedHostNameAnd2645 != NULL)
|
|
{
|
|
RemoveEntryList(&serviceNormalizedHostEntry2645.listEntry);
|
|
RemoveEntryList(&serviceNormalizedHostEntry443.listEntry);
|
|
}
|
|
}
|
|
|
|
// Stop user process synchronization
|
|
ReleaseUserMutex(hUserMutex);
|
|
|
|
// Free the space allocated during processing of the request
|
|
if (pHostNameAnd443)
|
|
free(pHostNameAnd443);
|
|
|
|
if (pHostNameAnd2645)
|
|
free(pHostNameAnd2645);
|
|
|
|
if (pNormalizedHostNameAnd443)
|
|
free(pNormalizedHostNameAnd443);
|
|
|
|
if (pNormalizedHostNameAnd2645)
|
|
free(pNormalizedHostNameAnd2645);
|
|
|
|
free(pNormalizedHostName);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-ObtainAuthTokenInt- Host name normalization failed\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_NAME_RESOLVE_ERROR);
|
|
}
|
|
|
|
exit:
|
|
|
|
if (hUserMutex != NULL)
|
|
{
|
|
DestroyUserMutex(hUserMutex);
|
|
}
|
|
DbgTrace(1, "-ObtainAuthTokenInt- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus SSCS_CALL
|
|
ObtainAuthToken(
|
|
IN const char *pServiceName,
|
|
IN const char *pHostName,
|
|
INOUT char *pAuthTokenBuf,
|
|
INOUT int *pAuthTokenBufLen)
|
|
//
|
|
// Arguments:
|
|
// pServiceName -
|
|
// Pointer to NULL terminated string that contains the
|
|
// name of the service to which the client is trying to
|
|
// authenticate.
|
|
//
|
|
// pHostName -
|
|
// Pointer to NULL terminated string that contains the
|
|
// name of the host where resides the service to which the
|
|
// client is trying to authenticate. Note that the name
|
|
// can either be a DNS name or a dotted IP address.
|
|
//
|
|
// pAuthTokenBuf -
|
|
// Pointer to buffer that will receive the authentication
|
|
// token. The length of this buffer is specified by the
|
|
// pAuthTokenBufLen parameter. Note that the the authentication
|
|
// token will be in the form of a NULL terminated string.
|
|
//
|
|
// pAuthTokenBufLen -
|
|
// Pointer to integer that contains the length of the
|
|
// buffer pointed at by pAuthTokenBuf. Upon return of the
|
|
// function, the integer will contain the actual length
|
|
// of the authentication token if the function successfully
|
|
// completes or the buffer length required if the function
|
|
// fails because the buffer pointed at by pAuthTokenBuf is
|
|
// not large enough.
|
|
//
|
|
// Returns:
|
|
// Casa Status
|
|
//
|
|
// Description:
|
|
// Get authentication token to authenticate user to specified
|
|
// service at host.
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
|
|
DbgTrace(1, "-ObtainAuthToken- Start\n", 0);
|
|
|
|
// Call our internal worker
|
|
retStatus = ObtainAuthTokenInt(pServiceName,
|
|
pHostName,
|
|
NULL,
|
|
pAuthTokenBuf,
|
|
pAuthTokenBufLen);
|
|
|
|
DbgTrace(1, "-ObtainAuthToken- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void
|
|
CleanUpAuthTokenCacheInt(
|
|
IN const void *pCredStoreScope)
|
|
//
|
|
// Arguments:
|
|
// pCredStoreScope -
|
|
// Pointer to CASA structure for scoping credential store access
|
|
// to specific users. This can only be leveraged by applications
|
|
// running in the context of System.
|
|
//
|
|
// Returns:
|
|
// Nothing
|
|
//
|
|
// Description:
|
|
// Flush the AuthToken cache.
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
HANDLE hUserMutex = NULL;
|
|
|
|
DbgTrace(1, "-CleanUpAuthTokenCacheInt- Start\n", 0);
|
|
|
|
// Obtain our synchronization mutex
|
|
AcquireModuleMutex;
|
|
|
|
// Create user synchronization mutex
|
|
retStatus = CreateUserMutex(&hUserMutex);
|
|
if (retStatus != CASA_STATUS_SUCCESS)
|
|
{
|
|
DbgTrace(0, "-CleanUpAuthTokenCacheInt- Error creating mutex for the user\n", 0);
|
|
goto exit;
|
|
}
|
|
|
|
// Make sure we are fully initialized
|
|
if (g_bInitialized == false)
|
|
{
|
|
retStatus = InitializeLibrary();
|
|
|
|
if (retStatus == CASA_STATUS_SUCCESS)
|
|
{
|
|
g_bInitialized = true;
|
|
}
|
|
else
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Release our synchronization mutex
|
|
ReleaseModuleMutex;
|
|
|
|
// Start user process synchronization
|
|
AcquireUserMutex(hUserMutex);
|
|
|
|
// Delete all of the tokens in our cache
|
|
DeleteAuthTokenEntriesInCache(pCredStoreScope);
|
|
DeleteSessionTokenEntriesInCache(pCredStoreScope);
|
|
|
|
// Stop user process synchronization
|
|
ReleaseUserMutex(hUserMutex);
|
|
|
|
exit:
|
|
|
|
if (hUserMutex != NULL)
|
|
{
|
|
DestroyUserMutex(hUserMutex);
|
|
}
|
|
|
|
DbgTrace(1, "-CleanUpAuthTokenCacheInt- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void SSCS_CALL
|
|
CleanUpAuthTokenCache(void)
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns:
|
|
// Nothing
|
|
//
|
|
// Description:
|
|
// Flush the AuthToken cache.
|
|
//=======================================================================--
|
|
{
|
|
DbgTrace(1, "-CleanUpAuthTokenCache- Start\n", 0);
|
|
|
|
// Call our internal worker
|
|
CleanUpAuthTokenCacheInt(NULL);
|
|
|
|
DbgTrace(1, "-CleanUpAuthTokenCache- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void
|
|
CreateATSHostEntry(
|
|
IN const char *pHostName,
|
|
IN uint16_t port)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
ATSHostEntry *pHostEntry;
|
|
|
|
DbgTrace(1, "-CreateATSHostEntry- Start\n", 0);
|
|
|
|
// Create host entry
|
|
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)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int retStatus = -1;
|
|
int getConfigStatus = -1;
|
|
ConfigIf *pClientConfigIf;
|
|
char *pDebugLevelSetting;
|
|
char *pDebugLogFolderPathSetting;
|
|
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",
|
|
&pClientConfigIf);
|
|
if (CASA_SUCCESS(getConfigStatus)
|
|
&& CasaStatusCode(getConfigStatus) != CASA_STATUS_OBJECT_NOT_FOUND)
|
|
{
|
|
// Check if a DebugLevel has been configured
|
|
pDebugLevelSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "DebugLevel");
|
|
if (pDebugLevelSetting != NULL)
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- DebugLevel configured = %s\n", pDebugLevelSetting);
|
|
|
|
// Convert the number to hex
|
|
DebugLevel = (int) dtoul(pDebugLevelSetting, strlen(pDebugLevelSetting));
|
|
|
|
// Free the buffer holding the debug level
|
|
pClientConfigIf->freeValueString(pClientConfigIf, pDebugLevelSetting);
|
|
}
|
|
|
|
// Check if a DebugLogFolderPath has been configured
|
|
pDebugLogFolderPathSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "DebugLogFolderPath");
|
|
if (pDebugLogFolderPathSetting != NULL)
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- DebugLogFolderPath configured = %s\n", pDebugLogFolderPathSetting);
|
|
|
|
// Use the setting to come up with the path to the debug log file
|
|
g_pDebugLogFilePath = malloc(strlen(LOG_FILE_NAME) + strlen(pDebugLogFolderPathSetting) + 1);
|
|
if (g_pDebugLogFilePath)
|
|
{
|
|
strcpy(g_pDebugLogFilePath, pDebugLogFolderPathSetting);
|
|
strcat(g_pDebugLogFilePath, LOG_FILE_NAME);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- Failed to allocate buffer for debug file path\n", 0);
|
|
}
|
|
|
|
// Free the buffer holding the debug folder path
|
|
pClientConfigIf->freeValueString(pClientConfigIf, pDebugLogFolderPathSetting);
|
|
}
|
|
|
|
// Check if an ATS Host List has been configured
|
|
pATSHostListSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATSHostList");
|
|
if (pATSHostListSetting != NULL)
|
|
{
|
|
char *pSavePtr;
|
|
char *pHostAndPort;
|
|
|
|
DbgTrace(0, "-InitializeLibrary- ATSHostList configured = %s\n", pATSHostListSetting);
|
|
|
|
// Go through all configured host addresses
|
|
pHostAndPort = strtok_r(pATSHostListSetting, ";", &pSavePtr);
|
|
while (pHostAndPort != NULL)
|
|
{
|
|
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 list setting
|
|
pClientConfigIf->freeValueString(pClientConfigIf, pATSHostListSetting);
|
|
}
|
|
|
|
// Check if the DisableSecureConnections setting has been configured
|
|
pDisableSecureConnections = pClientConfigIf->getEntryValue(pClientConfigIf, "DisableSecureConnections");
|
|
if (pDisableSecureConnections != NULL)
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- DisableSecureConnections setting configured = %s\n", pDisableSecureConnections);
|
|
|
|
// Adjust the g_rpcFlags variable based on the setting
|
|
if (stricmp(pDisableSecureConnections, "true") == 0)
|
|
{
|
|
g_rpcFlags &= ~SECURE_RPC_FLAG;
|
|
}
|
|
else if (stricmp(pDisableSecureConnections, "false") == 0)
|
|
{
|
|
g_rpcFlags |= SECURE_RPC_FLAG;
|
|
}
|
|
|
|
// Free the buffer holding the DisableSecureConnections setting
|
|
pClientConfigIf->freeValueString(pClientConfigIf, pDisableSecureConnections);
|
|
}
|
|
|
|
// Check the AllowUntrustedCerts setting if using secure connections
|
|
if (g_rpcFlags & SECURE_RPC_FLAG)
|
|
{
|
|
// Check if the AllowUntrustedCerts setting has been configured
|
|
pAllowInvalidCerts = pClientConfigIf->getEntryValue(pClientConfigIf, "AllowUntrustedCerts");
|
|
if (pAllowInvalidCerts != NULL)
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- AllowUntrustedCerts setting configured = %s\n", pAllowInvalidCerts);
|
|
|
|
// Adjust the g_rpcFlags variable based on the setting
|
|
if (stricmp(pAllowInvalidCerts, "false") == 0)
|
|
{
|
|
g_rpcFlags &= ~ALLOW_INVALID_CERTS_RPC_FLAG;
|
|
}
|
|
else if (stricmp(pAllowInvalidCerts, "true") == 0)
|
|
{
|
|
g_rpcFlags |= ALLOW_INVALID_CERTS_RPC_FLAG;
|
|
}
|
|
|
|
// Free the buffer holding the AllowInvalidCerts setting
|
|
pClientConfigIf->freeValueString(pClientConfigIf, pAllowInvalidCerts);
|
|
}
|
|
|
|
// Check the UsersCannotAllowInvalidCerts setting if not allowing invalid certs.
|
|
if ((g_rpcFlags & ALLOW_INVALID_CERTS_RPC_FLAG) == 0)
|
|
{
|
|
// Check if the UsersCannotAllowInvalidCerts setting has been configured
|
|
pUsersCannotAllowInvalidCerts = pClientConfigIf->getEntryValue(pClientConfigIf, "UsersCannotAllowInvalidCerts");
|
|
if (pUsersCannotAllowInvalidCerts != NULL)
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- UsersCannotAllowInvalidCerts setting configured = %s\n", pUsersCannotAllowInvalidCerts);
|
|
|
|
// Adjust the g_rpcFlags variable based on the setting
|
|
if (stricmp(pUsersCannotAllowInvalidCerts, "false") == 0)
|
|
{
|
|
g_rpcFlags |= ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
|
}
|
|
else if (stricmp(pUsersCannotAllowInvalidCerts, "true") == 0)
|
|
{
|
|
g_rpcFlags &= ~ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG;
|
|
}
|
|
|
|
// Free the buffer holding the UsersCannotAllowInvalidCerts setting
|
|
pClientConfigIf->freeValueString(pClientConfigIf, pUsersCannotAllowInvalidCerts);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Release config interface instance
|
|
pClientConfigIf->releaseReference(pClientConfigIf);
|
|
}
|
|
|
|
// Initialize the host name normalization
|
|
retStatus = InitializeHostNameNormalization();
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Initialize the auth cache
|
|
retStatus = InitializeAuthCache();
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
retStatus = InitializeRpc();
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- Auth cache intialization failed\n", 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-InitializeLibrary- HostName Normalizer intialization failed\n", 0);
|
|
}
|
|
|
|
DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void
|
|
UnInitializeLibrary(void)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
LIST_ENTRY *pListEntry;
|
|
ATSHostEntry *pHostEntry;
|
|
|
|
DbgTrace(1, "-UnInitializeLibrary- Start\n", 0);
|
|
|
|
// Un-initialize the host name normalization
|
|
UnInitializeHostNameNormalization();
|
|
|
|
// Un-initialize the auth cache
|
|
UnInitializeAuthCache();
|
|
|
|
// Un-initialize the Rpc engine
|
|
UnInitializeRpc();
|
|
|
|
// Free necessary buffers
|
|
if (g_pDebugLogFilePath)
|
|
{
|
|
char *pBuffer = g_pDebugLogFilePath;
|
|
g_pDebugLogFilePath = NULL;
|
|
free(pBuffer);
|
|
}
|
|
|
|
pListEntry = g_ATSHostList.Flink;
|
|
if (pListEntry)
|
|
{
|
|
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);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|