You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2448 lines
76 KiB
2448 lines
76 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
|