From d55ac482ac66dd98ab226c77b00b251794078fec Mon Sep 17 00:00:00 2001 From: Juan Carlos Luciani Date: Fri, 1 Dec 2006 12:42:52 +0000 Subject: [PATCH] Updates resulting from self-code review. --- CASA-auth-token/client/lib/engine.c | 7 +- .../client/lib/mechanisms/krb5/windows/get.c | 8 +- .../client/lib/mechanisms/pwd/get.c | 729 +++++++++--------- .../pwd/windows/PwdAuthenticate.conf | 2 +- CASA-auth-token/client/lib/windows/dllsup.c | 2 +- CASA-auth-token/client/lib/windows/platform.c | 135 ++-- CASA-auth-token/client/lib/windows/rpc.c | 520 +++++++------ 7 files changed, 734 insertions(+), 669 deletions(-) diff --git a/CASA-auth-token/client/lib/engine.c b/CASA-auth-token/client/lib/engine.c index 95377113..250af9d3 100644 --- a/CASA-auth-token/client/lib/engine.c +++ b/CASA-auth-token/client/lib/engine.c @@ -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 diff --git a/CASA-auth-token/client/lib/mechanisms/krb5/windows/get.c b/CASA-auth-token/client/lib/mechanisms/krb5/windows/get.c index f1f1dddf..46262248 100644 --- a/CASA-auth-token/client/lib/mechanisms/krb5/windows/get.c +++ b/CASA-auth-token/client/lib/mechanisms/krb5/windows/get.c @@ -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); diff --git a/CASA-auth-token/client/lib/mechanisms/pwd/get.c b/CASA-auth-token/client/lib/mechanisms/pwd/get.c index b9ec68e2..1745bdf5 100644 --- a/CASA-auth-token/client/lib/mechanisms/pwd/get.c +++ b/CASA-auth-token/client/lib/mechanisms/pwd/get.c @@ -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 - * - ***********************************************************************/ - - -//===[ 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 + * + ***********************************************************************/ + + +//===[ 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; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/lib/mechanisms/pwd/windows/PwdAuthenticate.conf b/CASA-auth-token/client/lib/mechanisms/pwd/windows/PwdAuthenticate.conf index 7d8b27ea..948d43e6 100644 --- a/CASA-auth-token/client/lib/mechanisms/pwd/windows/PwdAuthenticate.conf +++ b/CASA-auth-token/client/lib/mechanisms/pwd/windows/PwdAuthenticate.conf @@ -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 diff --git a/CASA-auth-token/client/lib/windows/dllsup.c b/CASA-auth-token/client/lib/windows/dllsup.c index ba628c74..25019123 100644 --- a/CASA-auth-token/client/lib/windows/dllsup.c +++ b/CASA-auth-token/client/lib/windows/dllsup.c @@ -128,7 +128,7 @@ BOOL APIENTRY DllMain( //=======================================================================-- { BOOL retStatus = TRUE; - char programFilesFolder[MAX_PATH]; + char programFilesFolder[MAX_PATH] = {0}; switch (ul_reason_for_call) { diff --git a/CASA-auth-token/client/lib/windows/platform.c b/CASA-auth-token/client/lib/windows/platform.c index 25f2a1c5..41862696 100644 --- a/CASA-auth-token/client/lib/windows/platform.c +++ b/CASA-auth-token/client/lib/windows/platform.c @@ -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 diff --git a/CASA-auth-token/client/lib/windows/rpc.c b/CASA-auth-token/client/lib/windows/rpc.c index e792a883..940534f4 100644 --- a/CASA-auth-token/client/lib/windows/rpc.c +++ b/CASA-auth-token/client/lib/windows/rpc.c @@ -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);