Leaked source code of windows server 2003
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

//+-------------------------------------------------------------------------
//
// 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);
}