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.

731 lines
18 KiB

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