|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1999
//
// File: certhier.cpp
//
// Contents: Install cert server hierarchical
//
// History: 09-26-96
//
//--------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
// C Run-Time Includes
#include <stdlib.h>
#include <string.h>
#include <memory.h>
// Windows System Includes
#include <winsvc.h>
#include <rpc.h>
#include <tchar.h>
#include <csdisp.h>
#include <certca.h>
// Application Includes
#include "cscsp.h"
#include "certmsg.h"
#include "certhier.h"
#include "setupids.h"
#include "tfc.h"
#define __dwFILE__ __dwFILE_INITLIB_CERTHIER_CPP__
// following veriables are extern in initlib, bad.
LPSTR pszObjIdSignatureAlgorithm = szOID_OIWSEC_sha1RSASign;
HRESULT csiFillKeyProvInfo( IN WCHAR const *pwszContainerName, IN WCHAR const *pwszProvName, IN DWORD dwProvType, IN BOOL fMachineKeyset, OUT CRYPT_KEY_PROV_INFO *pKeyProvInfo) // call csiFreeKeyProvInfo to free
{ HRESULT hr; WCHAR *pwszContainerNameT = NULL; WCHAR *pwszProvNameT = NULL;
ZeroMemory(pKeyProvInfo, sizeof(*pKeyProvInfo));
hr = myDupString(pwszContainerName, &pwszContainerNameT); _JumpIfError(hr, error, "myDupString");
hr = myDupString(pwszProvName, &pwszProvNameT); _JumpIfError(hr, error, "myDupString");
pKeyProvInfo->pwszContainerName = pwszContainerNameT; pKeyProvInfo->pwszProvName = pwszProvNameT; pKeyProvInfo->dwProvType = dwProvType; if (fMachineKeyset) { pKeyProvInfo->dwFlags = CRYPT_MACHINE_KEYSET; } pKeyProvInfo->dwKeySpec = AT_SIGNATURE; pwszContainerNameT = NULL; pwszProvNameT = NULL; hr = S_OK;
error: if (NULL != pwszContainerNameT) { LocalFree(pwszContainerNameT); } if (NULL != pwszProvNameT) { LocalFree(pwszProvNameT); } return(hr); }
VOID csiFreeKeyProvInfo( IN OUT CRYPT_KEY_PROV_INFO *pKeyProvInfo) { if (NULL != pKeyProvInfo->pwszProvName) { LocalFree(pKeyProvInfo->pwszProvName); pKeyProvInfo->pwszProvName = NULL; } if (NULL != pKeyProvInfo->pwszContainerName) { LocalFree(pKeyProvInfo->pwszContainerName); pKeyProvInfo->pwszContainerName = NULL; } }
HRESULT GetCertServerKeyProviderInfo( IN WCHAR const *pwszSanitizedCAName, IN WCHAR const *pwszKeyContainerName, OUT ALG_ID *pidAlg, OUT BOOL *pfMachineKeyset, OUT CRYPT_KEY_PROV_INFO *pKeyProvInfo) // call csiFreeKeyProvInfo to free
{ HRESULT hr; WCHAR *pwszProvName = NULL; DWORD dwProvType;
ZeroMemory(pKeyProvInfo, sizeof(*pKeyProvInfo));
// get CSP info
hr = myGetCertSrvCSP( FALSE, // fEncryptionCSP
pwszSanitizedCAName, &dwProvType, &pwszProvName, pidAlg, pfMachineKeyset, NULL); // pdwKeySize
_JumpIfError(hr, error, "myGetCertSrvCSP");
hr = csiFillKeyProvInfo( pwszKeyContainerName, pwszProvName, dwProvType, *pfMachineKeyset, pKeyProvInfo); _JumpIfError(hr, error, "csiFillKeyProvInfo");
error: if (NULL != pwszProvName) { LocalFree(pwszProvName); } return(hr); }
HRESULT mySetCertRegKeyIndexAndContainer( IN WCHAR const *pwszSanitizedCAName, IN DWORD iKey, IN WCHAR const *pwszKeyContainer) { HRESULT hr; hr = mySetCertRegDWValue( pwszSanitizedCAName, NULL, NULL, wszREGREQUESTKEYINDEX, iKey); _JumpIfErrorStr(hr, error, "mySetCertRegDWValue", wszREGREQUESTKEYINDEX);
hr = mySetCertRegStrValue( pwszSanitizedCAName, NULL, NULL, wszREGREQUESTKEYCONTAINER, pwszKeyContainer); _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", wszREGREQUESTKEYCONTAINER);
error: return(hr); }
HRESULT myGetCertRegKeyIndexAndContainer( IN WCHAR const *pwszSanitizedCAName, OUT DWORD *piKey, OUT WCHAR **ppwszKeyContainer) { HRESULT hr; *ppwszKeyContainer = NULL;
hr = myGetCertRegDWValue( pwszSanitizedCAName, NULL, NULL, wszREGREQUESTKEYINDEX, piKey); if (S_OK != hr) { if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr) { _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGREQUESTKEYINDEX); } *piKey = 0; }
hr = myGetCertRegStrValue( pwszSanitizedCAName, NULL, NULL, wszREGREQUESTKEYCONTAINER, ppwszKeyContainer); if (S_OK != hr) { if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr) { _JumpErrorStr(hr, error, "myGetCertRegStrValue", wszREGREQUESTKEYCONTAINER); } hr = myDupString(pwszSanitizedCAName, ppwszKeyContainer); _JumpIfError(hr, error, "myDupString"); } CSASSERT(S_OK == hr);
error: return(hr); }
HRESULT FinishSuspendedSetupFromPKCS7( IN HINSTANCE hInstance, IN BOOL fUnattended, IN HWND hwnd, IN WCHAR const *pwszSanitizedCAName, IN OPTIONAL WCHAR const *pwszKeyContainer, IN DWORD iKey, IN BOOL fRenew, IN BYTE const *pbChain, IN DWORD cbChain) { HRESULT hr; CRYPT_KEY_PROV_INFO KeyProvInfo; WCHAR *pwszCommonName = NULL; WCHAR *pwszServerName = NULL; WCHAR *pwszCertFile = NULL; WCHAR *pwszKeyContainerReg = NULL; ENUM_CATYPES CAType; DWORD iCertNew; BOOL fUseDS; ALG_ID idAlg; BOOL fMachineKeyset;
ZeroMemory(&KeyProvInfo, sizeof(KeyProvInfo));
hr = myGetCARegHashCount(pwszSanitizedCAName, CSRH_CASIGCERT, &iCertNew); _JumpIfError(hr, error, "myGetCARegHashCount");
if (NULL == pwszKeyContainer) { // get Key Index and Container name from registry
hr = myGetCertRegKeyIndexAndContainer( pwszSanitizedCAName, &iKey, &pwszKeyContainerReg); _JumpIfError(hr, error, "myGetCertRegKeyIndexAndContainer");
pwszKeyContainer = pwszKeyContainerReg; }
// get CSP info
hr = GetCertServerKeyProviderInfo( pwszSanitizedCAName, pwszKeyContainer, &idAlg, &fMachineKeyset, &KeyProvInfo); _JumpIfError(hr, error, "GetCertServerKeyProviderInfo");
// get common name
hr = myGetCertRegStrValue( pwszSanitizedCAName, NULL, NULL, wszREGCOMMONNAME, &pwszCommonName); _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCOMMONNAME);
// get ca type
hr = myGetCertRegDWValue( pwszSanitizedCAName, NULL, NULL, wszREGCATYPE, (DWORD *) &CAType); _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCATYPE);
// use DS or not
hr = myGetCertRegDWValue( pwszSanitizedCAName, NULL, NULL, wszREGCAUSEDS, (DWORD *) &fUseDS); _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCAUSEDS);
// server name
hr = myGetCertRegStrValue( pwszSanitizedCAName, NULL, NULL, wszREGCASERVERNAME, &pwszServerName); _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME);
hr = myGetCARegFileNameTemplate( wszREGCACERTFILENAME, pwszServerName, pwszSanitizedCAName, iCertNew, iKey, &pwszCertFile); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr) { _JumpIfError(hr, error, "myGetCARegFileNameTemplate"); }
hr = csiFinishInstallationFromPKCS7( hInstance, fUnattended, hwnd, pwszSanitizedCAName, pwszCommonName, &KeyProvInfo, CAType, iCertNew, iKey, fUseDS, fRenew, pwszServerName, pbChain, cbChain, pwszCertFile); _JumpIfError(hr, error, "csiFinishInstallationFromPKCS7");
error: if (NULL != pwszKeyContainerReg) { LocalFree(pwszKeyContainerReg); } if (NULL != pwszCommonName) { LocalFree(pwszCommonName); } if (NULL != pwszCertFile) { LocalFree(pwszCertFile); } if (NULL != pwszServerName) { LocalFree(pwszServerName); } csiFreeKeyProvInfo(&KeyProvInfo); CSILOG(hr, IDS_ILOG_FINISHSUSPENDEDSETUP, NULL, NULL, NULL); return(hr); }
typedef struct _CERTHIERINFO { HINSTANCE hInstance; BOOL fUnattended; WCHAR *pwszSanitizedCAName; WCHAR *pwszParentMachine; WCHAR *pwszParentCA; WCHAR *pwszParentMachineDefault; WCHAR *pwszParentCADefault; DWORD iCertNew; DWORD iKey; } CERTHIERINFO;
VOID FreeCertHierInfo( IN OUT CERTHIERINFO *pCertHierInfo) { if (NULL != pCertHierInfo->pwszSanitizedCAName) { LocalFree(pCertHierInfo->pwszSanitizedCAName); } if (NULL != pCertHierInfo->pwszParentMachine) { LocalFree(pCertHierInfo->pwszParentMachine); } if (NULL != pCertHierInfo->pwszParentCA) { LocalFree(pCertHierInfo->pwszParentCA); } if (NULL != pCertHierInfo->pwszParentMachineDefault) { LocalFree(pCertHierInfo->pwszParentMachineDefault); } if (NULL != pCertHierInfo->pwszParentCADefault) { LocalFree(pCertHierInfo->pwszParentCADefault); } }
CERTSRVUICASELECTION g_CertHierCARequestUICASelection = {NULL, NULL, NULL, NULL, NULL, ENUM_UNKNOWN_CA, false};
HRESULT csiGetCARequestFileName( IN HINSTANCE hInstance, IN HWND hwnd, IN WCHAR const *pwszSanitizedCAName, IN DWORD iCertNew, IN DWORD iKey, OUT WCHAR **ppwszRequestFile) { HRESULT hr; WCHAR *pwszServerName = NULL; WCHAR *pwszRequestFile = NULL; WCHAR *pwszSharedFolder = NULL;
// init
*ppwszRequestFile = NULL;
// get server name
hr = myGetCertRegStrValue( pwszSanitizedCAName, NULL, NULL, wszREGCASERVERNAME, &pwszServerName); _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME);
hr = myGetCARegFileNameTemplate( wszREGREQUESTFILENAME, pwszServerName, pwszSanitizedCAName, iCertNew, iKey, &pwszRequestFile); if (S_OK != hr) { hr = myGetCertRegStrValue( NULL, NULL, NULL, wszREGDIRECTORY, &pwszSharedFolder); if (S_OK != hr) { CSASSERT(NULL == pwszSharedFolder); }
hr = csiBuildCACertFileName( hInstance, hwnd, TRUE, // fUnattended
pwszSharedFolder, pwszSanitizedCAName, L".req", 0, // iCertNew == 0!
&pwszRequestFile); _JumpIfError(hr, error, "csiBuildCACertFileName");
hr = mySetCARegFileNameTemplate( wszREGREQUESTFILENAME, pwszServerName, pwszSanitizedCAName, pwszRequestFile); _JumpIfError(hr, error, "mySetCARegFileNameTemplate");
LocalFree(pwszRequestFile); pwszRequestFile = NULL;
hr = csiBuildCACertFileName( hInstance, hwnd, TRUE, // fUnattended
pwszSharedFolder, pwszSanitizedCAName, L".req", iCertNew, &pwszRequestFile); _JumpIfError(hr, error, "csiBuildCACertFileName"); }
*ppwszRequestFile = pwszRequestFile; pwszRequestFile = NULL;
hr = S_OK; error: if (NULL != pwszRequestFile) { LocalFree(pwszRequestFile); } if (NULL != pwszServerName) { LocalFree(pwszServerName); } if (NULL != pwszSharedFolder) { LocalFree(pwszSharedFolder); } return hr; }
HRESULT InitCertHierControls( HWND hDlg, CERTHIERINFO *pCertHierInfo) { HRESULT hr; BOOL fCAsExist; WCHAR *pwszHelpText = NULL; WCHAR *pwszRequestFile = NULL; WCHAR *pwszExpandedHelpText = NULL;
if (NULL != pCertHierInfo->pwszParentMachineDefault) { SetWindowText( GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME), pCertHierInfo->pwszParentMachineDefault);
if (NULL != pCertHierInfo->pwszParentCADefault) { SetWindowText( GetDlgItem(hDlg, IDC_PARENT_CA_NAME), pCertHierInfo->pwszParentCADefault); } }
// load formatted help string
hr = myLoadRCString( pCertHierInfo->hInstance, IDS_REQUEST_HELPTEXT, &pwszHelpText); _JumpIfError(hr, error, "myLoadRCString");
// get request file name
hr = csiGetCARequestFileName( pCertHierInfo->hInstance, hDlg, pCertHierInfo->pwszSanitizedCAName, pCertHierInfo->iCertNew, pCertHierInfo->iKey, &pwszRequestFile); _JumpIfError(hr, error, "csiGetCARequestFileName");
// replace %1
if (!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, pwszHelpText, 0, 0, reinterpret_cast<WCHAR *>(&pwszExpandedHelpText), 0, reinterpret_cast<va_list *> (const_cast<WCHAR **>(&pwszRequestFile))) ) { hr = myHLastError(); _JumpError(hr, error, "FormatMessage"); }
// set help text
SetWindowText(GetDlgItem(hDlg, IDC_REQUEST_HELPTEXT), pwszExpandedHelpText);
hr = myInitUICASelectionControls( &g_CertHierCARequestUICASelection, pCertHierInfo->hInstance, hDlg, GetDlgItem(hDlg, IDC_BROWSE_CA), GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME), GetDlgItem(hDlg, IDC_PARENT_CA_NAME), csiIsAnyDSCAAvailable(), &fCAsExist); _JumpIfError(hr, error, "myInitUICASelectionControls");
error: if (NULL != pwszHelpText) { LocalFree(pwszHelpText); } if (NULL != pwszRequestFile) { LocalFree(pwszRequestFile); } if (NULL != pwszExpandedHelpText) { LocalFree(pwszExpandedHelpText); } return(hr); }
HRESULT HandleOKButton( HWND hDlg, CERTHIERINFO *pCertHierInfo, BOOL *pfLeave) { HRESULT hr; WCHAR *pwszParentMachine = NULL; WCHAR *pwszParentCA = NULL;
hr = myUICASelectionValidation(&g_CertHierCARequestUICASelection, pfLeave); _JumpIfError(hr, error, "myUICASelectionValidation"); if (!*pfLeave) { goto error; } // get parent ca info
hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME), &pwszParentMachine); _JumpIfError(hr, error, "myUIGetWindowText");
hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_PARENT_CA_NAME), &pwszParentCA); _JumpIfError(hr, error, "myUIGetWindowText");
pCertHierInfo->pwszParentMachine = pwszParentMachine; pwszParentMachine = NULL; pCertHierInfo->pwszParentCA = pwszParentCA; pwszParentCA = NULL;
hr = S_OK; error: if (NULL != pwszParentMachine) { LocalFree(pwszParentMachine); } if (NULL != pwszParentCA) { LocalFree(pwszParentCA); } return(hr); }
INT_PTR CALLBACK CertHierProc( HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) { HRESULT hr; BOOL ret = FALSE; BOOL fLeave; static CERTHIERINFO *s_pCertHierInfo = NULL; static BOOL s_fComputerChange = FALSE;
switch (iMsg) { case WM_INITDIALOG: s_pCertHierInfo = (CERTHIERINFO *) lParam;
hr = InitCertHierControls(hDlg, s_pCertHierInfo); _JumpIfError(hr, error, "InitCertHierControls");
ret = TRUE; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_BROWSE_CA: ret = TRUE; hr = myUICAHandleCABrowseButton( &g_CertHierCARequestUICASelection, csiIsAnyDSCAAvailable(), IDS_CA_PICKER_TITLE, IDS_CA_PICKER_PROMPT, NULL); _JumpIfError(hr, error, "myUICAHandleCABrowseButton"); break;
case IDC_PARENT_CA_NAME: hr = myUICAHandleCAListDropdown( (int)HIWORD(wParam), &g_CertHierCARequestUICASelection, &s_fComputerChange); _PrintIfError(hr, "myUICAHandleCAListDropdown"); break;
case IDC_PARENT_COMPUTER_NAME: switch ((int)HIWORD(wParam)) { case EN_CHANGE: // edit change
s_fComputerChange = TRUE; break; } break;
case IDOK: ret = TRUE; hr = HandleOKButton(hDlg, s_pCertHierInfo, &fLeave); _PrintIfError(hr, "HandleOKButton"); if (fLeave) { // update return status
ret = EndDialog(hDlg, IDOK); goto error; //done;
} break;
case IDCANCEL: ret = EndDialog(hDlg, IDCANCEL); break; } break; }
error: return(ret); }
VOID MarkSetupComplete( IN WCHAR const *pwszSanitizedCAName) { HRESULT hr; // Clear pending/denied flags:
hr = SetSetupStatus( pwszSanitizedCAName, SETUP_SUSPEND_FLAG | SETUP_ONLINE_FLAG | SETUP_REQUEST_FLAG | SETUP_DENIED_FLAG, FALSE); _PrintIfError(hr, "SetSetupStatus");
// Force new CRL generation on startup:
hr = SetSetupStatus(pwszSanitizedCAName, SETUP_FORCECRL_FLAG, TRUE); _PrintIfError(hr, "SetSetupStatus");
CSILOG(hr, IDS_ILOG_SETUPCOMPLETE, NULL, NULL, NULL); }
HRESULT FindKeyIndex( IN HCERTSTORE hMyStore, IN WCHAR const *pwszSanitizedCAName, IN BOOL fUnattended, IN BOOL fMachineKeyset, IN DWORD cCert, CRYPT_KEY_PROV_INFO *pKeyMatch, OUT DWORD *piKey) { HRESULT hr; DWORD i; CERT_CONTEXT const *pccCert = NULL; CRYPT_KEY_PROV_INFO *pKey = NULL; HCRYPTPROV hProv = NULL; CERT_PUBLIC_KEY_INFO *pPubKeyMatch = NULL; CERT_PUBLIC_KEY_INFO *pPubKey = NULL; DWORD cb; DWORD NameId;
*piKey = MAXDWORD;
// get CSP handle
if (!myCertSrvCryptAcquireContext( &hProv, pKeyMatch->pwszContainerName, pKeyMatch->pwszProvName, pKeyMatch->dwProvType, fUnattended? CRYPT_SILENT : 0, fMachineKeyset)) { hr = myHLastError(); _JumpError(hr, error, "myCertSrvCryptAcquireContext"); } if (hProv == NULL) { hr = E_HANDLE; _JumpError(hr, error, "myCertSrvCryptAcquireContext"); }
if (!myCryptExportPublicKeyInfo( hProv, AT_SIGNATURE, CERTLIB_USE_LOCALALLOC, &pPubKeyMatch, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myCryptExportPublicKeyInfo"); } CryptReleaseContext(hProv, 0); hProv = NULL;
for (i = 0; ; i++) { if (i >= cCert) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); _JumpError(hr, error, "old key not found"); } hr = myFindCACertByHashIndex( hMyStore, pwszSanitizedCAName, CSRH_CASIGCERT, i, &NameId, &pccCert); if (S_FALSE == hr) { continue; } _JumpIfError(hr, error, "myFindCACertByHashIndex");
// get the key provider info
if (!myCertGetCertificateContextProperty( pccCert, CERT_KEY_PROV_INFO_PROP_ID, CERTLIB_USE_LOCALALLOC, (VOID **) &pKey, &cb)) { hr = myHLastError(); _JumpError(hr, error, "CertGetCertificateContextProperty"); }
// get CSP handle
if (!myCertSrvCryptAcquireContext( &hProv, pKey->pwszContainerName, pKey->pwszProvName, pKey->dwProvType, fUnattended? CRYPT_SILENT : 0, fMachineKeyset)) { hr = myHLastError(); _JumpError(hr, error, "myCertSrvCryptAcquireContext"); } if (hProv == NULL) { hr = E_HANDLE; _JumpError(hr, error, "myCertSrvCryptAcquireContext"); }
if (!myCryptExportPublicKeyInfo( hProv, AT_SIGNATURE, CERTLIB_USE_LOCALALLOC, &pPubKey, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myCryptExportPublicKeyInfo"); }
// by design, CertComparePublicKeyInfo doesn't set last error!
if (CertComparePublicKeyInfo(X509_ASN_ENCODING, pPubKey, pPubKeyMatch)) { hr = myGetNameId(pccCert, &NameId); if (S_OK != hr) { *piKey = i; } else { *piKey = CANAMEIDTOIKEY(NameId); } break; }
LocalFree(pPubKey); pPubKey = NULL;
CryptReleaseContext(hProv, 0); hProv = NULL;
LocalFree(pKey); pKey = NULL;
CertFreeCertificateContext(pccCert); pccCert = NULL; } hr = S_OK;
error: if (NULL != pPubKeyMatch) { LocalFree(pPubKeyMatch); } if (NULL != pPubKey) { LocalFree(pPubKey); } if (NULL != hProv) { CryptReleaseContext(hProv, 0); } if (NULL != pKey) { LocalFree(pKey); } if (NULL != pccCert) { CertFreeCertificateContext(pccCert); } CSILOG(hr, IDS_ILOG_KEYINDEX, NULL, NULL, piKey); return(hr); }
HRESULT LoadCurrentCACertAndKeyInfo( IN WCHAR const *pwszSanitizedCAName, IN BOOL fNewKey, IN BOOL fUnattended, IN BOOL fMachineKeyset, IN DWORD iCertNew, OUT DWORD *piKey, OUT WCHAR **ppwszKeyContainer, OUT CERT_CONTEXT const **ppccCertOld) { HRESULT hr; HCERTSTORE hMyStore = NULL; DWORD cbKey; CRYPT_KEY_PROV_INFO *pKey = NULL; WCHAR *pwszKeyContainer = NULL; DWORD NameId;
*ppwszKeyContainer = NULL; *ppccCertOld = NULL; *piKey = MAXDWORD;
// open MY store
hMyStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, NULL, // hProv
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_MAXIMUM_ALLOWED_FLAG, wszMY_CERTSTORE); if (NULL == hMyStore) { hr = myHLastError(); _JumpError(hr, error, "CertOpenStore"); } hr = myFindCACertByHashIndex( hMyStore, pwszSanitizedCAName, CSRH_CASIGCERT, iCertNew - 1, &NameId, ppccCertOld); _JumpIfError(hr, error, "myFindCACertByHashIndex");
if (fNewKey) { *piKey = iCertNew; // New key: iKey set to iCert
hr = myAllocIndexedName( pwszSanitizedCAName, *piKey, &pwszKeyContainer); _JumpIfError(hr, error, "myAllocIndexedName"); } else { // get the key provider info
if (!myCertGetCertificateContextProperty( *ppccCertOld, CERT_KEY_PROV_INFO_PROP_ID, CERTLIB_USE_LOCALALLOC, (VOID **) &pKey, &cbKey)) { hr = myHLastError(); _JumpError(hr, error, "CertGetCertificateContextProperty"); } hr = myDupString(pKey->pwszContainerName, &pwszKeyContainer); _JumpIfError(hr, error, "myDupString");
// Reuse key: iKey set to match oldest iCert using this key:
hr = FindKeyIndex( hMyStore, pwszSanitizedCAName, fUnattended, fMachineKeyset, iCertNew, pKey, piKey); _JumpIfError(hr, error, "FindKeyIndex");
CSASSERT(MAXDWORD != *piKey); } *ppwszKeyContainer = pwszKeyContainer; pwszKeyContainer = NULL; CSASSERT(S_OK == hr);
error: if (NULL != pwszKeyContainer) { LocalFree(pwszKeyContainer); } if (NULL != pKey) { LocalFree(pKey); } if (NULL != hMyStore) { CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG); } CSILOG(hr, IDS_ILOG_LOADOLDCERT, *ppwszKeyContainer, NULL, piKey); return(hr); }
HRESULT ReplaceExtension( IN CERT_EXTENSION const *pExtension, IN OUT DWORD *pcExtension, IN OUT CERT_EXTENSION *rgExtension) { DWORD i;
CSASSERT(NULL != pExtension->pszObjId); for (i = 0; ; i++) { if (i == *pcExtension) { if (NULL != pExtension->Value.pbData) { (*pcExtension)++; // not found: append to array
} break; } CSASSERT(i < *pcExtension); if (0 == strcmp(pExtension->pszObjId, rgExtension[i].pszObjId)) { if (NULL == pExtension->Value.pbData) { // remove extension: copy last extension on top of this one
// and decrement extension count
(*pcExtension)--; pExtension = &rgExtension[*pcExtension]; } break; } } rgExtension[i] = *pExtension; // append or overwrite extension
return(S_OK); }
HRESULT GetMinimumCertValidityPeriod( IN WCHAR const *pwszSanitizedCAName, IN DWORD cCert, OUT LONGLONG *pTimeDelta) { HRESULT hr; HCERTSTORE hMyStore = NULL; DWORD NameId; CERT_CONTEXT const *pcc = NULL; BOOL fFirst = TRUE; DWORD i;
// open MY store
hMyStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, NULL, // hProv
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_MAXIMUM_ALLOWED_FLAG, wszMY_CERTSTORE); if (NULL == hMyStore) { hr = myHLastError(); _JumpError(hr, error, "CertOpenStore"); } for (i = 0; i < cCert; i++) { LONGLONG TimeDelta;
hr = myFindCACertByHashIndex( hMyStore, pwszSanitizedCAName, CSRH_CASIGCERT, i, &NameId, &pcc); if (S_OK != hr) { _PrintError(hr, "myFindCACertByHashIndex"); continue; }
TimeDelta = mySubtractFileTimes( &pcc->pCertInfo->NotAfter, &pcc->pCertInfo->NotBefore);
DBGPRINT(( DBG_SS_CERTLIBI, "iCert=%u TimeDelta=%x:%x\n", i, (DWORD) (TimeDelta >> 32), (DWORD) TimeDelta));
if (fFirst || *pTimeDelta > TimeDelta) { *pTimeDelta = TimeDelta; DBGPRINT(( DBG_SS_CERTLIBI, "iCert=%u *pTimeDelta=%x:%x\n", i, (DWORD) (*pTimeDelta >> 32), (DWORD) *pTimeDelta)); fFirst = FALSE; }
CertFreeCertificateContext(pcc); pcc = NULL; } if (fFirst) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "no old Certs"); } hr = S_OK;
error: if (NULL != pcc) { CertFreeCertificateContext(pcc); } if (NULL != hMyStore) { CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG); } return(hr); }
HRESULT GetCertHashExtension( IN CERT_CONTEXT const *pCert, OUT BYTE **ppbData, OUT DWORD *pcbData) { HRESULT hr; BYTE abHash[CBMAX_CRYPT_HASH_LEN]; CRYPT_DATA_BLOB Blob; DWORD cbHash;
cbHash = sizeof(abHash); if (!CertGetCertificateContextProperty( pCert, CERT_HASH_PROP_ID, abHash, &cbHash)) { hr = myHLastError(); _JumpError(hr, error, "CertGetCertificateContextProperty"); } Blob.cbData = cbHash; Blob.pbData = abHash; if (!myEncodeObject( X509_ASN_ENCODING, X509_OCTET_STRING, &Blob, 0, CERTLIB_USE_LOCALALLOC, ppbData, pcbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } hr = S_OK;
error: return(hr); }
HRESULT CloneRootCert( IN HINF hInf, IN CERT_CONTEXT const *pccCertOld, IN CRYPT_KEY_PROV_INFO const *pKeyProvInfo, IN HCRYPTPROV hProv, IN WCHAR const *pwszSanitizedCAName, IN DWORD iCert, IN DWORD iKey, IN BOOL fUseDS, IN BOOL fNewKey, IN DWORD dwRevocationFlags, IN HINSTANCE hInstance, IN BOOL fUnattended, IN HWND hwnd, OUT BYTE **ppbCert, OUT DWORD *pcbCert) { HRESULT hr; CERT_INFO Cert; GUID guidSerialNumber; LONGLONG TimeDelta; CERT_PUBLIC_KEY_INFO *pPubKey = NULL; DWORD cbPubKey; DWORD NameId; CERT_EXTENSION *paext = NULL; FILETIME ftNotAfterMin; DWORD dwValidityPeriodCount; ENUM_PERIOD enumValidityPeriod; CERT_EXTENSION *pext;
#define CEXT_REPLACED 9
CERT_EXTENSION extBasicConstraints = { NULL, FALSE, 0, NULL}; CERT_EXTENSION extSKI = { szOID_SUBJECT_KEY_IDENTIFIER, FALSE, 0, NULL }; CERT_EXTENSION extCDP = { szOID_CRL_DIST_POINTS, FALSE, 0, NULL }; CERT_EXTENSION extVersion = { szOID_CERTSRV_CA_VERSION, FALSE, 0, NULL }; CERT_EXTENSION extPreviousHash = { szOID_CERTSRV_PREVIOUS_CERT_HASH, FALSE, 0, NULL }; CERT_EXTENSION extPolicy = { szOID_CERT_POLICIES, FALSE, 0, NULL }; CERT_EXTENSION extCross = { szOID_CROSS_CERT_DIST_POINTS, FALSE, 0, NULL }; CERT_EXTENSION extAIA = { szOID_AUTHORITY_INFO_ACCESS, FALSE, 0, NULL }; CERT_EXTENSION extEKU = { NULL, FALSE, 0, NULL};
*ppbCert = NULL;
CopyMemory(&Cert, pccCertOld->pCertInfo, sizeof(Cert)); Cert.dwVersion = CERT_V3; myGenerateGuidSerialNumber(&guidSerialNumber);
Cert.SerialNumber.pbData = (BYTE *) &guidSerialNumber; Cert.SerialNumber.cbData = sizeof(guidSerialNumber); if (!myAreBlobsSame( Cert.Issuer.pbData, Cert.Issuer.cbData, Cert.Subject.pbData, Cert.Subject.cbData)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "non-Root Cert"); }
if (!myCryptExportPublicKeyInfo( hProv, AT_SIGNATURE, CERTLIB_USE_LOCALALLOC, &pPubKey, &cbPubKey)) { hr = myHLastError(); _JumpError(hr, error, "myCryptExportPublicKeyInfo"); }
Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
// make new cert expire at least 1 minute after old cert.
ftNotAfterMin = Cert.NotAfter; myMakeExprDateTime(&ftNotAfterMin, 1, ENUM_PERIOD_MINUTES);
GetSystemTimeAsFileTime(&Cert.NotBefore);
hr = myInfGetValidityPeriod( hInf, NULL, // pwszValidityPeriodCount
NULL, // pwszValidityPeriodString
&dwValidityPeriodCount, &enumValidityPeriod, NULL); // pfSwap
if (S_OK == hr) { Cert.NotAfter = Cert.NotBefore; myMakeExprDateTime( &Cert.NotAfter, dwValidityPeriodCount, enumValidityPeriod); TimeDelta = 0; } else { hr = GetMinimumCertValidityPeriod( pwszSanitizedCAName, iCert, &TimeDelta); _JumpIfError(hr, error, "GetMinimumCertValidityPeriod");
CSASSERT(0 != TimeDelta); } myMakeExprDateTime( &Cert.NotBefore, -CCLOCKSKEWMINUTESDEFAULT, ENUM_PERIOD_MINUTES); if (0 != TimeDelta) { Cert.NotAfter = Cert.NotBefore; myAddToFileTime(&Cert.NotAfter, TimeDelta); }
// make new cert expire at least 1 minute after old cert.
if (0 > CompareFileTime(&Cert.NotAfter, &ftNotAfterMin)) { Cert.NotAfter = ftNotAfterMin; }
if (!fNewKey) { Cert.NotBefore = pccCertOld->pCertInfo->NotBefore; }
paext = (CERT_EXTENSION *) LocalAlloc( LMEM_FIXED, (Cert.cExtension + CEXT_REPLACED) * sizeof(paext[0])); if (NULL == paext) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory(paext, Cert.rgExtension, Cert.cExtension * sizeof(paext[0])); Cert.rgExtension = paext;
// Basic constraints extension:
hr = myInfGetBasicConstraints2CAExtensionOrDefault(hInf, &extBasicConstraints); _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
ReplaceExtension(&extBasicConstraints, &Cert.cExtension, Cert.rgExtension);
// Subject Key Identifier extension:
// If we're reusing the old key, reuse the old SKI -- even if it's "wrong".
pext = NULL; if (!fNewKey) { pext = CertFindExtension( szOID_SUBJECT_KEY_IDENTIFIER, Cert.cExtension, Cert.rgExtension); } if (NULL == pext) { hr = myCreateSubjectKeyIdentifierExtension( pPubKey, &extSKI.Value.pbData, &extSKI.Value.cbData); _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension");
ReplaceExtension(&extSKI, &Cert.cExtension, Cert.rgExtension); }
hr = CreateRevocationExtension( hInf, pwszSanitizedCAName, iCert, iKey, fUseDS, dwRevocationFlags, &extCDP.fCritical, &extCDP.Value.pbData, &extCDP.Value.cbData); _PrintIfError2(hr, "CreateRevocationExtension", S_FALSE); if (S_OK == hr || S_FALSE == hr) { ReplaceExtension(&extCDP, &Cert.cExtension, Cert.rgExtension); }
// Build the CA Version extension
NameId = MAKECANAMEID(iCert, iKey);
if (!myEncodeObject( X509_ASN_ENCODING, X509_INTEGER, &NameId, 0, CERTLIB_USE_LOCALALLOC, &extVersion.Value.pbData, &extVersion.Value.cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } ReplaceExtension(&extVersion, &Cert.cExtension, Cert.rgExtension);
// Build the previous CA cert hash extension
hr = GetCertHashExtension( pccCertOld, &extPreviousHash.Value.pbData, &extPreviousHash.Value.cbData); _JumpIfError(hr, error, "GetCertHashExtension");
ReplaceExtension(&extPreviousHash, &Cert.cExtension, Cert.rgExtension);
// Build the Policy Statement extension
hr = myInfGetPolicyStatementExtension(hInf, &extPolicy); if (S_OK == hr || S_FALSE == hr) { ReplaceExtension(&extPolicy, &Cert.cExtension, Cert.rgExtension); }
// Build the Cross Cert Dist Points extension
hr = myInfGetCrossCertDistributionPointsExtension(hInf, &extCross); if (S_OK == hr || S_FALSE == hr) { ReplaceExtension(&extCross, &Cert.cExtension, Cert.rgExtension); }
// Build the Authority Information Access extension
hr = CreateAuthorityInformationAccessExtension( hInf, pwszSanitizedCAName, iCert, iKey, fUseDS, &extAIA.fCritical, &extAIA.Value.pbData, &extAIA.Value.cbData); _PrintIfError3( hr, "CreateAuthorityInformationAccessExtension", E_HANDLE, S_FALSE); if (S_OK == hr || S_FALSE == hr) { ReplaceExtension(&extAIA, &Cert.cExtension, Cert.rgExtension); }
// Build the Enhanced Key Usage extension
hr = myInfGetEnhancedKeyUsageExtension(hInf, &extEKU); if (S_OK == hr || S_FALSE == hr) { ReplaceExtension(&extEKU, &Cert.cExtension, Cert.rgExtension); }
hr = EncodeCertAndSign( hProv, &Cert, Cert.SignatureAlgorithm.pszObjId, ppbCert, pcbCert, hInstance, fUnattended, hwnd); _JumpIfError(hr, error, "EncodeCertAndSign");
error: if (NULL != extBasicConstraints.Value.pbData) { LocalFree(extBasicConstraints.Value.pbData); } if (NULL != extSKI.Value.pbData) { LocalFree(extSKI.Value.pbData); } if (NULL != extCDP.Value.pbData) { LocalFree(extCDP.Value.pbData); } if (NULL != extVersion.Value.pbData) { LocalFree(extVersion.Value.pbData); } if (NULL != extPreviousHash.Value.pbData) { LocalFree(extPreviousHash.Value.pbData); } if (NULL != extPolicy.Value.pbData) { LocalFree(extPolicy.Value.pbData); } if (NULL != extCross.Value.pbData) { LocalFree(extCross.Value.pbData); } if (NULL != extAIA.Value.pbData) { LocalFree(extAIA.Value.pbData); } if (NULL != extEKU.Value.pbData) { LocalFree(extEKU.Value.pbData); } if (NULL != paext) { LocalFree(paext); } if (NULL != pPubKey) { LocalFree(pPubKey); } CSILOG(hr, IDS_ILOG_CLONECERT, NULL, NULL, NULL); return(hr); }
HRESULT csiBuildRequest( OPTIONAL IN HINF hInf, OPTIONAL IN CERT_CONTEXT const *pccPrevious, IN BYTE const *pbSubjectEncoded, IN DWORD cbSubjectEncoded, IN char const *pszAlgId, IN BOOL fNewKey, IN DWORD iCert, IN DWORD iKey, IN HCRYPTPROV hProv, IN HWND hwnd, IN HINSTANCE hInstance, IN BOOL fUnattended, OUT BYTE **ppbEncode, OUT DWORD *pcbEncode) { HRESULT hr; CERT_PUBLIC_KEY_INFO *pInfo = NULL; DWORD cbInfo = 0; BYTE *pbEncode = NULL; DWORD cbEncode; CERT_REQUEST_INFO CertRequestInfo; CRYPT_ALGORITHM_IDENTIFIER AlgId; HCERTTYPE hCertType = NULL; CRYPT_ATTR_BLOB ExtBlob; CRYPT_ATTR_BLOB VersionBlob; CRYPT_ATTRIBUTE aAttrib[2]; CERT_EXTENSIONS *pExtensions = NULL; CERT_EXTENSIONS Extensions; CERT_EXTENSION aext[8]; CERT_EXTENSION *paext = NULL; DWORD i; DWORD NameId = MAKECANAMEID(iCert, iKey); DWORD cExtCommon = 0; CERT_EXTENSION *pext; DWORD cAttribute = 0; CRYPT_ATTR_BLOB *paAttribute = NULL; WCHAR *pwszTemplateName; WCHAR *pwszTemplateNameInf = NULL;
ExtBlob.pbData = NULL; VersionBlob.pbData = NULL;
if (!CryptExportPublicKeyInfo( hProv, AT_SIGNATURE, X509_ASN_ENCODING, NULL, &cbInfo)) { hr = myHLastError(); _JumpError(hr, error, "CryptExportPublicKeyInfo"); }
pInfo = (CERT_PUBLIC_KEY_INFO *) LocalAlloc(LMEM_FIXED, cbInfo); if (NULL == pInfo) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
if (!CryptExportPublicKeyInfo( hProv, AT_SIGNATURE, X509_ASN_ENCODING, pInfo, &cbInfo)) { hr = myHLastError(); _JumpError(hr, error, "CryptExportPublicKeyInfo"); }
CertRequestInfo.dwVersion = CERT_REQUEST_V1; CertRequestInfo.Subject.pbData = const_cast<BYTE *>(pbSubjectEncoded); CertRequestInfo.Subject.cbData = cbSubjectEncoded; CertRequestInfo.SubjectPublicKeyInfo = *pInfo;
// Build the CA Version extension
if (!myEncodeObject( X509_ASN_ENCODING, X509_INTEGER, &NameId, 0, CERTLIB_USE_LOCALALLOC, &aext[cExtCommon].Value.pbData, &aext[cExtCommon].Value.cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } aext[cExtCommon].pszObjId = szOID_CERTSRV_CA_VERSION; aext[cExtCommon].fCritical = FALSE; cExtCommon++;
// Build the previous CA cert hash extension
if (0 != iCert && NULL != pccPrevious) { hr = GetCertHashExtension( pccPrevious, &aext[cExtCommon].Value.pbData, &aext[cExtCommon].Value.cbData); _JumpIfError(hr, error, "GetCertHashExtension");
aext[cExtCommon].pszObjId = szOID_CERTSRV_PREVIOUS_CERT_HASH; aext[cExtCommon].fCritical = FALSE; cExtCommon++; }
// Subject Key Identifier extension:
// If we're reusing the old key, reuse the old SKI -- even if it's "wrong".
pext = NULL; if (0 != iCert && NULL != pccPrevious && !fNewKey) { pext = CertFindExtension( szOID_SUBJECT_KEY_IDENTIFIER, pccPrevious->pCertInfo->cExtension, pccPrevious->pCertInfo->rgExtension); } if (NULL != pext) { aext[cExtCommon].Value.cbData = pext->Value.cbData; aext[cExtCommon].Value.pbData = (BYTE *) LocalAlloc( LMEM_FIXED, pext->Value.cbData); if (NULL == aext[cExtCommon].Value.pbData) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory( aext[cExtCommon].Value.pbData, pext->Value.pbData, pext->Value.cbData); } else { hr = myCreateSubjectKeyIdentifierExtension( &CertRequestInfo.SubjectPublicKeyInfo, &aext[cExtCommon].Value.pbData, &aext[cExtCommon].Value.cbData); _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension"); }
aext[cExtCommon].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER; aext[cExtCommon].fCritical = FALSE; cExtCommon++;
hr = myInfGetPolicyStatementExtension(hInf, &aext[cExtCommon]); _PrintIfError(hr, "myInfGetPolicyStatementExtension"); if (S_OK == hr) { aext[cExtCommon].pszObjId = szOID_CERT_POLICIES; cExtCommon++; }
hr = myInfGetCrossCertDistributionPointsExtension(hInf, &aext[cExtCommon]); _PrintIfError(hr, "myInfGetCrossCertDistributionPointsExtension"); if (S_OK == hr) { aext[cExtCommon].pszObjId = szOID_CROSS_CERT_DIST_POINTS; cExtCommon++; }
hr = myInfGetRequestAttributes( hInf, &cAttribute, &paAttribute, &pwszTemplateNameInf); _PrintIfError(hr, "myInfGetRequestAttributes");
pwszTemplateName = pwszTemplateNameInf; if (NULL == pwszTemplateName) { pwszTemplateName = wszCERTTYPE_SUBORDINATE_CA; }
// Build the attribute containing the appropriate cert type info
hr = CAFindCertTypeByName( pwszTemplateName, NULL, CT_FIND_LOCAL_SYSTEM | CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES, &hCertType); if (S_OK == hr) { hr = CAGetCertTypeExtensions(hCertType, &pExtensions); _JumpIfError(hr, error, "CAGetCertTypeExtensions");
paext = (CERT_EXTENSION *) LocalAlloc( LMEM_FIXED, (pExtensions->cExtension + cExtCommon) * sizeof(paext[0])); if (NULL == paext) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory(&paext[0], &aext[0], cExtCommon * sizeof(paext[0])); CopyMemory( &paext[cExtCommon], pExtensions->rgExtension, pExtensions->cExtension * sizeof(paext[0]));
Extensions.cExtension = cExtCommon + pExtensions->cExtension; Extensions.rgExtension = paext; } else { DBGERRORPRINTLINE("CAFindCertTypeByName", hr);
// standard extensions are not available from CAGetCertTypeExtensions;
// construct them manually.
// Build the Cert Template extension
hr = myBuildCertTypeExtension(pwszTemplateName, &aext[cExtCommon]); _JumpIfError(hr, error, "myBuildCertTypeExtension");
cExtCommon++;
if (!CreateKeyUsageExtension( myCASIGN_KEY_USAGE, &aext[cExtCommon].Value.pbData, &aext[cExtCommon].Value.cbData, hInstance, fUnattended, hwnd)) { hr = myHLastError(); _JumpError(hr, error, "CreateKeyUsageExtension"); } aext[cExtCommon].pszObjId = szOID_KEY_USAGE; aext[cExtCommon].fCritical = FALSE; cExtCommon++;
hr = myInfGetBasicConstraints2CAExtensionOrDefault( hInf, &aext[cExtCommon]); _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
cExtCommon++;
CSASSERT(ARRAYSIZE(aext) >= cExtCommon);
Extensions.cExtension = cExtCommon; Extensions.rgExtension = aext; }
if (!myEncodeObject( X509_ASN_ENCODING, X509_EXTENSIONS, &Extensions, 0, CERTLIB_USE_LOCALALLOC, &ExtBlob.pbData, &ExtBlob.cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); }
// get the OS Version
hr = myBuildOSVersionAttribute(&VersionBlob.pbData, &VersionBlob.cbData); _JumpIfError(hr, error, "myBuildOSVersionAttribute");
aAttrib[0].pszObjId = szOID_RSA_certExtensions; aAttrib[0].cValue = 1; aAttrib[0].rgValue = &ExtBlob;
aAttrib[1].pszObjId = szOID_OS_VERSION; aAttrib[1].cValue = 1; aAttrib[1].rgValue = &VersionBlob;
CertRequestInfo.cAttribute = ARRAYSIZE(aAttrib); CertRequestInfo.rgAttribute = aAttrib;
AlgId.pszObjId = const_cast<char *>(pszAlgId); AlgId.Parameters.cbData = 0; AlgId.Parameters.pbData = NULL;
if (!CryptSignAndEncodeCertificate( hProv, AT_SIGNATURE, X509_ASN_ENCODING, X509_CERT_REQUEST_TO_BE_SIGNED, &CertRequestInfo, &AlgId, NULL, NULL, &cbEncode)) { hr = myHLastError(); _JumpError(hr, error, "CryptSignAndEncodeCertificate"); }
pbEncode = (BYTE *) LocalAlloc(LMEM_FIXED, cbEncode); if (NULL == pbEncode) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
if (!CryptSignAndEncodeCertificate( hProv, AT_SIGNATURE, X509_ASN_ENCODING, X509_CERT_REQUEST_TO_BE_SIGNED, &CertRequestInfo, &AlgId, NULL, pbEncode, &cbEncode)) { hr = myHLastError(); _JumpError(hr, error, "CryptSignAndEncodeCertificate"); }
// return value
*ppbEncode = pbEncode; *pcbEncode = cbEncode; hr = S_OK;
error: if (NULL != pwszTemplateNameInf) { LocalFree(pwszTemplateNameInf); } if (NULL != paAttribute) { myInfFreeRequestAttributes(cAttribute, paAttribute); } for (i = 0; i < cExtCommon; i++) { if (NULL != aext[i].Value.pbData) { LocalFree(aext[i].Value.pbData); } } if (NULL != paext) { LocalFree(paext); } if (NULL != ExtBlob.pbData) { LocalFree(ExtBlob.pbData); } if (NULL != VersionBlob.pbData) { LocalFree(VersionBlob.pbData); } if (NULL != pInfo) { LocalFree(pInfo); } if (NULL != hCertType) { if (NULL != pExtensions && &Extensions != pExtensions) { CAFreeCertTypeExtensions(hCertType, pExtensions); } CACloseCertType(hCertType); } CSILOG(hr, IDS_ILOG_BUILDREQUEST, NULL, NULL, &NameId); return(hr); }
//+-------------------------------------------------------------------------
// CertServerRequestCACertificateAndComplete -- implements the following:
// MMC snapin's RenewCert and InstallCert verbs
// certutil -InstallCert & -RenewCert
//+-------------------------------------------------------------------------
HRESULT CertServerRequestCACertificateAndComplete( IN HINSTANCE hInstance, IN HWND hwnd, IN DWORD Flags, IN WCHAR const *pwszCAName, OPTIONAL IN WCHAR const *pwszParentMachine, OPTIONAL IN WCHAR const *pwszParentCA, OPTIONAL IN WCHAR const *pwszCAChainFile, OPTIONAL OUT WCHAR **ppwszRequestFile) { HRESULT hr; DWORD dwSetupStatus; WCHAR const *pwszFinalParentMachine = pwszParentMachine; WCHAR const *pwszFinalParentCA = pwszParentCA; WCHAR *pwszRequestFile = NULL; WCHAR *pwszCertFile = NULL; BYTE *pbRequest = NULL; DWORD cbRequest; BSTR strChain = NULL; BYTE *pbChain = NULL; DWORD cbChain; WCHAR *pwszKeyContainer = NULL; WCHAR *pwszServerName = NULL; WCHAR *pwsz; CERTHIERINFO CertHierInfo; ENUM_CATYPES CAType; BOOL fUseDS; DWORD dwRevocationFlags; DWORD iCertNew; DWORD iKey; CERT_CONTEXT const *pccCertOld = NULL; HCRYPTPROV hProv = NULL; CRYPT_KEY_PROV_INFO KeyProvInfo; ALG_ID idAlg; BOOL fMachineKeyset; BOOL fKeyGenFailed; CHAR *pszAlgId = NULL; BOOL fUnattended = (CSRF_UNATTENDED & Flags)? TRUE : FALSE; BOOL fRenew = (CSRF_RENEWCACERT & Flags)? TRUE : FALSE; BOOL fNewKey = (CSRF_NEWKEYS & Flags)? TRUE : FALSE; UINT idMsg; WCHAR *pwszProvName = NULL; DWORD dwProvType; HINF hInf = INVALID_HANDLE_VALUE; DWORD ErrorLine; idMsg = IDS_ILOG_INSTALLCERT; if (fRenew) { idMsg = fNewKey? IDS_ILOG_RENEWNEWKEY : IDS_ILOG_RENEWOLDKEY; } ZeroMemory(&CertHierInfo, sizeof(CertHierInfo)); ZeroMemory(&KeyProvInfo, sizeof(KeyProvInfo)); if (NULL != ppwszRequestFile) { *ppwszRequestFile = NULL; } if (NULL == pwszCAName) { hr = E_POINTER; _JumpError(hr, error, "NULL CA Name"); } hr = mySanitizeName(pwszCAName, &CertHierInfo.pwszSanitizedCAName); _JumpIfError(hr, error, "mySanitizeName"); hr = GetSetupStatus(CertHierInfo.pwszSanitizedCAName, &dwSetupStatus); _JumpIfError(hr, error, "GetSetupStatus"); hr = myGetCertRegDWValue( CertHierInfo.pwszSanitizedCAName, NULL, NULL, wszREGCATYPE, (DWORD *) &CAType); _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCATYPE); // use DS or not
hr = myGetCertRegDWValue( CertHierInfo.pwszSanitizedCAName, NULL, NULL, wszREGCAUSEDS, (DWORD *) &fUseDS); _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCAUSEDS); hr = myGetCertRegStrValue( CertHierInfo.pwszSanitizedCAName, NULL, NULL, wszREGCASERVERNAME, &pwszServerName); _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME); hr = myGetCertRegDWValue( CertHierInfo.pwszSanitizedCAName, wszREGKEYPOLICYMODULES, wszCLASS_CERTPOLICY, wszREGREVOCATIONTYPE, &dwRevocationFlags); if (S_OK != hr) { dwRevocationFlags = fUseDS? REVEXT_DEFAULT_DS : REVEXT_DEFAULT_NODS; } // Current Hash count is the same as the next iCert
hr = myGetCARegHashCount( CertHierInfo.pwszSanitizedCAName, CSRH_CASIGCERT, &iCertNew); _JumpIfError(hr, error, "myGetCARegHashCount"); if (fRenew) { // We're renewing the CA cert, so the initial setup should be complete.
hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE); if (0 == iCertNew || (SETUP_SUSPEND_FLAG & dwSetupStatus)) { _JumpError(hr, error, "not fully installed"); } if (SETUP_REQUEST_FLAG & dwSetupStatus) { if (0 == (CSRF_OVERWRITE & Flags)) { _JumpError(hr, error, "Renewal already in progress"); } _PrintError(hr, "Ignoring renewal already in progress"); }
hr = myGetCertSrvCSP( FALSE, // fEncryptionCSP
CertHierInfo.pwszSanitizedCAName, &dwProvType, &pwszProvName, &idAlg, &fMachineKeyset, NULL); // pdwKeySize
_JumpIfError(hr, error, "myGetCertSrvCSP");
hr = LoadCurrentCACertAndKeyInfo( CertHierInfo.pwszSanitizedCAName, fNewKey, fUnattended, fMachineKeyset, iCertNew, &iKey, &pwszKeyContainer, &pccCertOld); _JumpIfError(hr, error, "LoadCurrentCACertAndKeyInfo"); CSASSERT(MAXDWORD != iKey); hr = csiFillKeyProvInfo( pwszKeyContainer, pwszProvName, dwProvType, fMachineKeyset, &KeyProvInfo); _JumpIfError(hr, error, "csiFillKeyProvInfo");
hr = GetCertServerKeyProviderInfo( CertHierInfo.pwszSanitizedCAName, pwszKeyContainer, &idAlg, &fMachineKeyset, &KeyProvInfo); _JumpIfError(hr, error, "GetCertServerKeyProviderInfo"); hr = myInfOpenFile(NULL, &hInf, &ErrorLine); _PrintIfError2( hr, "myInfOpenFile", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
if (fNewKey) { CWaitCursor cwait; DWORD cbitKey; hr = myInfGetKeyLength(hInf, &cbitKey); if (S_OK != hr) { cbitKey = CertGetPublicKeyLength( X509_ASN_ENCODING, &pccCertOld->pCertInfo->SubjectPublicKeyInfo); if (0 == cbitKey || 512 == cbitKey) { if (0 == cbitKey) { hr = myHLastError(); _PrintError(hr, "CertGetPublicKeyLength"); } cbitKey = 1024; } } hr = csiGenerateCAKeys( KeyProvInfo.pwszContainerName, KeyProvInfo.pwszProvName, KeyProvInfo.dwProvType, fMachineKeyset, cbitKey, // dwKeyLength,
hInstance, fUnattended, hwnd, &fKeyGenFailed); _JumpIfError(hr, error, "csiGenerateCAKeys"); } // get CSP handle
if (!myCertSrvCryptAcquireContext( &hProv, KeyProvInfo.pwszContainerName, KeyProvInfo.pwszProvName, KeyProvInfo.dwProvType, fUnattended? CRYPT_SILENT : 0, fMachineKeyset)) { hr = myHLastError(); _JumpError(hr, error, "myCertSrvCryptAcquireContext"); } if (hProv == NULL) { hr = E_HANDLE; _JumpError(hr, error, "myCertSrvCryptAcquireContext"); } if (IsRootCA(CAType)) { hr = CloneRootCert( hInf, pccCertOld, &KeyProvInfo, hProv, CertHierInfo.pwszSanitizedCAName, iCertNew, iKey, fUseDS, fNewKey, dwRevocationFlags, hInstance, fUnattended, hwnd, &pbChain, &cbChain); _JumpIfError(hr, error, "CloneRootCert"); } else { // get request file name
hr = csiGetCARequestFileName( hInstance, hwnd, CertHierInfo.pwszSanitizedCAName, iCertNew, iKey, &pwszRequestFile); _JumpIfError(hr, error, "csiGetCARequestFileName"); hr = myGetSigningOID( NULL, // hProv
KeyProvInfo.pwszProvName, KeyProvInfo.dwProvType, idAlg, &pszAlgId); _JumpIfError(hr, error, "myGetSigningOID"); hr = csiBuildRequest( hInf, pccCertOld, pccCertOld->pCertInfo->Subject.pbData, pccCertOld->pCertInfo->Subject.cbData, pszAlgId, fNewKey, iCertNew, iKey, hProv, hwnd, hInstance, fUnattended, &pbRequest, &cbRequest); _JumpIfError(hr, error, "csiBuildRequest"); hr = EncodeToFileW( pwszRequestFile, pbRequest, cbRequest, DECF_FORCEOVERWRITE | CRYPT_STRING_BASE64REQUESTHEADER); _JumpIfError(hr, error, "EncodeToFileW"); hr = mySetCertRegKeyIndexAndContainer( CertHierInfo.pwszSanitizedCAName, iKey, pwszKeyContainer); _JumpIfError(hr, error, "mySetCertRegKeyIndexAndContainer"); hr = SetSetupStatus( CertHierInfo.pwszSanitizedCAName, SETUP_REQUEST_FLAG, TRUE); _JumpIfError(hr, error, "SetSetupStatus"); if (NULL != ppwszRequestFile) { *ppwszRequestFile = pwszRequestFile; pwszRequestFile = NULL; CSASSERT(S_OK == hr); } } } else { // We're not renewing the CA cert, so this had better be an incomplete
// renewal or initial setup; we're waiting for the new cert or chain.
if (IsRootCA(CAType) || 0 == (SETUP_REQUEST_FLAG & dwSetupStatus)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE); _JumpIfError(hr, error, "no outstanding request"); } hr = myGetCertRegKeyIndexAndContainer( CertHierInfo.pwszSanitizedCAName, &iKey, &pwszKeyContainer); _JumpIfError(hr, error, "myGetCertRegKeyIndexAndContainer"); if (NULL == pwszCAChainFile) { // pop up open dlg
hr = myGetOpenFileName( hwnd, hInstance, IDS_CAHIER_INSTALL_TITLE, IDS_CAHIER_CERTFILE_FILTER, 0, // no def ext
OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, NULL, // no default file
&pwszCertFile); if (S_OK == hr && NULL != pwszCertFile) { pwszCAChainFile = pwszCertFile; } } if (NULL != pwszCAChainFile) { hr = DecodeFileW(pwszCAChainFile, &pbChain, &cbChain, CRYPT_STRING_ANY); _JumpIfErrorStr(hr, error, "DecodeFileW", pwszCAChainFile); } } if (!IsRootCA(CAType) && NULL == pbChain) { // if we haven't created the request, grab it from a file for resubmission
if (pbRequest == NULL) { hr = myGetCARegFileNameTemplate( wszREGREQUESTFILENAME, pwszServerName, CertHierInfo.pwszSanitizedCAName, iCertNew, iKey, &pwszRequestFile); _JumpIfError(hr, error, "myGetCARegFileNameTemplate"); hr = DecodeFileW(pwszRequestFile, &pbRequest, &cbRequest, CRYPT_STRING_ANY); _JumpIfErrorStr(hr, error, "DecodeFileW", pwszRequestFile); } if (NULL == pwszParentMachine || NULL == pwszParentCA) { CertHierInfo.hInstance = hInstance; CertHierInfo.fUnattended = fUnattended; CertHierInfo.iCertNew = iCertNew; CertHierInfo.iKey = iKey; // get parent ca info
hr = myGetCertRegStrValue( CertHierInfo.pwszSanitizedCAName, NULL, NULL, wszREGPARENTCAMACHINE, &CertHierInfo.pwszParentMachineDefault); _PrintIfErrorStr(hr, "myGetCertRegStrValue", wszREGPARENTCAMACHINE); hr = myGetCertRegStrValue( CertHierInfo.pwszSanitizedCAName, NULL, NULL, wszREGPARENTCANAME, &CertHierInfo.pwszParentCADefault); _PrintIfErrorStr(hr, "myGetCertRegStrValue", wszREGPARENTCANAME); // invoke parent ca dialog to select
if (IDOK != (int) DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_COMPLETE_DIALOG), hwnd, CertHierProc, (LPARAM) &CertHierInfo)) { // cancel
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED); _JumpError(hr, error, "cancel"); } pwszFinalParentMachine = CertHierInfo.pwszParentMachine; pwszFinalParentCA = CertHierInfo.pwszParentCA; } BOOL fRetrievePending = (SETUP_REQUEST_FLAG & dwSetupStatus) && (SETUP_ONLINE_FLAG & dwSetupStatus) && NULL != CertHierInfo.pwszParentMachineDefault && NULL != CertHierInfo.pwszParentCADefault && 0 == lstrcmpi( pwszFinalParentMachine, CertHierInfo.pwszParentMachineDefault) && 0 == lstrcmpi( pwszFinalParentCA, CertHierInfo.pwszParentCADefault); // submit to parent ca
hr = csiSubmitCARequest( hInstance, fUnattended, hwnd, fRenew, fRetrievePending, CertHierInfo.pwszSanitizedCAName, pwszFinalParentMachine, pwszFinalParentCA, pbRequest, cbRequest, &strChain); _JumpIfError(hr, error, "csiSubmitCARequest"); cbChain = SysStringByteLen(strChain); } hr = FinishSuspendedSetupFromPKCS7( hInstance, fUnattended, hwnd, CertHierInfo.pwszSanitizedCAName, pwszKeyContainer, iKey, fRenew || 0 != iCertNew, NULL != pbChain? pbChain : (BYTE *) strChain, cbChain); _JumpIfError(hr, error, "FinishSuspendedSetupFromPKCS7"); MarkSetupComplete(CertHierInfo.pwszSanitizedCAName); CSASSERT(S_OK == hr); error: if (INVALID_HANDLE_VALUE != hInf) { myInfCloseFile(hInf); } FreeCertHierInfo(&CertHierInfo); csiFreeKeyProvInfo(&KeyProvInfo); if (NULL != hProv) { CryptReleaseContext(hProv, 0); } if (NULL != pszAlgId) { LocalFree(pszAlgId); } if (NULL != pwszKeyContainer) { LocalFree(pwszKeyContainer); } if (NULL != pccCertOld) { CertFreeCertificateContext(pccCertOld); } if (NULL != pwszRequestFile) { LocalFree(pwszRequestFile); } if (NULL != pwszCertFile) { LocalFree(pwszCertFile); } if (NULL != pwszServerName) { LocalFree(pwszServerName); } if (NULL != pbRequest) { LocalFree(pbRequest); } if (NULL != pbChain) { LocalFree(pbChain); } if (NULL != pwszProvName) { LocalFree(pwszProvName); } if (NULL != strChain) { SysFreeString(strChain); } CSILOG(hr, idMsg, pwszCAName, NULL, NULL); return(hr); }
|