windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/common/keysvc/keysvcc.cpp
2020-09-26 16:20:57 +08:00

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;
}