2c8668479c
to be able to deliver the client component onto distributions targeting desktops without having to deliver the server components. This commit is for the resulting client project.
800 lines
29 KiB
C
800 lines
29 KiB
C
/***********************************************************************
|
|
*
|
|
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; version 2.1
|
|
* of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, Novell, Inc.
|
|
*
|
|
* To contact Novell about this file by physical or electronic mail,
|
|
* you may find current contact information at www.novell.com.
|
|
*
|
|
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
|
*
|
|
***********************************************************************/
|
|
|
|
|
|
//===[ Include files ]=====================================================
|
|
|
|
#include "internal.h"
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
#define INITIAL_RESPONSE_DATA_BUF_SIZE 1028
|
|
#define INCREMENT_RESPONSE_DATA_BUF_SIZE 256
|
|
|
|
#define MAX_RPC_RETRIES 3
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
CopyMultiToWideAlloc(
|
|
IN char *pMulti,
|
|
IN int multiSize,
|
|
INOUT LPWSTR *ppWide,
|
|
INOUT int *pWideSize)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int retStatus;
|
|
int size, i;
|
|
|
|
DbgTrace(2, "-CopyMultiToWideAlloc- Start\n", 0);
|
|
|
|
size = (multiSize + 1) * sizeof(WCHAR);
|
|
|
|
if ((*ppWide = (PWCHAR) malloc(size)) != NULL)
|
|
{
|
|
for (i = 0; i < multiSize; i++)
|
|
{
|
|
*(*ppWide + i) = (unsigned char) *(pMulti + i);
|
|
}
|
|
|
|
*(*ppWide + i) = L'\0';
|
|
|
|
if (pWideSize)
|
|
{
|
|
*pWideSize = size - sizeof(WCHAR);
|
|
}
|
|
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
DbgTrace(2, "-CopyMultiToWideAlloc- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
CopyWideToMultiAlloc(
|
|
IN LPWSTR pWide,
|
|
IN int wideSize,
|
|
INOUT char **ppMulti,
|
|
INOUT int *pMultiSize)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
int retStatus;
|
|
int size, i;
|
|
|
|
DbgTrace(2, "-CopyWideToMultiAlloc- Start\n", 0);
|
|
|
|
size = wideSize + 1;
|
|
|
|
if ((*ppMulti = malloc(size)) != NULL)
|
|
{
|
|
for (i = 0; i < wideSize; i++)
|
|
{
|
|
*(*ppMulti + i) = (char) *(pWide + i);
|
|
}
|
|
|
|
*(*ppMulti + i) = '\0';
|
|
|
|
if (pMultiSize)
|
|
{
|
|
*pMultiSize = size - 1;
|
|
}
|
|
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
DbgTrace(2, "-CopyWideToMultiAlloc- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
RpcSession*
|
|
OpenRpcSession(
|
|
IN char *pHostName,
|
|
IN uint16_t hostPort)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
RpcSession *pSession;
|
|
bool success = false;
|
|
|
|
DbgTrace(1, "-OpenRpcSession- Start\n", 0);
|
|
|
|
// Allocate space for the session
|
|
pSession = (RpcSession*) malloc(sizeof(*pSession));
|
|
if (pSession)
|
|
{
|
|
// Zero the session structure
|
|
memset(pSession, 0, sizeof(*pSession));
|
|
|
|
// Save copy of the hostname
|
|
pSession->pHostName = malloc(strlen(pHostName) + 1);
|
|
if (pSession->pHostName)
|
|
{
|
|
strcpy(pSession->pHostName, pHostName);
|
|
|
|
// Open a Winhttp session
|
|
pSession->hSession = WinHttpOpen(L"CASA Client/1.0",
|
|
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
|
WINHTTP_NO_PROXY_NAME,
|
|
WINHTTP_NO_PROXY_BYPASS,
|
|
0);
|
|
if (pSession->hSession)
|
|
{
|
|
LPWSTR pWideHostName;
|
|
int wideHostLen;
|
|
|
|
// Session opened, now convert the host name to Unicode so that
|
|
// we can open a connection.
|
|
if (CopyMultiToWideAlloc(pHostName,
|
|
(int) strlen(pHostName),
|
|
&pWideHostName,
|
|
&wideHostLen) == CASA_STATUS_SUCCESS)
|
|
{
|
|
// Now open connection
|
|
pSession->hConnection = WinHttpConnect(pSession->hSession,
|
|
pWideHostName,
|
|
hostPort,
|
|
0);
|
|
if (pSession->hConnection == NULL)
|
|
{
|
|
DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError());
|
|
}
|
|
else
|
|
{
|
|
success = true;
|
|
}
|
|
|
|
// Free the host name wide string buffer
|
|
free(pWideHostName);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for host name\n", 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0);
|
|
}
|
|
|
|
// Clean up if we did not succeed
|
|
if (!success)
|
|
{
|
|
if (pSession)
|
|
{
|
|
if (pSession->hConnection)
|
|
WinHttpCloseHandle(pSession->hConnection);
|
|
|
|
if (pSession->hSession)
|
|
WinHttpCloseHandle(pSession->hSession);
|
|
|
|
if (pSession->pHostName)
|
|
free(pSession->pHostName);
|
|
|
|
free(pSession);
|
|
pSession = NULL;
|
|
}
|
|
}
|
|
|
|
DbgTrace(2, "-OpenRpcSession- End, pSession = %08X\n", pSession);
|
|
|
|
return pSession;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
void
|
|
CloseRpcSession(
|
|
IN RpcSession *pSession)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
DbgTrace(1, "-CloseRpcSession- Start\n", 0);
|
|
|
|
// Close the connection handle
|
|
WinHttpCloseHandle(pSession->hConnection);
|
|
|
|
// Close the session handle
|
|
WinHttpCloseHandle(pSession->hSession);
|
|
|
|
// Free hostname buffer if necessary
|
|
if (pSession->pHostName)
|
|
free(pSession->pHostName);
|
|
|
|
// Free the space allocated for the session
|
|
free(pSession);
|
|
|
|
DbgTrace(1, "-CloseRpcSession- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
void CALLBACK
|
|
SecureFailureStatusCallback(
|
|
IN HINTERNET hRequest,
|
|
IN DWORD *pContext,
|
|
IN DWORD internetStatus,
|
|
IN LPVOID pStatusInformation,
|
|
IN DWORD statusInformationLength)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L0
|
|
//=======================================================================--
|
|
{
|
|
DbgTrace(1, "-SecureFailureStatusCallback- Start\n", 0);
|
|
|
|
// Only deal with failures related to certificates
|
|
if (internetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
|
|
{
|
|
// Save the specific failure status
|
|
*pContext = *(DWORD*) pStatusInformation;
|
|
}
|
|
|
|
DbgTrace(1, "-SecureFailureStatusCallback- End\n", 0);
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
InternalRpc(
|
|
IN RpcSession *pSession,
|
|
IN char *pMethod,
|
|
IN long flags,
|
|
IN char *pRequestData,
|
|
INOUT char **ppResponseData,
|
|
INOUT int *pResponseDataLen)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
#define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated
|
|
|
|
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
|
char rpcTarget[256];
|
|
LPWSTR pWideRpcTarget;
|
|
int wideRpcTargetLen;
|
|
WCHAR sendHeaders[] = L"Content-Type: text/html";
|
|
DWORD securityFailureStatusFlags;
|
|
int retriesAllowed = 1;
|
|
bool attemptRetry;
|
|
|
|
DbgTrace(1, "-InternalRpc- Start\n", 0);
|
|
|
|
// Initialize output parameter
|
|
*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))
|
|
{
|
|
HINTERNET hRequest;
|
|
|
|
do
|
|
{
|
|
// Forget about having been told to retry
|
|
attemptRetry = false;
|
|
|
|
// 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)
|
|
{
|
|
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)))
|
|
{
|
|
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,
|
|
NULL,
|
|
&httpCompStatus,
|
|
&httpCompStatusLen,
|
|
WINHTTP_NO_HEADER_INDEX))
|
|
{
|
|
// Check that the request completed successfully
|
|
if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0)
|
|
{
|
|
char *pResponseData;
|
|
int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE;
|
|
int responseDataRead = 0;
|
|
|
|
// Now read the response data, to do so we need to allocate a buffer.
|
|
pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE);
|
|
if (pResponseData)
|
|
{
|
|
char *pCurrLocation = pResponseData;
|
|
DWORD bytesRead;
|
|
|
|
do
|
|
{
|
|
bytesRead = 0;
|
|
if (WinHttpReadData(hRequest,
|
|
(LPVOID) pCurrLocation,
|
|
responseDataBufSize - responseDataRead,
|
|
&bytesRead))
|
|
{
|
|
pCurrLocation += bytesRead;
|
|
responseDataRead += bytesRead;
|
|
|
|
// Check if we need to allocate a larger buffer
|
|
if (responseDataRead == responseDataBufSize)
|
|
{
|
|
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
|
|
{
|
|
// Failed to receive the response data, free the allocated buffer.
|
|
free(pResponseData);
|
|
}
|
|
}
|
|
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- HTTP request did not complete successfully, status = %S\n", httpCompStatus);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_UNSUCCESSFUL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
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();
|
|
|
|
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)
|
|
{
|
|
WINHTTP_CERTIFICATE_INFO certInfo;
|
|
DWORD certInfoLen = sizeof(certInfo);
|
|
|
|
// 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 *pSubjectInfo;
|
|
int subjectInfoLen;
|
|
|
|
// Convert the subjectInfo to multi-byte
|
|
retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo,
|
|
(int) wcslen(certInfo.lpszSubjectInfo),
|
|
&pSubjectInfo,
|
|
&subjectInfoLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
char *pIssuerInfo;
|
|
int issuerInfoLen;
|
|
|
|
// Convert the issuerInfo to multi-byte
|
|
retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo,
|
|
(int) wcslen(certInfo.lpszIssuerInfo),
|
|
&pIssuerInfo,
|
|
&issuerInfoLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
long invalidCertFlags = 0;
|
|
|
|
// 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))
|
|
{
|
|
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 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());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 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
|
|
{
|
|
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--);
|
|
|
|
// Free the rpc target wide string buffer
|
|
free(pWideRpcTarget);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0);
|
|
}
|
|
|
|
DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus
|
|
Rpc(
|
|
IN RpcSession *pSession,
|
|
IN char *pMethod,
|
|
IN long flags,
|
|
IN char *pRequestData,
|
|
INOUT char **ppResponseData,
|
|
INOUT int *pResponseDataLen)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
int retries = 0;
|
|
|
|
DbgTrace(1, "-Rpc- Start\n", 0);
|
|
|
|
// Retry the RPC as needed
|
|
do
|
|
{
|
|
// Issue the RPC
|
|
retStatus = InternalRpc(pSession,
|
|
pMethod,
|
|
flags,
|
|
pRequestData,
|
|
ppResponseData,
|
|
pResponseDataLen);
|
|
|
|
// Account for this try
|
|
retries ++;
|
|
|
|
} while (CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE
|
|
&& retries < MAX_RPC_RETRIES);
|
|
|
|
DbgTrace(1, "-Rpc- End, retStatus = %d\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus
|
|
InitializeRpc(void)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
|
|
|
DbgTrace(1, "-InitializeRpc- Start\n", 0);
|
|
|
|
// Nothing to do for windows
|
|
|
|
DbgTrace(1, "-InitializeRpc- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|