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.

405 lines
11 KiB

  1. /*++
  2. Copyright (C) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. BMOFCHCK.CPP
  5. Abstract:
  6. Has test to determine if a binary mof is valid. Note that the file has
  7. not been tested and is not currently a part of mofcomp. This exists as a
  8. backup in case the current fixes are not bullet proof.
  9. History:
  10. davj 27-Nov-00 Created.
  11. --*/
  12. #include "precomp.h"
  13. #include <wbemutil.h>
  14. #include <genutils.h>
  15. #include "trace.h"
  16. #include "bmof.h"
  17. BYTE * CheckObject(BYTE * pObj, BYTE * pToFar, DWORD dwSizeOfObj);
  18. DWORD CheckString(BYTE * pStr,BYTE * pToFar);
  19. void CheckClassOrInst(WBEM_Object * pObject, BYTE * pToFar);
  20. enum EFailureType
  21. {
  22. UNALIGNED_PTR = 0,
  23. BAD_OBJECT,
  24. BAD_SIZE,
  25. BAD_STRING,
  26. BAD_ARRAY_DATA,
  27. BAD_SCALAR_DATA,
  28. BAD_FLAVOR_TABLE
  29. };
  30. class CGenException
  31. {
  32. private:
  33. EFailureType m_eType;
  34. public:
  35. CGenException( EFailureType eType ){ m_eType =eType ;}
  36. EFailureType GetErrorCode() { return m_eType; }
  37. };
  38. #ifdef _WIN64
  39. #define RETURN_IF_UNALIGN64() return FALSE;
  40. #else
  41. #define RETURN_IF_UNALIGN64()
  42. #endif
  43. void CheckAlignment(DWORD dwToCheck)
  44. {
  45. if(dwToCheck & 3)
  46. {
  47. ERRORTRACE((LOG_MOFCOMP,"CheckAlignment\n"));
  48. #ifdef _WIN64
  49. throw CGenException( UNALIGNED_PTR );
  50. #endif
  51. }
  52. }
  53. DWORD CheckSimpleValue(BYTE *pData, BYTE *pToFar, DWORD dwType, BOOL bQualifier)
  54. {
  55. DWORD dwTypeSize = iTypeSize(dwType);
  56. if(dwTypeSize == 0)
  57. throw CGenException( BAD_SCALAR_DATA );
  58. if(dwType == VT_DISPATCH)
  59. {
  60. WBEM_Object * pObject;
  61. pObject = (WBEM_Object *)pData;
  62. CheckClassOrInst(pObject, pToFar);
  63. return pObject->dwLength;
  64. }
  65. else if(dwType == VT_BSTR)
  66. {
  67. DWORD dwNumChar = CheckString(pData ,pToFar);
  68. return (dwNumChar+1) * sizeof(WCHAR);
  69. }
  70. if(pData + dwTypeSize >= pToFar)
  71. throw CGenException( BAD_SCALAR_DATA );
  72. return dwTypeSize;
  73. }
  74. void CheckValue(BYTE * pData, BYTE * pToFar, DWORD dwType, BOOL bQualifier)
  75. {
  76. DWORD * pArrayInfo, dwNumObj, dwCnt;
  77. if(pData >= pToFar)
  78. throw CGenException( BAD_OBJECT );
  79. CheckAlignment((DWORD)pData);
  80. if(dwType & VT_ARRAY)
  81. {
  82. CheckObject(pData, pToFar, 4*sizeof(DWORD));
  83. DWORD dwSimpleType = dwType & ~VT_ARRAY & ~VT_BYREF;
  84. pArrayInfo = (DWORD *)pData;
  85. // check the number of rows. Currently only 1 is supported
  86. pArrayInfo++;
  87. if(*pArrayInfo != 1)
  88. {
  89. throw CGenException( BAD_ARRAY_DATA );
  90. }
  91. // Get the number of objects
  92. pArrayInfo++;
  93. dwNumObj = *pArrayInfo;
  94. // Start into the row. It starts off with the total size
  95. pArrayInfo++;
  96. CheckAlignment(*pArrayInfo);
  97. // Test each object
  98. pArrayInfo++; // now points to first object
  99. BYTE * pSingleData = (BYTE *)pArrayInfo;
  100. for(dwCnt = 0; dwCnt < dwNumObj; dwCnt++)
  101. {
  102. DWORD dwSize = CheckSimpleValue(pSingleData, pToFar, dwSimpleType, bQualifier);
  103. pSingleData += dwSize;
  104. }
  105. }
  106. else
  107. CheckSimpleValue(pData, pToFar, dwType, bQualifier);
  108. }
  109. BYTE * CheckObject(BYTE * pObj, BYTE * pToFar, DWORD dwSizeOfObj)
  110. {
  111. if(pObj + dwSizeOfObj >= pToFar)
  112. throw CGenException( BAD_OBJECT );
  113. CheckAlignment((DWORD)pObj);
  114. // these always start off with the size, make sure that is OK
  115. DWORD * pdw = (DWORD *)pObj;
  116. if(*pdw + pObj >= pToFar)
  117. throw CGenException( BAD_SIZE );
  118. return *pdw + pObj + 1;
  119. }
  120. DWORD CheckString(BYTE * pStr,BYTE * pToFar)
  121. {
  122. DWORD dwNumChar = 0;
  123. if(pStr >= pToFar)
  124. throw CGenException( BAD_STRING );
  125. CheckAlignment((DWORD)pStr);
  126. WCHAR * pwc;
  127. for(pwc = (WCHAR *)pStr; *pwc && pwc < (WCHAR*)pToFar; pwc++, dwNumChar++); // intentional semi
  128. if(pwc >= (WCHAR *)pToFar)
  129. throw CGenException( BAD_STRING );
  130. return dwNumChar;
  131. }
  132. void CheckQualifier(WBEM_Qualifier *pQual, BYTE * pToFar)
  133. {
  134. BYTE * pByteInfo = (BYTE *)pQual;
  135. pByteInfo += sizeof(WBEM_Qualifier);
  136. pToFar = CheckObject((BYTE *)pQual, pToFar, sizeof(WBEM_Qualifier));
  137. CheckString(pByteInfo + pQual->dwOffsetName, pToFar);
  138. CheckValue(pByteInfo + pQual->dwOffsetValue, pToFar, pQual->dwType, TRUE);
  139. return;
  140. }
  141. void CheckQualList(WBEM_QualifierList *pQualList, BYTE * pToFar)
  142. {
  143. DWORD dwNumQual, dwCnt;
  144. WBEM_Qualifier *pQual;
  145. pToFar = CheckObject((BYTE *)pQualList, pToFar, sizeof(WBEM_QualifierList));
  146. dwNumQual = pQualList->dwNumQualifiers;
  147. if(dwNumQual == 0)
  148. return;
  149. pQual = (WBEM_Qualifier *)((PBYTE)pQualList + sizeof(WBEM_QualifierList));
  150. for(dwCnt = 0; dwCnt < dwNumQual; dwCnt++)
  151. {
  152. CheckQualifier(pQual, pToFar);
  153. pQual = (WBEM_Qualifier *)((BYTE *)pQual + pQual->dwLength);
  154. }
  155. return;
  156. }
  157. void CheckProperty(WBEM_Property *pProperty, BOOL bProperty, BYTE * pToFar)
  158. {
  159. WBEM_QualifierList *pQualList;
  160. BYTE * pValue;
  161. pToFar = CheckObject((BYTE *)pProperty, pToFar, sizeof(WBEM_Property));
  162. if(pProperty->dwOffsetName != 0xffffffff)
  163. {
  164. BYTE * pStr = ((BYTE *)pProperty +
  165. sizeof(WBEM_Property) +
  166. pProperty->dwOffsetName);
  167. CheckString(pStr, pToFar);
  168. }
  169. if(pProperty->dwOffsetQualifierSet != 0xffffffff)
  170. {
  171. pQualList = (WBEM_QualifierList *)((BYTE *)pProperty +
  172. sizeof(WBEM_Property) +
  173. pProperty->dwOffsetQualifierSet);
  174. CheckQualList(pQualList, pToFar);
  175. }
  176. if(pProperty->dwOffsetValue != 0xffffffff)
  177. {
  178. CheckAlignment(pProperty->dwOffsetValue & 3);
  179. pValue = ((BYTE *)pProperty +
  180. sizeof(WBEM_Property) +
  181. pProperty->dwOffsetValue);
  182. CheckValue(pValue, pToFar, pProperty->dwType, FALSE);
  183. }
  184. return;
  185. }
  186. void CheckPropList(WBEM_PropertyList *pPropList, BOOL bProperty, BYTE * pToFar)
  187. {
  188. DWORD dwNumProp, dwCnt;
  189. WBEM_Property *pProperty;
  190. pToFar = CheckObject((BYTE *)pPropList, pToFar, sizeof(WBEM_PropertyList));
  191. dwNumProp = pPropList->dwNumberOfProperties;
  192. if(dwNumProp == 0)
  193. return;
  194. pProperty = (WBEM_Property *)((PBYTE)pPropList + sizeof(WBEM_PropertyList));
  195. for(dwCnt = 0; dwCnt < dwNumProp; dwCnt++)
  196. {
  197. CheckProperty(pProperty, bProperty, pToFar);
  198. pProperty = (WBEM_Property *)((BYTE *)pProperty + pProperty->dwLength);
  199. }
  200. return;
  201. }
  202. void CheckClassOrInst(WBEM_Object * pObject, BYTE * pToFar)
  203. {
  204. WBEM_QualifierList *pQualList;
  205. WBEM_PropertyList * pPropList;
  206. WBEM_PropertyList * pMethodList;
  207. pToFar = CheckObject((BYTE *)pObject, pToFar, sizeof(WBEM_Object));
  208. if(pObject->dwType != 0 && pObject->dwType != 1)
  209. throw CGenException( BAD_OBJECT );
  210. // Check the qualifier list
  211. if(pObject->dwOffsetQualifierList != 0xffffffff)
  212. {
  213. pQualList = (WBEM_QualifierList *)((BYTE *)pObject +
  214. sizeof(WBEM_Object) +
  215. pObject->dwOffsetQualifierList);
  216. CheckQualList(pQualList, pToFar);
  217. }
  218. // check the property list
  219. if(pObject->dwOffsetPropertyList != 0xffffffff)
  220. {
  221. pPropList = (WBEM_PropertyList *)((BYTE *)pObject +
  222. sizeof(WBEM_Object) +
  223. pObject->dwOffsetPropertyList);
  224. CheckPropList(pPropList, TRUE, pToFar);
  225. }
  226. // check the method list
  227. if(pObject->dwOffsetMethodList != 0xffffffff)
  228. {
  229. pMethodList = (WBEM_PropertyList *)((BYTE *)pObject +
  230. sizeof(WBEM_Object) +
  231. pObject->dwOffsetMethodList);
  232. CheckPropList(pMethodList, FALSE, pToFar);
  233. }
  234. return;
  235. }
  236. void CheckBMOFQualFlavor(BYTE * pBinaryMof, BYTE * pToFar)
  237. {
  238. UNALIGNED DWORD * pdwTemp;
  239. BYTE * pFlavorBlob;
  240. DWORD dwNumPairs;
  241. UNALIGNED DWORD * pOffset;
  242. DWORD dwMyOffset;
  243. DWORD dwCnt;
  244. DWORD dwOrigBlobSize = 0;
  245. // Calculate the pointer of the start of the flavor data
  246. pdwTemp = (DWORD * )pBinaryMof;
  247. pdwTemp++; // point to the original blob size
  248. dwOrigBlobSize = *pdwTemp;
  249. pFlavorBlob = pBinaryMof + dwOrigBlobSize;
  250. // Dont even try past the end of memory
  251. if(pFlavorBlob + 20 >= pToFar)
  252. return;
  253. // Check if the flavor blob is valid, it should start off with the
  254. // characters "BMOFQUALFLAVOR11"
  255. if(memcmp(pFlavorBlob, "BMOFQUALFLAVOR11", 16))
  256. return; // Not really a problem since it may be old file
  257. // The flavor part of the file has the format
  258. // DWORD dwNumPair, followed by pairs of dwords;
  259. // offset, flavor
  260. // Determine the number of pairs
  261. pFlavorBlob+= 16; // skip past signature
  262. pdwTemp = (DWORD *)pFlavorBlob;
  263. dwNumPairs = *pdwTemp; // Number of offset/value pairs
  264. if(dwNumPairs < 1)
  265. return;
  266. // Given the number of pairs, make sure there is enough memory
  267. if((pFlavorBlob + sizeof(DWORD) + (dwNumPairs * 2 * sizeof(DWORD)))>= pToFar)
  268. throw CGenException( BAD_FLAVOR_TABLE );
  269. // point to the first offset/flavor pair
  270. pOffset = pdwTemp+1;
  271. // go through the offset/flavor list. Ignore the flavors, but make sure the
  272. // offsets are valid
  273. for(dwCnt = 0; dwCnt < dwNumPairs; dwCnt++)
  274. {
  275. if(*pOffset >= dwOrigBlobSize)
  276. throw CGenException( BAD_FLAVOR_TABLE );
  277. pOffset += 2;
  278. }
  279. }
  280. //***************************************************************************
  281. //
  282. // IsValidBMOF.
  283. //
  284. // DESCRIPTION:
  285. //
  286. // Checks to make sure that a binary mof is properly aligned on
  287. // 4 byte boundaries. Note that this is not really necessary for
  288. // 32 bit windows.
  289. //
  290. // PARAMETERS:
  291. //
  292. // pBuffer Pointer to uncompressed binary mof data.
  293. //
  294. // RETURN:
  295. //
  296. // TRUE if all is well.
  297. //
  298. //***************************************************************************
  299. BOOL IsValidBMOF(BYTE * pData, BYTE * pToFar)
  300. {
  301. WBEM_Binary_MOF * pBinaryMof;
  302. DWORD dwNumObj, dwCnt;
  303. WBEM_Object * pObject;
  304. if(pData == NULL || pToFar == NULL || pData >= pToFar)
  305. return FALSE;
  306. try
  307. {
  308. pBinaryMof = (WBEM_Binary_MOF *)pData;
  309. CheckObject(pData, pToFar, sizeof(WBEM_Binary_MOF));
  310. if(pBinaryMof->dwSignature != BMOF_SIG)
  311. return FALSE;
  312. dwNumObj = pBinaryMof->dwNumberOfObjects;
  313. if(dwNumObj == 0)
  314. return TRUE;
  315. pObject = (WBEM_Object *)(pData + sizeof(WBEM_Binary_MOF));
  316. for(dwCnt = 0; dwCnt < dwNumObj; dwCnt++)
  317. {
  318. CheckClassOrInst(pObject, pToFar);
  319. pObject = (WBEM_Object *)((PBYTE *)pObject + pObject->dwLength);
  320. }
  321. CheckBMOFQualFlavor(pData, pToFar);
  322. }
  323. catch(CGenException)
  324. {
  325. ERRORTRACE((LOG_MOFCOMP,"BINARY MOF had exception\n"));
  326. return FALSE;
  327. }
  328. return TRUE;
  329. }