|
|
//depot/Lab03_DEV/Ds/security/cryptoapi/common/keysvc/keysvcc.cpp#3 - edit change 21738 (text)
//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 <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <wincrypt.h>
#include <rpc.h>
#include <ntdsapi.h>
#include <assert.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} };
DWORD g_cwzrBindingList = sizeof(g_awzrBindingList)/sizeof(g_awzrBindingList[0]);
//
// BUGBUG: TODO: move the following to common header (rkeysvcc.w)
//
#define RKEYSVC_CONNECT_SECURE_ONLY 0x00000001
/****************************************
* 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 = (USHORT)(wcslen(pszString) * sizeof(WCHAR)); pUnicodeString->MaximumLength = pUnicodeString->Length + sizeof(WCHAR); pUnicodeString->Buffer = (USHORT*)pszString;
// Ensure that we don't have a string longer than allowed by our interface:
assert(pUnicodeString->Length < 64*1024); assert(pUnicodeString->MaximumLength < 64*1024); }
ULONG SetupRemoteRPCSecurity(handle_t hRPCBinding, LPSTR wszServer, BOOL fMutualAuth) { DWORD ccServerPrincName; DWORD dwResult; RPC_SECURITY_QOS SecurityQOS; ULONG ulErr; unsigned char szServerPrincName[256];
ZeroMemory(szServerPrincName, sizeof(szServerPrincName));
// Construct the SPN of the server we want to communicate with:
ccServerPrincName = sizeof(szServerPrincName) / sizeof(szServerPrincName[0]); dwResult = DsMakeSpn("protectedstorage", wszServer, NULL, 0, NULL, &ccServerPrincName, (LPSTR)szServerPrincName); if (ERROR_SUCCESS != dwResult) { goto Ret; }
// Specify quality of service parameters.
SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; // the server will need to impersonate us
SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION; SecurityQOS.Capabilities = fMutualAuth ? RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH : RPC_C_QOS_CAPABILITIES_DEFAULT ; // do we need mutual auth?
SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; // calls go to the server under the identity that created the binding handle
// NOTE: we still need to get MUTUAL_AUTH working in the remote case:
ulErr = RpcBindingSetAuthInfoExA(hRPCBinding, szServerPrincName, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE, NULL, RPC_C_AUTHZ_NAME, &SecurityQOS); if (RPC_S_OK != ulErr) { goto Ret; } ulErr = ERROR_SUCCESS; Ret: return ulErr; }
ULONG SetupLocalRPCSecurity(handle_t hRPCBinding, BOOL fMutualAuth) { CHAR szDomainName[128]; CHAR szName[128]; DWORD cbDomainName; DWORD cbName; PSID pSid = NULL; RPC_SECURITY_QOS SecurityQOS; SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; SID_NAME_USE SidNameUse; ULONG ulErr;
// We're doing LRPC -- we need to get the account name of the service to do mutual auth
if (!AllocateAndInitializeSid(&SidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSid)) { ulErr = GetLastError(); goto Ret; }
cbName = sizeof(szName); cbDomainName = sizeof(szDomainName); if (!LookupAccountSidA(NULL, pSid, szName, &cbName, szDomainName, &cbDomainName, &SidNameUse)) { ulErr = GetLastError(); goto Ret; } // Specify quality of service parameters.
SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; // the server will need to impersonate us
SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION; SecurityQOS.Capabilities = fMutualAuth ? RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH : RPC_C_QOS_CAPABILITIES_DEFAULT ; // do we need mutual auth?
SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; // calls go to the server under the identity that created the binding handle
ulErr = RpcBindingSetAuthInfoExA(hRPCBinding, (unsigned char *)szName, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, NULL, 0, &SecurityQOS); if (RPC_S_OK != ulErr) { goto Ret; }
ulErr = ERROR_SUCCESS; Ret: if (NULL != pSid) { FreeSid(pSid); } return ulErr; }
//*****************************************************
//
// Implementation of Client API for Key Service
//
//*****************************************************
//--------------------------------------------------------------------------------
// KeyOpenKeyServiceEx
//
// Creates a KEYSVCC_HANDLE which a keysvc client can use to access the keysvc
// interface. This method should
//
// a) Create an RPC binding handle based on the best available protseq (LRPC or named pipes)
// b) request mutual auth to ensure that the (L)RPC server isn't spoofing us.
// c) set PKT_PRIVACY encryption type. NOTE: should this work for LPC?
// d) ping the server to ensure that it's up (allows for better error reporting)
// e) determine whether the server is an XP box. If it is XP, we need to
// return an old-style KEYSVC_HANDLE for compatibility. This field
// is ignored post-XP.
//
// rpc_ifspec - the interface to open (keysvc or remote keysvc)
// pszMachineName - the server to bind to
// OwnerType - must be KeySvcMachine
// pwszOwnerName - must be NULL
// fMutualAuth - TRUE if mutual auth is required, FALSE otherwise
// pReserved - must be NULL
// phKeySvcCli - the handle through which the client can access keysvc.
// Must be closed through KeyCloseKeyService().
//
ULONG KeyOpenKeyServiceEx (/* [in] */ BOOL fRemoteKeysvc, /* [in] */ LPSTR pszMachineName, /* [in] */ KEYSVC_TYPE OwnerType, /* [in] */ LPWSTR pwszOwnerName, /* [in] */ BOOL fMutualAuth, /* [out][in] */ void *pReserved, /* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
{ BOOL static fDone = FALSE; DWORD i; handle_t hRPCBinding = NULL; PKEYSVCC_INFO pKeySvcCliInfo = NULL; ULONG ulErr = 0; unsigned char *pStringBinding = NULL;
if (NULL != pReserved || KeySvcMachine != OwnerType || NULL != pwszOwnerName) { ulErr = ERROR_INVALID_PARAMETER; goto Ret; }
// 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);
//
// a) Create the binding handle
for (i = 0; i < g_cwzrBindingList; i++) { if (RPC_S_OK != RpcNetworkIsProtseqValid( (unsigned char *)g_awzrBindingList[i].pszProtSeq)) { goto next; }
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) { goto next; }
ulErr = RpcBindingFromStringBinding( pStringBinding, &hRPCBinding); if (RPC_S_OK != ulErr) { goto next; }
//
// b) we've got the RPC binding, now request mutual auth and
// c) request PKT_PRIVACY
//
if (0 == strcmp("ncalrpc", g_awzrBindingList[i].pszProtSeq)) { ulErr = SetupLocalRPCSecurity(hRPCBinding, fMutualAuth); if (ERROR_SUCCESS != ulErr) { goto next; } } else if (0 == strcmp("ncacn_np", g_awzrBindingList[i].pszProtSeq)) { ulErr = SetupRemoteRPCSecurity(hRPCBinding, pszMachineName, fMutualAuth); if (ERROR_SUCCESS != ulErr) { goto next; } } else { // Unknown binding (shouldn't get here):
ulErr = RPC_S_WRONG_KIND_OF_BINDING; goto Ret; }
//
// d) We've set up mutual auth, now ping the server to make sure it's up.
// BUGBUG: There are two recommended ways of doing this. The "preferred"
// way is to resolve the endpoint and call RpcMgmtIsServerListening().
// This didn't work for me -- the function returned RPC_S_OK regardless
// of whether the server was up. The "less preferred but acceptable"
// way is simply to call a method on the remote interface. In the interests
// of time, I'm sticking with this method for Whistler.
//
// e) we'll also try to determine whether we're binding to an XP
// box. If so, return a KEYSVC_HANDLE for compatibility.
// This is ignored post-XP.
// we already have the binding we want to return:
pKeySvcCliInfo->hRPCBinding = hRPCBinding; pKeySvcCliInfo->hKeySvc = NULL; // NULL for post-XP (we'll check this below)
RpcTryExcept { KEYSVC_UNICODE_STRING kusOwnerName; KEYSVC_BLOB kBlobAuthentication; PKEYSVC_BLOB pkBlobReserved = NULL; PKEYSVC_BLOB pkBlobVersion = NULL; KEYSVC_HANDLE khCli = NULL;
ZeroMemory(&kusOwnerName, sizeof(kusOwnerName)); ZeroMemory(&kBlobAuthentication, sizeof(kBlobAuthentication));
if (!fRemoteKeysvc) ulErr = KeyrOpenKeyService(hRPCBinding, KeySvcMachine, &kusOwnerName, 0, &kBlobAuthentication, &pkBlobVersion, &khCli); else ulErr = RKeyrOpenKeyService(hRPCBinding, KeySvcMachine, &kusOwnerName, 0, &kBlobAuthentication, &pkBlobVersion, &khCli); if (ERROR_SUCCESS == ulErr) { // we've got an XP box. Return the KEYSVC_HANDLE to the client.
pKeySvcCliInfo->hKeySvc = khCli; } else if (ERROR_CALL_NOT_IMPLEMENTED == ulErr) { // we have a post-XP box -- that's fine.
ulErr = ERROR_SUCCESS; } else { // unexpected, we'll give up.
} } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) { // handle only the RPC exceptions
// We encountered an exception trying to contact the remote computer --
// give up and return the error to the user.
ulErr = RpcExceptionCode(); } RpcEndExcept; if (ERROR_SUCCESS == ulErr) { break; }
next: if (NULL != hRPCBinding) { // If we're talking to an XP box, free server data:
if (NULL != pKeySvcCliInfo->hKeySvc) { PKEYSVC_BLOB pTmpReserved = NULL; KeyrCloseKeyService(hRPCBinding, pKeySvcCliInfo->hKeySvc, &pTmpReserved); pKeySvcCliInfo->hKeySvc = NULL; }
// close the RPC binding
RpcBindingFree(&hRPCBinding); hRPCBinding = NULL; }
if (NULL != pStringBinding) { RpcStringFree(&pStringBinding); pStringBinding = NULL; } }
if (ERROR_SUCCESS != ulErr) { // the server's a) not up, b) not supporting mutual auth, or c) not a compatibile version
goto Ret; } ulErr = ERROR_SUCCESS; *phKeySvcCli = pKeySvcCliInfo; Ret: __try { if (pStringBinding) RpcStringFree(&pStringBinding); if (ERROR_SUCCESS != ulErr) { // If we're talking to an XP box, free server data:
if (NULL != pKeySvcCliInfo) { if (NULL != pKeySvcCliInfo->hRPCBinding && NULL != pKeySvcCliInfo->hKeySvc) { PKEYSVC_BLOB pTmpReserved = NULL; KeyrCloseKeyService(pKeySvcCliInfo->hRPCBinding, pKeySvcCliInfo->hKeySvc, &pTmpReserved); } LocalFree(pKeySvcCliInfo); }
// close the RPC binding
if (NULL != hRPCBinding) { RpcBindingFree(&hRPCBinding); } } } __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 (FALSE /*local key svc*/, pszMachineName, OwnerType, pwszOwnerName, TRUE, pReserved, phKeySvcCli); } 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;
if (NULL != pKeySvcCliInfo->hRPCBinding) { if (NULL != pKeySvcCliInfo->hKeySvc) { ulErr = KeyrCloseKeyService(pKeySvcCliInfo->hRPCBinding, pKeySvcCliInfo->hKeySvc, &pTmpReserved); } RpcBindingFree(&pKeySvcCliInfo->hRPCBinding); } LocalFree(hKeySvcCli); } __except ( EXCEPTION_EXECUTE_HANDLER ) { ulErr = _exception_code(); } Ret: return ulErr; }
// 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*/, //RESERVED: must be NULL (we don't support remote machine enrollment anymore)
/* [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 = CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNKNOWN; 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; // Ensure that we don't have a blob longer than allowed by our interface:
assert(CertBlob.pb < 128*1024); } } // 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); } } __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); } if (NULL != pdwStatus) { *pdwStatus = (DWORD)ulKeySvcStatus; }
} __except ( EXCEPTION_EXECUTE_HANDLER ) { return _exception_code(); } return dwErr; }
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; }
extern "C" ULONG RKeyOpenKeyService (/* [in] */ LPSTR pszMachineName, /* [in] */ KEYSVC_TYPE OwnerType, /* [in] */ LPWSTR pwszOwnerName, /* [in] */ void *ulFlags, /* [out][in] */ void *pReserved, /* [out] */ KEYSVCC_HANDLE *phKeySvcCli) { return KeyOpenKeyServiceEx (TRUE /*remote key svc*/, pszMachineName, OwnerType, pwszOwnerName, (0 != (PtrToUlong(ulFlags) & RKEYSVC_CONNECT_SECURE_ONLY)), pReserved, phKeySvcCli); }
extern "C" ULONG RKeyCloseKeyService( /* [in] */ KEYSVCC_HANDLE hKeySvcCli, /* [out][in] */ void *pReserved) { return KeyCloseKeyService(hKeySvcCli, pReserved); }
extern "C" ULONG RKeyPFXInstall (/* [in] */ KEYSVCC_HANDLE hKeySvcCli, /* [in] */ PKEYSVC_BLOB pPFX, /* [in] */ PKEYSVC_UNICODE_STRING pPassword, /* [in] */ ULONG ulFlags) { PKEYSVCC_INFO pKeySvcCliInfo = 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; }
|