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