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.
405 lines
11 KiB
405 lines
11 KiB
/*++
|
|
|
|
Copyright (C) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
BMOFCHCK.CPP
|
|
|
|
Abstract:
|
|
|
|
Has test to determine if a binary mof is valid. Note that the file has
|
|
not been tested and is not currently a part of mofcomp. This exists as a
|
|
backup in case the current fixes are not bullet proof.
|
|
|
|
History:
|
|
|
|
davj 27-Nov-00 Created.
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wbemutil.h>
|
|
#include <genutils.h>
|
|
#include "trace.h"
|
|
#include "bmof.h"
|
|
|
|
BYTE * CheckObject(BYTE * pObj, BYTE * pToFar, DWORD dwSizeOfObj);
|
|
DWORD CheckString(BYTE * pStr,BYTE * pToFar);
|
|
void CheckClassOrInst(WBEM_Object * pObject, BYTE * pToFar);
|
|
enum EFailureType
|
|
{
|
|
UNALIGNED_PTR = 0,
|
|
BAD_OBJECT,
|
|
BAD_SIZE,
|
|
BAD_STRING,
|
|
BAD_ARRAY_DATA,
|
|
BAD_SCALAR_DATA,
|
|
BAD_FLAVOR_TABLE
|
|
};
|
|
|
|
class CGenException
|
|
{
|
|
private:
|
|
EFailureType m_eType;
|
|
|
|
public:
|
|
|
|
CGenException( EFailureType eType ){ m_eType =eType ;}
|
|
EFailureType GetErrorCode() { return m_eType; }
|
|
};
|
|
|
|
|
|
#ifdef _WIN64
|
|
#define RETURN_IF_UNALIGN64() return FALSE;
|
|
#else
|
|
#define RETURN_IF_UNALIGN64()
|
|
#endif
|
|
|
|
void CheckAlignment(DWORD dwToCheck)
|
|
{
|
|
if(dwToCheck & 3)
|
|
{
|
|
ERRORTRACE((LOG_MOFCOMP,"CheckAlignment\n"));
|
|
#ifdef _WIN64
|
|
throw CGenException( UNALIGNED_PTR );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
DWORD CheckSimpleValue(BYTE *pData, BYTE *pToFar, DWORD dwType, BOOL bQualifier)
|
|
{
|
|
DWORD dwTypeSize = iTypeSize(dwType);
|
|
if(dwTypeSize == 0)
|
|
throw CGenException( BAD_SCALAR_DATA );
|
|
|
|
if(dwType == VT_DISPATCH)
|
|
{
|
|
WBEM_Object * pObject;
|
|
pObject = (WBEM_Object *)pData;
|
|
CheckClassOrInst(pObject, pToFar);
|
|
return pObject->dwLength;
|
|
}
|
|
else if(dwType == VT_BSTR)
|
|
{
|
|
DWORD dwNumChar = CheckString(pData ,pToFar);
|
|
return (dwNumChar+1) * sizeof(WCHAR);
|
|
}
|
|
if(pData + dwTypeSize >= pToFar)
|
|
throw CGenException( BAD_SCALAR_DATA );
|
|
return dwTypeSize;
|
|
}
|
|
|
|
void CheckValue(BYTE * pData, BYTE * pToFar, DWORD dwType, BOOL bQualifier)
|
|
{
|
|
DWORD * pArrayInfo, dwNumObj, dwCnt;
|
|
if(pData >= pToFar)
|
|
throw CGenException( BAD_OBJECT );
|
|
CheckAlignment((DWORD)pData);
|
|
if(dwType & VT_ARRAY)
|
|
{
|
|
CheckObject(pData, pToFar, 4*sizeof(DWORD));
|
|
DWORD dwSimpleType = dwType & ~VT_ARRAY & ~VT_BYREF;
|
|
pArrayInfo = (DWORD *)pData;
|
|
// check the number of rows. Currently only 1 is supported
|
|
|
|
pArrayInfo++;
|
|
if(*pArrayInfo != 1)
|
|
{
|
|
throw CGenException( BAD_ARRAY_DATA );
|
|
}
|
|
|
|
// Get the number of objects
|
|
|
|
pArrayInfo++;
|
|
dwNumObj = *pArrayInfo;
|
|
|
|
// Start into the row. It starts off with the total size
|
|
|
|
pArrayInfo++;
|
|
CheckAlignment(*pArrayInfo);
|
|
|
|
// Test each object
|
|
|
|
pArrayInfo++; // now points to first object
|
|
|
|
BYTE * pSingleData = (BYTE *)pArrayInfo;
|
|
for(dwCnt = 0; dwCnt < dwNumObj; dwCnt++)
|
|
{
|
|
DWORD dwSize = CheckSimpleValue(pSingleData, pToFar, dwSimpleType, bQualifier);
|
|
pSingleData += dwSize;
|
|
}
|
|
}
|
|
else
|
|
CheckSimpleValue(pData, pToFar, dwType, bQualifier);
|
|
}
|
|
|
|
BYTE * CheckObject(BYTE * pObj, BYTE * pToFar, DWORD dwSizeOfObj)
|
|
{
|
|
if(pObj + dwSizeOfObj >= pToFar)
|
|
throw CGenException( BAD_OBJECT );
|
|
CheckAlignment((DWORD)pObj);
|
|
|
|
// these always start off with the size, make sure that is OK
|
|
|
|
DWORD * pdw = (DWORD *)pObj;
|
|
|
|
if(*pdw + pObj >= pToFar)
|
|
throw CGenException( BAD_SIZE );
|
|
return *pdw + pObj + 1;
|
|
}
|
|
DWORD CheckString(BYTE * pStr,BYTE * pToFar)
|
|
{
|
|
DWORD dwNumChar = 0;
|
|
if(pStr >= pToFar)
|
|
throw CGenException( BAD_STRING );
|
|
CheckAlignment((DWORD)pStr);
|
|
WCHAR * pwc;
|
|
for(pwc = (WCHAR *)pStr; *pwc && pwc < (WCHAR*)pToFar; pwc++, dwNumChar++); // intentional semi
|
|
if(pwc >= (WCHAR *)pToFar)
|
|
throw CGenException( BAD_STRING );
|
|
return dwNumChar;
|
|
}
|
|
|
|
void CheckQualifier(WBEM_Qualifier *pQual, BYTE * pToFar)
|
|
{
|
|
BYTE * pByteInfo = (BYTE *)pQual;
|
|
pByteInfo += sizeof(WBEM_Qualifier);
|
|
pToFar = CheckObject((BYTE *)pQual, pToFar, sizeof(WBEM_Qualifier));
|
|
CheckString(pByteInfo + pQual->dwOffsetName, pToFar);
|
|
CheckValue(pByteInfo + pQual->dwOffsetValue, pToFar, pQual->dwType, TRUE);
|
|
return;
|
|
}
|
|
|
|
void CheckQualList(WBEM_QualifierList *pQualList, BYTE * pToFar)
|
|
{
|
|
DWORD dwNumQual, dwCnt;
|
|
WBEM_Qualifier *pQual;
|
|
|
|
pToFar = CheckObject((BYTE *)pQualList, pToFar, sizeof(WBEM_QualifierList));
|
|
|
|
dwNumQual = pQualList->dwNumQualifiers;
|
|
if(dwNumQual == 0)
|
|
return;
|
|
pQual = (WBEM_Qualifier *)((PBYTE)pQualList + sizeof(WBEM_QualifierList));
|
|
|
|
for(dwCnt = 0; dwCnt < dwNumQual; dwCnt++)
|
|
{
|
|
CheckQualifier(pQual, pToFar);
|
|
pQual = (WBEM_Qualifier *)((BYTE *)pQual + pQual->dwLength);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CheckProperty(WBEM_Property *pProperty, BOOL bProperty, BYTE * pToFar)
|
|
{
|
|
WBEM_QualifierList *pQualList;
|
|
BYTE * pValue;
|
|
pToFar = CheckObject((BYTE *)pProperty, pToFar, sizeof(WBEM_Property));
|
|
if(pProperty->dwOffsetName != 0xffffffff)
|
|
{
|
|
BYTE * pStr = ((BYTE *)pProperty +
|
|
sizeof(WBEM_Property) +
|
|
pProperty->dwOffsetName);
|
|
CheckString(pStr, pToFar);
|
|
}
|
|
|
|
if(pProperty->dwOffsetQualifierSet != 0xffffffff)
|
|
{
|
|
pQualList = (WBEM_QualifierList *)((BYTE *)pProperty +
|
|
sizeof(WBEM_Property) +
|
|
pProperty->dwOffsetQualifierSet);
|
|
CheckQualList(pQualList, pToFar);
|
|
}
|
|
|
|
if(pProperty->dwOffsetValue != 0xffffffff)
|
|
{
|
|
CheckAlignment(pProperty->dwOffsetValue & 3);
|
|
pValue = ((BYTE *)pProperty +
|
|
sizeof(WBEM_Property) +
|
|
pProperty->dwOffsetValue);
|
|
|
|
CheckValue(pValue, pToFar, pProperty->dwType, FALSE);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CheckPropList(WBEM_PropertyList *pPropList, BOOL bProperty, BYTE * pToFar)
|
|
{
|
|
DWORD dwNumProp, dwCnt;
|
|
WBEM_Property *pProperty;
|
|
|
|
pToFar = CheckObject((BYTE *)pPropList, pToFar, sizeof(WBEM_PropertyList));
|
|
|
|
dwNumProp = pPropList->dwNumberOfProperties;
|
|
if(dwNumProp == 0)
|
|
return;
|
|
pProperty = (WBEM_Property *)((PBYTE)pPropList + sizeof(WBEM_PropertyList));
|
|
|
|
for(dwCnt = 0; dwCnt < dwNumProp; dwCnt++)
|
|
{
|
|
CheckProperty(pProperty, bProperty, pToFar);
|
|
pProperty = (WBEM_Property *)((BYTE *)pProperty + pProperty->dwLength);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CheckClassOrInst(WBEM_Object * pObject, BYTE * pToFar)
|
|
{
|
|
WBEM_QualifierList *pQualList;
|
|
WBEM_PropertyList * pPropList;
|
|
WBEM_PropertyList * pMethodList;
|
|
|
|
pToFar = CheckObject((BYTE *)pObject, pToFar, sizeof(WBEM_Object));
|
|
if(pObject->dwType != 0 && pObject->dwType != 1)
|
|
throw CGenException( BAD_OBJECT );
|
|
|
|
// Check the qualifier list
|
|
|
|
if(pObject->dwOffsetQualifierList != 0xffffffff)
|
|
{
|
|
pQualList = (WBEM_QualifierList *)((BYTE *)pObject +
|
|
sizeof(WBEM_Object) +
|
|
pObject->dwOffsetQualifierList);
|
|
CheckQualList(pQualList, pToFar);
|
|
}
|
|
|
|
// check the property list
|
|
|
|
if(pObject->dwOffsetPropertyList != 0xffffffff)
|
|
{
|
|
pPropList = (WBEM_PropertyList *)((BYTE *)pObject +
|
|
sizeof(WBEM_Object) +
|
|
pObject->dwOffsetPropertyList);
|
|
CheckPropList(pPropList, TRUE, pToFar);
|
|
}
|
|
|
|
// check the method list
|
|
|
|
if(pObject->dwOffsetMethodList != 0xffffffff)
|
|
{
|
|
|
|
pMethodList = (WBEM_PropertyList *)((BYTE *)pObject +
|
|
sizeof(WBEM_Object) +
|
|
pObject->dwOffsetMethodList);
|
|
CheckPropList(pMethodList, FALSE, pToFar);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CheckBMOFQualFlavor(BYTE * pBinaryMof, BYTE * pToFar)
|
|
{
|
|
UNALIGNED DWORD * pdwTemp;
|
|
BYTE * pFlavorBlob;
|
|
DWORD dwNumPairs;
|
|
UNALIGNED DWORD * pOffset;
|
|
DWORD dwMyOffset;
|
|
DWORD dwCnt;
|
|
DWORD dwOrigBlobSize = 0;
|
|
|
|
// Calculate the pointer of the start of the flavor data
|
|
|
|
pdwTemp = (DWORD * )pBinaryMof;
|
|
pdwTemp++; // point to the original blob size
|
|
dwOrigBlobSize = *pdwTemp;
|
|
pFlavorBlob = pBinaryMof + dwOrigBlobSize;
|
|
|
|
// Dont even try past the end of memory
|
|
|
|
if(pFlavorBlob + 20 >= pToFar)
|
|
return;
|
|
|
|
// Check if the flavor blob is valid, it should start off with the
|
|
// characters "BMOFQUALFLAVOR11"
|
|
|
|
if(memcmp(pFlavorBlob, "BMOFQUALFLAVOR11", 16))
|
|
return; // Not really a problem since it may be old file
|
|
|
|
// The flavor part of the file has the format
|
|
// DWORD dwNumPair, followed by pairs of dwords;
|
|
// offset, flavor
|
|
|
|
// Determine the number of pairs
|
|
|
|
pFlavorBlob+= 16; // skip past signature
|
|
pdwTemp = (DWORD *)pFlavorBlob;
|
|
dwNumPairs = *pdwTemp; // Number of offset/value pairs
|
|
if(dwNumPairs < 1)
|
|
return;
|
|
|
|
// Given the number of pairs, make sure there is enough memory
|
|
|
|
if((pFlavorBlob + sizeof(DWORD) + (dwNumPairs * 2 * sizeof(DWORD)))>= pToFar)
|
|
throw CGenException( BAD_FLAVOR_TABLE );
|
|
|
|
// point to the first offset/flavor pair
|
|
|
|
pOffset = pdwTemp+1;
|
|
|
|
// go through the offset/flavor list. Ignore the flavors, but make sure the
|
|
// offsets are valid
|
|
|
|
for(dwCnt = 0; dwCnt < dwNumPairs; dwCnt++)
|
|
{
|
|
if(*pOffset >= dwOrigBlobSize)
|
|
throw CGenException( BAD_FLAVOR_TABLE );
|
|
pOffset += 2;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// IsValidBMOF.
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Checks to make sure that a binary mof is properly aligned on
|
|
// 4 byte boundaries. Note that this is not really necessary for
|
|
// 32 bit windows.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pBuffer Pointer to uncompressed binary mof data.
|
|
//
|
|
// RETURN:
|
|
//
|
|
// TRUE if all is well.
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL IsValidBMOF(BYTE * pData, BYTE * pToFar)
|
|
{
|
|
WBEM_Binary_MOF * pBinaryMof;
|
|
DWORD dwNumObj, dwCnt;
|
|
WBEM_Object * pObject;
|
|
if(pData == NULL || pToFar == NULL || pData >= pToFar)
|
|
return FALSE;
|
|
try
|
|
{
|
|
|
|
pBinaryMof = (WBEM_Binary_MOF *)pData;
|
|
CheckObject(pData, pToFar, sizeof(WBEM_Binary_MOF));
|
|
if(pBinaryMof->dwSignature != BMOF_SIG)
|
|
return FALSE;
|
|
dwNumObj = pBinaryMof->dwNumberOfObjects;
|
|
if(dwNumObj == 0)
|
|
return TRUE;
|
|
pObject = (WBEM_Object *)(pData + sizeof(WBEM_Binary_MOF));
|
|
for(dwCnt = 0; dwCnt < dwNumObj; dwCnt++)
|
|
{
|
|
CheckClassOrInst(pObject, pToFar);
|
|
pObject = (WBEM_Object *)((PBYTE *)pObject + pObject->dwLength);
|
|
}
|
|
CheckBMOFQualFlavor(pData, pToFar);
|
|
}
|
|
catch(CGenException)
|
|
{
|
|
ERRORTRACE((LOG_MOFCOMP,"BINARY MOF had exception\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|