//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 2000-2002. // // File: CertTemplate.cpp // // Contents: CCertTemplate // //---------------------------------------------------------------------------- /// CertTemplate.cpp: implementation of the CCertTemplate class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CertTemplate.h" #define _SECOND ((ULONGLONG) 10000000) #define _MINUTE (60 * _SECOND) #define _HOUR (60 * _MINUTE) #define _DAY (24 * _HOUR) CERT_EXTENSION g_EKUCertExtension = {szOID_ENHANCED_KEY_USAGE, 0, {0, 0}}; CERT_EXTENSION g_certPolCertExtension = {szOID_CERT_POLICIES, 0, {0, 0}}; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CCertTemplate::CCertTemplate( PCWSTR pszObjectName, PCWSTR pszTemplateName, const CString& szLDAPPath, bool fIsReadOnly, const bool fUseCache) : CCertTmplCookie (CERTTMPL_CERT_TEMPLATE, pszObjectName), m_strTemplateName (pszTemplateName), m_hCertType (0), m_dwVersion (0), m_dwEnrollmentFlags (0), m_dwSubjectNameFlags (0), m_dwPrivateKeyFlags (0), m_dwGeneralFlags (0), m_dwKeySpec (0), m_bIsClone (false), m_bCanBeDeletedOnCancel (false), m_bGoodForAutoenrollmentFlagPendingSave (false), m_szLDAPPath (szLDAPPath), m_fIsReadOnly (fIsReadOnly), m_nOriginalValidityDays (-1), m_nNewValidityDays (-1), m_nOriginalRenewalDays (-1), m_nNewRenewalDays (-1), m_pCertExtensions (0), m_fUseCache (fUseCache), m_bIssuancePoliciesRequired (false), m_fFailedToSetSecurity (false) { // _TRACE (1, L"Entering CCertTemplate::CCertTemplate\n"); m_strOriginalTemplateName = pszTemplateName; Initialize (); // _TRACE (-1, L"Leaving CCertTemplate::CCertTemplate\n"); } CCertTemplate::CCertTemplate( const CCertTemplate &rTemplate, bool bIsClone, bool fIsReadOnly, const bool fUseCache) : CCertTmplCookie (CERTTMPL_CERT_TEMPLATE), m_hCertType (0), m_dwVersion (0), m_dwEnrollmentFlags (0), m_dwSubjectNameFlags (0), m_dwPrivateKeyFlags (0), m_dwGeneralFlags (0), m_dwKeySpec (0), m_bIsClone (bIsClone), m_bCanBeDeletedOnCancel (true), m_bGoodForAutoenrollmentFlagPendingSave (false), m_fIsReadOnly (fIsReadOnly), m_szLDAPPath (rTemplate.GetLDAPPath ()), m_nOriginalValidityDays (-1), m_nNewValidityDays (-1), m_nOriginalRenewalDays (-1), m_nNewRenewalDays (-1), m_pCertExtensions (0), m_fUseCache (fUseCache), m_bIssuancePoliciesRequired (false), m_fFailedToSetSecurity (false) { // _TRACE (1, L"Entering CCertTemplate::CCertTemplate (copy constructor)\n"); // _TRACE (-1, L"Leaving CCertTemplate::CCertTemplate (copy constructor)\n"); } CCertTemplate::~CCertTemplate() { // _TRACE (1, L"Entering CCertTemplate::~CCertTemplate - m_hCertType = 0x%x\n", m_hCertType); if ( m_hCertType ) { FreeCertExtensions (); HRESULT hr = CACloseCertType (m_hCertType); _ASSERT (SUCCEEDED (hr)); if ( !SUCCEEDED (hr) ) { _TRACE (0, L"CACloseCertType (%s) failed: 0x%x\n", hr); } } // _TRACE (-1, L"Leaving CCertTemplate::~CCertTemplate\n"); } HRESULT CCertTemplate::Initialize() { // _TRACE (1, L"Entering CCertTemplate::Initialize - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( !m_hCertType ) { DWORD dwFlags = CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES; if ( !m_fUseCache ) { dwFlags |= CT_FLAG_NO_CACHE_LOOKUP; } hr = CAFindCertTypeByName (m_strTemplateName, NULL, dwFlags, &m_hCertType); _ASSERT (SUCCEEDED (hr)); } if ( SUCCEEDED (hr) ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_SCHEMA_VERSION, &m_dwVersion); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_SCHEMA_VERSION) failed: 0x%x\n", hr); } // Get enrollment flags if ( SUCCEEDED (hr) ) { hr = CAGetCertTypeFlagsEx (m_hCertType, CERTTYPE_ENROLLMENT_FLAG, &m_dwEnrollmentFlags); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypeFlagsEx (CERTTYPE_ENROLLMENT_FLAG) failed: 0x%x\n", hr); } } // Get subject name flags if ( SUCCEEDED (hr) ) { hr = CAGetCertTypeFlagsEx (m_hCertType, CERTTYPE_SUBJECT_NAME_FLAG, &m_dwSubjectNameFlags); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypeFlagsEx (CERTTYPE_SUBJECT_NAME_FLAG) failed: 0x%x\n", hr); } } // Get private key flags if ( SUCCEEDED (hr) ) { hr = CAGetCertTypeFlagsEx (m_hCertType, CERTTYPE_PRIVATE_KEY_FLAG, &m_dwPrivateKeyFlags); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypeFlagsEx (CERTTYPE_PRIVATE_KEY_FLAG) failed: 0x%x\n", hr); } } // Get general flags if ( SUCCEEDED (hr) ) { hr = CAGetCertTypeFlagsEx (m_hCertType, CERTTYPE_GENERAL_FLAG, &m_dwGeneralFlags); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypeFlagsEx (CERTTYPE_GENERAL_FLAG) failed: 0x%x\n", hr); } } if ( SUCCEEDED (hr) ) { hr = CAGetCertTypeKeySpec (m_hCertType, &m_dwKeySpec); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypeKeySpec () failed: 0x%x\n", hr); } } } else { _TRACE (0, L"CAFindCertTypeByName (%s) failed: 0x%x\n", (PCWSTR) m_strTemplateName, hr); } // _TRACE (-1, L"Leaving CCertTemplate::Initialize: 0x%x\n", hr); return hr; } DWORD CCertTemplate::GetType() const { return m_dwVersion; } CString CCertTemplate::GetDisplayName () { // _TRACE (1, L"Entering CCertTemplate::GetDisplayName - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( m_szDisplayName.IsEmpty () ) { if ( m_hCertType ) { PWSTR* rgwszProp = 0; hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_FRIENDLY_NAME, &rgwszProp); if ( SUCCEEDED (hr) && rgwszProp ) { m_szDisplayName = *rgwszProp; CAFreeCertTypeProperty (m_hCertType, rgwszProp); } else { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_FRIENDLY_NAME) failed: 0x%x\n", hr); m_szDisplayName = GetObjectName (); } } else m_szDisplayName = GetObjectName (); } // _TRACE (-1, L"Leaving CCertTemplate::GetDisplayName: %s, 0x%x\n", (PCWSTR) m_szDisplayName, hr); return m_szDisplayName; } CString CCertTemplate::GetTemplateName() const { return m_strTemplateName; } bool CCertTemplate::SubjectIsCA() const { return (m_dwGeneralFlags & CT_FLAG_IS_CA) ? true : false; } bool CCertTemplate::SubjectIsCrossCA() const { return (m_dwGeneralFlags & CT_FLAG_IS_CROSS_CA) ? true : false; } bool CCertTemplate::IsMachineType() const { return (m_dwGeneralFlags & CT_FLAG_MACHINE_TYPE) ? true : false; } bool CCertTemplate::PublishToDS() const { return (m_dwEnrollmentFlags & CT_FLAG_PUBLISH_TO_DS) ? true : false; } DWORD CCertTemplate::GetCertExtensionCount() { DWORD dwCnt = 0; PCERT_EXTENSIONS pCertExtensions = 0; HRESULT hr = CAGetCertTypeExtensions (m_hCertType, &pCertExtensions); if ( SUCCEEDED (hr) ) { if ( pCertExtensions ) { dwCnt = pCertExtensions->cExtension; CAFreeCertTypeExtensions (m_hCertType, pCertExtensions); } } else { _TRACE (0, L"CAGetCertTypeExtensions () failed: 0x%x\n", hr); } return dwCnt; } /////////////////////////////////////////////////////////////////////////////// // // Method: GetCertExtension // // Note: The pointer returned through ppCertExtension must not be freed. The // caller must call FreeCertExtensions () when done with it. /////////////////////////////////////////////////////////////////////////////// HRESULT CCertTemplate::GetCertExtension (PSTR pszOID, PCERT_EXTENSION* ppCertExtension) { HRESULT hr = S_OK; if ( ppCertExtension ) { hr = CAGetCertTypeExtensions (m_hCertType, &m_pCertExtensions); if ( SUCCEEDED (hr) ) { if ( m_pCertExtensions ) { *ppCertExtension = CertFindExtension(pszOID, m_pCertExtensions->cExtension, m_pCertExtensions->rgExtension); if ( ! (*ppCertExtension) ) { if ( SubjectIsCA () ) { if ( !_stricmp (szOID_ENHANCED_KEY_USAGE, pszOID) ) *ppCertExtension = &g_EKUCertExtension; else if ( !_stricmp (szOID_CERT_POLICIES, pszOID) ) *ppCertExtension = &g_certPolCertExtension; } } } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeExtensions () failed: 0x%x\n", hr); } } else return E_POINTER; return hr; } HRESULT CCertTemplate::GetCertExtension(DWORD dwIndex, PSTR* ppszObjId, BOOL& fCritical) { if ( !ppszObjId ) return E_POINTER; PCERT_EXTENSIONS pCertExtensions = 0; HRESULT hr = CAGetCertTypeExtensions (m_hCertType, &pCertExtensions); if ( SUCCEEDED (hr) ) { if ( pCertExtensions ) { if ( dwIndex >= pCertExtensions->cExtension ) hr = E_INVALIDARG; else { PCERT_EXTENSION pExtension = &pCertExtensions->rgExtension[dwIndex]; ASSERT (pExtension->pszObjId); if ( pExtension->pszObjId ) { // security review 2/21/2002 BryanWal ok PSTR pszOID = new char[strlen (pExtension->pszObjId)+1]; if ( pszOID ) { // security review 2/21/2002 BryanWal ok strcpy (pszOID, pExtension->pszObjId); *ppszObjId = pszOID; fCritical = pExtension->fCritical; } else hr = E_OUTOFMEMORY; } else hr = E_FAIL; } CAFreeCertTypeExtensions (m_hCertType, pCertExtensions); } } else { _TRACE (0, L"CAGetCertTypeExtensions () failed: 0x%x\n", hr); } return hr; } bool CCertTemplate::HasKeySpecSignature() const { return m_dwKeySpec & AT_SIGNATURE ? true : false; } bool CCertTemplate::HasEncryptionSignature() const { return m_dwKeySpec & AT_KEYEXCHANGE ? true : false; } bool CCertTemplate::RequireSubjectInRequest() const { return m_dwSubjectNameFlags & CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT ? true : false; } #define CVT_BASE (1000 * 1000 * 10) HRESULT CCertTemplate::ConvertCertTypeFileTimeToDays (FILETIME const *pftCertType, int& nDays) { HRESULT hr = S_OK; if ( !pftCertType ) return E_POINTER; LONGLONG ll = *(LONGLONG *) pftCertType; // Signed 64 bit scalar! if (0 > ll) { ll = -ll; ll /= CVT_BASE; // now in seconds nDays = (int) (ll / (60 * 60 * 24)); } else nDays = 0; return hr; } HRESULT CCertTemplate::GetValidityPeriod(int& nValidityDays) { HRESULT hr = S_OK; FILETIME ftValidity; hr = CAGetCertTypeExpiration (m_hCertType, &ftValidity, 0); if ( SUCCEEDED (hr) ) { hr = ConvertCertTypeFileTimeToDays (&ftValidity, nValidityDays); if ( SUCCEEDED (hr) ) m_nOriginalValidityDays = nValidityDays; } return hr; } HRESULT CCertTemplate::GetRenewalPeriod(int& nRenewalDays) { HRESULT hr = S_OK; FILETIME ftRenewal; hr = CAGetCertTypeExpiration (m_hCertType, 0, &ftRenewal); if ( SUCCEEDED (hr) ) { hr = ConvertCertTypeFileTimeToDays (&ftRenewal, nRenewalDays); if ( SUCCEEDED (hr) ) m_nOriginalRenewalDays = nRenewalDays; } return hr; } // NEW CLONE HRESULT CCertTemplate::Clone ( const CCertTemplate& rTemplate, const CString& strTemplateName, const CString& strDisplayName) { _TRACE (1, L"Entering CCertTemplate::Clone (%s, %s)\n", (PCWSTR) strTemplateName, (PCWSTR) strDisplayName); HRESULT hr = S_OK; _ASSERT (m_bIsClone); if ( m_bIsClone ) { m_strTemplateName = strTemplateName; // Set the originalTemplateName so that we can tell later if the // user has renamed the template. This is important because renaming // a template creates a brand new template and the old one must then // be deleted. m_strOriginalTemplateName = strTemplateName; SetObjectName (strDisplayName); if ( SUCCEEDED (hr) ) { hr = CAFindCertTypeByName (rTemplate.GetTemplateName (), NULL, CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES | CT_FLAG_NO_CACHE_LOOKUP, &m_hCertType); if ( SUCCEEDED (hr) ) { HCERTTYPE hNewCertType = 0; hr = CACloneCertType ( m_hCertType, strTemplateName, strDisplayName, 0, (GetType () > 1 ) ? (CT_CLONE_KEEP_SUBJECT_NAME_SETTING | CT_CLONE_KEEP_AUTOENROLLMENT_SETTING): 0, &hNewCertType); if ( SUCCEEDED (hr) ) { CACloseCertType (m_hCertType); m_hCertType = hNewCertType; m_szLDAPPath = GetDN (); hr = Initialize (); } else { _TRACE (0, L"CACloneCertType (%s, %s) failed: 0x%d\n", (PCWSTR) strTemplateName, (PCWSTR) strDisplayName, hr); } } else { _TRACE (0, L"CAFindCertTypeByName (%s) failed: 0x%x", (PCWSTR) rTemplate.GetTemplateName (), hr); } } } else hr = E_FAIL; _TRACE (-1, L"Leaving CCertTemplate::Clone: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::Delete() { _TRACE (1, L"Entering CCertTemplate::Delete - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( !(m_dwGeneralFlags & CT_FLAG_IS_DEFAULT) ) { if ( m_hCertType ) { hr = CADeleteCertType (m_hCertType); if ( FAILED (hr) ) { _TRACE (0, L"CADeleteCertType failed: 0x%x\n", hr); } } else { _TRACE (0, L"m_hCertType was unexpectedly NULL\n"); hr = E_UNEXPECTED; } } else hr = E_FAIL; _TRACE (-1, L"Leaving CCertTemplate::Delete: 0x%x\n", hr); return hr; } bool CCertTemplate::IsDefault() const { return m_dwGeneralFlags & CT_FLAG_IS_DEFAULT ? true : false; } bool CCertTemplate::IsClone() const { return m_bIsClone; } HRESULT CCertTemplate::SetTemplateName(const CString &strTemplateName) { _TRACE (1, L"Entering CCertTemplate::SetTemplateName (%s) - m_hCertType = 0x%x\n", strTemplateName, m_hCertType); HRESULT hr = S_OK; if ( LocaleStrCmp (m_strTemplateName, strTemplateName) ) { PWSTR rgwszProp[2]; rgwszProp[0] = (PWSTR)(PCWSTR) strTemplateName; rgwszProp[1] = 0;; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_CN, rgwszProp); if ( SUCCEEDED (hr) ) { m_strTemplateName = strTemplateName; } else { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_CN, %s) failed: 0x%x", rgwszProp[0], hr); } } _TRACE (-1, L"Leaving CCertTemplate::SetTemplateName: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetDisplayName(const CString &strDisplayName, bool bForce) { _TRACE (1, L"Entering CCertTemplate::SetDisplayName (%s) - m_hCertType = 0x%x\n", strDisplayName, m_hCertType); HRESULT hr = S_OK; if ( bForce || LocaleStrCmp (GetDisplayName (), strDisplayName) ) { PWSTR rgwszProp[2]; rgwszProp[0] = (PWSTR)(PCWSTR) strDisplayName; rgwszProp[1] = 0; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_FRIENDLY_NAME, rgwszProp); if ( SUCCEEDED (hr) ) { m_szDisplayName = L""; m_szDisplayName = GetDisplayName (); SetObjectName (m_szDisplayName); } else { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_FRIENDLY_NAME, %s) failed: 0x%x", rgwszProp[0], hr); } } _TRACE (-1, L"Leaving CCertTemplate::SetDisplayName: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SaveChanges(bool bIncrementMinorVersion /*=true*/) { _TRACE (1, L"Entering CCertTemplate::SaveChanges - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; m_bCanBeDeletedOnCancel = false; if ( m_hCertType ) { // Save validity period if ( -1 != m_nNewValidityDays && m_nOriginalValidityDays != m_nNewValidityDays ) { LONGLONG ll = (LONGLONG) m_nNewValidityDays * (60 * 60 * 24); // seconds ll *= CVT_BASE; ll = -ll; FILETIME ftValidity; ftValidity.dwLowDateTime = (DWORD) (ll & 0xFFFFFFFF); ftValidity.dwHighDateTime = (DWORD) (ll >> 32); // save the new value back to the cert template hr = CASetCertTypeExpiration (m_hCertType, &ftValidity, 0); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypeExpiration (validity) failed: 0x%x\n", hr); } } // Save renewal period if ( -1 != m_nNewRenewalDays && m_nOriginalRenewalDays != m_nNewRenewalDays ) { LONGLONG ll = (LONGLONG) m_nNewRenewalDays * (60 * 60 * 24); // seconds ll *= CVT_BASE; ll = -ll; // get the original value FILETIME ftRenewal; ftRenewal.dwLowDateTime = (DWORD) (ll & 0xFFFFFFFF); ftRenewal.dwHighDateTime = (DWORD) (ll >> 32); // save the new value back to the cert template hr = CASetCertTypeExpiration (m_hCertType, 0, &ftRenewal); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypeExpiration (renewal) failed: 0x%x\n", hr); } } if ( SUCCEEDED (hr) ) { if ( bIncrementMinorVersion ) hr = IncrementMinorVersion (); if ( SUCCEEDED (hr) ) { hr = CAUpdateCertType (m_hCertType); if ( SUCCEEDED (hr) ) { // If the name was changed a new template was created and the old one needs to be deleted if ( LocaleStrCmp (m_strOriginalTemplateName, m_strTemplateName) ) { HCERTTYPE hCertType = 0; HRESULT hr1 = CAFindCertTypeByName (m_strOriginalTemplateName, NULL, CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES | CT_FLAG_NO_CACHE_LOOKUP, &hCertType); if ( SUCCEEDED (hr1) ) { hr1 = CADeleteCertType (hCertType); if (FAILED (hr1) ) { _TRACE (0, L"Cert Template was renamed. Original cert template %s was found but could not be deleted: 0x%x\n", m_strOriginalTemplateName, hr); } m_strOriginalTemplateName = m_strTemplateName; hr1 = CACloseCertType (hCertType); if ( FAILED (hr1) ) { _TRACE (0, L"CACloseCertType () failed: 0x%x", hr); } } else { _TRACE (0, L"Cert Template was renamed. Unable to find original cert template %s. 0x%x\n", m_strOriginalTemplateName, hr); } } else { m_bIsClone = false; Cancel (); // cause all settings to be refreshed } } else { _TRACE (0, L"CAUpdateCertType () failed: 0x%x", hr); } } } } else hr = E_FAIL; if ( SUCCEEDED (hr) ) m_bIsClone = false; _TRACE (-1, L"Leaving CCertTemplate::SaveChanges: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetSubjectIsCA(bool bSubjectIsCA) { _TRACE (1, L"Entering CCertTemplate::SetSubjectIsCA - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = SetFlag (CERTTYPE_GENERAL_FLAG, CT_FLAG_IS_CA, bSubjectIsCA); _TRACE (-1, L"Leaving CCertTemplate::SetSubjectIsCA: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetKeySpecSignature(bool bHasKeySpecSignature) { _TRACE (1, L"Entering CCertTemplate::SetKeySpecSignature - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( m_hCertType ) { if ( bHasKeySpecSignature ) m_dwKeySpec |= AT_SIGNATURE; else m_dwKeySpec &= ~AT_SIGNATURE; hr = CASetCertTypeKeySpec (m_hCertType, m_dwKeySpec); if ( SUCCEEDED (hr) ) { PCERT_EXTENSION pCertExtension = 0; hr = GetCertExtension (szOID_KEY_USAGE, &pCertExtension); if ( SUCCEEDED (hr) && pCertExtension ) { DWORD cbKeyUsage = 0; if ( ::CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE, pCertExtension->Value.pbData, pCertExtension->Value.cbData, 0, NULL, &cbKeyUsage) ) { CRYPT_BIT_BLOB* pKeyUsage = (CRYPT_BIT_BLOB*) ::LocalAlloc (LPTR, cbKeyUsage); if ( pKeyUsage ) { if ( ::CryptDecodeObject (CRYPT_ASN_ENCODING, szOID_KEY_USAGE, pCertExtension->Value.pbData, pCertExtension->Value.cbData, 0, pKeyUsage, &cbKeyUsage) ) { if (pKeyUsage->cbData >= 1) { if ( bHasKeySpecSignature ) { pKeyUsage->pbData[0] |= CERT_DIGITAL_SIGNATURE_KEY_USAGE; // NTRAID# 312946 Cert Template Snap-in: // Should clear up the Key Encipherment // bit for signature certificate pKeyUsage->pbData[0] &= ~CERT_KEY_AGREEMENT_KEY_USAGE; pKeyUsage->pbData[0] &= ~CERT_KEY_ENCIPHERMENT_KEY_USAGE; pKeyUsage->pbData[0] &= ~CERT_DATA_ENCIPHERMENT_KEY_USAGE; } else { // is encryption only - clear the digital // signature and non-repudiation key usages pKeyUsage->pbData[0] &= ~CERT_DIGITAL_SIGNATURE_KEY_USAGE; pKeyUsage->pbData[0] &= ~CERT_NON_REPUDIATION_KEY_USAGE; if ( !(CERT_KEY_AGREEMENT_KEY_USAGE & pKeyUsage->pbData[0]) ) pKeyUsage->pbData[0] |= CERT_KEY_ENCIPHERMENT_KEY_USAGE; } pKeyUsage->cUnusedBits = 0; SetKeyUsage (pKeyUsage, pCertExtension->fCritical ? true : false); FreeCertExtensions (); } } else { DWORD dwErr = GetLastError (); _TRACE (0, L"CryptDecodeObject (szOID_KEY_USAGE) failed: 0x%x\n", dwErr); DisplaySystemError (NULL, dwErr); } ::LocalFree (pKeyUsage); } } else { DWORD dwErr = GetLastError (); _TRACE (0, L"CryptDecodeObject (szOID_KEY_USAGE) failed: 0x%x\n", dwErr); DisplaySystemError (NULL, dwErr); } } } else { _TRACE (0, L"CASetCertTypeKeySpec() failed: 0x%x\n", hr); } } else hr = E_UNEXPECTED; _TRACE (-1, L"Leaving CCertTemplate::SetKeySpecSignature: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetFlag (DWORD dwFlagType, DWORD dwFlag, bool bValue) { _TRACE (1, L"Entering CCertTemplate::SetFlag - m_hCertType = 0x%x\n", m_hCertType);; HRESULT hr = S_OK; DWORD* pdwFlags = 0; switch (dwFlagType) { case CERTTYPE_ENROLLMENT_FLAG: pdwFlags = &m_dwEnrollmentFlags; break; case CERTTYPE_SUBJECT_NAME_FLAG: pdwFlags = &m_dwSubjectNameFlags; break; case CERTTYPE_PRIVATE_KEY_FLAG: pdwFlags = &m_dwPrivateKeyFlags; break; case CERTTYPE_GENERAL_FLAG: pdwFlags = &m_dwGeneralFlags; break; default: _ASSERT (0); hr = E_FAIL; break; } if ( pdwFlags ) { if ( bValue ) *pdwFlags |= dwFlag; else *pdwFlags &= ~dwFlag; hr = CASetCertTypeFlagsEx (m_hCertType, dwFlagType, *pdwFlags); _ASSERT (SUCCEEDED (hr)); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypeFlagsEx () failed: 0x%x\n", hr); } } _TRACE (-1, L"Leaving CCertTemplate::SetFlag: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetEncryptionSignature(bool bHasEncryptionSignature) { _TRACE (1, L"Entering CCertTemplate::SetEncryptionSignature - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( m_hCertType ) { if ( bHasEncryptionSignature ) m_dwKeySpec |= AT_KEYEXCHANGE; else m_dwKeySpec &= ~AT_KEYEXCHANGE; hr = CASetCertTypeKeySpec (m_hCertType, m_dwKeySpec); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypeKeySpec() failed: 0x%x\n", hr); } } else hr = E_UNEXPECTED; _TRACE (-1, L"Leaving CCertTemplate::SetEncryptionSignature: 0x%x\n", hr); return hr; } bool CCertTemplate::CanBeDeletedOnCancel() const { return m_bCanBeDeletedOnCancel; } HRESULT CCertTemplate::SetAutoEnrollment(bool bSuitableForAutoEnrollment) { HRESULT hr = S_OK; if ( IsClone () ) { // If this is a clone, the autoenrollment flag has already been turned // off. Here we wish only to keep track of what the user's // preferences are so that we can turn it on, if desired, at the // final save. m_bGoodForAutoenrollmentFlagPendingSave = bSuitableForAutoEnrollment; } else hr = SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_AUTO_ENROLLMENT, bSuitableForAutoEnrollment); return hr; } HRESULT CCertTemplate::GetMinimumKeySize(DWORD &dwMinKeySize) const { _TRACE (1, L"Entering CCertTemplate::GetMinimumKeySize - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( m_hCertType ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_MIN_KEY_SIZE, &dwMinKeySize); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_MIN_KEY_SIZE) failed: 0x%x\n", hr); } } _TRACE (-1, L"Leaving CCertTemplate::GetMinimumKeySize (%d): 0x%x\n", dwMinKeySize, hr); return hr; } bool CCertTemplate::PrivateKeyIsExportable() const { return (m_dwPrivateKeyFlags & CT_FLAG_EXPORTABLE_KEY) ? true : false; } HRESULT CCertTemplate::MakePrivateKeyExportable(bool bMakeExportable) { return SetFlag (CERTTYPE_PRIVATE_KEY_FLAG, CT_FLAG_EXPORTABLE_KEY, bMakeExportable); } bool CCertTemplate::AllowPrivateKeyArchival() const { return (m_dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL) ? true : false; } HRESULT CCertTemplate::AllowPrivateKeyArchival(bool bAllowArchival) { return SetFlag (CERTTYPE_PRIVATE_KEY_FLAG, CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL, bAllowArchival); } bool CCertTemplate::IncludeSymmetricAlgorithms() const { return (m_dwEnrollmentFlags & CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS) ? true : false; } HRESULT CCertTemplate::IncludeSymmetricAlgorithms(bool bInclude) { return SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS, bInclude); } HRESULT CCertTemplate::DoAutoEnrollmentPendingSave() { HRESULT hr = S_OK; if ( m_hCertType ) { if ( IsClone () && m_bGoodForAutoenrollmentFlagPendingSave ) { // Set the flag for real hr = SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_AUTO_ENROLLMENT, true); // Save changes if ( SUCCEEDED (hr) ) hr = SaveChanges (); } } else hr = E_FAIL; return hr; } bool CCertTemplate::AltNameIncludesDNS() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_ALT_REQUIRE_DNS) ? true : false; } HRESULT CCertTemplate::AltNameIncludesDNS(bool fIncludeDNS) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_ALT_REQUIRE_DNS, fIncludeDNS); } bool CCertTemplate::AltNameIncludesEMail() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL) ? true : false; } HRESULT CCertTemplate::AltNameIncludesEMail(bool bIncludesEMail) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL, bIncludesEMail); } bool CCertTemplate::AltNameIncludesUPN() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_ALT_REQUIRE_UPN) ? true : false; } HRESULT CCertTemplate::AltNameIncludesUPN(bool bIncludesUPN) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_ALT_REQUIRE_UPN, bIncludesUPN); } bool CCertTemplate::SubjectNameIncludesEMail() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_REQUIRE_EMAIL) ? true : false; } HRESULT CCertTemplate::SubjectNameIncludesEMail(bool bIncludesEMail) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_REQUIRE_EMAIL, bIncludesEMail); } bool CCertTemplate::SubjectNameMustBeFullDN() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH) ? true : false; } HRESULT CCertTemplate::SubjectNameMustBeFullDN(bool bMustBeDN) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH, bMustBeDN); } bool CCertTemplate::SubjectNameMustBeCN() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME) ? true : false; } HRESULT CCertTemplate::SubjectNameMustBeCN(bool bMustBeCN) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME, bMustBeCN); } HRESULT CCertTemplate::RequireSubjectInRequest(bool bRequire) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT, bRequire); } bool CCertTemplate::AltNameIncludesSPN() const { return (m_dwSubjectNameFlags & CT_FLAG_SUBJECT_ALT_REQUIRE_SPN) ? true : false; } HRESULT CCertTemplate::AltNameIncludesSPN(bool bIncludesSPN) { return SetFlag (CERTTYPE_SUBJECT_NAME_FLAG, CT_FLAG_SUBJECT_ALT_REQUIRE_SPN, bIncludesSPN); } HRESULT CCertTemplate::SetMinimumKeySizeValue(DWORD dwMinKeySize) { _TRACE (1, L"Entering CCertTemplate::SetMinimumKeySizeValue (%d)- m_hCertType = 0x%x\n", dwMinKeySize, m_hCertType); HRESULT hr = S_OK; if ( m_hCertType ) { hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_MIN_KEY_SIZE, &dwMinKeySize); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_MIN_KEY_SIZE) failed: 0x%x\n", hr); } } _TRACE (-1, L"Leaving CCertTemplate::SetMinimumKeySizeValue (%d): 0x%x\n", dwMinKeySize, hr); return hr; } HRESULT CCertTemplate::ModifyCriticalExtensions (const CString &szExtension, bool bAdd) { _TRACE (1, L"Entering CCertTemplate::ModifyCriticalExtensions (%s, bAdd=%s)\n", (PCWSTR) szExtension, bAdd ? L"true" : L"false"); PWSTR* pawszCriticalExtensions = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_CRITICAL_EXTENSIONS, &pawszCriticalExtensions); if ( SUCCEEDED (hr) ) { if ( !pawszCriticalExtensions ) pawszCriticalExtensions = (PWSTR*) LocalAlloc (LPTR, sizeof (PWSTR)); if ( pawszCriticalExtensions ) { hr = ModifyStringList (CERTTYPE_PROP_CRITICAL_EXTENSIONS, &pawszCriticalExtensions, szExtension, bAdd); LocalFree (pawszCriticalExtensions); } else hr = E_OUTOFMEMORY; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_CRITICAL_EXTENSIONS) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::ModifyCriticalExtensions: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::ModifyCSPList(const CString &szCSPName, bool bAdd) { _TRACE (1, L"Entering CCertTemplate::ModifyCSPList (%s, bAdd=%s)\n", (PCWSTR) szCSPName, bAdd ? L"true" : L"false"); PWSTR* pawszCSPList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_CSP_LIST, &pawszCSPList); if ( SUCCEEDED (hr) ) { if ( !pawszCSPList ) pawszCSPList = (PWSTR*) LocalAlloc (LPTR, sizeof (PWSTR*)); if ( pawszCSPList ) { hr = ModifyStringList (CERTTYPE_PROP_CSP_LIST, &pawszCSPList, szCSPName, bAdd); LocalFree (pawszCSPList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_CSP_LIST) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::ModifyCSPList: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::ModifyRAIssuancePolicyList(const CString &szRAPolicyOID, bool bAdd) { _TRACE (1, L"Entering CCertTemplate::ModifyRAIssuancePolicyList (%s, bAdd=%s)\n", (PCWSTR) szRAPolicyOID, bAdd ? L"true" : L"false"); PWSTR* pawszRAPolicyList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_RA_POLICY, &pawszRAPolicyList); if ( SUCCEEDED (hr) ) { if ( !pawszRAPolicyList ) pawszRAPolicyList = (PWSTR*) LocalAlloc (LPTR, sizeof (PWSTR*)); if ( pawszRAPolicyList ) { hr = ModifyStringList (CERTTYPE_PROP_RA_POLICY, &pawszRAPolicyList, szRAPolicyOID, bAdd); LocalFree (pawszRAPolicyList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_RA_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::ModifyRAIssuancePolicyList: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::ModifyRAApplicationPolicyList(const CString &szRAPolicyOID, bool bAdd) { _TRACE (1, L"Entering CCertTemplate::ModifyRAApplicationPolicyList (%s, bAdd=%s)\n", (PCWSTR) szRAPolicyOID, bAdd ? L"true" : L"false"); PWSTR* pawszRAPolicyList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_RA_APPLICATION_POLICY, &pawszRAPolicyList); if ( SUCCEEDED (hr) ) { if ( !pawszRAPolicyList ) pawszRAPolicyList = (PWSTR*) LocalAlloc (LPTR, sizeof (PWSTR*)); if ( pawszRAPolicyList ) { hr = ModifyStringList (CERTTYPE_PROP_RA_APPLICATION_POLICY, &pawszRAPolicyList, szRAPolicyOID, bAdd); LocalFree (pawszRAPolicyList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_RA_APPLICATION_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::ModifyRAApplicationPolicyList: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::ModifySupercededTemplateList( const CString &szSupercededTemplateName, bool bAdd) { _TRACE (1, L"Entering CCertTemplate::ModifySupercededTemplateList (%s, bAdd=%s)\n", (PCWSTR) szSupercededTemplateName, bAdd ? L"true" : L"false"); PWSTR* pawszSupercededTemplateList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_SUPERSEDE, &pawszSupercededTemplateList); if ( SUCCEEDED (hr) ) { if ( !pawszSupercededTemplateList ) pawszSupercededTemplateList = (PWSTR*) LocalAlloc (LPTR, sizeof (PWSTR*)); if ( pawszSupercededTemplateList ) { hr = ModifyStringList (CERTTYPE_PROP_SUPERSEDE, &pawszSupercededTemplateList, szSupercededTemplateName, bAdd); LocalFree (pawszSupercededTemplateList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_SUPERSEDE) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::ModifySupercededTemplateList: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::ModifyStringList(const CString& szPropertyName, PWSTR** ppStringList, const CString &szValue, bool bAdd) { _TRACE (1, L"Entering CCertTemplate::ModifyStringList (%s, bAdd=%s)\n", (PCWSTR) szValue, bAdd ? L"true" : L"false"); HRESULT hr = S_OK; if ( !szValue.IsEmpty () ) { bool bFound = false; int nCnt = 0; size_t cbNameBytes = 0; int nDeleteIndex = -1; // count the number of items we already have and get the string lengths for (int nIndex = 0; (*ppStringList)[nIndex]; nIndex++) { nCnt++; // security review 2/21/2002 BryanWal ok cbNameBytes += (wcslen ((*ppStringList)[nIndex]) + 1) * sizeof (WCHAR); if ( !LocaleStrCmp (szValue, (*ppStringList)[nIndex]) ) { bFound = true; if ( !bAdd ) nDeleteIndex = nIndex; } } // Adding a name: If the name was found, nothing needs to be done, // otherwise, increment the count and rebuild the list. // Removing a name: If the name was not found, nothing needs to be // done, otherwise, decrement the count and rebuild the list. if ( (bAdd && !bFound) || (!bAdd && bFound) ) { // awszResult is an array of pointers to different offsets of // null-terminated strings stored in a contiguous array PWSTR *awszResult = 0; if ( bAdd ) nCnt++; else nCnt--; if ( bAdd ) { // security review 2/21/2002 BryanWal ok cbNameBytes += (wcslen (szValue) + 1 ) * sizeof (WCHAR); } size_t cbBuf = sizeof (WCHAR*) * (nCnt + 1) + // the WCHAR pointers cbNameBytes; // the strings themselves awszResult = (WCHAR**) LocalAlloc (LPTR, cbBuf); if ( awszResult ) { // set the ptr to the space after the last valid index ( // including the NULL terminator PWSTR ptr = (WCHAR*) &awszResult[nCnt+1]; int nTgtIndex = 0; for (int nSrcIndex = 0; (*ppStringList)[nSrcIndex]; nSrcIndex++) { // If we are removing the name, and this is the item to be // removed, then skip this name and go to the next if ( !bAdd && nSrcIndex == nDeleteIndex ) continue; awszResult[nTgtIndex] = ptr; // security review 2/21/2002 BryanWal ok ptr += wcslen ((*ppStringList)[nSrcIndex]) + 1; // ptr arithmetic - increments by sizeof (WCHAR) // security review 2/21/2002 BryanWal ok wcscpy (awszResult[nTgtIndex], (*ppStringList)[nSrcIndex]); nTgtIndex++; } // If we are adding, append the name here if ( bAdd ) { awszResult[nTgtIndex] = ptr; // security review 2/21/2002 BryanWal ok ptr += wcslen (szValue) + 1; // ptr arithmetic - increments by sizeof (WCHAR) // security review 2/21/2002 BryanWal ok wcscpy (awszResult[nTgtIndex], szValue); nTgtIndex++; } _ASSERT (nTgtIndex == nCnt); awszResult[nTgtIndex] = 0; LocalFree (*ppStringList); (*ppStringList) = awszResult; hr = CASetCertTypePropertyEx (m_hCertType, szPropertyName, (*ppStringList)); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypePropertyEx (%s) failed: 0x%x\n", szPropertyName, hr); } } else hr = E_OUTOFMEMORY; } } else hr = E_INVALIDARG; _TRACE (-1, L"Leaving CCertTemplate::ModifyStringList: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::IsExtensionCritical (PCWSTR szExtension, bool& bCritical) { _TRACE (1, L"Entering CCertTemplate::IsExtensionCritical (szExtension=%s\n", szExtension); // Get Cryptographic Service Providers PWSTR* pawszCriticalExtensionList = 0; bCritical = false; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_CRITICAL_EXTENSIONS, &pawszCriticalExtensionList); if ( SUCCEEDED (hr) ) { if ( pawszCriticalExtensionList ) { for (int nIndex = 0; pawszCriticalExtensionList[nIndex]; nIndex++) { if ( !wcscmp (szExtension, pawszCriticalExtensionList[nIndex]) ) { bCritical = true; break; } } LocalFree (pawszCriticalExtensionList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_CRITICAL_EXTENSIONS) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GeIsExtensionCriticaltCSP (szCSP=%s, bCritical=%s): 0x%x\n", szExtension, bCritical ? L"true" : L"false", hr); return hr; } HRESULT CCertTemplate::GetCSP(int nIndex, CString &szCSP) { _TRACE (1, L"Entering CCertTemplate::GetCSP (nIndex=%d\n", nIndex); // Get Cryptographic Service Providers PWSTR* pawszCSPList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_CSP_LIST, &pawszCSPList); if ( SUCCEEDED (hr) ) { if ( pawszCSPList ) { int nCnt = 0; while ( pawszCSPList[nCnt] ) nCnt++; if ( nIndex < nCnt ) szCSP = pawszCSPList[nIndex]; else hr = E_INVALIDARG; LocalFree (pawszCSPList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_CSP_LIST) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetCSP (szCSP=%s): 0x%x\n", (PCWSTR) szCSP, hr); return hr; } HRESULT CCertTemplate::GetCertPolicy (int nIndex, CString &szCertPolicy) { _TRACE (1, L"Entering CCertTemplate::GetCertPolicy (nIndex=%d\n", nIndex); HRESULT hr = S_OK; PWSTR* pawszCertPolicyList = 0; hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_POLICY, &pawszCertPolicyList); if ( SUCCEEDED (hr) ) { if ( pawszCertPolicyList ) { int nCnt = 0; while ( pawszCertPolicyList[nCnt] ) nCnt++; if ( nIndex < nCnt ) szCertPolicy = pawszCertPolicyList[nIndex]; else hr = E_FAIL; LocalFree (pawszCertPolicyList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetCertPolicy (szCSP=%s): 0x%x\n", (PCWSTR) szCertPolicy, hr); return hr; } HRESULT CCertTemplate::GetRAIssuancePolicy (int nIndex, CString &szRAPolicyOID) { _TRACE (1, L"Entering CCertTemplate::GetRAIssuancePolicy (nIndex=%d\n", nIndex); PWSTR* pawszRAPolicyList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_RA_POLICY, &pawszRAPolicyList); if ( SUCCEEDED (hr) ) { if ( pawszRAPolicyList ) { int nCnt = 0; while ( pawszRAPolicyList[nCnt] ) nCnt++; if ( nIndex < nCnt ) szRAPolicyOID = pawszRAPolicyList[nIndex]; else hr = E_FAIL; LocalFree (pawszRAPolicyList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_RA_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetRAIssuancePolicy (szRAPolicyOID=%s): 0x%x\n", (PCWSTR) szRAPolicyOID, hr); return hr; } HRESULT CCertTemplate::GetRAApplicationPolicy (int nIndex, CString &szRAPolicyOID) { _TRACE (1, L"Entering CCertTemplate::GetRAApplicationPolicy (nIndex=%d\n", nIndex); PWSTR* pawszRAPolicyList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_RA_APPLICATION_POLICY, &pawszRAPolicyList); if ( SUCCEEDED (hr) ) { if ( pawszRAPolicyList ) { int nCnt = 0; while ( pawszRAPolicyList[nCnt] ) nCnt++; if ( nIndex < nCnt ) szRAPolicyOID = pawszRAPolicyList[nIndex]; else hr = E_FAIL; LocalFree (pawszRAPolicyList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_RA_APPLICATION_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetRAApplicationPolicy (szRAPolicyOID=%s): 0x%x\n", (PCWSTR) szRAPolicyOID, hr); return hr; } HRESULT CCertTemplate::GetSupercededTemplate(int nIndex, CString &szSupercededTemplate) { _TRACE (1, L"Entering CCertTemplate::GetSupercededTemplate (nIndex=%d\n", nIndex); PWSTR* pawszSupercededTemplateList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_SUPERSEDE, &pawszSupercededTemplateList); if ( SUCCEEDED (hr) ) { if ( pawszSupercededTemplateList ) { int nCnt = 0; while ( pawszSupercededTemplateList[nCnt] ) nCnt++; if ( nIndex < nCnt ) szSupercededTemplate = pawszSupercededTemplateList[nIndex]; else hr = E_FAIL; LocalFree (pawszSupercededTemplateList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_SUPERSEDE) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetSupercededTemplate (szSupercededTemplate=%s): 0x%x\n", (PCWSTR) szSupercededTemplate, hr); return hr; } bool CCertTemplate::ReadOnly() const { return m_fIsReadOnly; } HRESULT CCertTemplate::SetSecurity(PSECURITY_DESCRIPTOR pSD) { HRESULT hr = CACertTypeSetSecurity (m_hCertType, pSD); if (S_OK != hr) return hr; for (int nTry = 0; nTry < 20; nTry++) { hr = CAUpdateCertType(m_hCertType); if ( FAILED (hr) && HRESULT_FROM_WIN32 (ERROR_DS_OBJ_NOT_FOUND) == hr ) { // pause and retry up to 20 times - object was renamed and needs a // little time to propagate // NTRAID# 643744 Certtmpl: Cannot save security settings on newly // cloned template from member in non Root Domain -- object not found Sleep (1000); continue; } else break; } if ( FAILED (hr) ) Cancel (); return hr; } HRESULT CCertTemplate::GetSecurity(PSECURITY_DESCRIPTOR *ppSD) const { return CACertTypeGetSecurity (m_hCertType, ppSD); } CString CCertTemplate::GetLDAPPath() const { return m_szLDAPPath; } HRESULT CCertTemplate::SetValidityPeriod(int nDays) { HRESULT hr = S_OK; if ( nDays >= 0 ) this->m_nNewValidityDays = nDays; else hr = E_INVALIDARG; return hr; } HRESULT CCertTemplate::SetRenewalPeriod(int nDays) { HRESULT hr = S_OK; if ( nDays >= 0 ) this->m_nNewRenewalDays = nDays; else hr = E_INVALIDARG; return hr; } HRESULT CCertTemplate::SetPublishToDS(bool bPublish) { _TRACE (1, L"Entering CCertTemplate::SetPublishToDS - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_PUBLISH_TO_DS, bPublish); _TRACE (-1, L"Leaving CCertTemplate::SetPublishToDS: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::GetRANumSignaturesRequired(DWORD &dwNumSignatures) { _TRACE (1, L"Entering CCertTemplate::GetRANumSignaturesRequired - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; if ( m_hCertType ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_RA_SIGNATURE, &dwNumSignatures); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_RA_SIGNATURE) failed: 0x%x\n", hr); } } else hr = E_FAIL; _TRACE (-1, L"Leaving CCertTemplate::GetRANumSignaturesRequired: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetRANumSignaturesRequired(DWORD dwNumSignaturesRequired) { _TRACE (1, L"Entering CCertTemplate::SetRANumSignaturesRequired (%d)- m_hCertType = 0x%x\n", dwNumSignaturesRequired, m_hCertType); HRESULT hr = S_OK; if ( m_hCertType ) { hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_RA_SIGNATURE, &dwNumSignaturesRequired); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_RA_SIGNATURE) failed: 0x%x\n", hr); } } else hr = E_FAIL; _TRACE (-1, L"Leaving CCertTemplate::SetRANumSignaturesRequired (): 0x%x\n", hr); return hr; } bool CCertTemplate::ReenrollmentValidWithPreviousApproval() const { return m_dwEnrollmentFlags & CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT ? true : false; } HRESULT CCertTemplate::SetReenrollmentValidWithPreviousApproval(bool bValid) { _TRACE (1, L"Entering CCertTemplate::SetReenrollmentValidWithPreviousApproval - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT, bValid); _TRACE (-1, L"Leaving CCertTemplate::SetReenrollmentValidWithPreviousApproval: 0x%x\n", hr); return hr; } bool CCertTemplate::PendAllRequests() const { return m_dwEnrollmentFlags & CT_FLAG_PEND_ALL_REQUESTS ? true : false; } HRESULT CCertTemplate::SetPendAllRequests(bool bPend) { _TRACE (1, L"Entering CCertTemplate::SetPendAllRequests - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_PEND_ALL_REQUESTS, bPend); _TRACE (-1, L"Leaving CCertTemplate::SetPendAllRequests: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::GetMajorVersion(DWORD &dwMajorVersion) const { // _TRACE (1, L"Entering CCertTemplate::GetMajorVersion\n"); HRESULT hr = S_OK; if ( m_hCertType ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_REVISION, &dwMajorVersion); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_REVISION) failed: 0x%x\n", hr); } } else hr = E_FAIL; // _TRACE (-1, L"Leaving CCertTemplate::GetMajorVersion (dwMajorVersion = %d) : 0x%x\n", // dwMajorVersion, hr); return hr; } HRESULT CCertTemplate::GetMinorVersion(DWORD &dwMinorVersion) const { // _TRACE (1, L"Entering CCertTemplate::GetMinorVersion\n"); HRESULT hr = S_OK; if ( m_hCertType ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_MINOR_REVISION, &dwMinorVersion); if ( FAILED (hr) ) { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_MINOR_REVISION) failed: 0x%x\n", hr); } } else hr = E_FAIL; // _TRACE (-1, L"Leaving CCertTemplate::GetMinorVersion (dwMinorVersion = %d) : 0x%x\n", // dwMinorVersion, hr); return hr; } HRESULT CCertTemplate::IncrementMajorVersion() { _TRACE (1, L"Entering CCertTemplate::IncrementMajorVersion\n"); HRESULT hr = S_OK; DWORD dwMajorVersion = 0; if ( m_hCertType ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_REVISION, &dwMajorVersion); if ( SUCCEEDED (hr) ) { dwMajorVersion++; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_REVISION, &dwMajorVersion); if ( SUCCEEDED (hr) ) { DWORD dwMinorVersion = 0; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_MINOR_REVISION, &dwMinorVersion); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_MINOR_REVISION, %d) failed: 0x%x\n", dwMinorVersion, hr); } } else { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_REVISION, %d) failed: 0x%x\n", dwMajorVersion, hr); } } else { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_REVISION) failed: 0x%x\n", hr); } } else hr = E_FAIL; _TRACE (-1, L"Leaving CCertTemplate::IncrementMajorVersion (dwMajorVersion = %d) : 0x%x\n", dwMajorVersion, hr); return hr; } HRESULT CCertTemplate::IncrementMinorVersion() { _TRACE (1, L"Entering CCertTemplate::IncrementMinorVersion\n"); HRESULT hr = S_OK; DWORD dwMinorVersion = 0; if ( m_hCertType ) { hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_MINOR_REVISION, &dwMinorVersion); if ( SUCCEEDED (hr) ) { dwMinorVersion++; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_MINOR_REVISION, &dwMinorVersion); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_MINOR_REVISION, %d) failed: 0x%x\n", dwMinorVersion, hr); } } else { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_MINOR_REVISION) failed: 0x%x\n", hr); } } else hr = E_FAIL; _TRACE (-1, L"Leaving CCertTemplate::IncrementMinorVersion (dwMinorVersion = %d) : 0x%x\n", dwMinorVersion, hr); return hr; } bool CCertTemplate::GoodForAutoEnrollment() const { bool bGoodForAutoEnrollment = false; // Bug 175912 Version 1 type templates not good for autoenrollment if ( (GetType () > 1) && (m_dwEnrollmentFlags & CT_FLAG_AUTO_ENROLLMENT) ) bGoodForAutoEnrollment = true; return bGoodForAutoEnrollment; } HRESULT CCertTemplate::SetKeyUsage(CRYPT_BIT_BLOB* pKeyUsage, bool bCritical) { _TRACE (1, L"Entering CCertTemplate::SetKeyUsage\n"); HRESULT hr = S_OK; if ( pKeyUsage ) { hr = CASetCertTypeExtension( m_hCertType, TEXT (szOID_KEY_USAGE), bCritical ? CA_EXT_FLAG_CRITICAL : 0, pKeyUsage); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypeExtension (szOID_KEY_USAGE) failed: 0x%x\n", hr); } } else hr = E_POINTER; _TRACE (-1, L"Leaving CCertTemplate::SetKeyUsage: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetBasicConstraints(PCERT_BASIC_CONSTRAINTS2_INFO pBCInfo, bool bCritical) { _TRACE (1, L"Entering CCertTemplate::SetBasicConstraints\n"); HRESULT hr = S_OK; if ( pBCInfo ) { hr = CASetCertTypeExtension( m_hCertType, TEXT (szOID_BASIC_CONSTRAINTS2), bCritical ? CA_EXT_FLAG_CRITICAL : 0, pBCInfo); if ( FAILED (hr) ) { _TRACE (0, L"CASetCertTypeExtension (X509_BASIC_CONSTRAINTS2) failed: 0x%x\n", hr); } } else hr = E_POINTER; _TRACE (-1, L"Leaving CCertTemplate::SetBasicConstraints: 0x%x\n", hr); return hr; } bool CCertTemplate::CheckDSCert() const { return (m_dwEnrollmentFlags & CT_FLAG_AUTO_ENROLLMENT_CHECK_USER_DS_CERTIFICATE) ? true : false; } HRESULT CCertTemplate::SetCheckDSCert(bool bCheck) { return SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_AUTO_ENROLLMENT_CHECK_USER_DS_CERTIFICATE, bCheck); } bool CCertTemplate::RemoveInvalidCertFromPersonalStore () const { return (m_dwEnrollmentFlags & CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE) ? true : false; } HRESULT CCertTemplate::SetRemoveInvalidCertFromPersonalStore(bool bRemove) { return SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE, bRemove); } bool CCertTemplate::UserInteractionRequired () const { return (m_dwEnrollmentFlags & CT_FLAG_USER_INTERACTION_REQUIRED) ? true : false; } HRESULT CCertTemplate::SetUserInteractionRequired(bool bSet) { return SetFlag (CERTTYPE_ENROLLMENT_FLAG, CT_FLAG_USER_INTERACTION_REQUIRED, bSet); } bool CCertTemplate::StrongKeyProtectionRequired () const { return (m_dwPrivateKeyFlags & CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED) ? true : false; } HRESULT CCertTemplate::SetStrongKeyProtectionRequired(bool bSet) { return SetFlag (CERTTYPE_PRIVATE_KEY_FLAG, CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED, bSet); } HRESULT CCertTemplate::GetEnhancedKeyUsage (int nIndex, CString &szEKU) { _TRACE (1, L"Entering CCertTemplate::GetEnhancedKeyUsage (nIndex=%d\n", nIndex); HRESULT hr = S_OK; PWSTR* pawszEKU = 0; hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_EXTENDED_KEY_USAGE, &pawszEKU); if ( SUCCEEDED (hr) ) { if ( pawszEKU ) { int nCnt = 0; while ( pawszEKU[nCnt] ) nCnt++; if ( nIndex < nCnt ) szEKU = pawszEKU[nIndex]; else hr = E_FAIL; } else hr = E_FAIL; LocalFree (pawszEKU); } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_EXTENDED_KEY_USAGE) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetEnhancedKeyUsage (szEKU=%s): 0x%x\n", (PCWSTR) szEKU, hr); return hr; } HRESULT CCertTemplate::GetApplicationPolicy (int nIndex, CString &szAppPolicy) { _TRACE (1, L"Entering CCertTemplate::GetApplicationPolicy (nIndex=%d\n", nIndex); HRESULT hr = S_OK; PWSTR* pawszAppPolicy = 0; hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_APPLICATION_POLICY, &pawszAppPolicy); if ( SUCCEEDED (hr) ) { if ( pawszAppPolicy ) { int nCnt = 0; while ( pawszAppPolicy[nCnt] ) nCnt++; if ( nIndex < nCnt ) szAppPolicy = pawszAppPolicy[nIndex]; else hr = E_FAIL; } else hr = E_FAIL; LocalFree (pawszAppPolicy); } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_APPLICATION_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetApplicationPolicy (szAppPolicy=%s): 0x%x\n", (PCWSTR) szAppPolicy, hr); return hr; } HRESULT CCertTemplate::SetEnhancedKeyUsage (const PWSTR* pawszEKU, bool bCritical) { _TRACE (1, L"Entering CCertTemplate::SetEnhancedKeyUsage ()\n"); HRESULT hr = S_OK; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_EXTENDED_KEY_USAGE, (PVOID) pawszEKU); if ( SUCCEEDED (hr) ) { hr = ModifyCriticalExtensions (szOID_ENHANCED_KEY_USAGE, bCritical); } else { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_EXTENDED_KEY_USAGE) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::SetEnhancedKeyUsage: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetApplicationPolicy (const PWSTR* pawszAppPolicy, bool bCritical) { _TRACE (1, L"Entering CCertTemplate::SetApplicationPolicy ()\n"); HRESULT hr = S_OK; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_APPLICATION_POLICY, (PVOID) pawszAppPolicy); if ( SUCCEEDED (hr) ) { hr = ModifyCriticalExtensions (szOID_APPLICATION_CERT_POLICIES, bCritical); } else { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_APPLICATION_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::SetApplicationPolicy: 0x%x\n", hr); return hr; } HRESULT CCertTemplate::SetCertPolicy (const PWSTR* pawszCertPolicy, bool bCritical) { _TRACE (1, L"Entering CCertTemplate::SetCertPolicy ()\n"); HRESULT hr = S_OK; hr = CASetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_POLICY, (PVOID) pawszCertPolicy); if ( SUCCEEDED (hr) ) { hr = ModifyCriticalExtensions (szOID_CERT_POLICIES, bCritical); } else { _TRACE (0, L"CASetCertTypePropertyEx (CERTTYPE_PROP_POLICY) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::SetCertPolicy: 0x%x\n", hr); return hr; } void CCertTemplate::FreeCertExtensions() { if ( m_pCertExtensions ) { CAFreeCertTypeExtensions (m_hCertType, m_pCertExtensions); m_pCertExtensions = 0; } } HRESULT CCertTemplate::Cancel() { _TRACE (1, L"Entering CCertTemplate::Cancel\n"); HRESULT hr = S_OK; // Close and re-open cert template without saving. if ( m_hCertType ) { FreeCertExtensions (); hr = CACloseCertType (m_hCertType); _ASSERT (SUCCEEDED (hr)); if ( SUCCEEDED (hr) ) { m_hCertType = 0; // Reinitialize the cert template if ( !m_bIsClone ) hr = Initialize (); } else { _TRACE (0, L"CACloseCertType (%s) failed: 0x%x\n", hr); } } else hr = E_FAIL; _TRACE (-1, L":Leaving CCertTemplate::Cancel: 0x%x\n", hr); return hr; } /* NO LONGER NEEDED NTRAID# 321742 bool CCertTemplate::AllowAutoenrollment() { // Bug 251388 "There are templates that should never be allowed to set // autoenrollment flag (CT_FLAG_AUTO_ENROLLMENT). The "Allow // Autoenrollment" task for those templates should be disabled if one of // the following three conditions is true: // // templates whose subject name flag has CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT // set; // templates whose subject name flag has // CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME set; // templates whose CERTTYPE_PROP_RA_SIGNATURE is greater than 1 and // CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT is not set in the // enrollment flag." bool bResult = true; DWORD dwNumSignatures = 0; GetRANumSignaturesRequired (dwNumSignatures); // NTRAID# 175912 Version 1 type templates not good for autoenrollment if ( 1 == GetType () || (m_dwSubjectNameFlags & CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT) || (m_dwSubjectNameFlags & CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME) || ( dwNumSignatures > 1 && !(m_dwEnrollmentFlags & CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT)) ) { bResult = false; } // NTRAID# 276180 Certificate Template Snap-in: Grey out "Allow // Autoenrollment" context menu based on properties of the template if ( RequireSubjectInRequest () || dwNumSignatures >= 2 && !ReenrollmentValidWithPreviousApproval () ) { bResult = false; } return bResult; } */ HRESULT CCertTemplate::GetSubjectTypeDescription (int nIndex, CString &szSubjectTypeDescription) { _TRACE (1, L"Entering CCertTemplate::GetSubjectTypeDescription (nIndex=%d\n", nIndex); PWSTR* pawszSubjectTypeDescriptionList = 0; HRESULT hr = CAGetCertTypeProperty (m_hCertType, CERTTYPE_PROP_DESCRIPTION, &pawszSubjectTypeDescriptionList); if ( SUCCEEDED (hr) ) { if ( pawszSubjectTypeDescriptionList ) { int nCnt = 0; while ( pawszSubjectTypeDescriptionList[nCnt] ) nCnt++; if ( nIndex < nCnt ) szSubjectTypeDescription = pawszSubjectTypeDescriptionList[nIndex]; else hr = E_FAIL; LocalFree (pawszSubjectTypeDescriptionList); } else hr = E_FAIL; } else { _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_DESCRIPTION) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving CCertTemplate::GetSubjectTypeDescription (szRAPolicyOID=%s): 0x%x\n", (PCWSTR) szSubjectTypeDescription, hr); return hr; } // NTRAID# 278356 CertSRV: No CSPs in mmc certificate snapin advanced // option list with v2 templates that have ENC and SIG as purpose. HRESULT CCertTemplate::SetDigitalSignature( bool bSet, bool bSetOnlyDigitalSignature /* = false */) { _TRACE (1, L"Entering CCertTemplate::SetDigitalSignature (bSet = %s)\n", bSet ? L"true" : L"false"); PCERT_EXTENSION pCertExtension = 0; HRESULT hr = GetCertExtension (szOID_KEY_USAGE, &pCertExtension); if ( SUCCEEDED (hr) ) { ASSERT (pCertExtension); if ( pCertExtension ) { DWORD cbKeyUsage = 0; if ( ::CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE, pCertExtension->Value.pbData, pCertExtension->Value.cbData, 0, NULL, &cbKeyUsage) ) { CRYPT_BIT_BLOB* pKeyUsage = (CRYPT_BIT_BLOB*) ::LocalAlloc (LPTR, cbKeyUsage); if ( pKeyUsage ) { if ( ::CryptDecodeObject (CRYPT_ASN_ENCODING, szOID_KEY_USAGE, pCertExtension->Value.pbData, pCertExtension->Value.cbData, 0, pKeyUsage, &cbKeyUsage) ) { if (pKeyUsage->cbData >= 1) { pKeyUsage->cUnusedBits = 0; if ( bSetOnlyDigitalSignature ) { pKeyUsage->pbData[0] = CERT_DIGITAL_SIGNATURE_KEY_USAGE; } else if ( bSet ) pKeyUsage->pbData[0] |= CERT_DIGITAL_SIGNATURE_KEY_USAGE; else pKeyUsage->pbData[0] &= ~CERT_DIGITAL_SIGNATURE_KEY_USAGE; hr = SetKeyUsage (pKeyUsage, pCertExtension->fCritical ? true : false); } else hr = E_FAIL; } else { DWORD dwErr = GetLastError (); hr = HRESULT_FROM_WIN32 (dwErr); _TRACE (0, L"CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE) failed: 0x%x\n", dwErr); } LocalFree (pKeyUsage); } else hr = E_OUTOFMEMORY; } else { DWORD dwErr = GetLastError (); hr = HRESULT_FROM_WIN32 (dwErr); _TRACE (0, L"CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE) failed: 0x%x\n", dwErr); } } FreeCertExtensions (); } _TRACE (-1, L"Leaving CCertTemplate::SetDigitalSignature (bSet = %s): 0x%x\n", bSet ? L"true" : L"false", hr); return hr; } HRESULT CCertTemplate::GetDigitalSignature( bool &bHasDigitalSignature, bool* pbHasOnlyDigitalSignature /* = 0 */) { _TRACE (1, L"Entering CCertTemplate::GetDigitalSignature ()\n"); PCERT_EXTENSION pCertExtension = 0; HRESULT hr = GetCertExtension (szOID_KEY_USAGE, &pCertExtension); if ( SUCCEEDED (hr) ) { ASSERT (pCertExtension); if ( pCertExtension ) { DWORD cbKeyUsage = 0; if ( ::CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE, pCertExtension->Value.pbData, pCertExtension->Value.cbData, 0, NULL, &cbKeyUsage) ) { CRYPT_BIT_BLOB* pKeyUsage = (CRYPT_BIT_BLOB*) ::LocalAlloc (LPTR, cbKeyUsage); if ( pKeyUsage ) { if ( ::CryptDecodeObject (CRYPT_ASN_ENCODING, szOID_KEY_USAGE, pCertExtension->Value.pbData, pCertExtension->Value.cbData, 0, pKeyUsage, &cbKeyUsage) ) { if (pKeyUsage->cbData >= 1) { pKeyUsage->cUnusedBits = 0; if ( pKeyUsage->pbData[0] & CERT_DIGITAL_SIGNATURE_KEY_USAGE ) bHasDigitalSignature = true; else bHasDigitalSignature = false; if ( pbHasOnlyDigitalSignature ) { if ( pKeyUsage->pbData[0] == CERT_DIGITAL_SIGNATURE_KEY_USAGE ) *pbHasOnlyDigitalSignature = true; else *pbHasOnlyDigitalSignature = false; } } else hr = E_FAIL; } else { DWORD dwErr = GetLastError (); hr = HRESULT_FROM_WIN32 (dwErr); _TRACE (0, L"CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE) failed: 0x%x\n", dwErr); } LocalFree (pKeyUsage); } else hr = E_OUTOFMEMORY; } else { DWORD dwErr = GetLastError (); hr = HRESULT_FROM_WIN32 (dwErr); _TRACE (0, L"CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_KEY_USAGE) failed: 0x%x\n", dwErr); } } FreeCertExtensions (); } _TRACE (-1, L"Leaving CCertTemplate::GetDigitalSignature (bHasDigitalSignature = %s): 0x%x\n", bHasDigitalSignature ? L"true" : L"false", hr); return hr; } void CCertTemplate::IssuancePoliciesRequired(bool bRequired) { m_bIssuancePoliciesRequired = bRequired; } bool CCertTemplate::IssuancePoliciesRequired() const { return m_bIssuancePoliciesRequired; } CString CCertTemplate::GetDN () const { _TRACE (1, L"Entering CCertTemplate::GetDN - m_hCertType = 0x%x\n", m_hCertType); HRESULT hr = S_OK; CString szDN; if ( m_hCertType ) { PWSTR* rgwszProp = 0; hr = CAGetCertTypePropertyEx (m_hCertType, CERTTYPE_PROP_DN, &rgwszProp); if ( SUCCEEDED (hr) && rgwszProp ) { szDN = *rgwszProp; CAFreeCertTypeProperty (m_hCertType, rgwszProp); } else { _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_DN) failed: 0x%x\n", hr); szDN = GetObjectName (); } } else szDN = GetObjectName (); _TRACE (-1, L"Leaving CCertTemplate::GetDN: %s, 0x%x\n", (PCWSTR) szDN, hr); return szDN; }