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.

986 lines
32 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. SafeIdep.c (WinSAFER Identify Objects privates)
  5. Abstract:
  6. This module implements the WinSAFER APIs that loads the names (and
  7. high-level information) of all Authorization Levels defined within
  8. a given registry context. The list of available levels is loaded
  9. into a Rtl Generic Table that can be enumerated and accessed using
  10. conventional Rtl Generic Table techniques.
  11. Author:
  12. Jeffrey Lawson (JLawson) - Nov 1999
  13. Environment:
  14. User mode only.
  15. Exported Functions:
  16. CodeAuthzLevelObjpInitializeTable
  17. CodeAuthzLevelObjpLoadTable
  18. CodeAuthzLevelObjpEntireTableFree
  19. Revision History:
  20. Created - Nov 1999
  21. --*/
  22. #include "pch.h"
  23. #pragma hdrstop
  24. #include <winsafer.h>
  25. #include <winsaferp.h>
  26. #include "saferp.h"
  27. PVOID NTAPI
  28. SaferpGenericTableAllocate (
  29. IN PRTL_GENERIC_TABLE Table,
  30. IN CLONG ByteSize
  31. )
  32. /*++
  33. Routine Description:
  34. Internal callback for the generic table implementation.
  35. This function allocates memory for a new entry in a GENERIC_TABLE
  36. Arguments:
  37. Table - pointer to the Generic Table structure
  38. ByteSize - the size, in bytes, of the structure to allocate
  39. Return Value:
  40. Pointer to the allocated space.
  41. --*/
  42. {
  43. UNREFERENCED_PARAMETER(Table);
  44. return (PVOID) RtlAllocateHeap(RtlProcessHeap(), 0, ByteSize);
  45. }
  46. VOID NTAPI
  47. SaferpGenericTableFree (
  48. IN PRTL_GENERIC_TABLE Table,
  49. IN PVOID Buffer
  50. )
  51. /*++
  52. Routine Description:
  53. Internal callback for the generic table implementation.
  54. This function frees the space used by a GENERIC_TABLE entry.
  55. Arguments:
  56. Table - pointer to the Generic Table structure
  57. Buffer - pointer to the space to deallocate.
  58. Return Value:
  59. None.
  60. --*/
  61. {
  62. UNREFERENCED_PARAMETER(Table);
  63. ASSERT(Buffer != NULL);
  64. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) Buffer);
  65. }
  66. RTL_GENERIC_COMPARE_RESULTS NTAPI
  67. SaferpGuidIdentsTableCompare (
  68. IN PRTL_GENERIC_TABLE Table,
  69. IN PVOID FirstStruct,
  70. IN PVOID SecondStruct
  71. )
  72. /*++
  73. Routine Description:
  74. Arguments:
  75. Return Value:
  76. --*/
  77. {
  78. PAUTHZIDENTSTABLERECORD FirstObj = (PAUTHZIDENTSTABLERECORD) FirstStruct;
  79. PAUTHZIDENTSTABLERECORD SecondObj = (PAUTHZIDENTSTABLERECORD) SecondStruct;
  80. int result;
  81. UNREFERENCED_PARAMETER(Table);
  82. // Explicitly handle null parameters as wildcards, allowing them
  83. // to match anything. We use this for quick deletion of the table.
  84. if (FirstStruct == NULL || SecondStruct == NULL)
  85. return GenericEqual;
  86. // Compare ascending by guid.
  87. result = memcmp(&FirstObj->IdentGuid,
  88. &SecondObj->IdentGuid, sizeof(GUID));
  89. if ( result < 0 )
  90. return GenericLessThan;
  91. else if ( result > 0 )
  92. return GenericGreaterThan;
  93. else
  94. return GenericEqual;
  95. }
  96. VOID NTAPI
  97. CodeAuthzGuidIdentsInitializeTable(
  98. IN OUT PRTL_GENERIC_TABLE pAuthzObjTable
  99. )
  100. /*++
  101. Routine Description:
  102. Arguments:
  103. pAuthzObjTable - pointer to the generic table structure to initialize.
  104. Return Value:
  105. Does not return a value.
  106. --*/
  107. {
  108. RtlInitializeGenericTable(
  109. pAuthzObjTable,
  110. (PRTL_GENERIC_COMPARE_ROUTINE) SaferpGuidIdentsTableCompare,
  111. (PRTL_GENERIC_ALLOCATE_ROUTINE) SaferpGenericTableAllocate,
  112. (PRTL_GENERIC_FREE_ROUTINE) SaferpGenericTableFree,
  113. NULL);
  114. }
  115. NTSTATUS NTAPI
  116. SaferpGuidIdentsLoadTable (
  117. IN OUT PRTL_GENERIC_TABLE pAuthzIdentTable,
  118. IN DWORD dwScopeId,
  119. IN HANDLE hKeyCustomBase,
  120. IN DWORD dwLevelId,
  121. IN SAFER_IDENTIFICATION_TYPES dwIdentityType
  122. )
  123. /*++
  124. Routine Description:
  125. Loads all Code Identities of a particular fragment type and which
  126. map to a specific LevelId value.
  127. Arguments:
  128. pAuthzIdentTable - specifies the table into which the new Code Identity
  129. records should be inserted.
  130. dwScopeId - can be AUTHZSCOPEID_USER, AUTHZSCOPEID_MACHINE, or
  131. AUTHSCOPEID_REGISTRY.
  132. hKeyCustomBase - used only if dwScopeId is AUTHZSCOPEID_REGISTRY.
  133. dwLevelId - specifies the LevelId for which identities should
  134. be loaded.
  135. dwIdentityType - specifies the type of identity to load.
  136. This can be SaferIdentityTypeImageName, SaferIdentityTypeImageHash,
  137. or SaferIdentityTypeUrlZone.
  138. Return Value:
  139. Returns STATUS_SUCCESS if no error occurs.
  140. --*/
  141. {
  142. DWORD dwIndex;
  143. NTSTATUS Status;
  144. HANDLE hKeyIdentityBase = NULL;
  145. HANDLE hKeyThisIdentity = NULL;
  146. PUCHAR LocalBuffer = NULL;
  147. DWORD Size = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
  148. LocalBuffer = (PUCHAR) RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  149. if (LocalBuffer == NULL)
  150. {
  151. return STATUS_NO_MEMORY;
  152. }
  153. //
  154. // We were given the key to the root of the policy storage,
  155. // so we need to open the subkey that contains the Identities.
  156. //
  157. {
  158. WCHAR szPathSuffix[MAX_PATH];
  159. WCHAR szDigits[20];
  160. UNICODE_STRING UnicodePathSuffix;
  161. UNICODE_STRING UnicodeDigits;
  162. UnicodePathSuffix.Buffer = szPathSuffix;
  163. UnicodePathSuffix.Length = 0;
  164. UnicodePathSuffix.MaximumLength = sizeof(szPathSuffix);
  165. UnicodeDigits.Buffer = szDigits;
  166. UnicodeDigits.Length = 0;
  167. UnicodeDigits.MaximumLength = sizeof(szDigits);
  168. Status = RtlAppendUnicodeToString(
  169. &UnicodePathSuffix,
  170. SAFER_CODEIDS_REGSUBKEY L"\\");
  171. if (!NT_SUCCESS(Status))
  172. {
  173. goto Cleanup;
  174. }
  175. Status = RtlIntegerToUnicodeString(
  176. dwLevelId, 10, &UnicodeDigits);
  177. if (!NT_SUCCESS(Status))
  178. {
  179. goto Cleanup;
  180. }
  181. Status = RtlAppendUnicodeStringToString(
  182. &UnicodePathSuffix, &UnicodeDigits);
  183. if (!NT_SUCCESS(Status))
  184. {
  185. goto Cleanup;
  186. }
  187. switch (dwIdentityType)
  188. {
  189. case SaferIdentityTypeImageName:
  190. Status = RtlAppendUnicodeToString(
  191. &UnicodePathSuffix, L"\\" SAFER_PATHS_REGSUBKEY);
  192. break;
  193. case SaferIdentityTypeImageHash:
  194. Status = RtlAppendUnicodeToString(
  195. &UnicodePathSuffix, L"\\" SAFER_HASHMD5_REGSUBKEY);
  196. break;
  197. case SaferIdentityTypeUrlZone:
  198. Status = RtlAppendUnicodeToString(
  199. &UnicodePathSuffix, L"\\" SAFER_SOURCEURL_REGSUBKEY);
  200. break;
  201. default:
  202. Status = STATUS_INVALID_PARAMETER;
  203. break;
  204. }
  205. if (!NT_SUCCESS(Status))
  206. {
  207. goto Cleanup;
  208. }
  209. ASSERT(UnicodePathSuffix.Buffer[ UnicodePathSuffix.Length /
  210. sizeof(WCHAR) ] == UNICODE_NULL);
  211. Status = CodeAuthzpOpenPolicyRootKey(
  212. dwScopeId,
  213. hKeyCustomBase,
  214. UnicodePathSuffix.Buffer,
  215. KEY_READ,
  216. FALSE,
  217. &hKeyIdentityBase);
  218. if (!NT_SUCCESS(Status))
  219. {
  220. goto Cleanup;
  221. }
  222. }
  223. //
  224. // Iterate through all subkeys under this branch.
  225. //
  226. for (dwIndex = 0; ; dwIndex++)
  227. {
  228. DWORD dwLength;
  229. OBJECT_ATTRIBUTES ObjectAttributes;
  230. AUTHZIDENTSTABLERECORD AuthzIdentsRec;
  231. PKEY_BASIC_INFORMATION pBasicInformation =
  232. (PKEY_BASIC_INFORMATION) LocalBuffer;
  233. PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 pPartialInformation =
  234. (PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64) LocalBuffer;
  235. UNICODE_STRING ValueName;
  236. UNICODE_STRING UnicodeKeyname;
  237. //
  238. // Find the next Identity GUID that we will check.
  239. //
  240. Status = NtEnumerateKey(hKeyIdentityBase,
  241. dwIndex,
  242. KeyBasicInformation,
  243. pBasicInformation,
  244. Size,
  245. &dwLength);
  246. if (!NT_SUCCESS(Status)) {
  247. //
  248. // If this one key was too large to fit in our query buffer
  249. // then simply skip over it and try enumerating the next one.
  250. //
  251. if (Status == STATUS_BUFFER_OVERFLOW) {
  252. //
  253. // Reallocate and retry.
  254. //
  255. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) LocalBuffer);
  256. Size = dwLength;
  257. LocalBuffer = (PUCHAR) RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  258. if (LocalBuffer == NULL)
  259. {
  260. Status = STATUS_NO_MEMORY;
  261. goto Cleanup;
  262. }
  263. pBasicInformation = (PKEY_BASIC_INFORMATION) LocalBuffer;
  264. pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64) LocalBuffer;
  265. Status = NtEnumerateKey(hKeyIdentityBase,
  266. dwIndex,
  267. KeyBasicInformation,
  268. pBasicInformation,
  269. Size,
  270. &dwLength);
  271. if (!NT_SUCCESS(Status)) {
  272. break;
  273. }
  274. } else {
  275. break;
  276. }
  277. }
  278. UnicodeKeyname.Buffer = pBasicInformation->Name;
  279. UnicodeKeyname.MaximumLength = UnicodeKeyname.Length =
  280. (USHORT) pBasicInformation->NameLength;
  281. //
  282. // Translate the keyname (which we expect to be a GUID).
  283. //
  284. RtlZeroMemory(&AuthzIdentsRec, sizeof(AUTHZIDENTSTABLERECORD));
  285. Status = RtlGUIDFromString(&UnicodeKeyname,
  286. &AuthzIdentsRec.IdentGuid);
  287. if (!NT_SUCCESS(Status) ||
  288. IsZeroGUID(&AuthzIdentsRec.IdentGuid)) {
  289. // the keyname was apparently not numeric.
  290. continue;
  291. }
  292. AuthzIdentsRec.dwScopeId = dwScopeId;
  293. AuthzIdentsRec.dwLevelId = dwLevelId;
  294. AuthzIdentsRec.dwIdentityType = dwIdentityType;
  295. if (RtlLookupElementGenericTable(
  296. pAuthzIdentTable, (PVOID) &AuthzIdentsRec) != NULL) {
  297. // this identity GUID happens to have already been found.
  298. continue;
  299. }
  300. //
  301. // Try to open a handle to that Identity GUID.
  302. //
  303. InitializeObjectAttributes(&ObjectAttributes,
  304. &UnicodeKeyname,
  305. OBJ_CASE_INSENSITIVE,
  306. hKeyIdentityBase,
  307. NULL
  308. );
  309. Status = NtOpenKey(&hKeyThisIdentity,
  310. KEY_READ,
  311. &ObjectAttributes);
  312. if (!NT_SUCCESS(Status)) {
  313. // If we failed to open it, skip to the next one.
  314. break;
  315. }
  316. //
  317. // Add the new record into our table.
  318. //
  319. switch (dwIdentityType) {
  320. // --------------------
  321. case SaferIdentityTypeImageName:
  322. //
  323. // Read the image path.
  324. //
  325. RtlInitUnicodeString(
  326. &ValueName, SAFER_IDS_ITEMDATA_REGVALUE);
  327. Status = NtQueryValueKey(hKeyThisIdentity,
  328. &ValueName,
  329. KeyValuePartialInformationAlign64,
  330. pPartialInformation,
  331. Size,
  332. &dwLength);
  333. if (!NT_SUCCESS(Status)) {
  334. if (Status == STATUS_BUFFER_OVERFLOW) {
  335. //
  336. // Reallocate and retry.
  337. //
  338. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) LocalBuffer);
  339. Size = dwLength;
  340. LocalBuffer = (PUCHAR) RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  341. if (LocalBuffer == NULL)
  342. {
  343. Status = STATUS_NO_MEMORY;
  344. goto Cleanup;
  345. }
  346. pBasicInformation = (PKEY_BASIC_INFORMATION) LocalBuffer;
  347. pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64) LocalBuffer;
  348. Status = NtQueryValueKey(hKeyThisIdentity,
  349. &ValueName,
  350. KeyValuePartialInformationAlign64,
  351. pPartialInformation,
  352. Size,
  353. &dwLength);
  354. if (!NT_SUCCESS(Status)) {
  355. break;
  356. }
  357. } else {
  358. break;
  359. }
  360. }
  361. if (pPartialInformation->Type == REG_SZ ||
  362. pPartialInformation->Type == REG_EXPAND_SZ) {
  363. AuthzIdentsRec.ImageNameInfo.bExpandVars =
  364. (pPartialInformation->Type == REG_EXPAND_SZ);
  365. Status = RtlCreateUnicodeString(
  366. &AuthzIdentsRec.ImageNameInfo.ImagePath,
  367. (LPCWSTR) pPartialInformation->Data);
  368. if (!NT_SUCCESS(Status)) {
  369. break;
  370. }
  371. } else {
  372. Status = STATUS_UNSUCCESSFUL;
  373. break;
  374. }
  375. //
  376. // Read the extra WinSafer flags.
  377. //
  378. RtlInitUnicodeString(&ValueName,
  379. SAFER_IDS_SAFERFLAGS_REGVALUE);
  380. Status = NtQueryValueKey(hKeyThisIdentity,
  381. &ValueName,
  382. KeyValuePartialInformationAlign64,
  383. pPartialInformation,
  384. Size,
  385. &dwLength);
  386. if (NT_SUCCESS(Status) &&
  387. pPartialInformation->Type == REG_DWORD &&
  388. pPartialInformation->DataLength == sizeof(DWORD)) {
  389. AuthzIdentsRec.ImageNameInfo.dwSaferFlags =
  390. (*(PDWORD) pPartialInformation->Data);
  391. } else {
  392. // default the flags if they are missing.
  393. AuthzIdentsRec.ImageNameInfo.dwSaferFlags = 0;
  394. Status = STATUS_SUCCESS;
  395. }
  396. break;
  397. // --------------------
  398. case SaferIdentityTypeImageHash:
  399. //
  400. // Read the hash data and hash size.
  401. //
  402. RtlInitUnicodeString(&ValueName,
  403. SAFER_IDS_ITEMDATA_REGVALUE);
  404. Status = NtQueryValueKey(hKeyThisIdentity,
  405. &ValueName,
  406. KeyValuePartialInformationAlign64,
  407. pPartialInformation,
  408. Size,
  409. &dwLength);
  410. if (!NT_SUCCESS(Status)) {
  411. if (Status == STATUS_BUFFER_OVERFLOW) {
  412. //
  413. // Reallocate and retry.
  414. //
  415. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) LocalBuffer);
  416. Size = dwLength;
  417. LocalBuffer = (PUCHAR) RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  418. if (LocalBuffer == NULL)
  419. {
  420. Status = STATUS_NO_MEMORY;
  421. goto Cleanup;
  422. }
  423. pBasicInformation = (PKEY_BASIC_INFORMATION) LocalBuffer;
  424. pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64) LocalBuffer;
  425. Status = NtQueryValueKey(hKeyThisIdentity,
  426. &ValueName,
  427. KeyValuePartialInformationAlign64,
  428. pPartialInformation,
  429. Size,
  430. &dwLength);
  431. if (!NT_SUCCESS(Status)) {
  432. break;
  433. }
  434. } else {
  435. break;
  436. }
  437. }
  438. if (pPartialInformation->Type == REG_BINARY &&
  439. pPartialInformation->DataLength > 0 &&
  440. pPartialInformation->DataLength <= SAFER_MAX_HASH_SIZE) {
  441. AuthzIdentsRec.ImageHashInfo.HashSize =
  442. pPartialInformation->DataLength;
  443. RtlCopyMemory(&AuthzIdentsRec.ImageHashInfo.ImageHash[0],
  444. pPartialInformation->Data,
  445. pPartialInformation->DataLength);
  446. } else {
  447. Status = STATUS_UNSUCCESSFUL;
  448. break;
  449. }
  450. //
  451. // Read the algorithm used to compute the hash.
  452. //
  453. RtlInitUnicodeString(&ValueName,
  454. SAFER_IDS_HASHALG_REGVALUE);
  455. Status = NtQueryValueKey(hKeyThisIdentity,
  456. &ValueName,
  457. KeyValuePartialInformationAlign64,
  458. pPartialInformation,
  459. Size,
  460. &dwLength);
  461. if (!NT_SUCCESS(Status)) {
  462. break;
  463. }
  464. if (pPartialInformation->Type == REG_DWORD &&
  465. pPartialInformation->DataLength == sizeof(DWORD)) {
  466. AuthzIdentsRec.ImageHashInfo.HashAlgorithm =
  467. *((PDWORD) pPartialInformation->Data);
  468. } else {
  469. Status = STATUS_UNSUCCESSFUL;
  470. break;
  471. }
  472. if ((AuthzIdentsRec.ImageHashInfo.HashAlgorithm &
  473. ALG_CLASS_ALL) != ALG_CLASS_HASH) {
  474. Status = STATUS_UNSUCCESSFUL;
  475. break;
  476. }
  477. //
  478. // Read the original image size.
  479. //
  480. RtlInitUnicodeString(&ValueName,
  481. SAFER_IDS_ITEMSIZE_REGVALUE);
  482. Status = NtQueryValueKey(hKeyThisIdentity,
  483. &ValueName,
  484. KeyValuePartialInformationAlign64,
  485. pPartialInformation,
  486. Size,
  487. &dwLength);
  488. if (!NT_SUCCESS(Status)) {
  489. if (Status == STATUS_BUFFER_OVERFLOW) {
  490. //
  491. // Reallocate and retry.
  492. //
  493. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) LocalBuffer);
  494. Size = dwLength;
  495. LocalBuffer = (PUCHAR) RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  496. if (LocalBuffer == NULL)
  497. {
  498. Status = STATUS_NO_MEMORY;
  499. goto Cleanup;
  500. }
  501. pBasicInformation = (PKEY_BASIC_INFORMATION) LocalBuffer;
  502. pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64) LocalBuffer;
  503. Status = NtQueryValueKey(hKeyThisIdentity,
  504. &ValueName,
  505. KeyValuePartialInformationAlign64,
  506. pPartialInformation,
  507. Size,
  508. &dwLength);
  509. if (!NT_SUCCESS(Status)) {
  510. break;
  511. }
  512. } else {
  513. break;
  514. }
  515. }
  516. if (pPartialInformation->Type == REG_DWORD &&
  517. pPartialInformation->DataLength == sizeof(DWORD)) {
  518. AuthzIdentsRec.ImageHashInfo.ImageSize.LowPart =
  519. *((PDWORD) pPartialInformation->Data);
  520. AuthzIdentsRec.ImageHashInfo.ImageSize.HighPart = 0;
  521. } else if (pPartialInformation->Type == REG_QWORD &&
  522. pPartialInformation->DataLength == 2 * sizeof(DWORD) ) {
  523. AuthzIdentsRec.ImageHashInfo.ImageSize.QuadPart =
  524. ((PLARGE_INTEGER) pPartialInformation->Data)->QuadPart;
  525. } else {
  526. Status = STATUS_UNSUCCESSFUL;
  527. break;
  528. }
  529. //
  530. // Read the extra WinSafer flags.
  531. //
  532. RtlInitUnicodeString(&ValueName,
  533. SAFER_IDS_SAFERFLAGS_REGVALUE);
  534. Status = NtQueryValueKey(hKeyThisIdentity,
  535. &ValueName,
  536. KeyValuePartialInformationAlign64,
  537. pPartialInformation,
  538. Size,
  539. &dwLength);
  540. if (NT_SUCCESS(Status) &&
  541. pPartialInformation->Type == REG_DWORD &&
  542. pPartialInformation->DataLength == sizeof(DWORD)) {
  543. #ifdef SAFER_POLICY_ONLY_EXES
  544. AuthzIdentsRec.ImageHashInfo.dwSaferFlags =
  545. (*((PDWORD) pPartialInformation->Data)) &
  546. ~SAFER_POLICY_ONLY_EXES;
  547. #else
  548. AuthzIdentsRec.ImageHashInfo.dwSaferFlags =
  549. (*((PDWORD) pPartialInformation->Data));
  550. #endif
  551. } else {
  552. // default the flags if they are missing.
  553. AuthzIdentsRec.ImageHashInfo.dwSaferFlags = 0;
  554. Status = STATUS_SUCCESS;
  555. }
  556. break;
  557. // --------------------
  558. case SaferIdentityTypeUrlZone:
  559. //
  560. // Read the zone identifier.
  561. //
  562. RtlInitUnicodeString(&ValueName,
  563. SAFER_IDS_ITEMDATA_REGVALUE);
  564. Status = NtQueryValueKey(hKeyThisIdentity,
  565. &ValueName,
  566. KeyValuePartialInformationAlign64,
  567. pPartialInformation,
  568. Size,
  569. &dwLength);
  570. if (!NT_SUCCESS(Status)) {
  571. if (Status == STATUS_BUFFER_OVERFLOW) {
  572. //
  573. // Reallocate and retry.
  574. //
  575. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) LocalBuffer);
  576. Size = dwLength;
  577. LocalBuffer = (PUCHAR) RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  578. if (LocalBuffer == NULL)
  579. {
  580. Status = STATUS_NO_MEMORY;
  581. goto Cleanup;
  582. }
  583. pBasicInformation = (PKEY_BASIC_INFORMATION) LocalBuffer;
  584. pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64) LocalBuffer;
  585. Status = NtQueryValueKey(hKeyThisIdentity,
  586. &ValueName,
  587. KeyValuePartialInformationAlign64,
  588. pPartialInformation,
  589. Size,
  590. &dwLength);
  591. if (!NT_SUCCESS(Status)) {
  592. break;
  593. }
  594. } else {
  595. break;
  596. }
  597. }
  598. if (pPartialInformation->Type == REG_DWORD &&
  599. pPartialInformation->DataLength == sizeof(DWORD)) {
  600. AuthzIdentsRec.ImageZone.UrlZoneId =
  601. * (PDWORD) pPartialInformation->Data;
  602. } else {
  603. Status = STATUS_UNSUCCESSFUL;
  604. break;
  605. }
  606. //
  607. // Read the extra WinSafer flags.
  608. //
  609. RtlInitUnicodeString(&ValueName,
  610. SAFER_IDS_SAFERFLAGS_REGVALUE);
  611. Status = NtQueryValueKey(hKeyThisIdentity,
  612. &ValueName,
  613. KeyValuePartialInformationAlign64,
  614. pPartialInformation,
  615. Size,
  616. &dwLength);
  617. if (NT_SUCCESS(Status) &&
  618. pPartialInformation->Type == REG_DWORD &&
  619. pPartialInformation->DataLength == sizeof(DWORD)) {
  620. #ifdef SAFER_POLICY_ONLY_EXES
  621. AuthzIdentsRec.ImageZone.dwSaferFlags =
  622. (*(PDWORD) pPartialInformation->Data) &
  623. ~SAFER_POLICY_ONLY_EXES;
  624. #else
  625. AuthzIdentsRec.ImageZone.dwSaferFlags =
  626. (*(PDWORD) pPartialInformation->Data);
  627. #endif
  628. } else {
  629. // default the flags if they are missing.
  630. AuthzIdentsRec.ImageZone.dwSaferFlags = 0;
  631. Status = STATUS_SUCCESS;
  632. }
  633. break;
  634. // --------------------
  635. default:
  636. ASSERT(0 && "unexpected identity type");
  637. Status = STATUS_INVALID_INFO_CLASS;
  638. }
  639. // Only insert the record if we don't have
  640. // any other entries with this same GUID.
  641. if (NT_SUCCESS(Status)) {
  642. RtlInsertElementGenericTable(
  643. pAuthzIdentTable,
  644. (PVOID) &AuthzIdentsRec,
  645. sizeof(AUTHZIDENTSTABLERECORD),
  646. NULL);
  647. }
  648. NtClose(hKeyThisIdentity);
  649. hKeyThisIdentity = NULL;
  650. }
  651. Cleanup:
  652. if (hKeyThisIdentity != NULL) {
  653. NtClose(hKeyThisIdentity);
  654. }
  655. if (hKeyIdentityBase != NULL) {
  656. NtClose(hKeyIdentityBase);
  657. }
  658. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) LocalBuffer);
  659. return Status;
  660. }
  661. NTSTATUS NTAPI
  662. CodeAuthzGuidIdentsLoadTableAll (
  663. IN PRTL_GENERIC_TABLE pAuthzLevelTable,
  664. IN OUT PRTL_GENERIC_TABLE pAuthzIdentTable,
  665. IN DWORD dwScopeId,
  666. IN HANDLE hKeyCustomBase
  667. )
  668. /*++
  669. Routine Description:
  670. Arguments:
  671. pAuthzLevelTable - specifies the table that has already been
  672. loaded with the WinSafer Levels that should be allowed.
  673. These Levels do not necessarily need to have been loaded
  674. from the same scope from which the Code Identities are
  675. being loaded from.
  676. pAuthzIdentTable - specifies the table into which the loaded
  677. Code Identities should be inserted.
  678. dwScopeId - scope from where the Code Identities should be loaded from.
  679. This may be AUTHZSCOPEID_MACHINE, AUTHZSCOPEID_USER, or
  680. AUTHZSCOPEID_REGISTRY.
  681. hKeyCustomBase - only used if dwScopeId was AUTHZSCOPEID_REGISTRY.
  682. Return Value:
  683. Returns STATUS_SUCCESS if no errors occurred.
  684. --*/
  685. {
  686. NTSTATUS Status;
  687. NTSTATUS WorstStatus = STATUS_SUCCESS;
  688. PVOID RestartKey;
  689. PAUTHZLEVELTABLERECORD pAuthzLevelRecord;
  690. //
  691. // Enumerate through all records and close the registry handles.
  692. //
  693. RestartKey = NULL;
  694. for (pAuthzLevelRecord = (PAUTHZLEVELTABLERECORD)
  695. RtlEnumerateGenericTableWithoutSplaying(
  696. pAuthzLevelTable, &RestartKey);
  697. pAuthzLevelRecord != NULL;
  698. pAuthzLevelRecord = (PAUTHZLEVELTABLERECORD)
  699. RtlEnumerateGenericTableWithoutSplaying(
  700. pAuthzLevelTable, &RestartKey)
  701. )
  702. {
  703. Status = SaferpGuidIdentsLoadTable(
  704. pAuthzIdentTable,
  705. dwScopeId,
  706. hKeyCustomBase,
  707. pAuthzLevelRecord->dwLevelId,
  708. SaferIdentityTypeImageName);
  709. if (!NT_SUCCESS(Status))
  710. WorstStatus = Status;
  711. Status = SaferpGuidIdentsLoadTable(
  712. pAuthzIdentTable,
  713. dwScopeId,
  714. hKeyCustomBase,
  715. pAuthzLevelRecord->dwLevelId,
  716. SaferIdentityTypeImageHash);
  717. if (!NT_SUCCESS(Status))
  718. WorstStatus = Status;
  719. Status = SaferpGuidIdentsLoadTable(
  720. pAuthzIdentTable,
  721. dwScopeId,
  722. hKeyCustomBase,
  723. pAuthzLevelRecord->dwLevelId,
  724. SaferIdentityTypeUrlZone);
  725. if (!NT_SUCCESS(Status))
  726. WorstStatus = Status;
  727. }
  728. return WorstStatus;
  729. }
  730. VOID NTAPI
  731. CodeAuthzGuidIdentsEntireTableFree (
  732. IN OUT PRTL_GENERIC_TABLE pAuthzIdentTable
  733. )
  734. /*++
  735. Routine Description:
  736. Frees the allocated memory associated with all of the entries
  737. currently within a Code Identities table. Once the table has
  738. been emptied, it may immediately be filled again without any
  739. other initialization necessary.
  740. Arguments:
  741. pAuthzIdentTable - pointer to the table that should be cleared.
  742. Return Value:
  743. Does not return any value.
  744. --*/
  745. {
  746. ULONG NumElements;
  747. //
  748. // Now iterate through the table again and free all of the
  749. // elements themselves.
  750. //
  751. NumElements = RtlNumberGenericTableElements(pAuthzIdentTable);
  752. while ( NumElements-- > 0 ) {
  753. // Delete all elements. Note that we pass NULL as the element
  754. // to delete because our compare function is smart enough to
  755. // allow treatment of NULL as a wildcard element.
  756. BOOL retval = RtlDeleteElementGenericTable( pAuthzIdentTable, NULL);
  757. ASSERT(retval == TRUE);
  758. }
  759. }
  760. PAUTHZIDENTSTABLERECORD NTAPI
  761. CodeAuthzIdentsLookupByGuid (
  762. IN PRTL_GENERIC_TABLE pAuthzIdentTable,
  763. IN REFGUID pIdentGuid
  764. )
  765. /*++
  766. Routine Description:
  767. This function searches for an identity within a GENERIC_TABLE.
  768. Arguments:
  769. pAuthzIdentTable - pointer to the Generic Table structure
  770. pIdentGuid -
  771. Return Value:
  772. Returns a pointer to the Code Identity record if the GUID
  773. specified was found. Otherwise NULL is returned.
  774. --*/
  775. {
  776. AUTHZIDENTSTABLERECORD AuthzIdentsRec;
  777. RtlCopyMemory(&AuthzIdentsRec.IdentGuid, pIdentGuid, sizeof(GUID));
  778. return (PAUTHZIDENTSTABLERECORD)
  779. RtlLookupElementGenericTable(pAuthzIdentTable,
  780. (PVOID) &AuthzIdentsRec);
  781. }