|
|
#include "wzrdpvk.h"
#include "certca.h"
#include "cautil.h"
#include "CertRequesterContext.h"
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//
// LocalContext Implementation.
// See CertRequestContext.h for method-level documentation.
//
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT LocalContext::BuildCSPList() { DWORD dwIndex = 0; DWORD dwProviderType = 0; DWORD cbSize = 0; HRESULT hr = E_FAIL; LPWSTR pwszProviderName = 0; if (NULL == m_pCertWizardInfo) return E_POINTER;
//free the old memory
FreeProviders(m_pCertWizardInfo->dwCSPCount, m_pCertWizardInfo->rgdwProviderType, m_pCertWizardInfo->rgwszProvider); m_pCertWizardInfo->dwCSPCount = 0; m_pCertWizardInfo->rgdwProviderType = NULL; m_pCertWizardInfo->rgwszProvider = NULL;
for (dwIndex = 0; CryptEnumProvidersU(dwIndex, 0, 0, &dwProviderType, NULL, &cbSize); dwIndex++) { pwszProviderName = (LPWSTR)WizardAlloc(cbSize); if(NULL == pwszProviderName) goto MemoryErr; //get the provider name and type
if(!CryptEnumProvidersU (dwIndex, 0, 0, &dwProviderType, pwszProviderName, &cbSize)) goto CryptEnumProvidersUError; m_pCertWizardInfo->dwCSPCount = dwIndex + 1; m_pCertWizardInfo->rgdwProviderType = (DWORD *)WizardRealloc (m_pCertWizardInfo->rgdwProviderType, sizeof(DWORD) * m_pCertWizardInfo->dwCSPCount);
if(NULL == m_pCertWizardInfo->rgdwProviderType) goto MemoryErr;
m_pCertWizardInfo->rgwszProvider = (LPWSTR *)WizardRealloc (m_pCertWizardInfo->rgwszProvider, sizeof(LPWSTR) * m_pCertWizardInfo->dwCSPCount);
if(NULL == m_pCertWizardInfo->rgwszProvider) goto MemoryErr;
(m_pCertWizardInfo->rgdwProviderType)[dwIndex] = dwProviderType; (m_pCertWizardInfo->rgwszProvider)[dwIndex] = pwszProviderName;
// Our only reference to this data should now be m_pCertWizardInfo->rgwszProvider.
pwszProviderName = NULL; }
//we should have some CSPs
if(0 == m_pCertWizardInfo->dwCSPCount) goto FailErr; hr = S_OK; CommonReturn: return hr; ErrorReturn: if (NULL != pwszProviderName) { WizardFree(pwszProviderName); }
//free the old memory
FreeProviders(m_pCertWizardInfo->dwCSPCount, m_pCertWizardInfo->rgdwProviderType, m_pCertWizardInfo->rgwszProvider);
m_pCertWizardInfo->dwCSPCount = 0; m_pCertWizardInfo->rgdwProviderType = NULL; m_pCertWizardInfo->rgwszProvider = NULL;
goto CommonReturn;
SET_HRESULT(CryptEnumProvidersUError, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(MemoryErr, E_OUTOFMEMORY); SET_HRESULT(FailErr, E_FAIL); }
BOOL LocalContext::CheckAccessPermission(IN HCERTTYPE hCertType) { BOOL fResult = FALSE; HANDLE hClientToken = NULL; HRESULT hr = E_FAIL;
// First attempts to get the thread token. If this fails, acquires the
// process token. Finally, if that fails, returns NULL.
if (0 != (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_ALLOW_ALL_TEMPLATES)) { fResult = TRUE; } else { hClientToken = this->GetClientIdentity(); if (NULL == hClientToken) goto GetClientIdentityError;
__try { fResult = S_OK == CACertTypeAccessCheck(hCertType, hClientToken); } __except(EXCEPTION_EXECUTE_HANDLER) { goto CACertTypeAccessCheckError; } }
CommonReturn: if (NULL != hClientToken) { CloseHandle(hClientToken); } return fResult;
ErrorReturn: fResult = FALSE; goto CommonReturn;
SET_HRESULT(CACertTypeAccessCheckError, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(GetClientIdentityError, HRESULT_FROM_WIN32(GetLastError())); }
BOOL LocalContext::CheckCAPermission(IN HCAINFO hCAInfo) { BOOL fResult = FALSE; HANDLE hClientToken = NULL; HRESULT hr = E_FAIL;
if (0 != (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_ALLOW_ALL_CAS)) { fResult = TRUE; } else { hClientToken = this->GetClientIdentity(); if (NULL == hClientToken) goto GetClientIdentityError;
__try { fResult = S_OK == CAAccessCheck(hCAInfo, hClientToken); } __except(EXCEPTION_EXECUTE_HANDLER) { goto CAAccessCheckError; } }
CommonReturn: if (NULL != hClientToken) { CloseHandle(hClientToken); } return fResult;
ErrorReturn: fResult = FALSE; goto CommonReturn;
SET_HRESULT(CAAccessCheckError, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(GetClientIdentityError, HRESULT_FROM_WIN32(GetLastError())); }
HRESULT LocalContext::GetDefaultCSP(OUT BOOL *pfAllocateCSP) { DWORD cbData = 0; HCRYPTPROV hProv = NULL; HRESULT hr = E_FAIL; LPSTR pszName = NULL; LPWSTR pwszName = NULL;
if (NULL == m_pCertWizardInfo) return E_POINTER;
if (NULL == pfAllocateCSP) return E_INVALIDARG;
*pfAllocateCSP = FALSE;
//no provider has been selected
if(0 == m_pCertWizardInfo->dwProviderType) return S_OK;
//return if user has selected both the dwProviderType
//or the provider name
if(NULL != m_pCertWizardInfo->pwszProvider) return S_OK;
//get the default provider
if(!CryptAcquireContext(&hProv, NULL, NULL, m_pCertWizardInfo->dwProviderType, CRYPT_VERIFYCONTEXT)) goto Win32Err; //get the provider name
if(!CryptGetProvParam(hProv, PP_NAME, NULL, &cbData, 0) || (0==cbData)) goto Win32Err;
if(NULL == (pszName = (LPSTR)WizardAlloc(cbData))) goto MemoryErr;
if(!CryptGetProvParam(hProv, PP_NAME, (BYTE *)pszName, &cbData, 0)) goto Win32Err; pwszName = MkWStr(pszName); if(NULL == pwszName) goto MemoryErr;
m_pCertWizardInfo->pwszProvider=(LPWSTR)WizardAlloc(sizeof(WCHAR) * (wcslen(pwszName)+1)); if(NULL == m_pCertWizardInfo->pwszProvider) goto MemoryErr;
*pfAllocateCSP = TRUE; wcscpy(m_pCertWizardInfo->pwszProvider,pwszName);
hr = S_OK;
CommonReturn: if(NULL != hProv) { CryptReleaseContext(hProv, 0); } if(NULL != pszName) { WizardFree(pszName); } if(NULL != pwszName) { FreeWStr(pwszName); }
return hr;
ErrorReturn: m_idsText = IDS_INVALID_CSP; goto CommonReturn;
SET_HRESULT(Win32Err, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(MemoryErr, E_OUTOFMEMORY); }
HRESULT LocalContext::Enroll(OUT DWORD *pdwStatus, OUT HANDLE *pResult) { BOOL fHasNextCSP = TRUE; BOOL fHasNextCA = TRUE; BOOL fRequestIsCached; BOOL fCreateRequest; BOOL fFreeRequest; BOOL fSubmitRequest; CERT_BLOB renewCert; CERT_ENROLL_INFO RequestInfo; CERT_REQUEST_PVK_NEW CertRequestPvkNew; CERT_REQUEST_PVK_NEW CertRenewPvk; CRYPTUI_WIZ_CERT_CA CertCA; DWORD dwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNKNOWN; DWORD dwCSPIndex; DWORD dwSavedGenKeyFlags; HANDLE hRequest = NULL; HRESULT hr = E_FAIL; LPWSTR pwszHashAlg = NULL;
//init 1st for error jump
ZeroMemory(&CertRenewPvk, sizeof(CertRenewPvk));
if (NULL == pResult) return E_INVALIDARG; if (NULL == m_pCertWizardInfo) return E_POINTER;
memset(&CertCA, 0, sizeof(CertCA)); memset(&RequestInfo, 0, sizeof(RequestInfo));
dwSavedGenKeyFlags = m_pCertWizardInfo->dwGenKeyFlags;
fCreateRequest = 0 == (m_pCertWizardInfo->dwFlags & (CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY)); fFreeRequest = 0 == (m_pCertWizardInfo->dwFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY)); fSubmitRequest = 0 == (m_pCertWizardInfo->dwFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_FREE_ONLY));
// An invalid combination of flags was specified.
if (FALSE == (fCreateRequest || fFreeRequest || fSubmitRequest)) return E_INVALIDARG;
// For FREE_ONLY and SUBMIT_ONLY, copy the request from the IN parameter.
if (0 != ((CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY) & m_pCertWizardInfo->dwFlags)) { if (NULL == *pResult) return E_INVALIDARG;
hRequest = *pResult; }
// Initialize to false ... we need the marshalled parameters to know whether we can cache the request.
fRequestIsCached = FALSE;
// Iterate over each CA, performing a create and submit operation for each.
// Note that we can cache requests for certs if key archival is not needed.
//
if (fCreateRequest || fSubmitRequest) { for (IEnumCA CAEnumerator(m_pCertWizardInfo); TRUE; ) { if (S_OK != (CAEnumerator.Next(&CertCA))) { if (!FAILED(hr)) hr=E_FAIL;
if (E_FAIL == hr) m_pCertWizardInfo->idsText = IDS_NO_CA_FOR_ENROLL_REQUEST_FAILED;
goto ErrorReturn; }
// Create a certificate request only if
// 1) This is not a submit-only or a free-only operation.
// 2) We don't already have a cached request.
// (We can cache requests which don't require key archival on the CA).
//
// The request is created by looping over available CSPs until one successfully generates
// the request.
//
if (TRUE == fCreateRequest && FALSE == fRequestIsCached) { BOOL fHasNextCSP = TRUE; for (IEnumCSP CSPEnumerator(m_pCertWizardInfo); fHasNextCSP; ) { _JumpCondition(S_OK != (hr = CSPEnumerator.Next(&dwCSPIndex)), ErrorReturn); _JumpCondition(S_OK != (hr = CSPEnumerator.HasNext(&fHasNextCSP)), ErrorReturn); // Each call to MarshallRequestParameters can change the dwGenKeyFlags of pCertWizardInfo
// if the CSP does not support the min key size contained in this field.
// As a result, we must reset the dwGenKeyFlags field to the desired value
// before every call to MarshallRequestParameters.
m_pCertWizardInfo->dwGenKeyFlags = dwSavedGenKeyFlags; if (S_OK != (hr = ::MarshallRequestParameters (dwCSPIndex, m_pCertWizardInfo, &renewCert, &CertRequestPvkNew, &CertRenewPvk, &pwszHashAlg, &RequestInfo))) goto NextCSP; if (NULL != hRequest) { ::FreeRequest(hRequest); hRequest = NULL; }
hr = ::CreateRequest (m_pCertWizardInfo->dwFlags, m_pCertWizardInfo->dwPurpose, CertCA.pwszCAName, CertCA.pwszCALocation, ((CRYPTUI_WIZ_CERT_RENEW & m_pCertWizardInfo->dwPurpose) ? &renewCert : NULL), ((CRYPTUI_WIZ_CERT_RENEW & m_pCertWizardInfo->dwPurpose) ? &CertRenewPvk : NULL), m_pCertWizardInfo->fNewKey, &CertRequestPvkNew, pwszHashAlg, (LPWSTR)m_pCertWizardInfo->pwszDesStore, m_pCertWizardInfo->dwStoreFlags, &RequestInfo, &hRequest);
// Process the return value:
if (S_OK == hr) { // Success, get rid of whatever error text we have from past creations:
m_pCertWizardInfo->idsText = 0;
// We're done if we don't need to submit the request.
_JumpCondition(!fSubmitRequest, CommonReturn);
// Cache the request if we don't need support for key archival.
fRequestIsCached = 0 == (CertRequestPvkNew.dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL); break; } else if (E_ACCESSDENIED == HRESULT_FROM_WIN32(hr)) { // E_ACCESSDENIED could indicate one of several different error conditions. Map this
// to an resource identifier which details the possible causes of failure, and try again...
m_pCertWizardInfo->idsText = IDS_NO_ACCESS_TO_ICERTREQUEST2; } else if (NTE_BAD_ALGID == HRESULT_FROM_WIN32(hr)) { // NTE_BAD_ALGID indicates that the CSP didn't support the algorithm type required
// by the template. Map this to a resource identifier that details the possible causes
// of failure, and try again...
m_pCertWizardInfo->idsText = IDS_CSP_BAD_ALGTYPE; } else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == HRESULT_FROM_WIN32(hr)) { // The user cancelled the operation. Don't try to enroll any longer.
goto ErrorReturn; } else { // It's an error, but we don't need to map it to special text. Just keep processing...
}
// We're out of CSPs, and we haven't yet created the request!
if (!fHasNextCSP) { // If the template doesn't require key archival, we're done. Otherwise, we've got to
// try the other CAs. Note that if we had a mechanism for knowing whether it was the
// key archival step
if (0 == (CertRequestPvkNew.dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL)) goto ErrorReturn; else { ::FreeRequestParameters(&pwszHashAlg, &RequestInfo); goto NextCA; } }
NextCSP: ::FreeRequestParameters(&pwszHashAlg, &RequestInfo); } } // Submit the request only if this is not a create-only or a free-only operation:
//
if (TRUE == fSubmitRequest) { hr = ::SubmitRequest (hRequest, FALSE, m_pCertWizardInfo->dwPurpose, m_pCertWizardInfo->fConfirmation, m_pCertWizardInfo->hwndParent, (LPWSTR)m_pCertWizardInfo->pwszConfirmationTitle, m_pCertWizardInfo->idsConfirmTitle, CertCA.pwszCALocation, CertCA.pwszCAName, NULL, NULL, NULL, &dwStatus, (PCCERT_CONTEXT *)pResult); if (S_OK == hr) { // Success, get rid of whatever error text we have from past submits:
m_pCertWizardInfo->idsText = 0;
// If we've successfully submitted or pended
goto CommonReturn; } else if (E_ACCESSDENIED == HRESULT_FROM_WIN32(hr)) { // E_ACCESSDENIED could indicate one of several different error conditions. Map this
// to an resource identifier which details the possible causes of failure, and try again...
m_pCertWizardInfo->idsText = IDS_SUBMIT_NO_ACCESS_TO_ICERTREQUEST2; }
// Some error has occured.
// If it's a non-CA related error, give up...
_JumpCondition(dwStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR && dwStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED && dwStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED, ErrorReturn); // Otherwise, try another CA...
} NextCA:; } } CommonReturn: // Write the request to pResult for a create only operation:
if (hr == S_OK && 0 != (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_CREATE_ONLY)) { *pResult = hRequest; }
// Write the status code, if requested.
if (NULL != pdwStatus) { *pdwStatus = dwStatus; }
// Free resources.
if (NULL != hRequest && fFreeRequest) { ::FreeRequest(hRequest); } ::FreeRequestParameters(&pwszHashAlg, &RequestInfo); if (NULL != CertRenewPvk.pwszKeyContainer) { WizardFree((LPVOID)CertRenewPvk.pwszKeyContainer); } if (NULL != CertRenewPvk.pwszProvider) { WizardFree((LPVOID)CertRenewPvk.pwszProvider); }
return hr;
ErrorReturn: goto CommonReturn; }
HRESULT LocalContext::QueryRequestStatus(IN HANDLE hRequest, OUT CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO *pQueryInfo) { HRESULT hr;
if (!QueryRequest(hRequest, pQueryInfo)) goto QueryRequestError;
hr = S_OK; ErrorReturn: return hr;
SET_HRESULT(QueryRequestError, GetLastError()); }
HRESULT KeySvcContext::QueryRequestStatus(IN HANDLE hRequest, OUT CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO *pQueryInfo) { DWORD dwErr = 0; DWORD dwIndex = 0; HRESULT hr = E_FAIL; KEYSVCC_HANDLE hKeyService = NULL; KEYSVC_TYPE dwServiceType = KeySvcMachine; LPSTR pszMachineName = NULL; PKEYSVC_PROVIDER_INFO pProviderInfo = NULL; ULONG cProvider = 0;
if (NULL == m_pCertWizardInfo) return E_POINTER;
if (0 != (hr = ::KeyOpenKeyService(pszMachineName, dwServiceType, (LPWSTR)(m_pCertWizardInfo->pwszAccountName), // Service name if necessary
NULL, // no authentication string right now
NULL, &hKeyService))) goto KeyOpenKeyServiceError;
if (0 != (hr = ::KeyQueryRequestStatus(hKeyService, hRequest, pQueryInfo))) goto KeyQueryRequestStatusError;
hr = S_OK; ErrorReturn: if (NULL != hKeyService) { KeyCloseKeyService(hKeyService, NULL); } if (NULL != pszMachineName) { FreeMBStr(NULL,pszMachineName); } return hr;
TRACE_ERROR(KeyOpenKeyServiceError); TRACE_ERROR(KeyQueryRequestStatusError); } HRESULT LocalContext::Initialize() { return S_OK; }
HANDLE LocalContext::GetClientIdentity() { HANDLE hHandle = NULL; HANDLE hClientToken = NULL; HANDLE hProcessToken = NULL; HRESULT hr;
// Step 1: attempt to acquire the thread token.
hHandle = GetCurrentThread(); if (NULL == hHandle) goto GetThreadTokenError; if (!OpenThreadToken(hHandle, TOKEN_QUERY, TRUE, // open as self
&hClientToken)) goto GetThreadTokenError; // We got the thread token:
goto GetThreadTokenSuccess; // Step 2: we've failed to acquire the thread token,
// try to get the process token.
GetThreadTokenError: if (hHandle != NULL) { CloseHandle(hHandle); } // We failed to get the thread token, now try to acquire the process token:
hHandle = GetCurrentProcess(); if (NULL == hHandle) goto GetProcessHandleError; if (!OpenProcessToken(hHandle, TOKEN_DUPLICATE, &hProcessToken)) goto OpenProcessTokenError; if(!DuplicateToken(hProcessToken, SecurityImpersonation, &hClientToken)) goto DuplicateTokenError; GetThreadTokenSuccess: CommonReturn: if (NULL != hHandle) { CloseHandle(hHandle); } if (NULL != hProcessToken) { CloseHandle(hProcessToken); } return hClientToken; ErrorReturn: goto CommonReturn; SET_HRESULT(DuplicateTokenError, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(GetProcessHandleError, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(OpenProcessTokenError, HRESULT_FROM_WIN32(GetLastError())); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//
// KeySvcContext Implementation.
// See requesters.h for method-level documentation.
//
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT KeySvcContext::BuildCSPList() { DWORD dwErr = 0; DWORD dwIndex = 0; HRESULT hr = E_FAIL; KEYSVCC_HANDLE hKeyService = NULL; KEYSVC_TYPE dwServiceType = KeySvcMachine; LPSTR pszMachineName = NULL; PKEYSVC_PROVIDER_INFO pProviderInfo = NULL; ULONG cProvider = 0; if (NULL == m_pCertWizardInfo) return E_POINTER;
// Free the memory currently associated with the CSP fields:
FreeProviders(m_pCertWizardInfo->dwCSPCount, m_pCertWizardInfo->rgdwProviderType, m_pCertWizardInfo->rgwszProvider);
m_pCertWizardInfo->dwCSPCount = 0; m_pCertWizardInfo->rgdwProviderType = NULL; m_pCertWizardInfo->rgwszProvider = NULL;
//get the psz machine name
if(NULL == m_pCertWizardInfo->pwszMachineName) goto FailErr;
if(!MkMBStr(NULL, 0, m_pCertWizardInfo->pwszMachineName, &pszMachineName)) goto MkMBStrError;
//connect to the key service
dwServiceType = NULL != m_pCertWizardInfo->pwszAccountName ? KeySvcService : KeySvcMachine;
if (0 != (hr = ::KeyOpenKeyService(pszMachineName, dwServiceType, (LPWSTR)(m_pCertWizardInfo->pwszAccountName), // Service name if necessary
NULL, // no authentication string right now
NULL, &hKeyService))) goto KeyOpenKeyServiceError; //get the providers
if(0 != (hr = KeyEnumerateProviders (hKeyService, NULL, &cProvider, &pProviderInfo))) goto KeyEnumerateProvidersError;
//copy the provider information
m_pCertWizardInfo->dwCSPCount = cProvider; m_pCertWizardInfo->rgdwProviderType = (DWORD *)WizardAlloc(sizeof(DWORD) * cProvider); if (NULL == m_pCertWizardInfo->rgdwProviderType) goto MemoryErr; memset(m_pCertWizardInfo->rgdwProviderType, 0, sizeof(DWORD) * cProvider); m_pCertWizardInfo->rgwszProvider = (LPWSTR *)WizardAlloc(sizeof(LPWSTR) * cProvider); if (NULL == m_pCertWizardInfo->rgwszProvider) goto MemoryErr;
memset(m_pCertWizardInfo->rgwszProvider, 0, sizeof(LPWSTR) * cProvider); for(dwIndex=0; dwIndex < cProvider; dwIndex++) { (m_pCertWizardInfo->rgdwProviderType)[dwIndex] = pProviderInfo[dwIndex].ProviderType; (m_pCertWizardInfo->rgwszProvider)[dwIndex] = WizardAllocAndCopyWStr((LPWSTR)(pProviderInfo[dwIndex].Name.Buffer)); if (NULL == (m_pCertWizardInfo->rgwszProvider)[dwIndex]) goto MemoryErr; }
//we should have some CSPs
if(0 == m_pCertWizardInfo->dwCSPCount) goto FailErr;
hr = S_OK;
CommonReturn: if (NULL != hKeyService) { KeyCloseKeyService(hKeyService, NULL); } if (NULL != pszMachineName) { FreeMBStr(NULL,pszMachineName); } if (NULL != pProviderInfo) { WizardFree(pProviderInfo); }
return hr;
ErrorReturn: // Free and invalidate our provider lists:
FreeProviders(m_pCertWizardInfo->dwCSPCount, m_pCertWizardInfo->rgdwProviderType, m_pCertWizardInfo->rgwszProvider);
m_pCertWizardInfo->dwCSPCount = 0; m_pCertWizardInfo->rgdwProviderType = NULL; m_pCertWizardInfo->rgwszProvider = NULL;
goto CommonReturn;
SET_HRESULT(FailErr, E_FAIL); SET_HRESULT(KeyEnumerateProvidersError, HRESULT_FROM_WIN32(hr)); SET_HRESULT(KeyOpenKeyServiceError, HRESULT_FROM_WIN32(hr)); SET_HRESULT(MemoryErr, E_OUTOFMEMORY); SET_HRESULT(MkMBStrError, HRESULT_FROM_WIN32(GetLastError())); }
BOOL KeySvcContext::CheckAccessPermission(IN HCERTTYPE hCertType) { BOOL fResult = FALSE; LPWSTR *awszCurrentType = NULL; LPWSTR *awszTypeName = NULL; if (NULL == m_pCertWizardInfo) { SetLastError(E_POINTER); return FALSE; }
if (0 != (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_ALLOW_ALL_TEMPLATES)) { return TRUE; }
if(NULL != m_pCertWizardInfo->awszAllowedCertTypes) { if(S_OK == CAGetCertTypeProperty(hCertType, CERTTYPE_PROP_DN, &awszTypeName)) { if(NULL != awszTypeName) { if(NULL != awszTypeName[0]) { awszCurrentType = m_pCertWizardInfo->awszAllowedCertTypes;
while(NULL != *awszCurrentType) { if(wcscmp(*awszCurrentType, awszTypeName[0]) == 0) { return TRUE; } awszCurrentType++; } } CAFreeCertTypeProperty(hCertType, awszTypeName); } } }
return FALSE; }
BOOL KeySvcContext::CheckCAPermission(IN HCAINFO hCAInfo) { LPWSTR *wszCAName = NULL; LPWSTR *wszCurrentCA = NULL; if (NULL == m_pCertWizardInfo) { SetLastError(E_POINTER); return FALSE; }
if (0 != (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_ALLOW_ALL_CAS)) { return TRUE; }
if (NULL != m_pCertWizardInfo->awszValidCA) { if(S_OK == CAGetCAProperty(hCAInfo, CA_PROP_NAME, &wszCAName)) { if(NULL != wszCAName) { if(NULL != wszCAName[0]) { wszCurrentCA = m_pCertWizardInfo->awszValidCA; while(*wszCurrentCA) { if(0 == wcscmp(*wszCurrentCA, wszCAName[0])) { return TRUE; } wszCurrentCA++; } } CAFreeCAProperty(hCAInfo, wszCAName); } } }
return FALSE; }
HRESULT KeySvcContext::GetDefaultCSP(OUT BOOL *pfAllocateCSP) { DWORD dwDefaultFlag = 0; HRESULT hr = E_FAIL; LPSTR pszMachineName = NULL; LPWSTR pwszName = NULL; KEYSVC_TYPE dwServiceType = KeySvcMachine; KEYSVCC_HANDLE hKeyService = NULL; PKEYSVC_PROVIDER_INFO pKeyProviderInfo = NULL;
if (NULL == m_pCertWizardInfo) return E_POINTER;
if (NULL == pfAllocateCSP) return E_INVALIDARG;
*pfAllocateCSP = FALSE;
//no provider has been selected
if(0 == m_pCertWizardInfo->dwProviderType) return S_OK;
//return if user has selected both the dwProviderType
//or the provider name
if(NULL != m_pCertWizardInfo->pwszProvider) return S_OK;
//get the psz machine name
if(NULL == m_pCertWizardInfo->pwszMachineName) goto InvalidArgErr;
if(!MkMBStr(NULL, 0, m_pCertWizardInfo->pwszMachineName, &pszMachineName)) goto Win32Err;
dwServiceType = NULL != m_pCertWizardInfo->pwszAccountName ? KeySvcService : KeySvcMachine;
//connect to the key service
if (0 != (hr = KeyOpenKeyService (pszMachineName, dwServiceType, (LPWSTR)(m_pCertWizardInfo->pwszAccountName), // Service name if necessary
NULL, // no authentication string right now
NULL, &hKeyService))) { m_idsText = IDS_RPC_CALL_FAILED; goto Win32Err; }
//get the default provider name
if(0 != (hr = KeyGetDefaultProvider (hKeyService, m_pCertWizardInfo->dwProviderType, 0, NULL, &dwDefaultFlag, &pKeyProviderInfo))) { m_idsText = IDS_RPC_CALL_FAILED; goto Win32Err; }
pwszName = (LPWSTR)(pKeyProviderInfo->Name.Buffer); if(NULL == pwszName) goto FailErr;
m_pCertWizardInfo->pwszProvider = (LPWSTR)WizardAlloc(sizeof(WCHAR) * (wcslen(pwszName)+1)); if(NULL == m_pCertWizardInfo->pwszProvider) goto MemoryErr;
*pfAllocateCSP = TRUE; wcscpy(m_pCertWizardInfo->pwszProvider, pwszName);
hr = S_OK;
CommonReturn: if (NULL != pKeyProviderInfo) { WizardFree(pKeyProviderInfo); } if (NULL != hKeyService) { KeyCloseKeyService(hKeyService, NULL); } if (NULL != pszMachineName) { FreeMBStr(NULL,pszMachineName); }
return hr;
ErrorReturn: goto CommonReturn;
SET_HRESULT(InvalidArgErr, E_INVALIDARG); SET_HRESULT(Win32Err, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(MemoryErr, E_OUTOFMEMORY); SET_HRESULT(FailErr, E_FAIL); }
HRESULT WhistlerMachineContext::Enroll(OUT DWORD *pdwStatus, IN OUT HANDLE *pResult) { BOOL fRequestIsCached; BOOL fCreateRequest = 0 == (m_pCertWizardInfo->dwFlags & (CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY)); BOOL fFreeRequest = 0 == (m_pCertWizardInfo->dwFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY)); BOOL fSubmitRequest = 0 == (m_pCertWizardInfo->dwFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_FREE_ONLY)); CERT_BLOB renewCert; CERT_ENROLL_INFO RequestInfo; CERT_REQUEST_PVK_NEW CertRequestPvkNew; CERT_REQUEST_PVK_NEW CertRenewPvk; CRYPTUI_WIZ_CERT_CA CertCA; DWORD dwFlags; DWORD dwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNKNOWN; DWORD dwCSPIndex; DWORD dwSavedGenKeyFlags; HANDLE hRequest = NULL; HRESULT hr = E_FAIL; KEYSVCC_HANDLE hKeyService = NULL; KEYSVC_TYPE ktServiceType; LPSTR pszMachineName = NULL; LPWSTR pwszHashAlg = NULL;
//init 1st for error jump
ZeroMemory(&CertRenewPvk, sizeof(CertRenewPvk));
if (NULL == pResult) return E_INVALIDARG; if (NULL == m_pCertWizardInfo) return E_POINTER;
memset(&renewCert, 0, sizeof(renewCert)); memset(&CertCA, 0, sizeof(CertCA)); memset(&RequestInfo, 0, sizeof(RequestInfo));
dwSavedGenKeyFlags = m_pCertWizardInfo->dwGenKeyFlags;
// An invalid combination of flags was specified.
if (FALSE == (fCreateRequest || fFreeRequest || fSubmitRequest)) return E_INVALIDARG;
// For FREE_ONLY and SUBMIT_ONLY, copy the request from the IN parameter.
if (0 != ((CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY) & m_pCertWizardInfo->dwFlags)) { if (NULL == *pResult) return E_INVALIDARG;
hRequest = *pResult; }
if(!MkMBStr(NULL, 0, m_pCertWizardInfo->pwszMachineName, &pszMachineName)) goto MkMBStrError;
ktServiceType = NULL != m_pCertWizardInfo->pwszAccountName ? KeySvcService : KeySvcMachine;
hr = ::KeyOpenKeyService (pszMachineName, ktServiceType, (LPWSTR)(m_pCertWizardInfo->pwszAccountName), NULL, NULL, &hKeyService); _JumpConditionWithExpr(S_OK != hr, KeyOpenKeyServiceError, m_idsText = IDS_RPC_CALL_FAILED);
// Initialize to false ... we need the marshalled parameters to know whether we can cache the request.
fRequestIsCached = FALSE;
// Iterate over each CA, performing a create and submit operation for each.
// Note that we can cache requests for certs if key archival is not needed.
//
if (fCreateRequest || fSubmitRequest) { for (IEnumCA CAEnumerator(m_pCertWizardInfo); TRUE; ) { if (S_OK != (CAEnumerator.Next(&CertCA))) { if(!FAILED(hr)) hr=E_FAIL;
if (E_FAIL == hr) m_pCertWizardInfo->idsText = IDS_NO_CA_FOR_ENROLL_REQUEST_FAILED;
goto ErrorReturn; }
// Create a certificate request only if
// 1) This is not a submit-only or a free-only operation.
// 2) We don't already have a cached request.
// (We can cache requests which don't require key archival on the CA).
//
// The request is created by looping over available CSPs until one successfully generates
// the request.
//
if (TRUE == fCreateRequest && FALSE == fRequestIsCached) { BOOL fHasNextCSP = TRUE; for (IEnumCSP CSPEnumerator(m_pCertWizardInfo); fHasNextCSP; ) { _JumpCondition(S_OK != (hr = CSPEnumerator.Next(&dwCSPIndex)), ErrorReturn); _JumpCondition(S_OK != (hr = CSPEnumerator.HasNext(&fHasNextCSP)), ErrorReturn);
// Each call to MarshallRequestParameters can change the dwGenKeyFlags of pCertWizardInfo
// if the CSP does not support the min key size contained in this field.
// As a result, we must reset the dwGenKeyFlags field to the desired value
// before every call to MarshallRequestParameters.
m_pCertWizardInfo->dwGenKeyFlags = dwSavedGenKeyFlags; if (S_OK != (hr = ::MarshallRequestParameters (dwCSPIndex, m_pCertWizardInfo, &renewCert, &CertRequestPvkNew, &CertRenewPvk, &pwszHashAlg, &RequestInfo))) goto NextCSP;
if (NULL != hRequest) { this->FreeRequest(hKeyService, pszMachineName, &hRequest); hRequest = NULL; }
hr = this->CreateRequest (hKeyService, pszMachineName, CertCA.pwszCALocation, CertCA.pwszCAName, &CertRequestPvkNew, &renewCert, &CertRenewPvk, pwszHashAlg, &RequestInfo, &hRequest);
// Process the return value:
if (S_OK == hr) { // Success, get rid of whatever error text we have from past creations:
m_pCertWizardInfo->idsText = 0;
// We're done if we don't need to submit the request.
_JumpCondition(!fSubmitRequest, CommonReturn);
// Cache the request if we don't need support for key archival.
fRequestIsCached = 0 == (CertRequestPvkNew.dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL); break; } else if (E_ACCESSDENIED == HRESULT_FROM_WIN32(hr)) { // E_ACCESSDENIED could indicate one of several different error conditions. Map this
// to an resource identifier which details the possible causes of failure, and try again...
m_pCertWizardInfo->idsText = IDS_NO_ACCESS_TO_ICERTREQUEST2; } else if (NTE_BAD_ALGID == HRESULT_FROM_WIN32(hr)) { // NTE_BAD_ALGID indicates that the CSP didn't support the algorithm type required
// by the template. Map this to a resource identifier that details the possible causes
// of failure, and try again...
m_pCertWizardInfo->idsText = IDS_CSP_BAD_ALGTYPE; } else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == HRESULT_FROM_WIN32(hr)) { // The user cancelled the operation. Don't try to enroll any longer.
goto ErrorReturn; } else { // It's an error, but we don't need to map it to special text. Just keep processing...
} // We're out of CSPs, and we haven't yet created the request!
if (!fHasNextCSP) { // If the template doesn't require key archival, we're done. Otherwise, we've got to
// try the other CAs. Note that if we had a mechanism for knowing whether it was the
// key archival step
if (0 == (CertRequestPvkNew.dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL)) goto ErrorReturn; else { ::FreeRequestParameters(&pwszHashAlg, &RequestInfo); goto NextCA; } } NextCSP: ::FreeRequestParameters(&pwszHashAlg, &RequestInfo); } }
if (TRUE == fSubmitRequest) { hr = this->SubmitRequest (hKeyService, pszMachineName, CertCA.pwszCALocation, CertCA.pwszCAName, hRequest, (PCCERT_CONTEXT *)pResult, &dwStatus); if (S_OK == hr) { // Success, get rid of whatever error text we have from past submits:
m_pCertWizardInfo->idsText = 0;
// If we've successfully submitted or pended
goto CommonReturn; } else if (E_ACCESSDENIED == HRESULT_FROM_WIN32(hr)) { // E_ACCESSDENIED could indicate one of several different error conditions. Map this
// to an resource identifier which details the possible causes of failure, and try again...
m_pCertWizardInfo->idsText = IDS_SUBMIT_NO_ACCESS_TO_ICERTREQUEST2; } // Some error has occured.
// If it's a non-CA related error, give up...
_JumpCondition(dwStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR && dwStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED && dwStatus != CRYPTUI_WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED, ErrorReturn);
// Otherwise, try another CA...
} NextCA:; } }
CommonReturn: // Write the request to pResult for a create only operation:
if (hr == S_OK && 0 != (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_CREATE_ONLY)) { *pResult = hRequest; }
// Write the status code, if requested.
if (NULL != pdwStatus) { *pdwStatus = dwStatus; }
// Free resources.
if (NULL != hRequest && TRUE == fFreeRequest) { this->FreeRequest(hKeyService, pszMachineName, hRequest); } if (NULL != hKeyService) { ::KeyCloseKeyService(hKeyService, NULL); } if (NULL != pszMachineName) { ::FreeMBStr(NULL,pszMachineName); } if (NULL != CertRenewPvk.pwszKeyContainer) { WizardFree((LPVOID)CertRenewPvk.pwszKeyContainer); } if (NULL != CertRenewPvk.pwszProvider) { WizardFree((LPVOID)CertRenewPvk.pwszProvider); }
::FreeRequestParameters(&pwszHashAlg, &RequestInfo);
return hr;
ErrorReturn: goto CommonReturn;
SET_HRESULT(KeyOpenKeyServiceError, hr); SET_HRESULT(MkMBStrError, HRESULT_FROM_WIN32(GetLastError())); }
HRESULT WhistlerMachineContext::CreateRequest (IN KEYSVCC_HANDLE hKeyService, IN LPSTR pszMachineName, IN LPWSTR pwszCALocation, IN LPWSTR pwszCAName, IN PCERT_REQUEST_PVK_NEW pKeyNew, IN CERT_BLOB *pCert, IN PCERT_REQUEST_PVK_NEW pRenewKey, IN LPWSTR pwszHashAlg, IN PCERT_ENROLL_INFO pRequestInfo, OUT HANDLE *phRequest) { CERT_BLOB PKCS7Blob; CERT_BLOB renewCert; DWORD dwFlags = m_pCertWizardInfo->dwFlags;
dwFlags &= ~(CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY); dwFlags |= CRYPTUI_WIZ_CREATE_ONLY;
// Create the certificate request...
return ::KeyEnroll_V2 (hKeyService, pszMachineName, TRUE, m_pCertWizardInfo->dwPurpose, dwFlags, (LPWSTR)(m_pCertWizardInfo->pwszAccountName), NULL, (CRYPTUI_WIZ_CERT_ENROLL & m_pCertWizardInfo->dwPurpose) ? TRUE : FALSE, pwszCALocation, pwszCAName, m_pCertWizardInfo->fNewKey, pKeyNew, pCert, pRenewKey, pwszHashAlg, (LPWSTR)m_pCertWizardInfo->pwszDesStore, m_pCertWizardInfo->dwStoreFlags, pRequestInfo, (LPWSTR)m_pCertWizardInfo->pwszRequestString, 0, NULL, phRequest, NULL, NULL, NULL); }
HRESULT WhistlerMachineContext::SubmitRequest (IN KEYSVCC_HANDLE hKeyService, IN LPSTR pszMachineName, IN LPWSTR pwszCALocation, IN LPWSTR pwszCAName, IN HANDLE hRequest, OUT PCCERT_CONTEXT *ppCertContext, OUT DWORD *pdwStatus) { CERT_BLOB HashBlob; CERT_BLOB PKCS7Blob; HRESULT hr = E_FAIL;
memset(&HashBlob, 0, sizeof(HashBlob)); memset(&PKCS7Blob, 0, sizeof(PKCS7Blob));
DWORD dwFlags = m_pCertWizardInfo->dwFlags;
dwFlags &= ~(CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_FREE_ONLY); dwFlags |= CRYPTUI_WIZ_SUBMIT_ONLY;
// Submit the certificate request...
hr = ::KeyEnroll_V2 (hKeyService, pszMachineName, TRUE, m_pCertWizardInfo->dwPurpose, dwFlags, (LPWSTR)(m_pCertWizardInfo->pwszAccountName), NULL, (CRYPTUI_WIZ_CERT_ENROLL & m_pCertWizardInfo->dwPurpose) ? TRUE : FALSE, pwszCALocation, pwszCAName, m_pCertWizardInfo->fNewKey, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0, NULL, &hRequest, &PKCS7Blob, &HashBlob, pdwStatus); if (S_OK == hr && CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED == *pdwStatus) { hr = this->ToCertContext (&PKCS7Blob, &HashBlob, pdwStatus, ppCertContext); }
if (NULL != HashBlob.pbData) { ::WizardFree(HashBlob.pbData); } if (NULL != PKCS7Blob.pbData) { ::WizardFree(PKCS7Blob.pbData); }
return hr; }
void WhistlerMachineContext::FreeRequest (IN KEYSVCC_HANDLE hKeyService, IN LPSTR pszMachineName, IN HANDLE hRequest) { DWORD dwFlags = m_pCertWizardInfo->dwFlags;
dwFlags &= ~(CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY); dwFlags |= CRYPTUI_WIZ_FREE_ONLY;
::KeyEnroll_V2 (hKeyService, pszMachineName, TRUE, 0, dwFlags, NULL, NULL, FALSE, NULL, NULL, FALSE, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0, NULL, &hRequest, NULL, NULL, NULL); }
HRESULT KeySvcContext::ToCertContext(IN CERT_BLOB *pPKCS7Blob, IN CERT_BLOB *pHashBlob, OUT DWORD *pdwStatus, OUT PCCERT_CONTEXT *ppCertContext) { HCERTSTORE hCertStore = NULL; HRESULT hr = E_FAIL;
if (NULL == pPKCS7Blob || NULL == pHashBlob || NULL == ppCertContext) return E_INVALIDARG; //get the certificate store from the PKCS7 for the remote case
if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, pPKCS7Blob, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, NULL, &hCertStore, NULL, NULL)) { if (NULL != pdwStatus) { *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED; } goto FailError; }
//find the certificate based on the hash
if (NULL == (*ppCertContext = ::CertFindCertificateInStore (hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, pHashBlob, NULL))) { if (NULL != pdwStatus) { *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED; } goto FailError; }
hr = S_OK;
CommonReturn: if(NULL != hCertStore) { CertCloseStore(hCertStore, 0); } return hr;
ErrorReturn: if (NULL != pdwStatus && 0 == *pdwStatus) { *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_KEYSVC_FAILED; } goto CommonReturn;
SET_HRESULT(FailError, E_FAIL); }
HRESULT KeySvcContext::Initialize() { if (NULL == m_pCertWizardInfo) return E_POINTER;
// We don't need to download the list of allowed templates if we're not going
// to be performing the access check anyway.
if (0 == (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_ALLOW_ALL_TEMPLATES)) { //for the remote enrollment, we have to get the allowed cert type
//list from the key service.
if(!::GetCertTypeName(m_pCertWizardInfo)) { m_idsText = IDS_NO_VALID_CERT_TEMPLATE; return HRESULT_FROM_WIN32(GetLastError()); } }
// We don't need to download the list of allowed CAs if we're not going
// to be performing the access check anyway
if (0 == (m_pCertWizardInfo->dwFlags & CRYPTUI_WIZ_ALLOW_ALL_CAS)) { if(!::GetCAName(m_pCertWizardInfo)) { m_idsText = IDS_NO_CA_FOR_ENROLL; return HRESULT_FROM_WIN32(GetLastError()); } } return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//
// CertRequesterContext: implementation of abstract superclass.
// See requesters.h for method-level documentation.
//
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CertRequesterContext::MakeDefaultCertRequesterContext (OUT CertRequesterContext **ppRequesterContext) { CERT_WIZARD_INFO *pCertWizardInfo = NULL; HRESULT hr; pCertWizardInfo = (CERT_WIZARD_INFO *)WizardAlloc(sizeof(CERT_WIZARD_INFO)); _JumpCondition(NULL == pCertWizardInfo, MemoryError);
hr = MakeCertRequesterContext (NULL, NULL, 0, pCertWizardInfo, ppRequesterContext, NULL); _JumpCondition(S_OK != hr, MakeCertRequesterContextError);
hr = S_OK; CommonReturn: return hr;
ErrorReturn: if (NULL != pCertWizardInfo) { WizardFree(pCertWizardInfo); } goto CommonReturn;
SET_HRESULT(MakeCertRequesterContextError, hr); SET_HRESULT(MemoryError, E_OUTOFMEMORY); }
HRESULT CertRequesterContext::MakeCertRequesterContext (IN LPCWSTR pwszAccountName, IN LPCWSTR pwszMachineName, IN DWORD dwCertOpenStoreFlags, IN CERT_WIZARD_INFO *pCertWizardInfo, OUT CertRequesterContext **ppRequesterContext, OUT UINT *pIDSText) { BOOL fMachine = FALSE; DWORD const dwLocalUserNameSize = UNLEN + 1; DWORD const dwLocalMachineNameSize = MAX_COMPUTERNAME_LENGTH + 1; HRESULT hr = E_FAIL; UINT idsText = NULL == pIDSText ? 0 : *pIDSText; WCHAR wszLocalUserName[dwLocalUserNameSize] = { 0 }; WCHAR wszLocalMachineName[dwLocalMachineNameSize] = { 0 };
// Input validation:
if (NULL == pCertWizardInfo || NULL == ppRequesterContext) return E_INVALIDARG; // Should not have assigned values to these fields yet:
if (NULL != pCertWizardInfo->pwszAccountName || NULL != pCertWizardInfo->pwszMachineName) return E_INVALIDARG;
if(!GetUserNameU(wszLocalUserName, (DWORD *)&dwLocalUserNameSize)) { idsText=IDS_FAIL_TO_GET_USER_NAME; goto Win32Error; }
if(!GetComputerNameU(wszLocalMachineName, (DWORD *)&dwLocalMachineNameSize)) { idsText=IDS_FAIL_TO_GET_COMPUTER_NAME; goto Win32Error; }
// Map all unspecified values to defaults:
//
// Default #1: NULL pwszAccountName indicates current user _iff_ pwszMachineName is NULL.
if (NULL == pwszAccountName && NULL == pwszMachineName) { pwszAccountName = wszLocalUserName; }
// Default #2: NULL pwszMachineName indicates local machine.
if (NULL == pwszMachineName) { pwszMachineName = wszLocalMachineName; }
// Default #3: NULL pwszAccountName and non-NULL pwszMachineName indicates machine enrollment.
fMachine = (NULL == pwszAccountName || (0 != _wcsicmp(pwszAccountName, wszLocalUserName)) || (0 != _wcsicmp(pwszMachineName, wszLocalMachineName)));
// Default #4: dwCertOpenStoreFlags == 0 defaults to CERT_SYSTEM_STORE_LOCAL_MACHINE
// for machine enrollment, CERT_SYSTEM_STORE_CURRENT_USER for user enrollment.
if (0 == dwCertOpenStoreFlags) { dwCertOpenStoreFlags = fMachine ? CERT_SYSTEM_STORE_LOCAL_MACHINE : CERT_SYSTEM_STORE_CURRENT_USER; }
// Now that we've mapped unspecified values to defaults, assign the wizard's fields
// with these values:
//
if (NULL != pwszAccountName) { pCertWizardInfo->pwszAccountName = (LPWSTR)WizardAlloc(sizeof(WCHAR) * (wcslen(pwszAccountName) + 1)); _JumpConditionWithExpr(NULL == pCertWizardInfo->pwszAccountName, MemoryError, idsText = IDS_OUT_OF_MEMORY); wcscpy((LPWSTR)pCertWizardInfo->pwszAccountName, pwszAccountName); }
pCertWizardInfo->pwszMachineName = (LPWSTR)WizardAlloc(sizeof(WCHAR) * (wcslen(pwszMachineName) + 1)); _JumpConditionWithExpr(NULL == pCertWizardInfo->pwszMachineName, MemoryError, idsText = IDS_OUT_OF_MEMORY); wcscpy((LPWSTR)pCertWizardInfo->pwszMachineName, pwszMachineName);
pCertWizardInfo->fMachine = fMachine; pCertWizardInfo->dwStoreFlags = dwCertOpenStoreFlags;
// We need keysvc if:
//
// 1) We're doing machine enrollment (we need to run under the local machine's context).
// 2) An account _other_ than the current user on the local machine is specified.
// (we need to run under another user's context).
//
if (TRUE == fMachine) { KEYSVC_TYPE ktServiceType; KEYSVC_OPEN_KEYSVC_INFO OpenKeySvcInfo = { sizeof(KEYSVC_OPEN_KEYSVC_INFO), 0 }; KEYSVCC_HANDLE hKeyService = NULL; LPSTR pszMachineName = NULL;
ktServiceType = NULL != pwszAccountName ? KeySvcService : KeySvcMachine; _JumpConditionWithExpr(!MkMBStr(NULL, 0, pwszMachineName, &pszMachineName), MkMBStrError, idsText = IDS_OUT_OF_MEMORY);
// See if we're enrolling for a W2K or a Whistler machine:
hr = KeyOpenKeyService (pszMachineName, ktServiceType, (LPWSTR)pwszAccountName, NULL, &OpenKeySvcInfo, &hKeyService); _JumpConditionWithExpr(S_OK != hr, KeyOpenKeyServiceError, idsText = IDS_RPC_CALL_FAILED); switch (OpenKeySvcInfo.ulVersion) { case KEYSVC_VERSION_WHISTLER: *ppRequesterContext = new WhistlerMachineContext(pCertWizardInfo); break; case KEYSVC_VERSION_W2K: default: hr = E_UNEXPECTED; goto KeyOpenKeyServiceError; } } else { // We're requesting a cert for ourselves: we don't need keysvc.
*ppRequesterContext = new LocalContext(pCertWizardInfo); } if (NULL == *ppRequesterContext) goto MemoryError;
hr = S_OK;
CommonReturn: return hr;
ErrorReturn: if (NULL != pCertWizardInfo->pwszMachineName) { WizardFree((LPVOID)pCertWizardInfo->pwszMachineName); } if (NULL != pCertWizardInfo->pwszAccountName) { WizardFree((LPVOID)pCertWizardInfo->pwszAccountName); } pCertWizardInfo->pwszMachineName = NULL; pCertWizardInfo->pwszAccountName = NULL;
// Assign error text if specified:
if (NULL != pIDSText) { *pIDSText = idsText; } goto CommonReturn;
SET_HRESULT(MemoryError, E_OUTOFMEMORY); SET_HRESULT(KeyOpenKeyServiceError, hr); SET_HRESULT(MkMBStrError, HRESULT_FROM_WIN32(GetLastError())); SET_HRESULT(Win32Error, HRESULT_FROM_WIN32(GetLastError())); }
CertRequesterContext::~CertRequesterContext() { if (NULL != m_pCertWizardInfo) { if (NULL != m_pCertWizardInfo->pwszMachineName) { WizardFree((LPVOID)m_pCertWizardInfo->pwszMachineName); } if (NULL != m_pCertWizardInfo->pwszAccountName) { WizardFree((LPVOID)m_pCertWizardInfo->pwszAccountName); } m_pCertWizardInfo->pwszMachineName = NULL; m_pCertWizardInfo->pwszAccountName = NULL; } }
|