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.
1607 lines
39 KiB
1607 lines
39 KiB
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: prop.cpp
|
|
//
|
|
// Contents: Cert Server Property interface implementation
|
|
//
|
|
// History: 31-Jul-96 vich created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include "csprop.h"
|
|
#include "cscom.h"
|
|
#include "csdisp.h"
|
|
#include "com.h"
|
|
#include "certlog.h"
|
|
#include "certsrvd.h"
|
|
#include "dbtable.h"
|
|
#include "elog.h"
|
|
|
|
#define __dwFILE__ __dwFILE_CERTSRV_PROP_CPP__
|
|
|
|
|
|
#ifndef DBG_PROP
|
|
# define DBG_PROP 0
|
|
#endif
|
|
|
|
|
|
HRESULT
|
|
PropSetRequestTimeProperty(
|
|
IN ICertDBRow *prow,
|
|
IN WCHAR const *pwszProp)
|
|
{
|
|
HRESULT hr;
|
|
SYSTEMTIME st;
|
|
FILETIME ft;
|
|
|
|
GetSystemTime(&st);
|
|
if (!SystemTimeToFileTime(&st, &ft))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "SystemTimeToFileTime");
|
|
}
|
|
hr = prow->SetProperty(
|
|
pwszProp,
|
|
PROPTYPE_DATE | PROPCALLER_SERVER | PROPTABLE_REQUEST,
|
|
sizeof(ft),
|
|
(BYTE *) &ft);
|
|
_JumpIfError(hr, error, "SetProperty");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
PropParseRequest(
|
|
IN ICertDBRow *prow,
|
|
IN DWORD dwFlags,
|
|
IN DWORD cbRequest,
|
|
IN BYTE const *pbRequest,
|
|
IN OUT CERTSRV_RESULT_CONTEXT *pResult)
|
|
{
|
|
HRESULT hr;
|
|
|
|
pResult->dwFlagsTop = dwFlags;
|
|
hr = PKCSParseRequest(
|
|
dwFlags,
|
|
prow,
|
|
cbRequest,
|
|
pbRequest,
|
|
NULL,
|
|
NULL,
|
|
pResult);
|
|
_JumpIfError(hr, error, "PKCSParseRequest");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
propVerifyDateRange(
|
|
IN ICertDBRow *prow,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszPropertyName,
|
|
IN FILETIME const *pft)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbProp;
|
|
FILETIME ftNotBefore;
|
|
FILETIME ftNotAfter;
|
|
|
|
hr = E_INVALIDARG;
|
|
CSASSERT((PROPTYPE_MASK & Flags) == PROPTYPE_DATE);
|
|
|
|
if ((PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE)
|
|
{
|
|
_JumpError(hr, error, "Flags: Invalid table");
|
|
}
|
|
if (0 != mylstrcmpiS(pwszPropertyName, g_wszPropCertificateNotBeforeDate) &&
|
|
0 != mylstrcmpiS(pwszPropertyName, g_wszPropCertificateNotAfterDate))
|
|
{
|
|
_JumpError(hr, error, "pwszPropertyName: Invalid date property");
|
|
}
|
|
|
|
cbProp = sizeof(ftNotBefore);
|
|
hr = prow->GetProperty(
|
|
g_wszPropCertificateNotBeforeDate,
|
|
Flags,
|
|
NULL,
|
|
&cbProp,
|
|
(BYTE *) &ftNotBefore);
|
|
_JumpIfError(hr, error, "GetProperty");
|
|
|
|
cbProp = sizeof(ftNotAfter);
|
|
hr = prow->GetProperty(
|
|
g_wszPropCertificateNotAfterDate,
|
|
Flags,
|
|
NULL,
|
|
&cbProp,
|
|
(BYTE *) &ftNotAfter);
|
|
_JumpIfError(hr, error, "GetProperty");
|
|
|
|
if (0 > CompareFileTime(pft, &ftNotBefore) ||
|
|
0 < CompareFileTime(pft, &ftNotAfter))
|
|
{
|
|
CERTSRVDBGPRINTTIME("Old Not Before", &ftNotBefore);
|
|
CERTSRVDBGPRINTTIME(" Old Not After", &ftNotAfter);
|
|
CERTSRVDBGPRINTTIME(
|
|
0 == mylstrcmpiS(
|
|
pwszPropertyName,
|
|
g_wszPropCertificateNotBeforeDate)?
|
|
"New Not Before" : " New Not After",
|
|
pft);
|
|
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr(hr, error, "FILETIME out of range", pwszPropertyName);
|
|
}
|
|
|
|
error:
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
// Returns TRUE if names match!
|
|
|
|
#define PROPNAMEMATCH(cwcNameVariable, pwszNameVariable, wszNameLiteral) \
|
|
(WSZARRAYSIZE((wszNameLiteral)) == (cwcNameVariable) && \
|
|
0 == LSTRCMPIS((pwszNameVariable), (wszNameLiteral)))
|
|
|
|
HRESULT
|
|
propGetSystemProperty(
|
|
IN WCHAR const *pwszPropName,
|
|
IN DWORD Flags,
|
|
IN LONG Context,
|
|
OUT BOOL *pfSystemProperty,
|
|
OUT VARIANT *pvarPropertyValue)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE *pbFree = NULL;
|
|
DWORD cwcPropName;
|
|
DWORD cwcBaseName;
|
|
WCHAR wszBaseName[32];
|
|
WCHAR const *pwszIndex;
|
|
WCHAR wszRenewalSuffix[cwcFILENAMESUFFIXMAX];
|
|
DWORD iCert = MAXDWORD;
|
|
DWORD iCRL;
|
|
DWORD iDummy;
|
|
DWORD State;
|
|
DWORD PropType;
|
|
DWORD cbCopy;
|
|
DWORD cbOut;
|
|
BYTE const *pbOut = NULL; // PROPTYPE_LONG or PROPTYPE_BINARY
|
|
WCHAR const *pwszOut = NULL; // PROPTYPE_STRING
|
|
CRL_CONTEXT const *pCRL = NULL;
|
|
CERTSRV_COM_CONTEXT *pComContext;
|
|
BOOL fT;
|
|
|
|
*pfSystemProperty = FALSE;
|
|
wszRenewalSuffix[0] = L'\0';
|
|
cbOut = 0;
|
|
|
|
// Allow "PropName.#"
|
|
// Copy the base part of the property name to a local buffer, so we can do
|
|
// case ignore string compares.
|
|
|
|
cwcPropName = wcslen(pwszPropName);
|
|
|
|
cwcBaseName = wcscspn(pwszPropName, L".");
|
|
if (ARRAYSIZE(wszBaseName) - 1 < cwcBaseName)
|
|
{
|
|
cwcBaseName = ARRAYSIZE(wszBaseName) - 1;
|
|
}
|
|
|
|
CopyMemory(wszBaseName, pwszPropName, cwcBaseName * sizeof(WCHAR));
|
|
wszBaseName[cwcBaseName] = L'\0';
|
|
|
|
pwszIndex = &pwszPropName[cwcBaseName];
|
|
if (L'.' == *pwszIndex)
|
|
{
|
|
pwszIndex++;
|
|
iCert = _wtol(pwszIndex);
|
|
for ( ; L'\0' != *pwszIndex; pwszIndex++)
|
|
{
|
|
if (!iswdigit(*pwszIndex))
|
|
{
|
|
CSASSERT(S_OK == hr); // Not a system property, return S_OK
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Assume property type is a long:
|
|
|
|
PropType = PROPTYPE_LONG;
|
|
*pfSystemProperty = TRUE;
|
|
|
|
if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCATYPE))
|
|
{
|
|
pbOut = (BYTE const *) &g_CAType;
|
|
cbOut = sizeof(g_CAType);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPUSEDS))
|
|
{
|
|
pbOut = (BYTE const *) &g_fUseDS;
|
|
cbOut = sizeof(g_fUseDS);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPDELTACRLSDISABLED))
|
|
{
|
|
pbOut = (BYTE const *) &g_fDeltaCRLPublishDisabled;
|
|
cbOut = sizeof(g_fDeltaCRLPublishDisabled);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSERVERUPGRADED))
|
|
{
|
|
pbOut = (BYTE const *) &g_fServerUpgraded;
|
|
cbOut = sizeof(g_fServerUpgraded);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPLOGLEVEL))
|
|
{
|
|
pbOut = (BYTE const *) &g_dwLogLevel;
|
|
cbOut = sizeof(g_dwLogLevel);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSESSIONCOUNT))
|
|
{
|
|
pbOut = (BYTE const *) &g_dwSessionCount;
|
|
cbOut = sizeof(g_dwSessionCount);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPREQUESTERTOKEN))
|
|
{
|
|
hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
|
|
_JumpIfError(hr, error, "ComGetClientInfo");
|
|
|
|
if (NULL == pComContext->hAccessToken ||
|
|
INVALID_HANDLE_VALUE == pComContext->hAccessToken)
|
|
{
|
|
hr = CERTSRV_E_PROPERTY_EMPTY;
|
|
_JumpError(hr, error, "ComGetClientInfo(bad hAccessToken)");
|
|
}
|
|
pbOut = (BYTE const *) &pComContext->hAccessToken;
|
|
cbOut = sizeof(pComContext->hAccessToken);
|
|
PropType = PROPTYPE_BINARY;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPREQUESTERCAACCESS))
|
|
{
|
|
hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
|
|
_JumpIfError(hr, error, "ComGetClientInfo");
|
|
|
|
if (0 == (CCCF_INREQUESTGROUPSET & pComContext->dwFlags))
|
|
{
|
|
hr = CERTSRV_E_PROPERTY_EMPTY;
|
|
_JumpError(hr, error, "ComGetClientInfo(fInRequestGroup not set)");
|
|
}
|
|
fT = (CCCF_INREQUESTGROUP & pComContext->dwFlags)? TRUE : FALSE;
|
|
pbOut = (BYTE const *) &fT;
|
|
cbOut = sizeof(fT);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPKEYARCHIVED))
|
|
{
|
|
hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
|
|
_JumpIfError(hr, error, "ComGetClientInfo");
|
|
|
|
if (0 == (CCCF_KEYARCHIVEDSET & pComContext->dwFlags))
|
|
{
|
|
hr = CoreSetArchivedKey(pComContext);
|
|
_JumpIfError(hr, error, "CoreSetArchivedKey");
|
|
|
|
CSASSERT(CCCF_KEYARCHIVEDSET & pComContext->dwFlags);
|
|
}
|
|
fT = (CCCF_KEYARCHIVED & pComContext->dwFlags)? TRUE : FALSE;
|
|
pbOut = (BYTE const *) &fT;
|
|
cbOut = sizeof(fT);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPUSERDN))
|
|
{
|
|
hr = ComGetClientInfo(Context, MAXDWORD, &pComContext);
|
|
_JumpIfError(hr, error, "ComGetClientInfo");
|
|
|
|
if (NULL == pComContext->pwszUserDN)
|
|
{
|
|
if (!g_fUseDS)
|
|
{
|
|
hr = CERTSRV_E_PROPERTY_EMPTY;
|
|
_JumpError(hr, error, "ComGetClientInfo(bad pwszUserDN)");
|
|
}
|
|
hr = CoreSetComContextUserDN(
|
|
pComContext->RequestId,
|
|
Context,
|
|
MAXDWORD,
|
|
&pwszOut);
|
|
_JumpIfError(hr, error, "CoreSetComContextUserDN");
|
|
}
|
|
pwszOut = pComContext->pwszUserDN;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCERTCOUNT))
|
|
{
|
|
pbOut = (BYTE const *) &g_cCACerts;
|
|
cbOut = sizeof(g_cCACerts);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSANITIZEDCANAME))
|
|
{
|
|
pwszOut = g_wszSanitizedName;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPSANITIZEDSHORTNAME))
|
|
{
|
|
pwszOut = g_pwszSanitizedDSName;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPMACHINEDNSNAME))
|
|
{
|
|
pwszOut = g_pwszServerName;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPCONFIGDN))
|
|
{
|
|
pwszOut = g_strConfigDN;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPDOMAINDN))
|
|
{
|
|
pwszOut = g_strDomainDN;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcPropName, pwszPropName, wszPROPMODULEREGLOC))
|
|
{
|
|
// future: cache storage location once it is built
|
|
|
|
WCHAR *pwszQuasiPath;
|
|
DWORD cwcQuasiPath;
|
|
WCHAR const *pwszPrefix;
|
|
MarshalInterface *pIF;
|
|
|
|
if ((PROPCALLER_MASK & Flags) == PROPCALLER_POLICY)
|
|
{
|
|
pIF = &g_miPolicy;
|
|
cwcQuasiPath = ARRAYSIZE(L"Policy\\"); // includes L'\0'
|
|
pwszPrefix = L"Policy\\";
|
|
}
|
|
else
|
|
{
|
|
hr = ExitGetActiveModule(Context, &pIF);
|
|
_JumpIfError(hr, error, "ExitGetActiveModule");
|
|
cwcQuasiPath = ARRAYSIZE(L"Exit\\"); // includes L'\0'
|
|
pwszPrefix = L"Exit\\";
|
|
}
|
|
|
|
cwcQuasiPath += wcslen(pIF->GetProgID());
|
|
pwszQuasiPath = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
cwcQuasiPath * sizeof(WCHAR));
|
|
if (NULL == pwszQuasiPath)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(pwszQuasiPath, pwszPrefix);
|
|
wcscat(pwszQuasiPath, pIF->GetProgID());
|
|
|
|
hr = myRegOpenRelativeKey(
|
|
pIF->GetConfig(),
|
|
pwszQuasiPath,
|
|
RORKF_FULLPATH | RORKF_CREATESUBKEYS,
|
|
(WCHAR **) &pwszOut,
|
|
NULL,
|
|
NULL);
|
|
LocalFree(pwszQuasiPath);
|
|
_JumpIfError(hr, error, "myRegOpenRelativeKey");
|
|
|
|
CSASSERT(NULL != pwszOut);
|
|
pbFree = (BYTE *) pwszOut;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWCACERTIFICATE))
|
|
{
|
|
hr = PKCSGetCACert(
|
|
CR_PROP_CASIGCERT,
|
|
iCert,
|
|
const_cast<BYTE **>(&pbOut),
|
|
&cbOut); // not alloc'd
|
|
_JumpIfError(hr, error, "PKCSGetCACert");
|
|
|
|
PropType = PROPTYPE_BINARY;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWCRL))
|
|
{
|
|
hr = CRLGetCRL(iCert, FALSE, &pCRL, NULL);
|
|
_JumpIfError(hr, error, "CRLGetCRL");
|
|
|
|
cbOut = pCRL->cbCrlEncoded;
|
|
pbOut = pCRL->pbCrlEncoded;
|
|
PropType = PROPTYPE_BINARY;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPRAWDELTACRL))
|
|
{
|
|
hr = CRLGetCRL(iCert, TRUE, &pCRL, NULL);
|
|
_JumpIfError2(
|
|
hr,
|
|
error,
|
|
"CRLGetCRL",
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
cbOut = pCRL->cbCrlEncoded;
|
|
pbOut = pCRL->pbCrlEncoded;
|
|
PropType = PROPTYPE_BINARY;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCERTSTATE))
|
|
{
|
|
hr = PKCSMapCertIndex(iCert, &iCert, &State);
|
|
_JumpIfError(hr, error, "PKCSMapCertIndex");
|
|
|
|
pbOut = (BYTE *) &State;
|
|
cbOut = sizeof(State);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCERTSUFFIX))
|
|
{
|
|
hr = PKCSMapCertIndex(iCert, &iCert, &State);
|
|
_JumpIfError(hr, error, "PKCSMapCertIndex");
|
|
|
|
pwszOut = wszRenewalSuffix;
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLINDEX))
|
|
{
|
|
hr = PKCSMapCRLIndex(iCert, &iCert, &iCRL, &State);
|
|
_JumpIfError(hr, error, "PKCSMapCRLIndex");
|
|
|
|
pbOut = (BYTE *) &iCRL;
|
|
cbOut = sizeof(iCRL);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLSTATE))
|
|
{
|
|
hr = PKCSMapCRLIndex(iCert, &iCert, &iCRL, &State);
|
|
_JumpIfError(hr, error, "PKCSMapCRLIndex");
|
|
|
|
pbOut = (BYTE *) &State;
|
|
cbOut = sizeof(State);
|
|
}
|
|
else if (PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPCRLSUFFIX))
|
|
{
|
|
hr = PKCSMapCRLIndex(iCert, &iDummy, &iCert, &State);
|
|
_JumpIfError(hr, error, "PKCSMapCRLIndex");
|
|
|
|
pwszOut = wszRenewalSuffix;
|
|
}
|
|
else if(PROPNAMEMATCH(cwcBaseName, wszBaseName, wszPROPTEMPLATECHANGESEQUENCENUMBER))
|
|
{
|
|
pbOut = (BYTE const *) &g_cTemplateUpdateSequenceNum;
|
|
cbOut = sizeof(g_cTemplateUpdateSequenceNum);
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(S_OK == hr); // Not a system property, return S_OK
|
|
*pfSystemProperty = FALSE;
|
|
goto error;
|
|
}
|
|
|
|
CSASSERT((NULL != pbOut) ^ (NULL != pwszOut)); // exactly 1 must be set
|
|
|
|
cbCopy = cbOut;
|
|
if (NULL != pwszOut)
|
|
{
|
|
if (wszRenewalSuffix == pwszOut && 0 != iCert)
|
|
{
|
|
wsprintf(wszRenewalSuffix, L"(%u)", iCert);
|
|
}
|
|
PropType = PROPTYPE_STRING;
|
|
cbOut = wcslen(pwszOut) * sizeof(WCHAR);
|
|
cbCopy = cbOut + sizeof(WCHAR);
|
|
pbOut = (BYTE *) pwszOut;
|
|
}
|
|
|
|
if ((PROPTYPE_MASK & Flags) != PropType)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError2(hr, error, "bad PropType", hr);
|
|
}
|
|
|
|
hr = myUnmarshalVariant(
|
|
PROPMARSHAL_LOCALSTRING | Flags,
|
|
cbOut,
|
|
pbOut,
|
|
pvarPropertyValue);
|
|
_JumpIfError(hr, error, "myUnmarshalVariant");
|
|
|
|
error:
|
|
if (NULL != pCRL)
|
|
{
|
|
CertFreeCRLContext(pCRL);
|
|
}
|
|
if (NULL != pbFree)
|
|
{
|
|
LocalFree(pbFree);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
class CComputedProperty : public ICertDBComputedColumn
|
|
{
|
|
public:
|
|
CComputedProperty();
|
|
~CComputedProperty();
|
|
|
|
// IUnknown
|
|
STDMETHODIMP QueryInterface(const IID& iid, void **ppv);
|
|
ULONG STDMETHODCALLTYPE AddRef();
|
|
ULONG STDMETHODCALLTYPE Release();
|
|
|
|
STDMETHOD(GetAlternateColumnId)(
|
|
IN DWORD ComputedColumnId,
|
|
OUT DWORD *pAlternateColumnId,
|
|
OUT DWORD *pPropType);
|
|
|
|
STDMETHOD(ComputeColumnValue)(
|
|
IN DWORD ComputedColumnId,
|
|
IN DWORD AlternateColumnId,
|
|
IN DWORD PropType,
|
|
IN DWORD cbProp,
|
|
IN BYTE const *pbProp,
|
|
OUT DWORD *pdwValue);
|
|
|
|
HRESULT SavePropertyArgument(
|
|
IN WCHAR const *pwszPropIn,
|
|
OUT WCHAR **ppwszPropOut);
|
|
|
|
private:
|
|
WCHAR *m_pwszArg;
|
|
|
|
// Reference count
|
|
long m_cRef;
|
|
};
|
|
|
|
|
|
CComputedProperty::CComputedProperty()
|
|
{
|
|
m_pwszArg = NULL;
|
|
m_cRef = 1;
|
|
}
|
|
|
|
|
|
CComputedProperty::~CComputedProperty()
|
|
{
|
|
if (NULL != m_pwszArg)
|
|
{
|
|
LocalFree(m_pwszArg);
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CComputedProperty::QueryInterface(
|
|
const IID& iid,
|
|
void **ppv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == ppv)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
if (iid == IID_IUnknown)
|
|
{
|
|
*ppv = static_cast<ICertDBComputedColumn *>(this);
|
|
}
|
|
else if (iid == IID_ICertDBComputedColumn)
|
|
{
|
|
*ppv = static_cast<ICertDBComputedColumn *>(this);
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
hr = E_NOINTERFACE;
|
|
_JumpError(hr, error, "IID");
|
|
}
|
|
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
CComputedProperty::AddRef()
|
|
{
|
|
return(InterlockedIncrement(&m_cRef));
|
|
}
|
|
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
CComputedProperty::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement(&m_cRef);
|
|
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
return(cRef);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CComputedProperty::ComputeColumnValue(
|
|
IN DWORD ComputedColumnId,
|
|
IN DWORD AlternateColumnId,
|
|
IN DWORD PropType,
|
|
IN DWORD cbProp,
|
|
IN BYTE const *pbProp,
|
|
OUT DWORD *pdwValue)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR const *pwszRequesterName;
|
|
|
|
*pdwValue = 0;
|
|
if (NULL == m_pwszArg)
|
|
{
|
|
hr = CERTSRV_E_PROPERTY_EMPTY;
|
|
_JumpError(hr, error, "m_pwszArg NULL");
|
|
}
|
|
if ((DTI_REQUESTTABLE | DTR_OFFICER) != ComputedColumnId ||
|
|
(DTI_REQUESTTABLE | DTR_REQUESTERNAME) != AlternateColumnId ||
|
|
PROPTYPE_STRING != PropType ||
|
|
0 == cbProp ||
|
|
((sizeof(WCHAR) - 1) & cbProp))
|
|
{
|
|
hr = CERTSRV_E_PROPERTY_EMPTY;
|
|
_JumpError(hr, error, "ComputedColumnId");
|
|
}
|
|
pwszRequesterName = (WCHAR const *) pbProp;
|
|
CSASSERT(L'\0' == pwszRequesterName[cbProp / sizeof(WCHAR)]);
|
|
CSASSERT(sizeof(WCHAR) * wcslen(pwszRequesterName) == cbProp);
|
|
|
|
hr = CheckOfficerRightsFromOfficerName(m_pwszArg, pwszRequesterName);
|
|
if (S_OK == hr)
|
|
{
|
|
*pdwValue = 1;
|
|
}
|
|
else if (CERTSRV_E_RESTRICTEDOFFICER == hr)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
_JumpIfError(hr, error, "CheckOfficerRightsFromOfficerName");
|
|
|
|
error:
|
|
DBGPRINT((
|
|
DBG_SS_CERTSRV,
|
|
"ComputeColumnValue(%ws) = %u hr=%x\n",
|
|
(WCHAR const *) pbProp,
|
|
*pdwValue,
|
|
hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CComputedProperty::SavePropertyArgument(
|
|
IN WCHAR const *pwszPropIn,
|
|
OUT WCHAR **ppwszPropOut)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszT;
|
|
|
|
CSASSERT(NULL == m_pwszArg);
|
|
hr = myDupString(pwszPropIn, ppwszPropOut);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
|
|
pwszT = wcschr(*ppwszPropOut, wcLPAREN);
|
|
if (NULL != pwszT)
|
|
{
|
|
WCHAR *pwsz2 = pwszT;
|
|
|
|
while (--pwsz2 >= *ppwszPropOut && L' ' == *pwsz2)
|
|
{
|
|
*pwsz2 = L'\0';
|
|
}
|
|
|
|
*pwszT++ = L'\0';
|
|
while (L' ' == *pwszT)
|
|
{
|
|
pwszT++;
|
|
}
|
|
hr = myDupString(pwszT, &m_pwszArg);
|
|
_JumpIfError(hr, error, "myDupString");
|
|
|
|
pwszT = wcschr(m_pwszArg, wcRPAREN);
|
|
if (NULL == pwszT)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr(hr, error, "SavePropertyArgument", pwszPropIn);
|
|
}
|
|
do
|
|
{
|
|
*pwszT-- = L'\0';
|
|
} while (pwszT >= m_pwszArg && L' ' == *pwszT);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CComputedProperty::GetAlternateColumnId(
|
|
IN DWORD ComputedColumnId,
|
|
OUT DWORD *pAlternateColumnId,
|
|
OUT DWORD *pPropType)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*pAlternateColumnId = 0;
|
|
if ((DTI_REQUESTTABLE | DTR_OFFICER) != ComputedColumnId)
|
|
{
|
|
hr = CERTSRV_E_PROPERTY_EMPTY;
|
|
_JumpError(hr, error, "ComputedColumnId");
|
|
}
|
|
*pAlternateColumnId = DTI_REQUESTTABLE | DTR_REQUESTERNAME;
|
|
*pPropType = PROPTYPE_STRING;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
FNCIGETPROPERTY PropCIGetProperty;
|
|
|
|
HRESULT
|
|
PropCIGetProperty(
|
|
IN LONG Context,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszPropertyName,
|
|
OUT VARIANT *pvarPropertyValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD RequestId;
|
|
DWORD cbprop;
|
|
BYTE *pbprop = NULL;
|
|
ICertDBRow *prow = NULL;
|
|
BYTE rgbFastBuf[128]; // many properties are small (128)
|
|
BOOL fSystemProperty;
|
|
CComputedProperty ccp;
|
|
WCHAR *pwszPropAlloc = NULL;
|
|
|
|
if (NULL != pvarPropertyValue)
|
|
{
|
|
VariantInit(pvarPropertyValue);
|
|
}
|
|
if (NULL == pwszPropertyName || NULL == pvarPropertyValue)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
|
|
hr = E_INVALIDARG;
|
|
if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY &&
|
|
(PROPCALLER_MASK & Flags) != PROPCALLER_EXIT &&
|
|
(PROPCALLER_MASK & Flags) != PROPCALLER_SERVER)
|
|
{
|
|
_JumpError(hr, error, "Flags: Invalid caller");
|
|
}
|
|
|
|
if ((PROPTABLE_MASK & Flags) != PROPTABLE_REQUEST &&
|
|
(PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE &&
|
|
(PROPTABLE_MASK & Flags) != PROPTABLE_ATTRIBUTE)
|
|
{
|
|
_JumpError(hr, error, "Flags: Invalid table");
|
|
}
|
|
|
|
fSystemProperty = FALSE;
|
|
if ((PROPTABLE_MASK & Flags) == PROPTABLE_CERTIFICATE)
|
|
{
|
|
hr = ComVerifyRequestContext(TRUE, Flags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
// Check for special, hard-coded properties first
|
|
|
|
hr = propGetSystemProperty(
|
|
pwszPropertyName,
|
|
Flags,
|
|
Context,
|
|
&fSystemProperty,
|
|
pvarPropertyValue);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"propGetSystemProperty",
|
|
pwszPropertyName,
|
|
E_INVALIDARG);
|
|
}
|
|
|
|
if (!fSystemProperty)
|
|
{
|
|
DWORD VerifyFlags = Flags;
|
|
|
|
if (((PROPCALLER_MASK | PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
|
|
(PROPCALLER_SERVER | PROPTABLE_REQUEST | PROPTYPE_LONG) &&
|
|
0 == LSTRCMPIS(pwszPropertyName, wszPROPREQUESTREQUESTID))
|
|
{
|
|
VerifyFlags = PROPCALLER_EXIT | (~PROPCALLER_MASK & VerifyFlags);
|
|
}
|
|
hr = ComVerifyRequestContext(FALSE, VerifyFlags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
pbprop = rgbFastBuf;
|
|
cbprop = sizeof(rgbFastBuf);
|
|
|
|
// PROPCALLER_SERVER indicates this call is only for Context validation
|
|
// -- return a zero RequestId. This keeps CRL publication exit module
|
|
// notification from failing.
|
|
|
|
if (0 == RequestId &&
|
|
((PROPCALLER_MASK | PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
|
|
(PROPCALLER_SERVER | PROPTABLE_REQUEST | PROPTYPE_LONG) &&
|
|
0 == LSTRCMPIS(pwszPropertyName, wszPROPREQUESTREQUESTID))
|
|
{
|
|
*(DWORD *) pbprop = 0;
|
|
cbprop = sizeof(DWORD);
|
|
}
|
|
else
|
|
{
|
|
WCHAR const *pwszPropT;
|
|
|
|
if (PROPTYPE_STRING == (PROPTYPE_MASK & Flags) &&
|
|
PROPTABLE_CERTIFICATE == (PROPTABLE_MASK & Flags))
|
|
{
|
|
BOOL fSubjectDot;
|
|
|
|
hr = PKCSVerifySubjectRDN(
|
|
NULL, // prow
|
|
&pwszPropertyName,
|
|
NULL, // pwszPropertyValue
|
|
&fSubjectDot);
|
|
_JumpIfError(hr, error, "PKCSVerifySubjectRDN");
|
|
}
|
|
hr = g_pCertDB->OpenRow(
|
|
PROPOPEN_READONLY | PROPTABLE_REQCERT,
|
|
RequestId,
|
|
NULL,
|
|
&prow);
|
|
_JumpIfError(hr, error, "OpenRow");
|
|
|
|
if ((PROPTABLE_MASK & Flags) == PROPTABLE_REQUEST ||
|
|
(PROPTABLE_MASK & Flags) == PROPTABLE_CERTIFICATE)
|
|
{
|
|
hr = ccp.SavePropertyArgument(pwszPropertyName, &pwszPropAlloc);
|
|
_JumpIfError(hr, error, "SavePropertyArgument");
|
|
|
|
pwszPropT = pwszPropAlloc;
|
|
}
|
|
else
|
|
{
|
|
pwszPropT = pwszPropertyName;
|
|
}
|
|
|
|
hr = prow->GetProperty(
|
|
pwszPropT,
|
|
Flags,
|
|
g_OfficerRightsSD.IsEnabled()? &ccp : NULL,
|
|
&cbprop,
|
|
pbprop);
|
|
if (S_OK != hr)
|
|
{
|
|
if (HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW) != hr)
|
|
{
|
|
_JumpIfError3(
|
|
hr,
|
|
error,
|
|
"GetProperty",
|
|
CERTSRV_E_PROPERTY_EMPTY,
|
|
E_INVALIDARG);
|
|
}
|
|
|
|
CSASSERT(ARRAYSIZE(rgbFastBuf) < cbprop);
|
|
|
|
DBGPRINT((
|
|
DBG_SS_CERTSRVI,
|
|
"FastBuf miss: PropCIGetProperty - pbprop %i bytes\n",
|
|
cbprop));
|
|
|
|
pbprop = (BYTE *) LocalAlloc(LMEM_FIXED, cbprop);
|
|
if (NULL == pbprop)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
hr = prow->GetProperty(
|
|
pwszPropT,
|
|
Flags,
|
|
g_OfficerRightsSD.IsEnabled()? &ccp : NULL,
|
|
&cbprop,
|
|
pbprop);
|
|
_JumpIfError(hr, error, "GetProperty");
|
|
}
|
|
} // property is in-hand
|
|
|
|
if ((((PROPTABLE_MASK | PROPTYPE_MASK) & Flags) ==
|
|
(PROPTABLE_REQUEST | PROPTYPE_BINARY)) &&
|
|
(0 == LSTRCMPIS(pwszPropertyName, wszPROPREQUESTRAWARCHIVEDKEY) ||
|
|
0 == LSTRCMPIS(pwszPropertyName,
|
|
wszPROPREQUESTDOT wszPROPREQUESTRAWARCHIVEDKEY)))
|
|
{
|
|
*pbprop = 0;
|
|
cbprop = sizeof(*pbprop);
|
|
}
|
|
|
|
hr = myUnmarshalVariant(
|
|
PROPMARSHAL_LOCALSTRING | Flags,
|
|
cbprop,
|
|
pbprop,
|
|
pvarPropertyValue);
|
|
_JumpIfError(hr, error, "myUnmarshalVariant");
|
|
}
|
|
|
|
error:
|
|
if (NULL != prow)
|
|
{
|
|
prow->Release();
|
|
}
|
|
if (NULL != pbprop && pbprop != rgbFastBuf)
|
|
{
|
|
LocalFree(pbprop);
|
|
}
|
|
if (NULL != pwszPropAlloc)
|
|
{
|
|
LocalFree(pwszPropAlloc);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
propSetSystemProperty(
|
|
IN WCHAR const *pwszPropName,
|
|
IN DWORD Flags,
|
|
OUT BOOL *pfSystemProperty,
|
|
IN VARIANT const *pvarPropertyValue)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD LogLevel = MAXDWORD;
|
|
DWORD infotype = EVENTLOG_INFORMATION_TYPE;
|
|
DWORD LogMsg = MSG_POLICY_LOG_INFORMATION;
|
|
WCHAR *pwsz = NULL;
|
|
DWORD cwcMax;
|
|
|
|
*pfSystemProperty = FALSE;
|
|
cwcMax = 1;
|
|
|
|
if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGTERSE))
|
|
{
|
|
LogLevel = CERTLOG_TERSE;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGERROR))
|
|
{
|
|
LogLevel = CERTLOG_ERROR;
|
|
infotype = EVENTLOG_ERROR_TYPE;
|
|
LogMsg = MSG_POLICY_LOG_ERROR;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGWARNING))
|
|
{
|
|
LogLevel = CERTLOG_WARNING;
|
|
infotype = EVENTLOG_WARNING_TYPE;
|
|
LogMsg = MSG_POLICY_LOG_WARNING;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszPropName, wszPROPEVENTLOGVERBOSE))
|
|
{
|
|
LogLevel = CERTLOG_VERBOSE;
|
|
}
|
|
else
|
|
if (0 == LSTRCMPIS(pwszPropName, wszPROPDCNAME))
|
|
{
|
|
pwsz = g_wszPolicyDCName;
|
|
cwcMax = g_cwcPolicyDCName;
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(S_OK == hr); // Not a system property, return S_OK
|
|
goto error;
|
|
}
|
|
*pfSystemProperty = TRUE;
|
|
|
|
if (PROPTYPE_STRING != (PROPTYPE_MASK & Flags) ||
|
|
VT_BSTR != pvarPropertyValue->vt ||
|
|
NULL == pvarPropertyValue->bstrVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr(hr, error, "string property value/type", pwszPropName);
|
|
}
|
|
|
|
if (NULL != pwsz)
|
|
{
|
|
// Terminate first to avoid problems with multi-threaded access.
|
|
|
|
pwsz[cwcMax - 1] = L'\0';
|
|
wcsncpy(pwsz, pvarPropertyValue->bstrVal, cwcMax - 1);
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(MAXDWORD != LogLevel);
|
|
if (LogLevel <= g_dwLogLevel)
|
|
{
|
|
WCHAR const *apwsz[2];
|
|
WCHAR const *pwszMessage = pvarPropertyValue->bstrVal;
|
|
HRESULT hrPrefix;
|
|
|
|
if (ComParseErrorPrefix(
|
|
pvarPropertyValue->bstrVal,
|
|
&hrPrefix,
|
|
&pwszMessage))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pwszMessage = pvarPropertyValue->bstrVal;
|
|
}
|
|
apwsz[0] = g_strPolicyDescription;
|
|
apwsz[1] = pwszMessage;
|
|
|
|
hr = LogEvent(infotype, LogMsg, ARRAYSIZE(apwsz), apwsz);
|
|
_JumpIfError(hr, error, "LogEvent");
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
FNCISETPROPERTY PropCISetProperty;
|
|
|
|
HRESULT
|
|
PropCISetProperty(
|
|
IN LONG Context,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszPropertyName,
|
|
IN VARIANT const *pvarPropertyValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD RequestId;
|
|
DWORD cbprop;
|
|
BYTE *pbprop = NULL;
|
|
ICertDBRow *prow = NULL;
|
|
BOOL fSubjectDot = FALSE;
|
|
BOOL fSystemProperty;
|
|
BOOL fCommitted = FALSE;
|
|
|
|
if (NULL == pwszPropertyName || NULL == pvarPropertyValue)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
hr = E_INVALIDARG;
|
|
if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY)
|
|
{
|
|
_JumpError(hr, error, "Flags: Invalid caller");
|
|
}
|
|
if ((PROPTABLE_MASK & Flags) != PROPTABLE_CERTIFICATE)
|
|
{
|
|
_JumpError(hr, error, "Flags: Invalid table");
|
|
}
|
|
|
|
hr = ComVerifyRequestContext(TRUE, Flags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
// Check for special, hard-coded properties first
|
|
|
|
fSystemProperty = FALSE;
|
|
hr = propSetSystemProperty(
|
|
pwszPropertyName,
|
|
Flags,
|
|
&fSystemProperty,
|
|
pvarPropertyValue);
|
|
_JumpIfError(hr, error, "propSetSystemProperty");
|
|
|
|
if (!fSystemProperty)
|
|
{
|
|
hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
hr = myMarshalVariant(
|
|
pvarPropertyValue,
|
|
PROPMARSHAL_NULLBSTROK | PROPMARSHAL_LOCALSTRING | Flags,
|
|
&cbprop,
|
|
&pbprop);
|
|
_JumpIfError(hr, error, "myMarshalVariant");
|
|
|
|
hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, RequestId, NULL, &prow);
|
|
_JumpIfError(hr, error, "OpenRow");
|
|
|
|
if (PROPTYPE_DATE == (PROPTYPE_MASK & Flags))
|
|
{
|
|
hr = propVerifyDateRange(
|
|
prow,
|
|
Flags,
|
|
pwszPropertyName,
|
|
(FILETIME *) pbprop);
|
|
_JumpIfError(hr, error, "propVerifyDateRange");
|
|
}
|
|
else
|
|
if (PROPTYPE_STRING == (PROPTYPE_MASK & Flags) &&
|
|
PROPTABLE_CERTIFICATE == (PROPTABLE_MASK & Flags))
|
|
{
|
|
hr = PKCSVerifySubjectRDN(
|
|
prow,
|
|
&pwszPropertyName,
|
|
(WCHAR const *) pbprop,
|
|
&fSubjectDot);
|
|
_JumpIfError(hr, error, "PKCSVerifySubjectRDN");
|
|
}
|
|
|
|
if (NULL == pbprop && fSubjectDot)
|
|
{
|
|
hr = PKCSDeleteAllSubjectRDNs(prow, Flags);
|
|
_JumpIfError(hr, error, "PKCSDeleteAllSubjectRDNs");
|
|
}
|
|
else
|
|
{
|
|
hr = prow->SetProperty(pwszPropertyName, Flags, cbprop, pbprop);
|
|
_JumpIfError(hr, error, "SetProperty");
|
|
}
|
|
|
|
hr = prow->CommitTransaction(CDBROW_COMMIT_SOFTCOMMIT); // not critical to flush
|
|
_JumpIfError(hr, error, "CommitTransaction");
|
|
|
|
fCommitted = TRUE;
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != prow)
|
|
{
|
|
if (S_OK != hr && !fCommitted)
|
|
{
|
|
HRESULT hr2 = prow->CommitTransaction(CDBROW_COMMIT_ROLLBACK);
|
|
_PrintIfError(hr2, "CommitTransaction");
|
|
}
|
|
prow->Release();
|
|
}
|
|
if (NULL != pbprop)
|
|
{
|
|
LocalFree(pbprop);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
PropGetExtension(
|
|
IN ICertDBRow *prow,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszExtensionName,
|
|
OUT DWORD *pdwExtFlags,
|
|
OUT DWORD *pcbValue,
|
|
OUT BYTE **ppbValue) // LocalAlloc
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbprop;
|
|
BYTE *pbprop = NULL;
|
|
|
|
CSASSERT(
|
|
PROPCALLER_EXIT == (PROPCALLER_MASK & Flags) ||
|
|
PROPCALLER_POLICY == (PROPCALLER_MASK & Flags) ||
|
|
PROPCALLER_SERVER == (PROPCALLER_MASK & Flags));
|
|
|
|
CSASSERT(0 == (~(PROPMARSHAL_LOCALSTRING | PROPCALLER_MASK | PROPTYPE_MASK) & Flags));
|
|
|
|
hr = myVerifyObjId(pwszExtensionName);
|
|
_JumpIfError(hr, error, "myVerifyObjId");
|
|
|
|
cbprop = 0;
|
|
hr = prow->GetExtension(pwszExtensionName, pdwExtFlags, &cbprop, NULL);
|
|
_JumpIfError2(hr, error, "GetExtension(NULL)", CERTSRV_E_PROPERTY_EMPTY);
|
|
|
|
pbprop = (BYTE *) LocalAlloc(LMEM_FIXED, cbprop);
|
|
if (NULL == pbprop)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc(ExtValue)");
|
|
}
|
|
|
|
hr = prow->GetExtension(pwszExtensionName, pdwExtFlags, &cbprop, pbprop);
|
|
_JumpIfError(hr, error, "GetExtension");
|
|
|
|
if (PROPTYPE_BINARY == (PROPTYPE_MASK & Flags))
|
|
{
|
|
*pcbValue = cbprop;
|
|
*ppbValue = pbprop;
|
|
pbprop = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = myDecodeExtension(Flags, pbprop, cbprop, ppbValue, pcbValue);
|
|
_JumpIfError(hr, error, "myDecodeExtension");
|
|
}
|
|
|
|
error:
|
|
if (NULL != pbprop)
|
|
{
|
|
LocalFree(pbprop);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
PropSetExtension(
|
|
IN ICertDBRow *prow,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszExtensionName,
|
|
IN DWORD ExtFlags,
|
|
IN DWORD cbValue,
|
|
IN BYTE const *pbValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbprop;
|
|
BYTE *pbprop = NULL;
|
|
|
|
CSASSERT(
|
|
PROPCALLER_ADMIN == (PROPCALLER_MASK & Flags) ||
|
|
PROPCALLER_POLICY == (PROPCALLER_MASK & Flags) ||
|
|
PROPCALLER_SERVER == (PROPCALLER_MASK & Flags) ||
|
|
PROPCALLER_REQUEST == (PROPCALLER_MASK & Flags));
|
|
|
|
CSASSERT(0 == (~(PROPMARSHAL_LOCALSTRING | PROPCALLER_MASK | PROPTYPE_MASK) & Flags));
|
|
|
|
hr = myVerifyObjId(pwszExtensionName);
|
|
_JumpIfError(hr, error, "myVerifyObjId");
|
|
|
|
if (PROPTYPE_BINARY == (PROPTYPE_MASK & Flags))
|
|
{
|
|
cbprop = cbValue;
|
|
pbprop = (BYTE *) pbValue;
|
|
}
|
|
else
|
|
{
|
|
hr = myEncodeExtension(Flags, pbValue, cbValue, &pbprop, &cbprop);
|
|
_JumpIfError(hr, error, "myEncodeExtension");
|
|
}
|
|
|
|
hr = prow->SetExtension(pwszExtensionName, ExtFlags, cbprop, pbprop);
|
|
_JumpIfError(hr, error, "SetExtension");
|
|
|
|
error:
|
|
if (NULL != pbprop && pbprop != pbValue)
|
|
{
|
|
LocalFree(pbprop);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
FNCIGETEXTENSION PropCIGetExtension;
|
|
|
|
HRESULT
|
|
PropCIGetExtension(
|
|
IN LONG Context,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszExtensionName,
|
|
OUT DWORD *pdwExtFlags,
|
|
OUT VARIANT *pvarValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD RequestId;
|
|
BYTE *pbValue = NULL;
|
|
DWORD cbValue;
|
|
ICertDBRow *prow = NULL;
|
|
|
|
if (NULL != pvarValue)
|
|
{
|
|
VariantInit(pvarValue);
|
|
}
|
|
if (NULL == pwszExtensionName || NULL == pdwExtFlags || NULL == pvarValue)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
hr = g_pCertDB->OpenRow(PROPOPEN_READONLY | PROPTABLE_REQCERT, RequestId, NULL, &prow);
|
|
_JumpIfError(hr, error, "OpenRow");
|
|
|
|
hr = PropGetExtension(
|
|
prow,
|
|
PROPMARSHAL_LOCALSTRING | Flags,
|
|
pwszExtensionName,
|
|
pdwExtFlags,
|
|
&cbValue,
|
|
&pbValue);
|
|
_JumpIfError2(hr, error, "PropGetExtension", CERTSRV_E_PROPERTY_EMPTY);
|
|
|
|
hr = myUnmarshalVariant(
|
|
PROPMARSHAL_LOCALSTRING | Flags,
|
|
cbValue,
|
|
pbValue,
|
|
pvarValue);
|
|
_JumpIfError(hr, error, "myUnmarshalVariant");
|
|
|
|
error:
|
|
if (NULL != prow)
|
|
{
|
|
prow->Release();
|
|
}
|
|
if (NULL != pbValue)
|
|
{
|
|
LocalFree(pbValue);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
FNCISETPROPERTY PropCISetExtension;
|
|
|
|
HRESULT
|
|
PropCISetExtension(
|
|
IN LONG Context,
|
|
IN DWORD Flags,
|
|
IN WCHAR const *pwszExtensionName,
|
|
IN DWORD ExtFlags,
|
|
IN VARIANT const *pvarValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD RequestId;
|
|
DWORD cbprop;
|
|
BYTE *pbprop = NULL;
|
|
ICertDBRow *prow = NULL;
|
|
BOOL fCommitted = FALSE;
|
|
|
|
if (NULL == pwszExtensionName || NULL == pvarValue)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "NULL parm");
|
|
}
|
|
if ((PROPCALLER_MASK & Flags) != PROPCALLER_POLICY)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "Flags: Invalid caller");
|
|
}
|
|
hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
hr = myMarshalVariant(
|
|
pvarValue,
|
|
PROPMARSHAL_LOCALSTRING | Flags,
|
|
&cbprop,
|
|
&pbprop);
|
|
_JumpIfError(hr, error, "myMarshalVariant");
|
|
|
|
hr = g_pCertDB->OpenRow(PROPTABLE_REQCERT, RequestId, NULL, &prow);
|
|
_JumpIfError(hr, error, "OpenRow");
|
|
|
|
hr = PropSetExtension(
|
|
prow,
|
|
PROPMARSHAL_LOCALSTRING | Flags,
|
|
pwszExtensionName,
|
|
ExtFlags,
|
|
cbprop,
|
|
pbprop);
|
|
_JumpIfError(hr, error, "PropSetExtension");
|
|
|
|
hr = prow->CommitTransaction(CDBROW_COMMIT_SOFTCOMMIT); // not critical to flush
|
|
_JumpIfError(hr, error, "CommitTransaction");
|
|
|
|
fCommitted = TRUE;
|
|
|
|
error:
|
|
if (NULL != prow)
|
|
{
|
|
if (S_OK != hr && !fCommitted)
|
|
{
|
|
HRESULT hr2 = prow->CommitTransaction(CDBROW_COMMIT_ROLLBACK);
|
|
_PrintIfError(hr2, "CommitTransaction");
|
|
}
|
|
prow->Release();
|
|
}
|
|
if (NULL != pbprop)
|
|
{
|
|
LocalFree(pbprop);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
FNCIENUMSETUP PropCIEnumSetup;
|
|
|
|
HRESULT
|
|
PropCIEnumSetup(
|
|
IN LONG Context,
|
|
IN LONG Flags,
|
|
IN OUT CIENUM *pciEnum)
|
|
{
|
|
HRESULT hr;
|
|
DWORD RequestId;
|
|
|
|
CSASSERT(CSExpr(CIE_CALLER_POLICY == PROPCALLER_POLICY));
|
|
CSASSERT(CSExpr(CIE_CALLER_EXIT == PROPCALLER_EXIT));
|
|
CSASSERT(CSExpr(CIE_CALLER_MASK == PROPCALLER_MASK));
|
|
|
|
hr = ComVerifyRequestContext(FALSE, Flags, Context, &RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
hr = pciEnum->EnumSetup(RequestId, Context, Flags);
|
|
_JumpIfError(hr, error, "EnumSetup");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
FNCIENUMNEXT PropCIEnumNext;
|
|
|
|
HRESULT
|
|
PropCIEnumNext(
|
|
IN OUT CIENUM *pciEnum,
|
|
OUT BSTR *pstrPropertyName)
|
|
{
|
|
HRESULT hr;
|
|
DWORD RequestId;
|
|
|
|
CSASSERT(CSExpr(CIE_CALLER_POLICY == PROPCALLER_POLICY));
|
|
CSASSERT(CSExpr(CIE_CALLER_EXIT == PROPCALLER_EXIT));
|
|
CSASSERT(CSExpr(CIE_CALLER_MASK == PROPCALLER_MASK));
|
|
|
|
hr = ComVerifyRequestContext(
|
|
FALSE,
|
|
pciEnum->GetFlags(),
|
|
pciEnum->GetContext(),
|
|
&RequestId);
|
|
_JumpIfError(hr, error, "ComVerifyRequestContext");
|
|
|
|
hr = pciEnum->EnumNext(pstrPropertyName);
|
|
_JumpIfError2(hr, error, "EnumNext", S_FALSE);
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
FNCIENUMCLOSE PropCIEnumClose;
|
|
|
|
HRESULT
|
|
PropCIEnumClose(
|
|
IN OUT CIENUM *pciEnum)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = pciEnum->EnumClose();
|
|
_JumpIfError(hr, error, "EnumClose");
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
PropSetAttributeProperty(
|
|
IN ICertDBRow *prow,
|
|
IN BOOL fConcatenateRDNs,
|
|
IN BOOL fPrependNewValue,
|
|
IN DWORD dwTable,
|
|
IN DWORD cwcNameMax,
|
|
OPTIONAL IN WCHAR const *pwszSuffix,
|
|
IN WCHAR const *pwszName,
|
|
IN WCHAR const *pwszValue)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR *pwszTemp = NULL;
|
|
WCHAR const *pwszValue2 = pwszValue;
|
|
DWORD cbProp;
|
|
DWORD dwFlags = dwTable | PROPTYPE_STRING | PROPCALLER_SERVER;
|
|
|
|
CSASSERT(
|
|
PROPTABLE_ATTRIBUTE == dwTable ||
|
|
PROPTABLE_REQUEST == dwTable ||
|
|
PROPTABLE_CERTIFICATE == dwTable);
|
|
|
|
|
|
// if the name and value are both non-empty ...
|
|
|
|
if (NULL != pwszName && L'\0' != *pwszName &&
|
|
NULL != pwszValue && L'\0' != *pwszValue)
|
|
{
|
|
if (PROPTABLE_ATTRIBUTE != dwTable)
|
|
{
|
|
if (g_fEnforceRDNNameLengths && wcslen(pwszValue) > cwcNameMax)
|
|
{
|
|
hr = CERTSRV_E_BAD_REQUESTSUBJECT;
|
|
DBGPRINT((
|
|
DBG_SS_CERTSRV,
|
|
"RDN component too long: %u/%u: %ws=\"%ws\"\n",
|
|
wcslen(pwszValue),
|
|
cwcNameMax,
|
|
pwszName,
|
|
pwszValue));
|
|
_JumpErrorStr(hr, error, "RDN component too long", pwszValue);
|
|
}
|
|
if (fConcatenateRDNs)
|
|
{
|
|
cbProp = 0;
|
|
hr = prow->GetProperty(pwszName, dwFlags, NULL, &cbProp, NULL);
|
|
if (CERTSRV_E_PROPERTY_EMPTY != hr)
|
|
{
|
|
DWORD cwcAdd;
|
|
|
|
_JumpIfError(hr, error, "GetProperty");
|
|
|
|
cwcAdd = 1 + wcslen(pwszValue);
|
|
|
|
// cbProp includes trailing L'\0' when out buffer is NULL
|
|
|
|
pwszTemp = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
cbProp + sizeof(WCHAR) * cwcAdd);
|
|
if (NULL == pwszTemp)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
// If there are multiple RDN components for the same DB
|
|
// column, concatenate them.
|
|
|
|
if (fPrependNewValue)
|
|
{
|
|
wcscpy(pwszTemp, pwszValue);
|
|
wcscat(pwszTemp, wszNAMESEPARATORDEFAULT);
|
|
CSASSERT(wcslen(pwszTemp) == cwcAdd);
|
|
}
|
|
|
|
hr = prow->GetProperty(
|
|
pwszName,
|
|
dwFlags,
|
|
NULL,
|
|
&cbProp,
|
|
(BYTE *) &pwszTemp[fPrependNewValue? cwcAdd : 0]);
|
|
_JumpIfError(hr, error, "GetProperty");
|
|
|
|
// If there are multiple RDN components for the same DB
|
|
// column, concatenate them.
|
|
|
|
if (!fPrependNewValue)
|
|
{
|
|
wcscat(pwszTemp, wszNAMESEPARATORDEFAULT);
|
|
wcscat(pwszTemp, pwszValue);
|
|
}
|
|
pwszValue2 = pwszTemp;
|
|
|
|
// cbProp now does NOT include trailing L'\0'
|
|
|
|
CSASSERT(
|
|
sizeof(WCHAR) * wcslen(pwszTemp) ==
|
|
cbProp + sizeof(WCHAR) * cwcAdd);
|
|
}
|
|
}
|
|
else if (NULL != pwszSuffix)
|
|
{
|
|
hr = myAddNameSuffix(
|
|
pwszValue,
|
|
pwszSuffix,
|
|
cwcNameMax,
|
|
&pwszTemp);
|
|
_JumpIfError(hr, error, "myAddNameSuffix");
|
|
|
|
pwszValue2 = pwszTemp;
|
|
}
|
|
}
|
|
hr = prow->SetProperty(
|
|
pwszName,
|
|
dwFlags,
|
|
MAXDWORD,
|
|
(BYTE const *) pwszValue2);
|
|
_JumpIfError(hr, error, "SetProperty");
|
|
}
|
|
|
|
error:
|
|
if (NULL != pwszTemp)
|
|
{
|
|
LocalFree(pwszTemp);
|
|
}
|
|
return(hr);
|
|
}
|