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