//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: policy.cpp // // Contents: Cert Server Policy Module implementation // //--------------------------------------------------------------------------- #include "pch.cpp" #pragma hdrstop #include #include "celib.h" #include "policy.h" #include "module.h" BOOL fDebug = DBG_CERTSRV; #ifndef DBG_CERTSRV #error -- DBG_CERTSRV not defined! #endif // worker HRESULT polGetServerCallbackInterface( OUT ICertServerPolicy **ppServer, IN LONG Context) { HRESULT hr; if (NULL == ppServer) { hr = E_POINTER; _JumpError(hr, error, "Policy:polGetServerCallbackInterface"); } hr = CoCreateInstance( CLSID_CCertServerPolicy, NULL, // pUnkOuter CLSCTX_INPROC_SERVER, IID_ICertServerPolicy, (VOID **) ppServer); _JumpIfError(hr, error, "Policy:CoCreateInstance"); if (NULL == *ppServer) { hr = E_UNEXPECTED; _JumpError(hr, error, "Policy:CoCreateInstance"); } // only set context if nonzero if (0 != Context) { hr = (*ppServer)->SetContext(Context); _JumpIfError(hr, error, "Policy:SetContext"); } error: return hr; } HRESULT polGetProperty( IN ICertServerPolicy *pServer, IN BOOL fRequest, IN WCHAR const *pwszPropertyName, IN DWORD PropType, OUT VARIANT *pvarOut) { HRESULT hr; BSTR strName = NULL; VariantInit(pvarOut); strName = SysAllocString(pwszPropertyName); if (NULL == strName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } if (fRequest) { hr = pServer->GetRequestProperty(strName, PropType, pvarOut); _JumpIfErrorStr2( hr, error, "Policy:GetRequestProperty", pwszPropertyName, CERTSRV_E_PROPERTY_EMPTY); } else { hr = pServer->GetCertificateProperty(strName, PropType, pvarOut); _JumpIfErrorStr2( hr, error, "Policy:GetCertificateProperty", pwszPropertyName, CERTSRV_E_PROPERTY_EMPTY); } error: if (NULL != strName) { SysFreeString(strName); } return(hr); } HRESULT polGetStringProperty( IN ICertServerPolicy *pServer, IN BOOL fRequest, IN WCHAR const *pwszPropertyName, OUT BSTR *pstrOut) { HRESULT hr; VARIANT var; VariantInit(&var); if (NULL != *pstrOut) { SysFreeString(*pstrOut); *pstrOut = NULL; } hr = polGetProperty( pServer, fRequest, pwszPropertyName, PROPTYPE_STRING, &var); _JumpIfError2( hr, error, "Policy:polGetProperty", CERTSRV_E_PROPERTY_EMPTY); if (VT_BSTR != var.vt || NULL == var.bstrVal || L'\0' == var.bstrVal) { hr = CERTSRV_E_PROPERTY_EMPTY; _JumpError(hr, error, "Policy:polGetProperty"); } *pstrOut = var.bstrVal; var.vt = VT_EMPTY; hr = S_OK; error: VariantClear(&var); return(hr); } HRESULT polGetLongProperty( IN ICertServerPolicy *pServer, IN BOOL fRequest, IN WCHAR const *pwszPropertyName, OUT LONG *plOut) { HRESULT hr; VARIANT var; VariantInit(&var); hr = polGetProperty( pServer, fRequest, pwszPropertyName, PROPTYPE_LONG, &var); _JumpIfError2(hr, error, "Policy:polGetProperty", CERTSRV_E_PROPERTY_EMPTY); if (VT_I4 != var.vt) { hr = CERTSRV_E_PROPERTY_EMPTY; _JumpError(hr, error, "Policy:polGetProperty"); } *plOut = var.lVal; hr = S_OK; error: VariantClear(&var); return(hr); } HRESULT polGetRequestStringProperty( IN ICertServerPolicy *pServer, IN WCHAR const *pwszPropertyName, OUT BSTR *pstrOut) { HRESULT hr; hr = polGetStringProperty(pServer, TRUE, pwszPropertyName, pstrOut); _JumpIfError2(hr, error, "polGetStringProperty", CERTSRV_E_PROPERTY_EMPTY); error: return(hr); } HRESULT polGetCertificateStringProperty( IN ICertServerPolicy *pServer, IN WCHAR const *pwszPropertyName, OUT BSTR *pstrOut) { HRESULT hr; hr = polGetStringProperty(pServer, FALSE, pwszPropertyName, pstrOut); _JumpIfError2(hr, error, "polGetStringProperty", CERTSRV_E_PROPERTY_EMPTY); error: return(hr); } HRESULT polGetRequestLongProperty( IN ICertServerPolicy *pServer, IN WCHAR const *pwszPropertyName, OUT LONG *plOut) { HRESULT hr; hr = polGetLongProperty(pServer, TRUE, pwszPropertyName, plOut); _JumpIfError2(hr, error, "polGetLongProperty", CERTSRV_E_PROPERTY_EMPTY); error: return(hr); } HRESULT polGetCertificateLongProperty( IN ICertServerPolicy *pServer, IN WCHAR const *pwszPropertyName, OUT LONG *plOut) { HRESULT hr; hr = polGetLongProperty(pServer, FALSE, pwszPropertyName, plOut); _JumpIfError2(hr, error, "polGetLongProperty", CERTSRV_E_PROPERTY_EMPTY); error: return(hr); } HRESULT polGetRequestAttribute( IN ICertServerPolicy *pServer, IN WCHAR const *pwszAttributeName, OUT BSTR *pstrOut) { HRESULT hr; BSTR strName = NULL; strName = SysAllocString(pwszAttributeName); if (NULL == strName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->GetRequestAttribute(strName, pstrOut); _JumpIfErrorStr2( hr, error, "Policy:GetRequestAttribute", pwszAttributeName, CERTSRV_E_PROPERTY_EMPTY); error: if (NULL != strName) { SysFreeString(strName); } return(hr); } HRESULT polGetCertificateExtension( IN ICertServerPolicy *pServer, IN WCHAR const *pwszExtensionName, IN DWORD dwPropType, IN OUT VARIANT *pvarOut) { HRESULT hr; BSTR strName = NULL; strName = SysAllocString(pwszExtensionName); if (NULL == strName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->GetCertificateExtension(strName, dwPropType, pvarOut); _JumpIfErrorStr2( hr, error, "Policy:GetCertificateExtension", pwszExtensionName, CERTSRV_E_PROPERTY_EMPTY); error: if (NULL != strName) { SysFreeString(strName); } return(hr); } HRESULT polSetCertificateExtension( IN ICertServerPolicy *pServer, IN WCHAR const *pwszExtensionName, IN DWORD dwPropType, IN DWORD dwExtFlags, IN VARIANT const *pvarIn) { HRESULT hr; BSTR strName = NULL; strName = SysAllocString(pwszExtensionName); if (NULL == strName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->SetCertificateExtension( strName, dwPropType, dwExtFlags, pvarIn); _JumpIfErrorStr( hr, error, "Policy:SetCertificateExtension", pwszExtensionName); error: if (NULL != strName) { SysFreeString(strName); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::~CCertPolicySample -- destructor // // free memory associated with this instance //+-------------------------------------------------------------------------- CCertPolicySample::~CCertPolicySample() { _Cleanup(); } VOID CCertPolicySample::_FreeStringArray( IN OUT DWORD *pcString, IN OUT LPWSTR **papwsz) { LPWSTR *apwsz = *papwsz; DWORD i; if (NULL != apwsz) { for (i = *pcString; i-- > 0; ) { if (NULL != apwsz[i]) { DBGPRINT((fDebug, "_FreeStringArray[%u]: '%ws'\n", i, apwsz[i])); LocalFree(apwsz[i]); } } LocalFree(apwsz); *papwsz = NULL; } *pcString = 0; } //+-------------------------------------------------------------------------- // CCertPolicySample::_Cleanup -- free memory associated with this instance // // free memory associated with this instance //+-------------------------------------------------------------------------- VOID CCertPolicySample::_Cleanup() { DWORD i; if (m_strDescription) { SysFreeString(m_strDescription); m_strDescription = NULL; } // RevocationExtension variables: if (NULL != m_wszASPRevocationURL) { LocalFree(m_wszASPRevocationURL); m_wszASPRevocationURL = NULL; } _FreeStringArray(&m_cEnableRequestExtensions, &m_apwszEnableRequestExtensions); _FreeStringArray(&m_cEnableEnrolleeRequestExtensions, &m_apwszEnableEnrolleeRequestExtensions); _FreeStringArray(&m_cDisableExtensions, &m_apwszDisableExtensions); if (NULL != m_strCAName) { SysFreeString(m_strCAName); m_strCAName = NULL; } if (NULL != m_strCASanitizedName) { SysFreeString(m_strCASanitizedName); m_strCASanitizedName = NULL; } if (NULL != m_strCASanitizedDSName) { SysFreeString(m_strCASanitizedDSName); m_strCASanitizedDSName = NULL; } if (NULL != m_strRegStorageLoc) { SysFreeString(m_strRegStorageLoc); m_strRegStorageLoc = NULL; } if (NULL != m_pCert) { CertFreeCertificateContext(m_pCert); m_pCert = NULL; } if (m_strMachineDNSName) { SysFreeString(m_strMachineDNSName); m_strMachineDNSName=NULL; } } HRESULT CCertPolicySample::_ReadRegistryString( IN HKEY hkey, IN BOOL fURL, IN WCHAR const *pwszRegName, IN WCHAR const *pwszSuffix, OUT LPWSTR *ppwszOut) { HRESULT hr; WCHAR *pwszRegValue = NULL; DWORD cbValue; DWORD dwType; *ppwszOut = NULL; hr = RegQueryValueEx( hkey, pwszRegName, NULL, // lpdwReserved &dwType, NULL, &cbValue); _JumpIfErrorStr2( hr, error, "Policy:RegQueryValueEx", pwszRegName, ERROR_FILE_NOT_FOUND); if (REG_SZ != dwType && REG_MULTI_SZ != dwType) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpErrorStr(hr, error, "Policy:RegQueryValueEx TYPE", pwszRegName); } if (NULL != pwszSuffix) { cbValue += wcslen(pwszSuffix) * sizeof(WCHAR); } pwszRegValue = (WCHAR *) LocalAlloc(LMEM_FIXED, cbValue + sizeof(WCHAR)); if (NULL == pwszRegValue) { hr = E_OUTOFMEMORY; _JumpErrorStr(hr, error, "Policy:LocalAlloc", pwszRegName); } hr = RegQueryValueEx( hkey, pwszRegName, NULL, // lpdwReserved &dwType, (BYTE *) pwszRegValue, &cbValue); _JumpIfErrorStr(hr, error, "Policy:RegQueryValueEx", pwszRegName); // Handle malformed registry values cleanly: pwszRegValue[cbValue / sizeof(WCHAR)] = L'\0'; if (NULL != pwszSuffix) { wcscat(pwszRegValue, pwszSuffix); } hr = ceFormatCertsrvStringArray( fURL, // fURL m_strMachineDNSName, // pwszServerName_p1_2 m_strCASanitizedName, // pwszSanitizedName_p3_7 m_iCert, // iCert_p4 MAXDWORD, // iCertTarget_p4 L"", // pwszDomainDN_p5 L"", // pwszConfigDN_p6 m_iCRL, // iCRL_p8 FALSE, // fDeltaCRL_p9 TRUE, // fDSAttrib_p10_11 1, // cStrings (LPCWSTR *) &pwszRegValue, // apwszStringsIn ppwszOut); // apwszStringsOut _JumpIfError(hr, error, "Policy:ceFormatCertsrvStringArray"); error: if (NULL != pwszRegValue) { LocalFree(pwszRegValue); } return(ceHError(hr)); // Reg routines return Win32 error codes } #if DBG_CERTSRV VOID CCertPolicySample::_DumpStringArray( IN char const *pszType, IN DWORD count, IN LPWSTR const *apwsz) { DWORD i; WCHAR const *pwszName; for (i = 0; i < count; i++) { pwszName = L""; if (iswdigit(apwsz[i][0])) { pwszName = ceGetOIDName(apwsz[i]); // Static: do not free! } DBGPRINT(( fDebug, "%hs[%u]: %ws%hs%ws\n", pszType, i, apwsz[i], L'\0' != *pwszName? " -- " : "", pwszName)); } } #endif // DBG_CERTSRV HRESULT CCertPolicySample::_SetSystemStringProp( IN ICertServerPolicy *pServer, IN WCHAR const *pwszName, OPTIONAL IN WCHAR const *pwszValue) { HRESULT hr; BSTR strName = NULL; VARIANT varValue; varValue.vt = VT_NULL; varValue.bstrVal = NULL; if (!ceConvertWszToBstr(&strName, pwszName, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } if (NULL != pwszValue) { if (!ceConvertWszToBstr(&varValue.bstrVal, pwszValue, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } varValue.vt = VT_BSTR; } hr = pServer->SetCertificateProperty(strName, PROPTYPE_STRING, &varValue); _JumpIfError(hr, error, "Policy:SetCertificateProperty"); error: VariantClear(&varValue); if (NULL != strName) { SysFreeString(strName); } return(hr); } HRESULT CCertPolicySample::_AddStringArray( IN WCHAR const *pwszzValue, IN BOOL fURL, IN OUT DWORD *pcStrings, IN OUT LPWSTR **papwszRegValues) { HRESULT hr; DWORD cString = 0; WCHAR const *pwsz; LPCWSTR *awszFormatStrings = NULL; LPWSTR *awszOutputStrings = NULL; // Count the number of strings we're adding for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1) { cString++; } if (0 == cString) // no strings { hr = S_OK; goto error; } awszFormatStrings = (LPCWSTR *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, cString * sizeof(LPWSTR)); if (NULL == awszFormatStrings) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:LocalAlloc"); } cString = 0; for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1) { // Skip strings that start with a an unescaped minus sign. // Strings with an escaped minus sign (2 minus signs) are not skipped. if (L'-' == *pwsz) { pwsz++; if (L'-' != *pwsz) { continue; } } awszFormatStrings[cString++] = pwsz; } // if no strings to add, don't modify if (cString > 0) { awszOutputStrings = (LPWSTR *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, (cString + *pcStrings) * sizeof(LPWSTR)); if (NULL == awszOutputStrings) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:LocalAlloc"); } if (0 != *pcStrings) { assert(NULL != *papwszRegValues); CopyMemory( awszOutputStrings, *papwszRegValues, *pcStrings * sizeof(LPWSTR)); } hr = ceFormatCertsrvStringArray( fURL, // fURL m_strMachineDNSName, // pwszServerName_p1_2 m_strCASanitizedName, // pwszSanitizedName_p3_7 m_iCert, // iCert_p4 MAXDWORD, // iCertTarget_p4 L"", // pwszDomainDN_p5 L"", // pwszConfigDN_p6 m_iCRL, // iCRL_p8 FALSE, // fDeltaCRL_p9 TRUE, // fDSAttrib_p10_11 cString, // cStrings awszFormatStrings, // apwszStringsIn awszOutputStrings + (*pcStrings)); // apwszStringsOut _JumpIfError(hr, error, "Policy:ceFormatCertsrvStringArray"); *pcStrings = (*pcStrings) + cString; if (*papwszRegValues) { LocalFree(*papwszRegValues); } *papwszRegValues = awszOutputStrings; awszOutputStrings = NULL; } hr = S_OK; error: if (NULL != awszOutputStrings) { LocalFree(awszOutputStrings); } if (NULL != awszFormatStrings) { LocalFree(awszFormatStrings); } return(hr); } HRESULT CCertPolicySample::_ReadRegistryStringArray( IN HKEY hkey, IN BOOL fURL, IN DWORD dwFlags, IN DWORD cRegNames, IN DWORD *aFlags, IN WCHAR const * const *apwszRegNames, IN OUT DWORD *pcStrings, IN OUT LPWSTR **papwszRegValues) { HRESULT hr; DWORD i; WCHAR *pwszzValue = NULL; DWORD cbValue; DWORD dwType; for (i = 0; i < cRegNames; i++) { if (0 == (dwFlags & aFlags[i])) { continue; } if (NULL != pwszzValue) { LocalFree(pwszzValue); pwszzValue = NULL; } hr = RegQueryValueEx( hkey, apwszRegNames[i], NULL, // lpdwReserved &dwType, NULL, &cbValue); if (S_OK != hr) { _PrintErrorStr2( hr, "Policy:RegQueryValueEx", apwszRegNames[i], ERROR_FILE_NOT_FOUND); continue; } if (REG_SZ != dwType && REG_MULTI_SZ != dwType) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _PrintErrorStr(hr, "Policy:RegQueryValueEx TYPE", apwszRegNames[i]); continue; } // Handle malformed registry values cleanly by adding two WCHAR L'\0's // allocate space for 3 WCHARs to allow for unaligned (odd) cbValue; pwszzValue = (WCHAR *) LocalAlloc( LMEM_FIXED, cbValue + 3 * sizeof(WCHAR)); if (NULL == pwszzValue) { hr = E_OUTOFMEMORY; _JumpErrorStr(hr, error, "Policy:LocalAlloc", apwszRegNames[i]); } hr = RegQueryValueEx( hkey, apwszRegNames[i], NULL, // lpdwReserved &dwType, (BYTE *) pwszzValue, &cbValue); if (S_OK != hr) { _PrintErrorStr(hr, "Policy:RegQueryValueEx", apwszRegNames[i]); continue; } // Handle malformed registry values cleanly: pwszzValue[cbValue / sizeof(WCHAR)] = L'\0'; pwszzValue[cbValue / sizeof(WCHAR) + 1] = L'\0'; hr = _AddStringArray( pwszzValue, fURL, pcStrings, papwszRegValues); _JumpIfErrorStr(hr, error, "_AddStringArray", apwszRegNames[i]); } hr = S_OK; error: if (NULL != pwszzValue) { LocalFree(pwszzValue); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::_InitRevocationExtension // //+-------------------------------------------------------------------------- VOID CCertPolicySample::_InitRevocationExtension( IN HKEY hkey) { HRESULT hr; DWORD dwType; DWORD cb; cb = sizeof(m_dwRevocationFlags); hr = RegQueryValueEx( hkey, wszREGREVOCATIONTYPE, NULL, // lpdwReserved &dwType, (BYTE *) &m_dwRevocationFlags, &cb); if (S_OK != hr || REG_DWORD != dwType || sizeof(m_dwRevocationFlags) != cb) { m_dwRevocationFlags = 0; goto error; } DBGPRINT((fDebug, "Revocation Flags = %x\n", m_dwRevocationFlags)); // clean up from previous call if (NULL != m_wszASPRevocationURL) { LocalFree(m_wszASPRevocationURL); m_wszASPRevocationURL = NULL; } if (REVEXT_ASPENABLE & m_dwRevocationFlags) { hr = _ReadRegistryString( hkey, TRUE, // fURL wszREGREVOCATIONURL, // pwszRegName L"?", // pwszSuffix &m_wszASPRevocationURL); // pstrRegValue _JumpIfErrorStr(hr, error, "_ReadRegistryString", wszREGREVOCATIONURL); _DumpStringArray("ASP", 1, &m_wszASPRevocationURL); } error: ; } //+-------------------------------------------------------------------------- // CCertPolicySample::_InitRequestExtensionList // //+-------------------------------------------------------------------------- VOID CCertPolicySample::_InitRequestExtensionList( IN HKEY hkey) { HRESULT hr; DWORD adwFlags[] = { EDITF_REQUESTEXTENSIONLIST, }; WCHAR *apwszRegNames[] = { wszREGENABLEREQUESTEXTENSIONLIST, }; WCHAR *apwszRegNamesEnrollee[] = { wszREGENABLEENROLLEEREQUESTEXTENSIONLIST, }; assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNames)); assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNamesEnrollee)); // clean up from previous call if (NULL != m_apwszEnableRequestExtensions) { _FreeStringArray( &m_cEnableRequestExtensions, &m_apwszEnableRequestExtensions); } if (NULL != m_apwszEnableEnrolleeRequestExtensions) { _FreeStringArray( &m_cEnableEnrolleeRequestExtensions, &m_apwszEnableEnrolleeRequestExtensions); } hr = _ReadRegistryStringArray( hkey, FALSE, // fURL m_dwEditFlags, ARRAYSIZE(adwFlags), adwFlags, apwszRegNames, &m_cEnableRequestExtensions, &m_apwszEnableRequestExtensions); _JumpIfError(hr, error, "_ReadRegistryStringArray"); _DumpStringArray( "Request", m_cEnableRequestExtensions, m_apwszEnableRequestExtensions); hr = _ReadRegistryStringArray( hkey, FALSE, // fURL m_dwEditFlags, ARRAYSIZE(adwFlags), adwFlags, apwszRegNamesEnrollee, &m_cEnableEnrolleeRequestExtensions, &m_apwszEnableEnrolleeRequestExtensions); _JumpIfError(hr, error, "_ReadRegistryStringArray"); _DumpStringArray( "EnrolleeRequest", m_cEnableEnrolleeRequestExtensions, m_apwszEnableEnrolleeRequestExtensions); error: ; } //+-------------------------------------------------------------------------- // CCertPolicySample::_InitDisableExtensionList // //+-------------------------------------------------------------------------- VOID CCertPolicySample::_InitDisableExtensionList( IN HKEY hkey) { HRESULT hr; DWORD adwFlags[] = { EDITF_DISABLEEXTENSIONLIST, }; WCHAR *apwszRegNames[] = { wszREGDISABLEEXTENSIONLIST, }; assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNames)); // clean up from previous call if (NULL != m_apwszDisableExtensions) { _FreeStringArray(&m_cDisableExtensions, &m_apwszDisableExtensions); } hr = _ReadRegistryStringArray( hkey, FALSE, // fURL m_dwEditFlags, ARRAYSIZE(adwFlags), adwFlags, apwszRegNames, &m_cDisableExtensions, &m_apwszDisableExtensions); _JumpIfError(hr, error, "_ReadRegistryStringArray"); _DumpStringArray( "Disable", m_cDisableExtensions, m_apwszDisableExtensions); error: ; } //+-------------------------------------------------------------------------- // CCertPolicySample::Initialize // // Returns S_OK on success. //+-------------------------------------------------------------------------- STDMETHODIMP CCertPolicySample::Initialize( /* [in] */ BSTR const strConfig) { HRESULT hr; HKEY hkey = NULL; DWORD dwType; DWORD dwSize; ICertServerPolicy *pServer = NULL; BOOL fUpgraded; BSTR bstrDescription = NULL; CERT_RDN_ATTR rdnAttr = { szOID_COMMON_NAME, CERT_RDN_ANY_TYPE, }; rdnAttr.Value.pbData = NULL; DBGPRINT((fDebug, "Policy:Initialize:\n")); __try { _Cleanup(); m_strCAName = SysAllocString(strConfig); if (NULL == m_strCAName) { hr = E_OUTOFMEMORY; _LeaveError(hr, "CCertPolicySample::SysAllocString"); } // force loading the description from resources hr = GetDescription(&bstrDescription); _LeaveIfError(hr, "CCertPolicySample::GetDescription"); // get server callbacks hr = polGetServerCallbackInterface(&pServer, 0); _LeaveIfError(hr, "Policy:polGetServerCallbackInterface"); hr = ReqInitialize(pServer); _JumpIfError(hr, error, "ReqInitialize"); // get storage location hr = polGetCertificateStringProperty( pServer, wszPROPMODULEREGLOC, &m_strRegStorageLoc); _LeaveIfErrorStr( hr, "Policy:polGetCertificateStringProperty", wszPROPMODULEREGLOC); // get CA type hr = polGetCertificateLongProperty( pServer, wszPROPCATYPE, (LONG *) &m_CAType); _LeaveIfErrorStr( hr, "Policy:polGetCertificateLongProperty", wszPROPCATYPE); // get sanitized name hr = polGetCertificateStringProperty( pServer, wszPROPSANITIZEDCANAME, &m_strCASanitizedName); _LeaveIfErrorStr( hr, "Policy:polGetCertificateStringProperty", wszPROPSANITIZEDCANAME); // get sanitized name hr = polGetCertificateStringProperty( pServer, wszPROPSANITIZEDSHORTNAME, &m_strCASanitizedDSName); _LeaveIfErrorStr( hr, "Policy:polGetCertificateStringProperty", wszPROPSANITIZEDSHORTNAME); hr = polGetCertificateLongProperty( pServer, wszPROPSERVERUPGRADED, (LONG *) &fUpgraded); if (S_OK != hr) { fUpgraded = FALSE; _PrintErrorStr( hr, "Policy:polGetCertificateLongProperty", wszPROPSERVERUPGRADED); } hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_strRegStorageLoc, 0, // dwReserved fUpgraded? KEY_ALL_ACCESS : (KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE), &hkey); _LeaveIfErrorStr( hr, "Policy:Initialize:RegOpenKeyEx", m_strRegStorageLoc); // Ignore error codes. dwSize = sizeof(m_dwDispositionFlags); hr = RegQueryValueEx( hkey, wszREGREQUESTDISPOSITION, 0, &dwType, (BYTE *) &m_dwDispositionFlags, &dwSize); if (S_OK != hr || REG_DWORD != dwType) { m_dwDispositionFlags = REQDISP_PENDINGFIRST | REQDISP_ISSUE; } DBGPRINT(( fDebug, "Disposition Flags = %x\n", m_dwDispositionFlags)); dwSize = sizeof(m_dwEditFlags); hr = RegQueryValueEx( hkey, wszREGEDITFLAGS, 0, &dwType, (BYTE *) &m_dwEditFlags, &dwSize); if (S_OK != hr || REG_DWORD != dwType) { m_dwEditFlags = EDITF_DEFAULT_STANDALONE; } if (fUpgraded) { DBGPRINT(( fDebug, "Initialize: setting EDITF_SERVERUPGRADED\n")); m_dwEditFlags |= EDITF_SERVERUPGRADED; dwSize = sizeof(m_dwEditFlags); hr = RegSetValueEx( hkey, wszREGEDITFLAGS, 0, REG_DWORD, (BYTE *) &m_dwEditFlags, dwSize); _PrintIfError(hr, "Policy:RegSetValueEx"); } DBGPRINT((fDebug, "Edit Flags = %x\n", m_dwEditFlags)); dwSize = sizeof(m_CAPathLength); hr = RegQueryValueEx( hkey, wszREGCAPATHLENGTH, 0, &dwType, (BYTE *) &m_CAPathLength, &dwSize); if (S_OK != hr || REG_DWORD != dwType) { m_CAPathLength = CAPATHLENGTH_INFINITE; } DBGPRINT((fDebug, "CAPathLength = %x\n", m_CAPathLength)); // Initialize the insertion string array. // Machine DNS name (%1) hr = polGetCertificateStringProperty( pServer, wszPROPMACHINEDNSNAME, &m_strMachineDNSName); _LeaveIfErrorStr( hr, "Policy:polGetCertificateStringProperty", wszPROPMACHINEDNSNAME); hr = polGetCertificateLongProperty( pServer, wszPROPCERTCOUNT, (LONG *) &m_iCert); _LeaveIfErrorStr( hr, "Policy:polGetCertificateLongProperty", wszPROPCERTCOUNT); if (0 == m_iCert) // no CA certs? { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); _LeaveIfErrorStr( hr, "Policy:polGetCertificateLongProperty", wszPROPCERTCOUNT); } m_iCert--; hr = polGetCertificateLongProperty( pServer, wszPROPCRLINDEX, (LONG *) &m_iCRL); _LeaveIfErrorStr( hr, "Policy:polGetCertificateLongProperty", wszPROPCRLINDEX); _InitRevocationExtension(hkey); _InitRequestExtensionList(hkey); _InitDisableExtensionList(hkey); hr = S_OK; } __except(hr = ceHError(GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); } error: if (NULL != bstrDescription) { SysFreeString(bstrDescription); } if (NULL != hkey) { RegCloseKey(hkey); } if (NULL != pServer) { pServer->Release(); } return(ceHError(hr)); // Reg routines return Win32 error codes } DWORD polFindObjIdInList( IN WCHAR const *pwsz, IN DWORD count, IN WCHAR const * const *ppwsz) { DWORD i; for (i = 0; i < count; i++) { if (NULL == pwsz || NULL == ppwsz[i]) { i = count; break; } if (0 == wcscmp(pwsz, ppwsz[i])) { break; } } return(i < count? i : MAXDWORD); } HRESULT CCertPolicySample::_EnumerateExtensions( IN ICertServerPolicy *pServer, IN LONG bNewRequest, IN BOOL fFirstPass, IN BOOL fEnableEnrolleeExtensions, IN DWORD cCriticalExtensions, OPTIONAL IN WCHAR const * const *apwszCriticalExtensions) { HRESULT hr; HRESULT hr2; BSTR strName = NULL; LONG ExtFlags; VARIANT varValue; BOOL fClose = FALSE; BOOL fEnable; BOOL fDisable; BOOL fCritical; VariantInit(&varValue); hr = pServer->EnumerateExtensionsSetup(0); _JumpIfError(hr, error, "Policy:EnumerateExtensionsSetup"); fClose = TRUE; while (TRUE) { hr = pServer->EnumerateExtensions(&strName); if (S_FALSE == hr) { hr = S_OK; break; } _JumpIfError(hr, error, "Policy:EnumerateExtensions"); hr = pServer->GetCertificateExtension( strName, PROPTYPE_BINARY, &varValue); _JumpIfError(hr, error, "Policy:GetCertificateExtension"); hr = pServer->GetCertificateExtensionFlags(&ExtFlags); _JumpIfError(hr, error, "Policy:GetCertificateExtensionFlags"); fEnable = FALSE; fDisable = FALSE; fCritical = FALSE; if (fFirstPass) { if (bNewRequest && (EXTENSION_DISABLE_FLAG & ExtFlags)) { switch (EXTENSION_ORIGIN_MASK & ExtFlags) { case EXTENSION_ORIGIN_REQUEST: case EXTENSION_ORIGIN_RENEWALCERT: case EXTENSION_ORIGIN_PKCS7: case EXTENSION_ORIGIN_CMC: if ((EDITF_ENABLEREQUESTEXTENSIONS & m_dwEditFlags) || MAXDWORD != polFindObjIdInList( strName, m_cEnableRequestExtensions, m_apwszEnableRequestExtensions) || (fEnableEnrolleeExtensions && MAXDWORD != polFindObjIdInList( strName, m_cEnableEnrolleeRequestExtensions, m_apwszEnableEnrolleeRequestExtensions))) { ExtFlags &= ~EXTENSION_DISABLE_FLAG; fEnable = TRUE; } break; } } } else { if (0 == (EXTENSION_DISABLE_FLAG & ExtFlags) && MAXDWORD != polFindObjIdInList( strName, m_cDisableExtensions, m_apwszDisableExtensions)) { ExtFlags |= EXTENSION_DISABLE_FLAG; fDisable = TRUE; } if (0 == (EXTENSION_CRITICAL_FLAG & ExtFlags) && MAXDWORD != polFindObjIdInList( strName, cCriticalExtensions, apwszCriticalExtensions)) { ExtFlags |= EXTENSION_CRITICAL_FLAG; fCritical = TRUE; } } if (fDisable || fEnable) { hr = pServer->SetCertificateExtension( strName, PROPTYPE_BINARY, ExtFlags, &varValue); _JumpIfError(hr, error, "Policy:SetCertificateExtension"); } if (fFirstPass || fDisable || fEnable) { DBGPRINT(( fDebug, "Policy:EnumerateExtensions(%ws, Flags=%x, %x bytes)%hs%hs\n", strName, ExtFlags, SysStringByteLen(varValue.bstrVal), fDisable? " DISABLING" : (fEnable? " ENABLING" : ""), fCritical? " +CRITICAL" : "")); } if (NULL != strName) { SysFreeString(strName); strName = NULL; } VariantClear(&varValue); } error: if (fClose) { hr2 = pServer->EnumerateExtensionsClose(); if (S_OK != hr2) { if (S_OK == hr) { hr = hr2; } _PrintError(hr2, "Policy:EnumerateExtensionsClose"); } } if (NULL != strName) { SysFreeString(strName); } VariantClear(&varValue); return(hr); } HRESULT EnumerateAttributes( IN ICertServerPolicy *pServer) { HRESULT hr; HRESULT hr2; BSTR strName = NULL; BOOL fClose = FALSE; BSTR strValue = NULL; hr = pServer->EnumerateAttributesSetup(0); _JumpIfError(hr, error, "Policy:EnumerateAttributesSetup"); fClose = TRUE; while (TRUE) { hr = pServer->EnumerateAttributes(&strName); if (S_FALSE == hr) { hr = S_OK; break; } _JumpIfError(hr, error, "Policy:EnumerateAttributes"); hr = pServer->GetRequestAttribute(strName, &strValue); _JumpIfError(hr, error, "Policy:GetRequestAttribute"); DBGPRINT(( fDebug, "Policy:EnumerateAttributes(%ws = %ws)\n", strName, strValue)); if (NULL != strName) { SysFreeString(strName); strName = NULL; } if (NULL != strValue) { SysFreeString(strValue); strValue = NULL; } } error: if (fClose) { hr2 = pServer->EnumerateAttributesClose(); if (S_OK != hr2) { _PrintError(hr2, "Policy:EnumerateAttributesClose"); if (S_OK == hr) { hr = hr2; } } } if (NULL != strName) { SysFreeString(strName); } if (NULL != strValue) { SysFreeString(strValue); } return(hr); } HRESULT GetRequestId( IN ICertServerPolicy *pServer, OUT LONG *plRequestId) { HRESULT hr; hr = polGetRequestLongProperty(pServer, wszPROPREQUESTREQUESTID, plRequestId); _JumpIfError(hr, error, "Policy:polGetRequestLongProperty"); DBGPRINT(( fDebug, "Policy:GetRequestId(%ws = %u)\n", wszPROPREQUESTREQUESTID, *plRequestId)); error: return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::_AddRevocationExtension // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::_AddRevocationExtension( IN ICertServerPolicy *pServer) { HRESULT hr = S_OK; BSTR strASPExtension = NULL; VARIANT varExtension; if (NULL != m_wszASPRevocationURL) { strASPExtension = SysAllocString(m_wszASPRevocationURL); if (NULL == strASPExtension) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } varExtension.vt = VT_BSTR; varExtension.bstrVal = strASPExtension; hr = polSetCertificateExtension( pServer, TEXT(szOID_NETSCAPE_REVOCATION_URL), PROPTYPE_STRING, 0, &varExtension); _JumpIfErrorStr(hr, error, "Policy:polSetCertificateExtension", L"ASP"); } error: if (NULL != strASPExtension) { SysFreeString(strASPExtension); } return(hr); } #define HIGHBIT(bitno) (1 << (7 - (bitno))) // bit counted from high end #define SSLBIT_CLIENT ((BYTE) HIGHBIT(0)) // certified for client auth #define SSLBIT_SERVER ((BYTE) HIGHBIT(1)) // certified for server auth #define SSLBIT_SMIME ((BYTE) HIGHBIT(2)) // certified for S/MIME #define SSLBIT_SIGN ((BYTE) HIGHBIT(3)) // certified for signing #define SSLBIT_RESERVED ((BYTE) HIGHBIT(4)) // reserved for future use #define SSLBIT_CASSL ((BYTE) HIGHBIT(5)) // CA for SSL auth certs #define SSLBIT_CASMIME ((BYTE) HIGHBIT(6)) // CA for S/MIME certs #define SSLBIT_CASIGN ((BYTE) HIGHBIT(7)) // CA for signing certs #define NSCERTTYPE_CLIENT ((BYTE) SSLBIT_CLIENT) #define NSCERTTYPE_SERVER ((BYTE) (SSLBIT_SERVER | SSLBIT_CLIENT)) #define NSCERTTYPE_SMIME ((BYTE) SSLBIT_SMIME) #define NSCERTTYPE_CA ((BYTE) (SSLBIT_CASSL | SSLBIT_CASMIME | SSLBIT_CASIGN)) //+-------------------------------------------------------------------------- // CCertPolicySample::_AddOldCertTypeExtension // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::_AddOldCertTypeExtension( IN ICertServerPolicy *pServer, IN BOOL fCA) { HRESULT hr = S_OK; ICertEncodeBitString *pBitString = NULL; BSTR strExtension = NULL; VARIANT varExtension; BSTR strBitString = NULL; BSTR strCertType = NULL; CERT_BASIC_CONSTRAINTS2_INFO Constraints; VARIANT varConstraints; DWORD cb; VariantInit(&varConstraints); if (EDITF_ADDOLDCERTTYPE & m_dwEditFlags) { BYTE CertType; if (!fCA) { hr = polGetCertificateExtension( pServer, TEXT(szOID_BASIC_CONSTRAINTS2), PROPTYPE_BINARY, &varConstraints); if (S_OK == hr) { cb = sizeof(Constraints); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, (BYTE const *) varConstraints.bstrVal, SysStringByteLen(varConstraints.bstrVal), 0, &Constraints, &cb)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:CryptDecodeObject"); } fCA = Constraints.fCA; } } hr = CoCreateInstance( CLSID_CCertEncodeBitString, NULL, // pUnkOuter CLSCTX_INPROC_SERVER, IID_ICertEncodeBitString, (VOID **) &pBitString); _JumpIfError(hr, error, "Policy:CoCreateInstance"); CertType = NSCERTTYPE_CLIENT; // Default to client auth. cert if (fCA) { CertType = NSCERTTYPE_CA; } else { hr = polGetRequestAttribute(pServer, wszPROPCERTTYPE, &strCertType); if (S_OK == hr) { if (0 == celstrcmpiL(strCertType, L"server")) { CertType = NSCERTTYPE_SERVER; } } } if (!ceConvertWszToBstr( &strBitString, (WCHAR const *) &CertType, sizeof(CertType))) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } hr = pBitString->Encode( sizeof(CertType) * 8, strBitString, &strExtension); _JumpIfError(hr, error, "Policy:BitString:Encode"); varExtension.vt = VT_BSTR; varExtension.bstrVal = strExtension; hr = polSetCertificateExtension( pServer, TEXT(szOID_NETSCAPE_CERT_TYPE), PROPTYPE_BINARY, 0, &varExtension); _JumpIfError(hr, error, "Policy:polSetCertificateExtension"); } error: VariantClear(&varConstraints); if (NULL != strExtension) { SysFreeString(strExtension); } if (NULL != strBitString) { SysFreeString(strBitString); } if (NULL != strCertType) { SysFreeString(strCertType); } if (NULL != pBitString) { pBitString->Release(); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::_AddAuthorityKeyId // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::_AddAuthorityKeyId( IN ICertServerPolicy *pServer) { HRESULT hr = S_OK; BYTE *pbEncoded = NULL; DWORD cbEncoded; BSTR strExtension = NULL; VARIANT varExtension; VARIANT varExtensionT; PCERT_AUTHORITY_KEY_ID2_INFO pInfo = NULL; DWORD cbInfo = 0; LONG ExtFlags = 0; VariantInit(&varExtension); // Optimization if ((EDITF_ENABLEAKIKEYID | EDITF_ENABLEAKIISSUERNAME | EDITF_ENABLEAKIISSUERSERIAL) == ((EDITF_ENABLEAKIKEYID | EDITF_ENABLEAKIISSUERNAME | EDITF_ENABLEAKIISSUERSERIAL | EDITF_ENABLEAKICRITICAL) & m_dwEditFlags)) { goto error; } hr = polGetCertificateExtension( pServer, TEXT(szOID_AUTHORITY_KEY_IDENTIFIER2), PROPTYPE_BINARY, &varExtension); _JumpIfError(hr, error, "Policy:polGetCertificateExtension"); hr = pServer->GetCertificateExtensionFlags(&ExtFlags); _JumpIfError(hr, error, "Policy:GetCertificateExtensionFlags"); if (VT_BSTR != varExtension.vt) { hr = E_INVALIDARG; _JumpError(hr, error, "Policy:GetCertificateExtension"); } cbInfo = 0; if (!ceDecodeObject( X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID2, (BYTE *) varExtension.bstrVal, SysStringByteLen(varExtension.bstrVal), FALSE, (VOID **) &pInfo, &cbInfo)) { hr = ceHLastError(); _JumpIfError(hr, error, "Policy:ceDecodeObject"); } // Make Any Modifications Here if (0 == (EDITF_ENABLEAKIKEYID & m_dwEditFlags)) { pInfo->KeyId.cbData = 0; pInfo->KeyId.pbData = NULL; } if (0 == (EDITF_ENABLEAKIISSUERNAME & m_dwEditFlags)) { pInfo->AuthorityCertIssuer.cAltEntry = 0; pInfo->AuthorityCertIssuer.rgAltEntry = NULL; } if (0 == (EDITF_ENABLEAKIISSUERSERIAL & m_dwEditFlags)) { pInfo->AuthorityCertSerialNumber.cbData = 0; pInfo->AuthorityCertSerialNumber.pbData = NULL; } if (EDITF_ENABLEAKICRITICAL & m_dwEditFlags) { ExtFlags |= EXTENSION_CRITICAL_FLAG; } if (0 == ((EDITF_ENABLEAKIKEYID | EDITF_ENABLEAKIISSUERNAME | EDITF_ENABLEAKIISSUERSERIAL) & m_dwEditFlags)) { ExtFlags |= EXTENSION_DISABLE_FLAG; } if (!ceEncodeObject( X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID2, pInfo, 0, FALSE, &pbEncoded, &cbEncoded)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:ceEncodeObject"); } if (!ceConvertWszToBstr( &strExtension, (WCHAR const *) pbEncoded, cbEncoded)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } varExtensionT.vt = VT_BSTR; varExtensionT.bstrVal = strExtension; hr = polSetCertificateExtension( pServer, TEXT(szOID_AUTHORITY_KEY_IDENTIFIER2), PROPTYPE_BINARY, ExtFlags, &varExtensionT); _JumpIfError(hr, error, "Policy:polSetCertificateExtension(AuthorityKeyId2)"); error: VariantClear(&varExtension); if (NULL != pInfo) { LocalFree(pInfo); } if (NULL != pbEncoded) { LocalFree(pbEncoded); } if (NULL != strExtension) { SysFreeString(strExtension); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicy::_AddDefaultKeyUsageExtension // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::_AddDefaultKeyUsageExtension( IN ICertServerPolicy *pServer, IN BOOL fCA) { HRESULT hr; BSTR strName = NULL; ICertEncodeBitString *pBitString = NULL; BSTR strExtension = NULL; VARIANT varExtension; BSTR strBitString = NULL; CERT_BASIC_CONSTRAINTS2_INFO Constraints; VARIANT varConstraints; VARIANT varKeyUsage; CRYPT_BIT_BLOB *pKeyUsage = NULL; DWORD cb; BYTE abKeyUsage[1]; BYTE *pbKeyUsage; DWORD cbKeyUsage; VariantInit(&varConstraints); VariantInit(&varKeyUsage); if (EDITF_ADDOLDKEYUSAGE & m_dwEditFlags) { BOOL fModified = FALSE; if (!fCA) { hr = polGetCertificateExtension( pServer, TEXT(szOID_BASIC_CONSTRAINTS2), PROPTYPE_BINARY, &varConstraints); if (S_OK == hr) { cb = sizeof(Constraints); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, (BYTE const *) varConstraints.bstrVal, SysStringByteLen(varConstraints.bstrVal), 0, &Constraints, &cb)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:CryptDecodeObject"); } fCA = Constraints.fCA; } } ZeroMemory(abKeyUsage, sizeof(abKeyUsage)); pbKeyUsage = abKeyUsage; cbKeyUsage = sizeof(abKeyUsage); hr = polGetCertificateExtension( pServer, TEXT(szOID_KEY_USAGE), PROPTYPE_BINARY, &varKeyUsage); if (S_OK == hr) { if (!ceDecodeObject( X509_ASN_ENCODING, X509_KEY_USAGE, (BYTE const *) varKeyUsage.bstrVal, SysStringByteLen(varKeyUsage.bstrVal), FALSE, (VOID **) &pKeyUsage, &cb)) { hr = GetLastError(); _PrintError(hr, "Policy:ceDecodeObject"); } else if (0 != cb && NULL != pKeyUsage && 0 != pKeyUsage->cbData) { pbKeyUsage = pKeyUsage->pbData; cbKeyUsage = pKeyUsage->cbData; } } if ((CERT_KEY_ENCIPHERMENT_KEY_USAGE & pbKeyUsage[0]) && (CERT_KEY_AGREEMENT_KEY_USAGE & pbKeyUsage[0])) { pbKeyUsage[0] &= ~CERT_KEY_AGREEMENT_KEY_USAGE; pbKeyUsage[0] |= CERT_DIGITAL_SIGNATURE_KEY_USAGE; fModified = TRUE; } if (fCA) { pbKeyUsage[0] |= ceCASIGN_KEY_USAGE; fModified = TRUE; } if (fModified) { hr = CoCreateInstance( CLSID_CCertEncodeBitString, NULL, // pUnkOuter CLSCTX_INPROC_SERVER, IID_ICertEncodeBitString, (VOID **) &pBitString); _JumpIfError(hr, error, "Policy:CoCreateInstance"); if (!ceConvertWszToBstr( &strBitString, (WCHAR const *) pbKeyUsage, cbKeyUsage)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } hr = pBitString->Encode(cbKeyUsage * 8, strBitString, &strExtension); _JumpIfError(hr, error, "Policy:Encode"); if (!ceConvertWszToBstr(&strName, TEXT(szOID_KEY_USAGE), -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } varExtension.vt = VT_BSTR; varExtension.bstrVal = strExtension; hr = pServer->SetCertificateExtension( strName, PROPTYPE_BINARY, 0, &varExtension); _JumpIfError(hr, error, "Policy:SetCertificateExtension"); } } hr = S_OK; error: VariantClear(&varConstraints); VariantClear(&varKeyUsage); if (NULL != pKeyUsage) { LocalFree(pKeyUsage); } if (NULL != strName) { SysFreeString(strName); } if (NULL != strExtension) { SysFreeString(strExtension); } if (NULL != strBitString) { SysFreeString(strBitString); } if (NULL != pBitString) { pBitString->Release(); } return(hr); } HRESULT CCertPolicySample::_AddEnhancedKeyUsageExtension( IN ICertServerPolicy *pServer) { HRESULT hr; BSTR strUsage = NULL; char *pszUsage = NULL; char *psz; char *pszNext; CERT_ENHKEY_USAGE ceu; CERT_POLICIES_INFO cpi; BYTE *pbKeyUsage = NULL; DWORD cbKeyUsage; BYTE *pbPolicies = NULL; DWORD cbPolicies; CERT_POLICY_INFO *pcpi = NULL; DWORD i; VARIANT varExtension; ZeroMemory(&ceu, sizeof(ceu)); ZeroMemory(&cpi, sizeof(cpi)); VariantInit(&varExtension); if (0 == (EDITF_ATTRIBUTEEKU & m_dwEditFlags)) { hr = S_OK; goto error; } hr = polGetRequestAttribute(pServer, wszPROPCERTUSAGE, &strUsage); if (S_OK != hr) { hr = S_OK; goto error; } if (!ceConvertWszToSz(&pszUsage, strUsage, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToSz"); } for (psz = pszUsage; '\0' != *psz; psz = pszNext) { pszNext = &psz[strcspn(psz, ",")]; if ('\0' != *pszNext) { pszNext++; } ceu.cUsageIdentifier++; } if (0 == ceu.cUsageIdentifier) { hr = S_OK; goto error; } ceu.rgpszUsageIdentifier = (char **) LocalAlloc( LMEM_FIXED, ceu.cUsageIdentifier * sizeof(ceu.rgpszUsageIdentifier[0])); if (NULL == ceu.rgpszUsageIdentifier) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:myLocalAlloc"); } // Destructively parse comma separated ObjIds into individual strings i = 0; for (psz = pszUsage; '\0' != *psz; psz = pszNext) { char *pszEnd; assert(i < ceu.cUsageIdentifier); pszNext = &psz[strcspn(psz, ",")]; pszEnd = pszNext; if ('\0' != *pszNext) { *pszNext++ = '\0'; } while (' ' == *psz) { psz++; } while (pszEnd > psz && ' ' == *--pszEnd) { *pszEnd = '\0'; } if ('\0' != *psz) { hr = ceVerifyObjIdA(psz); _JumpIfError(hr, error, "Policy:ceVerifyObjIdA"); ceu.rgpszUsageIdentifier[i++] = psz; } } ceu.cUsageIdentifier = i; if (0 == ceu.cUsageIdentifier) { hr = S_OK; goto error; } if (!ceEncodeObject( X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &ceu, 0, FALSE, &pbKeyUsage, &cbKeyUsage)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:ceEncodeObject"); } varExtension.bstrVal = NULL; if (!ceConvertWszToBstr( &varExtension.bstrVal, (WCHAR const *) pbKeyUsage, cbKeyUsage)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } varExtension.vt = VT_BSTR; hr = polSetCertificateExtension( pServer, TEXT(szOID_ENHANCED_KEY_USAGE), PROPTYPE_BINARY, 0, &varExtension); _JumpIfError(hr, error, "Policy:polSetCertificateExtension"); cpi.cPolicyInfo = ceu.cUsageIdentifier; cpi.rgPolicyInfo = (CERT_POLICY_INFO *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, cpi.cPolicyInfo * sizeof(cpi.rgPolicyInfo[0])); if (NULL == cpi.rgPolicyInfo) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:LocalAlloc"); } for (i = 0; i < cpi.cPolicyInfo; i++) { cpi.rgPolicyInfo[i].pszPolicyIdentifier = ceu.rgpszUsageIdentifier[i]; } if (!ceEncodeObject( X509_ASN_ENCODING, X509_CERT_POLICIES, &cpi, 0, FALSE, &pbPolicies, &cbPolicies)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:ceEncodeObject"); } if (!ceConvertWszToBstr( &varExtension.bstrVal, (WCHAR const *) pbPolicies, cbPolicies)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } hr = polSetCertificateExtension( pServer, TEXT(szOID_APPLICATION_CERT_POLICIES), PROPTYPE_BINARY, 0, &varExtension); _JumpIfError(hr, error, "Policy:polSetCertificateExtension"); error: if (NULL != pcpi) { LocalFree(pcpi); } VariantClear(&varExtension); if (NULL != ceu.rgpszUsageIdentifier) { LocalFree(ceu.rgpszUsageIdentifier); } if (NULL != pbPolicies) { LocalFree(pbPolicies); } if (NULL != pbKeyUsage) { LocalFree(pbKeyUsage); } if (NULL != pszUsage) { LocalFree(pszUsage); } if (NULL != strUsage) { SysFreeString(strUsage); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicy::_AddDefaultBasicConstraintsExtension // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::_AddDefaultBasicConstraintsExtension( IN ICertServerPolicy *pServer, IN BOOL fCA) { HRESULT hr; VARIANT varExtension; LONG ExtFlags; CERT_EXTENSION Ext; CERT_EXTENSION *pExtension = NULL; BSTR strCertType = NULL; VariantInit(&varExtension); if (EDITF_BASICCONSTRAINTSCA & m_dwEditFlags) { hr = polGetCertificateExtension( pServer, TEXT(szOID_BASIC_CONSTRAINTS2), PROPTYPE_BINARY, &varExtension); if (S_OK == hr) { CERT_BASIC_CONSTRAINTS2_INFO Constraints; DWORD cb; hr = pServer->GetCertificateExtensionFlags(&ExtFlags); if (S_OK == hr) { Ext.pszObjId = szOID_BASIC_CONSTRAINTS2; Ext.fCritical = FALSE; if (EXTENSION_CRITICAL_FLAG & ExtFlags) { Ext.fCritical = TRUE; } Ext.Value.pbData = (BYTE *) varExtension.bstrVal; Ext.Value.cbData = SysStringByteLen(varExtension.bstrVal); pExtension = &Ext; cb = sizeof(Constraints); if (!fCA && CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, Ext.Value.pbData, Ext.Value.cbData, 0, &Constraints, &cb)) { fCA = Constraints.fCA; } } } } if (EDITF_ATTRIBUTECA & m_dwEditFlags) { if (!fCA) { hr = polGetRequestAttribute(pServer, wszPROPCERTTYPE, &strCertType); if (S_OK == hr) { if (0 == celstrcmpiL(strCertType, L"ca")) { fCA = TRUE; } } } if (!fCA) { hr = polGetRequestAttribute(pServer, wszPROPCERTTEMPLATE, &strCertType); if (S_OK == hr) { if (0 == celstrcmpiL(strCertType, wszCERTTYPE_SUBORDINATE_CA) || 0 == celstrcmpiL(strCertType, wszCERTTYPE_CROSS_CA)) { fCA = TRUE; } } } } // For standalone, the extension is only enabled if it's a CA hr = AddBasicConstraintsCommon(pServer, pExtension, fCA, fCA); _JumpIfError(hr, error, "Policy:AddBasicConstraintsCommon"); error: VariantClear(&varExtension); if (NULL != strCertType) { SysFreeString(strCertType); } return(hr); } HRESULT CCertPolicySample::AddBasicConstraintsCommon( IN ICertServerPolicy *pServer, IN CERT_EXTENSION const *pExtension, IN BOOL fCA, IN BOOL fEnableExtension) { HRESULT hr; BSTR strExtension = NULL; VARIANT varExtension; CERT_CONTEXT const *pIssuerCert; CERT_EXTENSION *pIssuerExtension; LONG ExtFlags = 0; BYTE *pbConstraints = NULL; CERT_BASIC_CONSTRAINTS2_INFO Constraints; CERT_BASIC_CONSTRAINTS2_INFO IssuerConstraints; ZeroMemory(&IssuerConstraints, sizeof(IssuerConstraints)); DWORD cb; pIssuerCert = _GetIssuer(pServer); if (NULL == pIssuerCert) { hr = E_POINTER; _JumpError(hr, error, "_GetIssuer"); } if (NULL != pExtension) { cb = sizeof(Constraints); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, pExtension->Value.pbData, pExtension->Value.cbData, 0, &Constraints, &cb)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:CryptDecodeObject"); } // Cert templates use CAPATHLENGTH_INFINITE to indicate // fPathLenConstraint should be FALSE. if (CAPATHLENGTH_INFINITE == Constraints.dwPathLenConstraint) { // NOTE: This is ok as certcli already sets fPathLenConstraint to FALSE // for templates in this case. Constraints.fPathLenConstraint = FALSE; // NOTE: This is ok as autoenrollment ignores dwPathLenConstraint // if fPathLenConstraint is FALSE; Constraints.dwPathLenConstraint = 0; } if (pExtension->fCritical) { ExtFlags = EXTENSION_CRITICAL_FLAG; } } else { Constraints.fCA = fCA; Constraints.fPathLenConstraint = FALSE; Constraints.dwPathLenConstraint = 0; } if (EDITF_BASICCONSTRAINTSCRITICAL & m_dwEditFlags) { ExtFlags = EXTENSION_CRITICAL_FLAG; } // Check basic constraints against the issuer's cert. pIssuerExtension = CertFindExtension( szOID_BASIC_CONSTRAINTS2, pIssuerCert->pCertInfo->cExtension, pIssuerCert->pCertInfo->rgExtension); if (NULL != pIssuerExtension) { cb = sizeof(IssuerConstraints); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, pIssuerExtension->Value.pbData, pIssuerExtension->Value.cbData, 0, &IssuerConstraints, &cb)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:CryptDecodeObject"); } if (!IssuerConstraints.fCA) { hr = CERTSRV_E_INVALID_CA_CERTIFICATE; _JumpError(hr, error, "Policy:CA cert not a CA cert"); } } if (Constraints.fCA) { if (IssuerConstraints.fPathLenConstraint) { if (0 == IssuerConstraints.dwPathLenConstraint) { hr = CERTSRV_E_INVALID_CA_CERTIFICATE; _JumpError(hr, error, "Policy:CA cert is a leaf CA cert"); } if (!Constraints.fPathLenConstraint || Constraints.dwPathLenConstraint > IssuerConstraints.dwPathLenConstraint - 1) { Constraints.fPathLenConstraint = TRUE; Constraints.dwPathLenConstraint = IssuerConstraints.dwPathLenConstraint - 1; } } if (CAPATHLENGTH_INFINITE != m_CAPathLength) { if (0 == m_CAPathLength) { hr = CERTSRV_E_INVALID_CA_CERTIFICATE; _JumpError(hr, error, "Policy:Registry says not to issue CA certs"); } if (!Constraints.fPathLenConstraint || Constraints.dwPathLenConstraint > m_CAPathLength - 1) { Constraints.fPathLenConstraint = TRUE; Constraints.dwPathLenConstraint = m_CAPathLength - 1; } } } if (!fEnableExtension) { ExtFlags |= EXTENSION_DISABLE_FLAG; } if (!ceEncodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &Constraints, 0, FALSE, &pbConstraints, &cb)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:ceEncodeObject"); } if (!ceConvertWszToBstr( &strExtension, (WCHAR const *) pbConstraints, cb)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } varExtension.vt = VT_BSTR; varExtension.bstrVal = strExtension; hr = polSetCertificateExtension( pServer, TEXT(szOID_BASIC_CONSTRAINTS2), PROPTYPE_BINARY, ExtFlags, &varExtension); _JumpIfError(hr, error, "Policy:polSetCertificateExtension"); error: if (NULL != pbConstraints) { LocalFree(pbConstraints); } if (NULL != strExtension) { SysFreeString(strExtension); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicy::_SetValidityPeriod // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::_SetValidityPeriod( IN ICertServerPolicy *pServer) { HRESULT hr; BSTR strPeriodString = NULL; BSTR strPeriodCount = NULL; BSTR strNameNotBefore = NULL; BSTR strNameNotAfter = NULL; VARIANT varValue; LONG lDelta; ENUM_PERIOD enumValidityPeriod; BOOL fValidDigitString; VariantInit(&varValue); if (!(EDITF_ATTRIBUTEENDDATE & m_dwEditFlags)) { hr = S_OK; goto error; } hr = polGetRequestAttribute( pServer, wszPROPVALIDITYPERIODSTRING, &strPeriodString); if (S_OK != hr) { _PrintErrorStr2( hr, "Policy:polGetRequestAttribute", wszPROPVALIDITYPERIODSTRING, CERTSRV_E_PROPERTY_EMPTY); if (CERTSRV_E_PROPERTY_EMPTY == hr) { hr = S_OK; } goto error; } hr = polGetRequestAttribute( pServer, wszPROPVALIDITYPERIODCOUNT, &strPeriodCount); if (S_OK != hr) { _PrintErrorStr2( hr, "Policy:polGetRequestAttribute", wszPROPVALIDITYPERIODCOUNT, CERTSRV_E_PROPERTY_EMPTY); if (CERTSRV_E_PROPERTY_EMPTY == hr) { hr = S_OK; } goto error; } // Swap Count and String BSTRs if backwards -- Windows 2000 had it wrong. lDelta = ceWtoI(strPeriodCount, &fValidDigitString); if (!fValidDigitString) { BSTR str = strPeriodCount; strPeriodCount = strPeriodString; strPeriodString = str; lDelta = ceWtoI(strPeriodCount, &fValidDigitString); if (!fValidDigitString) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "Policy:ceWtoI"); } } hr = ceTranslatePeriodUnits(strPeriodString, lDelta, &enumValidityPeriod, &lDelta); _JumpIfError(hr, error, "Policy:ceTranslatePeriodUnits"); strNameNotBefore = SysAllocString(wszPROPCERTIFICATENOTBEFOREDATE); if (NULL == strNameNotBefore) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->GetCertificateProperty( strNameNotBefore, PROPTYPE_DATE, &varValue); _JumpIfError(hr, error, "Policy:GetCertificateProperty"); hr = ceMakeExprDate(&varValue.date, lDelta, enumValidityPeriod); _JumpIfError(hr, error, "Policy:ceMakeExprDate"); strNameNotAfter = SysAllocString(wszPROPCERTIFICATENOTAFTERDATE); if (NULL == strNameNotAfter) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->SetCertificateProperty( strNameNotAfter, PROPTYPE_DATE, &varValue); _JumpIfError(hr, error, "Policy:SetCertificateProperty"); hr = S_OK; error: VariantClear(&varValue); if (NULL != strPeriodString) { SysFreeString(strPeriodString); } if (NULL != strPeriodCount) { SysFreeString(strPeriodCount); } if (NULL != strNameNotBefore) { SysFreeString(strNameNotBefore); } if (NULL != strNameNotAfter) { SysFreeString(strNameNotAfter); } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::_AddV1TemplateNameExtension // // Returns S_OK on success. //+-------------------------------------------------------------------------- HRESULT CCertPolicySample::AddV1TemplateNameExtension( IN ICertServerPolicy *pServer, OPTIONAL IN WCHAR const *pwszTemplateName) { HRESULT hr; BSTR strName = NULL; LONG ExtFlags = 0; VARIANT varExtension; CERT_NAME_VALUE *pName = NULL; CERT_NAME_VALUE NameValue; DWORD cbEncoded; BYTE *pbEncoded = NULL; BOOL fUpdate = TRUE; VariantInit(&varExtension); strName = SysAllocString(TEXT(szOID_ENROLL_CERTTYPE_EXTENSION)); if (NULL == strName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->GetCertificateExtension( strName, PROPTYPE_BINARY, &varExtension); _PrintIfError2(hr, "Policy:GetCertificateExtension", hr); if (CERTSRV_E_PROPERTY_EMPTY == hr) { if (NULL == pwszTemplateName) { hr = S_OK; goto error; } } else { _JumpIfError(hr, error, "Policy:GetCertificateExtension"); hr = pServer->GetCertificateExtensionFlags(&ExtFlags); _JumpIfError(hr, error, "Policy:GetCertificateExtensionFlags"); if (VT_BSTR == varExtension.vt && 0 == (EXTENSION_DISABLE_FLAG & ExtFlags) && NULL != pwszTemplateName) { if (!ceDecodeObject( X509_ASN_ENCODING, X509_UNICODE_ANY_STRING, (BYTE *) varExtension.bstrVal, SysStringByteLen(varExtension.bstrVal), FALSE, (VOID **) &pName, &cbEncoded)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:ceDecodeObject"); } // case sensitive compare -- be sure to match case of template if (0 == lstrcmp( (WCHAR const *) pName->Value.pbData, pwszTemplateName)) { fUpdate = FALSE; } } } if (fUpdate) { if (NULL == pwszTemplateName) { ExtFlags |= EXTENSION_DISABLE_FLAG; } else { VariantClear(&varExtension); varExtension.bstrVal = NULL; NameValue.dwValueType = CERT_RDN_UNICODE_STRING; NameValue.Value.pbData = (BYTE *) pwszTemplateName; NameValue.Value.cbData = 0; if (!ceEncodeObject( X509_ASN_ENCODING, X509_UNICODE_ANY_STRING, &NameValue, 0, FALSE, &pbEncoded, &cbEncoded)) { hr = ceHLastError(); _JumpError(hr, error, "Policy:ceEncodeObject"); } if (!ceConvertWszToBstr( &varExtension.bstrVal, (WCHAR const *) pbEncoded, cbEncoded)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:ceConvertWszToBstr"); } varExtension.vt = VT_BSTR; ExtFlags &= ~EXTENSION_DISABLE_FLAG; } hr = pServer->SetCertificateExtension( strName, PROPTYPE_BINARY, ExtFlags, &varExtension); _JumpIfError(hr, error, "Policy:SetCertificateExtension"); } hr = S_OK; error: VariantClear(&varExtension); if (NULL != strName) { SysFreeString(strName); } if (NULL != pName) { LocalFree(pName); } if (NULL != pbEncoded) { LocalFree(pbEncoded); } return(hr); } STDMETHODIMP CCertPolicySample::VerifyRequest( /* [in] */ BSTR const, // strConfig /* [in] */ LONG Context, /* [in] */ LONG bNewRequest, /* [in] */ LONG, // Flags /* [out, retval] */ LONG __RPC_FAR *pDisposition) { HRESULT hr = E_FAIL; ICertServerPolicy *pServer = NULL; LONG lRequestId; CRequestInstance Request; BSTR strDisposition = NULL; BOOL fEnableEnrolleeExtensions; BOOL fReenroll = FALSE; DWORD cCriticalExtensions = 0; WCHAR const * const *apwszCriticalExtensions = NULL; lRequestId = 0; __try { if (NULL == pDisposition) { hr = E_POINTER; _LeaveError(hr, "Policy:pDisposition"); } *pDisposition = VR_INSTANT_BAD; hr = polGetServerCallbackInterface(&pServer, Context); _LeaveIfError(hr, "Policy:polGetServerCallbackInterface"); hr = GetRequestId(pServer, &lRequestId); _JumpIfError(hr, deny, "Policy:GetRequestId"); // only need to check user access for original submitter: // resubmit can only be called by admins if (bNewRequest && (0 == (m_dwEditFlags & EDITF_IGNOREREQUESTERGROUP))) { BOOL fRequesterAccess = FALSE; // Is this user allowed to request certs? hr = polGetCertificateLongProperty( pServer, wszPROPREQUESTERCAACCESS, (LONG *) &fRequesterAccess); _PrintIfErrorStr( hr, "Policy:polGetCertificateLongProperty", wszPROPREQUESTERCAACCESS); if (hr != S_OK || !fRequesterAccess) { hr = CERTSRV_E_ENROLL_DENIED; _JumpError(hr, deny, "Policy:fRequesterAccess"); } } hr = Request.Initialize( this, pServer, &fEnableEnrolleeExtensions); _LeaveIfError(hr, "Policy:VerifyRequest:Request.Initialize"); hr = _EnumerateExtensions( pServer, bNewRequest, TRUE, fEnableEnrolleeExtensions, 0, NULL); _LeaveIfError(hr, "_EnumerateExtensions"); { hr = _AddDefaultBasicConstraintsExtension( pServer, Request.IsCARequest()); _LeaveIfError(hr, "_AddDefaultBasicConstraintsExtension"); hr = _AddDefaultKeyUsageExtension(pServer, Request.IsCARequest()); _LeaveIfError(hr, "_AddDefaultKeyUsageExtension"); hr = _AddEnhancedKeyUsageExtension(pServer); _LeaveIfError(hr, "_AddEnhancedKeyUsageExtension"); } hr = _SetValidityPeriod(pServer); _LeaveIfError(hr, "_SetValidityPeriod"); hr = EnumerateAttributes(pServer); _LeaveIfError(hr, "Policy:EnumerateAttributes"); hr = _AddRevocationExtension(pServer); _LeaveIfError(hr, "_AddRevocationExtension"); hr = _AddOldCertTypeExtension(pServer, Request.IsCARequest()); _LeaveIfError(hr, "_AddOldCertTypeExtension"); hr = _AddAuthorityKeyId(pServer); _LeaveIfError(hr, "_AddAuthorityKeyId"); // pass hr as Disposition if ((EDITF_DISABLEEXTENSIONLIST & m_dwEditFlags) || NULL != apwszCriticalExtensions) { hr = _EnumerateExtensions( pServer, bNewRequest, FALSE, FALSE, cCriticalExtensions, apwszCriticalExtensions); _LeaveIfError(hr, "_EnumerateExtensions"); } if (bNewRequest && ( (REQDISP_PENDINGFIRST & m_dwDispositionFlags))) { *pDisposition = VR_PENDING; } else switch (REQDISP_MASK & m_dwDispositionFlags) { default: case REQDISP_PENDING: *pDisposition = VR_PENDING; break; case REQDISP_ISSUE: *pDisposition = VR_INSTANT_OK; break; case REQDISP_DENY: *pDisposition = VR_INSTANT_BAD; break; case REQDISP_USEREQUESTATTRIBUTE: *pDisposition = VR_INSTANT_OK; hr = polGetRequestAttribute( pServer, wszPROPDISPOSITION, &strDisposition); if (S_OK == hr) { if (0 == celstrcmpiL(strDisposition, wszPROPDISPOSITIONDENY)) { *pDisposition = VR_INSTANT_BAD; } if (0 == celstrcmpiL(strDisposition, wszPROPDISPOSITIONPENDING)) { *pDisposition = VR_PENDING; } } hr = S_OK; break; } deny: if (FAILED(hr)) { *pDisposition = hr; // pass failed HRESULT back as Disposition } else if (hr != S_OK) { *pDisposition = VR_INSTANT_BAD; } hr = S_OK; } __except(hr = ceHError(GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); } { HRESULT hr2 = hr; #define wszFORMATREQUESTID L"RequestId=%u" WCHAR wszRequestId[ARRAYSIZE(wszFORMATREQUESTID) + cwcDWORDSPRINTF]; if (S_OK == hr2 && NULL != pDisposition && FAILED(*pDisposition)) { hr2 = *pDisposition; } if (S_OK != hr2) { wsprintf(wszRequestId, wszFORMATREQUESTID, lRequestId); _PrintErrorStr(hr2, "VerifyRequest", wszRequestId); } } if (NULL != strDisposition) { SysFreeString(strDisposition); } if (NULL != pServer) { pServer->Release(); } //_PrintIfError(hr, "Policy:VerifyRequest(hr)"); //_PrintError(*pDisposition, "Policy:VerifyRequest(*pDisposition)"); return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::GetDescription // // Returns S_OK on success. //+-------------------------------------------------------------------------- STDMETHODIMP CCertPolicySample::GetDescription( /* [out, retval] */ BSTR __RPC_FAR *pstrDescription) { HRESULT hr = S_OK; WCHAR sz[MAX_PATH]; if(!m_strDescription) { assert(wcslen(wsz_SAMPLE_DESCRIPTION) < ARRAYSIZE(sz)); wcsncpy(sz, wsz_SAMPLE_DESCRIPTION, ARRAYSIZE(sz)); sz[ARRAYSIZE(sz) - 1] = L'\0'; m_strDescription = SysAllocString(sz); if (NULL == m_strDescription) { hr = E_OUTOFMEMORY; return hr; } } if (NULL != *pstrDescription) { SysFreeString(*pstrDescription); } *pstrDescription = SysAllocString(m_strDescription); if (NULL == *pstrDescription) { hr = E_OUTOFMEMORY; } return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::ShutDown // // Returns S_OK on success. //+-------------------------------------------------------------------------- STDMETHODIMP CCertPolicySample::ShutDown(VOID) { // called once, as Server unloading policy dll _Cleanup(); return(S_OK); } //+-------------------------------------------------------------------------- // CCertPolicySample::GetManageModule // // Returns S_OK on success. //+-------------------------------------------------------------------------- STDMETHODIMP CCertPolicySample::GetManageModule( /* [out, retval] */ ICertManageModule **ppManageModule) { HRESULT hr; *ppManageModule = NULL; hr = CoCreateInstance( CLSID_CCertManagePolicyModuleSample, NULL, // pUnkOuter CLSCTX_INPROC_SERVER, IID_ICertManageModule, (VOID **) ppManageModule); _JumpIfError(hr, error, "CoCreateInstance"); error: return(hr); } //+-------------------------------------------------------------------------- // CCertPolicySample::_GetIssuer // // Returns S_OK on success. //+-------------------------------------------------------------------------- PCCERT_CONTEXT CCertPolicySample::_GetIssuer( IN ICertServerPolicy *pServer) { HRESULT hr; VARIANT varValue; BSTR strName = NULL; VariantInit(&varValue); if (NULL != m_pCert) { hr = S_OK; goto error; } strName = SysAllocString(wszPROPRAWCACERTIFICATE); if (NULL == strName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "Policy:SysAllocString"); } hr = pServer->GetCertificateProperty(strName, PROPTYPE_BINARY, &varValue); _JumpIfError(hr, error, "Policy:GetCertificateProperty"); m_pCert = CertCreateCertificateContext( X509_ASN_ENCODING, (BYTE *) varValue.bstrVal, SysStringByteLen(varValue.bstrVal)); if (NULL == m_pCert) { hr = ceHLastError(); _JumpError(hr, error, "Policy:CertCreateCertificateContext"); } error: VariantClear(&varValue); if (NULL != strName) { SysFreeString(strName); } return(m_pCert); } STDMETHODIMP CCertPolicySample::InterfaceSupportsErrorInfo( IN REFIID riid) { static const IID *arr[] = { &IID_ICertPolicy, }; for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) { if (IsEqualGUID(*arr[i], riid)) { return(S_OK); } } return(S_FALSE); }