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.

8469 lines
310 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. cttoken.c
  5. Abstract:
  6. Common token object test routines.
  7. These routines are used in both kernel and user mode tests.
  8. This test assumes the security runtime library routines are
  9. functioning correctly.
  10. NOTE: This test program allocates a lot of memory and frees
  11. none of it ! ! !
  12. Author:
  13. Jim Kelly (JimK) 27-June-1990
  14. Environment:
  15. Test of token object.
  16. Revision History:
  17. --*/
  18. #include "tsecomm.c" // Mode dependent macros and routines.
  19. ////////////////////////////////////////////////////////////////
  20. // //
  21. // Module wide variables //
  22. // //
  23. ////////////////////////////////////////////////////////////////
  24. #define DEFAULT_DACL_LENGTH (1024L)
  25. #define GROUP_IDS_LENGTH (1024L)
  26. #define NEW_GROUP_STATE_LENGTH (1024L)
  27. #define PRIVILEGES_LENGTH (128L)
  28. #define TOO_BIG_ACL_SIZE (2048L)
  29. #define TOO_BIG_PRIMARY_GROUP_SIZE (39L)
  30. //
  31. // definitions related to TokenWithGroups
  32. // (we also substitute SYSTEM for NEANDERTHOL in some tests)
  33. //
  34. #define FLINTSTONE_INDEX (0L)
  35. #define CHILD_INDEX (1L)
  36. #define NEANDERTHOL_INDEX (2L)
  37. #define SYSTEM_INDEX (2L)
  38. #define WORLD_INDEX (3L)
  39. #define GROUP_COUNT (4L)
  40. #define RESTRICTED_SID_COUNT (2L)
  41. //
  42. // Definitions related to TokenWithPrivileges
  43. //
  44. #define UNSOLICITED_INDEX (0L)
  45. #define SECURITY_INDEX (1L)
  46. #define ASSIGN_PRIMARY_INDEX (2L)
  47. #define PRIVILEGE_COUNT (3L)
  48. NTSTATUS Status;
  49. HANDLE SimpleToken;
  50. HANDLE TokenWithGroups;
  51. HANDLE TokenWithDefaultOwner;
  52. HANDLE TokenWithPrivileges;
  53. HANDLE TokenWithDefaultDacl;
  54. HANDLE TokenWithRestrictedGroups;
  55. HANDLE TokenWithRestrictedPrivileges;
  56. HANDLE TokenWithRestrictedSids;
  57. HANDLE TokenWithMoreRestrictedSids;
  58. HANDLE Token;
  59. HANDLE ProcessToken;
  60. HANDLE ImpersonationToken;
  61. HANDLE AnonymousToken;
  62. OBJECT_ATTRIBUTES PrimaryTokenAttributes;
  63. PSECURITY_DESCRIPTOR PrimarySecurityDescriptor;
  64. SECURITY_QUALITY_OF_SERVICE PrimarySecurityQos;
  65. OBJECT_ATTRIBUTES ImpersonationTokenAttributes;
  66. PSECURITY_DESCRIPTOR ImpersonationSecurityDescriptor;
  67. SECURITY_QUALITY_OF_SERVICE ImpersonationSecurityQos;
  68. OBJECT_ATTRIBUTES AnonymousTokenAttributes;
  69. PSECURITY_DESCRIPTOR AnonymousSecurityDescriptor;
  70. SECURITY_QUALITY_OF_SERVICE AnonymousSecurityQos;
  71. ULONG DisabledGroupAttributes;
  72. ULONG OptionalGroupAttributes;
  73. ULONG NormalGroupAttributes;
  74. ULONG OwnerGroupAttributes;
  75. ULONG LengthAvailable;
  76. ULONG CurrentLength;
  77. TIME_FIELDS TempTimeFields = {3000, 1, 1, 1, 1, 1, 1, 1};
  78. LARGE_INTEGER NoExpiration;
  79. LUID BadAuthenticationId;
  80. LUID SystemAuthenticationId = SYSTEM_LUID;
  81. LUID OriginalAuthenticationId;
  82. TOKEN_SOURCE TestSource = {"SE: TEST", 0};
  83. PSID Owner;
  84. PSID Group;
  85. PACL Dacl;
  86. PSID TempOwner;
  87. PSID TempGroup;
  88. PACL TempDacl;
  89. UQUAD ThreadStack[256];
  90. INITIAL_TEB InitialTeb;
  91. NTSTATUS Status;
  92. CLIENT_ID ThreadClientId;
  93. CONTEXT ThreadContext;
  94. HANDLE ThreadHandle;
  95. OBJECT_ATTRIBUTES ThreadObja;
  96. ////////////////////////////////////////////////////////////////
  97. // //
  98. // Private Macros //
  99. // //
  100. ////////////////////////////////////////////////////////////////
  101. #define TestpPrintLuid(G) \
  102. DbgPrint( "(0x%x, 0x%x)", \
  103. (G).HighPart, (G).LowPart); \
  104. ////////////////////////////////////////////////////////////////
  105. // //
  106. // Initialization Routine //
  107. // //
  108. ////////////////////////////////////////////////////////////////
  109. BOOLEAN
  110. TestTokenInitialize()
  111. {
  112. NTSTATUS Status;
  113. ULONG ReturnLength;
  114. HANDLE ProcessToken;
  115. TOKEN_STATISTICS ProcessTokenStatistics;
  116. PTOKEN_PRIVILEGES NewState;
  117. if (!TSeVariableInitialization()) {
  118. DbgPrint("Se: Failed to initialize global test variables.\n");
  119. return FALSE;
  120. }
  121. DisabledGroupAttributes = (SE_GROUP_ENABLED_BY_DEFAULT);
  122. OptionalGroupAttributes = (SE_GROUP_ENABLED_BY_DEFAULT |
  123. SE_GROUP_ENABLED
  124. );
  125. NormalGroupAttributes = (SE_GROUP_MANDATORY |
  126. SE_GROUP_ENABLED_BY_DEFAULT |
  127. SE_GROUP_ENABLED
  128. );
  129. OwnerGroupAttributes = (SE_GROUP_MANDATORY |
  130. SE_GROUP_ENABLED_BY_DEFAULT |
  131. SE_GROUP_ENABLED |
  132. SE_GROUP_OWNER
  133. );
  134. PrimarySecurityDescriptor =
  135. (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );
  136. Status = RtlCreateSecurityDescriptor (
  137. PrimarySecurityDescriptor,
  138. SECURITY_DESCRIPTOR_REVISION1
  139. ); ASSERT(NT_SUCCESS(Status));
  140. Status = RtlSetDaclSecurityDescriptor (
  141. PrimarySecurityDescriptor,
  142. TRUE, //DaclPresent,
  143. NULL, //Dacl OPTIONAL, // No protection
  144. FALSE //DaclDefaulted OPTIONAL
  145. ); ASSERT(NT_SUCCESS(Status));
  146. InitializeObjectAttributes(
  147. &PrimaryTokenAttributes,
  148. NULL,
  149. OBJ_INHERIT,
  150. NULL,
  151. PrimarySecurityDescriptor
  152. );
  153. ImpersonationSecurityDescriptor =
  154. (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );
  155. ImpersonationSecurityQos.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
  156. ImpersonationSecurityQos.ImpersonationLevel = SecurityImpersonation;
  157. ImpersonationSecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  158. ImpersonationSecurityQos.EffectiveOnly = FALSE;
  159. InitializeObjectAttributes(
  160. &ImpersonationTokenAttributes,
  161. NULL,
  162. OBJ_INHERIT,
  163. NULL,
  164. NULL
  165. );
  166. ImpersonationTokenAttributes.SecurityQualityOfService =
  167. &ImpersonationSecurityQos;
  168. AnonymousSecurityDescriptor =
  169. (PSECURITY_DESCRIPTOR)TstAllocatePool( PagedPool, 1024 );
  170. AnonymousSecurityQos.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
  171. AnonymousSecurityQos.ImpersonationLevel = SecurityAnonymous;
  172. AnonymousSecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  173. AnonymousSecurityQos.EffectiveOnly = FALSE;
  174. InitializeObjectAttributes(
  175. &AnonymousTokenAttributes,
  176. NULL,
  177. OBJ_INHERIT,
  178. NULL,
  179. NULL
  180. );
  181. AnonymousTokenAttributes.SecurityQualityOfService =
  182. &AnonymousSecurityQos;
  183. //
  184. // Build an ACL for use.
  185. //
  186. Dacl = (PACL)TstAllocatePool( PagedPool, 256 );
  187. Dacl->AclRevision=ACL_REVISION;
  188. Dacl->Sbz1=0;
  189. Dacl->Sbz2=0;
  190. Dacl->AclSize=256;
  191. Dacl->AceCount=0;
  192. //
  193. // Set up expiration times
  194. //
  195. TempTimeFields.Year = 3000;
  196. TempTimeFields.Month = 1;
  197. TempTimeFields.Day = 1;
  198. TempTimeFields.Hour = 1;
  199. TempTimeFields.Minute = 1;
  200. TempTimeFields.Second = 1;
  201. TempTimeFields.Milliseconds = 1;
  202. TempTimeFields.Weekday = 1;
  203. RtlTimeFieldsToTime( &TempTimeFields, &NoExpiration );
  204. //
  205. // Set up a bad authentication ID
  206. //
  207. BadAuthenticationId = RtlConvertLongToLuid(1);
  208. //
  209. // Use a token source specific to security test
  210. //
  211. NtAllocateLocallyUniqueId( &(TestSource.SourceIdentifier) );
  212. //
  213. // Create a new thread for impersonation tests
  214. //
  215. //
  216. // Initialize object attributes.
  217. // Note that the name of the thread is NULL so that we
  218. // can run multiple copies of the test at the same time
  219. // without collisions.
  220. //
  221. InitializeObjectAttributes(&ThreadObja, NULL, 0, NULL, NULL);
  222. //
  223. // Initialize thread context and initial TEB.
  224. //
  225. RtlInitializeContext(NtCurrentProcess(),
  226. &ThreadContext,
  227. NULL,
  228. (PVOID)TestTokenInitialize,
  229. &ThreadStack[254]);
  230. InitialTeb.StackBase = &ThreadStack[254];
  231. InitialTeb.StackLimit = &ThreadStack[0];
  232. //
  233. // Create a thread in a suspended state.
  234. //
  235. Status = NtCreateThread(&ThreadHandle,
  236. THREAD_ALL_ACCESS,
  237. &ThreadObja,
  238. NtCurrentProcess(),
  239. &ThreadClientId,
  240. &ThreadContext,
  241. &InitialTeb,
  242. TRUE);
  243. ASSERT(NT_SUCCESS(Status));
  244. //
  245. // The following is sortof a horse-before-the-cart type of initialization.
  246. // Now that the system is enforcing things like "you can only create a
  247. // token with an AuthenticationId that the reference monitor has been told
  248. // about, it is necessary to obtain some information out of our current
  249. // token.
  250. //
  251. Status = NtOpenProcessToken(
  252. NtCurrentProcess(),
  253. TOKEN_ALL_ACCESS,
  254. &ProcessToken
  255. );
  256. ASSERT( NT_SUCCESS(Status) );
  257. Status = NtQueryInformationToken(
  258. ProcessToken, // Handle
  259. TokenStatistics, // TokenInformationClass
  260. &ProcessTokenStatistics, // TokenInformation
  261. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  262. &ReturnLength // ReturnLength
  263. );
  264. ASSERT(NT_SUCCESS(Status));
  265. OriginalAuthenticationId = ProcessTokenStatistics.AuthenticationId;
  266. DbgPrint("Se: enabling AssignPrimary & TCB privileges...\n");
  267. NewState = (PTOKEN_PRIVILEGES) TstAllocatePool(
  268. PagedPool,
  269. 200
  270. );
  271. NewState->PrivilegeCount = 2;
  272. NewState->Privileges[0].Luid = CreateTokenPrivilege;
  273. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  274. NewState->Privileges[1].Luid = AssignPrimaryTokenPrivilege;
  275. NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
  276. Status = NtAdjustPrivilegesToken(
  277. ProcessToken, // TokenHandle
  278. FALSE, // DisableAllPrivileges
  279. NewState, // NewState (OPTIONAL)
  280. 0, // BufferLength
  281. NULL, // PreviousState (OPTIONAL)
  282. &ReturnLength // ReturnLength
  283. );
  284. if (Status != STATUS_SUCCESS) {
  285. DbgPrint("Failed to enable TCB and AssignPrimaryToken privilegs: 0x%x\n",Status);
  286. return FALSE;
  287. }
  288. DbgPrint("Done.\n");
  289. return TRUE;
  290. }
  291. ////////////////////////////////////////////////////////////////
  292. // //
  293. // Test routines //
  294. // //
  295. ////////////////////////////////////////////////////////////////
  296. ////////////////////////////////////////////////////////////////
  297. // //
  298. // Token Creation Test //
  299. // //
  300. ////////////////////////////////////////////////////////////////
  301. BOOLEAN
  302. TestTokenCreate()
  303. {
  304. BOOLEAN CompletionStatus = TRUE;
  305. TOKEN_USER UserId;
  306. TOKEN_PRIMARY_GROUP PrimaryGroup;
  307. PTOKEN_GROUPS GroupIds;
  308. PTOKEN_PRIVILEGES Privileges;
  309. TOKEN_DEFAULT_DACL DefaultDacl;
  310. TOKEN_DEFAULT_DACL NullDefaultDacl;
  311. TOKEN_OWNER Owner;
  312. DbgPrint("\n");
  313. GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  314. GROUP_IDS_LENGTH
  315. );
  316. Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool,
  317. PRIVILEGES_LENGTH
  318. );
  319. DefaultDacl.DefaultDacl = (PACL)TstAllocatePool( PagedPool,
  320. DEFAULT_DACL_LENGTH
  321. );
  322. //
  323. // Create the simplest token possible
  324. // (no Groups, explicit Owner, or DefaultDacl)
  325. //
  326. DbgPrint("Se: Create Simple Token ... ");
  327. UserId.User.Sid = PebblesSid;
  328. UserId.User.Attributes = 0;
  329. GroupIds->GroupCount = 0;
  330. Privileges->PrivilegeCount = 0;
  331. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  332. Status = NtCreateToken(
  333. &Token, // Handle
  334. (TOKEN_ALL_ACCESS), // DesiredAccess
  335. &PrimaryTokenAttributes, // ObjectAttributes
  336. TokenPrimary, // TokenType
  337. &SystemAuthenticationId, // Authentication LUID
  338. &NoExpiration, // Expiration Time
  339. &UserId, // Owner ID
  340. GroupIds, // Group IDs
  341. Privileges, // Privileges
  342. NULL, // Owner
  343. &PrimaryGroup, // Primary Group
  344. NULL, // Default Dacl
  345. &TestSource // TokenSource
  346. );
  347. if (NT_SUCCESS(Status)) {
  348. DbgPrint("Succeeded.\n");
  349. Status = NtDuplicateObject(
  350. NtCurrentProcess(), // SourceProcessHandle
  351. Token, // SourceHandle
  352. NtCurrentProcess(), // TargetProcessHandle
  353. &SimpleToken, // TargetHandle
  354. 0, // DesiredAccess (over-ridden by option)
  355. 0, // HandleAttributes
  356. DUPLICATE_SAME_ACCESS // Options
  357. );
  358. ASSERT(NT_SUCCESS(Status));
  359. Status = NtClose(Token);
  360. ASSERT(NT_SUCCESS(Status));
  361. } else {
  362. DbgPrint("********** Failed ************\n");
  363. DbgPrint("Status is: 0x%lx \n", Status);
  364. CompletionStatus = FALSE;
  365. }
  366. ASSERT(NT_SUCCESS(Status));
  367. //
  368. // Create a token with groups
  369. //
  370. DbgPrint("Se: Create Token With Groups ... ");
  371. GroupIds->GroupCount = GROUP_COUNT;
  372. GroupIds->Groups[0].Sid = FlintstoneSid;
  373. GroupIds->Groups[1].Sid = ChildSid;
  374. GroupIds->Groups[2].Sid = NeandertholSid;
  375. GroupIds->Groups[3].Sid = WorldSid;
  376. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  377. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  378. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  379. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  380. UserId.User.Sid = PebblesSid;
  381. UserId.User.Attributes = 0;
  382. Privileges->PrivilegeCount = 0;
  383. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  384. Status = NtCreateToken(
  385. &Token, // Handle
  386. (TOKEN_ALL_ACCESS), // DesiredAccess
  387. &PrimaryTokenAttributes, // ObjectAttributes
  388. TokenPrimary, // TokenType
  389. &OriginalAuthenticationId, // Authentication LUID
  390. &NoExpiration, // Expiration Time
  391. &UserId, // Owner ID
  392. GroupIds, // Group IDs
  393. Privileges, // Privileges
  394. NULL, // Owner
  395. &PrimaryGroup, // Primary Group
  396. NULL, // Default Dacl
  397. &TestSource // TokenSource
  398. );
  399. if (NT_SUCCESS(Status)) {
  400. DbgPrint("Succeeded.\n");
  401. Status = NtDuplicateObject(
  402. NtCurrentProcess(), // SourceProcessHandle
  403. Token, // SourceHandle
  404. NtCurrentProcess(), // TargetProcessHandle
  405. &TokenWithGroups, // TargetHandle
  406. 0, // DesiredAccess (over-ridden by option)
  407. 0, // HandleAttributes
  408. DUPLICATE_SAME_ACCESS // Options
  409. );
  410. ASSERT(NT_SUCCESS(Status));
  411. Status = NtClose(Token);
  412. ASSERT(NT_SUCCESS(Status));
  413. } else {
  414. DbgPrint("********** Failed ************\n");
  415. DbgPrint("Status is: 0x%lx \n", Status);
  416. CompletionStatus = FALSE;
  417. }
  418. ASSERT(NT_SUCCESS(Status));
  419. //
  420. // Create a token with default owner
  421. //
  422. DbgPrint("Se: Create Token Default Owner ... ");
  423. GroupIds->GroupCount = GROUP_COUNT;
  424. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  425. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  426. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  427. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  428. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  429. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  430. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  431. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  432. UserId.User.Sid = PebblesSid;
  433. UserId.User.Attributes = 0;
  434. Owner.Owner = FlintstoneSid;
  435. Privileges->PrivilegeCount = 0;
  436. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  437. Status = NtCreateToken(
  438. &Token, // Handle
  439. (TOKEN_ALL_ACCESS), // DesiredAccess
  440. &PrimaryTokenAttributes, // ObjectAttributes
  441. TokenPrimary, // TokenType
  442. &SystemAuthenticationId, // Authentication LUID
  443. &NoExpiration, // Expiration Time
  444. &UserId, // Owner ID
  445. GroupIds, // Group IDs
  446. Privileges, // Privileges
  447. &Owner, // Owner
  448. &PrimaryGroup, // Primary Group
  449. NULL, // Default Dacl
  450. &TestSource // TokenSource
  451. );
  452. if (NT_SUCCESS(Status)) {
  453. DbgPrint("Succeeded.\n");
  454. Status = NtDuplicateObject(
  455. NtCurrentProcess(), // SourceProcessHandle
  456. Token, // SourceHandle
  457. NtCurrentProcess(), // TargetProcessHandle
  458. &TokenWithDefaultOwner, // TargetHandle
  459. 0, // DesiredAccess (over-ridden by option)
  460. 0, // HandleAttributes
  461. DUPLICATE_SAME_ACCESS // Options
  462. );
  463. ASSERT(NT_SUCCESS(Status));
  464. Status = NtClose(Token);
  465. ASSERT(NT_SUCCESS(Status));
  466. } else {
  467. DbgPrint("********** Failed ************\n");
  468. DbgPrint("Status is: 0x%lx \n", Status);
  469. CompletionStatus = FALSE;
  470. }
  471. ASSERT(NT_SUCCESS(Status));
  472. //
  473. // Create a token with default privileges
  474. //
  475. DbgPrint("Se: Create Token privileges ... ");
  476. GroupIds->GroupCount = GROUP_COUNT;
  477. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  478. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  479. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  480. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  481. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  482. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  483. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  484. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  485. UserId.User.Sid = PebblesSid;
  486. UserId.User.Attributes = 0;
  487. Owner.Owner = FlintstoneSid;
  488. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  489. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  490. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  491. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  492. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  493. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  494. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  495. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  496. Status = NtCreateToken(
  497. &Token, // Handle
  498. (TOKEN_ALL_ACCESS), // DesiredAccess
  499. &PrimaryTokenAttributes, // ObjectAttributes
  500. TokenPrimary, // TokenType
  501. &OriginalAuthenticationId, // Authentication LUID
  502. &NoExpiration, // Expiration Time
  503. &UserId, // Owner ID
  504. GroupIds, // Group IDs
  505. Privileges, // Privileges
  506. &Owner, // Owner
  507. &PrimaryGroup, // Primary Group
  508. NULL, // Default Dacl
  509. &TestSource // TokenSource
  510. );
  511. if (NT_SUCCESS(Status)) {
  512. DbgPrint("Succeeded.\n");
  513. Status = NtDuplicateObject(
  514. NtCurrentProcess(), // SourceProcessHandle
  515. Token, // SourceHandle
  516. NtCurrentProcess(), // TargetProcessHandle
  517. &TokenWithPrivileges, // TargetHandle
  518. 0, // DesiredAccess (over-ridden by option)
  519. 0, // HandleAttributes
  520. DUPLICATE_SAME_ACCESS // Options
  521. );
  522. ASSERT(NT_SUCCESS(Status));
  523. Status = NtClose(Token);
  524. ASSERT(NT_SUCCESS(Status));
  525. } else {
  526. DbgPrint("********** Failed ************\n");
  527. DbgPrint("Status is: 0x%lx \n", Status);
  528. CompletionStatus = FALSE;
  529. }
  530. ASSERT(NT_SUCCESS(Status));
  531. //
  532. // Create a token with default DACL
  533. //
  534. DbgPrint("Se: Create Token With Default Dacl ... ");
  535. GroupIds->GroupCount = GROUP_COUNT;
  536. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  537. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  538. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  539. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  540. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  541. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  542. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  543. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  544. UserId.User.Sid = PebblesSid;
  545. UserId.User.Attributes = 0;
  546. Owner.Owner = FlintstoneSid;
  547. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  548. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  549. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  550. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  551. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  552. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  553. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  554. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  555. Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);
  556. ASSERT(NT_SUCCESS(Status) );
  557. Status = NtCreateToken(
  558. &Token, // Handle
  559. (TOKEN_ALL_ACCESS), // DesiredAccess
  560. &PrimaryTokenAttributes, // ObjectAttributes
  561. TokenPrimary, // TokenType
  562. &SystemAuthenticationId, // Authentication LUID
  563. &NoExpiration, // Expiration Time
  564. &UserId, // Owner ID
  565. GroupIds, // Group IDs
  566. Privileges, // Privileges
  567. &Owner, // Owner
  568. &PrimaryGroup, // Primary Group
  569. &DefaultDacl, // Default Dacl
  570. &TestSource // TokenSource
  571. );
  572. if (NT_SUCCESS(Status)) {
  573. DbgPrint("Succeeded.\n");
  574. //
  575. // Save a copy of this for later use...
  576. //
  577. Status = NtDuplicateObject(
  578. NtCurrentProcess(), // SourceProcessHandle
  579. Token, // SourceHandle
  580. NtCurrentProcess(), // TargetProcessHandle
  581. &TokenWithDefaultDacl, // TargetHandle
  582. 0, // DesiredAccess (over-ridden by option)
  583. 0, // HandleAttributes
  584. DUPLICATE_SAME_ACCESS // Options
  585. );
  586. ASSERT(NT_SUCCESS(Status));
  587. Status = NtClose(Token);
  588. ASSERT(NT_SUCCESS(Status));
  589. } else {
  590. DbgPrint("********** Failed ************\n");
  591. DbgPrint("Status is: 0x%lx \n", Status);
  592. CompletionStatus = FALSE;
  593. }
  594. ASSERT(NT_SUCCESS(Status));
  595. //
  596. // Create a token with a null default DACL
  597. //
  598. DbgPrint("Se: Create Token With a Null Default Dacl ... ");
  599. GroupIds->GroupCount = GROUP_COUNT;
  600. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  601. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  602. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  603. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  604. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  605. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  606. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  607. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  608. UserId.User.Sid = PebblesSid;
  609. UserId.User.Attributes = 0;
  610. Owner.Owner = FlintstoneSid;
  611. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  612. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  613. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  614. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  615. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  616. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  617. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  618. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  619. NullDefaultDacl.DefaultDacl = NULL;
  620. Status = NtCreateToken(
  621. &Token, // Handle
  622. (TOKEN_ALL_ACCESS), // DesiredAccess
  623. &PrimaryTokenAttributes, // ObjectAttributes
  624. TokenPrimary, // TokenType
  625. &OriginalAuthenticationId, // Authentication LUID
  626. &NoExpiration, // Expiration Time
  627. &UserId, // Owner ID
  628. GroupIds, // Group IDs
  629. Privileges, // Privileges
  630. &Owner, // Owner
  631. &PrimaryGroup, // Primary Group
  632. &NullDefaultDacl, // Default Dacl
  633. &TestSource // TokenSource
  634. );
  635. if (NT_SUCCESS(Status)) {
  636. DbgPrint("Succeeded.\n");
  637. Status = NtClose(Token);
  638. ASSERT(NT_SUCCESS(Status));
  639. } else {
  640. DbgPrint("********** Failed ************\n");
  641. DbgPrint("Status is: 0x%lx \n", Status);
  642. CompletionStatus = FALSE;
  643. }
  644. ASSERT(NT_SUCCESS(Status));
  645. //
  646. // Create an impersonation token, Impersonation level = Impersonation
  647. //
  648. DbgPrint("Se: Create an impersonation token ... ");
  649. GroupIds->GroupCount = GROUP_COUNT;
  650. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  651. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  652. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  653. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  654. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  655. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  656. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  657. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  658. UserId.User.Sid = PebblesSid;
  659. UserId.User.Attributes = 0;
  660. Owner.Owner = FlintstoneSid;
  661. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  662. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  663. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  664. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  665. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  666. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  667. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  668. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  669. Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);
  670. ASSERT(NT_SUCCESS(Status) );
  671. Status = NtCreateToken(
  672. &Token, // Handle
  673. (TOKEN_ALL_ACCESS), // DesiredAccess
  674. &ImpersonationTokenAttributes, // ObjectAttributes
  675. TokenImpersonation, // TokenType
  676. &SystemAuthenticationId, // Authentication LUID
  677. &NoExpiration, // Expiration Time
  678. &UserId, // Owner ID
  679. GroupIds, // Group IDs
  680. Privileges, // Privileges
  681. &Owner, // Owner
  682. &PrimaryGroup, // Primary Group
  683. &DefaultDacl, // Default Dacl
  684. &TestSource // TokenSource
  685. );
  686. if (NT_SUCCESS(Status)) {
  687. DbgPrint("Succeeded.\n");
  688. Status = NtDuplicateObject(
  689. NtCurrentProcess(), // SourceProcessHandle
  690. Token, // SourceHandle
  691. NtCurrentProcess(), // TargetProcessHandle
  692. &ImpersonationToken, // TargetHandle
  693. 0, // DesiredAccess (over-ridden by option)
  694. 0, // HandleAttributes
  695. DUPLICATE_SAME_ACCESS // Options
  696. );
  697. ASSERT(NT_SUCCESS(Status));
  698. Status = NtClose(Token);
  699. ASSERT(NT_SUCCESS(Status));
  700. } else {
  701. DbgPrint("********** Failed ************\n");
  702. DbgPrint("Status is: 0x%lx \n", Status);
  703. CompletionStatus = FALSE;
  704. }
  705. ASSERT(NT_SUCCESS(Status));
  706. //
  707. // Create an impersonation token, Impersonation level = Anonymous
  708. //
  709. DbgPrint("Se: Create an anonymous token ... ");
  710. GroupIds->GroupCount = GROUP_COUNT;
  711. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  712. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  713. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  714. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  715. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  716. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  717. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  718. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  719. UserId.User.Sid = PebblesSid;
  720. UserId.User.Attributes = 0;
  721. Owner.Owner = FlintstoneSid;
  722. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  723. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  724. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  725. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  726. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  727. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  728. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  729. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  730. Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);
  731. ASSERT(NT_SUCCESS(Status) );
  732. Status = NtCreateToken(
  733. &Token, // Handle
  734. (TOKEN_ALL_ACCESS), // DesiredAccess
  735. &AnonymousTokenAttributes, // ObjectAttributes
  736. TokenImpersonation, // TokenType
  737. &OriginalAuthenticationId, // Authentication LUID
  738. &NoExpiration, // Expiration Time
  739. &UserId, // Owner ID
  740. GroupIds, // Group IDs
  741. Privileges, // Privileges
  742. &Owner, // Owner
  743. &PrimaryGroup, // Primary Group
  744. &DefaultDacl, // Default Dacl
  745. &TestSource // TokenSource
  746. );
  747. if (NT_SUCCESS(Status)) {
  748. DbgPrint("Succeeded.\n");
  749. Status = NtDuplicateObject(
  750. NtCurrentProcess(), // SourceProcessHandle
  751. Token, // SourceHandle
  752. NtCurrentProcess(), // TargetProcessHandle
  753. &AnonymousToken, // TargetHandle
  754. 0, // DesiredAccess (over-ridden by option)
  755. 0, // HandleAttributes
  756. DUPLICATE_SAME_ACCESS // Options
  757. );
  758. ASSERT(NT_SUCCESS(Status));
  759. Status = NtClose(Token);
  760. ASSERT(NT_SUCCESS(Status));
  761. } else {
  762. DbgPrint("********** Failed ************\n");
  763. DbgPrint("Status is: 0x%lx \n", Status);
  764. CompletionStatus = FALSE;
  765. }
  766. ASSERT(NT_SUCCESS(Status));
  767. //
  768. // Create the simplest token possible
  769. // (no Groups, explicit Owner, or DefaultDacl)
  770. //
  771. DbgPrint("Se: Create Token With Bad Authentication Id ... ");
  772. UserId.User.Sid = PebblesSid;
  773. UserId.User.Attributes = 0;
  774. GroupIds->GroupCount = 0;
  775. Privileges->PrivilegeCount = 0;
  776. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  777. Status = NtCreateToken(
  778. &Token, // Handle
  779. (TOKEN_ALL_ACCESS), // DesiredAccess
  780. &PrimaryTokenAttributes, // ObjectAttributes
  781. TokenPrimary, // TokenType
  782. &BadAuthenticationId, // Authentication LUID
  783. &NoExpiration, // Expiration Time
  784. &UserId, // Owner ID
  785. GroupIds, // Group IDs
  786. Privileges, // Privileges
  787. NULL, // Owner
  788. &PrimaryGroup, // Primary Group
  789. NULL, // Default Dacl
  790. &TestSource // TokenSource
  791. );
  792. if (Status == STATUS_NO_SUCH_LOGON_SESSION) {
  793. DbgPrint("Succeeded.\n");
  794. } else {
  795. DbgPrint("********** Failed ************\n");
  796. DbgPrint("Status is: 0x%lx \n", Status);
  797. DbgPrint("Status should be: 0x%lx \n", STATUS_NO_SUCH_LOGON_SESSION);
  798. CompletionStatus = FALSE;
  799. }
  800. //
  801. // All done with this test
  802. //
  803. return CompletionStatus;
  804. }
  805. ////////////////////////////////////////////////////////////////
  806. // //
  807. // Token Filtering Test //
  808. // //
  809. ////////////////////////////////////////////////////////////////
  810. BOOLEAN
  811. TestTokenFilter()
  812. {
  813. BOOLEAN CompletionStatus = TRUE;
  814. PTOKEN_GROUPS GroupIds;
  815. PTOKEN_GROUPS RestrictedGroupIds;
  816. PTOKEN_PRIVILEGES Privileges;
  817. DbgPrint("\n");
  818. GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  819. GROUP_IDS_LENGTH
  820. );
  821. RestrictedGroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  822. GROUP_IDS_LENGTH
  823. );
  824. Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool,
  825. PRIVILEGES_LENGTH
  826. );
  827. //
  828. // Filter a token without doing anything
  829. //
  830. DbgPrint("Se: Filter null Token ... ");
  831. Status = NtFilterToken(
  832. TokenWithGroups,
  833. 0, // no flags
  834. NULL, // no groups to disable
  835. NULL, // no privileges to disable
  836. NULL, // no restricted sids
  837. &Token
  838. );
  839. if (NT_SUCCESS(Status)) {
  840. DbgPrint("Succeeded.\n");
  841. NtClose(Token);
  842. } else {
  843. DbgPrint("********** Failed ************\n");
  844. DbgPrint("Status is: 0x%lx \n", Status);
  845. CompletionStatus = FALSE;
  846. }
  847. //
  848. // Filter a token and remove some groups
  849. //
  850. GroupIds->GroupCount = 2;
  851. GroupIds->Groups[0].Sid = FlintstoneSid;
  852. GroupIds->Groups[1].Sid = ChildSid;
  853. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
  854. GroupIds->Groups[CHILD_INDEX].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
  855. DbgPrint("Se: Filter token with disabled groups ... ");
  856. Status = NtFilterToken(
  857. TokenWithGroups,
  858. 0, // no flags
  859. GroupIds, // no groups to disable
  860. NULL, // no privileges to disable
  861. NULL, // no restricted sids
  862. &TokenWithRestrictedGroups
  863. );
  864. if (NT_SUCCESS(Status)) {
  865. DbgPrint("Succeeded.\n");
  866. } else {
  867. DbgPrint("********** Failed ************\n");
  868. DbgPrint("Status is: 0x%lx \n", Status);
  869. CompletionStatus = FALSE;
  870. }
  871. //
  872. // Filter a token and remove some privileges
  873. //
  874. Privileges->PrivilegeCount = 2;
  875. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  876. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  877. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  878. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  879. DbgPrint("Se: Filter token with disabled privilegs ... ");
  880. Status = NtFilterToken(
  881. TokenWithPrivileges,
  882. 0, // no flags
  883. NULL, // no groups to disable
  884. Privileges, // no privileges to disable
  885. NULL, // no restricted sids
  886. &TokenWithRestrictedPrivileges
  887. );
  888. if (NT_SUCCESS(Status)) {
  889. DbgPrint("Succeeded.\n");
  890. } else {
  891. DbgPrint("********** Failed ************\n");
  892. DbgPrint("Status is: 0x%lx \n", Status);
  893. CompletionStatus = FALSE;
  894. }
  895. //
  896. // Filter a restricted token and add some restricted sids
  897. //
  898. RestrictedGroupIds->GroupCount = RESTRICTED_SID_COUNT;
  899. RestrictedGroupIds->GroupCount = RESTRICTED_SID_COUNT;
  900. RestrictedGroupIds->Groups[0].Sid = FlintstoneSid;
  901. RestrictedGroupIds->Groups[1].Sid = ChildSid;
  902. RestrictedGroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  903. RestrictedGroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  904. DbgPrint("Se: Filter token with restricted sids ... ");
  905. Status = NtFilterToken(
  906. TokenWithGroups,
  907. 0, // no flags
  908. NULL, // no groups to disable
  909. NULL, // no privileges to disable
  910. RestrictedGroupIds, // no restricted sids
  911. &TokenWithRestrictedSids
  912. );
  913. if (NT_SUCCESS(Status)) {
  914. DbgPrint("Succeeded.\n");
  915. } else {
  916. DbgPrint("********** Failed ************\n");
  917. DbgPrint("Status is: 0x%lx \n", Status);
  918. CompletionStatus = FALSE;
  919. }
  920. //
  921. // Filter a token and add some restricted sids
  922. //
  923. RestrictedGroupIds->GroupCount = RESTRICTED_SID_COUNT;
  924. RestrictedGroupIds->Groups[0].Sid = NeandertholSid;
  925. RestrictedGroupIds->Groups[1].Sid = WorldSid;
  926. RestrictedGroupIds->Groups[0].Attributes = OwnerGroupAttributes;
  927. RestrictedGroupIds->Groups[1].Attributes = OptionalGroupAttributes;
  928. DbgPrint("Se: Filter token with more restricted sids ... ");
  929. Status = NtFilterToken(
  930. TokenWithRestrictedSids,
  931. 0, // no flags
  932. NULL, // no groups to disable
  933. NULL, // no privileges to disable
  934. RestrictedGroupIds, // no restricted sids
  935. &TokenWithMoreRestrictedSids
  936. );
  937. if (NT_SUCCESS(Status)) {
  938. DbgPrint("Succeeded.\n");
  939. } else {
  940. DbgPrint("********** Failed ************\n");
  941. DbgPrint("Status is: 0x%lx \n", Status);
  942. CompletionStatus = FALSE;
  943. }
  944. //
  945. // All done with this test
  946. //
  947. return CompletionStatus;
  948. }
  949. ////////////////////////////////////////////////////////////////
  950. // //
  951. // Open Primary Token Test //
  952. // //
  953. ////////////////////////////////////////////////////////////////
  954. BOOLEAN
  955. TestTokenOpenPrimary()
  956. {
  957. NTSTATUS Status;
  958. BOOLEAN CompletionStatus = TRUE;
  959. HANDLE ProcessToken;
  960. HANDLE SubProcessToken;
  961. HANDLE SubProcess;
  962. TOKEN_STATISTICS ProcessTokenStatistics;
  963. TOKEN_STATISTICS SubProcessTokenStatistics;
  964. ULONG ReturnLength;
  965. DbgPrint("\n");
  966. //
  967. // Open the current process's token
  968. //
  969. DbgPrint("Se: Open own process's token ... ");
  970. Status = NtOpenProcessToken(
  971. NtCurrentProcess(),
  972. TOKEN_ALL_ACCESS,
  973. &ProcessToken
  974. );
  975. if (NT_SUCCESS(Status)) {
  976. Status = NtQueryInformationToken(
  977. ProcessToken, // Handle
  978. TokenStatistics, // TokenInformationClass
  979. &ProcessTokenStatistics, // TokenInformation
  980. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  981. &ReturnLength // ReturnLength
  982. );
  983. ASSERT(NT_SUCCESS(Status));
  984. if ( ProcessTokenStatistics.TokenType == TokenPrimary) {
  985. if ( RtlEqualLuid( &ProcessTokenStatistics.AuthenticationId,
  986. &OriginalAuthenticationId ) ) {
  987. DbgPrint("Succeeded.\n");
  988. } else {
  989. DbgPrint("********** Failed ************\n");
  990. DbgPrint("Unexpected authentication ID value.\n");
  991. DbgPrint("Authentication ID is: ");
  992. TestpPrintLuid(ProcessTokenStatistics.AuthenticationId);
  993. DbgPrint("\n");
  994. CompletionStatus = FALSE;
  995. }
  996. } else {
  997. DbgPrint("********** Failed ************\n");
  998. DbgPrint("Token type not TokenPrimary.\n");
  999. DbgPrint("Returned token type is: 0x%lx \n",
  1000. ProcessTokenStatistics.TokenType);
  1001. DbgPrint("Authentication ID is: ");
  1002. TestpPrintLuid(ProcessTokenStatistics.AuthenticationId);
  1003. DbgPrint("\n");
  1004. CompletionStatus = FALSE;
  1005. }
  1006. Status = NtClose(ProcessToken);
  1007. ASSERT(NT_SUCCESS(Status));
  1008. } else {
  1009. DbgPrint("********** Failed ************\n");
  1010. DbgPrint("Status is: 0x%lx \n", Status);
  1011. CompletionStatus = FALSE;
  1012. }
  1013. //
  1014. // Open another process's token
  1015. //
  1016. DbgPrint("Se: Open another process's token ... ");
  1017. Status = NtCreateProcess(
  1018. &SubProcess,
  1019. (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE),
  1020. NULL,
  1021. NtCurrentProcess(), // ParentProcess
  1022. FALSE, // InheritObjectTable
  1023. NULL, // SectionHandle,
  1024. NULL, // DebugPort,
  1025. NULL // ExceptionPort
  1026. );
  1027. Status = NtOpenProcessToken(
  1028. SubProcess,
  1029. TOKEN_ALL_ACCESS,
  1030. &SubProcessToken
  1031. );
  1032. if (NT_SUCCESS(Status)) {
  1033. Status = NtQueryInformationToken(
  1034. SubProcessToken, // Handle
  1035. TokenStatistics, // TokenInformationClass
  1036. &SubProcessTokenStatistics, // TokenInformation
  1037. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  1038. &ReturnLength // ReturnLength
  1039. );
  1040. ASSERT(NT_SUCCESS(Status));
  1041. if ( SubProcessTokenStatistics.TokenType == TokenPrimary) {
  1042. if ( RtlEqualLuid( &SubProcessTokenStatistics.AuthenticationId,
  1043. &OriginalAuthenticationId ) ) {
  1044. if ( (ProcessTokenStatistics.TokenId.HighPart ==
  1045. SubProcessTokenStatistics.TokenId.HighPart) &&
  1046. (ProcessTokenStatistics.TokenId.LowPart ==
  1047. SubProcessTokenStatistics.TokenId.LowPart) ) {
  1048. DbgPrint("********** Failed ************\n");
  1049. DbgPrint("Same token as parent process (token IDs match).\n");
  1050. DbgPrint("Authentication ID is: ");
  1051. TestpPrintLuid(SubProcessTokenStatistics.AuthenticationId);
  1052. DbgPrint("\n");
  1053. CompletionStatus = FALSE;
  1054. } else {
  1055. DbgPrint("Succeeded.\n");
  1056. }
  1057. } else {
  1058. DbgPrint("********** Failed ************\n");
  1059. DbgPrint("Unexpected authentication ID value.\n");
  1060. DbgPrint("Authentication ID is: ");
  1061. TestpPrintLuid(SubProcessTokenStatistics.AuthenticationId);
  1062. DbgPrint("\n");
  1063. CompletionStatus = FALSE;
  1064. }
  1065. } else {
  1066. DbgPrint("********** Failed ************\n");
  1067. DbgPrint("Token type not TokenPrimary.\n");
  1068. DbgPrint("Returned token type is: 0x%lx \n",
  1069. SubProcessTokenStatistics.TokenType);
  1070. DbgPrint("Authentication ID is: ");
  1071. TestpPrintLuid(SubProcessTokenStatistics.AuthenticationId);
  1072. DbgPrint("\n");
  1073. CompletionStatus = FALSE;
  1074. }
  1075. Status = NtClose(SubProcessToken);
  1076. ASSERT(NT_SUCCESS(Status));
  1077. } else {
  1078. DbgPrint("********** Failed ************\n");
  1079. DbgPrint("Status is: 0x%lx \n", Status);
  1080. CompletionStatus = FALSE;
  1081. }
  1082. return CompletionStatus;
  1083. }
  1084. ////////////////////////////////////////////////////////////////
  1085. // //
  1086. // Query Token Test //
  1087. // //
  1088. ////////////////////////////////////////////////////////////////
  1089. BOOLEAN
  1090. TestTokenQuery()
  1091. {
  1092. BOOLEAN CompletionStatus = TRUE;
  1093. ULONG ReturnLength;
  1094. BOOLEAN ValuesCompare;
  1095. PTOKEN_USER UserId = NULL;
  1096. PTOKEN_PRIMARY_GROUP PrimaryGroup = NULL;
  1097. PTOKEN_GROUPS GroupIds = NULL;
  1098. PTOKEN_GROUPS RestrictedSids = NULL;
  1099. PTOKEN_PRIVILEGES Privileges = NULL;
  1100. PTOKEN_OWNER Owner = NULL;
  1101. PTOKEN_DEFAULT_DACL DefaultDacl = NULL;
  1102. SECURITY_IMPERSONATION_LEVEL QueriedImpersonationLevel;
  1103. TOKEN_SOURCE QueriedSource;
  1104. TOKEN_TYPE QueriedType;
  1105. TOKEN_STATISTICS QueriedStatistics;
  1106. DbgPrint("\n");
  1107. #if 0
  1108. //
  1109. // Query invalid return buffer address
  1110. //
  1111. DbgPrint("Se: Query with invalid buffer address ... ");
  1112. UserId = (PTOKEN_USER)((PVOID)0x200L);
  1113. Status = NtQueryInformationToken(
  1114. SimpleToken, // Handle
  1115. TokenUser, // TokenInformationClass
  1116. UserId, // TokenInformation
  1117. 3000, // TokenInformationLength
  1118. &ReturnLength // ReturnLength
  1119. );
  1120. #ifdef TOKEN_DEBUG
  1121. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1122. #endif //TOKEN_DEBUG
  1123. if (Status == STATUS_ACCESS_VIOLATION) {
  1124. DbgPrint("Succeeded.\n");
  1125. } else {
  1126. DbgPrint("********** Failed ************\n");
  1127. DbgPrint("Status is: 0x%lx \n", Status);
  1128. CompletionStatus = FALSE;
  1129. }
  1130. ASSERT(!NT_SUCCESS(Status));
  1131. #endif //0
  1132. ////////////////////////////////////////////////////////////////////////
  1133. // //
  1134. // Query User ID //
  1135. // //
  1136. ////////////////////////////////////////////////////////////////////////
  1137. //
  1138. // Query User ID with zero length buffer
  1139. //
  1140. DbgPrint("Se: Query User ID with zero length buffer ... ");
  1141. Status = NtQueryInformationToken(
  1142. SimpleToken, // Handle
  1143. TokenUser, // TokenInformationClass
  1144. UserId, // TokenInformation
  1145. 0, // TokenInformationLength
  1146. &ReturnLength // ReturnLength
  1147. );
  1148. #ifdef TOKEN_DEBUG
  1149. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1150. #endif //TOKEN_DEBUG
  1151. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1152. DbgPrint("Succeeded.\n");
  1153. } else {
  1154. DbgPrint("********** Failed ************\n");
  1155. DbgPrint("Status is: 0x%lx \n", Status);
  1156. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1157. CompletionStatus = FALSE;
  1158. }
  1159. ASSERT(!NT_SUCCESS(Status));
  1160. UserId = (PTOKEN_USER)TstAllocatePool( PagedPool,
  1161. ReturnLength
  1162. );
  1163. //
  1164. // Query user SID
  1165. // (This relies upon the ReturnLength returned from previous call)
  1166. //
  1167. DbgPrint("Se: Query token user ... ");
  1168. Status = NtQueryInformationToken(
  1169. SimpleToken, // Handle
  1170. TokenUser, // TokenInformationClass
  1171. UserId, // TokenInformation
  1172. ReturnLength, // TokenInformationLength
  1173. &ReturnLength // ReturnLength
  1174. );
  1175. #ifdef TOKEN_DEBUG
  1176. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1177. #endif //TOKEN_DEBUG
  1178. if (NT_SUCCESS(Status)) {
  1179. //
  1180. // Check returned value
  1181. //
  1182. if (RtlEqualSid((UserId->User.Sid), PebblesSid) ) {
  1183. DbgPrint("Succeeded.\n");
  1184. } else {
  1185. DbgPrint("********** Failed ************\n");
  1186. DbgPrint("Unexpected value returned by query.\n");
  1187. DbgPrint("Status is: 0x%lx \n", Status);
  1188. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1189. CompletionStatus = FALSE;
  1190. }
  1191. } else {
  1192. DbgPrint("********** Failed ************\n");
  1193. DbgPrint("Status is: 0x%lx \n", Status);
  1194. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1195. CompletionStatus = FALSE;
  1196. }
  1197. ASSERT(NT_SUCCESS(Status));
  1198. //
  1199. // Query with too little buffer
  1200. // (This relies upon the ReturnLength returned from previous call)
  1201. //
  1202. DbgPrint("Se: Query user with too small buffer ... ");
  1203. Status = NtQueryInformationToken(
  1204. SimpleToken, // Handle
  1205. TokenUser, // TokenInformationClass
  1206. UserId, // TokenInformation
  1207. ReturnLength-1, // TokenInformationLength
  1208. &ReturnLength // ReturnLength
  1209. );
  1210. #ifdef TOKEN_DEBUG
  1211. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1212. #endif //TOKEN_DEBUG
  1213. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1214. DbgPrint("Succeeded.\n");
  1215. } else {
  1216. DbgPrint("********** Failed ************\n");
  1217. DbgPrint("Status is: 0x%lx \n", Status);
  1218. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1219. CompletionStatus = FALSE;
  1220. }
  1221. ASSERT(!NT_SUCCESS(Status));
  1222. ////////////////////////////////////////////////////////////////////////
  1223. // //
  1224. // Query Primary Group //
  1225. // //
  1226. ////////////////////////////////////////////////////////////////////////
  1227. //
  1228. // Query primary group with zero length buffer
  1229. //
  1230. DbgPrint("Se: Query primary group with zero length buffer ... ");
  1231. Status = NtQueryInformationToken(
  1232. SimpleToken, // Handle
  1233. TokenPrimaryGroup, // TokenInformationClass
  1234. PrimaryGroup, // TokenInformation
  1235. 0, // TokenInformationLength
  1236. &ReturnLength // ReturnLength
  1237. );
  1238. #ifdef TOKEN_DEBUG
  1239. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1240. #endif //TOKEN_DEBUG
  1241. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1242. DbgPrint("Succeeded.\n");
  1243. } else {
  1244. DbgPrint("********** Failed ************\n");
  1245. DbgPrint("Status is: 0x%lx \n", Status);
  1246. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1247. CompletionStatus = FALSE;
  1248. }
  1249. ASSERT(!NT_SUCCESS(Status));
  1250. PrimaryGroup = (PTOKEN_PRIMARY_GROUP)TstAllocatePool( PagedPool,
  1251. ReturnLength
  1252. );
  1253. //
  1254. // Query primary group SID
  1255. // (This relies upon the ReturnLength returned from previous call)
  1256. //
  1257. DbgPrint("Se: Query primary group ... ");
  1258. Status = NtQueryInformationToken(
  1259. SimpleToken, // Handle
  1260. TokenPrimaryGroup, // TokenInformationClass
  1261. PrimaryGroup, // TokenInformation
  1262. ReturnLength, // TokenInformationLength
  1263. &ReturnLength // ReturnLength
  1264. );
  1265. #ifdef TOKEN_DEBUG
  1266. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1267. #endif //TOKEN_DEBUG
  1268. if (NT_SUCCESS(Status)) {
  1269. //
  1270. // Check returned value
  1271. //
  1272. if (RtlEqualSid( PrimaryGroup->PrimaryGroup, FlintstoneSid) ) {
  1273. DbgPrint("Succeeded.\n");
  1274. } else {
  1275. DbgPrint("********** Failed ************\n");
  1276. DbgPrint("Unexpected value returned by query.\n");
  1277. DbgPrint("Status is: 0x%lx \n", Status);
  1278. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1279. CompletionStatus = FALSE;
  1280. }
  1281. } else {
  1282. DbgPrint("********** Failed ************\n");
  1283. DbgPrint("Status is: 0x%lx \n", Status);
  1284. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1285. CompletionStatus = FALSE;
  1286. }
  1287. ASSERT(NT_SUCCESS(Status));
  1288. //
  1289. // Query with too little buffer
  1290. // (This relies upon the ReturnLength returned from previous call)
  1291. //
  1292. DbgPrint("Se: Query primary group with too small buffer ... ");
  1293. Status = NtQueryInformationToken(
  1294. SimpleToken, // Handle
  1295. TokenPrimaryGroup, // TokenInformationClass
  1296. PrimaryGroup, // TokenInformation
  1297. ReturnLength-1, // TokenInformationLength
  1298. &ReturnLength // ReturnLength
  1299. );
  1300. #ifdef TOKEN_DEBUG
  1301. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1302. #endif //TOKEN_DEBUG
  1303. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1304. DbgPrint("Succeeded.\n");
  1305. } else {
  1306. DbgPrint("********** Failed ************\n");
  1307. DbgPrint("Status is: 0x%lx \n", Status);
  1308. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1309. CompletionStatus = FALSE;
  1310. }
  1311. ASSERT(!NT_SUCCESS(Status));
  1312. ////////////////////////////////////////////////////////////////////////
  1313. // //
  1314. // Query Groups //
  1315. // //
  1316. ////////////////////////////////////////////////////////////////////////
  1317. //
  1318. // Query groups with zero length buffer
  1319. //
  1320. DbgPrint("Se: Query groups with zero length buffer ... ");
  1321. Status = NtQueryInformationToken(
  1322. TokenWithGroups, // Handle
  1323. TokenGroups, // TokenInformationClass
  1324. GroupIds, // TokenInformation
  1325. 0, // TokenInformationLength
  1326. &ReturnLength // ReturnLength
  1327. );
  1328. #ifdef TOKEN_DEBUG
  1329. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1330. #endif //TOKEN_DEBUG
  1331. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1332. DbgPrint("Succeeded.\n");
  1333. } else {
  1334. DbgPrint("********** Failed ************\n");
  1335. DbgPrint("Status is: 0x%lx \n", Status);
  1336. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1337. CompletionStatus = FALSE;
  1338. }
  1339. ASSERT(!NT_SUCCESS(Status));
  1340. GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  1341. ReturnLength
  1342. );
  1343. //
  1344. // Query Group SIDs
  1345. // (This relies upon the ReturnLength returned from previous call)
  1346. //
  1347. DbgPrint("Se: Query groups ... ");
  1348. Status = NtQueryInformationToken(
  1349. TokenWithGroups, // Handle
  1350. TokenGroups, // TokenInformationClass
  1351. GroupIds, // TokenInformation
  1352. ReturnLength, // TokenInformationLength
  1353. &ReturnLength // ReturnLength
  1354. );
  1355. #ifdef TOKEN_DEBUG
  1356. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1357. #endif //TOKEN_DEBUG
  1358. if (NT_SUCCESS(Status)) {
  1359. //
  1360. // Check returned value
  1361. // Group count = 4
  1362. // SID 0 = Flintstone
  1363. // SID 1 = ChildSid
  1364. // SID 2 = NeandertholSid
  1365. // SID 3 = WorldSid
  1366. //
  1367. ValuesCompare = TRUE;
  1368. if (GroupIds->GroupCount != GROUP_COUNT) {
  1369. ValuesCompare = FALSE;
  1370. }
  1371. if ( (!RtlEqualSid((GroupIds->Groups[FLINTSTONE_INDEX].Sid),
  1372. FlintstoneSid)) ||
  1373. (GroupIds->Groups[FLINTSTONE_INDEX].Attributes !=
  1374. OwnerGroupAttributes) ) {
  1375. ValuesCompare = FALSE;
  1376. }
  1377. if ( (!RtlEqualSid((GroupIds->Groups[CHILD_INDEX].Sid), ChildSid)) ||
  1378. (GroupIds->Groups[CHILD_INDEX].Attributes !=
  1379. OptionalGroupAttributes) ) {
  1380. ValuesCompare = FALSE;
  1381. }
  1382. if ( (!RtlEqualSid((GroupIds->Groups[NEANDERTHOL_INDEX].Sid),
  1383. NeandertholSid)) ||
  1384. (GroupIds->Groups[NEANDERTHOL_INDEX].Attributes !=
  1385. OptionalGroupAttributes) ) {
  1386. ValuesCompare = FALSE;
  1387. }
  1388. if ( (!RtlEqualSid((GroupIds->Groups[WORLD_INDEX].Sid), WorldSid)) ||
  1389. (GroupIds->Groups[WORLD_INDEX].Attributes != NormalGroupAttributes) ) {
  1390. ValuesCompare = FALSE;
  1391. }
  1392. if ( ValuesCompare ) {
  1393. DbgPrint("Succeeded.\n");
  1394. } else {
  1395. DbgPrint("********** Failed ************\n");
  1396. DbgPrint("Unexpected value returned by query.\n");
  1397. DbgPrint("Status is: 0x%lx \n", Status);
  1398. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1399. DbgPrint("Returned group count is: 0x%lx \n", GroupIds->GroupCount);
  1400. CompletionStatus = FALSE;
  1401. }
  1402. } else {
  1403. DbgPrint("********** Failed ************\n");
  1404. DbgPrint("Status is: 0x%lx \n", Status);
  1405. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1406. CompletionStatus = FALSE;
  1407. }
  1408. ASSERT(NT_SUCCESS(Status));
  1409. //
  1410. // Query with too little buffer
  1411. // (This relies upon the ReturnLength returned from previous call)
  1412. //
  1413. DbgPrint("Se: Query groups with too small buffer ... ");
  1414. Status = NtQueryInformationToken(
  1415. TokenWithGroups, // Handle
  1416. TokenGroups, // TokenInformationClass
  1417. GroupIds, // TokenInformation
  1418. ReturnLength-1, // TokenInformationLength
  1419. &ReturnLength // ReturnLength
  1420. );
  1421. #ifdef TOKEN_DEBUG
  1422. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1423. #endif //TOKEN_DEBUG
  1424. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1425. DbgPrint("Succeeded.\n");
  1426. } else {
  1427. DbgPrint("********** Failed ************\n");
  1428. DbgPrint("Status is: 0x%lx \n", Status);
  1429. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1430. CompletionStatus = FALSE;
  1431. }
  1432. ASSERT(!NT_SUCCESS(Status));
  1433. //
  1434. // Query groups with zero length buffer
  1435. //
  1436. DbgPrint("Se: Query restgroups with zero length buffer ... ");
  1437. Status = NtQueryInformationToken(
  1438. TokenWithRestrictedGroups,// Handle
  1439. TokenGroups, // TokenInformationClass
  1440. GroupIds, // TokenInformation
  1441. 0, // TokenInformationLength
  1442. &ReturnLength // ReturnLength
  1443. );
  1444. #ifdef TOKEN_DEBUG
  1445. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1446. #endif //TOKEN_DEBUG
  1447. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1448. DbgPrint("Succeeded.\n");
  1449. } else {
  1450. DbgPrint("********** Failed ************\n");
  1451. DbgPrint("Status is: 0x%lx \n", Status);
  1452. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1453. CompletionStatus = FALSE;
  1454. }
  1455. ASSERT(!NT_SUCCESS(Status));
  1456. GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  1457. ReturnLength
  1458. );
  1459. //
  1460. // Query Group SIDs
  1461. // (This relies upon the ReturnLength returned from previous call)
  1462. //
  1463. DbgPrint("Se: Query rest groups ... ");
  1464. Status = NtQueryInformationToken(
  1465. TokenWithRestrictedGroups,// Handle
  1466. TokenGroups, // TokenInformationClass
  1467. GroupIds, // TokenInformation
  1468. ReturnLength, // TokenInformationLength
  1469. &ReturnLength // ReturnLength
  1470. );
  1471. #ifdef TOKEN_DEBUG
  1472. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1473. #endif //TOKEN_DEBUG
  1474. if (NT_SUCCESS(Status)) {
  1475. //
  1476. // Check returned value
  1477. // Group count = 4
  1478. // SID 0 = Flintstone
  1479. // SID 1 = ChildSid
  1480. // SID 2 = NeandertholSid
  1481. // SID 3 = WorldSid
  1482. //
  1483. ValuesCompare = TRUE;
  1484. if (GroupIds->GroupCount != GROUP_COUNT) {
  1485. ValuesCompare = FALSE;
  1486. }
  1487. if ( (!RtlEqualSid((GroupIds->Groups[FLINTSTONE_INDEX].Sid),
  1488. FlintstoneSid)) ||
  1489. (GroupIds->Groups[FLINTSTONE_INDEX].Attributes !=
  1490. ((OwnerGroupAttributes & ~(SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT)) | SE_GROUP_USE_FOR_DENY_ONLY) ) ) {
  1491. ValuesCompare = FALSE;
  1492. }
  1493. if ( (!RtlEqualSid((GroupIds->Groups[CHILD_INDEX].Sid), ChildSid)) ||
  1494. (GroupIds->Groups[CHILD_INDEX].Attributes !=
  1495. ((OptionalGroupAttributes & ~(SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT)) | SE_GROUP_USE_FOR_DENY_ONLY)) ) {
  1496. ValuesCompare = FALSE;
  1497. }
  1498. if ( (!RtlEqualSid((GroupIds->Groups[NEANDERTHOL_INDEX].Sid),
  1499. NeandertholSid)) ||
  1500. (GroupIds->Groups[NEANDERTHOL_INDEX].Attributes !=
  1501. OptionalGroupAttributes) ) {
  1502. ValuesCompare = FALSE;
  1503. }
  1504. if ( (!RtlEqualSid((GroupIds->Groups[WORLD_INDEX].Sid), WorldSid)) ||
  1505. (GroupIds->Groups[WORLD_INDEX].Attributes != NormalGroupAttributes) ) {
  1506. ValuesCompare = FALSE;
  1507. }
  1508. if ( ValuesCompare ) {
  1509. DbgPrint("Succeeded.\n");
  1510. } else {
  1511. DbgPrint("********** Failed ************\n");
  1512. DbgPrint("Unexpected value returned by query.\n");
  1513. DbgPrint("Status is: 0x%lx \n", Status);
  1514. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1515. DbgPrint("Returned group count is: 0x%lx \n", GroupIds->GroupCount);
  1516. CompletionStatus = FALSE;
  1517. }
  1518. } else {
  1519. DbgPrint("********** Failed ************\n");
  1520. DbgPrint("Status is: 0x%lx \n", Status);
  1521. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1522. CompletionStatus = FALSE;
  1523. }
  1524. ASSERT(NT_SUCCESS(Status));
  1525. ////////////////////////////////////////////////////////////////////////
  1526. // //
  1527. // Query RestrictedSids //
  1528. // //
  1529. ////////////////////////////////////////////////////////////////////////
  1530. //
  1531. // Query groups with zero length buffer
  1532. //
  1533. DbgPrint("Se: Query null restricted with zero length buffer ... ");
  1534. Status = NtQueryInformationToken(
  1535. TokenWithGroups, // Handle
  1536. TokenRestrictedSids, // TokenInformationClass
  1537. RestrictedSids, // TokenInformation
  1538. 0, // TokenInformationLength
  1539. &ReturnLength // ReturnLength
  1540. );
  1541. #ifdef TOKEN_DEBUG
  1542. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1543. #endif //TOKEN_DEBUG
  1544. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1545. DbgPrint("Succeeded.\n");
  1546. } else {
  1547. DbgPrint("********** Failed ************\n");
  1548. DbgPrint("Status is: 0x%lx \n", Status);
  1549. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1550. CompletionStatus = FALSE;
  1551. }
  1552. ASSERT(!NT_SUCCESS(Status));
  1553. //
  1554. // Query groups with zero length buffer
  1555. //
  1556. DbgPrint("Se: Query restricted sids with zero length buffer ... ");
  1557. Status = NtQueryInformationToken(
  1558. TokenWithRestrictedSids, // Handle
  1559. TokenRestrictedSids, // TokenInformationClass
  1560. RestrictedSids, // TokenInformation
  1561. 0, // TokenInformationLength
  1562. &ReturnLength // ReturnLength
  1563. );
  1564. #ifdef TOKEN_DEBUG
  1565. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1566. #endif //TOKEN_DEBUG
  1567. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1568. DbgPrint("Succeeded.\n");
  1569. } else {
  1570. DbgPrint("********** Failed ************\n");
  1571. DbgPrint("Status is: 0x%lx \n", Status);
  1572. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1573. CompletionStatus = FALSE;
  1574. }
  1575. ASSERT(!NT_SUCCESS(Status));
  1576. RestrictedSids = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  1577. ReturnLength
  1578. );
  1579. //
  1580. // Query Group SIDs
  1581. // (This relies upon the ReturnLength returned from previous call)
  1582. //
  1583. DbgPrint("Se: Query restricted sids ... ");
  1584. Status = NtQueryInformationToken(
  1585. TokenWithRestrictedSids, // Handle
  1586. TokenRestrictedSids, // TokenInformationClass
  1587. RestrictedSids, // TokenInformation
  1588. ReturnLength, // TokenInformationLength
  1589. &ReturnLength // ReturnLength
  1590. );
  1591. #ifdef TOKEN_DEBUG
  1592. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1593. #endif //TOKEN_DEBUG
  1594. if (NT_SUCCESS(Status)) {
  1595. //
  1596. // Check returned value
  1597. // Group count = 2
  1598. // SID 0 = Flintstone
  1599. // SID 1 = ChildSid
  1600. //
  1601. ValuesCompare = TRUE;
  1602. if (RestrictedSids->GroupCount != RESTRICTED_SID_COUNT) {
  1603. ValuesCompare = FALSE;
  1604. }
  1605. if ( (!RtlEqualSid((RestrictedSids->Groups[FLINTSTONE_INDEX].Sid),
  1606. FlintstoneSid)) ||
  1607. (RestrictedSids->Groups[FLINTSTONE_INDEX].Attributes !=
  1608. (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY)) ) {
  1609. ValuesCompare = FALSE;
  1610. }
  1611. if ( (!RtlEqualSid((RestrictedSids->Groups[CHILD_INDEX].Sid), ChildSid)) ||
  1612. (RestrictedSids->Groups[CHILD_INDEX].Attributes !=
  1613. (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY)) ) {
  1614. ValuesCompare = FALSE;
  1615. }
  1616. if ( ValuesCompare ) {
  1617. DbgPrint("Succeeded.\n");
  1618. } else {
  1619. DbgPrint("********** Failed ************\n");
  1620. DbgPrint("Unexpected value returned by query.\n");
  1621. DbgPrint("Status is: 0x%lx \n", Status);
  1622. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1623. DbgPrint("Returned group count is: 0x%lx \n", RestrictedSids->GroupCount);
  1624. CompletionStatus = FALSE;
  1625. }
  1626. } else {
  1627. DbgPrint("********** Failed ************\n");
  1628. DbgPrint("Status is: 0x%lx \n", Status);
  1629. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1630. CompletionStatus = FALSE;
  1631. }
  1632. ASSERT(NT_SUCCESS(Status));
  1633. //
  1634. // Query restricted sids with zero length buffer
  1635. //
  1636. DbgPrint("Se: Query more restricted sids with zero length buffer ... ");
  1637. Status = NtQueryInformationToken(
  1638. TokenWithMoreRestrictedSids, // Handle
  1639. TokenRestrictedSids, // TokenInformationClass
  1640. RestrictedSids, // TokenInformation
  1641. 0, // TokenInformationLength
  1642. &ReturnLength // ReturnLength
  1643. );
  1644. #ifdef TOKEN_DEBUG
  1645. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1646. #endif //TOKEN_DEBUG
  1647. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1648. DbgPrint("Succeeded.\n");
  1649. } else {
  1650. DbgPrint("********** Failed ************\n");
  1651. DbgPrint("Status is: 0x%lx \n", Status);
  1652. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1653. CompletionStatus = FALSE;
  1654. }
  1655. ASSERT(!NT_SUCCESS(Status));
  1656. RestrictedSids = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  1657. ReturnLength
  1658. );
  1659. //
  1660. // Query Group SIDs
  1661. // (This relies upon the ReturnLength returned from previous call)
  1662. //
  1663. DbgPrint("Se: Query more restricted sids ... ");
  1664. Status = NtQueryInformationToken(
  1665. TokenWithMoreRestrictedSids, // Handle
  1666. TokenRestrictedSids, // TokenInformationClass
  1667. RestrictedSids, // TokenInformation
  1668. ReturnLength, // TokenInformationLength
  1669. &ReturnLength // ReturnLength
  1670. );
  1671. #ifdef TOKEN_DEBUG
  1672. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1673. #endif //TOKEN_DEBUG
  1674. if (NT_SUCCESS(Status)) {
  1675. //
  1676. // Check returned value
  1677. // Group count = 2
  1678. // SID 0 = Flintstone
  1679. // SID 1 = ChildSid
  1680. // SID 2 = Neaderthol
  1681. // SID 3 = World
  1682. //
  1683. ValuesCompare = TRUE;
  1684. if (RestrictedSids->GroupCount != GROUP_COUNT) {
  1685. ValuesCompare = FALSE;
  1686. }
  1687. if ( (!RtlEqualSid((RestrictedSids->Groups[FLINTSTONE_INDEX].Sid),
  1688. FlintstoneSid)) ||
  1689. (RestrictedSids->Groups[FLINTSTONE_INDEX].Attributes !=
  1690. (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY)) ) {
  1691. ValuesCompare = FALSE;
  1692. }
  1693. if ( (!RtlEqualSid((RestrictedSids->Groups[CHILD_INDEX].Sid), ChildSid)) ||
  1694. (RestrictedSids->Groups[CHILD_INDEX].Attributes !=
  1695. (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY)) ) {
  1696. ValuesCompare = FALSE;
  1697. }
  1698. if ( (!RtlEqualSid((RestrictedSids->Groups[NEANDERTHOL_INDEX].Sid),
  1699. NeandertholSid)) ||
  1700. (RestrictedSids->Groups[NEANDERTHOL_INDEX].Attributes !=
  1701. (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY)) ) {
  1702. ValuesCompare = FALSE;
  1703. }
  1704. if ( (!RtlEqualSid((RestrictedSids->Groups[WORLD_INDEX].Sid), WorldSid)) ||
  1705. (RestrictedSids->Groups[WORLD_INDEX].Attributes !=
  1706. (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY)) ) {
  1707. ValuesCompare = FALSE;
  1708. }
  1709. if ( ValuesCompare ) {
  1710. DbgPrint("Succeeded.\n");
  1711. } else {
  1712. DbgPrint("********** Failed ************\n");
  1713. DbgPrint("Unexpected value returned by query.\n");
  1714. DbgPrint("Status is: 0x%lx \n", Status);
  1715. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1716. DbgPrint("Returned group count is: 0x%lx \n", RestrictedSids->GroupCount);
  1717. CompletionStatus = FALSE;
  1718. }
  1719. } else {
  1720. DbgPrint("********** Failed ************\n");
  1721. DbgPrint("Status is: 0x%lx \n", Status);
  1722. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1723. CompletionStatus = FALSE;
  1724. }
  1725. ASSERT(NT_SUCCESS(Status));
  1726. //
  1727. // Query with too little buffer
  1728. // (This relies upon the ReturnLength returned from previous call)
  1729. //
  1730. DbgPrint("Se: Query groups with too small buffer ... ");
  1731. Status = NtQueryInformationToken(
  1732. TokenWithGroups, // Handle
  1733. TokenGroups, // TokenInformationClass
  1734. GroupIds, // TokenInformation
  1735. ReturnLength-1, // TokenInformationLength
  1736. &ReturnLength // ReturnLength
  1737. );
  1738. #ifdef TOKEN_DEBUG
  1739. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1740. #endif //TOKEN_DEBUG
  1741. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1742. DbgPrint("Succeeded.\n");
  1743. } else {
  1744. DbgPrint("********** Failed ************\n");
  1745. DbgPrint("Status is: 0x%lx \n", Status);
  1746. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1747. CompletionStatus = FALSE;
  1748. }
  1749. ASSERT(!NT_SUCCESS(Status));
  1750. ////////////////////////////////////////////////////////////////////////
  1751. // //
  1752. // Query Privileges //
  1753. // //
  1754. ////////////////////////////////////////////////////////////////////////
  1755. //
  1756. // Query groups with zero length buffer
  1757. //
  1758. DbgPrint("Se: Query privileges with zero length buffer ... ");
  1759. Status = NtQueryInformationToken(
  1760. TokenWithPrivileges, // Handle
  1761. TokenPrivileges, // TokenInformationClass
  1762. NULL, // TokenInformation
  1763. 0, // TokenInformationLength
  1764. &ReturnLength // ReturnLength
  1765. );
  1766. #ifdef TOKEN_DEBUG
  1767. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1768. #endif //TOKEN_DEBUG
  1769. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1770. DbgPrint("Succeeded.\n");
  1771. } else {
  1772. DbgPrint("********** Failed ************\n");
  1773. DbgPrint("Status is: 0x%lx \n", Status);
  1774. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1775. CompletionStatus = FALSE;
  1776. }
  1777. ASSERT(!NT_SUCCESS(Status));
  1778. Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool,
  1779. ReturnLength
  1780. );
  1781. //
  1782. // Query privileges
  1783. // (This relies upon the ReturnLength returned from previous call)
  1784. //
  1785. DbgPrint("Se: Query privileges ... ");
  1786. Status = NtQueryInformationToken(
  1787. TokenWithPrivileges, // Handle
  1788. TokenPrivileges, // TokenInformationClass
  1789. Privileges, // TokenInformation
  1790. ReturnLength, // TokenInformationLength
  1791. &ReturnLength // ReturnLength
  1792. );
  1793. #ifdef TOKEN_DEBUG
  1794. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1795. #endif //TOKEN_DEBUG
  1796. if (NT_SUCCESS(Status)) {
  1797. //
  1798. // Check returned value
  1799. // Privilege count = PRIVILEGE_COUNT
  1800. // Privilege UNSOLICITED_INDEX = UnsolicitedInputPrivilege
  1801. // Privilege SECURITY_INDEX = SecurityPrivilege
  1802. // Privilege ASSIGN_PRIMARY_INDEX = AssignPrimaryPrivilege
  1803. //
  1804. ValuesCompare = TRUE;
  1805. if (Privileges->PrivilegeCount != PRIVILEGE_COUNT) {
  1806. ValuesCompare = FALSE;
  1807. }
  1808. if ( !RtlEqualLuid(&Privileges->Privileges[UNSOLICITED_INDEX].Luid,
  1809. &UnsolicitedInputPrivilege) ||
  1810. (Privileges->Privileges[UNSOLICITED_INDEX].Attributes != 0) ) {
  1811. ValuesCompare = FALSE;
  1812. }
  1813. if ( !RtlEqualLuid(&Privileges->Privileges[SECURITY_INDEX].Luid,
  1814. &SecurityPrivilege) ||
  1815. (Privileges->Privileges[SECURITY_INDEX].Attributes != 0) ) {
  1816. ValuesCompare = FALSE;
  1817. }
  1818. if ( !RtlEqualLuid(&Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid,
  1819. &AssignPrimaryTokenPrivilege) ||
  1820. (Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes != SE_PRIVILEGE_ENABLED) ) {
  1821. ValuesCompare = FALSE;
  1822. }
  1823. if ( ValuesCompare ) {
  1824. DbgPrint("Succeeded.\n");
  1825. } else {
  1826. DbgPrint("********** Failed ************\n");
  1827. DbgPrint("Unexpected value returned by query.\n");
  1828. DbgPrint("Status is: 0x%lx \n", Status);
  1829. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1830. CompletionStatus = FALSE;
  1831. }
  1832. } else {
  1833. DbgPrint("********** Failed ************\n");
  1834. DbgPrint("Status is: 0x%lx \n", Status);
  1835. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1836. CompletionStatus = FALSE;
  1837. }
  1838. ASSERT(NT_SUCCESS(Status));
  1839. //
  1840. // Query with too little buffer
  1841. // (This relies upon the ReturnLength returned from previous call)
  1842. //
  1843. DbgPrint("Se: Query privileges with too small buffer ... ");
  1844. Status = NtQueryInformationToken(
  1845. TokenWithPrivileges, // Handle
  1846. TokenPrivileges, // TokenInformationClass
  1847. Privileges, // TokenInformation
  1848. ReturnLength-1, // TokenInformationLength
  1849. &ReturnLength // ReturnLength
  1850. );
  1851. #ifdef TOKEN_DEBUG
  1852. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1853. #endif //TOKEN_DEBUG
  1854. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1855. DbgPrint("Succeeded.\n");
  1856. } else {
  1857. DbgPrint("********** Failed ************\n");
  1858. DbgPrint("Status is: 0x%lx \n", Status);
  1859. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1860. CompletionStatus = FALSE;
  1861. }
  1862. ASSERT(!NT_SUCCESS(Status));
  1863. //
  1864. // Query groups with zero length buffer
  1865. //
  1866. DbgPrint("Se: Query rest privileges with zero length buffer ... ");
  1867. ReturnLength = 0;
  1868. Status = NtQueryInformationToken(
  1869. TokenWithRestrictedPrivileges, // Handle
  1870. TokenPrivileges, // TokenInformationClass
  1871. NULL, // TokenInformation
  1872. 0, // TokenInformationLength
  1873. &ReturnLength // ReturnLength
  1874. );
  1875. #ifdef TOKEN_DEBUG
  1876. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1877. #endif //TOKEN_DEBUG
  1878. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1879. DbgPrint("Succeeded.\n");
  1880. } else {
  1881. DbgPrint("********** Failed ************\n");
  1882. DbgPrint("Status is: 0x%lx \n", Status);
  1883. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1884. CompletionStatus = FALSE;
  1885. }
  1886. ASSERT(!NT_SUCCESS(Status));
  1887. Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool,
  1888. ReturnLength
  1889. );
  1890. //
  1891. // Query privileges
  1892. // (This relies upon the ReturnLength returned from previous call)
  1893. //
  1894. DbgPrint("Se: Query rest privileges ... ");
  1895. Status = NtQueryInformationToken(
  1896. TokenWithRestrictedPrivileges, // Handle
  1897. TokenPrivileges, // TokenInformationClass
  1898. Privileges, // TokenInformation
  1899. ReturnLength, // TokenInformationLength
  1900. &ReturnLength // ReturnLength
  1901. );
  1902. #ifdef TOKEN_DEBUG
  1903. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1904. #endif //TOKEN_DEBUG
  1905. if (NT_SUCCESS(Status)) {
  1906. //
  1907. // Check returned value
  1908. // Privilege count = PRIVILEGE_COUNT -2
  1909. // Privilege ASSIGN_PRIMARY_INDEX = AssignPrimaryPrivilege
  1910. //
  1911. ValuesCompare = TRUE;
  1912. if (Privileges->PrivilegeCount != PRIVILEGE_COUNT - 2) {
  1913. ValuesCompare = FALSE;
  1914. }
  1915. if ( !RtlEqualLuid(&Privileges->Privileges[0].Luid,
  1916. &AssignPrimaryTokenPrivilege) ||
  1917. (Privileges->Privileges[0].Attributes != SE_PRIVILEGE_ENABLED) ) {
  1918. ValuesCompare = FALSE;
  1919. }
  1920. if ( ValuesCompare ) {
  1921. DbgPrint("Succeeded.\n");
  1922. } else {
  1923. DbgPrint("********** Failed ************\n");
  1924. DbgPrint("Unexpected value returned by query.\n");
  1925. DbgPrint("Status is: 0x%lx \n", Status);
  1926. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1927. CompletionStatus = FALSE;
  1928. }
  1929. } else {
  1930. DbgPrint("********** Failed ************\n");
  1931. DbgPrint("Status is: 0x%lx \n", Status);
  1932. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1933. CompletionStatus = FALSE;
  1934. }
  1935. ASSERT(NT_SUCCESS(Status));
  1936. ////////////////////////////////////////////////////////////////////////
  1937. // //
  1938. // Query Owner //
  1939. // //
  1940. ////////////////////////////////////////////////////////////////////////
  1941. //
  1942. // Query Owner of simple token with zero length buffer
  1943. //
  1944. DbgPrint("Se: Query Owner of simple token with zero length buffer... ");
  1945. Status = NtQueryInformationToken(
  1946. SimpleToken, // Handle
  1947. TokenOwner, // TokenInformationClass
  1948. Owner, // TokenInformation
  1949. 0, // TokenInformationLength
  1950. &ReturnLength // ReturnLength
  1951. );
  1952. #ifdef TOKEN_DEBUG
  1953. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1954. #endif //TOKEN_DEBUG
  1955. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1956. DbgPrint("Succeeded.\n");
  1957. } else {
  1958. DbgPrint("********** Failed ************\n");
  1959. DbgPrint("Status is: 0x%lx \n", Status);
  1960. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1961. CompletionStatus = FALSE;
  1962. }
  1963. ASSERT(!NT_SUCCESS(Status));
  1964. Owner = (PTOKEN_OWNER)TstAllocatePool( PagedPool,
  1965. ReturnLength
  1966. );
  1967. //
  1968. // Query Owner SID
  1969. // (This relies upon the ReturnLength returned from previous call)
  1970. //
  1971. DbgPrint("Se: Query owner of simple token ... ");
  1972. Status = NtQueryInformationToken(
  1973. SimpleToken, // Handle
  1974. TokenOwner, // TokenInformationClass
  1975. Owner, // TokenInformation
  1976. ReturnLength, // TokenInformationLength
  1977. &ReturnLength // ReturnLength
  1978. );
  1979. #ifdef TOKEN_DEBUG
  1980. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  1981. #endif //TOKEN_DEBUG
  1982. if (NT_SUCCESS(Status)) {
  1983. //
  1984. // Check returned value
  1985. //
  1986. if (RtlEqualSid((Owner->Owner), PebblesSid) ) {
  1987. DbgPrint("Succeeded.\n");
  1988. } else {
  1989. DbgPrint("********** Failed ************\n");
  1990. DbgPrint("Unexpected value returned by query.\n");
  1991. DbgPrint("Status is: 0x%lx \n", Status);
  1992. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1993. CompletionStatus = FALSE;
  1994. }
  1995. } else {
  1996. DbgPrint("********** Failed ************\n");
  1997. DbgPrint("Status is: 0x%lx \n", Status);
  1998. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  1999. CompletionStatus = FALSE;
  2000. }
  2001. ASSERT(NT_SUCCESS(Status));
  2002. //
  2003. // Query owner of simple token with too little buffer
  2004. // (This relies upon the ReturnLength returned from previous call)
  2005. //
  2006. DbgPrint("Se: Query owner of simple token with too small buffer ... ");
  2007. Status = NtQueryInformationToken(
  2008. SimpleToken, // Handle
  2009. TokenOwner, // TokenInformationClass
  2010. Owner, // TokenInformation
  2011. ReturnLength-1, // TokenInformationLength
  2012. &ReturnLength // ReturnLength
  2013. );
  2014. #ifdef TOKEN_DEBUG
  2015. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2016. #endif //TOKEN_DEBUG
  2017. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2018. DbgPrint("Succeeded.\n");
  2019. } else {
  2020. DbgPrint("********** Failed ************\n");
  2021. DbgPrint("Status is: 0x%lx \n", Status);
  2022. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2023. CompletionStatus = FALSE;
  2024. }
  2025. ASSERT(!NT_SUCCESS(Status));
  2026. //
  2027. // Query default owner of token with zero length buffer
  2028. //
  2029. DbgPrint("Se: Query Default Owner of token with zero length buffer...");
  2030. Status = NtQueryInformationToken(
  2031. TokenWithDefaultOwner, // Handle
  2032. TokenOwner, // TokenInformationClass
  2033. Owner, // TokenInformation
  2034. 0, // TokenInformationLength
  2035. &ReturnLength // ReturnLength
  2036. );
  2037. #ifdef TOKEN_DEBUG
  2038. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2039. #endif //TOKEN_DEBUG
  2040. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2041. DbgPrint("Succeeded.\n");
  2042. } else {
  2043. DbgPrint("********** Failed ************\n");
  2044. DbgPrint("Status is: 0x%lx \n", Status);
  2045. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2046. CompletionStatus = FALSE;
  2047. }
  2048. ASSERT(!NT_SUCCESS(Status));
  2049. Owner = (PTOKEN_OWNER)TstAllocatePool( PagedPool,
  2050. ReturnLength
  2051. );
  2052. //
  2053. // Query default owner of token
  2054. // (This relies upon the ReturnLength returned from previous call)
  2055. //
  2056. DbgPrint("Se: Query default owner of token ... ");
  2057. Status = NtQueryInformationToken(
  2058. TokenWithDefaultOwner, // Handle
  2059. TokenOwner, // TokenInformationClass
  2060. Owner, // TokenInformation
  2061. ReturnLength, // TokenInformationLength
  2062. &ReturnLength // ReturnLength
  2063. );
  2064. #ifdef TOKEN_DEBUG
  2065. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2066. #endif //TOKEN_DEBUG
  2067. if (NT_SUCCESS(Status)) {
  2068. //
  2069. // Check returned value
  2070. //
  2071. if (RtlEqualSid((Owner->Owner), FlintstoneSid) ) {
  2072. DbgPrint("Succeeded.\n");
  2073. } else {
  2074. DbgPrint("********** Failed ************\n");
  2075. DbgPrint("Unexpected value returned by query.\n");
  2076. DbgPrint("Status is: 0x%lx \n", Status);
  2077. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2078. CompletionStatus = FALSE;
  2079. }
  2080. } else {
  2081. DbgPrint("********** Failed ************\n");
  2082. DbgPrint("Status is: 0x%lx \n", Status);
  2083. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2084. CompletionStatus = FALSE;
  2085. }
  2086. ASSERT(NT_SUCCESS(Status));
  2087. //
  2088. // Query default owner of token with too little buffer
  2089. // (This relies upon the ReturnLength returned from previous call)
  2090. //
  2091. DbgPrint("Se: Query default owner of token with too small buffer ... ");
  2092. Status = NtQueryInformationToken(
  2093. TokenWithDefaultOwner, // Handle
  2094. TokenOwner, // TokenInformationClass
  2095. Owner, // TokenInformation
  2096. ReturnLength-1, // TokenInformationLength
  2097. &ReturnLength // ReturnLength
  2098. );
  2099. #ifdef TOKEN_DEBUG
  2100. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2101. #endif //TOKEN_DEBUG
  2102. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2103. DbgPrint("Succeeded.\n");
  2104. } else {
  2105. DbgPrint("********** Failed ************\n");
  2106. DbgPrint("Status is: 0x%lx \n", Status);
  2107. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2108. CompletionStatus = FALSE;
  2109. }
  2110. ASSERT(!NT_SUCCESS(Status));
  2111. ////////////////////////////////////////////////////////////////////////
  2112. // //
  2113. // Query Default Dacl //
  2114. // //
  2115. ////////////////////////////////////////////////////////////////////////
  2116. //
  2117. // Query default dacl with zero length buffer
  2118. //
  2119. DbgPrint("Se: Query default DACL with zero length buffer ... ");
  2120. Status = NtQueryInformationToken(
  2121. TokenWithDefaultDacl, // Handle
  2122. TokenDefaultDacl, // TokenInformationClass
  2123. DefaultDacl, // TokenInformation
  2124. 0, // TokenInformationLength
  2125. &ReturnLength // ReturnLength
  2126. );
  2127. #ifdef TOKEN_DEBUG
  2128. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2129. #endif //TOKEN_DEBUG
  2130. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2131. DbgPrint("Succeeded.\n");
  2132. } else {
  2133. DbgPrint("********** Failed ************\n");
  2134. DbgPrint("Status is: 0x%lx \n", Status);
  2135. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2136. CompletionStatus = FALSE;
  2137. }
  2138. ASSERT(!NT_SUCCESS(Status));
  2139. DefaultDacl = (PTOKEN_DEFAULT_DACL)TstAllocatePool( PagedPool,
  2140. ReturnLength
  2141. );
  2142. //
  2143. // Query default dacl
  2144. // (This relies upon the ReturnLength returned from previous call)
  2145. //
  2146. DbgPrint("Se: Query default dacl ... ");
  2147. Status = NtQueryInformationToken(
  2148. TokenWithDefaultDacl, // Handle
  2149. TokenDefaultDacl, // TokenInformationClass
  2150. DefaultDacl, // TokenInformation
  2151. ReturnLength, // TokenInformationLength
  2152. &ReturnLength // ReturnLength
  2153. );
  2154. #ifdef TOKEN_DEBUG
  2155. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2156. #endif //TOKEN_DEBUG
  2157. if (NT_SUCCESS(Status)) {
  2158. //
  2159. // Check returned value
  2160. //
  2161. if (RtlValidAcl(DefaultDacl->DefaultDacl)) {
  2162. if (DefaultDacl->DefaultDacl->AceCount == 0) {
  2163. DbgPrint("Succeeded.\n");
  2164. } else {
  2165. DbgPrint("********** Failed ************\n");
  2166. DbgPrint("Unexpected value returned by query.\n");
  2167. DbgPrint("Status is: 0x%lx \n", Status);
  2168. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2169. CompletionStatus = FALSE;
  2170. }
  2171. } else {
  2172. DbgPrint("********** Failed ************\n");
  2173. DbgPrint("Unexpected value returned by query.\n");
  2174. DbgPrint("Status is: 0x%lx \n", Status);
  2175. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2176. CompletionStatus = FALSE;
  2177. }
  2178. } else {
  2179. DbgPrint("********** Failed ************\n");
  2180. DbgPrint("Status is: 0x%lx \n", Status);
  2181. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2182. CompletionStatus = FALSE;
  2183. }
  2184. ASSERT(NT_SUCCESS(Status));
  2185. //
  2186. // Query with too little buffer
  2187. // (This relies upon the ReturnLength returned from previous call)
  2188. //
  2189. DbgPrint("Se: Query default Dacl with too small buffer ... ");
  2190. Status = NtQueryInformationToken(
  2191. TokenWithDefaultDacl, // Handle
  2192. TokenDefaultDacl, // TokenInformationClass
  2193. DefaultDacl, // TokenInformation
  2194. ReturnLength-1, // TokenInformationLength
  2195. &ReturnLength // ReturnLength
  2196. );
  2197. #ifdef TOKEN_DEBUG
  2198. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2199. #endif //TOKEN_DEBUG
  2200. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2201. DbgPrint("Succeeded.\n");
  2202. } else {
  2203. DbgPrint("********** Failed ************\n");
  2204. DbgPrint("Status is: 0x%lx \n", Status);
  2205. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2206. CompletionStatus = FALSE;
  2207. }
  2208. ASSERT(!NT_SUCCESS(Status));
  2209. //
  2210. // Query token with no default dacl
  2211. //
  2212. DbgPrint("Se: Query default dacl from token with none ... ");
  2213. Status = NtQueryInformationToken(
  2214. SimpleToken, // Handle
  2215. TokenDefaultDacl, // TokenInformationClass
  2216. DefaultDacl, // TokenInformation
  2217. sizeof(TOKEN_DEFAULT_DACL), // TokenInformationLength
  2218. &ReturnLength // ReturnLength
  2219. );
  2220. #ifdef TOKEN_DEBUG
  2221. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2222. #endif //TOKEN_DEBUG
  2223. if (NT_SUCCESS(Status)) {
  2224. DbgPrint("Succeeded.\n");
  2225. } else {
  2226. DbgPrint("********** Failed ************\n");
  2227. DbgPrint("Status is: 0x%lx \n", Status);
  2228. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2229. CompletionStatus = FALSE;
  2230. }
  2231. ASSERT(NT_SUCCESS(Status));
  2232. ////////////////////////////////////////////////////////////////////////
  2233. // //
  2234. // Query Token Source //
  2235. // //
  2236. ////////////////////////////////////////////////////////////////////////
  2237. //
  2238. // Query Token Source with zero length buffer
  2239. //
  2240. DbgPrint("Se: Query Token Source with zero length buffer ... ");
  2241. Status = NtQueryInformationToken(
  2242. TokenWithPrivileges, // Handle
  2243. TokenSource, // TokenInformationClass
  2244. &QueriedSource, // TokenInformation
  2245. 0, // TokenInformationLength
  2246. &ReturnLength // ReturnLength
  2247. );
  2248. #ifdef TOKEN_DEBUG
  2249. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2250. #endif //TOKEN_DEBUG
  2251. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2252. if (ReturnLength == sizeof(TOKEN_SOURCE)) {
  2253. DbgPrint("Succeeded.\n");
  2254. } else {
  2255. DbgPrint("********** Failed ************\n");
  2256. DbgPrint("Status is: 0x%lx \n", Status);
  2257. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2258. DbgPrint("TOKEN_SOURCE data size is 0x%lx \n", sizeof(TOKEN_SOURCE));
  2259. CompletionStatus = FALSE;
  2260. }
  2261. } else {
  2262. DbgPrint("********** Failed ************\n");
  2263. DbgPrint("Status is: 0x%lx \n", Status);
  2264. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2265. CompletionStatus = FALSE;
  2266. }
  2267. ASSERT(!NT_SUCCESS(Status));
  2268. //
  2269. // Query token source
  2270. //
  2271. DbgPrint("Se: Query token source ... ");
  2272. Status = NtQueryInformationToken(
  2273. TokenWithPrivileges, // Handle
  2274. TokenSource, // TokenInformationClass
  2275. &QueriedSource, // TokenInformation
  2276. sizeof(TOKEN_SOURCE), // TokenInformationLength
  2277. &ReturnLength // ReturnLength
  2278. );
  2279. #ifdef TOKEN_DEBUG
  2280. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2281. #endif //TOKEN_DEBUG
  2282. if (NT_SUCCESS(Status)) {
  2283. //
  2284. // Check returned value against TestSource
  2285. //
  2286. ValuesCompare = TRUE;
  2287. if ( (QueriedSource.SourceName[0] != TestSource.SourceName[0]) ||
  2288. (QueriedSource.SourceName[1] != TestSource.SourceName[1]) ||
  2289. (QueriedSource.SourceName[2] != TestSource.SourceName[2]) ||
  2290. (QueriedSource.SourceName[3] != TestSource.SourceName[3]) ||
  2291. (QueriedSource.SourceName[4] != TestSource.SourceName[4]) ||
  2292. (QueriedSource.SourceName[5] != TestSource.SourceName[5]) ||
  2293. (QueriedSource.SourceName[6] != TestSource.SourceName[6]) ||
  2294. (QueriedSource.SourceName[7] != TestSource.SourceName[7]) ) {
  2295. ValuesCompare = FALSE;
  2296. }
  2297. if ( !RtlEqualLuid(&QueriedSource.SourceIdentifier,
  2298. &TestSource.SourceIdentifier) ) {
  2299. ValuesCompare = FALSE;
  2300. }
  2301. if ( ValuesCompare ) {
  2302. DbgPrint("Succeeded.\n");
  2303. } else {
  2304. DbgPrint("********** Failed ************\n");
  2305. DbgPrint("Unexpected value returned by query.\n");
  2306. DbgPrint("Status is: 0x%lx \n", Status);
  2307. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2308. CompletionStatus = FALSE;
  2309. }
  2310. } else {
  2311. DbgPrint("********** Failed ************\n");
  2312. DbgPrint("Status is: 0x%lx \n", Status);
  2313. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2314. CompletionStatus = FALSE;
  2315. }
  2316. ASSERT(NT_SUCCESS(Status));
  2317. //
  2318. // Query with too little buffer
  2319. // (This relies upon the ReturnLength returned from previous call)
  2320. //
  2321. DbgPrint("Se: Query token source with too small buffer ... ");
  2322. Status = NtQueryInformationToken(
  2323. TokenWithPrivileges, // Handle
  2324. TokenSource, // TokenInformationClass
  2325. &QueriedSource, // TokenInformation
  2326. ReturnLength - 1, // TokenInformationLength
  2327. &ReturnLength // ReturnLength
  2328. );
  2329. #ifdef TOKEN_DEBUG
  2330. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2331. #endif //TOKEN_DEBUG
  2332. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2333. DbgPrint("Succeeded.\n");
  2334. } else {
  2335. DbgPrint("********** Failed ************\n");
  2336. DbgPrint("Status is: 0x%lx \n", Status);
  2337. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2338. CompletionStatus = FALSE;
  2339. }
  2340. ASSERT(!NT_SUCCESS(Status));
  2341. ////////////////////////////////////////////////////////////////////////
  2342. // //
  2343. // Query Token Type //
  2344. // //
  2345. ////////////////////////////////////////////////////////////////////////
  2346. //
  2347. // Query Token type with zero length buffer
  2348. //
  2349. DbgPrint("Se: Query Token type with zero length buffer ... ");
  2350. Status = NtQueryInformationToken(
  2351. TokenWithPrivileges, // Handle
  2352. TokenType, // TokenInformationClass
  2353. &QueriedType, // TokenInformation
  2354. 0, // TokenInformationLength
  2355. &ReturnLength // ReturnLength
  2356. );
  2357. #ifdef TOKEN_DEBUG
  2358. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2359. #endif //TOKEN_DEBUG
  2360. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2361. if (ReturnLength == sizeof(TOKEN_TYPE)) {
  2362. DbgPrint("Succeeded.\n");
  2363. } else {
  2364. DbgPrint("********** Failed ************\n");
  2365. DbgPrint("Status is: 0x%lx \n", Status);
  2366. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2367. DbgPrint("TOKEN_TYPE data size is 0x%lx \n", sizeof(TOKEN_TYPE));
  2368. CompletionStatus = FALSE;
  2369. }
  2370. } else {
  2371. DbgPrint("********** Failed ************\n");
  2372. DbgPrint("Status is: 0x%lx \n", Status);
  2373. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2374. CompletionStatus = FALSE;
  2375. }
  2376. ASSERT(!NT_SUCCESS(Status));
  2377. //
  2378. // Query token type
  2379. //
  2380. DbgPrint("Se: Query token type ... ");
  2381. Status = NtQueryInformationToken(
  2382. TokenWithPrivileges, // Handle
  2383. TokenType, // TokenInformationClass
  2384. &QueriedType, // TokenInformation
  2385. sizeof(TOKEN_TYPE), // TokenInformationLength
  2386. &ReturnLength // ReturnLength
  2387. );
  2388. #ifdef TOKEN_DEBUG
  2389. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2390. #endif //TOKEN_DEBUG
  2391. if (NT_SUCCESS(Status)) {
  2392. //
  2393. // Check returned value against TestSource
  2394. //
  2395. if ( QueriedType == TokenPrimary ) {
  2396. DbgPrint("Succeeded.\n");
  2397. } else {
  2398. DbgPrint("********** Failed ************\n");
  2399. DbgPrint("Unexpected value returned by query.\n");
  2400. DbgPrint("Status is: 0x%lx \n", Status);
  2401. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2402. DbgPrint("Returned token type is: 0x%lx \n", QueriedType);
  2403. CompletionStatus = FALSE;
  2404. }
  2405. } else {
  2406. DbgPrint("********** Failed ************\n");
  2407. DbgPrint("Status is: 0x%lx \n", Status);
  2408. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2409. CompletionStatus = FALSE;
  2410. }
  2411. ASSERT(NT_SUCCESS(Status));
  2412. //
  2413. // Query with too little buffer
  2414. // (This relies upon the ReturnLength returned from previous call)
  2415. //
  2416. DbgPrint("Se: Query token type with too small buffer ... ");
  2417. Status = NtQueryInformationToken(
  2418. TokenWithPrivileges, // Handle
  2419. TokenType, // TokenInformationClass
  2420. &QueriedType, // TokenInformation
  2421. ReturnLength - 1, // TokenInformationLength
  2422. &ReturnLength // ReturnLength
  2423. );
  2424. #ifdef TOKEN_DEBUG
  2425. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2426. #endif //TOKEN_DEBUG
  2427. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2428. DbgPrint("Succeeded.\n");
  2429. } else {
  2430. DbgPrint("********** Failed ************\n");
  2431. DbgPrint("Status is: 0x%lx \n", Status);
  2432. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2433. CompletionStatus = FALSE;
  2434. }
  2435. ASSERT(!NT_SUCCESS(Status));
  2436. ////////////////////////////////////////////////////////////////////////
  2437. // //
  2438. // Query Impersonation Level //
  2439. // //
  2440. ////////////////////////////////////////////////////////////////////////
  2441. //
  2442. // Query Impersonation Level of primary token
  2443. //
  2444. DbgPrint("Se: Query Impersonation level of primary token ... ");
  2445. Status = NtQueryInformationToken(
  2446. TokenWithPrivileges, // Handle
  2447. TokenImpersonationLevel, // TokenInformationClass
  2448. &QueriedImpersonationLevel, // TokenInformation
  2449. sizeof(SECURITY_IMPERSONATION_LEVEL), // TokenInformationLength
  2450. &ReturnLength // ReturnLength
  2451. );
  2452. #ifdef TOKEN_DEBUG
  2453. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2454. #endif //TOKEN_DEBUG
  2455. if (Status == STATUS_INVALID_INFO_CLASS) {
  2456. DbgPrint("Succeeded.\n");
  2457. } else {
  2458. DbgPrint("********** Failed ************\n");
  2459. DbgPrint("Status is: 0x%lx \n", Status);
  2460. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2461. CompletionStatus = FALSE;
  2462. }
  2463. ASSERT(Status == STATUS_INVALID_INFO_CLASS);
  2464. ////////////////////////////////////////////////////////////////////////
  2465. // //
  2466. // Query Token Statistics //
  2467. // //
  2468. ////////////////////////////////////////////////////////////////////////
  2469. //
  2470. // Query Token statistics with zero length buffer
  2471. //
  2472. DbgPrint("Se: Query Token statistics with zero length buffer ... ");
  2473. Status = NtQueryInformationToken(
  2474. TokenWithPrivileges, // Handle
  2475. TokenStatistics, // TokenInformationClass
  2476. &QueriedStatistics, // TokenInformation
  2477. 0, // TokenInformationLength
  2478. &ReturnLength // ReturnLength
  2479. );
  2480. #ifdef TOKEN_DEBUG
  2481. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2482. #endif //TOKEN_DEBUG
  2483. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2484. if (ReturnLength == sizeof(TOKEN_STATISTICS)) {
  2485. DbgPrint("Succeeded.\n");
  2486. } else {
  2487. DbgPrint("********** Failed ************\n");
  2488. DbgPrint("Status is: 0x%lx \n", Status);
  2489. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2490. DbgPrint("TOKEN_STATISTICS data size is 0x%lx \n", sizeof(TOKEN_STATISTICS));
  2491. CompletionStatus = FALSE;
  2492. }
  2493. } else {
  2494. DbgPrint("********** Failed ************\n");
  2495. DbgPrint("Status is: 0x%lx \n", Status);
  2496. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2497. CompletionStatus = FALSE;
  2498. }
  2499. ASSERT(!NT_SUCCESS(Status));
  2500. //
  2501. // Query token statistics
  2502. //
  2503. DbgPrint("Se: Query token statistics ... ");
  2504. Status = NtQueryInformationToken(
  2505. TokenWithPrivileges, // Handle
  2506. TokenStatistics, // TokenInformationClass
  2507. &QueriedStatistics, // TokenInformation
  2508. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  2509. &ReturnLength // ReturnLength
  2510. );
  2511. #ifdef TOKEN_DEBUG
  2512. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2513. #endif //TOKEN_DEBUG
  2514. if (NT_SUCCESS(Status)) {
  2515. //
  2516. // Check returned value against TestSource
  2517. //
  2518. if ( ( QueriedStatistics.TokenType == TokenPrimary) &&
  2519. ( QueriedStatistics.GroupCount == 4 ) &&
  2520. ( QueriedStatistics.PrivilegeCount == PRIVILEGE_COUNT) ) {
  2521. DbgPrint("Succeeded.\n");
  2522. } else {
  2523. DbgPrint("********** Failed ************\n");
  2524. DbgPrint("Unexpected value returned by query.\n");
  2525. DbgPrint("Status is: 0x%lx \n", Status);
  2526. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2527. DbgPrint("Returned token type is: 0x%lx \n", QueriedStatistics.TokenType);
  2528. DbgPrint("Returned group count is: 0x%lx \n", QueriedStatistics.GroupCount);
  2529. DbgPrint("Returned privilege count is: 0x%lx \n", QueriedStatistics.PrivilegeCount);
  2530. CompletionStatus = FALSE;
  2531. }
  2532. } else {
  2533. DbgPrint("********** Failed ************\n");
  2534. DbgPrint("Status is: 0x%lx \n", Status);
  2535. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2536. CompletionStatus = FALSE;
  2537. }
  2538. ASSERT(NT_SUCCESS(Status));
  2539. //
  2540. // Query with too little buffer
  2541. // (This relies upon the ReturnLength returned from previous call)
  2542. //
  2543. DbgPrint("Se: Query token statistics with too small buffer ... ");
  2544. Status = NtQueryInformationToken(
  2545. TokenWithPrivileges, // Handle
  2546. TokenStatistics, // TokenInformationClass
  2547. &QueriedStatistics, // TokenInformation
  2548. ReturnLength - 1, // TokenInformationLength
  2549. &ReturnLength // ReturnLength
  2550. );
  2551. #ifdef TOKEN_DEBUG
  2552. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2553. #endif //TOKEN_DEBUG
  2554. if (Status == STATUS_BUFFER_TOO_SMALL) {
  2555. DbgPrint("Succeeded.\n");
  2556. } else {
  2557. DbgPrint("********** Failed ************\n");
  2558. DbgPrint("Status is: 0x%lx \n", Status);
  2559. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2560. CompletionStatus = FALSE;
  2561. }
  2562. ASSERT(!NT_SUCCESS(Status));
  2563. return CompletionStatus;
  2564. }
  2565. ////////////////////////////////////////////////////////////////
  2566. // //
  2567. // Set Token Test //
  2568. // //
  2569. ////////////////////////////////////////////////////////////////
  2570. BOOLEAN
  2571. TestTokenSet()
  2572. {
  2573. BOOLEAN CompletionStatus = TRUE;
  2574. ULONG InformationLength;
  2575. ULONG ReturnLength;
  2576. TOKEN_STATISTICS QueriedStatistics;
  2577. TOKEN_PRIMARY_GROUP AssignedPrimaryGroup;
  2578. PTOKEN_PRIMARY_GROUP QueriedPrimaryGroup = NULL;
  2579. TOKEN_OWNER AssignedOwner;
  2580. PTOKEN_OWNER QueriedOwner = NULL;
  2581. TOKEN_DEFAULT_DACL AssignedDefaultDacl;
  2582. PTOKEN_DEFAULT_DACL QueriedDefaultDacl = NULL;
  2583. PSID TooBigSid;
  2584. SID_IDENTIFIER_AUTHORITY BedrockAuthority = BEDROCK_AUTHORITY;
  2585. DbgPrint("\n");
  2586. //
  2587. // Set owner of a token to be an invalid group
  2588. //
  2589. DbgPrint("Se: Set default owner to be an invalid group ... ");
  2590. AssignedOwner.Owner = NeandertholSid;
  2591. InformationLength = (ULONG)sizeof(TOKEN_OWNER);
  2592. Status = NtSetInformationToken(
  2593. TokenWithGroups, // Handle
  2594. TokenOwner, // TokenInformationClass
  2595. &AssignedOwner, // TokenInformation
  2596. InformationLength // TokenInformationLength
  2597. );
  2598. if (Status == STATUS_INVALID_OWNER) {
  2599. DbgPrint("Succeeded.\n");
  2600. } else {
  2601. DbgPrint("********** Failed ************\n");
  2602. DbgPrint("Status is: 0x%lx \n", Status);
  2603. DbgPrint("InformationLength is: 0x%lx \n", InformationLength);
  2604. CompletionStatus = FALSE;
  2605. }
  2606. ASSERT(Status == STATUS_INVALID_OWNER);
  2607. //
  2608. // Set owner of a token to be an ID not in the token
  2609. //
  2610. DbgPrint("Se: Set default owner to be an ID not in the token ... ");
  2611. AssignedOwner.Owner = BarneySid;
  2612. InformationLength = (ULONG)sizeof(TOKEN_OWNER);
  2613. Status = NtSetInformationToken(
  2614. TokenWithGroups, // Handle
  2615. TokenOwner, // TokenInformationClass
  2616. &AssignedOwner, // TokenInformation
  2617. InformationLength // TokenInformationLength
  2618. );
  2619. if (Status == STATUS_INVALID_OWNER) {
  2620. DbgPrint("Succeeded.\n");
  2621. } else {
  2622. DbgPrint("********** Failed ************\n");
  2623. DbgPrint("Status is: 0x%lx \n", Status);
  2624. DbgPrint("InformationLength is: 0x%lx \n", InformationLength);
  2625. CompletionStatus = FALSE;
  2626. }
  2627. ASSERT(Status == STATUS_INVALID_OWNER);
  2628. //
  2629. // Set owner of a token to be a valid group
  2630. //
  2631. DbgPrint("Se: Set default owner to be a valid group ... ");
  2632. AssignedOwner.Owner = FlintstoneSid;
  2633. InformationLength = (ULONG)sizeof(TOKEN_OWNER);
  2634. Status = NtSetInformationToken(
  2635. TokenWithGroups, // Handle
  2636. TokenOwner, // TokenInformationClass
  2637. &AssignedOwner, // TokenInformation
  2638. InformationLength // TokenInformationLength
  2639. );
  2640. if (!NT_SUCCESS(Status)) {
  2641. DbgPrint("********** Failed ************\n");
  2642. DbgPrint("Status is: 0x%lx \n", Status);
  2643. DbgPrint("InformationLength is: 0x%lx \n", InformationLength);
  2644. CompletionStatus = FALSE;
  2645. }
  2646. ASSERT(NT_SUCCESS(Status));
  2647. //
  2648. // Query the Owner to see that it was set properly
  2649. //
  2650. Status = NtQueryInformationToken(
  2651. TokenWithGroups, // Handle
  2652. TokenOwner, // TokenInformationClass
  2653. QueriedOwner, // TokenInformation
  2654. 0, // TokenInformationLength
  2655. &ReturnLength // ReturnLength
  2656. );
  2657. #ifdef TOKEN_DEBUG
  2658. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2659. #endif //TOKEN_DEBUG
  2660. if (Status != STATUS_BUFFER_TOO_SMALL) {
  2661. DbgPrint("********** Failed Query of length ************\n");
  2662. DbgPrint("Status is: 0x%lx \n", Status);
  2663. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2664. CompletionStatus = FALSE;
  2665. }
  2666. ASSERT(!NT_SUCCESS(Status));
  2667. QueriedOwner = (PTOKEN_OWNER)TstAllocatePool( PagedPool,
  2668. ReturnLength
  2669. );
  2670. Status = NtQueryInformationToken(
  2671. TokenWithGroups, // Handle
  2672. TokenOwner, // TokenInformationClass
  2673. QueriedOwner, // TokenInformation
  2674. ReturnLength, // TokenInformationLength
  2675. &ReturnLength // ReturnLength
  2676. );
  2677. #ifdef TOKEN_DEBUG
  2678. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2679. #endif //TOKEN_DEBUG
  2680. if (NT_SUCCESS(Status)) {
  2681. //
  2682. // Check returned value
  2683. //
  2684. if (RtlEqualSid((QueriedOwner->Owner), AssignedOwner.Owner) ) {
  2685. DbgPrint("Succeeded.\n");
  2686. } else {
  2687. DbgPrint("********** Failed Comparison ************\n");
  2688. DbgPrint("Unexpected value returned by query.\n");
  2689. DbgPrint("Status is: 0x%lx \n", Status);
  2690. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2691. CompletionStatus = FALSE;
  2692. }
  2693. } else {
  2694. DbgPrint("********** Failed Query Of Value ************\n");
  2695. DbgPrint("Status is: 0x%lx \n", Status);
  2696. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2697. CompletionStatus = FALSE;
  2698. }
  2699. ASSERT(NT_SUCCESS(Status));
  2700. //
  2701. // Set Default Dacl
  2702. //
  2703. // Get a buffer for use in all Default Dacl assignment tests.
  2704. // This will be initialized to different sizes for each test.
  2705. //
  2706. AssignedDefaultDacl.DefaultDacl =
  2707. (PACL)TstAllocatePool( PagedPool, TOO_BIG_ACL_SIZE );
  2708. //
  2709. // Assign a discretionary ACL to a token that doesn't yet have one
  2710. //
  2711. DbgPrint("Se: Set original discretionary ACL in token ... ");
  2712. InformationLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  2713. RtlCreateAcl( AssignedDefaultDacl.DefaultDacl, 200, ACL_REVISION );
  2714. Status = NtQueryInformationToken(
  2715. TokenWithGroups, // Handle
  2716. TokenDefaultDacl, // TokenInformationClass
  2717. &QueriedDefaultDacl, // TokenInformation
  2718. 0, // TokenInformationLength
  2719. &ReturnLength // ReturnLength
  2720. );
  2721. #ifdef TOKEN_DEBUG
  2722. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2723. #endif //TOKEN_DEBUG
  2724. ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  2725. if (ReturnLength != sizeof(TOKEN_DEFAULT_DACL)) {
  2726. //
  2727. // Wait a minute, this token has a default Dacl
  2728. //
  2729. DbgPrint("******** Failed - token has default dacl *********\n");
  2730. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2731. CompletionStatus = FALSE;
  2732. } else {
  2733. Status = NtSetInformationToken(
  2734. TokenWithGroups, // Handle
  2735. TokenDefaultDacl, // TokenInformationClass
  2736. &AssignedDefaultDacl, // TokenInformation
  2737. InformationLength // TokenInformationLength
  2738. );
  2739. if (NT_SUCCESS(Status)) {
  2740. DbgPrint("Succeeded.\n");
  2741. } else {
  2742. DbgPrint("********** Failed ************\n");
  2743. DbgPrint("Status is: 0x%lx \n", Status);
  2744. CompletionStatus = FALSE;
  2745. }
  2746. }
  2747. ASSERT(NT_SUCCESS(Status));
  2748. //
  2749. // Replace a discretionary ACL in a token that already has one
  2750. // Make it big to help with future "too big" tests...
  2751. //
  2752. //
  2753. // find out how much space is available
  2754. //
  2755. Status = NtQueryInformationToken(
  2756. TokenWithGroups, // Handle
  2757. TokenStatistics, // TokenInformationClass
  2758. &QueriedStatistics, // TokenInformation
  2759. (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength
  2760. &ReturnLength // ReturnLength
  2761. );
  2762. #ifdef TOKEN_DEBUG
  2763. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2764. #endif //TOKEN_DEBUG
  2765. ASSERT(NT_SUCCESS(Status));
  2766. Status = NtQueryInformationToken(
  2767. TokenWithGroups, // Handle
  2768. TokenDefaultDacl, // TokenInformationClass
  2769. &QueriedDefaultDacl, // TokenInformation
  2770. 0, // TokenInformationLength
  2771. &ReturnLength // ReturnLength
  2772. );
  2773. #ifdef TOKEN_DEBUG
  2774. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2775. #endif //TOKEN_DEBUG
  2776. ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  2777. if (ReturnLength > sizeof(TOKEN_STATISTICS)) {
  2778. CurrentLength = ReturnLength - (ULONG)sizeof(TOKEN_STATISTICS);
  2779. } else {
  2780. CurrentLength = 0;
  2781. }
  2782. LengthAvailable = QueriedStatistics.DynamicAvailable + CurrentLength;
  2783. DbgPrint("Se: Replace discretionary ACL in token ... ");
  2784. InformationLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  2785. RtlCreateAcl( AssignedDefaultDacl.DefaultDacl,
  2786. (ULONG)(LengthAvailable - 50),
  2787. ACL_REVISION
  2788. );
  2789. Status = NtQueryInformationToken(
  2790. TokenWithGroups, // Handle
  2791. TokenDefaultDacl, // TokenInformationClass
  2792. &QueriedDefaultDacl, // TokenInformation
  2793. 0, // TokenInformationLength
  2794. &ReturnLength // ReturnLength
  2795. );
  2796. #ifdef TOKEN_DEBUG
  2797. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2798. #endif //TOKEN_DEBUG
  2799. if (!(ReturnLength > sizeof(TOKEN_DEFAULT_DACL))) {
  2800. //
  2801. // Wait a minute, this token doesn't have a default Dacl
  2802. //
  2803. DbgPrint("******** Failed - No default dacl *********\n");
  2804. CompletionStatus = FALSE;
  2805. } else {
  2806. Status = NtSetInformationToken(
  2807. TokenWithGroups, // Handle
  2808. TokenDefaultDacl, // TokenInformationClass
  2809. &AssignedDefaultDacl, // TokenInformation
  2810. InformationLength // TokenInformationLength
  2811. );
  2812. if (NT_SUCCESS(Status)) {
  2813. DbgPrint("Succeeded.\n");
  2814. } else {
  2815. DbgPrint("********** Failed ************\n");
  2816. DbgPrint("Status is: 0x%lx \n", Status);
  2817. CompletionStatus = FALSE;
  2818. }
  2819. }
  2820. ASSERT(NT_SUCCESS(Status));
  2821. //
  2822. // Assign a discretionary ACL that doesn't fit into the dynamic part of the
  2823. // token.
  2824. //
  2825. //
  2826. // find out how much space is available
  2827. //
  2828. Status = NtQueryInformationToken(
  2829. TokenWithGroups, // Handle
  2830. TokenStatistics, // TokenInformationClass
  2831. &QueriedStatistics, // TokenInformation
  2832. (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength
  2833. &ReturnLength // ReturnLength
  2834. );
  2835. #ifdef TOKEN_DEBUG
  2836. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2837. #endif //TOKEN_DEBUG
  2838. ASSERT(NT_SUCCESS(Status));
  2839. Status = NtQueryInformationToken(
  2840. TokenWithGroups, // Handle
  2841. TokenDefaultDacl, // TokenInformationClass
  2842. &QueriedDefaultDacl, // TokenInformation
  2843. 0, // TokenInformationLength
  2844. &ReturnLength // ReturnLength
  2845. );
  2846. #ifdef TOKEN_DEBUG
  2847. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2848. #endif //TOKEN_DEBUG
  2849. ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  2850. if (ReturnLength > sizeof(TOKEN_STATISTICS)) {
  2851. CurrentLength = ReturnLength - (ULONG)sizeof(TOKEN_STATISTICS);
  2852. } else {
  2853. CurrentLength = 0;
  2854. }
  2855. LengthAvailable = QueriedStatistics.DynamicAvailable + CurrentLength;
  2856. DbgPrint("Se: Set too big discretionary ACL ... ");
  2857. //
  2858. // Now make sure our ACL is large enough to exceed the available
  2859. // space.
  2860. //
  2861. RtlCreateAcl( AssignedDefaultDacl.DefaultDacl,
  2862. TOO_BIG_ACL_SIZE,
  2863. ACL_REVISION
  2864. );
  2865. if (TOO_BIG_ACL_SIZE < LengthAvailable) {
  2866. DbgPrint("********** Failed - Dynamic too big ************\n");
  2867. DbgPrint("Dynamic available is: 0x%lx \n",
  2868. QueriedStatistics.DynamicAvailable);
  2869. DbgPrint("Current default Dacl size is: 0x%lx \n", CurrentLength);
  2870. DbgPrint("Big ACL size is: 0x%lx \n", TOO_BIG_ACL_SIZE);
  2871. CompletionStatus = FALSE;
  2872. }
  2873. InformationLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  2874. Status = NtSetInformationToken(
  2875. TokenWithGroups, // Handle
  2876. TokenDefaultDacl, // TokenInformationClass
  2877. &AssignedDefaultDacl, // TokenInformation
  2878. InformationLength // TokenInformationLength
  2879. );
  2880. if (Status == STATUS_ALLOTTED_SPACE_EXCEEDED) {
  2881. DbgPrint("Succeeded.\n");
  2882. } else {
  2883. DbgPrint("********** Failed ************\n");
  2884. DbgPrint("Status is: 0x%lx \n", Status);
  2885. DbgPrint("Dynamic available is: 0x%lx \n",
  2886. QueriedStatistics.DynamicAvailable);
  2887. DbgPrint("Current default Dacl size is: 0x%lx \n", CurrentLength);
  2888. DbgPrint("Big ACL size is: 0x%lx \n", TOO_BIG_ACL_SIZE);
  2889. CompletionStatus = FALSE;
  2890. }
  2891. ASSERT(Status == STATUS_ALLOTTED_SPACE_EXCEEDED);
  2892. //
  2893. // Set primary group
  2894. //
  2895. DbgPrint("Se: Set primary group ... ");
  2896. AssignedPrimaryGroup.PrimaryGroup = RubbleSid;
  2897. InformationLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP);
  2898. Status = NtSetInformationToken(
  2899. TokenWithGroups, // Handle
  2900. TokenPrimaryGroup, // TokenInformationClass
  2901. &AssignedPrimaryGroup, // TokenInformation
  2902. InformationLength // TokenInformationLength
  2903. );
  2904. if (!NT_SUCCESS(Status)) {
  2905. DbgPrint("********** Failed ************\n");
  2906. DbgPrint("Status is: 0x%lx \n", Status);
  2907. DbgPrint("InformationLength is: 0x%lx \n", InformationLength);
  2908. CompletionStatus = FALSE;
  2909. }
  2910. ASSERT(NT_SUCCESS(Status));
  2911. //
  2912. // Query the Primary Group to see that it was set properly
  2913. //
  2914. Status = NtQueryInformationToken(
  2915. TokenWithGroups, // Handle
  2916. TokenPrimaryGroup, // TokenInformationClass
  2917. QueriedPrimaryGroup, // TokenInformation
  2918. 0, // TokenInformationLength
  2919. &ReturnLength // ReturnLength
  2920. );
  2921. #ifdef TOKEN_DEBUG
  2922. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2923. #endif //TOKEN_DEBUG
  2924. if (Status != STATUS_BUFFER_TOO_SMALL) {
  2925. DbgPrint("********** Failed Query of length ************\n");
  2926. DbgPrint("Status is: 0x%lx \n", Status);
  2927. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2928. CompletionStatus = FALSE;
  2929. }
  2930. ASSERT(!NT_SUCCESS(Status));
  2931. QueriedPrimaryGroup =
  2932. (PTOKEN_PRIMARY_GROUP)TstAllocatePool( PagedPool,
  2933. ReturnLength
  2934. );
  2935. Status = NtQueryInformationToken(
  2936. TokenWithGroups, // Handle
  2937. TokenPrimaryGroup, // TokenInformationClass
  2938. QueriedPrimaryGroup, // TokenInformation
  2939. ReturnLength, // TokenInformationLength
  2940. &ReturnLength // ReturnLength
  2941. );
  2942. #ifdef TOKEN_DEBUG
  2943. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2944. #endif //TOKEN_DEBUG
  2945. if (NT_SUCCESS(Status)) {
  2946. //
  2947. // Check returned value
  2948. //
  2949. if (RtlEqualSid((QueriedPrimaryGroup->PrimaryGroup),
  2950. AssignedPrimaryGroup.PrimaryGroup) ) {
  2951. DbgPrint("Succeeded.\n");
  2952. } else {
  2953. DbgPrint("********** Failed Comparison ************\n");
  2954. DbgPrint("Unexpected value returned by query.\n");
  2955. DbgPrint("Status is: 0x%lx \n", Status);
  2956. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2957. CompletionStatus = FALSE;
  2958. }
  2959. } else {
  2960. DbgPrint("********** Failed Query Of Value ************\n");
  2961. DbgPrint("Status is: 0x%lx \n", Status);
  2962. DbgPrint("Required return length is: 0x%lx \n", ReturnLength);
  2963. CompletionStatus = FALSE;
  2964. }
  2965. ASSERT(NT_SUCCESS(Status));
  2966. //
  2967. // Assign a primary group that doesn't fit into the dynamic part of the
  2968. // token.
  2969. //
  2970. DbgPrint("Se: Set too big primary group ... ");
  2971. //
  2972. // First, find out how much space is available
  2973. //
  2974. Status = NtQueryInformationToken(
  2975. TokenWithGroups, // Handle
  2976. TokenStatistics, // TokenInformationClass
  2977. &QueriedStatistics, // TokenInformation
  2978. (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength
  2979. &ReturnLength // ReturnLength
  2980. );
  2981. #ifdef TOKEN_DEBUG
  2982. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2983. #endif //TOKEN_DEBUG
  2984. ASSERT(NT_SUCCESS(Status));
  2985. Status = NtQueryInformationToken(
  2986. TokenWithGroups, // Handle
  2987. TokenPrimaryGroup, // TokenInformationClass
  2988. QueriedPrimaryGroup, // TokenInformation
  2989. ReturnLength, // TokenInformationLength
  2990. &ReturnLength // ReturnLength
  2991. );
  2992. #ifdef TOKEN_DEBUG
  2993. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  2994. #endif //TOKEN_DEBUG
  2995. ASSERT(NT_SUCCESS(Status));
  2996. CurrentLength = SeLengthSid(QueriedPrimaryGroup->PrimaryGroup);
  2997. LengthAvailable = QueriedStatistics.DynamicAvailable + CurrentLength;
  2998. //
  2999. // Now make sure our fake group ID is large enough to exceed the available
  3000. // space.
  3001. //
  3002. TooBigSid = (PSID)TstAllocatePool(
  3003. PagedPool,
  3004. RtlLengthRequiredSid( TOO_BIG_PRIMARY_GROUP_SIZE )
  3005. );
  3006. RtlInitializeSid(
  3007. TooBigSid,
  3008. &BedrockAuthority,
  3009. TOO_BIG_PRIMARY_GROUP_SIZE
  3010. );
  3011. if ((ULONG) SeLengthSid(TooBigSid) < LengthAvailable) {
  3012. DbgPrint("********** Failed - Dynamic too big ************\n");
  3013. DbgPrint("Dynamic available is: 0x%lx \n",
  3014. QueriedStatistics.DynamicAvailable);
  3015. DbgPrint("Existing primary group length is: 0x%lx \n", CurrentLength);
  3016. DbgPrint("Big SID size is: 0x%lx \n", SeLengthSid(TooBigSid));
  3017. CompletionStatus = FALSE;
  3018. }
  3019. AssignedPrimaryGroup.PrimaryGroup = TooBigSid;
  3020. InformationLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP);
  3021. Status = NtSetInformationToken(
  3022. TokenWithGroups, // Handle
  3023. TokenPrimaryGroup, // TokenInformationClass
  3024. &AssignedPrimaryGroup, // TokenInformation
  3025. InformationLength // TokenInformationLength
  3026. );
  3027. if (Status == STATUS_ALLOTTED_SPACE_EXCEEDED) {
  3028. DbgPrint("Succeeded.\n");
  3029. } else {
  3030. DbgPrint("********** Failed ************\n");
  3031. DbgPrint("Status is: 0x%lx \n", Status);
  3032. DbgPrint("Dynamic available is: 0x%lx \n",
  3033. QueriedStatistics.DynamicAvailable);
  3034. DbgPrint("Existing primary group length is: 0x%lx \n", CurrentLength);
  3035. DbgPrint("Big SID size is: 0x%lx \n", SeLengthSid(TooBigSid));
  3036. CompletionStatus = FALSE;
  3037. }
  3038. return CompletionStatus;
  3039. }
  3040. ////////////////////////////////////////////////////////////////
  3041. // //
  3042. // Adjust Privileges Test //
  3043. // //
  3044. ////////////////////////////////////////////////////////////////
  3045. BOOLEAN
  3046. TestTokenAdjustPrivileges()
  3047. {
  3048. BOOLEAN CompletionStatus = TRUE;
  3049. NTSTATUS Status;
  3050. NTSTATUS IgnoreStatus;
  3051. PTOKEN_PRIVILEGES NewState;
  3052. PTOKEN_PRIVILEGES PreviousState;
  3053. PTOKEN_PRIVILEGES PrePrivileges;
  3054. PTOKEN_PRIVILEGES PostPrivileges;
  3055. ULONG NewStateBufferLength = 200;
  3056. ULONG PreviousStateBufferLength = 200;
  3057. ULONG PrePrivilegesLength = 200;
  3058. ULONG PostPrivilegesLength = 200;
  3059. ULONG ReturnLength;
  3060. ULONG IgnoreReturnLength;
  3061. DbgPrint("\n");
  3062. PreviousState = (PTOKEN_PRIVILEGES)TstAllocatePool(
  3063. PagedPool,
  3064. PreviousStateBufferLength
  3065. );
  3066. PrePrivileges = (PTOKEN_PRIVILEGES)TstAllocatePool(
  3067. PagedPool,
  3068. PrePrivilegesLength
  3069. );
  3070. PostPrivileges = (PTOKEN_PRIVILEGES)TstAllocatePool(
  3071. PagedPool,
  3072. PostPrivilegesLength
  3073. );
  3074. NewState = (PTOKEN_PRIVILEGES)TstAllocatePool(
  3075. PagedPool,
  3076. NewStateBufferLength
  3077. );
  3078. //////////////////////////////////////////////////////////////////////
  3079. // //
  3080. // Adjust privileges giving no instructions //
  3081. // //
  3082. //////////////////////////////////////////////////////////////////////
  3083. DbgPrint("Se: Adjust privileges with no instructions ... ");
  3084. Status = NtAdjustPrivilegesToken(
  3085. SimpleToken, // TokenHandle
  3086. FALSE, // DisableAllPrivileges
  3087. NULL, // NewState (OPTIONAL)
  3088. 0, // BufferLength
  3089. NULL, // PreviousState (OPTIONAL)
  3090. &ReturnLength // ReturnLength
  3091. );
  3092. if (Status == STATUS_INVALID_PARAMETER) {
  3093. DbgPrint("Succeeded. \n");
  3094. } else {
  3095. DbgPrint("********** Failed ************\n");
  3096. DbgPrint("Status is: 0x%lx \n", Status);
  3097. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3098. CompletionStatus = FALSE;
  3099. }
  3100. ASSERT(Status == STATUS_INVALID_PARAMETER);
  3101. //////////////////////////////////////////////////////////////////////
  3102. // //
  3103. // Enable privileges in token with no privileges //
  3104. // //
  3105. //////////////////////////////////////////////////////////////////////
  3106. NewState->PrivilegeCount = 1;
  3107. NewState->Privileges[0].Luid = SecurityPrivilege;
  3108. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3109. DbgPrint("Se: Enable privilege in token with none ... ");
  3110. Status = NtAdjustPrivilegesToken(
  3111. SimpleToken, // TokenHandle
  3112. FALSE, // DisableAllPrivileges
  3113. NewState, // NewState (OPTIONAL)
  3114. 0, // BufferLength
  3115. NULL, // PreviousState (OPTIONAL)
  3116. &ReturnLength // ReturnLength
  3117. );
  3118. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  3119. DbgPrint("Succeeded. \n");
  3120. } else {
  3121. DbgPrint("********** Failed ************\n");
  3122. DbgPrint("Status is: 0x%lx \n", Status);
  3123. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3124. CompletionStatus = FALSE;
  3125. }
  3126. ASSERT(Status == STATUS_NOT_ALL_ASSIGNED);
  3127. //////////////////////////////////////////////////////////////////////
  3128. // //
  3129. // Enable a privilege that isn't assigned //
  3130. // //
  3131. //////////////////////////////////////////////////////////////////////
  3132. NewState->PrivilegeCount = 1;
  3133. NewState->Privileges[0].Luid = CreateTokenPrivilege;
  3134. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3135. DbgPrint("Se: Enable unassigned privilege in token with some ... ");
  3136. PrePrivileges->PrivilegeCount = 77;
  3137. IgnoreStatus = NtQueryInformationToken(
  3138. TokenWithPrivileges, // TokenHandle
  3139. TokenPrivileges, // TokenInformationClass
  3140. PrePrivileges, // TokenInformation
  3141. PrePrivilegesLength, // TokenInformationLength
  3142. &IgnoreReturnLength // ReturnLength
  3143. );
  3144. #ifdef TOKEN_DEBUG
  3145. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3146. #endif //TOKEN_DEBUG
  3147. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3148. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3149. Status = NtAdjustPrivilegesToken(
  3150. TokenWithPrivileges, // TokenHandle
  3151. FALSE, // DisableAllPrivileges
  3152. NewState, // NewState (OPTIONAL)
  3153. 0, // BufferLength
  3154. NULL, // PreviousState (OPTIONAL)
  3155. &ReturnLength // ReturnLength
  3156. );
  3157. PostPrivileges->PrivilegeCount = 88;
  3158. IgnoreStatus = NtQueryInformationToken(
  3159. TokenWithPrivileges, // TokenHandle
  3160. TokenPrivileges, // TokenInformationClass
  3161. PostPrivileges, // TokenInformation
  3162. PostPrivilegesLength, // TokenInformationLength
  3163. &IgnoreReturnLength // ReturnLength
  3164. );
  3165. #ifdef TOKEN_DEBUG
  3166. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3167. #endif //TOKEN_DEBUG
  3168. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3169. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3170. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  3171. //
  3172. // Check the privilege values
  3173. //
  3174. if ( (PrePrivileges->Privileges[0].Attributes ==
  3175. PostPrivileges->Privileges[0].Attributes) &&
  3176. (PrePrivileges->Privileges[1].Attributes ==
  3177. PostPrivileges->Privileges[1].Attributes) ) {
  3178. DbgPrint("Succeeded. \n");
  3179. } else {
  3180. DbgPrint("********** Failed Value Check ************\n");
  3181. DbgPrint("Status is: 0x%lx \n", Status);
  3182. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3183. PrePrivileges->Privileges[0].Attributes,
  3184. PostPrivileges->Privileges[0].Attributes);
  3185. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3186. PrePrivileges->Privileges[1].Attributes,
  3187. PostPrivileges->Privileges[1].Attributes);
  3188. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3189. CompletionStatus = FALSE;
  3190. }
  3191. } else {
  3192. DbgPrint("********** Failed ************\n");
  3193. DbgPrint("Status is: 0x%lx \n", Status);
  3194. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3195. CompletionStatus = FALSE;
  3196. }
  3197. ASSERT(Status == STATUS_NOT_ALL_ASSIGNED);
  3198. //////////////////////////////////////////////////////////////////////
  3199. // //
  3200. // Disable All Privileges (which they already are) //
  3201. // //
  3202. //////////////////////////////////////////////////////////////////////
  3203. DbgPrint("Se: Disable already disabled privileges ... ");
  3204. PrePrivileges->PrivilegeCount = 77;
  3205. IgnoreStatus = NtQueryInformationToken(
  3206. TokenWithPrivileges, // TokenHandle
  3207. TokenPrivileges, // TokenInformationClass
  3208. PrePrivileges, // TokenInformation
  3209. PrePrivilegesLength, // TokenInformationLength
  3210. &IgnoreReturnLength // ReturnLength
  3211. );
  3212. #ifdef TOKEN_DEBUG
  3213. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3214. #endif //TOKEN_DEBUG
  3215. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3216. ASSERT( PrePrivileges->Privileges[0].Attributes == 0 );
  3217. ASSERT( PrePrivileges->Privileges[1].Attributes == 0 );
  3218. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3219. Status = NtAdjustPrivilegesToken(
  3220. TokenWithPrivileges, // TokenHandle
  3221. TRUE, // DisableAllPrivileges
  3222. NULL, // NewState (OPTIONAL)
  3223. 0, // BufferLength
  3224. NULL, // PreviousState (OPTIONAL)
  3225. &ReturnLength // ReturnLength
  3226. );
  3227. PostPrivileges->PrivilegeCount = 88;
  3228. IgnoreStatus = NtQueryInformationToken(
  3229. TokenWithPrivileges, // TokenHandle
  3230. TokenPrivileges, // TokenInformationClass
  3231. PostPrivileges, // TokenInformation
  3232. PostPrivilegesLength, // TokenInformationLength
  3233. &IgnoreReturnLength // ReturnLength
  3234. );
  3235. #ifdef TOKEN_DEBUG
  3236. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3237. #endif //TOKEN_DEBUG
  3238. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3239. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3240. if (Status == STATUS_SUCCESS) {
  3241. //
  3242. // Check the privilege values
  3243. //
  3244. if ( (PostPrivileges->Privileges[0].Attributes == 0) &&
  3245. (PostPrivileges->Privileges[1].Attributes == 0) ) {
  3246. DbgPrint("Succeeded. \n");
  3247. } else {
  3248. DbgPrint("********** Failed Value Check ************\n");
  3249. DbgPrint("Status is: 0x%lx \n", Status);
  3250. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3251. PrePrivileges->Privileges[0].Attributes,
  3252. PostPrivileges->Privileges[0].Attributes);
  3253. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3254. PrePrivileges->Privileges[1].Attributes,
  3255. PostPrivileges->Privileges[1].Attributes);
  3256. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3257. CompletionStatus = FALSE;
  3258. }
  3259. } else {
  3260. DbgPrint("********** Failed ************\n");
  3261. DbgPrint("Status is: 0x%lx \n", Status);
  3262. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3263. CompletionStatus = FALSE;
  3264. }
  3265. ASSERT(Status == STATUS_SUCCESS);
  3266. //////////////////////////////////////////////////////////////////////
  3267. // //
  3268. // Enable currently disabled privileges //
  3269. // //
  3270. //////////////////////////////////////////////////////////////////////
  3271. DbgPrint("Se: Enable currently disabled privileges ... ");
  3272. PrePrivileges->PrivilegeCount = 77;
  3273. IgnoreStatus = NtQueryInformationToken(
  3274. TokenWithPrivileges, // TokenHandle
  3275. TokenPrivileges, // TokenInformationClass
  3276. PrePrivileges, // TokenInformation
  3277. PrePrivilegesLength, // TokenInformationLength
  3278. &IgnoreReturnLength // ReturnLength
  3279. );
  3280. #ifdef TOKEN_DEBUG
  3281. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3282. #endif //TOKEN_DEBUG
  3283. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3284. ASSERT( PrePrivileges->Privileges[0].Attributes == 0 );
  3285. ASSERT( PrePrivileges->Privileges[1].Attributes == 0 );
  3286. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3287. NewState->PrivilegeCount = 2;
  3288. NewState->Privileges[0].Luid = SecurityPrivilege;
  3289. NewState->Privileges[1].Luid = UnsolicitedInputPrivilege;
  3290. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3291. NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
  3292. Status = NtAdjustPrivilegesToken(
  3293. TokenWithPrivileges, // TokenHandle
  3294. FALSE, // DisableAllPrivileges
  3295. NewState, // NewState (OPTIONAL)
  3296. 0, // BufferLength
  3297. NULL, // PreviousState (OPTIONAL)
  3298. &ReturnLength // ReturnLength
  3299. );
  3300. PostPrivileges->PrivilegeCount = 88;
  3301. IgnoreStatus = NtQueryInformationToken(
  3302. TokenWithPrivileges, // TokenHandle
  3303. TokenPrivileges, // TokenInformationClass
  3304. PostPrivileges, // TokenInformation
  3305. PostPrivilegesLength, // TokenInformationLength
  3306. &IgnoreReturnLength // ReturnLength
  3307. );
  3308. #ifdef TOKEN_DEBUG
  3309. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3310. #endif //TOKEN_DEBUG
  3311. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3312. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3313. if (Status == STATUS_SUCCESS) {
  3314. //
  3315. // Check the privilege values
  3316. //
  3317. if ( (PostPrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED) &&
  3318. (PostPrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED)
  3319. ) {
  3320. DbgPrint("Succeeded. \n");
  3321. } else {
  3322. DbgPrint("********** Failed Value Check ************\n");
  3323. DbgPrint("Status is: 0x%lx \n", Status);
  3324. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3325. PrePrivileges->Privileges[0].Attributes,
  3326. PostPrivileges->Privileges[0].Attributes);
  3327. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3328. PrePrivileges->Privileges[1].Attributes,
  3329. PostPrivileges->Privileges[1].Attributes);
  3330. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3331. CompletionStatus = FALSE;
  3332. }
  3333. } else {
  3334. DbgPrint("********** Failed ************\n");
  3335. DbgPrint("Status is: 0x%lx \n", Status);
  3336. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3337. CompletionStatus = FALSE;
  3338. }
  3339. ASSERT(Status == STATUS_SUCCESS);
  3340. //////////////////////////////////////////////////////////////////////
  3341. // //
  3342. // Disable all enabled privileges //
  3343. // //
  3344. //////////////////////////////////////////////////////////////////////
  3345. DbgPrint("Se: Disable all enabled privileges ... ");
  3346. PrePrivileges->PrivilegeCount = 77;
  3347. IgnoreStatus = NtQueryInformationToken(
  3348. TokenWithPrivileges, // TokenHandle
  3349. TokenPrivileges, // TokenInformationClass
  3350. PrePrivileges, // TokenInformation
  3351. PrePrivilegesLength, // TokenInformationLength
  3352. &IgnoreReturnLength // ReturnLength
  3353. );
  3354. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3355. ASSERT( PrePrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED );
  3356. ASSERT( PrePrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED );
  3357. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3358. Status = NtAdjustPrivilegesToken(
  3359. TokenWithPrivileges, // TokenHandle
  3360. TRUE, // DisableAllPrivileges
  3361. NULL, // NewState (OPTIONAL)
  3362. 0, // BufferLength
  3363. NULL, // PreviousState (OPTIONAL)
  3364. &ReturnLength // ReturnLength
  3365. );
  3366. PostPrivileges->PrivilegeCount = 88;
  3367. IgnoreStatus = NtQueryInformationToken(
  3368. TokenWithPrivileges, // TokenHandle
  3369. TokenPrivileges, // TokenInformationClass
  3370. PostPrivileges, // TokenInformation
  3371. PostPrivilegesLength, // TokenInformationLength
  3372. &IgnoreReturnLength // ReturnLength
  3373. );
  3374. #ifdef TOKEN_DEBUG
  3375. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3376. #endif //TOKEN_DEBUG
  3377. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3378. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3379. if (Status == STATUS_SUCCESS) {
  3380. //
  3381. // Check the privilege values
  3382. //
  3383. if ( (PostPrivileges->Privileges[0].Attributes == 0) &&
  3384. (PostPrivileges->Privileges[1].Attributes == 0) ) {
  3385. DbgPrint("Succeeded. \n");
  3386. } else {
  3387. DbgPrint("********** Failed Value Check ************\n");
  3388. DbgPrint("Status is: 0x%lx \n", Status);
  3389. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3390. PrePrivileges->Privileges[0].Attributes,
  3391. PostPrivileges->Privileges[0].Attributes);
  3392. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3393. PrePrivileges->Privileges[1].Attributes,
  3394. PostPrivileges->Privileges[1].Attributes);
  3395. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3396. CompletionStatus = FALSE;
  3397. }
  3398. } else {
  3399. DbgPrint("********** Failed ************\n");
  3400. DbgPrint("Status is: 0x%lx \n", Status);
  3401. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3402. CompletionStatus = FALSE;
  3403. }
  3404. ASSERT(Status == STATUS_SUCCESS);
  3405. //////////////////////////////////////////////////////////////////////
  3406. // //
  3407. // Enable privileges requesting previous state with no return //
  3408. // length buffer //
  3409. // //
  3410. //////////////////////////////////////////////////////////////////////
  3411. DbgPrint("Se: PreviousState not NULL, ReturnLength NULL... ");
  3412. NewState->PrivilegeCount = 2;
  3413. NewState->Privileges[0].Luid = SecurityPrivilege;
  3414. NewState->Privileges[1].Luid = UnsolicitedInputPrivilege;
  3415. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3416. NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
  3417. Status = NtAdjustPrivilegesToken(
  3418. TokenWithPrivileges, // TokenHandle
  3419. FALSE, // DisableAllPrivileges
  3420. NewState, // NewState (OPTIONAL)
  3421. 0, // BufferLength
  3422. PreviousState, // PreviousState (OPTIONAL)
  3423. NULL // ReturnLength
  3424. );
  3425. if (Status == STATUS_ACCESS_VIOLATION) {
  3426. DbgPrint("Succeeded. \n");
  3427. } else {
  3428. DbgPrint("********** Failed ************\n");
  3429. DbgPrint("Status is: 0x%lx \n", Status);
  3430. CompletionStatus = FALSE;
  3431. }
  3432. ASSERT(Status == STATUS_ACCESS_VIOLATION);
  3433. //////////////////////////////////////////////////////////////////////
  3434. // //
  3435. // Enable privileges without requesting previous state and //
  3436. // providing no return length buffer //
  3437. // //
  3438. //////////////////////////////////////////////////////////////////////
  3439. DbgPrint("Se: PreviousState and ReturnLength both NULL... ");
  3440. NewState->PrivilegeCount = 2;
  3441. NewState->Privileges[0].Luid = SecurityPrivilege;
  3442. NewState->Privileges[1].Luid = UnsolicitedInputPrivilege;
  3443. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3444. NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
  3445. Status = NtAdjustPrivilegesToken(
  3446. TokenWithPrivileges, // TokenHandle
  3447. FALSE, // DisableAllPrivileges
  3448. NewState, // NewState (OPTIONAL)
  3449. 0, // BufferLength
  3450. NULL, // PreviousState (OPTIONAL)
  3451. NULL // ReturnLength
  3452. );
  3453. if (Status == STATUS_SUCCESS) {
  3454. DbgPrint("Succeeded. \n");
  3455. } else {
  3456. DbgPrint("********** Failed ************\n");
  3457. DbgPrint("Status is: 0x%lx \n", Status);
  3458. CompletionStatus = FALSE;
  3459. }
  3460. ASSERT(Status == STATUS_SUCCESS);
  3461. //////////////////////////////////////////////////////////////////////
  3462. // //
  3463. // Enable privileges requesting previous state with insufficient //
  3464. // buffer //
  3465. // //
  3466. //////////////////////////////////////////////////////////////////////
  3467. DbgPrint("Se: Too small buffer for previous state ... ");
  3468. //
  3469. // Establish a known previous state first...
  3470. //
  3471. Status = NtAdjustPrivilegesToken(
  3472. TokenWithPrivileges, // TokenHandle
  3473. TRUE, // DisableAllPrivileges
  3474. NULL, // NewState (OPTIONAL)
  3475. 0, // BufferLength
  3476. NULL, // PreviousState (OPTIONAL)
  3477. &ReturnLength // ReturnLength
  3478. );
  3479. NewState->PrivilegeCount = 2;
  3480. NewState->Privileges[0].Luid = SecurityPrivilege;
  3481. NewState->Privileges[1].Luid = UnsolicitedInputPrivilege;
  3482. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3483. NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
  3484. Status = NtAdjustPrivilegesToken(
  3485. TokenWithPrivileges, // TokenHandle
  3486. FALSE, // DisableAllPrivileges
  3487. NewState, // NewState (OPTIONAL)
  3488. 0, // BufferLength
  3489. PreviousState, // PreviousState (OPTIONAL)
  3490. &ReturnLength // ReturnLength
  3491. );
  3492. #ifdef TOKEN_DEBUG
  3493. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  3494. #endif //TOKEN_DEBUG
  3495. if (Status == STATUS_BUFFER_TOO_SMALL) {
  3496. DbgPrint("Succeeded. \n");
  3497. } else {
  3498. DbgPrint("********** Failed ************\n");
  3499. DbgPrint("Status is: 0x%lx \n", Status);
  3500. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3501. CompletionStatus = FALSE;
  3502. }
  3503. ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  3504. //////////////////////////////////////////////////////////////////////
  3505. // //
  3506. // Enable one of the privileges requesting previous state //
  3507. // //
  3508. //////////////////////////////////////////////////////////////////////
  3509. DbgPrint("Se: Enable one requesting previous state ... ");
  3510. PrePrivileges->PrivilegeCount = 77;
  3511. IgnoreStatus = NtQueryInformationToken(
  3512. TokenWithPrivileges, // TokenHandle
  3513. TokenPrivileges, // TokenInformationClass
  3514. PrePrivileges, // TokenInformation
  3515. PrePrivilegesLength, // TokenInformationLength
  3516. &IgnoreReturnLength // ReturnLength
  3517. );
  3518. #ifdef TOKEN_DEBUG
  3519. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3520. #endif //TOKEN_DEBUG
  3521. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3522. ASSERT( PrePrivileges->Privileges[0].Attributes == 0 );
  3523. ASSERT( PrePrivileges->Privileges[1].Attributes == 0 );
  3524. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3525. NewState->PrivilegeCount = 1;
  3526. NewState->Privileges[0].Luid = SecurityPrivilege;
  3527. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3528. Status = NtAdjustPrivilegesToken(
  3529. TokenWithPrivileges, // TokenHandle
  3530. FALSE, // DisableAllPrivileges
  3531. NewState, // NewState (OPTIONAL)
  3532. PreviousStateBufferLength, // BufferLength
  3533. PreviousState, // PreviousState (OPTIONAL)
  3534. &ReturnLength // ReturnLength
  3535. );
  3536. #ifdef TOKEN_DEBUG
  3537. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  3538. #endif //TOKEN_DEBUG
  3539. ASSERT(NT_SUCCESS(Status));
  3540. ASSERT(PreviousState->PrivilegeCount == 1);
  3541. PostPrivileges->PrivilegeCount = 88;
  3542. IgnoreStatus = NtQueryInformationToken(
  3543. TokenWithPrivileges, // TokenHandle
  3544. TokenPrivileges, // TokenInformationClass
  3545. PostPrivileges, // TokenInformation
  3546. PostPrivilegesLength, // TokenInformationLength
  3547. &IgnoreReturnLength // ReturnLength
  3548. );
  3549. #ifdef TOKEN_DEBUG
  3550. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3551. #endif //TOKEN_DEBUG
  3552. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3553. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3554. if (Status == STATUS_SUCCESS) {
  3555. //
  3556. // Check the privilege values
  3557. //
  3558. if ( (PostPrivileges->Privileges[SECURITY_INDEX].Attributes ==
  3559. SE_PRIVILEGE_ENABLED) &&
  3560. (PostPrivileges->Privileges[UNSOLICITED_INDEX].Attributes == 0)
  3561. ) {
  3562. DbgPrint("Succeeded. \n");
  3563. } else {
  3564. DbgPrint("********** Failed Value Check ************\n");
  3565. DbgPrint("Status is: 0x%lx \n", Status);
  3566. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3567. PrePrivileges->Privileges[0].Attributes,
  3568. PostPrivileges->Privileges[0].Attributes);
  3569. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3570. PrePrivileges->Privileges[1].Attributes,
  3571. PostPrivileges->Privileges[1].Attributes);
  3572. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3573. CompletionStatus = FALSE;
  3574. }
  3575. } else {
  3576. DbgPrint("********** Failed ************\n");
  3577. DbgPrint("Status is: 0x%lx \n", Status);
  3578. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3579. DbgPrint("Change Count is: 0x%lx \n", PreviousState->PrivilegeCount);
  3580. CompletionStatus = FALSE;
  3581. }
  3582. ASSERT(Status == STATUS_SUCCESS);
  3583. //////////////////////////////////////////////////////////////////////
  3584. // //
  3585. // Enable the other privilege requesting previous state //
  3586. // //
  3587. //////////////////////////////////////////////////////////////////////
  3588. DbgPrint("Se: Enable one requesting previous state ... ");
  3589. PrePrivileges->PrivilegeCount = 77;
  3590. IgnoreStatus = NtQueryInformationToken(
  3591. TokenWithPrivileges, // TokenHandle
  3592. TokenPrivileges, // TokenInformationClass
  3593. PrePrivileges, // TokenInformation
  3594. PrePrivilegesLength, // TokenInformationLength
  3595. &IgnoreReturnLength // ReturnLength
  3596. );
  3597. #ifdef TOKEN_DEBUG
  3598. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3599. #endif //TOKEN_DEBUG
  3600. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3601. ASSERT( PrePrivileges->Privileges[SECURITY_INDEX].Attributes ==
  3602. SE_PRIVILEGE_ENABLED );
  3603. ASSERT( PrePrivileges->Privileges[UNSOLICITED_INDEX].Attributes == 0 );
  3604. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3605. NewState->PrivilegeCount = 1;
  3606. NewState->Privileges[0].Luid = UnsolicitedInputPrivilege;
  3607. NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  3608. Status = NtAdjustPrivilegesToken(
  3609. TokenWithPrivileges, // TokenHandle
  3610. FALSE, // DisableAllPrivileges
  3611. NewState, // NewState (OPTIONAL)
  3612. PreviousStateBufferLength, // BufferLength
  3613. PreviousState, // PreviousState (OPTIONAL)
  3614. &ReturnLength // ReturnLength
  3615. );
  3616. #ifdef TOKEN_DEBUG
  3617. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  3618. #endif //TOKEN_DEBUG
  3619. ASSERT(NT_SUCCESS(Status));
  3620. ASSERT(PreviousState->PrivilegeCount == 1);
  3621. PostPrivileges->PrivilegeCount = 88;
  3622. IgnoreStatus = NtQueryInformationToken(
  3623. TokenWithPrivileges, // TokenHandle
  3624. TokenPrivileges, // TokenInformationClass
  3625. PostPrivileges, // TokenInformation
  3626. PostPrivilegesLength, // TokenInformationLength
  3627. &IgnoreReturnLength // ReturnLength
  3628. );
  3629. #ifdef TOKEN_DEBUG
  3630. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3631. #endif //TOKEN_DEBUG
  3632. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3633. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3634. if (Status == STATUS_SUCCESS) {
  3635. //
  3636. // Check the privilege values
  3637. //
  3638. if ( (PostPrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED) &&
  3639. (PostPrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED)
  3640. ) {
  3641. DbgPrint("Succeeded. \n");
  3642. } else {
  3643. DbgPrint("********** Failed Value Check ************\n");
  3644. DbgPrint("Status is: 0x%lx \n", Status);
  3645. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3646. PrePrivileges->Privileges[0].Attributes,
  3647. PostPrivileges->Privileges[0].Attributes);
  3648. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3649. PrePrivileges->Privileges[1].Attributes,
  3650. PostPrivileges->Privileges[1].Attributes);
  3651. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3652. CompletionStatus = FALSE;
  3653. }
  3654. } else {
  3655. DbgPrint("********** Failed ************\n");
  3656. DbgPrint("Status is: 0x%lx \n", Status);
  3657. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3658. DbgPrint("Change Count is: 0x%lx \n", PreviousState->PrivilegeCount);
  3659. CompletionStatus = FALSE;
  3660. }
  3661. ASSERT(Status == STATUS_SUCCESS);
  3662. //////////////////////////////////////////////////////////////////////
  3663. // //
  3664. // Return privileges to their previous state //
  3665. // Uses PreviousState from previous call //
  3666. // //
  3667. //////////////////////////////////////////////////////////////////////
  3668. DbgPrint("Se: Return privileges to previous state ... ");
  3669. PrePrivileges->PrivilegeCount = 77;
  3670. IgnoreStatus = NtQueryInformationToken(
  3671. TokenWithPrivileges, // TokenHandle
  3672. TokenPrivileges, // TokenInformationClass
  3673. PrePrivileges, // TokenInformation
  3674. PrePrivilegesLength, // TokenInformationLength
  3675. &IgnoreReturnLength // ReturnLength
  3676. );
  3677. #ifdef TOKEN_DEBUG
  3678. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3679. #endif //TOKEN_DEBUG
  3680. ASSERT( PrePrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3681. ASSERT( PrePrivileges->Privileges[0].Attributes == SE_PRIVILEGE_ENABLED );
  3682. ASSERT( PrePrivileges->Privileges[1].Attributes == SE_PRIVILEGE_ENABLED );
  3683. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3684. Status = NtAdjustPrivilegesToken(
  3685. TokenWithPrivileges, // TokenHandle
  3686. FALSE, // DisableAllPrivileges
  3687. PreviousState, // NewState (OPTIONAL)
  3688. 0, // BufferLength
  3689. NULL, // PreviousState (OPTIONAL)
  3690. &ReturnLength // ReturnLength
  3691. );
  3692. ASSERT(NT_SUCCESS(Status));
  3693. ASSERT(PreviousState->PrivilegeCount == 1);
  3694. PostPrivileges->PrivilegeCount = 88;
  3695. IgnoreStatus = NtQueryInformationToken(
  3696. TokenWithPrivileges, // TokenHandle
  3697. TokenPrivileges, // TokenInformationClass
  3698. PostPrivileges, // TokenInformation
  3699. PostPrivilegesLength, // TokenInformationLength
  3700. &IgnoreReturnLength // ReturnLength
  3701. );
  3702. #ifdef TOKEN_DEBUG
  3703. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3704. #endif //TOKEN_DEBUG
  3705. ASSERT( PostPrivileges->PrivilegeCount == PRIVILEGE_COUNT );
  3706. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3707. if (Status == STATUS_SUCCESS) {
  3708. //
  3709. // Check the privilege values
  3710. //
  3711. if ( (PostPrivileges->Privileges[SECURITY_INDEX].Attributes ==
  3712. SE_PRIVILEGE_ENABLED) &&
  3713. (PostPrivileges->Privileges[UNSOLICITED_INDEX].Attributes == 0)
  3714. ) {
  3715. DbgPrint("Succeeded. \n");
  3716. } else {
  3717. DbgPrint("********** Failed Value Check ************\n");
  3718. DbgPrint("Status is: 0x%lx \n", Status);
  3719. DbgPrint("Before and after privilege 0 state: 0x%lx, 0x%lx \n",
  3720. PrePrivileges->Privileges[0].Attributes,
  3721. PostPrivileges->Privileges[0].Attributes);
  3722. DbgPrint("Before and after privilege 1 state: 0x%lx, 0x%lx \n",
  3723. PrePrivileges->Privileges[1].Attributes,
  3724. PostPrivileges->Privileges[1].Attributes);
  3725. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3726. CompletionStatus = FALSE;
  3727. }
  3728. } else {
  3729. DbgPrint("********** Failed ************\n");
  3730. DbgPrint("Status is: 0x%lx \n", Status);
  3731. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3732. CompletionStatus = FALSE;
  3733. }
  3734. ASSERT(Status == STATUS_SUCCESS);
  3735. ////////////////////////////////////////////////////////////////
  3736. // //
  3737. // Done with test //
  3738. // //
  3739. ////////////////////////////////////////////////////////////////
  3740. TstDeallocatePool( PreviousState, PreviousStateBufferLength );
  3741. TstDeallocatePool( NewState, NewStateBufferLength );
  3742. TstDeallocatePool( PrePrivileges, PrePrivilegesLength );
  3743. TstDeallocatePool( PostPrivileges, PostPrivilegesLength );
  3744. return CompletionStatus;
  3745. }
  3746. ////////////////////////////////////////////////////////////////
  3747. // //
  3748. // Adjust Groups Test //
  3749. // //
  3750. ////////////////////////////////////////////////////////////////
  3751. BOOLEAN
  3752. TestTokenAdjustGroups()
  3753. {
  3754. BOOLEAN CompletionStatus = TRUE;
  3755. NTSTATUS Status;
  3756. NTSTATUS IgnoreStatus;
  3757. PTOKEN_GROUPS NewState;
  3758. PTOKEN_GROUPS PreviousState;
  3759. PTOKEN_GROUPS PreGroups;
  3760. PTOKEN_GROUPS PostGroups;
  3761. ULONG NewStateBufferLength = 600;
  3762. ULONG PreviousStateBufferLength = 600;
  3763. ULONG PreGroupsLength = 600;
  3764. ULONG PostGroupsLength = 600;
  3765. ULONG ReturnLength;
  3766. ULONG IgnoreReturnLength;
  3767. DbgPrint("\n");
  3768. PreviousState = (PTOKEN_GROUPS)TstAllocatePool(
  3769. PagedPool,
  3770. PreviousStateBufferLength
  3771. );
  3772. PreGroups = (PTOKEN_GROUPS)TstAllocatePool(
  3773. PagedPool,
  3774. PreGroupsLength
  3775. );
  3776. PostGroups = (PTOKEN_GROUPS)TstAllocatePool(
  3777. PagedPool,
  3778. PostGroupsLength
  3779. );
  3780. NewState = (PTOKEN_GROUPS)TstAllocatePool(
  3781. PagedPool,
  3782. NewStateBufferLength
  3783. );
  3784. //////////////////////////////////////////////////////////////////////
  3785. // //
  3786. // Adjust groups giving no instructions //
  3787. // //
  3788. //////////////////////////////////////////////////////////////////////
  3789. DbgPrint("Se: Adjust groups with no instructions ... ");
  3790. Status = NtAdjustGroupsToken(
  3791. SimpleToken, // TokenHandle
  3792. FALSE, // ResetToDefault
  3793. NULL, // NewState (OPTIONAL)
  3794. 0, // BufferLength
  3795. NULL, // PreviousState (OPTIONAL)
  3796. &ReturnLength // ReturnLength
  3797. );
  3798. if (Status == STATUS_INVALID_PARAMETER) {
  3799. DbgPrint("Succeeded. \n");
  3800. } else {
  3801. DbgPrint("********** Failed ************\n");
  3802. DbgPrint("Status is: 0x%lx \n", Status);
  3803. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3804. CompletionStatus = FALSE;
  3805. }
  3806. ASSERT(Status == STATUS_INVALID_PARAMETER);
  3807. /////////////////////////////////////////////////////////////////////////
  3808. // //
  3809. // Disable unknown group //
  3810. // //
  3811. /////////////////////////////////////////////////////////////////////////
  3812. DbgPrint("Se: Disable unknown group ... ");
  3813. PreGroups->GroupCount = 77;
  3814. IgnoreStatus = NtQueryInformationToken(
  3815. TokenWithGroups, // TokenHandle
  3816. TokenGroups, // TokenInformationClass
  3817. PreGroups, // TokenInformation
  3818. PreGroupsLength, // TokenInformationLength
  3819. &IgnoreReturnLength // ReturnLength
  3820. );
  3821. #ifdef TOKEN_DEBUG
  3822. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3823. #endif //TOKEN_DEBUG
  3824. if (IgnoreStatus != STATUS_SUCCESS) {
  3825. DbgPrint(" \n IgnoreStatus = 0x%lx \n", IgnoreStatus);
  3826. DbgPrint(" \n IgnoreReturnLength = 0x%lx \n", IgnoreReturnLength);
  3827. }
  3828. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  3829. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  3830. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  3831. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  3832. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  3833. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3834. NewState->GroupCount = 1;
  3835. NewState->Groups[0].Sid = RubbleSid;
  3836. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  3837. Status = NtAdjustGroupsToken(
  3838. TokenWithGroups, // TokenHandle
  3839. FALSE, // ResetToDefault
  3840. NewState, // NewState (OPTIONAL)
  3841. 0, // BufferLength
  3842. NULL, // PreviousState (OPTIONAL)
  3843. &ReturnLength // ReturnLength
  3844. );
  3845. PostGroups->GroupCount = 88;
  3846. IgnoreStatus = NtQueryInformationToken(
  3847. TokenWithGroups, // TokenHandle
  3848. TokenGroups, // TokenInformationClass
  3849. PostGroups, // TokenInformation
  3850. PostGroupsLength, // TokenInformationLength
  3851. &IgnoreReturnLength // ReturnLength
  3852. );
  3853. #ifdef TOKEN_DEBUG
  3854. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3855. #endif //TOKEN_DEBUG
  3856. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3857. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  3858. //
  3859. // Check the group values
  3860. //
  3861. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  3862. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  3863. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  3864. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  3865. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  3866. ) {
  3867. DbgPrint("Succeeded. \n");
  3868. } else {
  3869. DbgPrint("********** Failed Value Check ************\n");
  3870. DbgPrint("Status is: 0x%lx \n", Status);
  3871. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  3872. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  3873. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  3874. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  3875. PreGroups->Groups[CHILD_INDEX].Attributes,
  3876. PostGroups->Groups[CHILD_INDEX].Attributes);
  3877. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  3878. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  3879. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  3880. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  3881. PreGroups->Groups[WORLD_INDEX].Attributes,
  3882. PostGroups->Groups[WORLD_INDEX].Attributes);
  3883. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3884. CompletionStatus = FALSE;
  3885. }
  3886. } else {
  3887. DbgPrint("********** Failed ************\n");
  3888. DbgPrint("Status is: 0x%lx \n", Status);
  3889. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3890. CompletionStatus = FALSE;
  3891. }
  3892. ASSERT(Status == STATUS_NOT_ALL_ASSIGNED);
  3893. /////////////////////////////////////////////////////////////////////////
  3894. // //
  3895. // Enable unknown group //
  3896. // //
  3897. /////////////////////////////////////////////////////////////////////////
  3898. DbgPrint("Se: Enable unknown group ... ");
  3899. PreGroups->GroupCount = 77;
  3900. IgnoreStatus = NtQueryInformationToken(
  3901. TokenWithGroups, // TokenHandle
  3902. TokenGroups, // TokenInformationClass
  3903. PreGroups, // TokenInformation
  3904. PreGroupsLength, // TokenInformationLength
  3905. &IgnoreReturnLength // ReturnLength
  3906. );
  3907. #ifdef TOKEN_DEBUG
  3908. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3909. #endif //TOKEN_DEBUG
  3910. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  3911. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  3912. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  3913. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  3914. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  3915. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3916. NewState->GroupCount = 1;
  3917. NewState->Groups[0].Sid = RubbleSid;
  3918. NewState->Groups[0].Attributes = OptionalGroupAttributes;
  3919. Status = NtAdjustGroupsToken(
  3920. TokenWithGroups, // TokenHandle
  3921. FALSE, // ResetToDefault
  3922. NewState, // NewState (OPTIONAL)
  3923. 0, // BufferLength
  3924. NULL, // PreviousState (OPTIONAL)
  3925. &ReturnLength // ReturnLength
  3926. );
  3927. PostGroups->GroupCount = 88;
  3928. IgnoreStatus = NtQueryInformationToken(
  3929. TokenWithGroups, // TokenHandle
  3930. TokenGroups, // TokenInformationClass
  3931. PostGroups, // TokenInformation
  3932. PostGroupsLength, // TokenInformationLength
  3933. &IgnoreReturnLength // ReturnLength
  3934. );
  3935. #ifdef TOKEN_DEBUG
  3936. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3937. #endif //TOKEN_DEBUG
  3938. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3939. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  3940. //
  3941. // Check the group values
  3942. //
  3943. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  3944. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  3945. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  3946. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  3947. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  3948. ) {
  3949. DbgPrint("Succeeded. \n");
  3950. } else {
  3951. DbgPrint("********** Failed Value Check ************\n");
  3952. DbgPrint("Status is: 0x%lx \n", Status);
  3953. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  3954. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  3955. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  3956. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  3957. PreGroups->Groups[CHILD_INDEX].Attributes,
  3958. PostGroups->Groups[CHILD_INDEX].Attributes);
  3959. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  3960. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  3961. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  3962. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  3963. PreGroups->Groups[WORLD_INDEX].Attributes,
  3964. PostGroups->Groups[WORLD_INDEX].Attributes);
  3965. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3966. CompletionStatus = FALSE;
  3967. }
  3968. } else {
  3969. DbgPrint("********** Failed ************\n");
  3970. DbgPrint("Status is: 0x%lx \n", Status);
  3971. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  3972. CompletionStatus = FALSE;
  3973. }
  3974. ASSERT(Status == STATUS_NOT_ALL_ASSIGNED);
  3975. /////////////////////////////////////////////////////////////////////////
  3976. // //
  3977. // Disable mandatory group //
  3978. // //
  3979. /////////////////////////////////////////////////////////////////////////
  3980. DbgPrint("Se: Disable mandatory group ... ");
  3981. PreGroups->GroupCount = 77;
  3982. IgnoreStatus = NtQueryInformationToken(
  3983. TokenWithGroups, // TokenHandle
  3984. TokenGroups, // TokenInformationClass
  3985. PreGroups, // TokenInformation
  3986. PreGroupsLength, // TokenInformationLength
  3987. &IgnoreReturnLength // ReturnLength
  3988. );
  3989. #ifdef TOKEN_DEBUG
  3990. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  3991. #endif //TOKEN_DEBUG
  3992. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  3993. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  3994. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  3995. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  3996. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  3997. ASSERT(NT_SUCCESS(IgnoreStatus) );
  3998. NewState->GroupCount = 1;
  3999. NewState->Groups[0].Sid = WorldSid;
  4000. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4001. Status = NtAdjustGroupsToken(
  4002. TokenWithGroups, // TokenHandle
  4003. FALSE, // ResetToDefault
  4004. NewState, // NewState (OPTIONAL)
  4005. 0, // BufferLength
  4006. NULL, // PreviousState (OPTIONAL)
  4007. &ReturnLength // ReturnLength
  4008. );
  4009. PostGroups->GroupCount = 88;
  4010. IgnoreStatus = NtQueryInformationToken(
  4011. TokenWithGroups, // TokenHandle
  4012. TokenGroups, // TokenInformationClass
  4013. PostGroups, // TokenInformation
  4014. PostGroupsLength, // TokenInformationLength
  4015. &IgnoreReturnLength // ReturnLength
  4016. );
  4017. #ifdef TOKEN_DEBUG
  4018. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4019. #endif //TOKEN_DEBUG
  4020. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4021. if (Status == STATUS_CANT_DISABLE_MANDATORY) {
  4022. //
  4023. // Check the group values
  4024. //
  4025. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4026. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4027. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4028. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4029. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4030. ) {
  4031. DbgPrint("Succeeded. \n");
  4032. } else {
  4033. DbgPrint("********** Failed Value Check ************\n");
  4034. DbgPrint("Status is: 0x%lx \n", Status);
  4035. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4036. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4037. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4038. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4039. PreGroups->Groups[CHILD_INDEX].Attributes,
  4040. PostGroups->Groups[CHILD_INDEX].Attributes);
  4041. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4042. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4043. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4044. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4045. PreGroups->Groups[WORLD_INDEX].Attributes,
  4046. PostGroups->Groups[WORLD_INDEX].Attributes);
  4047. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4048. CompletionStatus = FALSE;
  4049. }
  4050. } else {
  4051. DbgPrint("********** Failed ************\n");
  4052. DbgPrint("Status is: 0x%lx \n", Status);
  4053. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4054. CompletionStatus = FALSE;
  4055. }
  4056. ASSERT(Status == STATUS_CANT_DISABLE_MANDATORY);
  4057. /////////////////////////////////////////////////////////////////////////
  4058. // //
  4059. // Enable mandatory group //
  4060. // //
  4061. /////////////////////////////////////////////////////////////////////////
  4062. DbgPrint("Se: Enable mandatory group ... ");
  4063. PreGroups->GroupCount = 77;
  4064. IgnoreStatus = NtQueryInformationToken(
  4065. TokenWithGroups, // TokenHandle
  4066. TokenGroups, // TokenInformationClass
  4067. PreGroups, // TokenInformation
  4068. PreGroupsLength, // TokenInformationLength
  4069. &IgnoreReturnLength // ReturnLength
  4070. );
  4071. #ifdef TOKEN_DEBUG
  4072. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4073. #endif //TOKEN_DEBUG
  4074. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4075. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4076. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4077. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4078. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4079. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4080. NewState->GroupCount = 1;
  4081. NewState->Groups[0].Sid = WorldSid;
  4082. NewState->Groups[0].Attributes = OptionalGroupAttributes;
  4083. Status = NtAdjustGroupsToken(
  4084. TokenWithGroups, // TokenHandle
  4085. FALSE, // ResetToDefault
  4086. NewState, // NewState (OPTIONAL)
  4087. 0, // BufferLength
  4088. NULL, // PreviousState (OPTIONAL)
  4089. &ReturnLength // ReturnLength
  4090. );
  4091. PostGroups->GroupCount = 88;
  4092. IgnoreStatus = NtQueryInformationToken(
  4093. TokenWithGroups, // TokenHandle
  4094. TokenGroups, // TokenInformationClass
  4095. PostGroups, // TokenInformation
  4096. PostGroupsLength, // TokenInformationLength
  4097. &IgnoreReturnLength // ReturnLength
  4098. );
  4099. #ifdef TOKEN_DEBUG
  4100. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4101. #endif //TOKEN_DEBUG
  4102. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4103. if (Status == STATUS_SUCCESS) {
  4104. //
  4105. // Check the group values
  4106. //
  4107. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4108. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4109. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4110. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4111. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4112. ) {
  4113. DbgPrint("Succeeded. \n");
  4114. } else {
  4115. DbgPrint("********** Failed Value Check ************\n");
  4116. DbgPrint("Status is: 0x%lx \n", Status);
  4117. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4118. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4119. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4120. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4121. PreGroups->Groups[CHILD_INDEX].Attributes,
  4122. PostGroups->Groups[CHILD_INDEX].Attributes);
  4123. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4124. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4125. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4126. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4127. PreGroups->Groups[WORLD_INDEX].Attributes,
  4128. PostGroups->Groups[WORLD_INDEX].Attributes);
  4129. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4130. CompletionStatus = FALSE;
  4131. }
  4132. } else {
  4133. DbgPrint("********** Failed ************\n");
  4134. DbgPrint("Status is: 0x%lx \n", Status);
  4135. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4136. CompletionStatus = FALSE;
  4137. }
  4138. ASSERT(Status == STATUS_SUCCESS);
  4139. /////////////////////////////////////////////////////////////////////////
  4140. // //
  4141. // Disable optional group //
  4142. // //
  4143. /////////////////////////////////////////////////////////////////////////
  4144. DbgPrint("Se: Disable optional group ... ");
  4145. PreGroups->GroupCount = 77;
  4146. IgnoreStatus = NtQueryInformationToken(
  4147. TokenWithGroups, // TokenHandle
  4148. TokenGroups, // TokenInformationClass
  4149. PreGroups, // TokenInformation
  4150. PreGroupsLength, // TokenInformationLength
  4151. &IgnoreReturnLength // ReturnLength
  4152. );
  4153. #ifdef TOKEN_DEBUG
  4154. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4155. #endif //TOKEN_DEBUG
  4156. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4157. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4158. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4159. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4160. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4161. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4162. NewState->GroupCount = 1;
  4163. NewState->Groups[0].Sid = ChildSid;
  4164. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4165. Status = NtAdjustGroupsToken(
  4166. TokenWithGroups, // TokenHandle
  4167. FALSE, // ResetToDefault
  4168. NewState, // NewState (OPTIONAL)
  4169. 0, // BufferLength
  4170. NULL, // PreviousState (OPTIONAL)
  4171. &ReturnLength // ReturnLength
  4172. );
  4173. PostGroups->GroupCount = 88;
  4174. IgnoreStatus = NtQueryInformationToken(
  4175. TokenWithGroups, // TokenHandle
  4176. TokenGroups, // TokenInformationClass
  4177. PostGroups, // TokenInformation
  4178. PostGroupsLength, // TokenInformationLength
  4179. &IgnoreReturnLength // ReturnLength
  4180. );
  4181. #ifdef TOKEN_DEBUG
  4182. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4183. #endif //TOKEN_DEBUG
  4184. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4185. if (Status == STATUS_SUCCESS) {
  4186. //
  4187. // Check the group values
  4188. //
  4189. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4190. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4191. (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) &&
  4192. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4193. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4194. ) {
  4195. DbgPrint("Succeeded. \n");
  4196. } else {
  4197. DbgPrint("********** Failed Value Check ************\n");
  4198. DbgPrint("Status is: 0x%lx \n", Status);
  4199. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4200. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4201. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4202. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4203. PreGroups->Groups[CHILD_INDEX].Attributes,
  4204. PostGroups->Groups[CHILD_INDEX].Attributes);
  4205. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4206. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4207. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4208. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4209. PreGroups->Groups[WORLD_INDEX].Attributes,
  4210. PostGroups->Groups[WORLD_INDEX].Attributes);
  4211. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4212. CompletionStatus = FALSE;
  4213. }
  4214. } else {
  4215. DbgPrint("********** Failed ************\n");
  4216. DbgPrint("Status is: 0x%lx \n", Status);
  4217. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4218. CompletionStatus = FALSE;
  4219. }
  4220. ASSERT(Status == STATUS_SUCCESS);
  4221. /////////////////////////////////////////////////////////////////////////
  4222. // //
  4223. // Disable already disabled group //
  4224. // //
  4225. /////////////////////////////////////////////////////////////////////////
  4226. DbgPrint("Se: Disable already disabled group ... ");
  4227. PreGroups->GroupCount = 77;
  4228. IgnoreStatus = NtQueryInformationToken(
  4229. TokenWithGroups, // TokenHandle
  4230. TokenGroups, // TokenInformationClass
  4231. PreGroups, // TokenInformation
  4232. PreGroupsLength, // TokenInformationLength
  4233. &IgnoreReturnLength // ReturnLength
  4234. );
  4235. #ifdef TOKEN_DEBUG
  4236. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4237. #endif //TOKEN_DEBUG
  4238. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4239. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4240. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  4241. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4242. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4243. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4244. NewState->GroupCount = 1;
  4245. NewState->Groups[0].Sid = ChildSid;
  4246. NewState->Groups[0].Attributes = 0;
  4247. Status = NtAdjustGroupsToken(
  4248. TokenWithGroups, // TokenHandle
  4249. FALSE, // ResetToDefault
  4250. NewState, // NewState (OPTIONAL)
  4251. 0, // BufferLength
  4252. NULL, // PreviousState (OPTIONAL)
  4253. &ReturnLength // ReturnLength
  4254. );
  4255. PostGroups->GroupCount = 88;
  4256. IgnoreStatus = NtQueryInformationToken(
  4257. TokenWithGroups, // TokenHandle
  4258. TokenGroups, // TokenInformationClass
  4259. PostGroups, // TokenInformation
  4260. PostGroupsLength, // TokenInformationLength
  4261. &IgnoreReturnLength // ReturnLength
  4262. );
  4263. #ifdef TOKEN_DEBUG
  4264. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4265. #endif //TOKEN_DEBUG
  4266. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4267. if (Status == STATUS_SUCCESS) {
  4268. //
  4269. // Check the group values
  4270. //
  4271. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4272. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4273. (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) &&
  4274. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4275. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4276. ) {
  4277. DbgPrint("Succeeded. \n");
  4278. } else {
  4279. DbgPrint("********** Failed Value Check ************\n");
  4280. DbgPrint("Status is: 0x%lx \n", Status);
  4281. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4282. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4283. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4284. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4285. PreGroups->Groups[CHILD_INDEX].Attributes,
  4286. PostGroups->Groups[CHILD_INDEX].Attributes);
  4287. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4288. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4289. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4290. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4291. PreGroups->Groups[WORLD_INDEX].Attributes,
  4292. PostGroups->Groups[WORLD_INDEX].Attributes);
  4293. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4294. CompletionStatus = FALSE;
  4295. }
  4296. } else {
  4297. DbgPrint("********** Failed ************\n");
  4298. DbgPrint("Status is: 0x%lx \n", Status);
  4299. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4300. CompletionStatus = FALSE;
  4301. }
  4302. ASSERT(Status == STATUS_SUCCESS);
  4303. /////////////////////////////////////////////////////////////////////////
  4304. // //
  4305. // Enable optional group //
  4306. // //
  4307. /////////////////////////////////////////////////////////////////////////
  4308. DbgPrint("Se: Enable optional group ... ");
  4309. PreGroups->GroupCount = 77;
  4310. IgnoreStatus = NtQueryInformationToken(
  4311. TokenWithGroups, // TokenHandle
  4312. TokenGroups, // TokenInformationClass
  4313. PreGroups, // TokenInformation
  4314. PreGroupsLength, // TokenInformationLength
  4315. &IgnoreReturnLength // ReturnLength
  4316. );
  4317. #ifdef TOKEN_DEBUG
  4318. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4319. #endif //TOKEN_DEBUG
  4320. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4321. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4322. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  4323. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4324. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4325. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4326. NewState->GroupCount = 1;
  4327. NewState->Groups[0].Sid = ChildSid;
  4328. NewState->Groups[0].Attributes = SE_GROUP_ENABLED;
  4329. Status = NtAdjustGroupsToken(
  4330. TokenWithGroups, // TokenHandle
  4331. FALSE, // ResetToDefault
  4332. NewState, // NewState (OPTIONAL)
  4333. 0, // BufferLength
  4334. NULL, // PreviousState (OPTIONAL)
  4335. &ReturnLength // ReturnLength
  4336. );
  4337. PostGroups->GroupCount = 88;
  4338. IgnoreStatus = NtQueryInformationToken(
  4339. TokenWithGroups, // TokenHandle
  4340. TokenGroups, // TokenInformationClass
  4341. PostGroups, // TokenInformation
  4342. PostGroupsLength, // TokenInformationLength
  4343. &IgnoreReturnLength // ReturnLength
  4344. );
  4345. #ifdef TOKEN_DEBUG
  4346. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4347. #endif //TOKEN_DEBUG
  4348. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4349. if (Status == STATUS_SUCCESS) {
  4350. //
  4351. // Check the group values
  4352. //
  4353. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4354. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4355. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4356. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4357. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4358. ) {
  4359. DbgPrint("Succeeded. \n");
  4360. } else {
  4361. DbgPrint("********** Failed Value Check ************\n");
  4362. DbgPrint("Status is: 0x%lx \n", Status);
  4363. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4364. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4365. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4366. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4367. PreGroups->Groups[CHILD_INDEX].Attributes,
  4368. PostGroups->Groups[CHILD_INDEX].Attributes);
  4369. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4370. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4371. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4372. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4373. PreGroups->Groups[WORLD_INDEX].Attributes,
  4374. PostGroups->Groups[WORLD_INDEX].Attributes);
  4375. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4376. CompletionStatus = FALSE;
  4377. }
  4378. } else {
  4379. DbgPrint("********** Failed ************\n");
  4380. DbgPrint("Status is: 0x%lx \n", Status);
  4381. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4382. CompletionStatus = FALSE;
  4383. }
  4384. ASSERT(Status == STATUS_SUCCESS);
  4385. /////////////////////////////////////////////////////////////////////////
  4386. // //
  4387. // Enable already enabled group //
  4388. // //
  4389. /////////////////////////////////////////////////////////////////////////
  4390. DbgPrint("Se: Enable already enabled group ... ");
  4391. PreGroups->GroupCount = 77;
  4392. IgnoreStatus = NtQueryInformationToken(
  4393. TokenWithGroups, // TokenHandle
  4394. TokenGroups, // TokenInformationClass
  4395. PreGroups, // TokenInformation
  4396. PreGroupsLength, // TokenInformationLength
  4397. &IgnoreReturnLength // ReturnLength
  4398. );
  4399. #ifdef TOKEN_DEBUG
  4400. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4401. #endif //TOKEN_DEBUG
  4402. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4403. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4404. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4405. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4406. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4407. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4408. NewState->GroupCount = 1;
  4409. NewState->Groups[0].Sid = ChildSid;
  4410. NewState->Groups[0].Attributes = SE_GROUP_ENABLED;
  4411. Status = NtAdjustGroupsToken(
  4412. TokenWithGroups, // TokenHandle
  4413. FALSE, // ResetToDefault
  4414. NewState, // NewState (OPTIONAL)
  4415. 0, // BufferLength
  4416. NULL, // PreviousState (OPTIONAL)
  4417. &ReturnLength // ReturnLength
  4418. );
  4419. PostGroups->GroupCount = 88;
  4420. IgnoreStatus = NtQueryInformationToken(
  4421. TokenWithGroups, // TokenHandle
  4422. TokenGroups, // TokenInformationClass
  4423. PostGroups, // TokenInformation
  4424. PostGroupsLength, // TokenInformationLength
  4425. &IgnoreReturnLength // ReturnLength
  4426. );
  4427. #ifdef TOKEN_DEBUG
  4428. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4429. #endif //TOKEN_DEBUG
  4430. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4431. if (Status == STATUS_SUCCESS) {
  4432. //
  4433. // Check the group values
  4434. //
  4435. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4436. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4437. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4438. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4439. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4440. ) {
  4441. DbgPrint("Succeeded. \n");
  4442. } else {
  4443. DbgPrint("********** Failed Value Check ************\n");
  4444. DbgPrint("Status is: 0x%lx \n", Status);
  4445. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4446. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4447. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4448. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4449. PreGroups->Groups[CHILD_INDEX].Attributes,
  4450. PostGroups->Groups[CHILD_INDEX].Attributes);
  4451. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4452. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4453. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4454. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4455. PreGroups->Groups[WORLD_INDEX].Attributes,
  4456. PostGroups->Groups[WORLD_INDEX].Attributes);
  4457. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4458. CompletionStatus = FALSE;
  4459. }
  4460. } else {
  4461. DbgPrint("********** Failed ************\n");
  4462. DbgPrint("Status is: 0x%lx \n", Status);
  4463. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4464. CompletionStatus = FALSE;
  4465. }
  4466. ASSERT(Status == STATUS_SUCCESS);
  4467. /////////////////////////////////////////////////////////////////////////
  4468. // //
  4469. // Disable optional and unknown group //
  4470. // //
  4471. /////////////////////////////////////////////////////////////////////////
  4472. DbgPrint("Se: Disable optional and unknown group ... ");
  4473. PreGroups->GroupCount = 77;
  4474. IgnoreStatus = NtQueryInformationToken(
  4475. TokenWithGroups, // TokenHandle
  4476. TokenGroups, // TokenInformationClass
  4477. PreGroups, // TokenInformation
  4478. PreGroupsLength, // TokenInformationLength
  4479. &IgnoreReturnLength // ReturnLength
  4480. );
  4481. #ifdef TOKEN_DEBUG
  4482. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4483. #endif //TOKEN_DEBUG
  4484. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4485. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4486. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4487. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4488. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4489. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4490. NewState->GroupCount = 2;
  4491. NewState->Groups[0].Sid = ChildSid;
  4492. NewState->Groups[1].Sid = RubbleSid;
  4493. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4494. NewState->Groups[1].Attributes = DisabledGroupAttributes;
  4495. Status = NtAdjustGroupsToken(
  4496. TokenWithGroups, // TokenHandle
  4497. FALSE, // ResetToDefault
  4498. NewState, // NewState (OPTIONAL)
  4499. 0, // BufferLength
  4500. NULL, // PreviousState (OPTIONAL)
  4501. &ReturnLength // ReturnLength
  4502. );
  4503. PostGroups->GroupCount = 88;
  4504. IgnoreStatus = NtQueryInformationToken(
  4505. TokenWithGroups, // TokenHandle
  4506. TokenGroups, // TokenInformationClass
  4507. PostGroups, // TokenInformation
  4508. PostGroupsLength, // TokenInformationLength
  4509. &IgnoreReturnLength // ReturnLength
  4510. );
  4511. #ifdef TOKEN_DEBUG
  4512. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4513. #endif //TOKEN_DEBUG
  4514. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4515. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  4516. //
  4517. // Check the group values
  4518. //
  4519. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4520. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4521. (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) &&
  4522. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4523. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4524. ) {
  4525. DbgPrint("Succeeded. \n");
  4526. } else {
  4527. DbgPrint("********** Failed Value Check ************\n");
  4528. DbgPrint("Status is: 0x%lx \n", Status);
  4529. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4530. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4531. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4532. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4533. PreGroups->Groups[CHILD_INDEX].Attributes,
  4534. PostGroups->Groups[CHILD_INDEX].Attributes);
  4535. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4536. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4537. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4538. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4539. PreGroups->Groups[WORLD_INDEX].Attributes,
  4540. PostGroups->Groups[WORLD_INDEX].Attributes);
  4541. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4542. CompletionStatus = FALSE;
  4543. }
  4544. } else {
  4545. DbgPrint("********** Failed ************\n");
  4546. DbgPrint("Status is: 0x%lx \n", Status);
  4547. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4548. CompletionStatus = FALSE;
  4549. }
  4550. ASSERT(Status == STATUS_NOT_ALL_ASSIGNED);
  4551. /////////////////////////////////////////////////////////////////////////
  4552. // //
  4553. // Enable optional and unknown group //
  4554. // //
  4555. /////////////////////////////////////////////////////////////////////////
  4556. DbgPrint("Se: Enable optional and unknown group ... ");
  4557. PreGroups->GroupCount = 77;
  4558. IgnoreStatus = NtQueryInformationToken(
  4559. TokenWithGroups, // TokenHandle
  4560. TokenGroups, // TokenInformationClass
  4561. PreGroups, // TokenInformation
  4562. PreGroupsLength, // TokenInformationLength
  4563. &IgnoreReturnLength // ReturnLength
  4564. );
  4565. #ifdef TOKEN_DEBUG
  4566. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4567. #endif //TOKEN_DEBUG
  4568. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4569. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4570. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  4571. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4572. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4573. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4574. NewState->GroupCount = 2;
  4575. NewState->Groups[0].Sid = ChildSid;
  4576. NewState->Groups[1].Sid = RubbleSid;
  4577. NewState->Groups[0].Attributes = OptionalGroupAttributes;
  4578. NewState->Groups[1].Attributes = OptionalGroupAttributes;
  4579. Status = NtAdjustGroupsToken(
  4580. TokenWithGroups, // TokenHandle
  4581. FALSE, // ResetToDefault
  4582. NewState, // NewState (OPTIONAL)
  4583. 0, // BufferLength
  4584. NULL, // PreviousState (OPTIONAL)
  4585. &ReturnLength // ReturnLength
  4586. );
  4587. PostGroups->GroupCount = 88;
  4588. IgnoreStatus = NtQueryInformationToken(
  4589. TokenWithGroups, // TokenHandle
  4590. TokenGroups, // TokenInformationClass
  4591. PostGroups, // TokenInformation
  4592. PostGroupsLength, // TokenInformationLength
  4593. &IgnoreReturnLength // ReturnLength
  4594. );
  4595. #ifdef TOKEN_DEBUG
  4596. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4597. #endif //TOKEN_DEBUG
  4598. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4599. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  4600. //
  4601. // Check the group values
  4602. //
  4603. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4604. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4605. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4606. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4607. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4608. ) {
  4609. DbgPrint("Succeeded. \n");
  4610. } else {
  4611. DbgPrint("********** Failed Value Check ************\n");
  4612. DbgPrint("Status is: 0x%lx \n", Status);
  4613. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4614. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4615. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4616. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4617. PreGroups->Groups[CHILD_INDEX].Attributes,
  4618. PostGroups->Groups[CHILD_INDEX].Attributes);
  4619. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4620. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4621. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4622. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4623. PreGroups->Groups[WORLD_INDEX].Attributes,
  4624. PostGroups->Groups[WORLD_INDEX].Attributes);
  4625. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4626. CompletionStatus = FALSE;
  4627. }
  4628. } else {
  4629. DbgPrint("********** Failed ************\n");
  4630. DbgPrint("Status is: 0x%lx \n", Status);
  4631. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4632. CompletionStatus = FALSE;
  4633. }
  4634. ASSERT(Status == STATUS_NOT_ALL_ASSIGNED);
  4635. /////////////////////////////////////////////////////////////////////////
  4636. // //
  4637. // Disable optional and mandatory group //
  4638. // //
  4639. /////////////////////////////////////////////////////////////////////////
  4640. DbgPrint("Se: Disable optional and mandatory group ... ");
  4641. PreGroups->GroupCount = 77;
  4642. IgnoreStatus = NtQueryInformationToken(
  4643. TokenWithGroups, // TokenHandle
  4644. TokenGroups, // TokenInformationClass
  4645. PreGroups, // TokenInformation
  4646. PreGroupsLength, // TokenInformationLength
  4647. &IgnoreReturnLength // ReturnLength
  4648. );
  4649. #ifdef TOKEN_DEBUG
  4650. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4651. #endif //TOKEN_DEBUG
  4652. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4653. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4654. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4655. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4656. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4657. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4658. NewState->GroupCount = 2;
  4659. NewState->Groups[0].Sid = ChildSid;
  4660. NewState->Groups[1].Sid = WorldSid;
  4661. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4662. NewState->Groups[1].Attributes = DisabledGroupAttributes;
  4663. Status = NtAdjustGroupsToken(
  4664. TokenWithGroups, // TokenHandle
  4665. FALSE, // ResetToDefault
  4666. NewState, // NewState (OPTIONAL)
  4667. 0, // BufferLength
  4668. NULL, // PreviousState (OPTIONAL)
  4669. &ReturnLength // ReturnLength
  4670. );
  4671. PostGroups->GroupCount = 88;
  4672. IgnoreStatus = NtQueryInformationToken(
  4673. TokenWithGroups, // TokenHandle
  4674. TokenGroups, // TokenInformationClass
  4675. PostGroups, // TokenInformation
  4676. PostGroupsLength, // TokenInformationLength
  4677. &IgnoreReturnLength // ReturnLength
  4678. );
  4679. #ifdef TOKEN_DEBUG
  4680. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4681. #endif //TOKEN_DEBUG
  4682. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4683. if (Status == STATUS_CANT_DISABLE_MANDATORY) {
  4684. //
  4685. // Check the group values
  4686. //
  4687. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4688. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4689. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4690. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4691. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4692. ) {
  4693. DbgPrint("Succeeded. \n");
  4694. } else {
  4695. DbgPrint("********** Failed Value Check ************\n");
  4696. DbgPrint("Status is: 0x%lx \n", Status);
  4697. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4698. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4699. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4700. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4701. PreGroups->Groups[CHILD_INDEX].Attributes,
  4702. PostGroups->Groups[CHILD_INDEX].Attributes);
  4703. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4704. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4705. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4706. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4707. PreGroups->Groups[WORLD_INDEX].Attributes,
  4708. PostGroups->Groups[WORLD_INDEX].Attributes);
  4709. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4710. CompletionStatus = FALSE;
  4711. }
  4712. } else {
  4713. DbgPrint("********** Failed ************\n");
  4714. DbgPrint("Status is: 0x%lx \n", Status);
  4715. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4716. CompletionStatus = FALSE;
  4717. }
  4718. ASSERT(Status == STATUS_CANT_DISABLE_MANDATORY);
  4719. /////////////////////////////////////////////////////////////////////////
  4720. // //
  4721. // Enable optional and mandatory group //
  4722. // //
  4723. /////////////////////////////////////////////////////////////////////////
  4724. DbgPrint("Se: Enable optional and mandatory group ... ");
  4725. NewState->GroupCount = 1;
  4726. NewState->Groups[0].Sid = ChildSid;
  4727. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4728. Status = NtAdjustGroupsToken(
  4729. TokenWithGroups, // TokenHandle
  4730. FALSE, // ResetToDefault
  4731. NewState, // NewState (OPTIONAL)
  4732. 0, // BufferLength
  4733. NULL, // PreviousState (OPTIONAL)
  4734. &ReturnLength // ReturnLength
  4735. );
  4736. ASSERT(Status == STATUS_SUCCESS);
  4737. PreGroups->GroupCount = 77;
  4738. IgnoreStatus = NtQueryInformationToken(
  4739. TokenWithGroups, // TokenHandle
  4740. TokenGroups, // TokenInformationClass
  4741. PreGroups, // TokenInformation
  4742. PreGroupsLength, // TokenInformationLength
  4743. &IgnoreReturnLength // ReturnLength
  4744. );
  4745. #ifdef TOKEN_DEBUG
  4746. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4747. #endif //TOKEN_DEBUG
  4748. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4749. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4750. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  4751. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4752. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4753. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4754. NewState->GroupCount = 2;
  4755. NewState->Groups[0].Sid = ChildSid;
  4756. NewState->Groups[1].Sid = WorldSid;
  4757. NewState->Groups[0].Attributes = OptionalGroupAttributes;
  4758. NewState->Groups[1].Attributes = OptionalGroupAttributes;
  4759. Status = NtAdjustGroupsToken(
  4760. TokenWithGroups, // TokenHandle
  4761. FALSE, // ResetToDefault
  4762. NewState, // NewState (OPTIONAL)
  4763. 0, // BufferLength
  4764. NULL, // PreviousState (OPTIONAL)
  4765. &ReturnLength // ReturnLength
  4766. );
  4767. PostGroups->GroupCount = 88;
  4768. IgnoreStatus = NtQueryInformationToken(
  4769. TokenWithGroups, // TokenHandle
  4770. TokenGroups, // TokenInformationClass
  4771. PostGroups, // TokenInformation
  4772. PostGroupsLength, // TokenInformationLength
  4773. &IgnoreReturnLength // ReturnLength
  4774. );
  4775. #ifdef TOKEN_DEBUG
  4776. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4777. #endif //TOKEN_DEBUG
  4778. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4779. if (Status == STATUS_SUCCESS) {
  4780. //
  4781. // Check the group values
  4782. //
  4783. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4784. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4785. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4786. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4787. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4788. ) {
  4789. DbgPrint("Succeeded. \n");
  4790. } else {
  4791. DbgPrint("********** Failed Value Check ************\n");
  4792. DbgPrint("Status is: 0x%lx \n", Status);
  4793. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4794. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4795. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4796. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4797. PreGroups->Groups[CHILD_INDEX].Attributes,
  4798. PostGroups->Groups[CHILD_INDEX].Attributes);
  4799. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4800. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4801. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4802. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4803. PreGroups->Groups[WORLD_INDEX].Attributes,
  4804. PostGroups->Groups[WORLD_INDEX].Attributes);
  4805. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4806. CompletionStatus = FALSE;
  4807. }
  4808. } else {
  4809. DbgPrint("********** Failed ************\n");
  4810. DbgPrint("Status is: 0x%lx \n", Status);
  4811. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4812. CompletionStatus = FALSE;
  4813. }
  4814. ASSERT(Status == STATUS_SUCCESS);
  4815. //////////////////////////////////////////////////////////////////////
  4816. // //
  4817. // Disable optional group requesting previous state with //
  4818. // insufficient buffer //
  4819. // //
  4820. //////////////////////////////////////////////////////////////////////
  4821. DbgPrint("Se: Too small buffer for previous state ... ");
  4822. PreGroups->GroupCount = 77;
  4823. IgnoreStatus = NtQueryInformationToken(
  4824. TokenWithGroups, // TokenHandle
  4825. TokenGroups, // TokenInformationClass
  4826. PreGroups, // TokenInformation
  4827. PreGroupsLength, // TokenInformationLength
  4828. &IgnoreReturnLength // ReturnLength
  4829. );
  4830. #ifdef TOKEN_DEBUG
  4831. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4832. #endif //TOKEN_DEBUG
  4833. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4834. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4835. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4836. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4837. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4838. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4839. NewState->GroupCount = 1;
  4840. NewState->Groups[0].Sid = ChildSid;
  4841. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4842. Status = NtAdjustGroupsToken(
  4843. TokenWithGroups, // TokenHandle
  4844. FALSE, // ResetToDefault
  4845. NewState, // NewState (OPTIONAL)
  4846. 0, // BufferLength
  4847. PreviousState, // PreviousState (OPTIONAL)
  4848. &ReturnLength // ReturnLength
  4849. );
  4850. #ifdef TOKEN_DEBUG
  4851. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  4852. #endif //TOKEN_DEBUG
  4853. PostGroups->GroupCount = 88;
  4854. IgnoreStatus = NtQueryInformationToken(
  4855. TokenWithGroups, // TokenHandle
  4856. TokenGroups, // TokenInformationClass
  4857. PostGroups, // TokenInformation
  4858. PostGroupsLength, // TokenInformationLength
  4859. &IgnoreReturnLength // ReturnLength
  4860. );
  4861. #ifdef TOKEN_DEBUG
  4862. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4863. #endif //TOKEN_DEBUG
  4864. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4865. if (Status == STATUS_BUFFER_TOO_SMALL) {
  4866. //
  4867. // Check the group values
  4868. //
  4869. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4870. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4871. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  4872. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  4873. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  4874. ) {
  4875. DbgPrint("Succeeded. \n");
  4876. } else {
  4877. DbgPrint("********** Failed Value Check ************\n");
  4878. DbgPrint("Status is: 0x%lx \n", Status);
  4879. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4880. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4881. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4882. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4883. PreGroups->Groups[CHILD_INDEX].Attributes,
  4884. PostGroups->Groups[CHILD_INDEX].Attributes);
  4885. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4886. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4887. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4888. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4889. PreGroups->Groups[WORLD_INDEX].Attributes,
  4890. PostGroups->Groups[WORLD_INDEX].Attributes);
  4891. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4892. CompletionStatus = FALSE;
  4893. }
  4894. } else {
  4895. DbgPrint("********** Failed ************\n");
  4896. DbgPrint("Status is: 0x%lx \n", Status);
  4897. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4898. CompletionStatus = FALSE;
  4899. }
  4900. ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  4901. /////////////////////////////////////////////////////////////////////////
  4902. // //
  4903. // Disable optional requesting previous state //
  4904. // //
  4905. /////////////////////////////////////////////////////////////////////////
  4906. DbgPrint("Se: Disable optional, requesting previous state ... ");
  4907. PreGroups->GroupCount = 77;
  4908. IgnoreStatus = NtQueryInformationToken(
  4909. TokenWithGroups, // TokenHandle
  4910. TokenGroups, // TokenInformationClass
  4911. PreGroups, // TokenInformation
  4912. PreGroupsLength, // TokenInformationLength
  4913. &IgnoreReturnLength // ReturnLength
  4914. );
  4915. #ifdef TOKEN_DEBUG
  4916. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4917. #endif //TOKEN_DEBUG
  4918. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  4919. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  4920. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  4921. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  4922. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  4923. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4924. NewState->GroupCount = 2;
  4925. NewState->Groups[0].Sid = NeandertholSid;
  4926. NewState->Groups[1].Sid = ChildSid;
  4927. NewState->Groups[0].Attributes = DisabledGroupAttributes;
  4928. NewState->Groups[1].Attributes = DisabledGroupAttributes;
  4929. PreviousState->GroupCount = 99;
  4930. Status = NtAdjustGroupsToken(
  4931. TokenWithGroups, // TokenHandle
  4932. FALSE, // ResetToDefault
  4933. NewState, // NewState (OPTIONAL)
  4934. PreviousStateBufferLength, // BufferLength
  4935. PreviousState, // PreviousState (OPTIONAL)
  4936. &ReturnLength // ReturnLength
  4937. );
  4938. #ifdef TOKEN_DEBUG
  4939. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  4940. #endif //TOKEN_DEBUG
  4941. PostGroups->GroupCount = 88;
  4942. IgnoreStatus = NtQueryInformationToken(
  4943. TokenWithGroups, // TokenHandle
  4944. TokenGroups, // TokenInformationClass
  4945. PostGroups, // TokenInformation
  4946. PostGroupsLength, // TokenInformationLength
  4947. &IgnoreReturnLength // ReturnLength
  4948. );
  4949. #ifdef TOKEN_DEBUG
  4950. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  4951. #endif //TOKEN_DEBUG
  4952. ASSERT(NT_SUCCESS(IgnoreStatus) );
  4953. if (Status == STATUS_SUCCESS) {
  4954. //
  4955. // Check the group values
  4956. //
  4957. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  4958. ASSERT( PreviousState->GroupCount == 2 );
  4959. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  4960. (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) &&
  4961. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes) &&
  4962. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) &&
  4963. (PreviousState->Groups[0].Attributes == OptionalGroupAttributes) &&
  4964. (PreviousState->Groups[1].Attributes == OptionalGroupAttributes)
  4965. ) {
  4966. DbgPrint("Succeeded. \n");
  4967. } else {
  4968. DbgPrint("********** Failed Value Check ************\n");
  4969. DbgPrint("Status is: 0x%lx \n", Status);
  4970. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  4971. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  4972. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  4973. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  4974. PreGroups->Groups[CHILD_INDEX].Attributes,
  4975. PostGroups->Groups[CHILD_INDEX].Attributes);
  4976. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  4977. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  4978. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  4979. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  4980. PreGroups->Groups[WORLD_INDEX].Attributes,
  4981. PostGroups->Groups[WORLD_INDEX].Attributes);
  4982. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4983. DbgPrint("Previous count is: 0x%lx \n", PreviousState->GroupCount);
  4984. DbgPrint("Previous state of group 0 is: 0x%lx \n",
  4985. PreviousState->Groups[0].Attributes);
  4986. DbgPrint("Previous state of group 1 is: 0x%lx \n",
  4987. PreviousState->Groups[1].Attributes);
  4988. CompletionStatus = FALSE;
  4989. }
  4990. } else {
  4991. DbgPrint("********** Failed ************\n");
  4992. DbgPrint("Status is: 0x%lx \n", Status);
  4993. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  4994. CompletionStatus = FALSE;
  4995. }
  4996. ASSERT(Status == STATUS_SUCCESS);
  4997. /////////////////////////////////////////////////////////////////////////
  4998. // //
  4999. // Return group to previous state //
  5000. // //
  5001. /////////////////////////////////////////////////////////////////////////
  5002. DbgPrint("Se: Return to previous state ... ");
  5003. PreGroups->GroupCount = 77;
  5004. IgnoreStatus = NtQueryInformationToken(
  5005. TokenWithGroups, // TokenHandle
  5006. TokenGroups, // TokenInformationClass
  5007. PreGroups, // TokenInformation
  5008. PreGroupsLength, // TokenInformationLength
  5009. &IgnoreReturnLength // ReturnLength
  5010. );
  5011. #ifdef TOKEN_DEBUG
  5012. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5013. #endif //TOKEN_DEBUG
  5014. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  5015. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  5016. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  5017. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes);
  5018. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  5019. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5020. Status = NtAdjustGroupsToken(
  5021. TokenWithGroups, // TokenHandle
  5022. FALSE, // ResetToDefault
  5023. PreviousState, // NewState (OPTIONAL)
  5024. PreviousStateBufferLength, // BufferLength
  5025. PreviousState, // PreviousState (OPTIONAL)
  5026. &ReturnLength // ReturnLength
  5027. );
  5028. #ifdef TOKEN_DEBUG
  5029. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  5030. #endif //TOKEN_DEBUG
  5031. PostGroups->GroupCount = 88;
  5032. IgnoreStatus = NtQueryInformationToken(
  5033. TokenWithGroups, // TokenHandle
  5034. TokenGroups, // TokenInformationClass
  5035. PostGroups, // TokenInformation
  5036. PostGroupsLength, // TokenInformationLength
  5037. &IgnoreReturnLength // ReturnLength
  5038. );
  5039. #ifdef TOKEN_DEBUG
  5040. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5041. #endif //TOKEN_DEBUG
  5042. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5043. if (Status == STATUS_SUCCESS) {
  5044. //
  5045. // Check the group values
  5046. //
  5047. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  5048. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  5049. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  5050. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  5051. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) &&
  5052. (PreviousState->Groups[0].Attributes == DisabledGroupAttributes) &&
  5053. (PreviousState->Groups[1].Attributes == DisabledGroupAttributes)
  5054. ) {
  5055. DbgPrint("Succeeded. \n");
  5056. } else {
  5057. DbgPrint("********** Failed Value Check ************\n");
  5058. DbgPrint("Status is: 0x%lx \n", Status);
  5059. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  5060. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  5061. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  5062. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  5063. PreGroups->Groups[CHILD_INDEX].Attributes,
  5064. PostGroups->Groups[CHILD_INDEX].Attributes);
  5065. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  5066. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  5067. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  5068. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  5069. PreGroups->Groups[WORLD_INDEX].Attributes,
  5070. PostGroups->Groups[WORLD_INDEX].Attributes);
  5071. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5072. CompletionStatus = FALSE;
  5073. }
  5074. } else {
  5075. DbgPrint("********** Failed ************\n");
  5076. DbgPrint("Status is: 0x%lx \n", Status);
  5077. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5078. CompletionStatus = FALSE;
  5079. }
  5080. ASSERT(Status == STATUS_SUCCESS);
  5081. /////////////////////////////////////////////////////////////////////////
  5082. // //
  5083. // Return to previous state again //
  5084. // //
  5085. /////////////////////////////////////////////////////////////////////////
  5086. DbgPrint("Se: Return to previous state again ... ");
  5087. PreGroups->GroupCount = 77;
  5088. IgnoreStatus = NtQueryInformationToken(
  5089. TokenWithGroups, // TokenHandle
  5090. TokenGroups, // TokenInformationClass
  5091. PreGroups, // TokenInformation
  5092. PreGroupsLength, // TokenInformationLength
  5093. &IgnoreReturnLength // ReturnLength
  5094. );
  5095. #ifdef TOKEN_DEBUG
  5096. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5097. #endif //TOKEN_DEBUG
  5098. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  5099. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  5100. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes);
  5101. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes);
  5102. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  5103. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5104. Status = NtAdjustGroupsToken(
  5105. TokenWithGroups, // TokenHandle
  5106. FALSE, // ResetToDefault
  5107. PreviousState, // NewState (OPTIONAL)
  5108. PreviousStateBufferLength, // BufferLength
  5109. PreviousState, // PreviousState (OPTIONAL)
  5110. &ReturnLength // ReturnLength
  5111. );
  5112. #ifdef TOKEN_DEBUG
  5113. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  5114. #endif //TOKEN_DEBUG
  5115. PostGroups->GroupCount = 88;
  5116. IgnoreStatus = NtQueryInformationToken(
  5117. TokenWithGroups, // TokenHandle
  5118. TokenGroups, // TokenInformationClass
  5119. PostGroups, // TokenInformation
  5120. PostGroupsLength, // TokenInformationLength
  5121. &IgnoreReturnLength // ReturnLength
  5122. );
  5123. #ifdef TOKEN_DEBUG
  5124. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5125. #endif //TOKEN_DEBUG
  5126. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5127. if (Status == STATUS_SUCCESS) {
  5128. //
  5129. // Check the group values
  5130. //
  5131. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  5132. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  5133. (PostGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes) &&
  5134. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes) &&
  5135. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) &&
  5136. (PreviousState->Groups[0].Attributes == OptionalGroupAttributes) &&
  5137. (PreviousState->Groups[1].Attributes == OptionalGroupAttributes)
  5138. ) {
  5139. DbgPrint("Succeeded. \n");
  5140. } else {
  5141. DbgPrint("********** Failed Value Check ************\n");
  5142. DbgPrint("Status is: 0x%lx \n", Status);
  5143. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  5144. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  5145. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  5146. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  5147. PreGroups->Groups[CHILD_INDEX].Attributes,
  5148. PostGroups->Groups[CHILD_INDEX].Attributes);
  5149. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  5150. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  5151. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  5152. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  5153. PreGroups->Groups[WORLD_INDEX].Attributes,
  5154. PostGroups->Groups[WORLD_INDEX].Attributes);
  5155. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5156. CompletionStatus = FALSE;
  5157. }
  5158. } else {
  5159. DbgPrint("********** Failed ************\n");
  5160. DbgPrint("Status is: 0x%lx \n", Status);
  5161. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5162. CompletionStatus = FALSE;
  5163. }
  5164. ASSERT(Status == STATUS_SUCCESS);
  5165. /////////////////////////////////////////////////////////////////////////
  5166. // //
  5167. // Return to default state (capture previous state) //
  5168. // //
  5169. /////////////////////////////////////////////////////////////////////////
  5170. DbgPrint("Se: Return to default state (w/previous state) ... ");
  5171. PreGroups->GroupCount = 77;
  5172. IgnoreStatus = NtQueryInformationToken(
  5173. TokenWithGroups, // TokenHandle
  5174. TokenGroups, // TokenInformationClass
  5175. PreGroups, // TokenInformation
  5176. PreGroupsLength, // TokenInformationLength
  5177. &IgnoreReturnLength // ReturnLength
  5178. );
  5179. #ifdef TOKEN_DEBUG
  5180. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5181. #endif //TOKEN_DEBUG
  5182. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  5183. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  5184. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  5185. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes);
  5186. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  5187. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5188. Status = NtAdjustGroupsToken(
  5189. TokenWithGroups, // TokenHandle
  5190. TRUE, // ResetToDefault
  5191. NULL, // NewState (OPTIONAL)
  5192. PreviousStateBufferLength, // BufferLength
  5193. PreviousState, // PreviousState (OPTIONAL)
  5194. &ReturnLength // ReturnLength
  5195. );
  5196. #ifdef TOKEN_DEBUG
  5197. DbgPrint("\n (debug) return length: 0x%lx \n", ReturnLength);
  5198. #endif //TOKEN_DEBUG
  5199. PostGroups->GroupCount = 88;
  5200. IgnoreStatus = NtQueryInformationToken(
  5201. TokenWithGroups, // TokenHandle
  5202. TokenGroups, // TokenInformationClass
  5203. PostGroups, // TokenInformation
  5204. PostGroupsLength, // TokenInformationLength
  5205. &IgnoreReturnLength // ReturnLength
  5206. );
  5207. #ifdef TOKEN_DEBUG
  5208. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5209. #endif //TOKEN_DEBUG
  5210. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5211. if (Status == STATUS_SUCCESS) {
  5212. //
  5213. // Check the group values
  5214. //
  5215. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  5216. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  5217. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  5218. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  5219. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes) &&
  5220. (PreviousState->Groups[0].Attributes == DisabledGroupAttributes) &&
  5221. (PreviousState->Groups[1].Attributes == DisabledGroupAttributes)
  5222. ) {
  5223. DbgPrint("Succeeded. \n");
  5224. } else {
  5225. DbgPrint("********** Failed Value Check ************\n");
  5226. DbgPrint("Status is: 0x%lx \n", Status);
  5227. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  5228. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  5229. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  5230. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  5231. PreGroups->Groups[CHILD_INDEX].Attributes,
  5232. PostGroups->Groups[CHILD_INDEX].Attributes);
  5233. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  5234. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  5235. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  5236. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  5237. PreGroups->Groups[WORLD_INDEX].Attributes,
  5238. PostGroups->Groups[WORLD_INDEX].Attributes);
  5239. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5240. CompletionStatus = FALSE;
  5241. }
  5242. } else {
  5243. DbgPrint("********** Failed ************\n");
  5244. DbgPrint("Status is: 0x%lx \n", Status);
  5245. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5246. CompletionStatus = FALSE;
  5247. }
  5248. ASSERT(Status == STATUS_SUCCESS);
  5249. /////////////////////////////////////////////////////////////////////////
  5250. // //
  5251. // Return to default state (don't capture previous state) //
  5252. // //
  5253. /////////////////////////////////////////////////////////////////////////
  5254. DbgPrint("Se: Return to default state (no previous state) ... ");
  5255. Status = NtAdjustGroupsToken(
  5256. TokenWithGroups, // TokenHandle
  5257. FALSE, // ResetToDefault
  5258. PreviousState, // NewState (OPTIONAL)
  5259. 0, // BufferLength
  5260. NULL, // PreviousState (OPTIONAL)
  5261. &ReturnLength // ReturnLength
  5262. );
  5263. ASSERT(Status == STATUS_SUCCESS);
  5264. PreGroups->GroupCount = 77;
  5265. IgnoreStatus = NtQueryInformationToken(
  5266. TokenWithGroups, // TokenHandle
  5267. TokenGroups, // TokenInformationClass
  5268. PreGroups, // TokenInformation
  5269. PreGroupsLength, // TokenInformationLength
  5270. &IgnoreReturnLength // ReturnLength
  5271. );
  5272. #ifdef TOKEN_DEBUG
  5273. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5274. #endif //TOKEN_DEBUG
  5275. ASSERT(PreGroups->GroupCount == GROUP_COUNT );
  5276. ASSERT(PreGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes);
  5277. ASSERT(PreGroups->Groups[CHILD_INDEX].Attributes == DisabledGroupAttributes);
  5278. ASSERT(PreGroups->Groups[NEANDERTHOL_INDEX].Attributes == DisabledGroupAttributes);
  5279. ASSERT(PreGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes);
  5280. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5281. Status = NtAdjustGroupsToken(
  5282. TokenWithGroups, // TokenHandle
  5283. TRUE, // ResetToDefault
  5284. NULL, // NewState (OPTIONAL)
  5285. 0, // BufferLength
  5286. NULL, // PreviousState (OPTIONAL)
  5287. &ReturnLength // ReturnLength
  5288. );
  5289. PostGroups->GroupCount = 88;
  5290. IgnoreStatus = NtQueryInformationToken(
  5291. TokenWithGroups, // TokenHandle
  5292. TokenGroups, // TokenInformationClass
  5293. PostGroups, // TokenInformation
  5294. PostGroupsLength, // TokenInformationLength
  5295. &IgnoreReturnLength // ReturnLength
  5296. );
  5297. #ifdef TOKEN_DEBUG
  5298. DbgPrint("\n (debug) ignore return length: 0x%lx \n", IgnoreReturnLength);
  5299. #endif //TOKEN_DEBUG
  5300. ASSERT(NT_SUCCESS(IgnoreStatus) );
  5301. if (Status == STATUS_SUCCESS) {
  5302. //
  5303. // Check the group values
  5304. //
  5305. ASSERT( PostGroups->GroupCount == GROUP_COUNT );
  5306. if ( (PostGroups->Groups[FLINTSTONE_INDEX].Attributes == OwnerGroupAttributes) &&
  5307. (PostGroups->Groups[CHILD_INDEX].Attributes == OptionalGroupAttributes) &&
  5308. (PostGroups->Groups[NEANDERTHOL_INDEX].Attributes == OptionalGroupAttributes) &&
  5309. (PostGroups->Groups[WORLD_INDEX].Attributes == NormalGroupAttributes)
  5310. ) {
  5311. DbgPrint("Succeeded. \n");
  5312. } else {
  5313. DbgPrint("********** Failed Value Check ************\n");
  5314. DbgPrint("Status is: 0x%lx \n", Status);
  5315. DbgPrint("Before/after Flintstone state: 0x%lx / 0x%lx \n",
  5316. PreGroups->Groups[FLINTSTONE_INDEX].Attributes,
  5317. PostGroups->Groups[FLINTSTONE_INDEX].Attributes);
  5318. DbgPrint("Before/after Child state: 0x%lx / 0x%lx \n",
  5319. PreGroups->Groups[CHILD_INDEX].Attributes,
  5320. PostGroups->Groups[CHILD_INDEX].Attributes);
  5321. DbgPrint("Before/after Neanderthol state: 0x%lx / 0x%lx \n",
  5322. PreGroups->Groups[NEANDERTHOL_INDEX].Attributes,
  5323. PostGroups->Groups[NEANDERTHOL_INDEX].Attributes);
  5324. DbgPrint("Before/after World state: 0x%lx / 0x%lx \n",
  5325. PreGroups->Groups[WORLD_INDEX].Attributes,
  5326. PostGroups->Groups[WORLD_INDEX].Attributes);
  5327. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5328. CompletionStatus = FALSE;
  5329. }
  5330. } else {
  5331. DbgPrint("********** Failed ************\n");
  5332. DbgPrint("Status is: 0x%lx \n", Status);
  5333. DbgPrint("Return Length is: 0x%lx \n", ReturnLength);
  5334. CompletionStatus = FALSE;
  5335. }
  5336. ASSERT(Status == STATUS_SUCCESS);
  5337. ////////////////////////////////////////////////////////////////
  5338. // //
  5339. // Done with test //
  5340. // //
  5341. ////////////////////////////////////////////////////////////////
  5342. TstDeallocatePool( PreviousState, PreviousStateBufferLength );
  5343. TstDeallocatePool( NewState, NewStateBufferLength );
  5344. TstDeallocatePool( PreGroups, PreGroupsLength );
  5345. TstDeallocatePool( PostGroups, PostGroupsLength );
  5346. return CompletionStatus;
  5347. }
  5348. ////////////////////////////////////////////////////////////////
  5349. // //
  5350. // Compare duplicate to original token & display test results //
  5351. // //
  5352. ////////////////////////////////////////////////////////////////
  5353. BOOLEAN
  5354. TestpCompareDuplicateToken(
  5355. IN NTSTATUS Status,
  5356. IN HANDLE OldToken,
  5357. IN OBJECT_ATTRIBUTES NewAttributes,
  5358. IN BOOLEAN EffectiveOnly,
  5359. IN TOKEN_TYPE NewType,
  5360. IN HANDLE NewToken
  5361. )
  5362. {
  5363. BOOLEAN CompletionStatus = TRUE;
  5364. ULONG OldReturnLength;
  5365. ULONG NewReturnLength;
  5366. PTOKEN_USER OldUserId = NULL;
  5367. PTOKEN_USER NewUserId = NULL;
  5368. TOKEN_SOURCE OldSource;
  5369. TOKEN_SOURCE NewSource;
  5370. TOKEN_STATISTICS OldStatistics;
  5371. TOKEN_STATISTICS NewStatistics;
  5372. BOOLEAN SomeNotCompared = FALSE;
  5373. //
  5374. // Appease the compiler Gods
  5375. //
  5376. NewAttributes = NewAttributes;
  5377. NewType = NewType;
  5378. EffectiveOnly = EffectiveOnly;
  5379. //
  5380. // If the status isn't success, don't bother comparing the tokens
  5381. //
  5382. if (!NT_SUCCESS(Status)) {
  5383. DbgPrint("********** Failed ************\n");
  5384. DbgPrint("Status is: 0x%lx \n", Status);
  5385. return FALSE;
  5386. }
  5387. //
  5388. // Compare the user IDs
  5389. //
  5390. Status = NtQueryInformationToken(
  5391. OldToken, // Handle
  5392. TokenUser, // TokenInformationClass
  5393. OldUserId, // TokenInformation
  5394. 0, // TokenInformationLength
  5395. &OldReturnLength // ReturnLength
  5396. ); ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  5397. OldUserId = (PTOKEN_USER)TstAllocatePool( PagedPool, OldReturnLength );
  5398. Status = NtQueryInformationToken(
  5399. OldToken, // Handle
  5400. TokenUser, // TokenInformationClass
  5401. OldUserId, // TokenInformation
  5402. OldReturnLength, // TokenInformationLength
  5403. &OldReturnLength // ReturnLength
  5404. ); ASSERT(NT_SUCCESS(Status));
  5405. Status = NtQueryInformationToken(
  5406. NewToken, // Handle
  5407. TokenUser, // TokenInformationClass
  5408. NewUserId, // TokenInformation
  5409. 0, // TokenInformationLength
  5410. &NewReturnLength // ReturnLength
  5411. ); ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  5412. NewUserId = (PTOKEN_USER)TstAllocatePool( PagedPool, NewReturnLength );
  5413. Status = NtQueryInformationToken(
  5414. NewToken, // Handle
  5415. TokenUser, // TokenInformationClass
  5416. NewUserId, // TokenInformation
  5417. NewReturnLength, // TokenInformationLength
  5418. &NewReturnLength // ReturnLength
  5419. ); ASSERT(NT_SUCCESS(Status));
  5420. if ( !RtlEqualSid(OldUserId->User.Sid, NewUserId->User.Sid) ) {
  5421. if (CompletionStatus) {
  5422. DbgPrint("*** Failed Value Comparison ***\n");
  5423. }
  5424. DbgPrint("User IDs don't match.\n");
  5425. CompletionStatus = FALSE;
  5426. }
  5427. TstDeallocatePool( OldUserId, OldReturnLength );
  5428. TstDeallocatePool( NewUserId, NewReturnLength );
  5429. //
  5430. // Check the token statistics
  5431. //
  5432. if (CompletionStatus) {
  5433. Status = NtQueryInformationToken(
  5434. OldToken, // Handle
  5435. TokenStatistics, // TokenInformationClass
  5436. &OldStatistics, // TokenInformation
  5437. (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength
  5438. &OldReturnLength // ReturnLength
  5439. ); ASSERT(NT_SUCCESS(Status));
  5440. Status = NtQueryInformationToken(
  5441. NewToken, // Handle
  5442. TokenStatistics, // TokenInformationClass
  5443. &NewStatistics, // TokenInformation
  5444. (ULONG)sizeof(TOKEN_STATISTICS), // TokenInformationLength
  5445. &NewReturnLength // ReturnLength
  5446. ); ASSERT(NT_SUCCESS(Status));
  5447. //
  5448. // Must have:
  5449. // Different TokenId values
  5450. // Same authenticationId value
  5451. // Same ExpirationTime
  5452. // Same token type
  5453. // Same ImpersonationLevel (if correct token type)
  5454. // Same DynamicCharged & DynamicAvailable
  5455. //
  5456. // GroupCount and PrivilegeCount are deferred to the group and
  5457. // privilege comparison due to the difficulty involved with
  5458. // taking EffectiveOnly into account.
  5459. //
  5460. // The new token must have a ModifiedId that is the same as the
  5461. // original.
  5462. //
  5463. //
  5464. // Token ID
  5465. //
  5466. if ( (OldStatistics.TokenId.HighPart ==
  5467. NewStatistics.TokenId.HighPart) &&
  5468. (OldStatistics.TokenId.LowPart ==
  5469. NewStatistics.TokenId.LowPart) ) {
  5470. DbgPrint("*** Failed ***\n");
  5471. DbgPrint(" TokenIds are equal.\n");
  5472. DbgPrint(" Old TokenId is: (0x%xl, 0x%xl)\n",
  5473. OldStatistics.TokenId.HighPart,
  5474. OldStatistics.TokenId.LowPart);
  5475. DbgPrint(" New TokenId is: (0x%xl, 0x%xl)\n",
  5476. NewStatistics.TokenId.HighPart,
  5477. NewStatistics.TokenId.LowPart);
  5478. DbgPrint(" ");
  5479. CompletionStatus = FALSE;
  5480. }
  5481. //
  5482. // Authentication ID
  5483. //
  5484. if ( !RtlEqualLuid(&OldStatistics.AuthenticationId,
  5485. &NewStatistics.AuthenticationId) ) {
  5486. DbgPrint("*** Failed ***\n");
  5487. DbgPrint(" AuthenticationIds are not equal.\n");
  5488. DbgPrint("Original Authentication ID is: ");
  5489. TestpPrintLuid(OldStatistics.AuthenticationId);
  5490. DbgPrint("\n");
  5491. DbgPrint("New Authentication ID is: ");
  5492. TestpPrintLuid(NewStatistics.AuthenticationId);
  5493. DbgPrint("\n");
  5494. DbgPrint(" ");
  5495. CompletionStatus = FALSE;
  5496. }
  5497. //
  5498. // ExpirationTime
  5499. //
  5500. if ( (OldStatistics.ExpirationTime.HighPart !=
  5501. NewStatistics.ExpirationTime.HighPart) ||
  5502. (OldStatistics.ExpirationTime.LowPart !=
  5503. NewStatistics.ExpirationTime.LowPart) ) {
  5504. DbgPrint("*** Failed ***\n");
  5505. DbgPrint(" ExpirationTimes differ.\n");
  5506. DbgPrint(" ");
  5507. CompletionStatus = FALSE;
  5508. }
  5509. //
  5510. // TokenType
  5511. //
  5512. if ( OldStatistics.TokenType != NewStatistics.TokenType ) {
  5513. DbgPrint("*** Failed ***\n");
  5514. DbgPrint(" Token types are different.\n");
  5515. DbgPrint(" Old token type is: 0x%lx \n", OldStatistics.TokenType );
  5516. DbgPrint(" New token type is: 0x%lx \n", NewStatistics.TokenType );
  5517. DbgPrint(" ");
  5518. CompletionStatus = FALSE;
  5519. }
  5520. //
  5521. // ImpersonationLevel
  5522. //
  5523. if (NewStatistics.TokenType = TokenImpersonation) {
  5524. if ( OldStatistics.ImpersonationLevel !=
  5525. NewStatistics.ImpersonationLevel ) {
  5526. DbgPrint("*** Failed ***\n");
  5527. DbgPrint(" Impersonation levels are different.\n");
  5528. DbgPrint(" Old impersonation level is: 0x%lx \n",
  5529. OldStatistics.ImpersonationLevel );
  5530. DbgPrint(" New impersonation level is: 0x%lx \n",
  5531. NewStatistics.ImpersonationLevel );
  5532. DbgPrint(" ");
  5533. CompletionStatus = FALSE;
  5534. }
  5535. }
  5536. //
  5537. // DynamicCharged
  5538. //
  5539. if ( OldStatistics.DynamicCharged != NewStatistics.DynamicCharged ) {
  5540. DbgPrint("*** Failed ***\n");
  5541. DbgPrint(" DynamicCharges are different.\n");
  5542. DbgPrint(" Old value is: 0x%lx \n", OldStatistics.DynamicCharged );
  5543. DbgPrint(" New value is: 0x%lx \n", NewStatistics.DynamicCharged );
  5544. DbgPrint(" ");
  5545. CompletionStatus = FALSE;
  5546. }
  5547. //
  5548. // DynamicAvailable
  5549. //
  5550. if ( OldStatistics.DynamicAvailable != NewStatistics.DynamicAvailable ) {
  5551. DbgPrint("*** Failed ***\n");
  5552. DbgPrint(" DynamicAvailable are different.\n");
  5553. DbgPrint(" Old value is: 0x%lx \n", OldStatistics.DynamicAvailable );
  5554. DbgPrint(" New value is: 0x%lx \n", NewStatistics.DynamicAvailable );
  5555. DbgPrint(" ");
  5556. CompletionStatus = FALSE;
  5557. }
  5558. //
  5559. // ModifiedId
  5560. //
  5561. if ( (NewStatistics.ModifiedId.HighPart !=
  5562. OldStatistics.ModifiedId.HighPart) ||
  5563. (NewStatistics.ModifiedId.LowPart !=
  5564. OldStatistics.ModifiedId.LowPart) ) {
  5565. DbgPrint("*** Failed ***\n");
  5566. DbgPrint(" ModifiedIds different.\n");
  5567. DbgPrint(" Old ModifiedId is: (0x%xl, 0x%xl)\n",
  5568. OldStatistics.ModifiedId.HighPart,
  5569. OldStatistics.ModifiedId.LowPart);
  5570. DbgPrint(" New ModifiedId is: (0x%xl, 0x%xl)\n",
  5571. NewStatistics.ModifiedId.HighPart,
  5572. NewStatistics.ModifiedId.LowPart);
  5573. DbgPrint(" ");
  5574. CompletionStatus = FALSE;
  5575. }
  5576. }
  5577. //
  5578. // Compare the group IDs
  5579. //
  5580. SomeNotCompared = TRUE;
  5581. //
  5582. // Compare the privileges
  5583. //
  5584. SomeNotCompared = TRUE;
  5585. //
  5586. // Compare the owner IDs
  5587. //
  5588. SomeNotCompared = TRUE;
  5589. //
  5590. // Compare the primary group IDs
  5591. //
  5592. SomeNotCompared = TRUE;
  5593. //
  5594. // Compare the default dacls
  5595. //
  5596. SomeNotCompared = TRUE;
  5597. //
  5598. // Compare the token source
  5599. //
  5600. if (CompletionStatus) {
  5601. Status = NtQueryInformationToken(
  5602. OldToken, // Handle
  5603. TokenSource, // TokenInformationClass
  5604. &OldSource, // TokenInformation
  5605. (ULONG)sizeof(TOKEN_SOURCE), // TokenInformationLength
  5606. &OldReturnLength // ReturnLength
  5607. ); ASSERT(NT_SUCCESS(Status));
  5608. Status = NtQueryInformationToken(
  5609. NewToken, // Handle
  5610. TokenSource, // TokenInformationClass
  5611. &NewSource, // TokenInformation
  5612. (ULONG)sizeof(TOKEN_SOURCE), // TokenInformationLength
  5613. &NewReturnLength // ReturnLength
  5614. ); ASSERT(NT_SUCCESS(Status));
  5615. if ( (OldSource.SourceIdentifier.HighPart ==
  5616. NewSource.SourceIdentifier.HighPart) &&
  5617. (OldSource.SourceIdentifier.LowPart ==
  5618. NewSource.SourceIdentifier.LowPart) ) {
  5619. if ( (OldSource.SourceName[0] != NewSource.SourceName[0]) ||
  5620. (OldSource.SourceName[1] != NewSource.SourceName[1]) ||
  5621. (OldSource.SourceName[2] != NewSource.SourceName[2]) ||
  5622. (OldSource.SourceName[3] != NewSource.SourceName[3]) ||
  5623. (OldSource.SourceName[4] != NewSource.SourceName[4]) ||
  5624. (OldSource.SourceName[5] != NewSource.SourceName[5]) ||
  5625. (OldSource.SourceName[6] != NewSource.SourceName[6]) ||
  5626. (OldSource.SourceName[7] != NewSource.SourceName[7]) ) {
  5627. DbgPrint("*** Failed Value Comparison ***\n");
  5628. DbgPrint(" SourceName changed.\n");
  5629. CompletionStatus = FALSE;
  5630. }
  5631. } else {
  5632. DbgPrint("*** Failed Value Comparison ***\n");
  5633. DbgPrint(" SourceIdentifier changed.\n");
  5634. DbgPrint(" Old SourceIdentifier is: (0x%xl, 0x%xl)\n",
  5635. OldSource.SourceIdentifier.HighPart,
  5636. OldSource.SourceIdentifier.LowPart);
  5637. DbgPrint(" New SourceIdentifier is: (0x%xl, 0x%xl)\n",
  5638. NewSource.SourceIdentifier.HighPart,
  5639. NewSource.SourceIdentifier.LowPart);
  5640. CompletionStatus = FALSE;
  5641. }
  5642. }
  5643. ////////////////////////////////// Done /////////////////////////
  5644. if (SomeNotCompared) {
  5645. DbgPrint("Incomplete\n");
  5646. DbgPrint(" Some fields not yet compared ... ");
  5647. }
  5648. if (CompletionStatus) {
  5649. DbgPrint("Succeeded. \n");
  5650. }
  5651. return CompletionStatus;
  5652. }
  5653. ////////////////////////////////////////////////////////////////
  5654. // //
  5655. // Duplicate Token Test //
  5656. // //
  5657. ////////////////////////////////////////////////////////////////
  5658. BOOLEAN
  5659. TestTokenDuplicate()
  5660. {
  5661. BOOLEAN CompletionStatus = TRUE;
  5662. BOOLEAN EffectiveOnly;
  5663. TOKEN_TYPE NewType;
  5664. HANDLE NewToken;
  5665. OBJECT_ATTRIBUTES NewAttributes;
  5666. SECURITY_QUALITY_OF_SERVICE ImpersonationLevel;
  5667. SECURITY_QUALITY_OF_SERVICE IdentificationLevel;
  5668. DbgPrint("\n");
  5669. //
  5670. // Initialize variables
  5671. //
  5672. ImpersonationLevel.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
  5673. ImpersonationLevel.ImpersonationLevel = SecurityImpersonation;
  5674. ImpersonationLevel.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  5675. ImpersonationLevel.EffectiveOnly = FALSE;
  5676. IdentificationLevel.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
  5677. IdentificationLevel.ImpersonationLevel = SecurityImpersonation;
  5678. IdentificationLevel.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  5679. IdentificationLevel.EffectiveOnly = FALSE;
  5680. InitializeObjectAttributes(
  5681. &NewAttributes,
  5682. NULL,
  5683. OBJ_INHERIT,
  5684. NULL,
  5685. NULL
  5686. );
  5687. ////////////////////////////////////////////////////////////
  5688. // //
  5689. // Duplicate the simple token //
  5690. // //
  5691. ////////////////////////////////////////////////////////////
  5692. DbgPrint("Se: Duplicate primary token ... ");
  5693. EffectiveOnly = FALSE;
  5694. NewType = TokenImpersonation;
  5695. NewAttributes.SecurityQualityOfService = &ImpersonationLevel;
  5696. Status = NtDuplicateToken(
  5697. SimpleToken, // ExistingTokenHandle
  5698. 0, // DesiredAccess
  5699. &NewAttributes, // ObjectAttributes
  5700. EffectiveOnly, // EffectiveOnly
  5701. NewType, // TokenType
  5702. &NewToken // NewTokenHandle
  5703. );
  5704. if (NT_SUCCESS(Status)) {
  5705. DbgPrint("Succeeded.\n");
  5706. Status = NtClose( NewToken ); ASSERT(NT_SUCCESS(NewToken));
  5707. } else {
  5708. DbgPrint("********** Failed ************\n");
  5709. DbgPrint("Status is: 0x%lx \n", Status);
  5710. return FALSE;
  5711. }
  5712. ////////////////////////////////////////////////////////////
  5713. // //
  5714. // Duplicate the restricted token //
  5715. // //
  5716. ////////////////////////////////////////////////////////////
  5717. DbgPrint("Se: Duplicate restricted sids ... ");
  5718. EffectiveOnly = FALSE;
  5719. NewType = TokenImpersonation;
  5720. NewAttributes.SecurityQualityOfService = &ImpersonationLevel;
  5721. Status = NtDuplicateToken(
  5722. TokenWithRestrictedSids, // ExistingTokenHandle
  5723. 0, // DesiredAccess
  5724. &NewAttributes, // ObjectAttributes
  5725. EffectiveOnly, // EffectiveOnly
  5726. NewType, // TokenType
  5727. &NewToken // NewTokenHandle
  5728. );
  5729. if (NT_SUCCESS(Status)) {
  5730. DbgPrint("Succeeded.\n");
  5731. Status = NtClose( NewToken ); ASSERT(NT_SUCCESS(NewToken));
  5732. } else {
  5733. DbgPrint("********** Failed ************\n");
  5734. DbgPrint("Status is: 0x%lx \n", Status);
  5735. return FALSE;
  5736. }
  5737. ////////////////////////////////////////////////////////////
  5738. // //
  5739. // Duplicate the token with restricted groups //
  5740. // //
  5741. ////////////////////////////////////////////////////////////
  5742. DbgPrint("Se: Duplicate restricted groups ... ");
  5743. EffectiveOnly = TRUE;
  5744. NewType = TokenImpersonation;
  5745. NewAttributes.SecurityQualityOfService = &ImpersonationLevel;
  5746. Status = NtDuplicateToken(
  5747. TokenWithRestrictedSids, // ExistingTokenHandle
  5748. 0, // DesiredAccess
  5749. &NewAttributes, // ObjectAttributes
  5750. EffectiveOnly, // EffectiveOnly
  5751. NewType, // TokenType
  5752. &NewToken // NewTokenHandle
  5753. );
  5754. if (NT_SUCCESS(Status)) {
  5755. DbgPrint("Succeeded.\n");
  5756. Status = NtClose( NewToken ); ASSERT(NT_SUCCESS(NewToken));
  5757. } else {
  5758. DbgPrint("********** Failed ************\n");
  5759. DbgPrint("Status is: 0x%lx \n", Status);
  5760. return FALSE;
  5761. }
  5762. ////////////////////////////////////////////////////////////
  5763. // //
  5764. // Duplicate the full impersonation token //
  5765. // //
  5766. ////////////////////////////////////////////////////////////
  5767. DbgPrint("Se: Duplicate full impersonation token ... ");
  5768. EffectiveOnly = FALSE;
  5769. NewType = TokenImpersonation;
  5770. NewAttributes.SecurityQualityOfService = &ImpersonationLevel;
  5771. Status = NtDuplicateToken(
  5772. ImpersonationToken, // ExistingTokenHandle
  5773. 0, // DesiredAccess
  5774. &NewAttributes, // ObjectAttributes
  5775. EffectiveOnly, // EffectiveOnly
  5776. NewType, // TokenType
  5777. &NewToken // NewTokenHandle
  5778. );
  5779. //
  5780. // Check to see that the duplicate is really a duplicate of
  5781. // the original and display the test results.
  5782. //
  5783. if (!TestpCompareDuplicateToken( Status,
  5784. ImpersonationToken,
  5785. NewAttributes,
  5786. EffectiveOnly,
  5787. NewType,
  5788. NewToken ) ) {
  5789. CompletionStatus = FALSE;
  5790. }
  5791. if (NT_SUCCESS(Status)) {
  5792. Status = NtClose( NewToken );
  5793. ASSERT(NT_SUCCESS(Status));
  5794. }
  5795. ////////////////////////////////////////////////////////////
  5796. // //
  5797. // Duplicate the full token, effective only //
  5798. // //
  5799. ////////////////////////////////////////////////////////////
  5800. DbgPrint("Se: Duplicate full token, effective only ... ");
  5801. EffectiveOnly = TRUE;
  5802. NewType = TokenImpersonation;
  5803. NewAttributes.SecurityQualityOfService = &ImpersonationLevel;
  5804. Status = NtDuplicateToken(
  5805. ImpersonationToken, // ExistingTokenHandle
  5806. 0, // DesiredAccess
  5807. &NewAttributes, // ObjectAttributes
  5808. EffectiveOnly, // EffectiveOnly
  5809. NewType, // TokenType
  5810. &NewToken // NewTokenHandle
  5811. );
  5812. //
  5813. // Check to see that the duplicate is really a duplicate of
  5814. // the original and display the test results.
  5815. //
  5816. if (!TestpCompareDuplicateToken( Status,
  5817. ImpersonationToken,
  5818. NewAttributes,
  5819. EffectiveOnly,
  5820. NewType,
  5821. NewToken ) ) {
  5822. CompletionStatus = FALSE;
  5823. }
  5824. if (NT_SUCCESS(Status)) {
  5825. Status = NtClose( NewToken );
  5826. ASSERT(NT_SUCCESS(Status));
  5827. }
  5828. return CompletionStatus;
  5829. }
  5830. ////////////////////////////////////////////////////////////////
  5831. // //
  5832. // Assign Primary Token Test //
  5833. // //
  5834. ////////////////////////////////////////////////////////////////
  5835. BOOLEAN
  5836. TestTokenAssignPrimary()
  5837. {
  5838. BOOLEAN CompletionStatus = TRUE;
  5839. ULONG ReturnLength;
  5840. TOKEN_STATISTICS OriginalTokenStatistics;
  5841. TOKEN_STATISTICS NewTokenStatistics;
  5842. TOKEN_STATISTICS AssignedTokenStatistics;
  5843. TOKEN_USER UserId;
  5844. TOKEN_PRIMARY_GROUP PrimaryGroup;
  5845. PTOKEN_GROUPS GroupIds;
  5846. PTOKEN_PRIVILEGES Privileges;
  5847. TOKEN_DEFAULT_DACL DefaultDacl;
  5848. TOKEN_OWNER Owner;
  5849. PROCESS_ACCESS_TOKEN PrimaryTokenInfo;
  5850. DbgPrint("\n");
  5851. ////////////////////////////////////////////////////////////
  5852. // //
  5853. // Assign a valid primary token //
  5854. // //
  5855. ////////////////////////////////////////////////////////////
  5856. DbgPrint("Se: Assign new primary token ... ");
  5857. //
  5858. // Get information about the current token
  5859. //
  5860. Status = NtOpenProcessToken(
  5861. NtCurrentProcess(),
  5862. TOKEN_ALL_ACCESS,
  5863. &ProcessToken
  5864. );
  5865. ASSERT (NT_SUCCESS(Status));
  5866. Status = NtQueryInformationToken(
  5867. ProcessToken, // Handle
  5868. TokenStatistics, // TokenInformationClass
  5869. &OriginalTokenStatistics, // TokenInformation
  5870. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  5871. &ReturnLength // ReturnLength
  5872. );
  5873. ASSERT(NT_SUCCESS(Status));
  5874. //
  5875. // Create a token with default DACL for use
  5876. //
  5877. GroupIds = (PTOKEN_GROUPS)TstAllocatePool( PagedPool,
  5878. GROUP_IDS_LENGTH
  5879. );
  5880. Privileges = (PTOKEN_PRIVILEGES)TstAllocatePool( PagedPool,
  5881. PRIVILEGES_LENGTH
  5882. );
  5883. DefaultDacl.DefaultDacl = (PACL)TstAllocatePool( PagedPool,
  5884. DEFAULT_DACL_LENGTH
  5885. );
  5886. GroupIds->GroupCount = GROUP_COUNT;
  5887. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  5888. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  5889. GroupIds->Groups[SYSTEM_INDEX].Sid = LocalSystemSid;
  5890. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  5891. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  5892. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  5893. GroupIds->Groups[SYSTEM_INDEX].Attributes = OptionalGroupAttributes;
  5894. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  5895. UserId.User.Sid = PebblesSid;
  5896. UserId.User.Attributes = 0;
  5897. Owner.Owner = FlintstoneSid;
  5898. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  5899. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  5900. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  5901. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  5902. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  5903. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  5904. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  5905. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  5906. Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);
  5907. ASSERT(NT_SUCCESS(Status) );
  5908. Status = NtCreateToken(
  5909. &Token, // Handle
  5910. (TOKEN_ALL_ACCESS), // DesiredAccess
  5911. &PrimaryTokenAttributes, // ObjectAttributes
  5912. TokenPrimary, // TokenType
  5913. &SystemAuthenticationId, // Authentication LUID
  5914. &NoExpiration, // Expiration Time
  5915. &UserId, // Owner ID
  5916. GroupIds, // Group IDs
  5917. Privileges, // Privileges
  5918. &Owner, // Owner
  5919. &PrimaryGroup, // Primary Group
  5920. &DefaultDacl, // Default Dacl
  5921. &TestSource // TokenSource
  5922. );
  5923. ASSERT(NT_SUCCESS(Status));
  5924. //
  5925. // Make sure key data is different than what is already on the process.
  5926. //
  5927. Status = NtQueryInformationToken(
  5928. Token, // Handle
  5929. TokenStatistics, // TokenInformationClass
  5930. &NewTokenStatistics, // TokenInformation
  5931. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  5932. &ReturnLength // ReturnLength
  5933. );
  5934. ASSERT(NT_SUCCESS(Status));
  5935. ASSERT( (OriginalTokenStatistics.TokenId.HighPart !=
  5936. NewTokenStatistics.TokenId.HighPart) ||
  5937. (OriginalTokenStatistics.TokenId.LowPart !=
  5938. NewTokenStatistics.TokenId.LowPart) );
  5939. //
  5940. // Assign the new token
  5941. //
  5942. PrimaryTokenInfo.Token = Token;
  5943. PrimaryTokenInfo.Thread = NtCurrentThread();
  5944. Status = NtSetInformationProcess(
  5945. NtCurrentProcess(),
  5946. ProcessAccessToken,
  5947. (PVOID)&PrimaryTokenInfo,
  5948. (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
  5949. );
  5950. if (!NT_SUCCESS(Status)) {
  5951. DbgPrint("********** Failed ************\n");
  5952. DbgPrint("Status is: 0x%lx \n", Status);
  5953. CompletionStatus = FALSE;
  5954. } else {
  5955. Status = NtClose( Token );
  5956. ASSERT(NT_SUCCESS(Status));
  5957. //
  5958. // Get information about the assigned token
  5959. //
  5960. Status = NtOpenProcessToken(
  5961. NtCurrentProcess(),
  5962. TOKEN_QUERY | TOKEN_QUERY_SOURCE,
  5963. &Token
  5964. );
  5965. ASSERT (NT_SUCCESS(Status));
  5966. Status = NtQueryInformationToken(
  5967. Token, // Handle
  5968. TokenStatistics, // TokenInformationClass
  5969. &AssignedTokenStatistics, // TokenInformation
  5970. sizeof(TOKEN_STATISTICS), // TokenInformationLength
  5971. &ReturnLength // ReturnLength
  5972. );
  5973. ASSERT(NT_SUCCESS(Status));
  5974. Status = NtClose( Token );
  5975. ASSERT(NT_SUCCESS(Status));
  5976. //
  5977. // Information about assigned token and the new token
  5978. // should be the same
  5979. //
  5980. ASSERT(AssignedTokenStatistics.TokenType == TokenPrimary);
  5981. if ( (NewTokenStatistics.TokenId.HighPart ==
  5982. AssignedTokenStatistics.TokenId.HighPart) &&
  5983. (NewTokenStatistics.TokenId.LowPart ==
  5984. AssignedTokenStatistics.TokenId.LowPart) ) {
  5985. DbgPrint("Succeeded.\n");
  5986. } else {
  5987. DbgPrint("********** Failed ************\n");
  5988. DbgPrint("Token ID mismatch.\n");
  5989. DbgPrint("New token ID is: (0x%lx, 0x%lx) \n",
  5990. NewTokenStatistics.TokenId.HighPart,
  5991. NewTokenStatistics.TokenId.LowPart);
  5992. DbgPrint("Assigned token ID is: (0x%lx, 0x%lx) \n",
  5993. AssignedTokenStatistics.TokenId.HighPart,
  5994. AssignedTokenStatistics.TokenId.LowPart);
  5995. CompletionStatus = FALSE;
  5996. }
  5997. }
  5998. //
  5999. // Change back to the original token
  6000. //
  6001. PrimaryTokenInfo.Token = ProcessToken;
  6002. PrimaryTokenInfo.Thread = NtCurrentThread();
  6003. Status = NtSetInformationProcess(
  6004. NtCurrentProcess(),
  6005. ProcessAccessToken,
  6006. (PVOID)&PrimaryTokenInfo,
  6007. (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
  6008. );
  6009. ASSERT(NT_SUCCESS(Status));
  6010. Status = NtClose( ProcessToken );
  6011. ASSERT(NT_SUCCESS(Status));
  6012. ////////////////////////////////////////////////////////////
  6013. // //
  6014. // Attempt to assign an impersonation token as primary //
  6015. // //
  6016. ////////////////////////////////////////////////////////////
  6017. DbgPrint("Se: Assign impersonation token as primary ... ");
  6018. //
  6019. // Create an impersonation token
  6020. //
  6021. GroupIds->GroupCount = GROUP_COUNT;
  6022. GroupIds->Groups[FLINTSTONE_INDEX].Sid = FlintstoneSid;
  6023. GroupIds->Groups[CHILD_INDEX].Sid = ChildSid;
  6024. GroupIds->Groups[NEANDERTHOL_INDEX].Sid = NeandertholSid;
  6025. GroupIds->Groups[WORLD_INDEX].Sid = WorldSid;
  6026. GroupIds->Groups[FLINTSTONE_INDEX].Attributes = OwnerGroupAttributes;
  6027. GroupIds->Groups[CHILD_INDEX].Attributes = OptionalGroupAttributes;
  6028. GroupIds->Groups[NEANDERTHOL_INDEX].Attributes = OptionalGroupAttributes;
  6029. GroupIds->Groups[WORLD_INDEX].Attributes = NormalGroupAttributes;
  6030. UserId.User.Sid = PebblesSid;
  6031. UserId.User.Attributes = 0;
  6032. Owner.Owner = FlintstoneSid;
  6033. Privileges->PrivilegeCount = PRIVILEGE_COUNT;
  6034. Privileges->Privileges[UNSOLICITED_INDEX].Luid = UnsolicitedInputPrivilege;
  6035. Privileges->Privileges[SECURITY_INDEX].Luid = SecurityPrivilege;
  6036. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Luid = AssignPrimaryTokenPrivilege;
  6037. Privileges->Privileges[UNSOLICITED_INDEX].Attributes = 0;
  6038. Privileges->Privileges[SECURITY_INDEX].Attributes = 0;
  6039. Privileges->Privileges[ASSIGN_PRIMARY_INDEX].Attributes = SE_PRIVILEGE_ENABLED;
  6040. PrimaryGroup.PrimaryGroup = FlintstoneSid;
  6041. Status = RtlCreateAcl( DefaultDacl.DefaultDacl, DEFAULT_DACL_LENGTH, ACL_REVISION);
  6042. ASSERT(NT_SUCCESS(Status) );
  6043. Status = NtCreateToken(
  6044. &Token, // Handle
  6045. (TOKEN_ALL_ACCESS), // DesiredAccess
  6046. &ImpersonationTokenAttributes, // ObjectAttributes
  6047. TokenImpersonation, // TokenType
  6048. &OriginalAuthenticationId, // Authentication LUID
  6049. &NoExpiration, // Expiration Time
  6050. &UserId, // Owner ID
  6051. GroupIds, // Group IDs
  6052. Privileges, // Privileges
  6053. &Owner, // Owner
  6054. &PrimaryGroup, // Primary Group
  6055. &DefaultDacl, // Default Dacl
  6056. &TestSource // TokenSource
  6057. );
  6058. ASSERT(NT_SUCCESS(Status));
  6059. //
  6060. // Assign the new token
  6061. //
  6062. PrimaryTokenInfo.Token = Token;
  6063. PrimaryTokenInfo.Thread = NtCurrentThread();
  6064. Status = NtSetInformationProcess(
  6065. NtCurrentProcess(),
  6066. ProcessAccessToken,
  6067. (PVOID)&PrimaryTokenInfo,
  6068. (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
  6069. );
  6070. if (Status == STATUS_BAD_TOKEN_TYPE) {
  6071. DbgPrint("Succeeded.\n");
  6072. } else {
  6073. DbgPrint("********** Failed ************\n");
  6074. DbgPrint("Status is: 0x%lx \n", Status);
  6075. CompletionStatus = FALSE;
  6076. }
  6077. Status = NtClose( Token );
  6078. ASSERT(NT_SUCCESS(Status));
  6079. return CompletionStatus;
  6080. }
  6081. ////////////////////////////////////////////////////////////////
  6082. // //
  6083. // Impersonation Test (with open test) //
  6084. // //
  6085. ////////////////////////////////////////////////////////////////
  6086. BOOLEAN
  6087. TestTokenImpersonation()
  6088. {
  6089. BOOLEAN CompletionStatus = TRUE;
  6090. HANDLE OpenedToken;
  6091. HANDLE NewToken;
  6092. OBJECT_ATTRIBUTES NewAttributes;
  6093. TOKEN_TYPE NewType;
  6094. BOOLEAN EffectiveOnly = FALSE;
  6095. SECURITY_QUALITY_OF_SERVICE ImpersonationLevel;
  6096. DbgPrint("\n");
  6097. ////////////////////////////////////////////////////////////
  6098. // //
  6099. // Terminate impersonation using NtSetInformationThread() //
  6100. // //
  6101. ////////////////////////////////////////////////////////////
  6102. DbgPrint("Se: Revert to self (specify NULL handle) ... ");
  6103. NewToken = NULL;
  6104. Status = NtSetInformationThread(
  6105. NtCurrentThread(),
  6106. ThreadImpersonationToken,
  6107. (PVOID)&NewToken,
  6108. (ULONG)sizeof(HANDLE)
  6109. );
  6110. if (NT_SUCCESS(Status)) {
  6111. DbgPrint("Succeeded.\n");
  6112. } else {
  6113. DbgPrint("********** Failed ************\n");
  6114. DbgPrint("Status is: 0x%lx \n", Status);
  6115. CompletionStatus = FALSE;
  6116. }
  6117. ////////////////////////////////////////////////////////////
  6118. // //
  6119. // Attempt to assign a primary token as an impersonation //
  6120. // token. //
  6121. // //
  6122. ////////////////////////////////////////////////////////////
  6123. DbgPrint("Se: Assigning primary token as impersonation token ... ");
  6124. NewToken = TokenWithGroups;
  6125. Status = NtSetInformationThread(
  6126. NtCurrentThread(),
  6127. ThreadImpersonationToken,
  6128. (PVOID)&NewToken,
  6129. (ULONG)sizeof(HANDLE)
  6130. );
  6131. if (Status == STATUS_BAD_TOKEN_TYPE) {
  6132. DbgPrint("Succeeded.\n");
  6133. } else {
  6134. DbgPrint("********** Failed ************\n");
  6135. DbgPrint("Status is: 0x%lx \n", Status);
  6136. CompletionStatus = FALSE;
  6137. }
  6138. ////////////////////////////////////////////////////////////
  6139. // //
  6140. // Assign a valid impersonation token //
  6141. // //
  6142. ////////////////////////////////////////////////////////////
  6143. DbgPrint("Se: Assign valid impersonation token ... ");
  6144. NewToken = ImpersonationToken;
  6145. Status = NtSetInformationThread(
  6146. NtCurrentThread(),
  6147. ThreadImpersonationToken,
  6148. (PVOID)&NewToken,
  6149. (ULONG)sizeof(HANDLE)
  6150. );
  6151. if (NT_SUCCESS(Status)) {
  6152. DbgPrint("Succeeded.\n");
  6153. } else {
  6154. DbgPrint("********** Failed ************\n");
  6155. DbgPrint("Status is: 0x%lx \n", Status);
  6156. CompletionStatus = FALSE;
  6157. }
  6158. ////////////////////////////////////////////////////////////
  6159. // //
  6160. // Open the impersonation token //
  6161. // //
  6162. ////////////////////////////////////////////////////////////
  6163. DbgPrint("Se: Open an impersonation token ... ");
  6164. Status = NtOpenThreadToken(
  6165. NtCurrentThread(),
  6166. TOKEN_ALL_ACCESS,
  6167. TRUE,
  6168. &OpenedToken
  6169. );
  6170. if (NT_SUCCESS(Status)) {
  6171. DbgPrint("Succeeded.\n");
  6172. Status = NtClose( OpenedToken );
  6173. ASSERT(NT_SUCCESS(Status));
  6174. } else {
  6175. DbgPrint("********** Failed ************\n");
  6176. DbgPrint("Status is: 0x%lx \n", Status);
  6177. CompletionStatus = FALSE;
  6178. }
  6179. ////////////////////////////////////////////////////////////
  6180. // //
  6181. // Open a non-existent impersonation token //
  6182. // //
  6183. ////////////////////////////////////////////////////////////
  6184. DbgPrint("Se: Open a non-existent impersonation token ... ");
  6185. //
  6186. // Clear any existing impersonation token.
  6187. //
  6188. NewToken = NULL;
  6189. Status = NtSetInformationThread(
  6190. NtCurrentThread(),
  6191. ThreadImpersonationToken,
  6192. (PVOID)&NewToken,
  6193. (ULONG)sizeof(HANDLE)
  6194. ); ASSERT(NT_SUCCESS(Status));
  6195. Status = NtOpenThreadToken(
  6196. NtCurrentThread(),
  6197. TOKEN_ALL_ACCESS,
  6198. TRUE,
  6199. &OpenedToken
  6200. );
  6201. if (Status == STATUS_NO_TOKEN) {
  6202. DbgPrint("Succeeded.\n");
  6203. } else {
  6204. DbgPrint("********** Failed ************\n");
  6205. DbgPrint("Status is: 0x%lx \n", Status);
  6206. CompletionStatus = FALSE;
  6207. }
  6208. ////////////////////////////////////////////////////////////
  6209. // //
  6210. // Open an anonymous impersonation token //
  6211. // //
  6212. ////////////////////////////////////////////////////////////
  6213. DbgPrint("Se: Open an anonymous impersonation token ... ");
  6214. //
  6215. // Assign an anonymous impersonation token
  6216. //
  6217. NewToken = AnonymousToken;
  6218. Status = NtSetInformationThread(
  6219. ThreadHandle,
  6220. ThreadImpersonationToken,
  6221. (PVOID)&NewToken,
  6222. (ULONG)sizeof(HANDLE)
  6223. ); ASSERT(NT_SUCCESS(Status));
  6224. Status = NtOpenThreadToken(
  6225. ThreadHandle,
  6226. TOKEN_ALL_ACCESS,
  6227. TRUE,
  6228. &OpenedToken
  6229. );
  6230. if (Status == STATUS_CANT_OPEN_ANONYMOUS) {
  6231. DbgPrint("Succeeded.\n");
  6232. } else {
  6233. DbgPrint("********** Failed ************\n");
  6234. DbgPrint("Status is: 0x%lx \n", Status);
  6235. CompletionStatus = FALSE;
  6236. }
  6237. ////////////////////////////////////////////////////////////
  6238. // //
  6239. // Change the impersonation of a thread //
  6240. // //
  6241. ////////////////////////////////////////////////////////////
  6242. DbgPrint("Se: Change the impersonation token ... ");
  6243. NewToken = NULL;
  6244. Status = NtSetInformationThread(
  6245. ThreadHandle,
  6246. ThreadImpersonationToken,
  6247. (PVOID)&NewToken,
  6248. (ULONG)sizeof(HANDLE)
  6249. ); ASSERT(NT_SUCCESS(Status));
  6250. NewToken = AnonymousToken;
  6251. Status = NtSetInformationThread(
  6252. ThreadHandle,
  6253. ThreadImpersonationToken,
  6254. (PVOID)&NewToken,
  6255. (ULONG)sizeof(HANDLE)
  6256. ); ASSERT(NT_SUCCESS(Status));
  6257. NewToken = ImpersonationToken;
  6258. Status = NtSetInformationThread(
  6259. ThreadHandle,
  6260. ThreadImpersonationToken,
  6261. (PVOID)&NewToken,
  6262. (ULONG)sizeof(HANDLE)
  6263. );
  6264. if (NT_SUCCESS(Status)) {
  6265. DbgPrint("Succeeded.\n");
  6266. } else {
  6267. DbgPrint("********** Failed ************\n");
  6268. DbgPrint("Status is: 0x%lx \n", Status);
  6269. CompletionStatus = FALSE;
  6270. }
  6271. ////////////////////////////////////////////////////////////
  6272. // //
  6273. // Impersonate a restricted token //
  6274. // //
  6275. ////////////////////////////////////////////////////////////
  6276. DbgPrint("Se: Impersonate restricted token ... ");
  6277. NewToken = NULL;
  6278. Status = NtSetInformationThread(
  6279. NtCurrentThread(),
  6280. ThreadImpersonationToken,
  6281. (PVOID)&NewToken,
  6282. (ULONG)sizeof(HANDLE)
  6283. ); ASSERT(NT_SUCCESS(Status));
  6284. //
  6285. // Initialize variables
  6286. //
  6287. InitializeObjectAttributes(
  6288. &NewAttributes,
  6289. NULL,
  6290. OBJ_INHERIT,
  6291. NULL,
  6292. NULL
  6293. );
  6294. ImpersonationLevel.Length = (ULONG)sizeof(SECURITY_QUALITY_OF_SERVICE);
  6295. ImpersonationLevel.ImpersonationLevel = SecurityImpersonation;
  6296. ImpersonationLevel.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  6297. ImpersonationLevel.EffectiveOnly = FALSE;
  6298. NewType = TokenImpersonation;
  6299. NewAttributes.SecurityQualityOfService = &ImpersonationLevel;
  6300. Status = NtDuplicateToken(
  6301. TokenWithRestrictedSids, // ExistingTokenHandle
  6302. TOKEN_ALL_ACCESS, // DesiredAccess
  6303. &NewAttributes, // ObjectAttributes
  6304. EffectiveOnly, // EffectiveOnly
  6305. NewType, // TokenType
  6306. &NewToken // NewTokenHandle
  6307. );
  6308. if (NT_SUCCESS(Status)) {
  6309. DbgPrint("Succeeded.\n");
  6310. } else {
  6311. DbgPrint("********** Failed ************\n");
  6312. DbgPrint("Status is: 0x%lx \n", Status);
  6313. CompletionStatus = FALSE;
  6314. }
  6315. Status = NtSetInformationThread(
  6316. NtCurrentThread(),
  6317. ThreadImpersonationToken,
  6318. (PVOID)&NewToken,
  6319. (ULONG)sizeof(HANDLE)
  6320. ); ASSERT(NT_SUCCESS(Status));
  6321. //
  6322. // Now try to open something, like the process, which should fail
  6323. //
  6324. Status = NtOpenProcessToken(
  6325. NtCurrentProcess(),
  6326. TOKEN_QUERY | TOKEN_QUERY_SOURCE,
  6327. &Token
  6328. );
  6329. if (Status != STATUS_ACCESS_DENIED) {
  6330. DbgPrint("********** Failed ************\n");
  6331. DbgPrint("Status is: 0x%lx \n", Status);
  6332. CompletionStatus = FALSE;
  6333. }
  6334. Status = NtOpenProcessToken(
  6335. NtCurrentProcess(),
  6336. MAXIMUM_ALLOWED,
  6337. &Token
  6338. );
  6339. if (Status != STATUS_ACCESS_DENIED) {
  6340. DbgPrint("********** Failed ************\n");
  6341. DbgPrint("Status is: 0x%lx \n", Status);
  6342. CompletionStatus = FALSE;
  6343. }
  6344. Status = NtDuplicateToken(
  6345. TokenWithMoreRestrictedSids, // ExistingTokenHandle
  6346. TOKEN_ALL_ACCESS, // DesiredAccess
  6347. &NewAttributes, // ObjectAttributes
  6348. EffectiveOnly, // EffectiveOnly
  6349. NewType, // TokenType
  6350. &NewToken // NewTokenHandle
  6351. );
  6352. if (NT_SUCCESS(Status)) {
  6353. DbgPrint("Succeeded.\n");
  6354. } else {
  6355. DbgPrint("********** Failed ************\n");
  6356. DbgPrint("Status is: 0x%lx \n", Status);
  6357. CompletionStatus = FALSE;
  6358. }
  6359. Status = NtSetInformationThread(
  6360. NtCurrentThread(),
  6361. ThreadImpersonationToken,
  6362. (PVOID)&NewToken,
  6363. (ULONG)sizeof(HANDLE)
  6364. ); ASSERT(NT_SUCCESS(Status));
  6365. //
  6366. // Now try to open something, like the process, which should succeed
  6367. //
  6368. Status = NtOpenProcessToken(
  6369. NtCurrentProcess(),
  6370. TOKEN_QUERY | TOKEN_QUERY_SOURCE,
  6371. &Token
  6372. );
  6373. if (Status != STATUS_SUCCESS) {
  6374. DbgPrint("********** Failed ************\n");
  6375. DbgPrint("Status is: 0x%lx \n", Status);
  6376. CompletionStatus = FALSE;
  6377. }
  6378. Status = NtOpenProcessToken(
  6379. NtCurrentProcess(),
  6380. MAXIMUM_ALLOWED,
  6381. &Token
  6382. );
  6383. if (Status != STATUS_SUCCESS) {
  6384. DbgPrint("********** Failed ************\n");
  6385. DbgPrint("Status is: 0x%lx \n", Status);
  6386. CompletionStatus = FALSE;
  6387. }
  6388. NewToken = NULL;
  6389. Status = NtSetInformationThread(
  6390. NtCurrentThread(),
  6391. ThreadImpersonationToken,
  6392. (PVOID)&NewToken,
  6393. (ULONG)sizeof(HANDLE)
  6394. );
  6395. if (NT_SUCCESS(Status)) {
  6396. DbgPrint("Succeeded.\n");
  6397. } else {
  6398. DbgPrint("********** Failed ************\n");
  6399. DbgPrint("Status is: 0x%lx \n", Status);
  6400. CompletionStatus = FALSE;
  6401. }
  6402. Status = NtTerminateThread(
  6403. ThreadHandle,
  6404. (NTSTATUS)0
  6405. );
  6406. ASSERT(NT_SUCCESS(Status));
  6407. return CompletionStatus;
  6408. }
  6409. ////////////////////////////////////////////////////////////////
  6410. // //
  6411. // Main Program Entry //
  6412. // //
  6413. ////////////////////////////////////////////////////////////////
  6414. BOOLEAN
  6415. CTToken() // Common Test for Token object
  6416. {
  6417. BOOLEAN Result = TRUE;
  6418. DbgPrint("Se: Initialization...");
  6419. TestTokenInitialize();
  6420. DbgPrint("Se: Token Creation Test... Test");
  6421. if (!TestTokenCreate()) { Result = FALSE; }
  6422. DbgPrint("Se: Token Filtering Test... Test");
  6423. if (!TestTokenFilter()) { Result = FALSE; }
  6424. DbgPrint("Se: Token Open Test (with primary token)... Test");
  6425. if (!TestTokenOpenPrimary()) { Result = FALSE; }
  6426. DbgPrint("Se: Token Query Test... Test");
  6427. if (!TestTokenQuery()) { Result = FALSE; }
  6428. DbgPrint("Se: Token Set Test... Test");
  6429. if (!TestTokenSet()) { Result = FALSE; }
  6430. DbgPrint("Se: Token Adjust Privileges Test... Test");
  6431. if (!TestTokenAdjustPrivileges()) {Result = FALSE; }
  6432. DbgPrint("Se: Token Adjust Group Test... Test");
  6433. if (!TestTokenAdjustGroups()) { Result = FALSE; }
  6434. DbgPrint("Se: Token Duplication Test... Test");
  6435. if (!TestTokenDuplicate()) { Result = FALSE; }
  6436. DbgPrint("Se: Primary Token Assignment Test... Test");
  6437. if (!TestTokenAssignPrimary()) { Result = FALSE; }
  6438. DbgPrint("Se: Impersonation Test (and impersonation open)... Test");
  6439. if (!TestTokenImpersonation()) { Result = FALSE; }
  6440. DbgPrint("\n");
  6441. DbgPrint("\n");
  6442. DbgPrint(" ********************\n");
  6443. DbgPrint(" ** **\n");
  6444. if (Result) {
  6445. DbgPrint("Se: ** Test Succeeded **\n");
  6446. } else {
  6447. DbgPrint("Se: ** Test Failed **\n");
  6448. }
  6449. DbgPrint(" ** **\n");
  6450. DbgPrint(" ********************\n");
  6451. DbgPrint("\n");
  6452. DbgPrint("\n");
  6453. return Result;
  6454. }