1373 lines
45 KiB
C++
1373 lines
45 KiB
C++
//depot/Lab03_N/DS/security/cryptoapi/common/keysvc/keysvcc.cpp#9 - edit change 6380 (text)
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: keysvcc.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <wincrypt.h>
|
|
#include "keysvc.h"
|
|
#include "cryptui.h"
|
|
#include "lenroll.h"
|
|
#include "keysvcc.h"
|
|
|
|
#include "unicode.h"
|
|
#include "waitsvc.h"
|
|
|
|
typedef struct _WZR_RPC_BINDING_LIST
|
|
{
|
|
LPCSTR pszProtSeq;
|
|
LPCSTR pszEndpoint;
|
|
} WZR_RPC_BINDING_LIST;
|
|
|
|
WZR_RPC_BINDING_LIST g_awzrBindingList[] =
|
|
{
|
|
{ KEYSVC_LOCAL_PROT_SEQ, KEYSVC_LOCAL_ENDPOINT },
|
|
{ KEYSVC_DEFAULT_PROT_SEQ, KEYSVC_DEFAULT_ENDPOINT},
|
|
{ KEYSVC_LEGACY_PROT_SEQ, KEYSVC_LEGACY_ENDPOINT}
|
|
};
|
|
|
|
DWORD g_cwzrBindingList = sizeof(g_awzrBindingList)/sizeof(g_awzrBindingList[0]);
|
|
|
|
/****************************************
|
|
* Client side Key Service handles
|
|
****************************************/
|
|
|
|
typedef struct _KEYSVCC_INFO_ {
|
|
KEYSVC_HANDLE hKeySvc;
|
|
handle_t hRPCBinding;
|
|
} KEYSVCC_INFO, *PKEYSVCC_INFO;
|
|
|
|
|
|
void InitUnicodeString(
|
|
PKEYSVC_UNICODE_STRING pUnicodeString,
|
|
LPCWSTR pszString
|
|
)
|
|
{
|
|
pUnicodeString->Length = wcslen(pszString) * sizeof(WCHAR);
|
|
pUnicodeString->MaximumLength = pUnicodeString->Length + sizeof(WCHAR);
|
|
pUnicodeString->Buffer = (USHORT*)pszString;
|
|
}
|
|
|
|
//*****************************************************
|
|
//
|
|
// Implementation of Client API for Key Service
|
|
//
|
|
//*****************************************************
|
|
|
|
ULONG KeyOpenKeyServiceEx
|
|
(/* [in] */ RPC_IF_HANDLE rpc_ifspec,
|
|
/* [in] */ LPSTR pszMachineName,
|
|
/* [in] */ KEYSVC_TYPE OwnerType,
|
|
/* [in] */ LPWSTR pwszOwnerName,
|
|
/* [in] */ void *pAuthentication,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
|
|
|
|
{
|
|
PKEYSVC_BLOB pVersion = NULL;
|
|
KEYSVC_BLOB Authentication;
|
|
PKEYSVC_BLOB pAuth;
|
|
unsigned char *pStringBinding = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
KEYSVC_UNICODE_STRING OwnerName;
|
|
ULONG ulErr = 0;
|
|
DWORD i;
|
|
static BOOL fDone = FALSE;
|
|
|
|
|
|
memset(&Authentication, 0, sizeof(Authentication));
|
|
memset(&OwnerName, 0, sizeof(OwnerName));
|
|
|
|
if (NULL != pAuthentication)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
if (NULL != pwszOwnerName)
|
|
{
|
|
InitUnicodeString(&OwnerName, pwszOwnerName);
|
|
}
|
|
|
|
|
|
// allocate for the client key service handle
|
|
if (NULL == (pKeySvcCliInfo =
|
|
(PKEYSVCC_INFO)LocalAlloc(LMEM_ZEROINIT,
|
|
sizeof(KEYSVCC_INFO))))
|
|
{
|
|
ulErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
|
|
//
|
|
// before doing the Bind operation, wait for the cryptography
|
|
// service to be available.
|
|
//
|
|
|
|
WaitForCryptService(L"ProtectedStorage", &fDone);
|
|
for (i = 0; i < g_cwzrBindingList; i++)
|
|
{
|
|
if (RPC_S_OK != RpcNetworkIsProtseqValid(
|
|
(unsigned char *)g_awzrBindingList[i].pszProtSeq))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ulErr = RpcStringBindingComposeA(
|
|
NULL,
|
|
(unsigned char *)g_awzrBindingList[i].pszProtSeq,
|
|
(unsigned char *)pszMachineName,
|
|
(unsigned char *)g_awzrBindingList[i].pszEndpoint,
|
|
NULL,
|
|
&pStringBinding);
|
|
if (RPC_S_OK != ulErr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ulErr = RpcBindingFromStringBinding(
|
|
pStringBinding,
|
|
&pKeySvcCliInfo->hRPCBinding);
|
|
if (NULL != pStringBinding)
|
|
{
|
|
RpcStringFree(&pStringBinding);
|
|
}
|
|
if (RPC_S_OK != ulErr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ulErr = RpcEpResolveBinding(pKeySvcCliInfo->hRPCBinding, rpc_ifspec);
|
|
if (RPC_S_OK != ulErr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
__try
|
|
{
|
|
|
|
ulErr = KeyrOpenKeyService(pKeySvcCliInfo->hRPCBinding,
|
|
OwnerType, &OwnerName,
|
|
0, &Authentication,
|
|
&pVersion, &pKeySvcCliInfo->hKeySvc);
|
|
|
|
*phKeySvcCli = (KEYSVCC_HANDLE)pKeySvcCliInfo;
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
if (RPC_S_OK == ulErr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(RPC_S_OK != ulErr)
|
|
{
|
|
goto Ret;
|
|
}
|
|
|
|
if (NULL != pReserved)
|
|
{
|
|
PKEYSVC_OPEN_KEYSVC_INFO pOpenInfoCaller = (PKEYSVC_OPEN_KEYSVC_INFO)pReserved;
|
|
if (pOpenInfoCaller->ulSize != sizeof(KEYSVC_OPEN_KEYSVC_INFO))
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
if (NULL == pVersion)
|
|
{
|
|
pOpenInfoCaller->ulVersion = KEYSVC_VERSION_W2K;
|
|
}
|
|
else
|
|
{
|
|
if (NULL == pVersion->pb)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
PKEYSVC_OPEN_KEYSVC_INFO pOpenInfoCallee = (PKEYSVC_OPEN_KEYSVC_INFO)pVersion->pb;
|
|
if (pOpenInfoCallee->ulSize != sizeof(KEYSVC_OPEN_KEYSVC_INFO))
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pOpenInfoCaller->ulVersion = pOpenInfoCallee->ulVersion;
|
|
}
|
|
}
|
|
|
|
Ret:
|
|
__try
|
|
{
|
|
if (NULL != pVersion)
|
|
midl_user_free(pVersion);
|
|
if (pStringBinding)
|
|
RpcStringFree(&pStringBinding);
|
|
if (0 != ulErr)
|
|
{
|
|
if (pKeySvcCliInfo)
|
|
{
|
|
// close the RPC binding
|
|
if (pKeySvcCliInfo->hRPCBinding)
|
|
RpcBindingFree(&pKeySvcCliInfo->hRPCBinding);
|
|
LocalFree(pKeySvcCliInfo);
|
|
}
|
|
}
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyOpenKeyService
|
|
(/* [in] */ LPSTR pszMachineName,
|
|
/* [in] */ KEYSVC_TYPE OwnerType,
|
|
/* [in] */ LPWSTR pwszOwnerName,
|
|
/* [in] */ void *pAuthentication,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
|
|
{
|
|
return KeyOpenKeyServiceEx
|
|
(IKeySvc_v1_0_c_ifspec,
|
|
pszMachineName,
|
|
OwnerType,
|
|
pwszOwnerName,
|
|
pAuthentication,
|
|
pReserved,
|
|
phKeySvcCli);
|
|
}
|
|
|
|
ULONG KeyEnumerateProviders(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out][in] */ ULONG *pcProviderCount,
|
|
/* [size_is][size_is][out][in] */ PKEYSVC_PROVIDER_INFO *ppProviders)
|
|
{
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrEnumerateProviders(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&pTmpReserved,
|
|
pcProviderCount, ppProviders);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyEnumerateProviderTypes(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out][in] */ ULONG *pcProviderCount,
|
|
/* [size_is][size_is][out][in] */ PKEYSVC_PROVIDER_INFO *ppProviders)
|
|
{
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrEnumerateProviderTypes(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&pTmpReserved,
|
|
pcProviderCount, ppProviders);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyEnumerateProvContainers(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ KEYSVC_PROVIDER_INFO Provider,
|
|
/* [in, out] */ void *pReserved,
|
|
/* [in, out] */ ULONG *pcContainerCount,
|
|
/* [in, out][size_is(,*pcContainerCount)] */
|
|
PKEYSVC_UNICODE_STRING *ppContainers)
|
|
{
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
return KeyrEnumerateProvContainers(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
Provider,
|
|
&pTmpReserved, pcContainerCount,
|
|
ppContainers);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyCloseKeyService(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [out][in] */ void *pReserved)
|
|
{
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrCloseKeyService(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&pTmpReserved);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyGetDefaultProvider(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ ULONG ulProvType,
|
|
/* [in] */ ULONG ulFlags,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out] */ ULONG *pulDefType,
|
|
/* [out] */ PKEYSVC_PROVIDER_INFO *ppProvider)
|
|
{
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrGetDefaultProvider(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
ulProvType, ulFlags,
|
|
&pTmpReserved, pulDefType,
|
|
ppProvider);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeySetDefaultProvider(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ ULONG ulFlags,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [in] */ KEYSVC_PROVIDER_INFO Provider)
|
|
{
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrSetDefaultProvider(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
ulFlags, &pTmpReserved,
|
|
Provider);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyEnroll
|
|
(/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ LPSTR pszMachineName, //IN Required: name of the remote machine
|
|
/* [in] */ BOOL fKeyService, //IN Required: Whether the function is called remotely
|
|
/* [in] */ DWORD dwPurpose, //IN Required: Indicates type of request - enroll/renew
|
|
/* [in] */ LPWSTR pszAcctName, //IN Optional: Account name the service runs under
|
|
/* [in] */ void *pAuthentication, //RESERVED must be NULL
|
|
/* [in] */ BOOL fEnroll, //IN Required: Whether it is enrollment or renew
|
|
/* [in] */ LPWSTR pszCALocation, //IN Required: The ca machine name
|
|
/* [in] */ LPWSTR pszCAName, //IN Required: The ca name
|
|
/* [in] */ BOOL fNewKey, //IN Required: Set the TRUE if new private key is needed
|
|
/* [in] */ PCERT_REQUEST_PVK_NEW pKeyNew, //IN Required: The private key information
|
|
/* [in] */ CERT_BLOB *pCert, //IN Optional: The old certificate if renewing
|
|
/* [in] */ PCERT_REQUEST_PVK_NEW pRenewKey, //IN Optional: The new private key information
|
|
/* [in] */ LPWSTR pszHashAlg, //IN Optional: The hash algorithm
|
|
/* [in] */ LPWSTR pszDesStore, //IN Optional: The destination store
|
|
/* [in] */ DWORD dwStoreFlags, //IN Optional: Flags for cert store.
|
|
/* [in] */ PCERT_ENROLL_INFO pRequestInfo, //IN Required: The information about the cert request
|
|
/* [in] */ LPWSTR pszAttributes, //IN Optional: Attribute string for request
|
|
/* [in] */ DWORD dwFlags, //RESERVED must be 0
|
|
/* [in] */ BYTE *pReserved, //RESERVED must be NULL
|
|
/* [out] */ CERT_BLOB *pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
|
|
/* [out] */ CERT_BLOB *pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
|
|
/* [out] */ DWORD *pdwStatus) //OUT Optional: The status of the enrollment/renewal
|
|
{
|
|
PKEYSVC_BLOB pReservedBlob = NULL;
|
|
KEYSVC_UNICODE_STRING AcctName;
|
|
KEYSVC_UNICODE_STRING CALocation;
|
|
KEYSVC_UNICODE_STRING CAName;
|
|
KEYSVC_UNICODE_STRING DesStore;
|
|
KEYSVC_UNICODE_STRING HashAlg;
|
|
KEYSVC_BLOB *pPKCS7KeySvcBlob = NULL;
|
|
KEYSVC_BLOB *pHashKeySvcBlob = NULL;
|
|
KEYSVC_CERT_ENROLL_INFO EnrollInfo;
|
|
KEYSVC_CERT_REQUEST_PVK_NEW NewKeyInfo;
|
|
KEYSVC_CERT_REQUEST_PVK_NEW RenewKeyInfo;
|
|
KEYSVC_BLOB CertBlob;
|
|
DWORD i;
|
|
DWORD j;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
DWORD dwErr = 0;
|
|
DWORD cbExtensions;
|
|
PBYTE pbExtensions;
|
|
|
|
__try
|
|
{
|
|
// initialize everything
|
|
memset(pPKCS7Blob, 0, sizeof(CERT_BLOB));
|
|
memset(pHashBlob, 0, sizeof(CERT_BLOB));
|
|
memset(&AcctName, 0, sizeof(AcctName));
|
|
memset(&CALocation, 0, sizeof(CALocation));
|
|
memset(&CAName, 0, sizeof(CAName));
|
|
memset(&HashAlg, 0, sizeof(HashAlg));
|
|
memset(&DesStore, 0, sizeof(DesStore));
|
|
memset(&NewKeyInfo, 0, sizeof(NewKeyInfo));
|
|
memset(&EnrollInfo, 0, sizeof(EnrollInfo));
|
|
memset(&RenewKeyInfo, 0, sizeof(RenewKeyInfo));
|
|
memset(&CertBlob, 0, sizeof(CertBlob));
|
|
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
// set up the key service unicode structs
|
|
if (pszAcctName)
|
|
InitUnicodeString(&AcctName, pszAcctName);
|
|
if (pszCALocation)
|
|
InitUnicodeString(&CALocation, pszCALocation);
|
|
if (pszCAName)
|
|
InitUnicodeString(&CAName, pszCAName);
|
|
if (pszHashAlg)
|
|
InitUnicodeString(&HashAlg, pszHashAlg);
|
|
if (pszDesStore)
|
|
InitUnicodeString(&DesStore, pszDesStore);
|
|
|
|
// set up the new key info structure for the remote call
|
|
NewKeyInfo.ulProvType = pKeyNew->dwProvType;
|
|
if (pKeyNew->pwszProvider)
|
|
{
|
|
InitUnicodeString(&NewKeyInfo.Provider, pKeyNew->pwszProvider);
|
|
}
|
|
NewKeyInfo.ulProviderFlags = pKeyNew->dwProviderFlags;
|
|
if (pKeyNew->pwszKeyContainer)
|
|
{
|
|
InitUnicodeString(&NewKeyInfo.KeyContainer,
|
|
pKeyNew->pwszKeyContainer);
|
|
}
|
|
NewKeyInfo.ulKeySpec = pKeyNew->dwKeySpec;
|
|
NewKeyInfo.ulGenKeyFlags = pKeyNew->dwGenKeyFlags;
|
|
|
|
// set up the usage OIDs
|
|
if (pRequestInfo->pwszUsageOID)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.UsageOID, pRequestInfo->pwszUsageOID);
|
|
}
|
|
|
|
// set up the cert DN Name
|
|
if (pRequestInfo->pwszCertDNName)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.CertDNName, pRequestInfo->pwszCertDNName);
|
|
}
|
|
|
|
// set up the request info structure for the remote call
|
|
EnrollInfo.ulPostOption = pRequestInfo->dwPostOption;
|
|
if (pRequestInfo->pwszFriendlyName)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.FriendlyName,
|
|
pRequestInfo->pwszFriendlyName);
|
|
}
|
|
if (pRequestInfo->pwszDescription)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.Description,
|
|
pRequestInfo->pwszDescription);
|
|
}
|
|
if (pszAttributes)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.Attributes, pszAttributes);
|
|
}
|
|
|
|
// convert the cert extensions
|
|
// NOTE, the extensions structure cannot be simply cast,
|
|
// as the structures have different packing behaviors in
|
|
// 64 bit systems.
|
|
|
|
|
|
EnrollInfo.cExtensions = pRequestInfo->dwExtensions;
|
|
cbExtensions = EnrollInfo.cExtensions*(sizeof(PKEYSVC_CERT_EXTENSIONS) +
|
|
sizeof(KEYSVC_CERT_EXTENSIONS));
|
|
|
|
for(i=0; i < EnrollInfo.cExtensions; i++)
|
|
{
|
|
cbExtensions += pRequestInfo->prgExtensions[i]->cExtension*
|
|
sizeof(KEYSVC_CERT_EXTENSION);
|
|
}
|
|
|
|
EnrollInfo.prgExtensions = (PKEYSVC_CERT_EXTENSIONS*)midl_user_allocate( cbExtensions);
|
|
|
|
if(NULL == EnrollInfo.prgExtensions)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
|
|
pbExtensions = (PBYTE)(EnrollInfo.prgExtensions + EnrollInfo.cExtensions);
|
|
|
|
|
|
|
|
|
|
for(i=0; i < EnrollInfo.cExtensions; i++)
|
|
{
|
|
EnrollInfo.prgExtensions[i] = (PKEYSVC_CERT_EXTENSIONS)pbExtensions;
|
|
pbExtensions += sizeof(KEYSVC_CERT_EXTENSIONS);
|
|
EnrollInfo.prgExtensions[i]->cExtension = pRequestInfo->prgExtensions[i]->cExtension;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension = (PKEYSVC_CERT_EXTENSION)pbExtensions;
|
|
pbExtensions += sizeof(KEYSVC_CERT_EXTENSION)*EnrollInfo.prgExtensions[i]->cExtension;
|
|
|
|
|
|
for(j=0; j < EnrollInfo.prgExtensions[i]->cExtension; j++)
|
|
{
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].pszObjId =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].pszObjId;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].fCritical =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].fCritical;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].cbData =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].Value.cbData;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].pbData =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].Value.pbData;
|
|
}
|
|
}
|
|
|
|
// if doing renewal then make sure have everything needed
|
|
if ((CRYPTUI_WIZ_CERT_RENEW == dwPurpose) &&
|
|
((NULL == pRenewKey) || (NULL == pCert)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// set up the new key info structure for the remote call
|
|
if (pRenewKey)
|
|
{
|
|
RenewKeyInfo.ulProvType = pRenewKey->dwProvType;
|
|
if (pRenewKey->pwszProvider)
|
|
{
|
|
InitUnicodeString(&RenewKeyInfo.Provider, pRenewKey->pwszProvider);
|
|
}
|
|
RenewKeyInfo.ulProviderFlags = pRenewKey->dwProviderFlags;
|
|
if (pRenewKey->pwszKeyContainer)
|
|
{
|
|
InitUnicodeString(&RenewKeyInfo.KeyContainer,
|
|
pRenewKey->pwszKeyContainer);
|
|
}
|
|
RenewKeyInfo.ulKeySpec = pRenewKey->dwKeySpec;
|
|
RenewKeyInfo.ulGenKeyFlags = pRenewKey->dwGenKeyFlags;
|
|
}
|
|
|
|
// set up the cert blob for renewal
|
|
if (pCert)
|
|
{
|
|
CertBlob.cb = pCert->cbData;
|
|
CertBlob.pb = pCert->pbData;
|
|
}
|
|
|
|
// make the remote enrollment call
|
|
if (0 != (dwErr = KeyrEnroll(pKeySvcCliInfo->hRPCBinding, fKeyService, dwPurpose,
|
|
&AcctName, &CALocation, &CAName, fNewKey,
|
|
&NewKeyInfo, &CertBlob, &RenewKeyInfo,
|
|
&HashAlg, &DesStore, dwStoreFlags,
|
|
&EnrollInfo, dwFlags, &pReservedBlob,
|
|
&pPKCS7KeySvcBlob,
|
|
&pHashKeySvcBlob, pdwStatus)))
|
|
goto Ret;
|
|
|
|
// allocate and copy the output parameters
|
|
if (pPKCS7KeySvcBlob->cb)
|
|
{
|
|
pPKCS7Blob->cbData = pPKCS7KeySvcBlob->cb;
|
|
if (NULL == (pPKCS7Blob->pbData =
|
|
(BYTE*)midl_user_allocate(pPKCS7Blob->cbData)))
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
memcpy(pPKCS7Blob->pbData, pPKCS7KeySvcBlob->pb,
|
|
pPKCS7Blob->cbData);
|
|
}
|
|
if (pHashKeySvcBlob->cb)
|
|
{
|
|
pHashBlob->cbData = pHashKeySvcBlob->cb;
|
|
if (NULL == (pHashBlob->pbData =
|
|
(BYTE*)midl_user_allocate(pHashBlob->cbData)))
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
memcpy(pHashBlob->pbData, pHashKeySvcBlob->pb, pHashBlob->cbData);
|
|
}
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
return _exception_code();
|
|
}
|
|
Ret:
|
|
__try
|
|
{
|
|
if (pPKCS7KeySvcBlob)
|
|
{
|
|
midl_user_free(pPKCS7KeySvcBlob);
|
|
}
|
|
if (pHashKeySvcBlob)
|
|
{
|
|
midl_user_free(pHashKeySvcBlob);
|
|
}
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
return _exception_code();
|
|
}
|
|
return dwErr;
|
|
}
|
|
|
|
// Params needed for create:
|
|
//
|
|
// Params not needed for submit:
|
|
// all except pszMachineName, dwPurpose, dwFlags, fEnroll, dwStoreFlags, hRequest, and dwFlags.
|
|
//
|
|
// Params not needed for free:
|
|
// all except pszMachineName, hRequest, and dwFlags.
|
|
//
|
|
ULONG KeyEnroll_V2
|
|
(/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ LPSTR pszMachineName, //IN Required: name of the remote machine
|
|
/* [in] */ BOOL fKeyService, //IN Required: Whether the function is called remotely
|
|
/* [in] */ DWORD dwPurpose, //IN Required: Indicates type of request - enroll/renew
|
|
/* [in] */ DWORD dwFlags, //IN Required: Flags for enrollment
|
|
/* [in] */ LPWSTR pszAcctName, //IN Optional: Account name the service runs under
|
|
/* [in] */ void *pAuthentication, //RESERVED must be NULL
|
|
/* [in] */ BOOL fEnroll, //IN Required: Whether it is enrollment or renew
|
|
/* [in] */ LPWSTR pszCALocation, //IN Required: The ca machine names to attempt to enroll with
|
|
/* [in] */ LPWSTR pszCAName, //IN Required: The ca names to attempt to enroll with
|
|
/* [in] */ BOOL fNewKey, //IN Required: Set the TRUE if new private key is needed
|
|
/* [in] */ PCERT_REQUEST_PVK_NEW pKeyNew, //IN Required: The private key information
|
|
/* [in] */ CERT_BLOB *pCert, //IN Optional: The old certificate if renewing
|
|
/* [in] */ PCERT_REQUEST_PVK_NEW pRenewKey, //IN Optional: The new private key information
|
|
/* [in] */ LPWSTR pszHashAlg, //IN Optional: The hash algorithm
|
|
/* [in] */ LPWSTR pszDesStore, //IN Optional: The destination store
|
|
/* [in] */ DWORD dwStoreFlags, //IN Optional: Flags for cert store.
|
|
/* [in] */ PCERT_ENROLL_INFO pRequestInfo, //IN Required: The information about the cert request
|
|
/* [in] */ LPWSTR pszAttributes, //IN Optional: Attribute string for request
|
|
/* [in] */ DWORD dwReservedFlags, //RESERVED must be 0
|
|
/* [in] */ BYTE *pReserved, //RESERVED must be NULL
|
|
/* [in][out] */ HANDLE *phRequest, //IN OUT Optional: A handle to a created request
|
|
/* [out] */ CERT_BLOB *pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
|
|
/* [out] */ CERT_BLOB *pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
|
|
/* [out] */ DWORD *pdwStatus) //OUT Optional: The status of the enrollment/renewal
|
|
{
|
|
PKEYSVC_BLOB pReservedBlob = NULL;
|
|
KEYSVC_UNICODE_STRING AcctName;
|
|
KEYSVC_UNICODE_STRING CALocation;
|
|
KEYSVC_UNICODE_STRING CAName;
|
|
KEYSVC_UNICODE_STRING DesStore;
|
|
KEYSVC_UNICODE_STRING HashAlg;
|
|
KEYSVC_BLOB KeySvcRequest;
|
|
KEYSVC_BLOB *pKeySvcRequest = NULL;
|
|
KEYSVC_BLOB *pPKCS7KeySvcBlob = NULL;
|
|
KEYSVC_BLOB *pHashKeySvcBlob = NULL;
|
|
ULONG ulKeySvcStatus = 0;
|
|
KEYSVC_CERT_ENROLL_INFO EnrollInfo;
|
|
KEYSVC_CERT_REQUEST_PVK_NEW_V2 NewKeyInfo;
|
|
KEYSVC_CERT_REQUEST_PVK_NEW_V2 RenewKeyInfo;
|
|
KEYSVC_BLOB CertBlob;
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD dwErr = 0;
|
|
DWORD cbExtensions;
|
|
PBYTE pbExtensions;
|
|
BOOL fCreateRequest = 0 == (dwFlags & (CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY));
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
|
|
__try
|
|
{
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// INITIALIZATION:
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
if (NULL != pPKCS7Blob) { memset(pPKCS7Blob, 0, sizeof(CERT_BLOB)); }
|
|
if (NULL != pHashBlob) { memset(pHashBlob, 0, sizeof(CERT_BLOB)); }
|
|
if (NULL != phRequest && NULL != *phRequest)
|
|
{
|
|
pKeySvcRequest = &KeySvcRequest;
|
|
pKeySvcRequest->cb = sizeof(*phRequest);
|
|
pKeySvcRequest->pb = (BYTE *)phRequest;
|
|
}
|
|
|
|
memset(&AcctName, 0, sizeof(AcctName));
|
|
memset(&CALocation, 0, sizeof(CALocation));
|
|
memset(&CAName, 0, sizeof(CAName));
|
|
memset(&HashAlg, 0, sizeof(HashAlg));
|
|
memset(&DesStore, 0, sizeof(DesStore));
|
|
memset(&NewKeyInfo, 0, sizeof(NewKeyInfo));
|
|
memset(&EnrollInfo, 0, sizeof(EnrollInfo));
|
|
memset(&RenewKeyInfo, 0, sizeof(RenewKeyInfo));
|
|
memset(&CertBlob, 0, sizeof(CertBlob));
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// PROCEDURE BODY:
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
// set up the key service unicode structs
|
|
if (pszAcctName)
|
|
InitUnicodeString(&AcctName, pszAcctName);
|
|
if (pszCALocation)
|
|
InitUnicodeString(&CALocation, pszCALocation);
|
|
if (pszCAName)
|
|
InitUnicodeString(&CAName, pszCAName);
|
|
if (pszHashAlg)
|
|
InitUnicodeString(&HashAlg, pszHashAlg);
|
|
if (pszDesStore)
|
|
InitUnicodeString(&DesStore, pszDesStore);
|
|
|
|
// set up the new key info structure for the remote call
|
|
// This is only necessary if we are actually _creating_ a request.
|
|
// Submit-only and free-only operations can skip this operation.
|
|
//
|
|
if (TRUE == fCreateRequest)
|
|
{
|
|
NewKeyInfo.ulProvType = pKeyNew->dwProvType;
|
|
if (pKeyNew->pwszProvider)
|
|
{
|
|
InitUnicodeString(&NewKeyInfo.Provider, pKeyNew->pwszProvider);
|
|
}
|
|
NewKeyInfo.ulProviderFlags = pKeyNew->dwProviderFlags;
|
|
if (pKeyNew->pwszKeyContainer)
|
|
{
|
|
InitUnicodeString(&NewKeyInfo.KeyContainer,
|
|
pKeyNew->pwszKeyContainer);
|
|
}
|
|
NewKeyInfo.ulKeySpec = pKeyNew->dwKeySpec;
|
|
NewKeyInfo.ulGenKeyFlags = pKeyNew->dwGenKeyFlags;
|
|
|
|
NewKeyInfo.ulEnrollmentFlags = pKeyNew->dwEnrollmentFlags;
|
|
NewKeyInfo.ulSubjectNameFlags = pKeyNew->dwSubjectNameFlags;
|
|
NewKeyInfo.ulPrivateKeyFlags = pKeyNew->dwPrivateKeyFlags;
|
|
NewKeyInfo.ulGeneralFlags = pKeyNew->dwGeneralFlags;
|
|
|
|
// set up the usage OIDs
|
|
if (pRequestInfo->pwszUsageOID)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.UsageOID, pRequestInfo->pwszUsageOID);
|
|
}
|
|
|
|
// set up the cert DN Name
|
|
if (pRequestInfo->pwszCertDNName)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.CertDNName, pRequestInfo->pwszCertDNName);
|
|
}
|
|
|
|
// set up the request info structure for the remote call
|
|
EnrollInfo.ulPostOption = pRequestInfo->dwPostOption;
|
|
if (pRequestInfo->pwszFriendlyName)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.FriendlyName,
|
|
pRequestInfo->pwszFriendlyName);
|
|
}
|
|
if (pRequestInfo->pwszDescription)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.Description,
|
|
pRequestInfo->pwszDescription);
|
|
}
|
|
if (pszAttributes)
|
|
{
|
|
InitUnicodeString(&EnrollInfo.Attributes, pszAttributes);
|
|
}
|
|
|
|
// convert the cert extensions
|
|
// NOTE, the extensions structure cannot be simply cast,
|
|
// as the structures have different packing behaviors in
|
|
// 64 bit systems.
|
|
|
|
|
|
EnrollInfo.cExtensions = pRequestInfo->dwExtensions;
|
|
cbExtensions = EnrollInfo.cExtensions*(sizeof(PKEYSVC_CERT_EXTENSIONS) +
|
|
sizeof(KEYSVC_CERT_EXTENSIONS));
|
|
|
|
for(i=0; i < EnrollInfo.cExtensions; i++)
|
|
{
|
|
cbExtensions += pRequestInfo->prgExtensions[i]->cExtension*
|
|
sizeof(KEYSVC_CERT_EXTENSION);
|
|
}
|
|
|
|
EnrollInfo.prgExtensions = (PKEYSVC_CERT_EXTENSIONS*)midl_user_allocate( cbExtensions);
|
|
|
|
if(NULL == EnrollInfo.prgExtensions)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
|
|
pbExtensions = (PBYTE)(EnrollInfo.prgExtensions + EnrollInfo.cExtensions);
|
|
|
|
for(i=0; i < EnrollInfo.cExtensions; i++)
|
|
{
|
|
EnrollInfo.prgExtensions[i] = (PKEYSVC_CERT_EXTENSIONS)pbExtensions;
|
|
pbExtensions += sizeof(KEYSVC_CERT_EXTENSIONS);
|
|
EnrollInfo.prgExtensions[i]->cExtension = pRequestInfo->prgExtensions[i]->cExtension;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension = (PKEYSVC_CERT_EXTENSION)pbExtensions;
|
|
pbExtensions += sizeof(KEYSVC_CERT_EXTENSION)*EnrollInfo.prgExtensions[i]->cExtension;
|
|
|
|
|
|
for(j=0; j < EnrollInfo.prgExtensions[i]->cExtension; j++)
|
|
{
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].pszObjId =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].pszObjId;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].fCritical =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].fCritical;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].cbData =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].Value.cbData;
|
|
|
|
EnrollInfo.prgExtensions[i]->rgExtension[j].pbData =
|
|
pRequestInfo->prgExtensions[i]->rgExtension[j].Value.pbData;
|
|
}
|
|
}
|
|
|
|
// if doing renewal then make sure have everything needed
|
|
if ((CRYPTUI_WIZ_CERT_RENEW == dwPurpose) &&
|
|
((NULL == pRenewKey) || (NULL == pCert)))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
// set up the new key info structure for the remote call
|
|
if (pRenewKey)
|
|
{
|
|
RenewKeyInfo.ulProvType = pRenewKey->dwProvType;
|
|
if (pRenewKey->pwszProvider)
|
|
{
|
|
InitUnicodeString(&RenewKeyInfo.Provider, pRenewKey->pwszProvider);
|
|
}
|
|
RenewKeyInfo.ulProviderFlags = pRenewKey->dwProviderFlags;
|
|
if (pRenewKey->pwszKeyContainer)
|
|
{
|
|
InitUnicodeString(&RenewKeyInfo.KeyContainer,
|
|
pRenewKey->pwszKeyContainer);
|
|
}
|
|
RenewKeyInfo.ulKeySpec = pRenewKey->dwKeySpec;
|
|
RenewKeyInfo.ulGenKeyFlags = pRenewKey->dwGenKeyFlags;
|
|
RenewKeyInfo.ulEnrollmentFlags = pRenewKey->dwEnrollmentFlags;
|
|
RenewKeyInfo.ulSubjectNameFlags = pRenewKey->dwSubjectNameFlags;
|
|
RenewKeyInfo.ulPrivateKeyFlags = pRenewKey->dwPrivateKeyFlags;
|
|
RenewKeyInfo.ulGeneralFlags = pRenewKey->dwGeneralFlags;
|
|
}
|
|
|
|
// set up the cert blob for renewal
|
|
if (pCert)
|
|
{
|
|
CertBlob.cb = pCert->cbData;
|
|
CertBlob.pb = pCert->pbData;
|
|
}
|
|
}
|
|
|
|
// make the remote enrollment call
|
|
if (0 != (dwErr = KeyrEnroll_V2
|
|
(pKeySvcCliInfo->hRPCBinding,
|
|
fKeyService,
|
|
dwPurpose,
|
|
dwFlags,
|
|
&AcctName,
|
|
&CALocation,
|
|
&CAName,
|
|
fNewKey,
|
|
&NewKeyInfo,
|
|
&CertBlob,
|
|
&RenewKeyInfo,
|
|
&HashAlg,
|
|
&DesStore,
|
|
dwStoreFlags,
|
|
&EnrollInfo,
|
|
dwReservedFlags,
|
|
&pReservedBlob,
|
|
&pKeySvcRequest,
|
|
&pPKCS7KeySvcBlob,
|
|
&pHashKeySvcBlob,
|
|
&ulKeySvcStatus)))
|
|
goto Ret;
|
|
|
|
// allocate and copy the output parameters.
|
|
if ((NULL != pKeySvcRequest) &&
|
|
(0 < pKeySvcRequest->cb) &&
|
|
(NULL != phRequest))
|
|
{
|
|
memcpy(phRequest, pKeySvcRequest->pb, sizeof(*phRequest));
|
|
}
|
|
|
|
if ((NULL != pPKCS7KeySvcBlob) &&
|
|
(0 < pPKCS7KeySvcBlob->cb) &&
|
|
(NULL != pPKCS7Blob))
|
|
{
|
|
pPKCS7Blob->cbData = pPKCS7KeySvcBlob->cb;
|
|
if (NULL == (pPKCS7Blob->pbData =
|
|
(BYTE*)midl_user_allocate(pPKCS7Blob->cbData)))
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
memcpy(pPKCS7Blob->pbData, pPKCS7KeySvcBlob->pb,
|
|
pPKCS7Blob->cbData);
|
|
}
|
|
if ((NULL != pHashKeySvcBlob) &&
|
|
(0 < pHashKeySvcBlob->cb) &&
|
|
(NULL != pHashBlob))
|
|
{
|
|
pHashBlob->cbData = pHashKeySvcBlob->cb;
|
|
if (NULL == (pHashBlob->pbData =
|
|
(BYTE*)midl_user_allocate(pHashBlob->cbData)))
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Ret;
|
|
}
|
|
memcpy(pHashBlob->pbData, pHashKeySvcBlob->pb, pHashBlob->cbData);
|
|
}
|
|
if (NULL != pdwStatus)
|
|
{
|
|
*pdwStatus = (DWORD)ulKeySvcStatus;
|
|
}
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
return _exception_code();
|
|
}
|
|
Ret:
|
|
__try
|
|
{
|
|
if(EnrollInfo.prgExtensions)
|
|
{
|
|
midl_user_free(EnrollInfo.prgExtensions);
|
|
}
|
|
if (pKeySvcRequest)
|
|
{
|
|
midl_user_free(pKeySvcRequest);
|
|
}
|
|
if (pPKCS7KeySvcBlob)
|
|
{
|
|
midl_user_free(pPKCS7KeySvcBlob);
|
|
}
|
|
if (pHashKeySvcBlob)
|
|
{
|
|
midl_user_free(pHashKeySvcBlob);
|
|
}
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
return _exception_code();
|
|
}
|
|
return dwErr;
|
|
}
|
|
|
|
ULONG KeyExportCert(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ LPWSTR pwszPassword,
|
|
/* [in] */ LPWSTR pwszCertStore,
|
|
/* [in] */ ULONG cHashCount,
|
|
/* [size_is][in] */ KEYSVC_CERT_HASH *pHashes,
|
|
/* [in] */ ULONG ulFlags,
|
|
/* [in, out] */ void *pReserved,
|
|
/* [out] */ PKEYSVC_BLOB *ppPFXBlob)
|
|
{
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
KEYSVC_UNICODE_STRING Password;
|
|
KEYSVC_UNICODE_STRING CertStore;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
memset(&Password, 0, sizeof(Password));
|
|
memset(&CertStore, 0, sizeof(CertStore));
|
|
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
InitUnicodeString(&Password, pwszPassword);
|
|
InitUnicodeString(&CertStore, pwszCertStore);
|
|
|
|
ulErr = KeyrExportCert(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&Password, &CertStore,
|
|
cHashCount, pHashes,
|
|
ulFlags, &pTmpReserved, ppPFXBlob);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG KeyImportCert(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ LPWSTR pwszPassword,
|
|
/* [in] */ LPWSTR pwszCertStore,
|
|
/* [in] */ PKEYSVC_BLOB pPFXBlob,
|
|
/* [in] */ ULONG ulFlags,
|
|
/* [in, out] */ void *pReserved)
|
|
{
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
KEYSVC_UNICODE_STRING Password;
|
|
KEYSVC_UNICODE_STRING CertStore;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
memset(&Password, 0, sizeof(Password));
|
|
memset(&CertStore, 0, sizeof(CertStore));
|
|
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
InitUnicodeString(&Password, pwszPassword);
|
|
InitUnicodeString(&CertStore, pwszCertStore);
|
|
|
|
ulErr = KeyrImportCert(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&Password, &CertStore,
|
|
pPFXBlob, ulFlags, &pTmpReserved);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
|
|
ULONG KeyEnumerateAvailableCertTypes(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out][in] */ ULONG *pcCertTypeCount,
|
|
/* [in, out][size_is(,*pcCertTypeCount)] */
|
|
PKEYSVC_UNICODE_STRING *ppCertTypes)
|
|
|
|
{
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrEnumerateAvailableCertTypes(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&pTmpReserved,
|
|
pcCertTypeCount,
|
|
ppCertTypes);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
|
|
ULONG KeyEnumerateCAs(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [in] */ ULONG ulFlags,
|
|
/* [out][in] */ ULONG *pcCACount,
|
|
/* [in, out][size_is(,*pcCACount)] */
|
|
PKEYSVC_UNICODE_STRING *ppCAs)
|
|
|
|
{
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrEnumerateCAs(pKeySvcCliInfo->hRPCBinding,
|
|
pKeySvcCliInfo->hKeySvc,
|
|
&pTmpReserved,
|
|
ulFlags,
|
|
pcCACount,
|
|
ppCAs);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
|
|
extern "C" ULONG KeyQueryRequestStatus
|
|
(/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ HANDLE hRequest,
|
|
/* [out, ref] */ CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO *pQueryInfo)
|
|
{
|
|
KEYSVC_QUERY_CERT_REQUEST_INFO ksQueryCertRequestInfo;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli || NULL == pQueryInfo)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
ZeroMemory(&ksQueryCertRequestInfo, sizeof(ksQueryCertRequestInfo));
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = KeyrQueryRequestStatus
|
|
(pKeySvcCliInfo->hRPCBinding,
|
|
(unsigned __int64)hRequest,
|
|
&ksQueryCertRequestInfo);
|
|
if (ERROR_SUCCESS == ulErr)
|
|
{
|
|
pQueryInfo->dwSize = ksQueryCertRequestInfo.ulSize;
|
|
pQueryInfo->dwStatus = ksQueryCertRequestInfo.ulStatus;
|
|
}
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
Ret:
|
|
return ulErr;
|
|
}
|
|
|
|
ULONG RKeyOpenKeyService
|
|
(/* [in] */ LPSTR pszMachineName,
|
|
/* [in] */ KEYSVC_TYPE OwnerType,
|
|
/* [in] */ LPWSTR pwszOwnerName,
|
|
/* [in] */ void *pAuthentication,
|
|
/* [out][in] */ void *pReserved,
|
|
/* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
|
|
{
|
|
BOOL fMustCloseKeyService = FALSE; // TRUE if the cleanup code must close key service
|
|
DWORD dwResult;
|
|
LPWSTR pwszServerPrincName = NULL;
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
|
|
dwResult = KeyOpenKeyServiceEx
|
|
(IKeySvcR_v1_0_c_ifspec,
|
|
pszMachineName,
|
|
OwnerType,
|
|
pwszOwnerName,
|
|
pAuthentication,
|
|
pReserved,
|
|
phKeySvcCli);
|
|
if (ERROR_SUCCESS != dwResult)
|
|
goto error;
|
|
fMustCloseKeyService = TRUE;
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)(*phKeySvcCli);
|
|
dwResult = RpcMgmtInqServerPrincNameW(pKeySvcCliInfo->hRPCBinding, RPC_C_AUTHN_GSS_NEGOTIATE, &pwszServerPrincName);
|
|
if (RPC_S_OK != dwResult)
|
|
goto error;
|
|
|
|
dwResult = RpcBindingSetAuthInfoW
|
|
(pKeySvcCliInfo->hRPCBinding,
|
|
pwszServerPrincName,
|
|
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // Calls are authenticated and encrypted
|
|
RPC_C_AUTHN_GSS_NEGOTIATE,
|
|
NULL,
|
|
RPC_C_AUTHZ_NONE
|
|
);
|
|
if (ERROR_SUCCESS != dwResult)
|
|
goto error;
|
|
|
|
fMustCloseKeyService = FALSE;
|
|
dwResult = ERROR_SUCCESS;
|
|
error:
|
|
if (fMustCloseKeyService) { RKeyCloseKeyService(phKeySvcCli, 0); }
|
|
if (NULL != pwszServerPrincName) { RpcStringFreeW(&pwszServerPrincName); }
|
|
return dwResult;
|
|
}
|
|
|
|
ULONG RKeyCloseKeyService(
|
|
/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [out][in] */ void *pReserved)
|
|
{
|
|
return KeyCloseKeyService(hKeySvcCli, pReserved);
|
|
}
|
|
|
|
|
|
ULONG RKeyPFXInstall
|
|
(/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
|
|
/* [in] */ PKEYSVC_BLOB pPFX,
|
|
/* [in] */ PKEYSVC_UNICODE_STRING pPassword,
|
|
/* [in] */ ULONG ulFlags)
|
|
{
|
|
PKEYSVCC_INFO pKeySvcCliInfo = NULL;
|
|
PKEYSVC_BLOB pTmpReserved = NULL;
|
|
ULONG ulErr = 0;
|
|
|
|
__try
|
|
{
|
|
if (NULL == hKeySvcCli)
|
|
{
|
|
ulErr = ERROR_INVALID_PARAMETER;
|
|
goto Ret;
|
|
}
|
|
|
|
pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
|
|
|
|
ulErr = RKeyrPFXInstall(pKeySvcCliInfo->hRPCBinding,
|
|
pPFX,
|
|
pPassword,
|
|
ulFlags);
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ulErr = _exception_code();
|
|
}
|
|
|
|
Ret:
|
|
return ulErr;
|
|
}
|