Updates resulting from self-code review.
This commit is contained in:
parent
74dce09720
commit
d55ac482ac
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -128,7 +128,7 @@ BOOL APIENTRY DllMain(
|
||||
//=======================================================================--
|
||||
{
|
||||
BOOL retStatus = TRUE;
|
||||
char programFilesFolder[MAX_PATH];
|
||||
char programFilesFolder[MAX_PATH] = {0};
|
||||
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user