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.
1357 lines
40 KiB
1357 lines
40 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: drvprov.cpp
|
|
//
|
|
// Contents: Microsoft Internet Security Authenticode Policy Provider
|
|
//
|
|
// Functions: DriverInitializePolicy
|
|
// DriverCleanupPolicy
|
|
// DriverFinalPolicy
|
|
// DriverRegisterServer
|
|
// DriverUnregisterServer
|
|
//
|
|
// *** local functions ***
|
|
// _ValidCatAttr
|
|
// _CheckVersionAttributeNEW
|
|
// _CheckVersionNEW
|
|
// _GetVersionNumbers
|
|
//
|
|
// History: 29-Sep-1997 pberkman created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include "global.hxx"
|
|
|
|
BOOL _GetVersionNumbers(
|
|
WCHAR *pwszMM,
|
|
DWORD *pdwMajor,
|
|
DWORD *pdwMinor,
|
|
DWORD *pdwBuild,
|
|
WCHAR *pwcFlagMinor,
|
|
WCHAR *pwcFlagBuild);
|
|
BOOL _ValidCatAttr(CRYPTCATATTRIBUTE *pAttr);
|
|
BOOL _CheckVersionAttributeNEW(DRIVER_VER_INFO *pVerInfo, CRYPTCATATTRIBUTE *pAttr);
|
|
DWORD _CheckVersionNEW(OSVERSIONINFO *pVersion, WCHAR *pwszAttr, BOOL fUseBuildNumber);
|
|
|
|
static LPSTR rgDriverUsages[] = {szOID_WHQL_CRYPTO, szOID_NT5_CRYPTO, szOID_OEM_WHQL_CRYPTO};
|
|
static CERT_USAGE_MATCH RequestUsage = {USAGE_MATCH_TYPE_OR, {sizeof(rgDriverUsages)/sizeof(LPSTR), rgDriverUsages}};
|
|
|
|
typedef struct _DRVPROV_PRIVATE_DATA
|
|
{
|
|
DWORD cbStruct;
|
|
|
|
CRYPT_PROVIDER_FUNCTIONS sAuthenticodePfns;
|
|
|
|
} DRVPROV_PRIVATE_DATA, *PDRVPROV_PRIVATE_DATA;
|
|
|
|
#define VER_CHECK_EQ 1
|
|
#define VER_CHECK_GT 2
|
|
#define VER_CHECK_LT 3
|
|
#define VER_CHECK_FAIL 4
|
|
|
|
HRESULT WINAPI DriverInitializePolicy(CRYPT_PROVIDER_DATA *pProvData)
|
|
{
|
|
if (!(pProvData->padwTrustStepErrors) ||
|
|
(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] != ERROR_SUCCESS))
|
|
{
|
|
return (S_FALSE);
|
|
}
|
|
|
|
if (!(_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, pRequestUsage)))
|
|
{
|
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] = ERROR_INVALID_PARAMETER;
|
|
return (S_FALSE);
|
|
}
|
|
|
|
GUID gAuthenticode = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
|
GUID gDriverProv = DRIVER_ACTION_VERIFY;
|
|
CRYPT_PROVIDER_PRIVDATA sPrivData;
|
|
CRYPT_PROVIDER_PRIVDATA *pPrivData;
|
|
DRVPROV_PRIVATE_DATA *pDriverData;
|
|
HRESULT hr;
|
|
|
|
hr = S_OK;
|
|
|
|
pPrivData = WTHelperGetProvPrivateDataFromChain(pProvData, &gDriverProv);
|
|
|
|
if (!(pPrivData))
|
|
{
|
|
memset(&sPrivData, 0x00, sizeof(CRYPT_PROVIDER_PRIVDATA));
|
|
sPrivData.cbStruct = sizeof(CRYPT_PROVIDER_PRIVDATA);
|
|
|
|
memcpy(&sPrivData.gProviderID, &gDriverProv, sizeof(GUID));
|
|
|
|
//
|
|
// add my data to the chain!
|
|
//
|
|
if (!pProvData->psPfns->pfnAddPrivData2Chain(pProvData, &sPrivData))
|
|
{
|
|
return (S_FALSE);
|
|
}
|
|
|
|
//
|
|
// get the new reference
|
|
//
|
|
pPrivData = WTHelperGetProvPrivateDataFromChain(pProvData, &gDriverProv);
|
|
}
|
|
|
|
|
|
//
|
|
// allocate space for my struct
|
|
//
|
|
if (!(pPrivData->pvProvData = pProvData->psPfns->pfnAlloc(sizeof(DRVPROV_PRIVATE_DATA))))
|
|
{
|
|
pProvData->dwError = GetLastError();
|
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] = TRUST_E_SYSTEM_ERROR;
|
|
return (S_FALSE);
|
|
}
|
|
|
|
memset(pPrivData->pvProvData, 0x00, sizeof(DRVPROV_PRIVATE_DATA));
|
|
pPrivData->cbProvData = sizeof(DRVPROV_PRIVATE_DATA);
|
|
|
|
pDriverData = (DRVPROV_PRIVATE_DATA *)pPrivData->pvProvData;
|
|
pDriverData->cbStruct = sizeof(DRVPROV_PRIVATE_DATA);
|
|
|
|
//
|
|
// fill in the Authenticode Functions
|
|
//
|
|
pDriverData->sAuthenticodePfns.cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
|
|
|
|
if (!(WintrustLoadFunctionPointers(&gAuthenticode, &pDriverData->sAuthenticodePfns)))
|
|
{
|
|
pProvData->psPfns->pfnFree(sPrivData.pvProvData);
|
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] = TRUST_E_PROVIDER_UNKNOWN;
|
|
return (S_FALSE);
|
|
}
|
|
|
|
if (pDriverData->sAuthenticodePfns.pfnInitialize)
|
|
{
|
|
hr = pDriverData->sAuthenticodePfns.pfnInitialize(pProvData);
|
|
}
|
|
|
|
//
|
|
// assign our usage
|
|
//
|
|
pProvData->pRequestUsage = &RequestUsage;
|
|
|
|
// for backwards compatibility
|
|
pProvData->pszUsageOID = szOID_WHQL_CRYPTO;
|
|
|
|
|
|
//
|
|
// do NOT allow test certs EVER!
|
|
//
|
|
// changed July 27, 2000
|
|
//
|
|
pProvData->dwRegPolicySettings &= ~(WTPF_TRUSTTEST | WTPF_TESTCANBEVALID);
|
|
|
|
//
|
|
// do NOT require the publisher to be in the trusted database
|
|
//
|
|
// (changed July 27, 2000)
|
|
//
|
|
pProvData->dwRegPolicySettings &= ~WTPF_ALLOWONLYPERTRUST;
|
|
|
|
//
|
|
// Always ignore offline errors.
|
|
//
|
|
// (Added 28 March, 2002)
|
|
//
|
|
pProvData->dwRegPolicySettings |=
|
|
WTPF_OFFLINEOK_IND |
|
|
WTPF_OFFLINEOK_COM |
|
|
WTPF_OFFLINEOKNBU_IND |
|
|
WTPF_OFFLINEOKNBU_COM;
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT WINAPI DriverCleanupPolicy(CRYPT_PROVIDER_DATA *pProvData)
|
|
{
|
|
GUID gDriverProv = DRIVER_ACTION_VERIFY;
|
|
CRYPT_PROVIDER_PRIVDATA *pMyData;
|
|
DRVPROV_PRIVATE_DATA *pDriverData;
|
|
HRESULT hr;
|
|
|
|
if (!(pProvData->padwTrustStepErrors) ||
|
|
(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] != ERROR_SUCCESS))
|
|
{
|
|
return (S_FALSE);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
pMyData = WTHelperGetProvPrivateDataFromChain(pProvData, &gDriverProv);
|
|
|
|
if (pMyData)
|
|
{
|
|
pDriverData = (DRVPROV_PRIVATE_DATA *)pMyData->pvProvData;
|
|
|
|
if (pDriverData != NULL)
|
|
{
|
|
//
|
|
// remove the data we allocated except for the "MyData"
|
|
// which WVT will clean up for us!
|
|
//
|
|
if (pDriverData->sAuthenticodePfns.pfnCleanupPolicy)
|
|
{
|
|
hr = pDriverData->sAuthenticodePfns.pfnCleanupPolicy(pProvData);
|
|
}
|
|
}
|
|
|
|
pProvData->psPfns->pfnFree(pMyData->pvProvData);
|
|
pMyData->pvProvData = NULL;
|
|
pMyData->cbProvData = 0;
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Allocates and returns the specified cryptographic message parameter.
|
|
//--------------------------------------------------------------------------
|
|
static void *AllocAndGetMsgParam(
|
|
IN HCRYPTMSG hMsg,
|
|
IN DWORD dwParamType,
|
|
IN DWORD dwIndex,
|
|
OUT DWORD *pcbData
|
|
)
|
|
{
|
|
void *pvData;
|
|
DWORD cbData;
|
|
|
|
if (!CryptMsgGetParam(
|
|
hMsg,
|
|
dwParamType,
|
|
dwIndex,
|
|
NULL, // pvData
|
|
&cbData) || 0 == cbData)
|
|
goto GetParamError;
|
|
if (NULL == (pvData = malloc(cbData)))
|
|
goto OutOfMemory;
|
|
if (!CryptMsgGetParam(
|
|
hMsg,
|
|
dwParamType,
|
|
dwIndex,
|
|
pvData,
|
|
&cbData)) {
|
|
free(pvData);
|
|
goto GetParamError;
|
|
}
|
|
|
|
CommonReturn:
|
|
*pcbData = cbData;
|
|
return pvData;
|
|
ErrorReturn:
|
|
pvData = NULL;
|
|
cbData = 0;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(OutOfMemory)
|
|
TRACE_ERROR(GetParamError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Alloc and NOCOPY Decode
|
|
//--------------------------------------------------------------------------
|
|
static void *AllocAndDecodeObject(
|
|
IN LPCSTR lpszStructType,
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded
|
|
)
|
|
{
|
|
DWORD cbStructInfo;
|
|
void *pvStructInfo;
|
|
|
|
CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
lpszStructType,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
CRYPT_DECODE_NOCOPY_FLAG,
|
|
NULL, // pvStructInfo
|
|
&cbStructInfo
|
|
);
|
|
if (cbStructInfo == 0)
|
|
goto ErrorReturn;
|
|
if (NULL == (pvStructInfo = malloc(cbStructInfo)))
|
|
goto ErrorReturn;
|
|
if (!CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
lpszStructType,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
CRYPT_DECODE_NOCOPY_FLAG,
|
|
pvStructInfo,
|
|
&cbStructInfo
|
|
)) {
|
|
free(pvStructInfo);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
CommonReturn:
|
|
return pvStructInfo;
|
|
ErrorReturn:
|
|
pvStructInfo = NULL;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
static void CopyBytesToMaxPathString(
|
|
IN const BYTE *pbData,
|
|
IN DWORD cbData,
|
|
OUT WCHAR wszDst[MAX_PATH]
|
|
)
|
|
{
|
|
DWORD cchDst;
|
|
|
|
if (pbData) {
|
|
cchDst = cbData / sizeof(WCHAR);
|
|
if (cchDst > MAX_PATH - 1)
|
|
cchDst = MAX_PATH - 1;
|
|
} else
|
|
cchDst = 0;
|
|
|
|
if (cchDst)
|
|
memcpy(wszDst, pbData, cchDst * sizeof(WCHAR));
|
|
|
|
wszDst[cchDst] = L'\0';
|
|
}
|
|
|
|
void UpdateDriverVersion(
|
|
IN CRYPT_PROVIDER_DATA *pProvData,
|
|
OUT WCHAR wszVersion[MAX_PATH]
|
|
)
|
|
{
|
|
HCRYPTMSG hMsg = pProvData->hMsg;
|
|
BYTE *pbContent = NULL;
|
|
DWORD cbContent;
|
|
PCTL_INFO pCtlInfo = NULL;
|
|
PCERT_EXTENSION pExt; // not allocated
|
|
PCAT_NAMEVALUE pNameValue = NULL;
|
|
|
|
if (NULL == hMsg)
|
|
goto NoMessage;
|
|
|
|
// Get the inner content.
|
|
if (NULL == (pbContent = (BYTE *) AllocAndGetMsgParam(
|
|
hMsg,
|
|
CMSG_CONTENT_PARAM,
|
|
0, // dwIndex
|
|
&cbContent))) goto GetContentError;
|
|
|
|
if (NULL == (pCtlInfo = (PCTL_INFO) AllocAndDecodeObject(
|
|
PKCS_CTL,
|
|
pbContent,
|
|
cbContent
|
|
)))
|
|
goto DecodeCtlError;
|
|
|
|
if (NULL == (pExt = CertFindExtension(
|
|
CAT_NAMEVALUE_OBJID,
|
|
pCtlInfo->cExtension,
|
|
pCtlInfo->rgExtension
|
|
)))
|
|
goto NoVersionExt;
|
|
|
|
if (NULL == (pNameValue = (PCAT_NAMEVALUE) AllocAndDecodeObject(
|
|
CAT_NAMEVALUE_STRUCT,
|
|
pExt->Value.pbData,
|
|
pExt->Value.cbData
|
|
)))
|
|
goto DecodeNameValueError;
|
|
|
|
CopyBytesToMaxPathString(pNameValue->Value.pbData,
|
|
pNameValue->Value.cbData, wszVersion);
|
|
|
|
CommonReturn:
|
|
if (pNameValue)
|
|
free(pNameValue);
|
|
if (pCtlInfo)
|
|
free(pCtlInfo);
|
|
if (pbContent)
|
|
free(pbContent);
|
|
|
|
return;
|
|
ErrorReturn:
|
|
wszVersion[0] = L'\0';
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR(NoMessage)
|
|
TRACE_ERROR(GetContentError)
|
|
TRACE_ERROR(DecodeCtlError)
|
|
TRACE_ERROR(NoVersionExt)
|
|
TRACE_ERROR(DecodeNameValueError)
|
|
}
|
|
|
|
|
|
BOOL _ValidCatAttr(CRYPTCATATTRIBUTE *pAttr)
|
|
{
|
|
if (!(pAttr) || (pAttr->cbValue < 1) || !(pAttr->pbValue))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT WINAPI DriverFinalPolicy(CRYPT_PROVIDER_DATA *pProvData)
|
|
{
|
|
GUID gDriverProv = DRIVER_ACTION_VERIFY;
|
|
HRESULT hr;
|
|
CRYPT_PROVIDER_PRIVDATA *pMyData;
|
|
CRYPT_PROVIDER_SGNR *pSigner;
|
|
CERT_CHAIN_POLICY_STATUS CertChainStatus;
|
|
CERT_CHAIN_POLICY_PARA CertChainPolicyPara;
|
|
|
|
CRYPTCATATTRIBUTE *pCatAttr;
|
|
CRYPTCATATTRIBUTE *pMemAttr;
|
|
|
|
DRIVER_VER_INFO *pVerInfo;
|
|
|
|
DWORD dwExceptionCode;
|
|
BOOL fUseCurrentOSVer = FALSE;
|
|
|
|
hr = ERROR_SUCCESS;
|
|
|
|
if (!(_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, pszUsageOID)) ||
|
|
!(pProvData->pWintrustData) ||
|
|
!(_ISINSTRUCT(WINTRUST_DATA, pProvData->pWintrustData->cbStruct, hWVTStateData)))
|
|
{
|
|
goto ErrorInvalidParam;
|
|
}
|
|
|
|
//
|
|
// First things first, make sure the signing cert chains up to a MS root
|
|
//
|
|
pSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
|
|
if (pSigner == NULL)
|
|
{
|
|
goto ErrorInvalidParam;
|
|
}
|
|
|
|
//
|
|
// The chain context may be NULL if another error was previously encountered
|
|
//
|
|
if (pSigner->pChainContext != NULL)
|
|
{
|
|
memset(&CertChainStatus, 0, sizeof(CertChainStatus));
|
|
CertChainStatus.cbSize = sizeof(CertChainStatus);
|
|
|
|
memset(&(CertChainPolicyPara), 0, sizeof(CertChainPolicyPara));
|
|
CertChainPolicyPara.cbSize = sizeof(CertChainPolicyPara);
|
|
CertChainPolicyPara.dwFlags = MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG;
|
|
|
|
if (!CertVerifyCertificateChainPolicy(
|
|
CERT_CHAIN_POLICY_MICROSOFT_ROOT,
|
|
pSigner->pChainContext,
|
|
&CertChainPolicyPara,
|
|
&CertChainStatus))
|
|
{
|
|
goto ErrorInvalidRoot;
|
|
}
|
|
|
|
if (CertChainStatus.dwError != ERROR_SUCCESS)
|
|
{
|
|
goto ErrorInvalidRoot;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize the fUseCurrentOSVer variable
|
|
//
|
|
if (_ISINSTRUCT(WINTRUST_DATA, pProvData->pWintrustData->cbStruct, dwProvFlags))
|
|
{
|
|
fUseCurrentOSVer =
|
|
(pProvData->pWintrustData->dwProvFlags & WTD_USE_DEFAULT_OSVER_CHECK) != 0;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
pVerInfo = (DRIVER_VER_INFO *)pProvData->pWintrustData->pPolicyCallbackData;
|
|
|
|
if (pVerInfo)
|
|
{
|
|
CRYPT_PROVIDER_SGNR *pSgnr;
|
|
CRYPT_PROVIDER_CERT *pCert;
|
|
|
|
// KeithV
|
|
// Today we do not support ranges of versions, so the version
|
|
// number must be the same. Also must be none zero
|
|
|
|
// Removed this check so that ranges can now be used - 9-10-99 (reidk)
|
|
|
|
/*if ((_ISINSTRUCT(DRIVER_VER_INFO, pVerInfo->cbStruct, sOSVersionLow)) &&
|
|
(_ISINSTRUCT(DRIVER_VER_INFO, pVerInfo->cbStruct, sOSVersionHigh)))
|
|
{
|
|
if(memcmp(&pVerInfo->sOSVersionLow,
|
|
&pVerInfo->sOSVersionHigh,
|
|
sizeof(DRIVER_VER_MAJORMINOR)) )
|
|
{
|
|
goto ErrorInvalidParam;
|
|
}
|
|
}*/
|
|
|
|
if (!(_ISINSTRUCT(DRIVER_VER_INFO, pVerInfo->cbStruct, pcSignerCertContext)))
|
|
{
|
|
goto ErrorInvalidParam;
|
|
}
|
|
|
|
pVerInfo->wszVersion[0] = NULL;
|
|
|
|
if (!(pSgnr = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
|
|
{
|
|
goto ErrorNoSigner;
|
|
}
|
|
|
|
if (!(pCert = WTHelperGetProvCertFromChain(pSgnr, 0)))
|
|
{
|
|
goto ErrorNoCert;
|
|
}
|
|
|
|
if (pCert->pCert)
|
|
{
|
|
CertGetNameStringW(
|
|
pCert->pCert,
|
|
CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
|
0, // dwFlags
|
|
NULL, // pvTypePara
|
|
pVerInfo->wszSignedBy,
|
|
MAX_PATH
|
|
);
|
|
|
|
pVerInfo->pcSignerCertContext = CertDuplicateCertificateContext(pCert->pCert);
|
|
|
|
if (pVerInfo->dwReserved1 == 0x1 && pVerInfo->dwReserved2 == 0) {
|
|
HCRYPTMSG hMsg = pProvData->hMsg;
|
|
|
|
// Return the message's store
|
|
if (hMsg) {
|
|
HCERTSTORE hStore;
|
|
hStore = CertOpenStore(
|
|
CERT_STORE_PROV_MSG,
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0, // hCryptProv
|
|
0, // dwFlags
|
|
(const void *) hMsg
|
|
);
|
|
pVerInfo->dwReserved2 = (ULONG_PTR) hStore;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (pProvData->padwTrustStepErrors)
|
|
{
|
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] = ERROR_SUCCESS;
|
|
}
|
|
|
|
if ((hr = checkGetErrorBasedOnStepErrors(pProvData)) != ERROR_SUCCESS)
|
|
{
|
|
goto StepError;
|
|
}
|
|
|
|
pCatAttr = NULL;
|
|
pMemAttr = NULL;
|
|
|
|
|
|
if ((pProvData->pPDSip) &&
|
|
(_ISINSTRUCT(PROVDATA_SIP, pProvData->pPDSip->cbStruct, psIndirectData)) &&
|
|
(pProvData->pPDSip->psSipSubjectInfo) &&
|
|
(pProvData->pPDSip->psSipSubjectInfo->dwUnionChoice == MSSIP_ADDINFO_CATMEMBER) &&
|
|
(pProvData->pPDSip->psSipSubjectInfo->psCatMember) &&
|
|
(pProvData->pPDSip->psSipSubjectInfo->psCatMember->pStore) &&
|
|
(pProvData->pPDSip->psSipSubjectInfo->psCatMember->pMember) &&
|
|
(pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CATALOG))
|
|
{
|
|
// The following APIs are in DELAYLOAD'ed mscat32.dll. If the
|
|
// DELAYLOAD fails an exception is raised.
|
|
__try {
|
|
HANDLE hCatStore;
|
|
|
|
hCatStore = CryptCATHandleFromStore(pProvData->pPDSip->psSipSubjectInfo->psCatMember->pStore);
|
|
|
|
//
|
|
// first look at the members attr
|
|
//
|
|
pMemAttr = CryptCATGetAttrInfo(hCatStore,
|
|
pProvData->pPDSip->psSipSubjectInfo->psCatMember->pMember,
|
|
L"OSAttr");
|
|
|
|
pCatAttr = CryptCATGetCatAttrInfo(hCatStore, L"OSAttr");
|
|
|
|
//
|
|
// This statement is to honor old _weird_ semantics where if there is a
|
|
// pointer to a pVerInfo struct and both the dwPlatformId/dwVersion fields
|
|
// of it are zero then don't do a version check. (probably for sigverif, or maybe
|
|
// even un-intentional, but keep old semantics regardless)
|
|
//
|
|
if ((pVerInfo == NULL) ||
|
|
(pVerInfo->dwPlatform != 0) ||
|
|
(pVerInfo->dwVersion != 0) ||
|
|
fUseCurrentOSVer)
|
|
{
|
|
|
|
if (_ValidCatAttr(pMemAttr))
|
|
{
|
|
if (!(_CheckVersionAttributeNEW(
|
|
fUseCurrentOSVer ? NULL : pVerInfo,
|
|
pMemAttr)))
|
|
{
|
|
goto OSAttrVersionError;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!_ValidCatAttr(pCatAttr) && !_ValidCatAttr(pMemAttr))
|
|
{
|
|
goto ValidOSAttrNotFound;
|
|
}
|
|
|
|
if (!(_CheckVersionAttributeNEW(
|
|
fUseCurrentOSVer ? NULL : pVerInfo,
|
|
pCatAttr)))
|
|
{
|
|
goto OSAttrVersionError;
|
|
}
|
|
}
|
|
}
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
dwExceptionCode = GetExceptionCode();
|
|
goto CryptCATException;
|
|
}
|
|
}
|
|
else if ((pProvData->pWintrustData) &&
|
|
(pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CATALOG))
|
|
{
|
|
goto ErrorInvalidParam;
|
|
}
|
|
|
|
//
|
|
// fill our name for SigVerif...
|
|
//
|
|
if (pVerInfo)
|
|
{
|
|
if (!(pVerInfo->wszVersion[0]))
|
|
{
|
|
if ((pMemAttr) && (pMemAttr->cbValue > 0) && (pMemAttr->pbValue))
|
|
{
|
|
CopyBytesToMaxPathString(pMemAttr->pbValue, pMemAttr->cbValue,
|
|
pVerInfo->wszVersion);
|
|
}
|
|
else if ((pCatAttr) && (pCatAttr->cbValue > 0) && (pCatAttr->pbValue))
|
|
{
|
|
CopyBytesToMaxPathString(pCatAttr->pbValue, pCatAttr->cbValue,
|
|
pVerInfo->wszVersion);
|
|
}
|
|
else
|
|
{
|
|
UpdateDriverVersion(pProvData, pVerInfo->wszVersion);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// retrieve my data from the provider struct
|
|
//
|
|
pMyData = WTHelperGetProvPrivateDataFromChain(pProvData, &gDriverProv);
|
|
|
|
if (pMyData)
|
|
{
|
|
DRVPROV_PRIVATE_DATA *pDriverData;
|
|
|
|
pDriverData = (DRVPROV_PRIVATE_DATA *)pMyData->pvProvData;
|
|
|
|
//
|
|
// call the standard final policy
|
|
//
|
|
if (pDriverData)
|
|
{
|
|
if (pDriverData->sAuthenticodePfns.pfnFinalPolicy)
|
|
{
|
|
DWORD dwOldUIFlags;
|
|
|
|
dwOldUIFlags = pProvData->pWintrustData->dwUIChoice;
|
|
pProvData->pWintrustData->dwUIChoice = WTD_UI_NONE;
|
|
|
|
hr = pDriverData->sAuthenticodePfns.pfnFinalPolicy(pProvData);
|
|
|
|
pProvData->pWintrustData->dwUIChoice = dwOldUIFlags;
|
|
}
|
|
}
|
|
}
|
|
|
|
CommonReturn:
|
|
if (hr != ERROR_INVALID_PARAMETER)
|
|
{
|
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] = hr;
|
|
}
|
|
|
|
return (hr);
|
|
|
|
ErrorReturn:
|
|
hr = GetLastError();
|
|
goto CommonReturn;
|
|
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorInvalidParam, ERROR_INVALID_PARAMETER);
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorNoSigner, TRUST_E_NOSIGNATURE);
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorNoCert, TRUST_E_NO_SIGNER_CERT);
|
|
SET_ERROR_VAR_EX(DBG_SS, ValidOSAttrNotFound,ERROR_APP_WRONG_OS);
|
|
SET_ERROR_VAR_EX(DBG_SS, OSAttrVersionError,ERROR_APP_WRONG_OS);
|
|
SET_ERROR_VAR_EX(DBG_SS, StepError, hr);
|
|
SET_ERROR_VAR_EX(DBG_SS, CryptCATException, dwExceptionCode);
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorInvalidRoot, CERT_E_UNTRUSTEDROOT);
|
|
}
|
|
|
|
|
|
#define OSATTR_ALL L'X'
|
|
#define OSATTR_GTEQ L'>'
|
|
#define OSATTR_LTEQ L'-'
|
|
#define OSATTR_LTEQ2 L'<'
|
|
#define OSATTR_OSSEP L':'
|
|
#define OSATTR_VERSEP L'.'
|
|
#define OSATTR_SEP L','
|
|
#define OSATTR_RANGE_SEP L';'
|
|
|
|
//
|
|
// NEW
|
|
//
|
|
BOOL _CheckVersionAttributeNEW(DRIVER_VER_INFO *pVerInfo, CRYPTCATATTRIBUTE *pAttr)
|
|
{
|
|
OSVERSIONINFO sVersion;
|
|
OSVERSIONINFO sVersionSave;
|
|
WCHAR *pwszCurrent;
|
|
WCHAR *pwszEnd = NULL;
|
|
WCHAR *pwszRangeSeperator = NULL;
|
|
BOOL fCheckRange = FALSE;
|
|
BOOL fUseBuildNumber = FALSE;
|
|
DWORD dwLowCheck;
|
|
DWORD dwHighCheck;
|
|
|
|
//
|
|
// If no version info was passed in, get the current
|
|
// OS version to that verification can be done against it
|
|
//
|
|
memset(&sVersion, 0x00, sizeof(OSVERSIONINFO));
|
|
if ((NULL == pVerInfo) || (pVerInfo->dwPlatform == 0))
|
|
{
|
|
sVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if (!GetVersionEx(&sVersion))
|
|
{
|
|
return FALSE;
|
|
}
|
|
fUseBuildNumber = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Analyze the pVerInfo struct and deduce whether we are checking a range,
|
|
// and/or whether the dwBuildNumber* fields exist and are being used.
|
|
//
|
|
if (_ISINSTRUCT(DRIVER_VER_INFO, pVerInfo->cbStruct, sOSVersionHigh))
|
|
{
|
|
//
|
|
// If version are different then a range is being used
|
|
//
|
|
if (memcmp( &(pVerInfo->sOSVersionLow),
|
|
&(pVerInfo->sOSVersionHigh),
|
|
sizeof(DRIVER_VER_MAJORMINOR)) != 0)
|
|
{
|
|
fCheckRange = TRUE;
|
|
}
|
|
|
|
//
|
|
// Just set these here since the first check is the same regardless
|
|
// of whetther we are doing range checking or not.
|
|
//
|
|
sVersion.dwPlatformId = pVerInfo->dwPlatform;
|
|
sVersion.dwMajorVersion = pVerInfo->sOSVersionLow.dwMajor;
|
|
sVersion.dwMinorVersion = pVerInfo->sOSVersionLow.dwMinor;
|
|
|
|
//
|
|
// Check to see if the dwBuildNumber* members exists, and
|
|
// if they are being used (not 0).
|
|
//
|
|
if ((_ISINSTRUCT(DRIVER_VER_INFO, pVerInfo->cbStruct, dwBuildNumberHigh)) &&
|
|
pVerInfo->dwBuildNumberLow != 0)
|
|
{
|
|
fUseBuildNumber = TRUE;
|
|
|
|
fCheckRange |= (pVerInfo->dwBuildNumberLow == pVerInfo->dwBuildNumberHigh) ?
|
|
FALSE : TRUE;
|
|
|
|
//
|
|
// Just set this in case we aren't doing range checking
|
|
//
|
|
sVersion.dwBuildNumber = pVerInfo->dwBuildNumberLow;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sVersion.dwPlatformId = pVerInfo->dwPlatform;
|
|
sVersion.dwMajorVersion = pVerInfo->dwVersion;
|
|
sVersion.dwMinorVersion = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save this in case multiple OSAttr elements need to be checked against
|
|
// a range
|
|
//
|
|
memcpy(&sVersionSave, &sVersion, sizeof(OSVERSIONINFO));
|
|
|
|
//
|
|
// Loop for each version in the attribute, and check to see if
|
|
// it satifies our criteria
|
|
//
|
|
pwszCurrent = (WCHAR *)pAttr->pbValue;
|
|
|
|
while ((pwszCurrent != NULL) && (*pwszCurrent))
|
|
{
|
|
//
|
|
// Find version seperator, insert '/0' if needed, and keep
|
|
// track of location for next time through the loop
|
|
//
|
|
pwszEnd = wcschr(pwszCurrent, OSATTR_SEP);
|
|
|
|
if (pwszEnd)
|
|
{
|
|
*pwszEnd = L'\0';
|
|
}
|
|
|
|
//
|
|
// Check to see if this version string is a range
|
|
//
|
|
pwszRangeSeperator = wcschr(pwszCurrent, OSATTR_RANGE_SEP);
|
|
if (pwszRangeSeperator != NULL)
|
|
{
|
|
//
|
|
// The version string in the cat file is a range
|
|
//
|
|
|
|
*pwszRangeSeperator = L'\0';
|
|
pwszRangeSeperator++;
|
|
|
|
dwLowCheck = _CheckVersionNEW(&sVersion, pwszCurrent, fUseBuildNumber);
|
|
|
|
//
|
|
// The only difference between checking a single OS version against a range,
|
|
// and checking a range of OS versions agains a range is the value used for the
|
|
// upper limit.
|
|
//
|
|
if (fCheckRange)
|
|
{
|
|
sVersion.dwPlatformId = pVerInfo->dwPlatform;
|
|
sVersion.dwMajorVersion = pVerInfo->sOSVersionHigh.dwMajor;
|
|
sVersion.dwMinorVersion = pVerInfo->sOSVersionHigh.dwMinor;
|
|
sVersion.dwBuildNumber = (fUseBuildNumber) ? pVerInfo->dwBuildNumberHigh : 0;
|
|
}
|
|
dwHighCheck = _CheckVersionNEW(&sVersion, pwszRangeSeperator, fUseBuildNumber);
|
|
|
|
if (((dwLowCheck == VER_CHECK_EQ) || (dwLowCheck == VER_CHECK_GT)) &&
|
|
((dwHighCheck == VER_CHECK_EQ) || (dwHighCheck == VER_CHECK_LT)))
|
|
{
|
|
if (pVerInfo)
|
|
{
|
|
CopyBytesToMaxPathString(
|
|
pAttr->pbValue,
|
|
pAttr->cbValue,
|
|
pVerInfo->wszVersion);
|
|
}
|
|
|
|
*(--pwszRangeSeperator) = OSATTR_RANGE_SEP;
|
|
if (pwszEnd != NULL)
|
|
{
|
|
*pwszEnd = OSATTR_SEP;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
*(--pwszRangeSeperator) = OSATTR_RANGE_SEP;
|
|
|
|
//
|
|
// copy back the low OSVER to get ready for the next pass
|
|
//
|
|
memcpy(&sVersion, &sVersionSave, sizeof(OSVERSIONINFO));
|
|
}
|
|
else
|
|
{
|
|
if (!fCheckRange)
|
|
{
|
|
if (_CheckVersionNEW(&sVersion, pwszCurrent, fUseBuildNumber) == VER_CHECK_EQ)
|
|
{
|
|
if (pVerInfo)
|
|
{
|
|
CopyBytesToMaxPathString(
|
|
pAttr->pbValue,
|
|
pAttr->cbValue,
|
|
pVerInfo->wszVersion);
|
|
}
|
|
|
|
if (pwszEnd != NULL)
|
|
{
|
|
*pwszEnd = OSATTR_SEP;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwLowCheck = _CheckVersionNEW(&sVersion, pwszCurrent, fUseBuildNumber);
|
|
|
|
sVersion.dwPlatformId = pVerInfo->dwPlatform;
|
|
sVersion.dwMajorVersion = pVerInfo->sOSVersionHigh.dwMajor;
|
|
sVersion.dwMinorVersion = pVerInfo->sOSVersionHigh.dwMinor;
|
|
sVersion.dwBuildNumber = (fUseBuildNumber) ? pVerInfo->dwBuildNumberHigh : 0;
|
|
dwHighCheck = _CheckVersionNEW(&sVersion, pwszCurrent, fUseBuildNumber);
|
|
|
|
if (((dwLowCheck == VER_CHECK_EQ) || (dwLowCheck == VER_CHECK_LT)) &&
|
|
((dwHighCheck == VER_CHECK_EQ) || (dwHighCheck == VER_CHECK_GT)))
|
|
{
|
|
if (pVerInfo)
|
|
{
|
|
CopyBytesToMaxPathString(
|
|
pAttr->pbValue,
|
|
pAttr->cbValue,
|
|
pVerInfo->wszVersion);
|
|
}
|
|
|
|
if (pwszEnd != NULL)
|
|
{
|
|
*pwszEnd = OSATTR_SEP;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// copy back the low OSVER to get ready for the next pass
|
|
//
|
|
memcpy(&sVersion, &sVersionSave, sizeof(OSVERSIONINFO));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there aren't anymore version in the attribute, then break,
|
|
// which means the version check failed
|
|
//
|
|
if (!(pwszEnd))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set up for next iteration
|
|
//
|
|
*pwszEnd = OSATTR_SEP;
|
|
pwszCurrent = pwszEnd;
|
|
pwszCurrent++;
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Comparison is done such that pVersion is VER_CHECK_LT, VER_CHECK_GT, or
|
|
// VER_CHECK_EQ to pwszAttr
|
|
//
|
|
DWORD _CheckVersionNEW(OSVERSIONINFO *pVersion, WCHAR *pwszAttr, BOOL fUseBuildNumber)
|
|
{
|
|
WCHAR *pwszCurrent;
|
|
WCHAR *pwszEnd;
|
|
DWORD dwPlatform;
|
|
DWORD dwMajor;
|
|
DWORD dwMinor;
|
|
DWORD dwBuild;
|
|
WCHAR wcFlagMinor;
|
|
WCHAR wcFlagBuild;
|
|
|
|
pwszCurrent = pwszAttr;
|
|
|
|
//
|
|
// format: os:major.minor, os:major.minor, ...
|
|
// 2:4.x = NT 4 (all)
|
|
// 2:4.> = NT 4 (all) and beyond
|
|
// 2:4.- = NT 4 (all) and before
|
|
// 2:4.< = NT 4 (all) and before
|
|
// 2:4.1.x = NT 4.1 (all)
|
|
// 2:4.1.> = NT 4.1 (all) and beyond
|
|
// 2:4.1.- = NT 4.1 (all) and before
|
|
// 2:4.1.< = NT 4.1 (all) and before
|
|
// 2:4.1 = NT 4.1 only
|
|
// 2:4.1.1 = NT 4.1 build # 1 only
|
|
//
|
|
if (!(pwszEnd = wcschr(pwszAttr, OSATTR_OSSEP)))
|
|
{
|
|
return(VER_CHECK_FAIL);
|
|
}
|
|
|
|
*pwszEnd = NULL;
|
|
|
|
//
|
|
// Check platform first
|
|
//
|
|
dwPlatform = (DWORD) _wtol(pwszCurrent);
|
|
*pwszEnd = OSATTR_OSSEP;
|
|
|
|
//
|
|
// MUST be same platform
|
|
//
|
|
if (dwPlatform != pVersion->dwPlatformId)
|
|
{
|
|
return(VER_CHECK_FAIL);
|
|
}
|
|
|
|
pwszCurrent = pwszEnd;
|
|
pwszCurrent++;
|
|
|
|
if (!(_GetVersionNumbers(pwszCurrent, &dwMajor, &dwMinor, &dwBuild, &wcFlagMinor, &wcFlagBuild)))
|
|
{
|
|
return(VER_CHECK_FAIL);
|
|
}
|
|
|
|
//
|
|
// The only way we can check against a build# is if the OSAttr has some build# node...
|
|
// which is not the case for an OSAttr like 2.4.x
|
|
//
|
|
if ((fUseBuildNumber && (dwBuild != 0)) ||
|
|
(wcFlagBuild != L'\0'))
|
|
{
|
|
switch (wcFlagBuild)
|
|
{
|
|
case OSATTR_ALL:
|
|
// 2:4.1.x = NT 4.1 (all)
|
|
if ((pVersion->dwMajorVersion == dwMajor) && (pVersion->dwMinorVersion == dwMinor))
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else if ((pVersion->dwMajorVersion < dwMajor) ||
|
|
((pVersion->dwMajorVersion == dwMajor) && (pVersion->dwMinorVersion < dwMinor)))
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
break;
|
|
|
|
case OSATTR_GTEQ:
|
|
// 2:4.1.> = NT 4.1 (all) and beyond
|
|
if ((pVersion->dwMajorVersion > dwMajor) ||
|
|
((pVersion->dwMajorVersion == dwMajor) && (pVersion->dwMinorVersion >= dwMinor)))
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
break;
|
|
|
|
case OSATTR_LTEQ:
|
|
case OSATTR_LTEQ2:
|
|
// 2:4.1.- = NT 4.1 (all) and before
|
|
// 2:4.1.< = NT 4.1 (all) and before
|
|
if ((pVersion->dwMajorVersion < dwMajor) ||
|
|
((pVersion->dwMajorVersion == dwMajor) && (pVersion->dwMinorVersion <= dwMinor)))
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
break;
|
|
default:
|
|
// 2:4.1.1 = NT 4.1 build # 1 only
|
|
|
|
if (pVersion->dwMajorVersion < dwMajor)
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else if (pVersion->dwMajorVersion > dwMajor)
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
else
|
|
{
|
|
if (pVersion->dwMinorVersion < dwMinor)
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else if (pVersion->dwMinorVersion > dwMinor)
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
else
|
|
{
|
|
if (pVersion->dwBuildNumber == dwBuild)
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else if (pVersion->dwBuildNumber < dwBuild)
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (wcFlagMinor)
|
|
{
|
|
case OSATTR_ALL:
|
|
// 2:4.x = NT 4 (all)
|
|
if (pVersion->dwMajorVersion == dwMajor)
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else if (pVersion->dwMajorVersion < dwMajor)
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
|
|
break;
|
|
|
|
case OSATTR_GTEQ:
|
|
// 2:4.> = NT 4 (all) and beyond
|
|
if (pVersion->dwMajorVersion >= dwMajor)
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
|
|
break;
|
|
|
|
case OSATTR_LTEQ:
|
|
case OSATTR_LTEQ2:
|
|
// 2:4.- = NT 4 (all) and before
|
|
// 2:4.< = NT 4 (all) and before
|
|
if (pVersion->dwMajorVersion <= dwMajor)
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
// 2:4.1 = NT 4.1 only
|
|
if ((pVersion->dwMajorVersion == dwMajor) && (pVersion->dwMinorVersion == dwMinor))
|
|
{
|
|
return(VER_CHECK_EQ);
|
|
}
|
|
else if (pVersion->dwMajorVersion == dwMajor)
|
|
{
|
|
if (pVersion->dwMinorVersion < dwMinor)
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
}
|
|
else if (pVersion->dwMajorVersion < dwMajor)
|
|
{
|
|
return(VER_CHECK_LT);
|
|
}
|
|
else
|
|
{
|
|
return(VER_CHECK_GT);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return(VER_CHECK_FAIL);
|
|
}
|
|
|
|
|
|
BOOL _GetVersionNumbers(
|
|
WCHAR *pwszMM,
|
|
DWORD *pdwMajor,
|
|
DWORD *pdwMinor,
|
|
DWORD *pdwBuild,
|
|
WCHAR *pwcFlagMinor,
|
|
WCHAR *pwcFlagBuild)
|
|
{
|
|
//
|
|
// special characters:
|
|
// - = all versions less than or equal to
|
|
// < = all versions less than or equal to
|
|
// > = all versions greater than or equal to
|
|
// X = all sub-versions.
|
|
//
|
|
WCHAR *pwszEnd;
|
|
|
|
*pdwMajor = 0;
|
|
*pdwMinor = 0;
|
|
*pdwBuild = 0;
|
|
*pwcFlagMinor = L'\0';
|
|
*pwcFlagBuild = L'\0';
|
|
|
|
if (pwszEnd = wcschr(pwszMM, OSATTR_VERSEP))
|
|
{
|
|
*pwszEnd = NULL;
|
|
}
|
|
|
|
*pdwMajor = (DWORD) _wtol(pwszMM);
|
|
|
|
//
|
|
// If there is only a major ver then return now, otherwise,
|
|
// continue processiing
|
|
//
|
|
if (pwszEnd == NULL)
|
|
{
|
|
return (TRUE);
|
|
}
|
|
|
|
*pwszEnd = OSATTR_VERSEP;
|
|
pwszMM = pwszEnd;
|
|
pwszMM++;
|
|
|
|
if (*pwszMM == '/0')
|
|
{
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// Get the minor ver/wildcard
|
|
//
|
|
if ((*pwszMM == OSATTR_GTEQ) ||
|
|
(*pwszMM == OSATTR_LTEQ) ||
|
|
(*pwszMM == OSATTR_LTEQ2) ||
|
|
(towupper(*pwszMM) == OSATTR_ALL))
|
|
{
|
|
*pwcFlagMinor = towupper(*pwszMM);
|
|
return(TRUE);
|
|
}
|
|
|
|
if (!(pwszEnd = wcschr(pwszMM, OSATTR_VERSEP)))
|
|
{
|
|
*pdwMinor = (DWORD) _wtol(pwszMM);
|
|
|
|
//
|
|
// This grandfathers all catalog files that had an OSAttr string of
|
|
// 2:4.1 to be 2:4.1.*
|
|
//
|
|
*pwcFlagBuild = OSATTR_ALL;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
*pwszEnd = NULL;
|
|
*pdwMinor = (DWORD) _wtol(pwszMM);
|
|
*pwszEnd = OSATTR_VERSEP;
|
|
pwszMM = pwszEnd;
|
|
pwszMM++;
|
|
|
|
//
|
|
// Get the build#/wildcard
|
|
//
|
|
if ((*pwszMM == OSATTR_GTEQ) ||
|
|
(*pwszMM == OSATTR_LTEQ) ||
|
|
(*pwszMM == OSATTR_LTEQ2) ||
|
|
(towupper(*pwszMM) == OSATTR_ALL))
|
|
{
|
|
*pwcFlagBuild = towupper(*pwszMM);
|
|
return(TRUE);
|
|
}
|
|
|
|
*pdwBuild = (DWORD) _wtol(pwszMM);
|
|
*pwcFlagBuild = L'\0';
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
STDAPI DriverRegisterServer(void)
|
|
{
|
|
GUID gDriver = DRIVER_ACTION_VERIFY;
|
|
CRYPT_REGISTER_ACTIONID sRegAID;
|
|
|
|
memset(&sRegAID, 0x00, sizeof(CRYPT_REGISTER_ACTIONID));
|
|
|
|
sRegAID.cbStruct = sizeof(CRYPT_REGISTER_ACTIONID);
|
|
|
|
// use our init policy
|
|
sRegAID.sInitProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sInitProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
|
|
sRegAID.sInitProvider.pwszFunctionName = DRIVER_INITPROV_FUNCTION;
|
|
|
|
// use standard object policy
|
|
sRegAID.sObjectProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sObjectProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
|
|
sRegAID.sObjectProvider.pwszFunctionName = SP_OBJTRUST_FUNCTION;
|
|
|
|
// use standard signature policy
|
|
sRegAID.sSignatureProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sSignatureProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
|
|
sRegAID.sSignatureProvider.pwszFunctionName = SP_SIGTRUST_FUNCTION;
|
|
|
|
// use standard cert builder
|
|
sRegAID.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sCertificateProvider.pwszDLLName = WT_PROVIDER_DLL_NAME;
|
|
sRegAID.sCertificateProvider.pwszFunctionName = WT_PROVIDER_CERTTRUST_FUNCTION;
|
|
|
|
// use standard cert policy
|
|
sRegAID.sCertificatePolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sCertificatePolicyProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
|
|
sRegAID.sCertificatePolicyProvider.pwszFunctionName = SP_CHKCERT_FUNCTION;
|
|
|
|
// use our final policy
|
|
sRegAID.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sFinalPolicyProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
|
|
sRegAID.sFinalPolicyProvider.pwszFunctionName = DRIVER_FINALPOLPROV_FUNCTION;
|
|
|
|
// use our cleanup policy
|
|
sRegAID.sCleanupProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
sRegAID.sCleanupProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
|
|
sRegAID.sCleanupProvider.pwszFunctionName = DRIVER_CLEANUPPOLICY_FUNCTION;
|
|
|
|
//
|
|
// Register our provider GUID...
|
|
//
|
|
if (!(WintrustAddActionID(&gDriver, 0, &sRegAID)))
|
|
{
|
|
return (S_FALSE);
|
|
}
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
STDAPI DriverUnregisterServer(void)
|
|
{
|
|
GUID gDriver = DRIVER_ACTION_VERIFY;
|
|
|
|
if (!(WintrustRemoveActionID(&gDriver)))
|
|
{
|
|
return (S_FALSE);
|
|
}
|
|
|
|
return (S_OK);
|
|
|
|
}
|