Updates resulting from self-code review.

This commit is contained in:
Juan Carlos Luciani 2006-12-01 12:42:52 +00:00
parent 74dce09720
commit d55ac482ac
7 changed files with 734 additions and 669 deletions

View File

@ -193,7 +193,10 @@ ObtainSessionToken(
// Free resources that may be hanging around
if (pRespMsg)
free(pRespMsg);
// Clear and free the memory associated with the request message since
// it may contain sensitive information.
memset(pReqMsg, 0, strlen(pReqMsg));
free(pReqMsg);
}
else
@ -223,6 +226,8 @@ ObtainSessionToken(
}
// 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

View File

@ -101,7 +101,6 @@ AuthTokenIf_GetAuthToken(
TimeStamp expiry;
CredHandle hCredentials = {0};
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0);
// Validate input parameters
@ -211,7 +210,9 @@ AuthTokenIf_GetAuthToken(
// Return the actual size or the size required
*pTokenBufLen = encodedTokenLen;
// Free the buffer containing the encoded token
// Free the buffer containing the encoded token after clearing
// its memory to avoid leaking sensitive information.
memset(pEncodedToken, 0, strlen(pEncodedToken));
free(pEncodedToken);
}
@ -229,7 +230,10 @@ AuthTokenIf_GetAuthToken(
// Free any buffer associated with the sendToken
if (sendTok.pvBuffer)
{
memset(sendTok.pvBuffer, 0, sendTok.cbBuffer);
FreeContextBuffer(sendTok.pvBuffer);
}
// Free the credential handle obtained
FreeCredentialsHandle(&hCredentials);

View File

@ -1,362 +1,371 @@
/***********************************************************************
*
* 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 ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//++=======================================================================
static
CasaStatus
GetUserCredentials(
IN const char *pRealm,
/***********************************************************************
*
* 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 ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//++=======================================================================
static
CasaStatus
GetUserCredentials(
IN const char *pRealm,
IN void *pCredStoreScope,
INOUT char **ppUsername,
INOUT char **ppPassword)
//
// Arguments:
// pRealm -
// The realm to which the credentials apply.
//
// pCredStoreScope -
// Pointer to CASA structure for scoping credential store access
// to specific users. This can only be leveraged when running in
// the context of System under Windows.
//
// ppUsername -
// Pointer to variable that will receive buffer with the username.
//
// ppPassword -
// Pointer to variable that will receive buffer with the password.
//
// Returns:
// Casa Status
//
// Description:
// Get authentication credentials for the specified realm.
//
// L2
//=======================================================================--
{
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_UNSUCCESSFUL);
char *pUsername;
char *pPassword;
int rcode = NSSCS_E_OBJECT_NOT_FOUND;
uint32_t credtype = SSCS_CRED_TYPE_BASIC_F;
SSCS_BASIC_CREDENTIAL credential = {0};
SSCS_SECRET_ID_T secretId = {0};
DbgTrace(1, "-GetUserCredentials- Start\n", 0);
// Initialize output parameters
*ppUsername = NULL;
*ppPassword = NULL;
// Get the length of the realm string into the secret id structure
// and verify thatr it is not too long.
secretId.len = sscs_Utf8Strlen(pRealm) + 1;
if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN)
{
// Set the secret id in the structure
sscs_Utf8Strcpy((char*) secretId.id, pRealm);
// Specify that we want the common name
credential.unFlags = USERNAME_TYPE_CN_F;
// Now try to get the credentials
rcode = miCASAGetCredential(0,
&secretId,
NULL,
&credtype,
&credential,
(SSCS_EXT_T*) pCredStoreScope);
if (rcode != NSSCS_SUCCESS)
{
// There were no credentials for the realm, now try to obtain the
// desktop credentials.
secretId.len = sscs_Utf8Strlen("Desktop") + 1;
if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN)
{
sscs_Utf8Strcpy((char*) secretId.id, "Desktop");
rcode = miCASAGetCredential(0,
&secretId,
NULL,
&credtype,
&credential,
(SSCS_EXT_T*) pCredStoreScope);
}
else
{
DbgTrace(0, "-GetUserCredentials- Desktop name too long\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
}
else
{
DbgTrace(0, "-GetUserCredentials- Realm name too long\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
// Proceed based on the result of the operatiosn above
if (rcode == NSSCS_SUCCESS
&& credential.username != NULL
&& credential.password != NULL)
{
// Allocate a buffer to return the username
pUsername = (char*) malloc(strlen((char*) credential.username) + 1);
if (pUsername)
{
// Copy the username into the buffer that we will be returning
strcpy(pUsername, (char*) credential.username);
// Allocate a buffer to return the password
pPassword = (char*) malloc(strlen((char*) credential.password) + 1);
if (pPassword)
{
// Copy the password into the buffer that we will be returning
strcpy(pPassword, (char*) credential.password);
DbgTrace(1, "-GetUserCredentials- Username = %s\n", pUsername);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
else
{
DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
// Free the buffer allocated for the username
free(pUsername);
}
}
else
{
DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
else
{
DbgTrace(0, "-GetUserCredentials- Failed to obtain credentials for pw authentication\n", 0);
}
// Return the buffers to the caller if successful
if (CASA_SUCCESS(retStatus))
{
*ppUsername = pUsername;
*ppPassword = pPassword;
}
DbgTrace(1, "-GetUserCredentials- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
CasaStatus SSCS_CALL
AuthTokenIf_GetAuthToken(
IN const void *pIfInstance,
IN const char *pContext,
IN const char *pMechInfo,
IN const char *pHostName,
INOUT char **ppUsername,
INOUT char **ppPassword)
//
// Arguments:
// pRealm -
// The realm to which the credentials apply.
//
// pCredStoreScope -
// Pointer to CASA structure for scoping credential store access
// to specific users. This can only be leveraged when running in
// the context of System under Windows.
//
// ppUsername -
// Pointer to variable that will receive buffer with the username.
//
// ppPassword -
// Pointer to variable that will receive buffer with the password.
//
// Returns:
// Casa Status
//
// Description:
// Get authentication credentials for the specified realm.
//
// L2
//=======================================================================--
{
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_UNSUCCESSFUL);
char *pUsername;
char *pPassword;
int rcode = NSSCS_E_OBJECT_NOT_FOUND;
uint32_t credtype = SSCS_CRED_TYPE_BASIC_F;
SSCS_BASIC_CREDENTIAL credential = {0};
SSCS_SECRET_ID_T secretId = {0};
DbgTrace(1, "-GetUserCredentials- Start\n", 0);
// Initialize output parameters
*ppUsername = NULL;
*ppPassword = NULL;
// Get the length of the realm string into the secret id structure
// and verify thatr it is not too long.
secretId.len = sscs_Utf8Strlen(pRealm) + 1;
if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN)
{
// Set the secret id in the structure
sscs_Utf8Strcpy((char*) secretId.id, pRealm);
// Specify that we want the common name
credential.unFlags = USERNAME_TYPE_CN_F;
// Now try to get the credentials
rcode = miCASAGetCredential(0,
&secretId,
NULL,
&credtype,
&credential,
(SSCS_EXT_T*) pCredStoreScope);
if (rcode != NSSCS_SUCCESS)
{
// There were no credentials for the realm, now try to obtain the
// desktop credentials.
secretId.len = sscs_Utf8Strlen("Desktop") + 1;
if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN)
{
sscs_Utf8Strcpy((char*) secretId.id, "Desktop");
rcode = miCASAGetCredential(0,
&secretId,
NULL,
&credtype,
&credential,
(SSCS_EXT_T*) pCredStoreScope);
}
else
{
DbgTrace(0, "-GetUserCredentials- Desktop name too long\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
}
else
{
DbgTrace(0, "-GetUserCredentials- Realm name too long\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
// Proceed based on the result of the operatiosn above
if (rcode == NSSCS_SUCCESS
&& credential.username != NULL
&& credential.password != NULL)
{
// Allocate a buffer to return the username
pUsername = (char*) malloc(strlen((char*) credential.username) + 1);
if (pUsername)
{
// Copy the username into the buffer that we will be returning
strcpy(pUsername, (char*) credential.username);
// Allocate a buffer to return the password
pPassword = (char*) malloc(strlen((char*) credential.password) + 1);
if (pPassword)
{
// Copy the password into the buffer that we will be returning
strcpy(pPassword, (char*) credential.password);
DbgTrace(1, "-GetUserCredentials- Username = %s\n", pUsername);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
else
{
DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
// Free the buffer allocated for the username
free(pUsername);
}
}
else
{
DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
else
{
DbgTrace(0, "-GetUserCredentials- Failed to obtain credentials for pw authentication\n", 0);
}
// Clear out the credential structure to make sure that we are not leaving sensitive
// information on the stack.
memset(&credential, 0, sizeof(credential));
// Return the buffers to the caller if successful
if (CASA_SUCCESS(retStatus))
{
*ppUsername = pUsername;
*ppPassword = pPassword;
}
DbgTrace(1, "-GetUserCredentials- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
CasaStatus SSCS_CALL
AuthTokenIf_GetAuthToken(
IN const void *pIfInstance,
IN const char *pContext,
IN const char *pMechInfo,
IN const char *pHostName,
IN void *pCredStoreScope,
INOUT char *pTokenBuf,
INOUT int *pTokenBufLen)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// pContext -
// Pointer to null terminated string containing mechanism specific
// context information. Another name for context is Authentication
// Realm.
//
// pMechInfo -
// Pointer to null terminated string containing mechanism specific
// information. This is information is provided by the server to
// aid the mechanism to generate an authentication token. For
// example, the mechanism information for a Kerberos mechanism
// may be the service principal name to which the user will be
// authenticating.
//
// pHostName -
// Pointer to null terminated string containing the name of the
// host where the ATS resides.
//
// pCredStoreScope -
// Pointer to CASA structure for scoping credential store access
// to specific users. This can only be leveraged when running in
// the context of System under Windows.
//
// pTokenBuf -
// Pointer to buffer that will receive the authentication
// token. The length of this buffer is specified by the
// pTokenBufLen parameter. Note that the the authentication
// token will be in the form of a NULL terminated string.
//
// pTokenBufLen -
// Pointer to integer that contains the length of the
// buffer pointed at by pTokenBuf. 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 pUserNameBuf is
// not large enough.
//
// Returns:
// Casa Status
//
// Description:
// Get authentication token to authenticate user to specified service.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
char *pUsername = NULL;
char *pPassword = NULL;
char *pToken;
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0);
// Validate input parameters
if (pIfInstance == NULL
|| pContext == NULL
|| pHostName == NULL
|| pTokenBufLen == NULL
|| (pTokenBuf == NULL && *pTokenBufLen != 0))
{
DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INVALID_PARAMETER);
goto exit;
}
// Get the user credentials
retStatus = GetUserCredentials(pContext,
pCredStoreScope,
&pUsername,
&pPassword);
if (CASA_SUCCESS(retStatus))
{
// Now construct the PW token with the following format:
// "username\r\n" + "password\r\n"
//
// First allocate a buffer large enough to hold the token
pToken = (char*) malloc(strlen(pUsername) + 2 + strlen(pPassword) + 2 + 1);
if (pToken)
{
char *pEncodedToken;
int encodedTokenLen;
// Now assemble the token
sprintf(pToken, "%s\r\n%s\r\n", pUsername, pPassword);
// The token has been assembled, now encode it.
retStatus = EncodeData(pToken,
(const int) strlen(pToken),
&pEncodedToken,
&encodedTokenLen);
if (CASA_SUCCESS(retStatus))
{
// Verify that the caller provided a buffer that is big enough
if (encodedTokenLen > *pTokenBufLen)
{
// The buffer is not big enough
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
else
{
// The buffer provided is large enough, copy the data.
memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
// Return the actual size or the size required
*pTokenBufLen = encodedTokenLen;
// Free the buffer containing the encoded token
free(pEncodedToken);
}
// Free the buffer allocated for the token
free(pToken);
}
else
{
DbgTrace(0, "-AuthTokenIf_GetAuthToken- Buffer allocation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
// Free allocated buffers
free(pUsername);
free(pPassword);
}
else
{
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the user credentials\n", 0);
}
exit:
DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================
INOUT char *pTokenBuf,
INOUT int *pTokenBufLen)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// pContext -
// Pointer to null terminated string containing mechanism specific
// context information. Another name for context is Authentication
// Realm.
//
// pMechInfo -
// Pointer to null terminated string containing mechanism specific
// information. This is information is provided by the server to
// aid the mechanism to generate an authentication token. For
// example, the mechanism information for a Kerberos mechanism
// may be the service principal name to which the user will be
// authenticating.
//
// pHostName -
// Pointer to null terminated string containing the name of the
// host where the ATS resides.
//
// pCredStoreScope -
// Pointer to CASA structure for scoping credential store access
// to specific users. This can only be leveraged when running in
// the context of System under Windows.
//
// pTokenBuf -
// Pointer to buffer that will receive the authentication
// token. The length of this buffer is specified by the
// pTokenBufLen parameter. Note that the the authentication
// token will be in the form of a NULL terminated string.
//
// pTokenBufLen -
// Pointer to integer that contains the length of the
// buffer pointed at by pTokenBuf. 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 pUserNameBuf is
// not large enough.
//
// Returns:
// Casa Status
//
// Description:
// Get authentication token to authenticate user to specified service.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
char *pUsername = NULL;
char *pPassword = NULL;
char *pToken;
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0);
// Validate input parameters
if (pIfInstance == NULL
|| pContext == NULL
|| pHostName == NULL
|| pTokenBufLen == NULL
|| (pTokenBuf == NULL && *pTokenBufLen != 0))
{
DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INVALID_PARAMETER);
goto exit;
}
// Get the user credentials
retStatus = GetUserCredentials(pContext,
pCredStoreScope,
&pUsername,
&pPassword);
if (CASA_SUCCESS(retStatus))
{
// Now construct the PW token with the following format:
// "username\r\n" + "password\r\n"
//
// First allocate a buffer large enough to hold the token
pToken = (char*) malloc(strlen(pUsername) + 2 + strlen(pPassword) + 2 + 1);
if (pToken)
{
char *pEncodedToken;
int encodedTokenLen;
// Now assemble the token
sprintf(pToken, "%s\r\n%s\r\n", pUsername, pPassword);
// The token has been assembled, now encode it.
retStatus = EncodeData(pToken,
(const int) strlen(pToken),
&pEncodedToken,
&encodedTokenLen);
if (CASA_SUCCESS(retStatus))
{
// Verify that the caller provided a buffer that is big enough
if (encodedTokenLen > *pTokenBufLen)
{
// The buffer is not big enough
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
else
{
// The buffer provided is large enough, copy the data.
memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
// Return the actual size or the size required
*pTokenBufLen = encodedTokenLen;
// Free the buffer containing the encoded token after clearing
// it to avoid leaking sensitive information.
memset(pEncodedToken, 0, strlen(pEncodedToken));
free(pEncodedToken);
}
// Free the buffer allocated for the token after clearing it
// to avoid leaving sensitive information behind.
memset(pToken, 0, strlen(pToken));
free(pToken);
}
else
{
DbgTrace(0, "-AuthTokenIf_GetAuthToken- Buffer allocation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_PWTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
// Free allocated buffers after clearing memory holding the password
free(pUsername);
memset(pPassword, 0, strlen(pPassword));
free(pPassword);
}
else
{
DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the user credentials\n", 0);
}
exit:
DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -28,5 +28,5 @@ LibraryName \Program Files\novell\casa\lib\pwmech.dll
# tools such as DbgView. Under Linux, debug statements are logged
# to /var/log/messages.
#
#DebugLevel 0
#DebugLevel 0

View File

@ -128,7 +128,7 @@ BOOL APIENTRY DllMain(
//=======================================================================--
{
BOOL retStatus = TRUE;
char programFilesFolder[MAX_PATH];
char programFilesFolder[MAX_PATH] = {0};
switch (ul_reason_for_call)
{

View File

@ -54,12 +54,12 @@ static
HANDLE hNormalizedHostNameCacheMutex;
// Client configuration file folder
char clientConfigFolder[MAX_PATH];
char clientConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth";
char clientConfigFolder[MAX_PATH + sizeof(clientConfigFolderPartialPath)];
// Authentication mechanism configuration file folder
char mechConfigFolder[MAX_PATH];
char mechConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth\\Mechanisms";
char mechConfigFolder[MAX_PATH + sizeof(mechConfigFolderPartialPath)];
// Path separator
char pathCharString[] = "\\";
@ -81,6 +81,8 @@ CreateUserMutex(
// L2
//=======================================================================--
{
#define USER_MUTEX_NAME_FMT_STRING "Global\\CASA_Auth_Mutex_%s"
CasaStatus retStatus = CASA_STATUS_SUCCESS;
char *pUsername = NULL;
DWORD nameLength = 0;
@ -99,32 +101,47 @@ CreateUserMutex(
if (GetUserName(pUsername, &nameLength))
{
SECURITY_ATTRIBUTES mutexAttributes;
char mutexName[256];
char *pMutexName;
// Now lets create a global semaphore for the
// user and allow its handle to be inherited.
mutexAttributes.nLength = sizeof(mutexAttributes);
mutexAttributes.lpSecurityDescriptor = NULL;
mutexAttributes.bInheritHandle = TRUE;
if (sprintf(mutexName, "Global\\CASA_Auth_Mutex_%s", pUsername) != -1)
// Allocate a buffer to hold the mutex name
pMutexName = (char*) malloc(sizeof(USER_MUTEX_NAME_FMT_STRING) + nameLength);
if (pMutexName)
{
*phMutex = CreateMutex(&mutexAttributes,
FALSE,
mutexName);
if (*phMutex == NULL)
// Now lets create a global semaphore for the
// user and allow its handle to be inherited.
mutexAttributes.nLength = sizeof(mutexAttributes);
mutexAttributes.lpSecurityDescriptor = NULL;
mutexAttributes.bInheritHandle = TRUE;
if (sprintf(pMutexName, USER_MUTEX_NAME_FMT_STRING, pUsername) != -1)
{
DbgTrace(0, "-CreateUserMutex- CreateMutex failed, error = %d\n", GetLastError());
*phMutex = CreateMutex(&mutexAttributes,
FALSE,
pMutexName);
if (*phMutex == NULL)
{
DbgTrace(0, "-CreateUserMutex- CreateMutex failed, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
else
{
DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
// Free the buffer used to hold the user mutex name
free(pMutexName);
}
else
{
DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError());
DbgTrace(0, "-CreateUserMutex- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
else
@ -415,53 +432,65 @@ NormalizeHostName(
// Now try to resolve the normalized name
pLookupResult = gethostbyname(pHostName);
if (pLookupResult && pLookupResult->h_addrtype == AF_INET)
if (pLookupResult
&& pLookupResult->h_addrtype == AF_INET
&& pLookupResult->h_length > 0
&& pLookupResult->h_addr_list[0] != NULL)
{
char dnsHostName[NI_MAXHOST];
// Set up a sockaddr structure
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]);
// Now try to resolve the name using DNS
if (getnameinfo((const struct sockaddr*) &sockAddr,
sizeof(sockAddr),
dnsHostName,
sizeof(dnsHostName),
NULL,
0,
NI_NAMEREQD) == 0)
char *pDnsHostName = (char*) malloc(NI_MAXHOST + 1);
if (pDnsHostName)
{
// We resolved the address to a DNS name, use it as the normalized name.
pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1;
pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired);
if (pEntry->pNormalizedHostName)
// Set up a sockaddr structure
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]);
// Now try to resolve the name using DNS
if (getnameinfo((const struct sockaddr*) &sockAddr,
sizeof(sockAddr),
pDnsHostName,
NI_MAXHOST,
NULL,
0,
NI_NAMEREQD) == 0)
{
// Copy the dns name
strcpy(pEntry->pNormalizedHostName, dnsHostName);
// We resolved the address to a DNS name, use it as the normalized name.
pEntry->buffLengthRequired = (int) strlen(pDnsHostName) + 1;
pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired);
if (pEntry->pNormalizedHostName)
{
// Copy the dns name
strcpy(pEntry->pNormalizedHostName, pDnsHostName);
}
else
{
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
}
}
else
{
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError());
// Not able to resolve the name in DNS, just use the host name as
// the normalized name.
pEntry->buffLengthRequired = (int) strlen(pHostName) + 1;
pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired);
if (pEntry->pNormalizedHostName)
{
// Copy the host name
strcpy(pEntry->pNormalizedHostName, pHostName);
}
else
{
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
}
}
// Free the buffer allocated to hold the DNS name
free(pDnsHostName);
}
else
{
DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError());
// Not able to resolve the name in DNS, just use the host name as
// the normalized name.
pEntry->buffLengthRequired = (int) strlen(pHostName) + 1;
pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired);
if (pEntry->pNormalizedHostName)
{
// Copy the host name
strcpy(pEntry->pNormalizedHostName, pHostName);
}
else
{
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
}
DbgTrace(0, "-NormalizeHostName- Buffer allocation failure\n", 0);
}
}
else

View File

@ -356,10 +356,14 @@ InternalRpc(
// L2
//=======================================================================--
{
#define RPC_TARGET_FMT_STRING "CasaAuthTokenSvc/Rpc?method=%s"
#ifndef CASA_STATUS_INVALID_SERVER_CERTIFICATE
#define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated
#endif
CasaStatus retStatus = CASA_STATUS_SUCCESS;
char rpcTarget[256];
char *pRpcTarget;
LPWSTR pWideRpcTarget;
int wideRpcTargetLen;
WCHAR sendHeaders[] = L"Content-Type: text/html";
@ -373,173 +377,184 @@ InternalRpc(
*ppResponseData = NULL;
// Create rpc target string and convert it to a wide string
sprintf(rpcTarget, "CasaAuthTokenSvc/Rpc?method=%s", pMethod);
retStatus = CopyMultiToWideAlloc(rpcTarget,
(int) strlen(rpcTarget),
&pWideRpcTarget,
&wideRpcTargetLen);
if (CASA_SUCCESS(retStatus))
pRpcTarget = (char*) malloc(sizeof(RPC_TARGET_FMT_STRING) + strlen(pMethod));
if (pRpcTarget)
{
HINTERNET hRequest;
do
sprintf(pRpcTarget, RPC_TARGET_FMT_STRING, pMethod);
retStatus = CopyMultiToWideAlloc(pRpcTarget,
(int) strlen(pRpcTarget),
&pWideRpcTarget,
&wideRpcTargetLen);
if (CASA_SUCCESS(retStatus))
{
// Forget about having been told to retry
attemptRetry = false;
HINTERNET hRequest;
// Open a request handle
hRequest = WinHttpOpenRequest(pSession->hConnection,
L"POST",
pWideRpcTarget,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
flags & SECURE_RPC_FLAG? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH);
if (hRequest)
do
{
int reqDataLen = (int) strlen(pRequestData);
// Forget about having been told to retry
attemptRetry = false;
// Check if we need to set options to deal with secure connections
if (flags & SECURE_RPC_FLAG)
{
// We are using secure connections, now proceed based on whether or not
// we are configured to allow invalid certificates.
if (flags & ALLOW_INVALID_CERTS_RPC_FLAG
|| (flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG
&& InvalidCertsFromHostAllowed(pSession->pHostName)))
{
DWORD secFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA;
// We are configured to allow invalid certificates, inform the HTTP stack.
if (WinHttpSetOption(hRequest,
WINHTTP_OPTION_SECURITY_FLAGS,
&secFlags,
sizeof(secFlags)) == FALSE)
{
DbgTrace(0, "-InternalRpc- Failed setting options to ignore invalid certs, error = %d\n", GetLastError());
}
}
else
{
// We are not configured to allow invalid certificates, set a callback handler
// to detect invalid certificate conditions.
if (WinHttpSetStatusCallback(hRequest,
SecureFailureStatusCallback,
WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
(DWORD_PTR) NULL) == WINHTTP_INVALID_STATUS_CALLBACK)
{
DbgTrace(0, "-InternalRpc- Failed setting status callback, error = %d\n", GetLastError());
}
}
}
// Send the request
securityFailureStatusFlags = 0;
if (WinHttpSendRequest(hRequest,
sendHeaders,
-1,
pRequestData,
reqDataLen,
reqDataLen,
(DWORD_PTR) &securityFailureStatusFlags))
{
// Request sent, now await for the response.
if (WinHttpReceiveResponse(hRequest, NULL))
{
WCHAR httpCompStatus[4] = {0};
DWORD httpCompStatusLen = sizeof(httpCompStatus);
// Response received, make sure that it completed successfully.
if (WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE,
// Open a request handle
hRequest = WinHttpOpenRequest(pSession->hConnection,
L"POST",
pWideRpcTarget,
NULL,
&httpCompStatus,
&httpCompStatusLen,
WINHTTP_NO_HEADER_INDEX))
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
flags & SECURE_RPC_FLAG? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH);
if (hRequest)
{
int reqDataLen = (int) strlen(pRequestData);
// Check if we need to set options to deal with secure connections
if (flags & SECURE_RPC_FLAG)
{
// We are using secure connections, now proceed based on whether or not
// we are configured to allow invalid certificates.
if (flags & ALLOW_INVALID_CERTS_RPC_FLAG
|| (flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG
&& InvalidCertsFromHostAllowed(pSession->pHostName)))
{
// Check that the request completed successfully
if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0)
DWORD secFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA;
// We are configured to allow invalid certificates, inform the HTTP stack.
if (WinHttpSetOption(hRequest,
WINHTTP_OPTION_SECURITY_FLAGS,
&secFlags,
sizeof(secFlags)) == FALSE)
{
char *pResponseData;
int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;
int responseDataRead = 0;
DbgTrace(0, "-InternalRpc- Failed setting options to ignore invalid certs, error = %d\n", GetLastError());
}
}
else
{
// We are not configured to allow invalid certificates, set a callback handler
// to detect invalid certificate conditions.
if (WinHttpSetStatusCallback(hRequest,
SecureFailureStatusCallback,
WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
(DWORD_PTR) NULL) == WINHTTP_INVALID_STATUS_CALLBACK)
{
DbgTrace(0, "-InternalRpc- Failed setting status callback, error = %d\n", GetLastError());
}
}
}
// Now read the response data, to do so we need to allocate a buffer.
pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE);
if (pResponseData)
// Send the request
securityFailureStatusFlags = 0;
if (WinHttpSendRequest(hRequest,
sendHeaders,
-1,
pRequestData,
reqDataLen,
reqDataLen,
(DWORD_PTR) &securityFailureStatusFlags))
{
// Request sent, now await for the response.
if (WinHttpReceiveResponse(hRequest, NULL))
{
WCHAR httpCompStatus[4] = {0};
DWORD httpCompStatusLen = sizeof(httpCompStatus);
// Response received, make sure that it completed successfully.
if (WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE,
NULL,
&httpCompStatus,
&httpCompStatusLen,
WINHTTP_NO_HEADER_INDEX))
{
// Check that the request completed successfully
if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0)
{
char *pCurrLocation = pResponseData;
DWORD bytesRead;
char *pResponseData;
int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;
int responseDataRead = 0;
do
// Now read the response data, to do so we need to allocate a buffer.
pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE);
if (pResponseData)
{
bytesRead = 0;
if (WinHttpReadData(hRequest,
(LPVOID) pCurrLocation,
responseDataBufSize - responseDataRead,
&bytesRead))
char *pCurrLocation = pResponseData;
DWORD bytesRead;
do
{
pCurrLocation += bytesRead;
responseDataRead += bytesRead;
// Check if we need to allocate a larger buffer
if (responseDataRead == responseDataBufSize)
bytesRead = 0;
if (WinHttpReadData(hRequest,
(LPVOID) pCurrLocation,
responseDataBufSize - responseDataRead,
&bytesRead))
{
char *pTmpBuf;
pCurrLocation += bytesRead;
responseDataRead += bytesRead;
// We need to upgrade the receive buffer
pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE);
if (pTmpBuf)
// Check if we need to allocate a larger buffer
if (responseDataRead == responseDataBufSize)
{
memcpy(pTmpBuf, pResponseData, responseDataBufSize);
free(pResponseData);
pResponseData = pTmpBuf;
pCurrLocation = pResponseData + responseDataBufSize;
responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE;
}
else
{
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
char *pTmpBuf;
// We need to upgrade the receive buffer
pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE);
if (pTmpBuf)
{
memcpy(pTmpBuf, pResponseData, responseDataBufSize);
free(pResponseData);
pResponseData = pTmpBuf;
pCurrLocation = pResponseData + responseDataBufSize;
responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE;
}
else
{
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
}
else
{
DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
} while (CASA_SUCCESS(retStatus)
&& bytesRead != 0);
// Check if the response data was successfully received
if (CASA_SUCCESS(retStatus))
{
// The response data was received, return it to the caller.
*ppResponseData = pResponseData;
*pResponseDataLen = responseDataRead;
}
else
{
DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
// Failed to receive the response data, free the allocated buffer.
free(pResponseData);
}
} while (CASA_SUCCESS(retStatus)
&& bytesRead != 0);
// Check if the response data was successfully received
if (CASA_SUCCESS(retStatus))
{
// The response data was received, return it to the caller.
*ppResponseData = pResponseData;
*pResponseDataLen = responseDataRead;
}
else
{
// Failed to receive the response data, free the allocated buffer.
free(pResponseData);
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
else
{
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
CASA_STATUS_UNSUCCESSFUL);
}
}
else
{
DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus);
DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
@ -547,7 +562,7 @@ InternalRpc(
}
else
{
DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError());
DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
@ -555,160 +570,163 @@ InternalRpc(
}
else
{
DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
else
{
int error = GetLastError();
int error = GetLastError();
if (error == ERROR_WINHTTP_CANNOT_CONNECT)
{
DbgTrace(0, "-InternalRpc- Unable to connect to server\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_AUTH_SERVER_UNAVAILABLE);
}
else if (error == ERROR_WINHTTP_SECURE_FAILURE)
{
DbgTrace(1, "-InternalRpc- Secure connection failure, flags = %0x\n", securityFailureStatusFlags);
// Try to deal with the issue
if ((securityFailureStatusFlags & ~(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA
| WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID
| WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) == 0
&& flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG)
if (error == ERROR_WINHTTP_CANNOT_CONNECT)
{
WINHTTP_CERTIFICATE_INFO certInfo;
DWORD certInfoLen = sizeof(certInfo);
DbgTrace(0, "-InternalRpc- Unable to connect to server\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_AUTH_SERVER_UNAVAILABLE);
}
else if (error == ERROR_WINHTTP_SECURE_FAILURE)
{
DbgTrace(1, "-InternalRpc- Secure connection failure, flags = %0x\n", securityFailureStatusFlags);
// The failure was due to an invalid CN, CA, or both.
//
// Obtain information about the server certificate to give user
// the choice of accepting it.
if (WinHttpQueryOption(hRequest,
WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT,
&certInfo,
&certInfoLen)
&& certInfo.lpszSubjectInfo != NULL
&& certInfo.lpszIssuerInfo != NULL)
// Try to deal with the issue
if ((securityFailureStatusFlags & ~(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA
| WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID
| WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) == 0
&& flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG)
{
char *pSubjectInfo;
int subjectInfoLen;
WINHTTP_CERTIFICATE_INFO certInfo;
DWORD certInfoLen = sizeof(certInfo);
// Convert the subjectInfo to multi-byte
retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo,
(int) wcslen(certInfo.lpszSubjectInfo),
&pSubjectInfo,
&subjectInfoLen);
if (CASA_SUCCESS(retStatus))
// The failure was due to an invalid CN, CA, or both.
//
// Obtain information about the server certificate to give user
// the choice of accepting it.
if (WinHttpQueryOption(hRequest,
WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT,
&certInfo,
&certInfoLen)
&& certInfo.lpszSubjectInfo != NULL
&& certInfo.lpszIssuerInfo != NULL)
{
char *pIssuerInfo;
int issuerInfoLen;
char *pSubjectInfo;
int subjectInfoLen;
// Convert the issuerInfo to multi-byte
retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo,
(int) wcslen(certInfo.lpszIssuerInfo),
&pIssuerInfo,
&issuerInfoLen);
// Convert the subjectInfo to multi-byte
retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo,
(int) wcslen(certInfo.lpszSubjectInfo),
&pSubjectInfo,
&subjectInfoLen);
if (CASA_SUCCESS(retStatus))
{
long invalidCertFlags = 0;
char *pIssuerInfo;
int issuerInfoLen;
// Setup the invalid cert flags
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
invalidCertFlags |= INVALID_CERT_CA_FLAG;
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
invalidCertFlags |= INVALID_CERT_CN_FLAG;
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
invalidCertFlags |= INVALID_CERT_DATE_FLAG;
// Give user the choice to accept the certificate
if (UserApprovedCert(pSession->pHostName,
pSubjectInfo,
pIssuerInfo,
invalidCertFlags))
// Convert the issuerInfo to multi-byte
retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo,
(int) wcslen(certInfo.lpszIssuerInfo),
&pIssuerInfo,
&issuerInfoLen);
if (CASA_SUCCESS(retStatus))
{
DbgTrace(1, "-InternalRpc- User approved invalid certificate from %s\n", pSession->pHostName);
long invalidCertFlags = 0;
// tbd - Investigate if there is a way to set the accepted certificate in a store so that
// it can be utilized by the SSL stack directly. This would be a better method for dealing with
// this issue.
// Setup the invalid cert flags
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
invalidCertFlags |= INVALID_CERT_CA_FLAG;
AllowInvalidCertsFromHost(pSession->pHostName);
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
invalidCertFlags |= INVALID_CERT_CN_FLAG;
// Try to retry the request
attemptRetry = true;
}
else
{
DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName);
if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
invalidCertFlags |= INVALID_CERT_DATE_FLAG;
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_SERVER_CERTIFICATE);
// Give user the choice to accept the certificate
if (UserApprovedCert(pSession->pHostName,
pSubjectInfo,
pIssuerInfo,
invalidCertFlags))
{
DbgTrace(1, "-InternalRpc- User approved invalid certificate from %s\n", pSession->pHostName);
// tbd - Investigate if there is a way to set the accepted certificate in a store so that
// it can be utilized by the SSL stack directly. This would be a better method for dealing with
// this issue.
AllowInvalidCertsFromHost(pSession->pHostName);
// Try to retry the request
attemptRetry = true;
}
else
{
DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_SERVER_CERTIFICATE);
}
// Free the buffer containing the issuerInfo
free(pIssuerInfo);
}
// Free the buffer containing the issuerInfo
free(pIssuerInfo);
// Free the buffer containing the subjectInfo
free(pSubjectInfo);
}
// Free the buffer containing the subjectInfo
free(pSubjectInfo);
// Free necessary certificate information
if (certInfo.lpszSubjectInfo) LocalFree(certInfo.lpszSubjectInfo);
if (certInfo.lpszIssuerInfo) LocalFree(certInfo.lpszIssuerInfo);
if (certInfo.lpszProtocolName) LocalFree(certInfo.lpszProtocolName);
if (certInfo.lpszSignatureAlgName) LocalFree(certInfo.lpszSignatureAlgName);
if (certInfo.lpszEncryptionAlgName) LocalFree(certInfo.lpszEncryptionAlgName);
}
else
{
DbgTrace(0, "-InternalRpc- Unable to obtain server certificate struct, error = %0x\n", GetLastError());
}
// Free necessary certificate information
if (certInfo.lpszSubjectInfo) LocalFree(certInfo.lpszSubjectInfo);
if (certInfo.lpszIssuerInfo) LocalFree(certInfo.lpszIssuerInfo);
if (certInfo.lpszProtocolName) LocalFree(certInfo.lpszProtocolName);
if (certInfo.lpszSignatureAlgName) LocalFree(certInfo.lpszSignatureAlgName);
if (certInfo.lpszEncryptionAlgName) LocalFree(certInfo.lpszEncryptionAlgName);
}
else
{
DbgTrace(0, "-InternalRpc- Unable to obtain server certificate struct, error = %0x\n", GetLastError());
// Decided to no give the user a choice to accept invalid server certificate
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_SERVER_CERTIFICATE);
}
}
else
{
// Decided to no give the user a choice to accept invalid server certificate
DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_SERVER_CERTIFICATE);
CASA_STATUS_UNSUCCESSFUL);
}
}
else
{
DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
// Close the request handle
WinHttpCloseHandle(hRequest);
}
else
{
DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
} while (attemptRetry && retriesAllowed--);
// Close the request handle
WinHttpCloseHandle(hRequest);
}
else
{
DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError());
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
} while (attemptRetry && retriesAllowed--);
// Free the rpc target wide string buffer
free(pWideRpcTarget);
}
else
{
DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0);
}
// Free the rpc target wide string buffer
free(pWideRpcTarget);
// Free buffer used to hold the rpc target string
free(pRpcTarget);
}
else
{
DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0);
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus);