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.

632 lines
15 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * verifyBlob.c
  7. *
  8. * Abstract:
  9. * This file contains blob verification code
  10. *
  11. * Revision History:
  12. * Neal Christiansen (nealch) 12/18/2000
  13. *
  14. *****************************************************************************/
  15. BOOL
  16. VerifyBlobHeader(
  17. BlobHeader *BlobHead,
  18. PCHAR Name,
  19. DWORD BlobType
  20. )
  21. /*++
  22. Routine Description:
  23. Verify that the given BLOB Header is valid
  24. Arguments:
  25. Return Value:
  26. TRUE if OK else FALSE
  27. --*/
  28. {
  29. BOOL good = TRUE;
  30. if (BlobHead->m_dwVersion != BLOB_VERSION_NUM) {
  31. printf("Invalid VERSION in %s blob header, was %08x, should be %08x\n",
  32. Name,
  33. BlobHead->m_dwVersion,
  34. BLOB_VERSION_NUM);
  35. good = FALSE;
  36. }
  37. if (BlobHead->m_dwBlbType != BlobType) {
  38. printf("Invalid TYPE in %s blob header, was %08x, should be %08x\n",
  39. Name,
  40. BlobHead->m_dwBlbType,
  41. BlobType);
  42. good = FALSE;
  43. }
  44. if (BlobHead->m_dwMagicNum != BLOB_MAGIC_NUM) {
  45. printf("Invalid MAGIC NUMBER in %s blob header, was %08x, should be %08x\n",
  46. Name,
  47. BlobHead->m_dwMagicNum,
  48. BLOB_MAGIC_NUM);
  49. good = FALSE;
  50. }
  51. if ((BlobHead->m_dwEntries <= 0) || (BlobHead->m_dwEntries >= 10000)) {
  52. printf("Invalid ENTRIES in %s blob header, was %08x, should be > 0 and < 10,000\n",
  53. Name,
  54. BlobHead->m_dwEntries);
  55. good = FALSE;
  56. }
  57. return good;
  58. }
  59. BOOL
  60. VerifyHashHeader(
  61. ListHeader *HashHead,
  62. PCHAR Name,
  63. DWORD Offset
  64. )
  65. /*++
  66. Routine Description:
  67. Verify that the given TREE Header is valid
  68. Arguments:
  69. Return Value:
  70. TRUE if OK else FALSE
  71. --*/
  72. {
  73. BOOL good = TRUE;
  74. DWORD calculatedSize;
  75. DWORD numNodes;
  76. //
  77. // Verify BLOB header
  78. //
  79. if (!VerifyBlobHeader(&HashHead->m_BlobHeader,Name,BLOB_TYPE_HASHLIST)) {
  80. return FALSE;
  81. }
  82. //
  83. // paulmcd: jan/2001
  84. // m_iHashBuckets will not be exact with m_dwEntries as it is the next
  85. // highest prime number. but it will always be larger than or equalto.
  86. //
  87. if (HashHead->m_iHashBuckets < HashHead->m_BlobHeader.m_dwEntries) {
  88. printf("Invalid HASH BUCKET COUNT in %s header, is %08x, should be %08x or %08x\n",
  89. Name,
  90. HashHead->m_iHashBuckets,
  91. HashHead->m_BlobHeader.m_dwEntries,
  92. HashHead->m_BlobHeader.m_dwEntries+1);
  93. good = FALSE;
  94. }
  95. if ((HashHead->m_dwDataOff != HashHead->m_BlobHeader.m_dwMaxSize)) {
  96. printf("Invalid DATA OFFSET in %s header, is %08x, should be %08x\n",
  97. Name,
  98. HashHead->m_dwDataOff,
  99. HashHead->m_BlobHeader.m_dwMaxSize);
  100. good = FALSE;
  101. }
  102. if ((HashHead->m_iFreeNode != 0)) {
  103. printf("Invalid FREE NODE in %s header, is %08x, should be 0\n",
  104. Name,
  105. HashHead->m_iFreeNode);
  106. good = FALSE;
  107. }
  108. //
  109. // Make sure the calucalted size is accurate
  110. //
  111. numNodes = HashHead->m_BlobHeader.m_dwEntries + 1;
  112. calculatedSize = sizeof(ListHeader) +
  113. (HashHead->m_iHashBuckets * sizeof(DWORD)) +
  114. (numNodes * sizeof(ListEntry));
  115. if (calculatedSize >= HashHead->m_BlobHeader.m_dwMaxSize) {
  116. printf("Invalid CALCULATED SIZE in %s header, is %08x, should be < %08x\n",
  117. Name,
  118. calculatedSize,
  119. HashHead->m_BlobHeader.m_dwMaxSize);
  120. good = FALSE;
  121. }
  122. return good;
  123. }
  124. BOOL
  125. VerifyHash(
  126. ListHeader *HashHead,
  127. PCHAR Name,
  128. DWORD Offset
  129. )
  130. /*++
  131. Routine Description:
  132. Verify that the given TREE entries are valid
  133. Arguments:
  134. Return Value:
  135. TRUE if OK else FALSE
  136. --*/
  137. {
  138. BOOL good = TRUE;
  139. UINT i;
  140. DWORD dataStart;
  141. DWORD numNodes;
  142. DWORD numBuckets;
  143. DWORD *hTable;
  144. ListEntry *hNode;
  145. //
  146. // Validate the HEADER
  147. //
  148. if (!VerifyHashHeader(HashHead,Name,Offset)) {
  149. return FALSE;
  150. }
  151. //
  152. // paulmcd: we have hash bucket and actual nodes. there is one extra
  153. // actual node than reported due to offset zero being null. the bucket
  154. // count is the next largest prime from numNodes
  155. //
  156. numBuckets = HashHead->m_iHashBuckets;
  157. numNodes = HashHead->m_BlobHeader.m_dwEntries + 1;
  158. //
  159. // Validate Hash table entries
  160. //
  161. hTable = (DWORD *)(HashHead + 1);
  162. for (i=0;i < HashHead->m_iHashBuckets;i++,hTable++) {
  163. if (*hTable >= numNodes) {
  164. printf("Invalid HASH TABLE ENTRY[%d] in %s, is %08x, should be < %08x\n",
  165. i,
  166. Name,
  167. *hTable,
  168. numNodes);
  169. good = FALSE;
  170. }
  171. }
  172. //
  173. // Validate the start of the Hash LIST entries
  174. //
  175. {
  176. ULONG_PTR actualOffset;
  177. ULONG_PTR calculatedOffset;
  178. actualOffset = (ULONG_PTR)hTable - (ULONG_PTR)HashHead;
  179. calculatedOffset = sizeof(ListHeader) +
  180. (HashHead->m_iHashBuckets * sizeof(DWORD));
  181. if (calculatedOffset != actualOffset) {
  182. printf("Invalid HASH LIST START in %s, offset is %08x, should be %08x\n",
  183. Name,
  184. actualOffset,
  185. calculatedOffset);
  186. return FALSE;
  187. }
  188. }
  189. //
  190. // Validate the Hash DATA entries
  191. //
  192. hNode = (ListEntry *)hTable;
  193. dataStart = sizeof(ListHeader) +
  194. (HashHead->m_iHashBuckets * sizeof(DWORD)) +
  195. (numNodes * sizeof(ListEntry));
  196. for (i=0;i < numNodes;i++,hNode++) {
  197. if ((hNode->m_iNext < 0) ||
  198. (hNode->m_iNext >= (INT)HashHead->m_iHashBuckets)) {
  199. printf("Invalid HASH NODE[%d] NEXT INDEX in %s, is %08x, should be < %08x\n",
  200. i,
  201. Name,
  202. hNode->m_iNext,
  203. HashHead->m_iHashBuckets);
  204. good = FALSE;
  205. }
  206. if ((hNode->m_dwData != 0) &&
  207. ((hNode->m_dwData < dataStart) ||
  208. (hNode->m_dwData >= HashHead->m_BlobHeader.m_dwMaxSize))) {
  209. printf("Invalid HASH NODE[%d] DATA INDEX in %s, is %08x, should be >= %08x and < %08x\n",
  210. i,
  211. Name,
  212. hNode->m_dwData,
  213. dataStart,
  214. HashHead->m_BlobHeader.m_dwMaxSize);
  215. good = FALSE;
  216. } else if ((hNode->m_dwData != 0) &&
  217. ((WCHAR)hNode->m_dwDataLen != *(PWCHAR)((DWORD_PTR)HashHead + hNode->m_dwData))) {
  218. printf("Invalid HASH NODE[%d] DATA LENGTH in %s, is %08x, should be %08x\n",
  219. i,
  220. Name,
  221. hNode->m_dwDataLen,
  222. *(PWCHAR)((DWORD_PTR)HashHead + hNode->m_dwData));
  223. good = FALSE;
  224. }
  225. if ((hNode->m_dwType != NODE_TYPE_UNKNOWN) &&
  226. (hNode->m_dwType != NODE_TYPE_INCLUDE) &&
  227. (hNode->m_dwType != NODE_TYPE_EXCLUDE))
  228. {
  229. printf("Invalid HASH NODE[%d] TYPE in %s, is %08x, should be %08x, %08x or %08x\n",
  230. i,
  231. Name,
  232. hNode->m_dwType,
  233. NODE_TYPE_UNKNOWN,
  234. NODE_TYPE_INCLUDE,
  235. NODE_TYPE_EXCLUDE);
  236. good = FALSE;
  237. }
  238. }
  239. return good;
  240. }
  241. BOOL
  242. VerifyTreeHeader(
  243. TreeHeader *TreeHead,
  244. PCHAR Name
  245. )
  246. /*++
  247. Routine Description:
  248. Verify that the given TREE Header is valid
  249. Arguments:
  250. Return Value:
  251. TRUE if OK else FALSE
  252. --*/
  253. {
  254. BOOL good = TRUE;
  255. DWORD calculatedSize;
  256. //
  257. // Verify BLOB header
  258. //
  259. if (!VerifyBlobHeader(&TreeHead->m_BlobHeader,Name,BLOB_TYPE_PATHTREE)) {
  260. return FALSE;
  261. }
  262. if ((TreeHead->m_dwMaxNodes != TreeHead->m_BlobHeader.m_dwEntries)) {
  263. printf("Invalid MAX NODES in %s header, is %08x, should be %08x\n",
  264. Name,
  265. TreeHead->m_dwMaxNodes,
  266. TreeHead->m_BlobHeader.m_dwEntries);
  267. good = FALSE;
  268. }
  269. if ((TreeHead->m_dwDataSize >= TreeHead->m_BlobHeader.m_dwMaxSize)) {
  270. printf("Invalid DATA SIZE in %s header, is %08x, should be < %08x\n",
  271. Name,
  272. TreeHead->m_dwDataSize,
  273. TreeHead->m_BlobHeader.m_dwMaxSize);
  274. good = FALSE;
  275. }
  276. if ((TreeHead->m_dwDataOff != TreeHead->m_BlobHeader.m_dwMaxSize)) {
  277. printf("Invalid DATA OFFSET in %s header, is %08x, should be %08x\n",
  278. Name,
  279. TreeHead->m_dwDataOff,
  280. TreeHead->m_BlobHeader.m_dwMaxSize);
  281. good = FALSE;
  282. }
  283. if ((TreeHead->m_iFreeNode != 0)) {
  284. printf("Invalid FREE NODE in %s header, is %08x, should be 0\n",
  285. Name,
  286. TreeHead->m_iFreeNode);
  287. good = FALSE;
  288. }
  289. if ((TreeHead->m_dwDefault != NODE_TYPE_EXCLUDE)) {
  290. printf("Invalid DEFAULT in %s header, is %08x, should be %08x\n",
  291. Name,
  292. TreeHead->m_dwDefault,
  293. NODE_TYPE_EXCLUDE);
  294. good = FALSE;
  295. }
  296. //
  297. // Make sure the calucalted size is accurate
  298. //
  299. calculatedSize = sizeof(TreeHeader) +
  300. (TreeHead->m_dwMaxNodes * sizeof(TreeNode)) +
  301. TreeHead->m_dwDataSize;
  302. if (calculatedSize != TreeHead->m_BlobHeader.m_dwMaxSize) {
  303. printf("Invalid CALCULATED SIZE in %s header, is %08x, should be %08x\n",
  304. Name,
  305. calculatedSize,
  306. TreeHead->m_BlobHeader.m_dwMaxSize);
  307. good = FALSE;
  308. }
  309. return good;
  310. }
  311. BOOL
  312. VerifyTree(
  313. TreeHeader *TreeHead,
  314. PCHAR Name,
  315. DWORD Offset
  316. )
  317. /*++
  318. Routine Description:
  319. Verify that the given TREE entries are valid
  320. Arguments:
  321. Return Value:
  322. TRUE if OK else FALSE
  323. --*/
  324. {
  325. BOOL good = TRUE;
  326. UINT i;
  327. DWORD dataStart;
  328. TreeNode *tn;
  329. ListHeader *localHashHead;
  330. char localName[128];
  331. //
  332. // Validate the HEADER
  333. //
  334. if (!VerifyTreeHeader(TreeHead,Name)) {
  335. return FALSE;
  336. }
  337. //
  338. // Validate the DATA entries
  339. //
  340. tn = (TreeNode *)(TreeHead + 1);
  341. dataStart = sizeof(TreeHeader) +
  342. (TreeHead->m_dwMaxNodes * sizeof(TreeNode));
  343. for (i=0;i < TreeHead->m_dwMaxNodes;i++,tn++) {
  344. if ((tn->m_iFather < 0) ||
  345. (tn->m_iFather >= (INT)TreeHead->m_dwMaxNodes))
  346. {
  347. printf("Invalid TREE NODE[%d] FATHER index in %s, is %08x, should be < %08x\n",
  348. i,
  349. Name,
  350. tn->m_iFather,
  351. TreeHead->m_dwMaxNodes);
  352. good = FALSE;
  353. }
  354. if ((tn->m_iSon < 0) ||
  355. (tn->m_iSon >= (INT)TreeHead->m_dwMaxNodes))
  356. {
  357. printf("Invalid TREE NODE[%d] SON index in %s, is %08x, should be < %08x\n",
  358. i,
  359. Name,
  360. tn->m_iSon,
  361. TreeHead->m_dwMaxNodes);
  362. good = FALSE;
  363. }
  364. if ((tn->m_iSibling < 0) ||
  365. (tn->m_iSibling >= (INT)TreeHead->m_dwMaxNodes))
  366. {
  367. printf("Invalid TREE NODE[%d] SIBLING index in %s, is %08x, should be < %08x\n",
  368. i,
  369. Name,
  370. tn->m_iSibling,
  371. TreeHead->m_dwMaxNodes);
  372. good = FALSE;
  373. }
  374. if ((tn->m_dwData < dataStart) ||
  375. (tn->m_dwData >= TreeHead->m_BlobHeader.m_dwMaxSize))
  376. {
  377. printf("Invalid TREE NODE[%d] DATA index in %s, is %08x, should be >= %08x and < %08x\n",
  378. i,
  379. Name,
  380. tn->m_dwData,
  381. dataStart,
  382. TreeHead->m_BlobHeader.m_dwMaxSize);
  383. good = FALSE;
  384. }
  385. if (tn->m_dwFileList != 0) {
  386. if ((tn->m_dwFileList < dataStart) ||
  387. (tn->m_dwFileList >= TreeHead->m_BlobHeader.m_dwMaxSize))
  388. {
  389. printf("Invalid TREE NODE[%d] FILELIST index in %s, is %08x, should be >= %08x and < %08x\n",
  390. i,
  391. Name,
  392. tn->m_dwData,
  393. dataStart,
  394. TreeHead->m_BlobHeader.m_dwMaxSize);
  395. good = FALSE;
  396. } else {
  397. localHashHead = (ListHeader *)((DWORD_PTR)TreeHead + tn->m_dwFileList);
  398. sprintf(localName,"TreeNode[%d]",i);
  399. if (!VerifyHash(localHashHead,localName,(Offset+tn->m_dwFileList))) {
  400. good = FALSE;
  401. }
  402. }
  403. }
  404. if ((tn->m_dwType != NODE_TYPE_UNKNOWN) &&
  405. (tn->m_dwType != NODE_TYPE_INCLUDE) &&
  406. (tn->m_dwType != NODE_TYPE_EXCLUDE))
  407. {
  408. printf("Invalid TREE NODE[%d] TYPE in %s, is %08x, should be %08x, %08x or %08x\n",
  409. i,
  410. Name,
  411. tn->m_dwType,
  412. NODE_TYPE_UNKNOWN,
  413. NODE_TYPE_INCLUDE,
  414. NODE_TYPE_EXCLUDE);
  415. good = FALSE;
  416. }
  417. }
  418. return good;
  419. }
  420. BOOL
  421. VerifyBlob(
  422. DWORD_PTR Blob
  423. )
  424. /*++
  425. Routine Description:
  426. Verify that the given BLOB is valid
  427. Arguments:
  428. Return Value:
  429. TRUE if OK else FALSE
  430. --*/
  431. {
  432. BlobHeader *blobHead;
  433. TreeHeader *treeHead;
  434. ListHeader *hashHead;
  435. DWORD calculatedSize = 0;
  436. //
  437. // Verify header to entire blob
  438. //
  439. blobHead = (BlobHeader *)Blob;
  440. if (!VerifyBlobHeader(blobHead,"PRIMARY",BLOB_TYPE_CONTAINER)) {
  441. return FALSE;
  442. }
  443. calculatedSize += sizeof(BlobHeader);
  444. //
  445. // Verify TreeHeader and Data
  446. //
  447. treeHead = (TreeHeader *)(Blob + calculatedSize);
  448. if (!VerifyTree(treeHead,"PRIMARY TREE",calculatedSize)) {
  449. return FALSE;
  450. }
  451. calculatedSize += treeHead->m_BlobHeader.m_dwMaxSize;
  452. //
  453. // Verify HashHeader and DATA
  454. //
  455. hashHead = (ListHeader *)(Blob + calculatedSize);
  456. if (!VerifyHash(hashHead,"PRIMARY HASH",calculatedSize)) {
  457. return FALSE;
  458. }
  459. calculatedSize += hashHead->m_BlobHeader.m_dwMaxSize;
  460. //
  461. // Validate total SIZE
  462. //
  463. if (calculatedSize != blobHead->m_dwMaxSize) {
  464. printf("Invalid PRIMARY BLOB size, is %08x, calculated to be %08x\n",
  465. blobHead->m_dwMaxSize,
  466. calculatedSize);
  467. return FALSE;
  468. }
  469. return TRUE;
  470. }