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.
2362 lines
57 KiB
2362 lines
57 KiB
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996-1998
|
|
//
|
|
// copied from K2 SDK policy.cpp.
|
|
// modified by GregKr for expolicy.
|
|
//
|
|
// File: expolicy.cpp
|
|
//
|
|
// Contents: KMS-specific Cert Server Policy Module implementation
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
#include "policy.h"
|
|
#include "celib.h"
|
|
//#include "newcert.h"
|
|
#include <assert.h>
|
|
|
|
#include <exver.h> // Exchange build version (rmj et al)
|
|
#include <kmsattr.h> // strings used by both KMS and ExPolicy
|
|
|
|
#ifndef DBG_CERTSRV
|
|
#error -- DBG_CERTSRV not defined!
|
|
#endif
|
|
|
|
BOOL fDebug = DBG_CERTSRV;
|
|
|
|
#if DBG_CERTSRV
|
|
#define EXP_FLAVOR L" debug"
|
|
#else
|
|
#define EXP_FLAVOR
|
|
#endif
|
|
|
|
#define MAKEFILEVERSION(_rmaj, _rmin, _bmaj, _bmin) \
|
|
L#_rmaj L"." L#_rmin L"." L#_bmaj L"." L#_bmin EXP_FLAVOR
|
|
|
|
#define MAKE_FILEVERSION_STR(_rmaj, _rmin, _bmaj, _bmin) \
|
|
MAKEFILEVERSION(_rmaj, _rmin, _bmaj, _bmin)
|
|
|
|
#define VER_FILEVERSION_STR \
|
|
MAKE_FILEVERSION_STR(rmj, rmn, rmm, rup)
|
|
|
|
const WCHAR g_wszDescription[] =
|
|
L"Microsoft Exchange KMServer Policy Module " VER_FILEVERSION_STR;
|
|
|
|
|
|
// worker
|
|
HRESULT
|
|
GetServerCallbackInterface(
|
|
OUT ICertServerPolicy **ppServer,
|
|
IN LONG Context)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == ppServer)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_CCertServerPolicy,
|
|
NULL, // pUnkOuter
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICertServerPolicy,
|
|
(VOID **) ppServer);
|
|
_JumpIfError(hr, error, "CoCreateInstance");
|
|
|
|
if (*ppServer == NULL)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
_JumpError(hr, error, "NULL *ppServer");
|
|
}
|
|
|
|
// only set context if nonzero
|
|
if (0 != Context)
|
|
{
|
|
hr = (*ppServer)->SetContext(Context);
|
|
_JumpIfError(hr, error, "Policy:SetContext");
|
|
}
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
WCHAR const * const s_rgpwszRegMultiStrValues[] =
|
|
{
|
|
wszREGLDAPISSUERCERTURL_OLD,
|
|
wszREGISSUERCERTURL_OLD,
|
|
wszREGFTPISSUERCERTURL_OLD,
|
|
wszREGFILEISSUERCERTURL_OLD,
|
|
wszREGLDAPREVOCATIONCRLURL_OLD,
|
|
wszREGREVOCATIONCRLURL_OLD,
|
|
wszREGFTPREVOCATIONCRLURL_OLD,
|
|
wszREGFILEREVOCATIONCRLURL_OLD,
|
|
};
|
|
|
|
|
|
typedef struct _REGDWORDVALUE
|
|
{
|
|
WCHAR const *pwszName;
|
|
DWORD dwValueDefault;
|
|
} REGDWORDVALUE;
|
|
|
|
const REGDWORDVALUE s_rgRegDWordValues[] =
|
|
{
|
|
{
|
|
wszREGREQUESTDISPOSITION,
|
|
REQDISP_ISSUE
|
|
},
|
|
{
|
|
wszREGISSUERCERTURLFLAGS,
|
|
ISSCERT_ENABLE |
|
|
ISSCERT_LDAPURL_OLD |
|
|
ISSCERT_HTTPURL_OLD |
|
|
ISSCERT_FTPURL_OLD |
|
|
ISSCERT_FILEURL_OLD
|
|
},
|
|
{
|
|
wszREGREVOCATIONTYPE,
|
|
REVEXT_CDPENABLE |
|
|
REVEXT_CDPLDAPURL_OLD |
|
|
REVEXT_CDPHTTPURL_OLD |
|
|
REVEXT_CDPFTPURL_OLD |
|
|
REVEXT_CDPFILEURL_OLD
|
|
},
|
|
};
|
|
|
|
|
|
HRESULT
|
|
CopyMultiStrRegValue(
|
|
IN HKEY hkeySrc,
|
|
IN HKEY hkeyDest,
|
|
IN WCHAR const *pwszName)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbValue;
|
|
DWORD dwType;
|
|
WCHAR *pwszzAlloc = NULL;
|
|
WCHAR *pwszzValue;
|
|
|
|
hr = RegQueryValueEx(hkeyDest, pwszName, NULL, &dwType, NULL, &cbValue);
|
|
if (S_OK == hr && REG_MULTI_SZ == dwType)
|
|
{
|
|
goto error; // preserve existing value
|
|
}
|
|
|
|
hr = RegQueryValueEx(hkeySrc, pwszName, NULL, &dwType, NULL, &cbValue);
|
|
if (S_OK == hr && REG_MULTI_SZ == dwType && sizeof(WCHAR) < cbValue)
|
|
{
|
|
pwszzAlloc = (WCHAR *) LocalAlloc(LMEM_FIXED, cbValue);
|
|
if (NULL == pwszzAlloc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
hr = RegQueryValueEx(
|
|
hkeySrc,
|
|
pwszName,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) pwszzAlloc,
|
|
&cbValue);
|
|
_JumpIfError(hr, error, "RegQueryValueEx");
|
|
|
|
pwszzValue = pwszzAlloc;
|
|
}
|
|
else
|
|
{
|
|
pwszzValue = L"\0";
|
|
cbValue = 2 * sizeof(WCHAR);
|
|
}
|
|
|
|
hr = RegSetValueEx(
|
|
hkeyDest,
|
|
pwszName,
|
|
NULL,
|
|
REG_MULTI_SZ,
|
|
(BYTE const *) pwszzValue,
|
|
cbValue);
|
|
_JumpIfError(hr, error, "RegSetValueEx");
|
|
|
|
error:
|
|
if (NULL != pwszzAlloc)
|
|
{
|
|
LocalFree(pwszzAlloc);
|
|
}
|
|
return(ceHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CopyDWordRegValue(
|
|
IN HKEY hkeySrc,
|
|
IN HKEY hkeyDest,
|
|
IN REGDWORDVALUE const *prdv)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbValue;
|
|
DWORD dwType;
|
|
DWORD dwValue;
|
|
|
|
hr = RegQueryValueEx(hkeyDest, prdv->pwszName, NULL, &dwType, NULL, &cbValue);
|
|
if (S_OK == hr && REG_DWORD == dwType)
|
|
{
|
|
goto error; // preserve existing value
|
|
}
|
|
|
|
cbValue = sizeof(dwValue);
|
|
hr = RegQueryValueEx(
|
|
hkeySrc,
|
|
prdv->pwszName,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) &dwValue,
|
|
&cbValue);
|
|
if (S_OK != hr || REG_DWORD != dwType || sizeof(dwValue) != cbValue)
|
|
{
|
|
dwValue = prdv->dwValueDefault;
|
|
}
|
|
|
|
hr = RegSetValueEx(
|
|
hkeyDest,
|
|
prdv->pwszName,
|
|
NULL,
|
|
REG_DWORD,
|
|
(BYTE const *) &dwValue,
|
|
sizeof(dwValue));
|
|
_JumpIfError(hr, error, "RegSetValueEx");
|
|
|
|
error:
|
|
return(ceHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
PopulateRegistryDefaults(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
IN WCHAR const *pwszStorageLocation)
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
HKEY hkeyHKLM = NULL;
|
|
HKEY hkeyDest = NULL;
|
|
HKEY hkeySrc = NULL;
|
|
DWORD dwDisposition;
|
|
WCHAR const *pwsz;
|
|
WCHAR *pwszSrc = NULL;
|
|
DWORD cwcPrefix;
|
|
DWORD cwc;
|
|
DWORD i;
|
|
|
|
DBGPRINT((TRUE, "pwszDest: '%ws'\n", pwszStorageLocation));
|
|
pwsz = wcsrchr(pwszStorageLocation, L'\\');
|
|
if (NULL == pwsz)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "Invalid registry path");
|
|
}
|
|
pwsz++;
|
|
cwcPrefix = SAFE_SUBTRACT_POINTERS(pwsz, pwszStorageLocation);
|
|
cwc = cwcPrefix + WSZARRAYSIZE(wszCLASS_CERTPOLICY);
|
|
pwszSrc = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
|
|
if (NULL == pwszSrc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
CopyMemory(pwszSrc, pwszStorageLocation, cwcPrefix * sizeof(WCHAR));
|
|
wcscpy(&pwszSrc[cwcPrefix], wszCLASS_CERTPOLICY);
|
|
assert(wcslen(pwszSrc) == cwc);
|
|
|
|
DBGPRINT((TRUE, "pwszSrc: '%ws'\n", pwszSrc));
|
|
|
|
if (NULL != pwszMachine)
|
|
{
|
|
hr = RegConnectRegistry(
|
|
pwszMachine,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hkeyHKLM);
|
|
_JumpIfError(hr, error, "RegConnectRegistry");
|
|
}
|
|
|
|
// open destination storage location for write
|
|
|
|
hr = RegCreateKeyEx(
|
|
NULL == pwszMachine? HKEY_LOCAL_MACHINE : hkeyHKLM,
|
|
pwszStorageLocation,
|
|
0,
|
|
NULL,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
NULL,
|
|
&hkeyDest,
|
|
&dwDisposition);
|
|
if (hr != S_OK)
|
|
{
|
|
_JumpError(hr, error, "RegOpenKeyEx");
|
|
}
|
|
|
|
// open source storage location for read
|
|
|
|
hr = RegOpenKeyEx(
|
|
NULL == pwszMachine? HKEY_LOCAL_MACHINE : hkeyHKLM,
|
|
pwszSrc,
|
|
0,
|
|
KEY_READ,
|
|
&hkeySrc);
|
|
_JumpIfError(hr, error, "RegOpenKeyEx");
|
|
|
|
hr = S_OK;
|
|
for (i = 0; i < ARRAYSIZE(s_rgpwszRegMultiStrValues); i++)
|
|
{
|
|
hr2 = CopyMultiStrRegValue(
|
|
hkeySrc,
|
|
hkeyDest,
|
|
s_rgpwszRegMultiStrValues[i]);
|
|
if (S_OK != hr2)
|
|
{
|
|
_PrintErrorStr(
|
|
hr2,
|
|
"CopyMultiStrRegValue",
|
|
s_rgpwszRegMultiStrValues[i]);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = hr2;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAYSIZE(s_rgRegDWordValues); i++)
|
|
{
|
|
hr2 = CopyDWordRegValue(
|
|
hkeySrc,
|
|
hkeyDest,
|
|
&s_rgRegDWordValues[i]);
|
|
if (S_OK != hr2)
|
|
{
|
|
_PrintErrorStr(
|
|
hr2,
|
|
"CopyDWordRegValue",
|
|
s_rgRegDWordValues[i].pwszName);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = hr2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
error:
|
|
if (NULL != pwszSrc)
|
|
{
|
|
LocalFree(pwszSrc);
|
|
}
|
|
if (NULL != hkeyHKLM)
|
|
{
|
|
RegCloseKey(hkeyHKLM);
|
|
}
|
|
if (NULL != hkeyDest)
|
|
{
|
|
RegCloseKey(hkeyDest);
|
|
}
|
|
if (NULL != hkeySrc)
|
|
{
|
|
RegCloseKey(hkeySrc);
|
|
}
|
|
return(ceHError(hr));
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::~CCertPolicyExchange -- destructor
|
|
//
|
|
// free memory associated with this instance
|
|
//+--------------------------------------------------------------------------
|
|
|
|
CCertPolicyExchange::~CCertPolicyExchange()
|
|
{
|
|
_Cleanup();
|
|
}
|
|
|
|
|
|
VOID
|
|
CCertPolicyExchange::_FreeStringArray(
|
|
IN OUT DWORD *pcString,
|
|
IN OUT LPWSTR **papstr)
|
|
{
|
|
BSTR *apstr = *papstr;
|
|
DWORD i;
|
|
|
|
if (NULL != apstr)
|
|
{
|
|
for (i = *pcString; i-- > 0; )
|
|
{
|
|
if (NULL != apstr[i])
|
|
{
|
|
DBGPRINT((fDebug, "_FreeStringArray[%u]: '%ws'\n", i, apstr[i]));
|
|
LocalFree(apstr[i]);
|
|
}
|
|
}
|
|
LocalFree(apstr);
|
|
*papstr = NULL;
|
|
}
|
|
*pcString = 0;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_Cleanup -- free memory associated with this instance
|
|
//
|
|
// free memory associated with this instance
|
|
//+--------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CCertPolicyExchange::_Cleanup()
|
|
{
|
|
// RevocationExtension variables:
|
|
|
|
_FreeStringArray(&m_cCDPRevocationURL, &m_ppwszCDPRevocationURL);
|
|
|
|
if (NULL != m_pwszASPRevocationURL)
|
|
{
|
|
LocalFree(m_pwszASPRevocationURL);
|
|
m_pwszASPRevocationURL = NULL;
|
|
}
|
|
|
|
// AuthorityInfoAccessExtension variables:
|
|
|
|
_FreeStringArray(&m_cIssuerCertURL, &m_ppwszIssuerCertURL);
|
|
|
|
if (NULL != m_bstrMachineDNSName)
|
|
{
|
|
SysFreeString(m_bstrMachineDNSName);
|
|
m_bstrMachineDNSName = NULL;
|
|
}
|
|
if (NULL != m_bstrCASanitizedName)
|
|
{
|
|
SysFreeString(m_bstrCASanitizedName);
|
|
m_bstrCASanitizedName = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_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, "RegQueryValueEx", pwszRegName, ERROR_FILE_NOT_FOUND);
|
|
|
|
if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpErrorStr(hr, error, "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, "LocalAlloc", pwszRegName);
|
|
}
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
pwszRegName,
|
|
NULL, // lpdwReserved
|
|
&dwType,
|
|
(BYTE *) pwszRegValue,
|
|
&cbValue);
|
|
_JumpIfErrorStr(hr, error, "RegQueryValueEx", pwszRegName);
|
|
|
|
// Handle malformed registry values cleanly:
|
|
|
|
pwszRegValue[cbValue / sizeof(WCHAR)] = L'\0';
|
|
if (NULL != pwszSuffix)
|
|
{
|
|
wcscat(pwszRegValue, pwszSuffix);
|
|
}
|
|
|
|
hr = ceFormatCertsrvStringArray(
|
|
fURL, // fURL
|
|
m_bstrMachineDNSName, // pwszServerName_p1_2
|
|
m_bstrCASanitizedName, // pwszSanitizedName_p3_7
|
|
m_iCert, // iCert_p4
|
|
MAXDWORD, // iCertTarget_p4
|
|
L"", // pwszDomainDN_p5
|
|
L"", // pwszConfigDN_p6
|
|
m_iCRL, // iCRL_p8
|
|
FALSE, // fDeltaCRL_p9,
|
|
FALSE, // fDSAttrib_p10_11,
|
|
1, // cStrings
|
|
(LPCWSTR *) &pwszRegValue, // apwszStringsIn
|
|
ppwszOut); // apwszStringsOut
|
|
_JumpIfError(hr, error, "ceFormatCertsrvStringArray");
|
|
|
|
error:
|
|
if (NULL != pwszRegValue)
|
|
{
|
|
LocalFree(pwszRegValue);
|
|
}
|
|
return(ceHError(hr));
|
|
}
|
|
|
|
|
|
#if DBG_CERTSRV
|
|
|
|
VOID
|
|
CCertPolicyExchange::_DumpStringArray(
|
|
IN char const *pszType,
|
|
IN DWORD cpwsz,
|
|
IN WCHAR const * const *ppwsz)
|
|
{
|
|
DWORD i;
|
|
WCHAR const *pwszName;
|
|
|
|
for (i = 0; i < cpwsz; i++)
|
|
{
|
|
pwszName = L"";
|
|
if (iswdigit(ppwsz[i][0]))
|
|
{
|
|
pwszName = ceGetOIDName(ppwsz[i]); // Static: do not free!
|
|
}
|
|
DBGPRINT((
|
|
fDebug,
|
|
"%hs[%u]: %ws%hs%ws\n",
|
|
pszType,
|
|
i,
|
|
ppwsz[i],
|
|
L'\0' != *pwszName? " -- " : "",
|
|
pwszName));
|
|
}
|
|
}
|
|
#endif // DBG_CERTSRV
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddStringArray(
|
|
IN WCHAR const *pwszzValue,
|
|
IN BOOL fURL,
|
|
IN OUT DWORD *pcStrings,
|
|
IN OUT LPWSTR **papstrRegValues)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
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
|
|
{
|
|
goto error;
|
|
}
|
|
awszFormatStrings = (LPCWSTR *) LocalAlloc(
|
|
LMEM_FIXED | LMEM_ZEROINIT,
|
|
cString * sizeof(LPWSTR));
|
|
if (NULL == awszFormatStrings)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "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, "LocalAlloc");
|
|
}
|
|
|
|
if (0 != *pcStrings)
|
|
{
|
|
assert(NULL != *papstrRegValues);
|
|
CopyMemory(awszOutputStrings, *papstrRegValues, *pcStrings * sizeof(LPWSTR));
|
|
}
|
|
|
|
hr = ceFormatCertsrvStringArray(
|
|
fURL, // fURL
|
|
m_bstrMachineDNSName, // pwszServerName_p1_2
|
|
m_bstrCASanitizedName, // pwszSanitizedName_p3_7
|
|
m_iCert, // iCert_p4
|
|
MAXDWORD, // iCertTarget_p4
|
|
L"", // pwszDomainDN_p5
|
|
L"", // pwszConfigDN_p6
|
|
m_iCRL, // iCRL_p8
|
|
FALSE, // fDeltaCRL_p9,
|
|
FALSE, // fDSAttrib_p10_11,
|
|
cString, // cStrings
|
|
awszFormatStrings, // apwszStringsIn
|
|
&awszOutputStrings[*pcStrings]); // apwszStringsOut
|
|
_JumpIfError(hr, error, "ceFormatCertsrvStringArray");
|
|
|
|
*pcStrings = (*pcStrings) + cString;
|
|
if (*papstrRegValues)
|
|
{
|
|
LocalFree(*papstrRegValues);
|
|
}
|
|
*papstrRegValues = awszOutputStrings;
|
|
awszOutputStrings = NULL;
|
|
}
|
|
|
|
error:
|
|
|
|
if (awszOutputStrings)
|
|
{
|
|
LocalFree(awszOutputStrings);
|
|
}
|
|
if (awszFormatStrings)
|
|
{
|
|
LocalFree(awszFormatStrings);
|
|
}
|
|
return(ceHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_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 **papstrRegValues)
|
|
{
|
|
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, "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, "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, "LocalAlloc", apwszRegNames[i]);
|
|
}
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
apwszRegNames[i],
|
|
NULL, // lpdwReserved
|
|
&dwType,
|
|
(BYTE *) pwszzValue,
|
|
&cbValue);
|
|
if (S_OK != hr)
|
|
{
|
|
_PrintErrorStr(hr, "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, papstrRegValues);
|
|
_JumpIfErrorStr(hr, error, "_AddStringArray", apwszRegNames[i]);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszzValue)
|
|
{
|
|
LocalFree(pwszzValue);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_InitRevocationExtension
|
|
//
|
|
//+--------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CCertPolicyExchange::_InitRevocationExtension(
|
|
IN HKEY hkey)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwType;
|
|
DWORD cb;
|
|
DWORD adwFlags[] = {
|
|
REVEXT_CDPLDAPURL_OLD,
|
|
REVEXT_CDPHTTPURL_OLD,
|
|
REVEXT_CDPFTPURL_OLD,
|
|
REVEXT_CDPFILEURL_OLD,
|
|
};
|
|
WCHAR *apwszRegNames[] = {
|
|
wszREGLDAPREVOCATIONCRLURL_OLD,
|
|
wszREGREVOCATIONCRLURL_OLD,
|
|
wszREGFTPREVOCATIONCRLURL_OLD,
|
|
wszREGFILEREVOCATIONCRLURL_OLD,
|
|
};
|
|
|
|
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)
|
|
{
|
|
goto error;
|
|
}
|
|
DBGPRINT((fDebug, "Revocation Flags = %x\n", m_dwRevocationFlags));
|
|
|
|
|
|
// clean up from previous call
|
|
if (NULL != m_ppwszCDPRevocationURL)
|
|
{
|
|
_FreeStringArray(&m_cCDPRevocationURL, &m_ppwszCDPRevocationURL);
|
|
}
|
|
|
|
if (NULL != m_pwszASPRevocationURL)
|
|
{
|
|
LocalFree(m_pwszASPRevocationURL);
|
|
m_pwszASPRevocationURL = NULL;
|
|
}
|
|
|
|
if (REVEXT_CDPENABLE & m_dwRevocationFlags)
|
|
{
|
|
assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNames));
|
|
hr = _ReadRegistryStringArray(
|
|
hkey,
|
|
TRUE, // fURL
|
|
m_dwRevocationFlags,
|
|
ARRAYSIZE(adwFlags),
|
|
adwFlags,
|
|
apwszRegNames,
|
|
&m_cCDPRevocationURL,
|
|
&m_ppwszCDPRevocationURL);
|
|
_JumpIfError(hr, error, "_ReadRegistryStringArray");
|
|
|
|
_DumpStringArray("CDP", m_cCDPRevocationURL, m_ppwszCDPRevocationURL);
|
|
}
|
|
|
|
if (REVEXT_ASPENABLE & m_dwRevocationFlags)
|
|
{
|
|
hr = _ReadRegistryString(
|
|
hkey,
|
|
TRUE, // fURL
|
|
wszREGREVOCATIONURL, // pwszRegName
|
|
L"?", // pwszSuffix
|
|
&m_pwszASPRevocationURL); // pstrRegValue
|
|
_JumpIfErrorStr(hr, error, "_ReadRegistryString", wszREGREVOCATIONCRLURL_OLD);
|
|
_DumpStringArray("ASP", 1, &m_pwszASPRevocationURL);
|
|
}
|
|
|
|
error:
|
|
;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_InitAuthorityInfoAccessExtension
|
|
//
|
|
//+--------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CCertPolicyExchange::_InitAuthorityInfoAccessExtension(
|
|
IN HKEY hkey)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwType;
|
|
DWORD cb;
|
|
DWORD adwFlags[] = {
|
|
ISSCERT_LDAPURL_OLD,
|
|
ISSCERT_HTTPURL_OLD,
|
|
ISSCERT_FTPURL_OLD,
|
|
ISSCERT_FILEURL_OLD,
|
|
};
|
|
WCHAR *apwszRegNames[] = {
|
|
wszREGLDAPISSUERCERTURL_OLD,
|
|
wszREGISSUERCERTURL_OLD,
|
|
wszREGFTPISSUERCERTURL_OLD,
|
|
wszREGFILEISSUERCERTURL_OLD,
|
|
};
|
|
|
|
// clean up from previous call
|
|
if (NULL != m_ppwszIssuerCertURL)
|
|
{
|
|
_FreeStringArray(&m_cIssuerCertURL, &m_ppwszIssuerCertURL);
|
|
}
|
|
|
|
|
|
|
|
cb = sizeof(m_dwIssuerCertURLFlags);
|
|
hr = RegQueryValueEx(
|
|
hkey,
|
|
wszREGISSUERCERTURLFLAGS,
|
|
NULL, // lpdwReserved
|
|
&dwType,
|
|
(BYTE *) &m_dwIssuerCertURLFlags,
|
|
&cb);
|
|
if (S_OK != hr ||
|
|
REG_DWORD != dwType ||
|
|
sizeof(m_dwIssuerCertURLFlags) != cb)
|
|
{
|
|
goto error;
|
|
}
|
|
DBGPRINT((fDebug, "Issuer Cert Flags = %x\n", m_dwIssuerCertURLFlags));
|
|
|
|
if (ISSCERT_ENABLE & m_dwIssuerCertURLFlags)
|
|
{
|
|
assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNames));
|
|
hr = _ReadRegistryStringArray(
|
|
hkey,
|
|
TRUE, // fURL
|
|
m_dwIssuerCertURLFlags,
|
|
ARRAYSIZE(adwFlags),
|
|
adwFlags,
|
|
apwszRegNames,
|
|
&m_cIssuerCertURL,
|
|
&m_ppwszIssuerCertURL);
|
|
_JumpIfError(hr, error, "_ReadRegistryStringArray");
|
|
|
|
_DumpStringArray("Issuer Cert", m_cIssuerCertURL, m_ppwszIssuerCertURL);
|
|
}
|
|
|
|
error:
|
|
;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::Initialize
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CCertPolicyExchange::Initialize(
|
|
/* [in] */ BSTR const strConfig)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey = NULL;
|
|
VARIANT varValue;
|
|
ICertServerPolicy *pServer = NULL;
|
|
BSTR strName = NULL;
|
|
|
|
VariantInit(&varValue);
|
|
|
|
_Cleanup();
|
|
|
|
hr = GetServerCallbackInterface(&pServer, 0);
|
|
_JumpIfError(hr, error, "GetServerCallbackInterface");
|
|
|
|
// get storage location
|
|
|
|
strName = SysAllocString(wszPROPMODULEREGLOC);
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
hr = pServer->GetCertificateProperty(
|
|
strName,
|
|
PROPTYPE_STRING,
|
|
&varValue);
|
|
_JumpIfError(hr, error, "GetCertificateProperty : wszPROPMODULEREGLOC");
|
|
|
|
m_pwszRegStorageLoc = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(wcslen(varValue.bstrVal) + 1) * sizeof(WCHAR));
|
|
if (NULL == m_pwszRegStorageLoc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(m_pwszRegStorageLoc, varValue.bstrVal);
|
|
VariantClear(&varValue);
|
|
|
|
hr = PopulateRegistryDefaults(NULL, m_pwszRegStorageLoc);
|
|
_PrintIfError(hr, "Policy:PopulateRegistryDefaults");
|
|
|
|
hr = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
m_pwszRegStorageLoc,
|
|
0, // dwReserved
|
|
KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE,
|
|
&hkey);
|
|
|
|
if ((HRESULT) ERROR_SUCCESS != hr)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
_JumpIfError(hr, error, "RegOpenKeyEx");
|
|
}
|
|
|
|
// Initialize the insertion string array.
|
|
// Machine DNS name (%1)
|
|
|
|
SysFreeString(strName);
|
|
strName = SysAllocString(wszPROPMACHINEDNSNAME);
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
hr = pServer->GetCertificateProperty(
|
|
strName,
|
|
PROPTYPE_STRING,
|
|
&varValue);
|
|
_JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
|
|
|
|
m_bstrMachineDNSName = SysAllocString(varValue.bstrVal);
|
|
if (NULL == m_bstrMachineDNSName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
VariantClear(&varValue);
|
|
|
|
SysFreeString(strName);
|
|
strName = SysAllocString(wszPROPCERTCOUNT);
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
hr = pServer->GetCertificateProperty(
|
|
strName,
|
|
PROPTYPE_LONG,
|
|
&varValue);
|
|
_JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
|
|
|
|
m_iCert = varValue.lVal - 1;
|
|
|
|
SysFreeString(strName);
|
|
strName = SysAllocString(wszPROPCRLINDEX);
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
hr = pServer->GetCertificateProperty(
|
|
strName,
|
|
PROPTYPE_LONG,
|
|
&varValue);
|
|
_JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
|
|
|
|
m_iCRL = varValue.lVal;
|
|
|
|
// get sanitized name
|
|
|
|
SysFreeString(strName);
|
|
strName = SysAllocString(wszPROPSANITIZEDCANAME);
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
hr = pServer->GetCertificateProperty(
|
|
strName,
|
|
PROPTYPE_STRING,
|
|
&varValue);
|
|
_JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
|
|
|
|
m_bstrCASanitizedName = SysAllocString(varValue.bstrVal);
|
|
if (NULL == m_bstrCASanitizedName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "SysAllocString");
|
|
}
|
|
VariantClear(&varValue);
|
|
|
|
_InitRevocationExtension(hkey);
|
|
_InitAuthorityInfoAccessExtension(hkey);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
VariantClear(&varValue);
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != hkey)
|
|
{
|
|
RegCloseKey(hkey);
|
|
}
|
|
if (NULL != pServer)
|
|
{
|
|
pServer->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
EnumerateExtensions(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hr2;
|
|
BSTR strName = NULL;
|
|
LONG ExtFlags;
|
|
VARIANT varValue;
|
|
BOOL fClose = FALSE;
|
|
|
|
VariantInit(&varValue);
|
|
hr = pServer->EnumerateExtensionsSetup(0);
|
|
_JumpIfError(hr, error, "EnumerateExtensionsSetup");
|
|
|
|
fClose = TRUE;
|
|
while (TRUE)
|
|
{
|
|
hr = pServer->EnumerateExtensions(&strName);
|
|
if (S_OK != hr)
|
|
{
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
_JumpError(hr, error, "EnumerateExtensions");
|
|
}
|
|
hr = pServer->GetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
&varValue);
|
|
_JumpIfError(hr, error, "GetCertificateExtension");
|
|
|
|
hr = pServer->GetCertificateExtensionFlags(&ExtFlags);
|
|
_JumpIfError(hr, error, "GetCertificateExtensionFlags");
|
|
|
|
if (fDebug)
|
|
{
|
|
wprintf(
|
|
L"Policy:EnumerateExtensions(%ws, Flags=%x, %x bytes)\n",
|
|
strName,
|
|
ExtFlags,
|
|
SysStringByteLen(varValue.bstrVal));
|
|
}
|
|
VariantClear(&varValue);
|
|
}
|
|
|
|
error:
|
|
if (fClose)
|
|
{
|
|
hr2 = pServer->EnumerateExtensionsClose();
|
|
if (S_OK != hr2)
|
|
{
|
|
_PrintError(hr2, "Policy:EnumerateExtensionsClose");
|
|
if (S_OK == hr)
|
|
{
|
|
hr = hr2;
|
|
}
|
|
}
|
|
}
|
|
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, "EnumerateAttributesSetup");
|
|
|
|
fClose = TRUE;
|
|
while (TRUE)
|
|
{
|
|
hr = pServer->EnumerateAttributes(&strName);
|
|
if (S_OK != hr)
|
|
{
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
_JumpError(hr, error, "EnumerateAttributes");
|
|
}
|
|
|
|
hr = pServer->GetRequestAttribute(strName, &strValue);
|
|
_JumpIfError(hr, error, "GetRequestAttribute");
|
|
|
|
if (fDebug)
|
|
{
|
|
wprintf(
|
|
L"Policy:EnumerateAttributes(%ws = %ws)\n",
|
|
strName,
|
|
strValue);
|
|
}
|
|
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
|
|
CheckRequestProperties(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr;
|
|
VARIANT varValue;
|
|
BSTR strName = NULL;
|
|
|
|
VariantInit(&varValue);
|
|
|
|
strName = SysAllocString(wszPROPREQUESTREQUESTID);
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
hr = pServer->GetRequestProperty(strName, PROPTYPE_LONG, &varValue);
|
|
_JumpIfError(hr, error, "GetRequestProperty");
|
|
|
|
if (fDebug)
|
|
{
|
|
wprintf(
|
|
L"Policy:CheckRequestProperties(%ws = %x)\n",
|
|
strName,
|
|
varValue.lVal);
|
|
}
|
|
VariantClear(&varValue);
|
|
|
|
error:
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddRevocationExtension
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddRevocationExtension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ICertEncodeCRLDistInfo *pCRLDist = NULL;
|
|
BSTR strCDPName = NULL;
|
|
BSTR strCDPExtension = NULL;
|
|
BSTR strName = NULL;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
DWORD i;
|
|
|
|
varExtension.vt = VT_BSTR;
|
|
if (NULL != m_ppwszCDPRevocationURL)
|
|
{
|
|
hr = CoCreateInstance(
|
|
CLSID_CCertEncodeCRLDistInfo,
|
|
NULL, // pUnkOuter
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICertEncodeCRLDistInfo,
|
|
(VOID **) &pCRLDist);
|
|
_JumpIfError(hr, error, "CoCreateInstance");
|
|
|
|
hr = pCRLDist->Reset(m_cCDPRevocationURL);
|
|
_JumpIfError(hr, error, "Reset");
|
|
|
|
for (i = 0; i < m_cCDPRevocationURL; i++)
|
|
{
|
|
DWORD j;
|
|
|
|
hr = pCRLDist->SetNameCount(i, 1);
|
|
_JumpIfError(hr, error, "SetNameCount");
|
|
|
|
for (j = 0; j < 1; j++)
|
|
{
|
|
BSTR str = SysAllocString(m_ppwszCDPRevocationURL[i]);
|
|
|
|
if (NULL == str)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
hr = pCRLDist->SetNameEntry(i, j, CERT_ALT_NAME_URL, str);
|
|
SysFreeString(str);
|
|
_JumpIfError(hr, error, "SetNameEntry");
|
|
}
|
|
}
|
|
hr = pCRLDist->Encode(&strCDPExtension);
|
|
_JumpIfError(hr, error, "Encode");
|
|
|
|
strCDPName = SysAllocString(TEXT(szOID_CRL_DIST_POINTS));
|
|
varExtension.bstrVal = strCDPExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strCDPName,
|
|
PROPTYPE_BINARY,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfErrorStr(hr, error, "SetCertificateExtension", L"CDP");
|
|
}
|
|
if (NULL != m_pwszASPRevocationURL)
|
|
{
|
|
strName = SysAllocString(TEXT(szOID_NETSCAPE_REVOCATION_URL));
|
|
strExtension = SysAllocString(m_pwszASPRevocationURL);
|
|
if (NULL == strName || NULL == strExtension)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_STRING,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfErrorStr(hr, error, "SetCertificateExtension", L"ASP");
|
|
VariantClear(&varExtension);
|
|
}
|
|
|
|
error:
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
if (NULL != strCDPName)
|
|
{
|
|
SysFreeString(strCDPName);
|
|
}
|
|
if (NULL != strCDPExtension)
|
|
{
|
|
SysFreeString(strCDPExtension);
|
|
}
|
|
if (NULL != pCRLDist)
|
|
{
|
|
pCRLDist->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddAuthorityInfoAccessExtension
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddAuthorityInfoAccessExtension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
BSTR strName = NULL;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
DWORD i;
|
|
|
|
CERT_AUTHORITY_INFO_ACCESS caio;
|
|
caio.rgAccDescr = NULL;
|
|
|
|
if (NULL == m_ppwszIssuerCertURL)
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
caio.cAccDescr = m_cIssuerCertURL;
|
|
caio.rgAccDescr = (CERT_ACCESS_DESCRIPTION *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
sizeof(CERT_ACCESS_DESCRIPTION) * m_cIssuerCertURL);
|
|
if (NULL == caio.rgAccDescr)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpIfError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
for (i = 0; i < m_cIssuerCertURL; i++)
|
|
{
|
|
caio.rgAccDescr[i].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
caio.rgAccDescr[i].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
caio.rgAccDescr[i].AccessLocation.pwszURL = m_ppwszIssuerCertURL[i];
|
|
}
|
|
|
|
if (!ceEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_AUTHORITY_INFO_ACCESS,
|
|
&caio,
|
|
0,
|
|
FALSE,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
{
|
|
hr = ceHLastError();
|
|
_JumpIfError(hr, error, "Policy:ceEncodeObject");
|
|
}
|
|
if (!ceConvertWszToBstr(
|
|
&strExtension,
|
|
(WCHAR const *) pbEncoded,
|
|
cbEncoded))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ceConvertWszToBstr");
|
|
}
|
|
strName = SysAllocString(TEXT(szOID_AUTHORITY_INFO_ACCESS));
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension(AuthInfoAccess)");
|
|
|
|
error:
|
|
if (NULL != pbEncoded)
|
|
{
|
|
LocalFree(pbEncoded);
|
|
}
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
if (NULL != caio.rgAccDescr)
|
|
{
|
|
LocalFree(caio.rgAccDescr);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddIssuerAltName2Extension
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddIssuerAltName2Extension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
BSTR strCertType = NULL;
|
|
BSTR strName = NULL;
|
|
BSTR strValue = NULL;
|
|
BSTR strKMServerName = NULL;
|
|
|
|
LPBYTE pbEncName = NULL;
|
|
ULONG cbEncName = 0;
|
|
|
|
LPBYTE pbEncExten = NULL;
|
|
ULONG cbEncExten = 0;
|
|
|
|
CERT_ALT_NAME_ENTRY cane = { 0 };
|
|
CERT_ALT_NAME_INFO cani = { 0 };
|
|
|
|
strKMServerName = SysAllocString(k_wszKMServerName);
|
|
if (NULL == strKMServerName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
hr = pServer->GetRequestAttribute(strKMServerName, &strValue);
|
|
_JumpIfErrorStr(
|
|
hr,
|
|
error,
|
|
CERTSRV_E_PROPERTY_EMPTY == hr?
|
|
"MISSING ATTRIBUTE -- GetRequestAttribute" :
|
|
"GetRequestAttribute",
|
|
k_wszKMServerName);
|
|
|
|
// CertStrToName to turn string into encoded name blob
|
|
|
|
if (!CertStrToNameW(
|
|
X509_ASN_ENCODING,
|
|
strValue,
|
|
CERT_X500_NAME_STR,
|
|
NULL,
|
|
NULL,
|
|
&cbEncName,
|
|
NULL))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CertStrToNameW");
|
|
}
|
|
|
|
pbEncName = new BYTE [cbEncName];
|
|
if (NULL == pbEncName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "new");
|
|
}
|
|
|
|
if (!CertStrToNameW(
|
|
X509_ASN_ENCODING,
|
|
strValue,
|
|
CERT_X500_NAME_STR,
|
|
NULL,
|
|
pbEncName,
|
|
&cbEncName,
|
|
NULL))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CertStrToNameW");
|
|
}
|
|
|
|
// fill in alt name info
|
|
|
|
cane.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
cane.DirectoryName.cbData = cbEncName;
|
|
cane.DirectoryName.pbData = pbEncName;
|
|
|
|
cani.cAltEntry = 1;
|
|
cani.rgAltEntry = &cane;
|
|
|
|
// encode alt name info
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ALTERNATE_NAME,
|
|
&cani,
|
|
NULL,
|
|
&cbEncExten))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
pbEncExten = new BYTE [cbEncExten];
|
|
if (NULL == pbEncExten)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "new");
|
|
}
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ALTERNATE_NAME,
|
|
&cani,
|
|
pbEncExten,
|
|
&cbEncExten))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
strName = SysAllocString(TEXT(szOID_ISSUER_ALT_NAME2));
|
|
strExtension = SysAllocStringByteLen((char *) pbEncExten, cbEncExten);
|
|
if (NULL == strName || NULL == strExtension)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
// add extension
|
|
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension(IssuerAltName2)");
|
|
|
|
error:
|
|
delete [] pbEncName;
|
|
delete [] pbEncExten;
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
if (NULL != strKMServerName)
|
|
{
|
|
SysFreeString(strKMServerName);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddSubjectAltName2Extension
|
|
//
|
|
// Returns S_OK on success.
|
|
// Returns S_FALSE for special request.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddSubjectAltName2Extension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
BSTR strCertType = NULL;
|
|
BSTR strName = NULL;
|
|
BSTR strDisplay = NULL;
|
|
BSTR strRFC822 = NULL;
|
|
|
|
BSTR strSubjAltNameRFC822 = NULL;
|
|
BSTR strSubjAltNameDisplay = NULL;
|
|
|
|
LPBYTE pbEncName = NULL;
|
|
ULONG cbEncName = 0;
|
|
|
|
LPBYTE pbEncExten = NULL;
|
|
ULONG cbEncExten = 0;
|
|
|
|
CERT_RDN_ATTR rdnattr = { 0 };
|
|
CERT_RDN rdn = { 0 };
|
|
CERT_NAME_INFO cni = { 0 };
|
|
CERT_ALT_NAME_ENTRY acane [2] = { 0 };
|
|
CERT_ALT_NAME_INFO cani = { 0 };
|
|
|
|
strSubjAltNameDisplay = SysAllocString(k_wszSubjAltNameDisplay);
|
|
if (NULL == strSubjAltNameDisplay)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
hr = pServer->GetRequestAttribute(strSubjAltNameDisplay, &strDisplay);
|
|
_JumpIfErrorStr(
|
|
hr,
|
|
error,
|
|
CERTSRV_E_PROPERTY_EMPTY == hr?
|
|
"MISSING ATTRIBUTE -- GetRequestAttribute" :
|
|
"GetRequestAttribute",
|
|
k_wszSubjAltNameDisplay);
|
|
|
|
strSubjAltNameRFC822 = SysAllocString(k_wszSubjAltNameRFC822);
|
|
if (NULL == strSubjAltNameRFC822)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
hr = pServer->GetRequestAttribute(strSubjAltNameRFC822, &strRFC822);
|
|
_JumpIfErrorStr(
|
|
hr,
|
|
error,
|
|
CERTSRV_E_PROPERTY_EMPTY == hr?
|
|
"MISSING ATTRIBUTE -- GetRequestAttribute" :
|
|
"GetRequestAttribute",
|
|
k_wszSubjAltNameRFC822);
|
|
|
|
// this identifies special request from KMS
|
|
|
|
if (0 == lstrcmpW(strDisplay, k_wszSpecialAttribute) &&
|
|
0 == lstrcmpW(strRFC822, k_wszSpecialAttribute))
|
|
{
|
|
hr = _AddSpecialAltNameExtension(pServer);
|
|
_JumpIfError(hr, error, "_AddSpecialAltNameExtension");
|
|
|
|
// there are no subject names to add, so exit
|
|
|
|
goto error;
|
|
}
|
|
|
|
// encode display name
|
|
|
|
rdnattr.pszObjId = szOID_COMMON_NAME;
|
|
rdnattr.dwValueType = CERT_RDN_UNICODE_STRING;
|
|
rdnattr.Value.cbData = SysStringByteLen(strDisplay);
|
|
rdnattr.Value.pbData = (LPBYTE) strDisplay;
|
|
|
|
rdn.cRDNAttr = 1;
|
|
rdn.rgRDNAttr = &rdnattr;
|
|
|
|
cni.cRDN = 1;
|
|
cni.rgRDN = &rdn;
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_NAME,
|
|
&cni,
|
|
NULL,
|
|
&cbEncName))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
pbEncName = new BYTE [cbEncName];
|
|
if (NULL == pbEncName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "new");
|
|
}
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_NAME,
|
|
&cni,
|
|
pbEncName,
|
|
&cbEncName))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
// fill in alt name info
|
|
|
|
acane[0].dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
acane[0].DirectoryName.cbData = cbEncName;
|
|
acane[0].DirectoryName.pbData = pbEncName;
|
|
|
|
acane[1].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
acane[1].pwszRfc822Name = strRFC822;
|
|
|
|
cani.cAltEntry = 2;
|
|
cani.rgAltEntry = acane;
|
|
|
|
// encode alt name info
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ALTERNATE_NAME,
|
|
&cani,
|
|
NULL,
|
|
&cbEncExten))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
pbEncExten = new BYTE [cbEncExten];
|
|
if (NULL == pbEncExten)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "new");
|
|
}
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ALTERNATE_NAME,
|
|
&cani,
|
|
pbEncExten,
|
|
&cbEncExten))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
strName = SysAllocString(TEXT(szOID_SUBJECT_ALT_NAME2));
|
|
strExtension = SysAllocStringByteLen((char *) pbEncExten, cbEncExten);
|
|
if (NULL == strName || NULL == strExtension)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
// add extension
|
|
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension");
|
|
|
|
error:
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
if (NULL != strSubjAltNameRFC822)
|
|
{
|
|
SysFreeString(strSubjAltNameRFC822);
|
|
}
|
|
if (NULL != strSubjAltNameDisplay)
|
|
{
|
|
SysFreeString(strSubjAltNameDisplay);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddSpecialAltNameExtension
|
|
//
|
|
// in response to request with both display and RFC822 equal to special value,
|
|
// fetch version info for CertSrv.exe and ExPolicy.dll, encode as multi-byte
|
|
// int, and set as IssuerAltName, marked critical. this should make cert
|
|
// unusable.
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddSpecialAltNameExtension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR strName = NULL;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
|
|
HRSRC hExeVersion = NULL;
|
|
HGLOBAL hExeVersionInMem = NULL;
|
|
LPBYTE pExeVersion = NULL;
|
|
|
|
// [0] to [3] are ExPolicy version.
|
|
// [4] to [7] are CertServer version.
|
|
WORD awVersions [] =
|
|
{ rmj, rmn, rmm, rup, 0, 0, 0, 0 };
|
|
|
|
ULONG ndxCertServer = 4;
|
|
|
|
CRYPT_INTEGER_BLOB intblobVersions = { 0 };
|
|
|
|
LPBYTE pbEncExten = NULL;
|
|
ULONG cbEncExten = 0;
|
|
|
|
// fill in version info
|
|
|
|
if (NULL == (hExeVersion =
|
|
FindResource(NULL, MAKEINTRESOURCE(1), RT_VERSION)) ||
|
|
NULL == (hExeVersionInMem = LoadResource(NULL, hExeVersion)) ||
|
|
NULL == (pExeVersion = (LPBYTE) LockResource(hExeVersionInMem)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "Find/Load/LockResource");
|
|
}
|
|
|
|
awVersions[ndxCertServer] = ((LPWORD)pExeVersion)[25];
|
|
awVersions[ndxCertServer + 1] = ((LPWORD)pExeVersion)[24];
|
|
awVersions[ndxCertServer + 2] = ((LPWORD)pExeVersion)[27];
|
|
awVersions[ndxCertServer + 3] = ((LPWORD)pExeVersion)[26];
|
|
|
|
intblobVersions.cbData = sizeof(awVersions);
|
|
intblobVersions.pbData = (LPBYTE) awVersions;
|
|
|
|
// encode version info
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_MULTI_BYTE_INTEGER,
|
|
&intblobVersions,
|
|
NULL,
|
|
&cbEncExten))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
pbEncExten = new BYTE [cbEncExten];
|
|
if (NULL == pbEncExten)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "new");
|
|
}
|
|
|
|
if (!CryptEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_MULTI_BYTE_INTEGER,
|
|
&intblobVersions,
|
|
pbEncExten,
|
|
&cbEncExten))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "CryptEncodeObject");
|
|
}
|
|
|
|
strName = SysAllocString(TEXT(szOID_ISSUER_ALT_NAME));
|
|
strExtension = SysAllocStringByteLen((char *) pbEncExten, cbEncExten);
|
|
if (NULL == strName || NULL == strExtension)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
// add extension
|
|
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
EXTENSION_CRITICAL_FLAG,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension");
|
|
|
|
error:
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
delete [] pbEncExten;
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddBasicConstraintsExtension
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddBasicConstraintsExtension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CERT_BASIC_CONSTRAINTS2_INFO bc2i;
|
|
BSTR strName = NULL;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
|
|
bc2i.fCA = FALSE;
|
|
bc2i.fPathLenConstraint = FALSE;
|
|
bc2i.dwPathLenConstraint = 0;
|
|
|
|
if (!ceEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_BASIC_CONSTRAINTS2,
|
|
&bc2i,
|
|
0,
|
|
FALSE,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
{
|
|
hr = GetLastError();
|
|
_JumpError(hr, error, "ceEncodeObject");
|
|
}
|
|
if (!ceConvertWszToBstr(
|
|
&strExtension,
|
|
(WCHAR const *) pbEncoded,
|
|
cbEncoded))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ceConvertWszToBstr");
|
|
}
|
|
|
|
strName = SysAllocString(TEXT(szOID_BASIC_CONSTRAINTS2));
|
|
if (NULL == strName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension");
|
|
|
|
error:
|
|
if (NULL != pbEncoded)
|
|
{
|
|
LocalFree(pbEncoded);
|
|
}
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddKeyUsageExtension
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddKeyUsageExtension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR strName = NULL;
|
|
ICertEncodeBitString *pBitString = NULL;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
BYTE KeyUsage = 0;
|
|
BSTR strBitString = NULL;
|
|
BSTR strKeyUsage = NULL;
|
|
BSTR strValue = NULL;
|
|
|
|
strKeyUsage = SysAllocString(k_wszKeyUsage);
|
|
if (NULL == strKeyUsage)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
hr = pServer->GetRequestAttribute(strKeyUsage, &strValue);
|
|
_JumpIfErrorStr(
|
|
hr,
|
|
error,
|
|
CERTSRV_E_PROPERTY_EMPTY == hr?
|
|
"MISSING ATTRIBUTE -- GetRequestAttribute" :
|
|
"GetRequestAttribute",
|
|
k_wszKeyUsage);
|
|
|
|
if (0 == wcscmp(strValue, k_wszUsageSealing))
|
|
{
|
|
KeyUsage = CERT_KEY_ENCIPHERMENT_KEY_USAGE;
|
|
}
|
|
else
|
|
if (0 == wcscmp(strValue, k_wszUsageSigning))
|
|
{
|
|
KeyUsage = CERT_DIGITAL_SIGNATURE_KEY_USAGE |
|
|
CERT_NON_REPUDIATION_KEY_USAGE;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "KeyUsage");
|
|
}
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_CCertEncodeBitString,
|
|
NULL, // pUnkOuter
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICertEncodeBitString,
|
|
(VOID **) &pBitString);
|
|
_JumpIfError(hr, error, "CoCreateInstance");
|
|
|
|
if (!ceConvertWszToBstr(
|
|
&strBitString,
|
|
(WCHAR const *) &KeyUsage,
|
|
sizeof(KeyUsage)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ceConvertWszToBstr");
|
|
}
|
|
|
|
hr = pBitString->Encode(
|
|
sizeof(KeyUsage) * 8,
|
|
strBitString,
|
|
&strExtension);
|
|
_JumpIfError(hr, error, "Encode");
|
|
|
|
if (!ceConvertWszToBstr(&strName, TEXT(szOID_KEY_USAGE), -1))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ceConvertWszToBstr");
|
|
}
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
EXTENSION_CRITICAL_FLAG,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension");
|
|
|
|
error:
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
if (NULL != strBitString)
|
|
{
|
|
SysFreeString(strBitString);
|
|
}
|
|
if (NULL != strKeyUsage)
|
|
{
|
|
SysFreeString(strKeyUsage);
|
|
}
|
|
if (NULL != strValue)
|
|
{
|
|
SysFreeString(strValue);
|
|
}
|
|
if (NULL != pBitString)
|
|
{
|
|
pBitString->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::_AddEnhancedKeyUsageExtension
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CCertPolicyExchange::_AddEnhancedKeyUsageExtension(
|
|
IN ICertServerPolicy *pServer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR strName = NULL;
|
|
BSTR strExtension = NULL;
|
|
VARIANT varExtension;
|
|
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
CERT_ENHKEY_USAGE ceu;
|
|
LPSTR pszEnhUsage = szOID_PKIX_KP_EMAIL_PROTECTION;
|
|
|
|
ceu.cUsageIdentifier = 1;
|
|
ceu.rgpszUsageIdentifier = &pszEnhUsage; // array of pszObjId
|
|
|
|
if (!ceEncodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ENHANCED_KEY_USAGE,
|
|
&ceu,
|
|
0,
|
|
FALSE,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
{
|
|
hr = GetLastError();
|
|
_JumpError(hr, error, "ceEncodeObject");
|
|
}
|
|
|
|
if (!ceConvertWszToBstr(
|
|
&strExtension,
|
|
(WCHAR const *) pbEncoded,
|
|
cbEncoded))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ceConvertWszToBstr");
|
|
}
|
|
|
|
if (!ceConvertWszToBstr(&strName, TEXT(szOID_ENHANCED_KEY_USAGE), -1))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "ceConvertWszToBstr");
|
|
}
|
|
varExtension.vt = VT_BSTR;
|
|
varExtension.bstrVal = strExtension;
|
|
hr = pServer->SetCertificateExtension(
|
|
strName,
|
|
PROPTYPE_BINARY,
|
|
0,
|
|
&varExtension);
|
|
_JumpIfError(hr, error, "SetCertificateExtension");
|
|
|
|
error:
|
|
if (NULL != pbEncoded)
|
|
{
|
|
LocalFree(pbEncoded);
|
|
}
|
|
if (NULL != strName)
|
|
{
|
|
SysFreeString(strName);
|
|
}
|
|
if (NULL != strExtension)
|
|
{
|
|
SysFreeString(strExtension);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::VerifyRequest
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CCertPolicyExchange::VerifyRequest(
|
|
/* [in] */ BSTR const strConfig,
|
|
/* [in] */ LONG Context,
|
|
/* [in] */ LONG bNewRequest,
|
|
/* [in] */ LONG Flags,
|
|
/* [out, retval] */ LONG __RPC_FAR *pDisposition)
|
|
{
|
|
HRESULT hr;
|
|
ICertServerPolicy *pServer = NULL;
|
|
|
|
hr = GetServerCallbackInterface(&pServer, Context);
|
|
_JumpIfError(hr, error, "GetServerCallbackInterface");
|
|
|
|
if (fDebug)
|
|
{
|
|
hr = EnumerateAttributes(pServer);
|
|
_JumpIfError(hr, error, "EnumerateAttributes");
|
|
|
|
hr = EnumerateExtensions(pServer);
|
|
_JumpIfError(hr, error, "EnumerateExtensions");
|
|
}
|
|
hr = _AddIssuerAltName2Extension(pServer);
|
|
_JumpIfError(hr, error, "_AddIssuerAltName2Extension");
|
|
|
|
// also handles 'special' KMS request
|
|
|
|
hr = _AddSubjectAltName2Extension(pServer);
|
|
_JumpIfError(hr, error, "_AddSubjectAltName2Extension");
|
|
|
|
hr = _AddBasicConstraintsExtension(pServer);
|
|
_JumpIfError(hr, error, "_AddBasicConstraintsExtension");
|
|
|
|
hr = _AddRevocationExtension(pServer);
|
|
_JumpIfError(hr, error, "_AddRevocationExtension");
|
|
|
|
hr = _AddAuthorityInfoAccessExtension(pServer);
|
|
_JumpIfError(hr, error, "_AddAuthorityInfoAccessExtension");
|
|
|
|
hr = _AddKeyUsageExtension(pServer);
|
|
_JumpIfError(hr, error, "_AddKeyUsageExtension");
|
|
|
|
hr = _AddEnhancedKeyUsageExtension(pServer);
|
|
_JumpIfError(hr, error, "_AddEnhancedKeyUsageExtension");
|
|
|
|
if (fDebug)
|
|
{
|
|
hr = EnumerateExtensions(pServer);
|
|
_JumpIfError(hr, error, "EnumerateExtensions");
|
|
}
|
|
hr = CheckRequestProperties(pServer);
|
|
_JumpIfError(hr, error, "_AddRevocationExtension");
|
|
|
|
error:
|
|
*pDisposition = S_OK == hr? VR_INSTANT_OK : VR_INSTANT_BAD;
|
|
if (NULL != pServer)
|
|
{
|
|
pServer->Release();
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::GetDescription
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CCertPolicyExchange::GetDescription(
|
|
/* [out, retval] */ BSTR __RPC_FAR *pstrDescription)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*pstrDescription = SysAllocString(g_wszDescription);
|
|
if (NULL == *pstrDescription)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "SysAllocString");
|
|
}
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::ShutDown
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CCertPolicyExchange::ShutDown(VOID)
|
|
{
|
|
return(S_OK);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
// CCertPolicyExchange::GetManageModule
|
|
//
|
|
// Returns S_OK on success.
|
|
//+--------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CCertPolicyExchange::GetManageModule(
|
|
/* [out, retval] */ ICertManageModule **ppManageModule)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*ppManageModule = NULL;
|
|
hr = CoCreateInstance(
|
|
CLSID_CCertManagePolicyModuleExchange,
|
|
NULL, // pUnkOuter
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICertManageModule,
|
|
(VOID **) ppManageModule);
|
|
_JumpIfError(hr, error, "CoCreateInstance");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CCertPolicyExchange::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
static const IID *arr[] =
|
|
{
|
|
&IID_ICertPolicy,
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i], riid))
|
|
{
|
|
return(S_OK);
|
|
}
|
|
}
|
|
return(S_FALSE);
|
|
}
|