Source code of Windows XP (NT5)
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.

2044 lines
57 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Tokenqry.c
  5. Abstract:
  6. This module implements the QUERY function for the executive
  7. token object.
  8. Author:
  9. Jim Kelly (JimK) 15-June-1990
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE,NtQueryInformationToken)
  16. #pragma alloc_text(PAGE,SeQueryAuthenticationIdToken)
  17. #pragma alloc_text(PAGE,SeQueryInformationToken)
  18. #pragma alloc_text(PAGE,SeQuerySessionIdToken)
  19. #endif
  20. NTSTATUS
  21. NtQueryInformationToken (
  22. IN HANDLE TokenHandle,
  23. IN TOKEN_INFORMATION_CLASS TokenInformationClass,
  24. OUT PVOID TokenInformation,
  25. IN ULONG TokenInformationLength,
  26. OUT PULONG ReturnLength
  27. )
  28. /*++
  29. Routine Description:
  30. Retrieve information about a specified token.
  31. Arguments:
  32. TokenHandle - Provides a handle to the token to operate on.
  33. TokenInformationClass - The token information class about which
  34. to retrieve information.
  35. TokenInformation - The buffer to receive the requested class of
  36. information. The buffer must be aligned on at least a
  37. longword boundary. The actual structures returned are
  38. dependent upon the information class requested, as defined in
  39. the TokenInformationClass parameter description.
  40. TokenInformation Format By Information Class:
  41. TokenUser => TOKEN_USER data structure. TOKEN_QUERY
  42. access is needed to retrieve this information about a
  43. token.
  44. TokenGroups => TOKEN_GROUPS data structure. TOKEN_QUERY
  45. access is needed to retrieve this information about a
  46. token.
  47. TokenPrivileges => TOKEN_PRIVILEGES data structure.
  48. TOKEN_QUERY access is needed to retrieve this information
  49. about a token.
  50. TokenOwner => TOKEN_OWNER data structure. TOKEN_QUERY
  51. access is needed to retrieve this information about a
  52. token.
  53. TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure.
  54. TOKEN_QUERY access is needed to retrieve this information
  55. about a token.
  56. TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure.
  57. TOKEN_QUERY access is needed to retrieve this information
  58. about a token.
  59. TokenSource => TOKEN_SOURCE data structure.
  60. TOKEN_QUERY_SOURCE access is needed to retrieve this
  61. information about a token.
  62. TokenType => TOKEN_TYPE data structure.
  63. TOKEN_QUERY access is needed to retrieve this information
  64. about a token.
  65. TokenStatistics => TOKEN_STATISTICS data structure.
  66. TOKEN_QUERY access is needed to retrieve this
  67. information about a token.
  68. TokenGroups => TOKEN_GROUPS data structure. TOKEN_QUERY
  69. access is needed to retrieve this information about a
  70. token.
  71. TokenInformationLength - Indicates the length, in bytes, of the
  72. TokenInformation buffer.
  73. ReturnLength - This OUT parameter receives the actual length of
  74. the requested information. If this value is larger than that
  75. provided by the TokenInformationLength parameter, then the
  76. buffer provided to receive the requested information is not
  77. large enough to hold that data and no data is returned.
  78. If the queried class is TokenDefaultDacl and there is no
  79. default Dacl established for the token, then the return
  80. length will be returned as zero, and no data will be returned.
  81. Return Value:
  82. STATUS_SUCCESS - Indicates the operation was successful.
  83. STATUS_BUFFER_TOO_SMALL - if the requested information did not
  84. fit in the provided output buffer. In this case, the
  85. ReturnLength OUT parameter contains the number of bytes
  86. actually needed to store the requested information.
  87. --*/
  88. {
  89. KPROCESSOR_MODE PreviousMode;
  90. NTSTATUS Status;
  91. PTOKEN Token;
  92. ULONG RequiredLength;
  93. ULONG Index;
  94. ULONG GroupsLength;
  95. ULONG RestrictedSidsLength;
  96. ULONG PrivilegesLength;
  97. PTOKEN_TYPE LocalType;
  98. PTOKEN_USER LocalUser;
  99. PTOKEN_GROUPS LocalGroups;
  100. PTOKEN_PRIVILEGES LocalPrivileges;
  101. PTOKEN_OWNER LocalOwner;
  102. PTOKEN_PRIMARY_GROUP LocalPrimaryGroup;
  103. PTOKEN_DEFAULT_DACL LocalDefaultDacl;
  104. PTOKEN_SOURCE LocalSource;
  105. PSECURITY_IMPERSONATION_LEVEL LocalImpersonationLevel;
  106. PTOKEN_STATISTICS LocalStatistics;
  107. PTOKEN_GROUPS_AND_PRIVILEGES LocalGroupsAndPrivileges;
  108. PSID PSid;
  109. PACL PAcl;
  110. PVOID Ignore;
  111. ULONG SessionId;
  112. PAGED_CODE();
  113. //
  114. // Get previous processor mode and probe output argument if necessary.
  115. //
  116. PreviousMode = KeGetPreviousMode();
  117. if (PreviousMode != KernelMode) {
  118. try {
  119. ProbeForWrite(
  120. TokenInformation,
  121. TokenInformationLength,
  122. sizeof(ULONG)
  123. );
  124. ProbeForWriteUlong(ReturnLength);
  125. } except(EXCEPTION_EXECUTE_HANDLER) {
  126. return GetExceptionCode();
  127. }
  128. }
  129. //
  130. // Case on information class.
  131. //
  132. switch ( TokenInformationClass ) {
  133. case TokenUser:
  134. LocalUser = (PTOKEN_USER)TokenInformation;
  135. Status = ObReferenceObjectByHandle(
  136. TokenHandle, // Handle
  137. TOKEN_QUERY, // DesiredAccess
  138. SeTokenObjectType, // ObjectType
  139. PreviousMode, // AccessMode
  140. (PVOID *)&Token, // Object
  141. NULL // GrantedAccess
  142. );
  143. if ( !NT_SUCCESS(Status) ) {
  144. return Status;
  145. }
  146. //
  147. // Gain exclusive access to the token.
  148. //
  149. SepAcquireTokenReadLock( Token );
  150. //
  151. // Return the length required now in case not enough buffer
  152. // was provided by the caller and we have to return an error.
  153. //
  154. RequiredLength = SeLengthSid( Token->UserAndGroups[0].Sid) +
  155. (ULONG)sizeof( TOKEN_USER );
  156. try {
  157. *ReturnLength = RequiredLength;
  158. } except(EXCEPTION_EXECUTE_HANDLER) {
  159. SepReleaseTokenReadLock( Token );
  160. ObDereferenceObject( Token );
  161. return GetExceptionCode();
  162. }
  163. if ( TokenInformationLength < RequiredLength ) {
  164. SepReleaseTokenReadLock( Token );
  165. ObDereferenceObject( Token );
  166. return STATUS_BUFFER_TOO_SMALL;
  167. }
  168. //
  169. // Return the user SID
  170. //
  171. try {
  172. //
  173. // Put SID immediately following TOKEN_USER data structure
  174. //
  175. PSid = (PSID)( (ULONG_PTR)LocalUser + (ULONG)sizeof(TOKEN_USER) );
  176. RtlCopySidAndAttributesArray(
  177. 1,
  178. Token->UserAndGroups,
  179. RequiredLength,
  180. &(LocalUser->User),
  181. PSid,
  182. ((PSID *)&Ignore),
  183. ((PULONG)&Ignore)
  184. );
  185. } except(EXCEPTION_EXECUTE_HANDLER) {
  186. SepReleaseTokenReadLock( Token );
  187. ObDereferenceObject( Token );
  188. return GetExceptionCode();
  189. }
  190. SepReleaseTokenReadLock( Token );
  191. ObDereferenceObject( Token );
  192. return STATUS_SUCCESS;
  193. case TokenGroups:
  194. LocalGroups = (PTOKEN_GROUPS)TokenInformation;
  195. Status = ObReferenceObjectByHandle(
  196. TokenHandle, // Handle
  197. TOKEN_QUERY, // DesiredAccess
  198. SeTokenObjectType, // ObjectType
  199. PreviousMode, // AccessMode
  200. (PVOID *)&Token, // Object
  201. NULL // GrantedAccess
  202. );
  203. if ( !NT_SUCCESS(Status) ) {
  204. return Status;
  205. }
  206. Index = 1;
  207. //
  208. // Gain exclusive access to the token.
  209. //
  210. SepAcquireTokenReadLock( Token );
  211. //
  212. // Figure out how much space is needed to return the group SIDs.
  213. // That's the size of TOKEN_GROUPS (without any array entries)
  214. // plus the size of an SID_AND_ATTRIBUTES times the number of groups.
  215. // The number of groups is Token->UserAndGroups-1 (since the count
  216. // includes the user ID). Then the lengths of each individual group
  217. // must be added.
  218. //
  219. RequiredLength = (ULONG)sizeof(TOKEN_GROUPS) +
  220. ((Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  221. ((ULONG)sizeof(SID_AND_ATTRIBUTES)) );
  222. while (Index < Token->UserAndGroupCount) {
  223. RequiredLength += SeLengthSid( Token->UserAndGroups[Index].Sid );
  224. Index += 1;
  225. } // endwhile
  226. //
  227. // Return the length required now in case not enough buffer
  228. // was provided by the caller and we have to return an error.
  229. //
  230. try {
  231. *ReturnLength = RequiredLength;
  232. } except(EXCEPTION_EXECUTE_HANDLER) {
  233. SepReleaseTokenReadLock( Token );
  234. ObDereferenceObject( Token );
  235. return GetExceptionCode();
  236. }
  237. if ( TokenInformationLength < RequiredLength ) {
  238. SepReleaseTokenReadLock( Token );
  239. ObDereferenceObject( Token );
  240. return STATUS_BUFFER_TOO_SMALL;
  241. }
  242. //
  243. // Now copy the groups.
  244. //
  245. try {
  246. LocalGroups->GroupCount = Token->UserAndGroupCount - 1;
  247. PSid = (PSID)( (ULONG_PTR)LocalGroups +
  248. (ULONG)sizeof(TOKEN_GROUPS) +
  249. ( (Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  250. (ULONG)sizeof(SID_AND_ATTRIBUTES) )
  251. );
  252. RtlCopySidAndAttributesArray(
  253. (ULONG)(Token->UserAndGroupCount - 1),
  254. &(Token->UserAndGroups[1]),
  255. RequiredLength,
  256. LocalGroups->Groups,
  257. PSid,
  258. ((PSID *)&Ignore),
  259. ((PULONG)&Ignore)
  260. );
  261. } except(EXCEPTION_EXECUTE_HANDLER) {
  262. SepReleaseTokenReadLock( Token );
  263. ObDereferenceObject( Token );
  264. return GetExceptionCode();
  265. }
  266. SepReleaseTokenReadLock( Token );
  267. ObDereferenceObject( Token );
  268. return STATUS_SUCCESS;
  269. case TokenRestrictedSids:
  270. LocalGroups = (PTOKEN_GROUPS)TokenInformation;
  271. Status = ObReferenceObjectByHandle(
  272. TokenHandle, // Handle
  273. TOKEN_QUERY, // DesiredAccess
  274. SeTokenObjectType, // ObjectType
  275. PreviousMode, // AccessMode
  276. (PVOID *)&Token, // Object
  277. NULL // GrantedAccess
  278. );
  279. if ( !NT_SUCCESS(Status) ) {
  280. return Status;
  281. }
  282. Index = 0;
  283. //
  284. // Gain exclusive access to the token.
  285. //
  286. SepAcquireTokenReadLock( Token );
  287. //
  288. // Figure out how much space is needed to return the group SIDs.
  289. // That's the size of TOKEN_GROUPS (without any array entries)
  290. // plus the size of an SID_AND_ATTRIBUTES times the number of groups.
  291. // The number of groups is Token->UserAndGroups-1 (since the count
  292. // includes the user ID). Then the lengths of each individual group
  293. // must be added.
  294. //
  295. RequiredLength = (ULONG)sizeof(TOKEN_GROUPS) +
  296. ((Token->RestrictedSidCount) *
  297. ((ULONG)sizeof(SID_AND_ATTRIBUTES)) -
  298. ANYSIZE_ARRAY * sizeof(SID_AND_ATTRIBUTES) );
  299. while (Index < Token->RestrictedSidCount) {
  300. RequiredLength += SeLengthSid( Token->RestrictedSids[Index].Sid );
  301. Index += 1;
  302. } // endwhile
  303. //
  304. // Return the length required now in case not enough buffer
  305. // was provided by the caller and we have to return an error.
  306. //
  307. try {
  308. *ReturnLength = RequiredLength;
  309. } except(EXCEPTION_EXECUTE_HANDLER) {
  310. SepReleaseTokenReadLock( Token );
  311. ObDereferenceObject( Token );
  312. return GetExceptionCode();
  313. }
  314. if ( TokenInformationLength < RequiredLength ) {
  315. SepReleaseTokenReadLock( Token );
  316. ObDereferenceObject( Token );
  317. return STATUS_BUFFER_TOO_SMALL;
  318. }
  319. //
  320. // Now copy the groups.
  321. //
  322. try {
  323. LocalGroups->GroupCount = Token->RestrictedSidCount;
  324. PSid = (PSID)( (ULONG_PTR)LocalGroups +
  325. (ULONG)sizeof(TOKEN_GROUPS) +
  326. ( (Token->RestrictedSidCount ) *
  327. (ULONG)sizeof(SID_AND_ATTRIBUTES) -
  328. ANYSIZE_ARRAY * sizeof(SID_AND_ATTRIBUTES) )
  329. );
  330. RtlCopySidAndAttributesArray(
  331. (ULONG)(Token->RestrictedSidCount),
  332. Token->RestrictedSids,
  333. RequiredLength,
  334. LocalGroups->Groups,
  335. PSid,
  336. ((PSID *)&Ignore),
  337. ((PULONG)&Ignore)
  338. );
  339. } except(EXCEPTION_EXECUTE_HANDLER) {
  340. SepReleaseTokenReadLock( Token );
  341. ObDereferenceObject( Token );
  342. return GetExceptionCode();
  343. }
  344. SepReleaseTokenReadLock( Token );
  345. ObDereferenceObject( Token );
  346. return STATUS_SUCCESS;
  347. case TokenPrivileges:
  348. LocalPrivileges = (PTOKEN_PRIVILEGES)TokenInformation;
  349. Status = ObReferenceObjectByHandle(
  350. TokenHandle, // Handle
  351. TOKEN_QUERY, // DesiredAccess
  352. SeTokenObjectType, // ObjectType
  353. PreviousMode, // AccessMode
  354. (PVOID *)&Token, // Object
  355. NULL // GrantedAccess
  356. );
  357. if ( !NT_SUCCESS(Status) ) {
  358. return Status;
  359. }
  360. //
  361. // Gain exclusive access to the token to prevent changes
  362. // from occuring to the privileges.
  363. //
  364. SepAcquireTokenReadLock( Token );
  365. //
  366. // Return the length required now in case not enough buffer
  367. // was provided by the caller and we have to return an error.
  368. //
  369. RequiredLength = (ULONG)sizeof(TOKEN_PRIVILEGES) +
  370. ((Token->PrivilegeCount - ANYSIZE_ARRAY) *
  371. ((ULONG)sizeof(LUID_AND_ATTRIBUTES)) );
  372. try {
  373. *ReturnLength = RequiredLength;
  374. } except(EXCEPTION_EXECUTE_HANDLER) {
  375. SepReleaseTokenReadLock( Token );
  376. ObDereferenceObject( Token );
  377. return GetExceptionCode();
  378. }
  379. if ( TokenInformationLength < RequiredLength ) {
  380. SepReleaseTokenReadLock( Token );
  381. ObDereferenceObject( Token );
  382. return STATUS_BUFFER_TOO_SMALL;
  383. }
  384. //
  385. // Return the token privileges.
  386. //
  387. try {
  388. LocalPrivileges->PrivilegeCount = Token->PrivilegeCount;
  389. RtlCopyLuidAndAttributesArray(
  390. Token->PrivilegeCount,
  391. Token->Privileges,
  392. LocalPrivileges->Privileges
  393. );
  394. } except(EXCEPTION_EXECUTE_HANDLER) {
  395. SepReleaseTokenReadLock( Token );
  396. ObDereferenceObject( Token );
  397. return GetExceptionCode();
  398. }
  399. SepReleaseTokenReadLock( Token );
  400. ObDereferenceObject( Token );
  401. return STATUS_SUCCESS;
  402. case TokenOwner:
  403. LocalOwner = (PTOKEN_OWNER)TokenInformation;
  404. Status = ObReferenceObjectByHandle(
  405. TokenHandle, // Handle
  406. TOKEN_QUERY, // DesiredAccess
  407. SeTokenObjectType, // ObjectType
  408. PreviousMode, // AccessMode
  409. (PVOID *)&Token, // Object
  410. NULL // GrantedAccess
  411. );
  412. if ( !NT_SUCCESS(Status) ) {
  413. return Status;
  414. }
  415. //
  416. // Gain exclusive access to the token to prevent changes
  417. // from occuring to the owner.
  418. //
  419. SepAcquireTokenReadLock( Token );
  420. //
  421. // Return the length required now in case not enough buffer
  422. // was provided by the caller and we have to return an error.
  423. //
  424. PSid = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
  425. RequiredLength = (ULONG)sizeof(TOKEN_OWNER) +
  426. SeLengthSid( PSid );
  427. try {
  428. *ReturnLength = RequiredLength;
  429. } except(EXCEPTION_EXECUTE_HANDLER) {
  430. SepReleaseTokenReadLock( Token );
  431. ObDereferenceObject( Token );
  432. return GetExceptionCode();
  433. }
  434. if ( TokenInformationLength < RequiredLength ) {
  435. SepReleaseTokenReadLock( Token );
  436. ObDereferenceObject( Token );
  437. return STATUS_BUFFER_TOO_SMALL;
  438. }
  439. //
  440. // Return the owner SID
  441. //
  442. PSid = (PSID)((ULONG_PTR)LocalOwner +
  443. (ULONG)sizeof(TOKEN_OWNER));
  444. try {
  445. LocalOwner->Owner = PSid;
  446. Status = RtlCopySid(
  447. (RequiredLength - (ULONG)sizeof(TOKEN_OWNER)),
  448. PSid,
  449. Token->UserAndGroups[Token->DefaultOwnerIndex].Sid
  450. );
  451. ASSERT( NT_SUCCESS(Status) );
  452. } except(EXCEPTION_EXECUTE_HANDLER) {
  453. SepReleaseTokenReadLock( Token );
  454. ObDereferenceObject( Token );
  455. return GetExceptionCode();
  456. }
  457. SepReleaseTokenReadLock( Token );
  458. ObDereferenceObject( Token );
  459. return STATUS_SUCCESS;
  460. case TokenPrimaryGroup:
  461. LocalPrimaryGroup = (PTOKEN_PRIMARY_GROUP)TokenInformation;
  462. Status = ObReferenceObjectByHandle(
  463. TokenHandle, // Handle
  464. TOKEN_QUERY, // DesiredAccess
  465. SeTokenObjectType, // ObjectType
  466. PreviousMode, // AccessMode
  467. (PVOID *)&Token, // Object
  468. NULL // GrantedAccess
  469. );
  470. if ( !NT_SUCCESS(Status) ) {
  471. return Status;
  472. }
  473. //
  474. // Gain exclusive access to the token to prevent changes
  475. // from occuring to the owner.
  476. //
  477. SepAcquireTokenReadLock( Token );
  478. //
  479. // Return the length required now in case not enough buffer
  480. // was provided by the caller and we have to return an error.
  481. //
  482. RequiredLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP) +
  483. SeLengthSid( Token->PrimaryGroup );
  484. try {
  485. *ReturnLength = RequiredLength;
  486. } except(EXCEPTION_EXECUTE_HANDLER) {
  487. SepReleaseTokenReadLock( Token );
  488. ObDereferenceObject( Token );
  489. return GetExceptionCode();
  490. }
  491. if ( TokenInformationLength < RequiredLength ) {
  492. SepReleaseTokenReadLock( Token );
  493. ObDereferenceObject( Token );
  494. return STATUS_BUFFER_TOO_SMALL;
  495. }
  496. //
  497. // Return the primary group SID
  498. //
  499. PSid = (PSID)((ULONG_PTR)LocalPrimaryGroup +
  500. (ULONG)sizeof(TOKEN_PRIMARY_GROUP));
  501. try {
  502. LocalPrimaryGroup->PrimaryGroup = PSid;
  503. Status = RtlCopySid( (RequiredLength - (ULONG)sizeof(TOKEN_PRIMARY_GROUP)),
  504. PSid,
  505. Token->PrimaryGroup
  506. );
  507. ASSERT( NT_SUCCESS(Status) );
  508. } except(EXCEPTION_EXECUTE_HANDLER) {
  509. SepReleaseTokenReadLock( Token );
  510. ObDereferenceObject( Token );
  511. return GetExceptionCode();
  512. }
  513. SepReleaseTokenReadLock( Token );
  514. ObDereferenceObject( Token );
  515. return STATUS_SUCCESS;
  516. case TokenDefaultDacl:
  517. LocalDefaultDacl = (PTOKEN_DEFAULT_DACL)TokenInformation;
  518. Status = ObReferenceObjectByHandle(
  519. TokenHandle, // Handle
  520. TOKEN_QUERY, // DesiredAccess
  521. SeTokenObjectType, // ObjectType
  522. PreviousMode, // AccessMode
  523. (PVOID *)&Token, // Object
  524. NULL // GrantedAccess
  525. );
  526. if ( !NT_SUCCESS(Status) ) {
  527. return Status;
  528. }
  529. RequiredLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  530. //
  531. // Gain exclusive access to the token to prevent changes
  532. // from occuring to the owner.
  533. //
  534. SepAcquireTokenReadLock( Token );
  535. //
  536. // Return the length required now in case not enough buffer
  537. // was provided by the caller and we have to return an error.
  538. //
  539. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  540. RequiredLength += Token->DefaultDacl->AclSize;
  541. }
  542. try {
  543. *ReturnLength = RequiredLength;
  544. } except(EXCEPTION_EXECUTE_HANDLER) {
  545. SepReleaseTokenReadLock( Token );
  546. ObDereferenceObject( Token );
  547. return GetExceptionCode();
  548. }
  549. if ( TokenInformationLength < RequiredLength ) {
  550. SepReleaseTokenReadLock( Token );
  551. ObDereferenceObject( Token );
  552. return STATUS_BUFFER_TOO_SMALL;
  553. }
  554. //
  555. // Return the default Dacl
  556. //
  557. PAcl = (PACL)((ULONG_PTR)LocalDefaultDacl +
  558. (ULONG)sizeof(TOKEN_DEFAULT_DACL));
  559. try {
  560. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  561. LocalDefaultDacl->DefaultDacl = PAcl;
  562. RtlCopyMemory( (PVOID)PAcl,
  563. (PVOID)Token->DefaultDacl,
  564. Token->DefaultDacl->AclSize
  565. );
  566. } else {
  567. LocalDefaultDacl->DefaultDacl = NULL;
  568. }
  569. } except(EXCEPTION_EXECUTE_HANDLER) {
  570. SepReleaseTokenReadLock( Token );
  571. ObDereferenceObject( Token );
  572. return GetExceptionCode();
  573. }
  574. SepReleaseTokenReadLock( Token );
  575. ObDereferenceObject( Token );
  576. return STATUS_SUCCESS;
  577. case TokenSource:
  578. LocalSource = (PTOKEN_SOURCE)TokenInformation;
  579. Status = ObReferenceObjectByHandle(
  580. TokenHandle, // Handle
  581. TOKEN_QUERY_SOURCE, // DesiredAccess
  582. SeTokenObjectType, // ObjectType
  583. PreviousMode, // AccessMode
  584. (PVOID *)&Token, // Object
  585. NULL // GrantedAccess
  586. );
  587. if ( !NT_SUCCESS(Status) ) {
  588. return Status;
  589. }
  590. //
  591. // The type of a token can not be changed, so
  592. // exclusive access to the token is not necessary.
  593. //
  594. //
  595. // Return the length required now in case not enough buffer
  596. // was provided by the caller and we have to return an error.
  597. //
  598. RequiredLength = (ULONG) sizeof(TOKEN_SOURCE);
  599. try {
  600. *ReturnLength = RequiredLength;
  601. } except(EXCEPTION_EXECUTE_HANDLER) {
  602. ObDereferenceObject( Token );
  603. return GetExceptionCode();
  604. }
  605. if ( TokenInformationLength < RequiredLength ) {
  606. ObDereferenceObject( Token );
  607. return STATUS_BUFFER_TOO_SMALL;
  608. }
  609. //
  610. // Return the token source
  611. //
  612. try {
  613. (*LocalSource) = Token->TokenSource;
  614. } except(EXCEPTION_EXECUTE_HANDLER) {
  615. ObDereferenceObject( Token );
  616. return GetExceptionCode();
  617. }
  618. ObDereferenceObject( Token );
  619. return STATUS_SUCCESS;
  620. case TokenType:
  621. LocalType = (PTOKEN_TYPE)TokenInformation;
  622. Status = ObReferenceObjectByHandle(
  623. TokenHandle, // Handle
  624. TOKEN_QUERY, // DesiredAccess
  625. SeTokenObjectType, // ObjectType
  626. PreviousMode, // AccessMode
  627. (PVOID *)&Token, // Object
  628. NULL // GrantedAccess
  629. );
  630. if ( !NT_SUCCESS(Status) ) {
  631. return Status;
  632. }
  633. //
  634. // The type of a token can not be changed, so
  635. // exclusive access to the token is not necessary.
  636. //
  637. //
  638. // Return the length required now in case not enough buffer
  639. // was provided by the caller and we have to return an error.
  640. //
  641. RequiredLength = (ULONG) sizeof(TOKEN_TYPE);
  642. try {
  643. *ReturnLength = RequiredLength;
  644. } except(EXCEPTION_EXECUTE_HANDLER) {
  645. ObDereferenceObject( Token );
  646. return GetExceptionCode();
  647. }
  648. if ( TokenInformationLength < RequiredLength ) {
  649. ObDereferenceObject( Token );
  650. return STATUS_BUFFER_TOO_SMALL;
  651. }
  652. //
  653. // Return the token type
  654. //
  655. try {
  656. (*LocalType) = Token->TokenType;
  657. } except(EXCEPTION_EXECUTE_HANDLER) {
  658. ObDereferenceObject( Token );
  659. return GetExceptionCode();
  660. }
  661. ObDereferenceObject( Token );
  662. return STATUS_SUCCESS;
  663. case TokenImpersonationLevel:
  664. LocalImpersonationLevel = (PSECURITY_IMPERSONATION_LEVEL)TokenInformation;
  665. Status = ObReferenceObjectByHandle(
  666. TokenHandle, // Handle
  667. TOKEN_QUERY, // DesiredAccess
  668. SeTokenObjectType, // ObjectType
  669. PreviousMode, // AccessMode
  670. (PVOID *)&Token, // Object
  671. NULL // GrantedAccess
  672. );
  673. if ( !NT_SUCCESS(Status) ) {
  674. return Status;
  675. }
  676. //
  677. // The impersonation level of a token can not be changed, so
  678. // exclusive access to the token is not necessary.
  679. //
  680. //
  681. // Make sure the token is an appropriate type to be retrieving
  682. // the impersonation level from.
  683. //
  684. if (Token->TokenType != TokenImpersonation) {
  685. ObDereferenceObject( Token );
  686. return STATUS_INVALID_INFO_CLASS;
  687. }
  688. //
  689. // Return the length required now in case not enough buffer
  690. // was provided by the caller and we have to return an error.
  691. //
  692. RequiredLength = (ULONG) sizeof(SECURITY_IMPERSONATION_LEVEL);
  693. try {
  694. *ReturnLength = RequiredLength;
  695. } except(EXCEPTION_EXECUTE_HANDLER) {
  696. ObDereferenceObject( Token );
  697. return GetExceptionCode();
  698. }
  699. if ( TokenInformationLength < RequiredLength ) {
  700. ObDereferenceObject( Token );
  701. return STATUS_BUFFER_TOO_SMALL;
  702. }
  703. //
  704. // Return the impersonation level
  705. //
  706. try {
  707. (*LocalImpersonationLevel) = Token->ImpersonationLevel;
  708. } except(EXCEPTION_EXECUTE_HANDLER) {
  709. ObDereferenceObject( Token );
  710. return GetExceptionCode();
  711. }
  712. ObDereferenceObject( Token );
  713. return STATUS_SUCCESS;
  714. case TokenStatistics:
  715. LocalStatistics = (PTOKEN_STATISTICS)TokenInformation;
  716. Status = ObReferenceObjectByHandle(
  717. TokenHandle, // Handle
  718. TOKEN_QUERY, // DesiredAccess
  719. SeTokenObjectType, // ObjectType
  720. PreviousMode, // AccessMode
  721. (PVOID *)&Token, // Object
  722. NULL // GrantedAccess
  723. );
  724. if ( !NT_SUCCESS(Status) ) {
  725. return Status;
  726. }
  727. RequiredLength = (ULONG)sizeof( TOKEN_STATISTICS );
  728. //
  729. // Gain exclusive access to the token.
  730. //
  731. SepAcquireTokenReadLock( Token );
  732. //
  733. // Return the length required now in case not enough buffer
  734. // was provided by the caller and we have to return an error.
  735. //
  736. try {
  737. *ReturnLength = RequiredLength;
  738. } except(EXCEPTION_EXECUTE_HANDLER) {
  739. SepReleaseTokenReadLock( Token );
  740. ObDereferenceObject( Token );
  741. return GetExceptionCode();
  742. }
  743. if ( TokenInformationLength < RequiredLength ) {
  744. SepReleaseTokenReadLock( Token );
  745. ObDereferenceObject( Token );
  746. return STATUS_BUFFER_TOO_SMALL;
  747. }
  748. //
  749. // Return the statistics
  750. //
  751. try {
  752. ULONG Size;
  753. LocalStatistics->TokenId = Token->TokenId;
  754. LocalStatistics->AuthenticationId = Token->AuthenticationId;
  755. LocalStatistics->ExpirationTime = Token->ExpirationTime;
  756. LocalStatistics->TokenType = Token->TokenType;
  757. LocalStatistics->ImpersonationLevel = Token->ImpersonationLevel;
  758. LocalStatistics->DynamicCharged = Token->DynamicCharged;
  759. Size = Token->DynamicCharged - SeLengthSid( Token->PrimaryGroup );;
  760. if (Token->DefaultDacl) {
  761. Size -= Token->DefaultDacl->AclSize;
  762. }
  763. LocalStatistics->DynamicAvailable = Size;
  764. LocalStatistics->GroupCount = Token->UserAndGroupCount-1;
  765. LocalStatistics->PrivilegeCount = Token->PrivilegeCount;
  766. LocalStatistics->ModifiedId = Token->ModifiedId;
  767. } except(EXCEPTION_EXECUTE_HANDLER) {
  768. SepReleaseTokenReadLock( Token );
  769. ObDereferenceObject( Token );
  770. return GetExceptionCode();
  771. }
  772. SepReleaseTokenReadLock( Token );
  773. ObDereferenceObject( Token );
  774. return STATUS_SUCCESS;
  775. case TokenSessionId:
  776. if ( TokenInformationLength != sizeof(ULONG) )
  777. return( STATUS_INFO_LENGTH_MISMATCH );
  778. Status = ObReferenceObjectByHandle(
  779. TokenHandle, // Handle
  780. TOKEN_QUERY, // DesiredAccess
  781. SeTokenObjectType, // ObjectType
  782. PreviousMode, // AccessMode
  783. (PVOID *)&Token, // Object
  784. NULL // GrantedAccess
  785. );
  786. if ( !NT_SUCCESS(Status) ) {
  787. return Status;
  788. }
  789. //
  790. // Get SessionId for the token
  791. //
  792. SeQuerySessionIdToken( (PACCESS_TOKEN)Token,
  793. &SessionId);
  794. try {
  795. *(PULONG)TokenInformation = SessionId;
  796. *ReturnLength = sizeof(ULONG);
  797. } except(EXCEPTION_EXECUTE_HANDLER) {
  798. ObDereferenceObject( Token );
  799. return GetExceptionCode();
  800. }
  801. ObDereferenceObject( Token );
  802. return( STATUS_SUCCESS );
  803. case TokenGroupsAndPrivileges:
  804. LocalGroupsAndPrivileges = (PTOKEN_GROUPS_AND_PRIVILEGES)TokenInformation;
  805. Status = ObReferenceObjectByHandle(
  806. TokenHandle, // Handle
  807. TOKEN_QUERY, // DesiredAccess
  808. SeTokenObjectType, // ObjectType
  809. PreviousMode, // AccessMode
  810. (PVOID *)&Token, // Object
  811. NULL // GrantedAccess
  812. );
  813. if ( !NT_SUCCESS(Status) ) {
  814. return Status;
  815. }
  816. //
  817. // Gain exclusive access to the token.
  818. //
  819. SepAcquireTokenReadLock( Token );
  820. //
  821. // Figure out how much space is needed to return the group SIDs.
  822. // The data arrangement is as follows:
  823. // GroupsAndPrivileges struct
  824. // User and Groups
  825. // Restricted sids
  826. // Privileges
  827. //
  828. PrivilegesLength = Token->PrivilegeCount *
  829. ((ULONG)sizeof(LUID_AND_ATTRIBUTES));
  830. GroupsLength = Token->UserAndGroupCount *
  831. ((ULONG)sizeof(SID_AND_ATTRIBUTES));
  832. RestrictedSidsLength = Token->RestrictedSidCount *
  833. ((ULONG)sizeof(SID_AND_ATTRIBUTES));
  834. Index = 0;
  835. while (Index < Token->UserAndGroupCount) {
  836. GroupsLength += SeLengthSid( Token->UserAndGroups[Index].Sid );
  837. Index += 1;
  838. } // endwhile
  839. Index = 0;
  840. while (Index < Token->RestrictedSidCount) {
  841. RestrictedSidsLength += SeLengthSid( Token->RestrictedSids[Index].Sid );
  842. Index += 1;
  843. } // endwhile
  844. RequiredLength = (ULONG)sizeof(TOKEN_GROUPS_AND_PRIVILEGES) +
  845. PrivilegesLength + RestrictedSidsLength + GroupsLength;
  846. //
  847. // Return the length required now in case not enough buffer
  848. // was provided by the caller and we have to return an error.
  849. //
  850. try {
  851. *ReturnLength = RequiredLength;
  852. } except(EXCEPTION_EXECUTE_HANDLER) {
  853. SepReleaseTokenReadLock( Token );
  854. ObDereferenceObject( Token );
  855. return GetExceptionCode();
  856. }
  857. if ( TokenInformationLength < RequiredLength ) {
  858. SepReleaseTokenReadLock( Token );
  859. ObDereferenceObject( Token );
  860. return STATUS_BUFFER_TOO_SMALL;
  861. }
  862. //
  863. // Now copy the groups, followed by restricted sids, followed by
  864. // privileges.
  865. //
  866. try {
  867. LocalGroupsAndPrivileges->AuthenticationId = Token->AuthenticationId;
  868. LocalGroupsAndPrivileges->SidLength = GroupsLength;
  869. LocalGroupsAndPrivileges->SidCount = Token->UserAndGroupCount;
  870. LocalGroupsAndPrivileges->Sids = (PSID_AND_ATTRIBUTES) ((ULONG_PTR)LocalGroupsAndPrivileges +
  871. (ULONG)sizeof(TOKEN_GROUPS_AND_PRIVILEGES));
  872. LocalGroupsAndPrivileges->RestrictedSidLength = RestrictedSidsLength;
  873. LocalGroupsAndPrivileges->RestrictedSidCount = Token->RestrictedSidCount;
  874. //
  875. // To distinguish between a restricted token with zero sids and
  876. // a non-restrcited token.
  877. //
  878. if (SeTokenIsRestricted((PACCESS_TOKEN) Token))
  879. {
  880. LocalGroupsAndPrivileges->RestrictedSids = (PSID_AND_ATTRIBUTES) ((ULONG_PTR) LocalGroupsAndPrivileges->Sids +
  881. GroupsLength);
  882. }
  883. else
  884. {
  885. LocalGroupsAndPrivileges->RestrictedSids = NULL;
  886. }
  887. LocalGroupsAndPrivileges->PrivilegeLength = PrivilegesLength;
  888. LocalGroupsAndPrivileges->PrivilegeCount = Token->PrivilegeCount;
  889. LocalGroupsAndPrivileges->Privileges = (PLUID_AND_ATTRIBUTES) ((ULONG_PTR) LocalGroupsAndPrivileges->Sids + GroupsLength +
  890. RestrictedSidsLength);
  891. PSid = (PSID)( (ULONG_PTR)LocalGroupsAndPrivileges->Sids +
  892. (Token->UserAndGroupCount *
  893. (ULONG)sizeof(SID_AND_ATTRIBUTES))
  894. );
  895. RtlCopySidAndAttributesArray(
  896. (ULONG)Token->UserAndGroupCount,
  897. Token->UserAndGroups,
  898. GroupsLength - (Token->UserAndGroupCount * ((ULONG)sizeof(SID_AND_ATTRIBUTES))),
  899. LocalGroupsAndPrivileges->Sids,
  900. PSid,
  901. ((PSID *)&Ignore),
  902. ((PULONG)&Ignore)
  903. );
  904. PSid = (PSID)((ULONG_PTR)LocalGroupsAndPrivileges->RestrictedSids +
  905. ((Token->RestrictedSidCount ) *
  906. (ULONG)sizeof(SID_AND_ATTRIBUTES))
  907. );
  908. if (LocalGroupsAndPrivileges->RestrictedSidCount > 0)
  909. {
  910. RtlCopySidAndAttributesArray(
  911. (ULONG)(Token->RestrictedSidCount),
  912. Token->RestrictedSids,
  913. RestrictedSidsLength - (Token->RestrictedSidCount * ((ULONG)sizeof(SID_AND_ATTRIBUTES))),
  914. LocalGroupsAndPrivileges->RestrictedSids,
  915. PSid,
  916. ((PSID *)&Ignore),
  917. ((PULONG)&Ignore)
  918. );
  919. }
  920. RtlCopyLuidAndAttributesArray(
  921. Token->PrivilegeCount,
  922. Token->Privileges,
  923. LocalGroupsAndPrivileges->Privileges
  924. );
  925. } except(EXCEPTION_EXECUTE_HANDLER) {
  926. SepReleaseTokenReadLock( Token );
  927. ObDereferenceObject( Token );
  928. return GetExceptionCode();
  929. }
  930. SepReleaseTokenReadLock( Token );
  931. ObDereferenceObject( Token );
  932. return STATUS_SUCCESS;
  933. case TokenSandBoxInert:
  934. try {
  935. *ReturnLength = sizeof(ULONG);
  936. } except(EXCEPTION_EXECUTE_HANDLER) {
  937. return GetExceptionCode();
  938. }
  939. if ( TokenInformationLength < sizeof(ULONG) ) {
  940. return( STATUS_INFO_LENGTH_MISMATCH );
  941. }
  942. Status = ObReferenceObjectByHandle(
  943. TokenHandle, // Handle
  944. TOKEN_QUERY, // DesiredAccess
  945. SeTokenObjectType, // ObjectType
  946. PreviousMode, // AccessMode
  947. (PVOID *)&Token, // Object
  948. NULL // GrantedAccess
  949. );
  950. if ( !NT_SUCCESS(Status) ) {
  951. return Status;
  952. }
  953. try {
  954. //
  955. // If the flag is present in the token then return TRUE.
  956. // Else return FALSE.
  957. //
  958. *(PULONG)TokenInformation = (Token->TokenFlags & TOKEN_SANDBOX_INERT)
  959. ? TRUE : FALSE;
  960. } except(EXCEPTION_EXECUTE_HANDLER) {
  961. ObDereferenceObject( Token );
  962. return GetExceptionCode();
  963. }
  964. ObDereferenceObject( Token );
  965. return( STATUS_SUCCESS );
  966. default:
  967. return STATUS_INVALID_INFO_CLASS;
  968. }
  969. }
  970. NTSTATUS
  971. SeQueryAuthenticationIdToken(
  972. IN PACCESS_TOKEN Token,
  973. OUT PLUID AuthenticationId
  974. )
  975. /*++
  976. Routine Description:
  977. Retrieve authentication ID out of the token.
  978. Arguments:
  979. Token - Referenced pointer to a token.
  980. AutenticationId - Receives the token's authentication ID.
  981. Return Value:
  982. STATUS_SUCCESS - Indicates the operation was successful.
  983. This is the only expected status.
  984. --*/
  985. {
  986. PAGED_CODE();
  987. SepAcquireTokenReadLock( ((PTOKEN)Token) );
  988. (*AuthenticationId) = ((PTOKEN)Token)->AuthenticationId;
  989. SepReleaseTokenReadLock( ((PTOKEN)Token) );
  990. return(STATUS_SUCCESS);
  991. }
  992. NTSTATUS
  993. SeQueryInformationToken (
  994. IN PACCESS_TOKEN AccessToken,
  995. IN TOKEN_INFORMATION_CLASS TokenInformationClass,
  996. OUT PVOID *TokenInformation
  997. )
  998. /*++
  999. Routine Description:
  1000. Retrieve information about a specified token.
  1001. Arguments:
  1002. TokenHandle - Provides a handle to the token to operate on.
  1003. TokenInformationClass - The token information class about which
  1004. to retrieve information.
  1005. TokenInformation - Receives a pointer to the requested information.
  1006. The actual structures returned are dependent upon the information
  1007. class requested, as defined in the TokenInformationClass parameter
  1008. description.
  1009. TokenInformation Format By Information Class:
  1010. TokenUser => TOKEN_USER data structure. TOKEN_QUERY
  1011. access is needed to retrieve this information about a
  1012. token.
  1013. TokenGroups => TOKEN_GROUPS data structure. TOKEN_QUERY
  1014. access is needed to retrieve this information about a
  1015. token.
  1016. TokenPrivileges => TOKEN_PRIVILEGES data structure.
  1017. TOKEN_QUERY access is needed to retrieve this information
  1018. about a token.
  1019. TokenOwner => TOKEN_OWNER data structure. TOKEN_QUERY
  1020. access is needed to retrieve this information about a
  1021. token.
  1022. TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure.
  1023. TOKEN_QUERY access is needed to retrieve this information
  1024. about a token.
  1025. TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure.
  1026. TOKEN_QUERY access is needed to retrieve this information
  1027. about a token.
  1028. TokenSource => TOKEN_SOURCE data structure.
  1029. TOKEN_QUERY_SOURCE access is needed to retrieve this
  1030. information about a token.
  1031. TokenType => TOKEN_TYPE data structure.
  1032. TOKEN_QUERY access is needed to retrieve this information
  1033. about a token.
  1034. TokenStatistics => TOKEN_STATISTICS data structure.
  1035. TOKEN_QUERY access is needed to retrieve this
  1036. information about a token.
  1037. Return Value:
  1038. STATUS_SUCCESS - Indicates the operation was successful.
  1039. --*/
  1040. {
  1041. NTSTATUS Status;
  1042. ULONG RequiredLength;
  1043. ULONG Index;
  1044. PSID PSid;
  1045. PACL PAcl;
  1046. PVOID Ignore;
  1047. PTOKEN Token = (PTOKEN)AccessToken;
  1048. PAGED_CODE();
  1049. //
  1050. // Case on information class.
  1051. //
  1052. switch ( TokenInformationClass ) {
  1053. case TokenUser:
  1054. {
  1055. PTOKEN_USER LocalUser;
  1056. //
  1057. // Gain exclusive access to the token.
  1058. //
  1059. SepAcquireTokenReadLock( Token );
  1060. //
  1061. // Return the length required now in case not enough buffer
  1062. // was provided by the caller and we have to return an error.
  1063. //
  1064. RequiredLength = SeLengthSid( Token->UserAndGroups[0].Sid) +
  1065. (ULONG)sizeof( TOKEN_USER );
  1066. LocalUser = ExAllocatePool( PagedPool, RequiredLength );
  1067. if (LocalUser == NULL) {
  1068. SepReleaseTokenReadLock( Token );
  1069. return( STATUS_INSUFFICIENT_RESOURCES );
  1070. }
  1071. //
  1072. // Return the user SID
  1073. //
  1074. // Put SID immediately following TOKEN_USER data structure
  1075. //
  1076. PSid = (PSID)( (ULONG_PTR)LocalUser + (ULONG)sizeof(TOKEN_USER) );
  1077. RtlCopySidAndAttributesArray(
  1078. 1,
  1079. Token->UserAndGroups,
  1080. RequiredLength,
  1081. &(LocalUser->User),
  1082. PSid,
  1083. ((PSID *)&Ignore),
  1084. ((PULONG)&Ignore)
  1085. );
  1086. SepReleaseTokenReadLock( Token );
  1087. *TokenInformation = LocalUser;
  1088. return STATUS_SUCCESS;
  1089. }
  1090. case TokenGroups:
  1091. {
  1092. PTOKEN_GROUPS LocalGroups;
  1093. //
  1094. // Gain exclusive access to the token.
  1095. //
  1096. SepAcquireTokenReadLock( Token );
  1097. //
  1098. // Figure out how much space is needed to return the group SIDs.
  1099. // That's the size of TOKEN_GROUPS (without any array entries)
  1100. // plus the size of an SID_AND_ATTRIBUTES times the number of groups.
  1101. // The number of groups is Token->UserAndGroups-1 (since the count
  1102. // includes the user ID). Then the lengths of each individual group
  1103. // must be added.
  1104. //
  1105. RequiredLength = (ULONG)sizeof(TOKEN_GROUPS) +
  1106. ((Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  1107. ((ULONG)sizeof(SID_AND_ATTRIBUTES)) );
  1108. Index = 1;
  1109. while (Index < Token->UserAndGroupCount) {
  1110. RequiredLength += SeLengthSid( Token->UserAndGroups[Index].Sid );
  1111. Index += 1;
  1112. } // endwhile
  1113. LocalGroups = ExAllocatePool( PagedPool, RequiredLength );
  1114. if (LocalGroups == NULL) {
  1115. SepReleaseTokenReadLock( Token );
  1116. return( STATUS_INSUFFICIENT_RESOURCES );
  1117. }
  1118. //
  1119. // Now copy the groups.
  1120. //
  1121. LocalGroups->GroupCount = Token->UserAndGroupCount - 1;
  1122. PSid = (PSID)( (ULONG_PTR)LocalGroups +
  1123. (ULONG)sizeof(TOKEN_GROUPS) +
  1124. ( (Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  1125. (ULONG)sizeof(SID_AND_ATTRIBUTES) )
  1126. );
  1127. RtlCopySidAndAttributesArray(
  1128. (ULONG)(Token->UserAndGroupCount - 1),
  1129. &(Token->UserAndGroups[1]),
  1130. RequiredLength,
  1131. LocalGroups->Groups,
  1132. PSid,
  1133. ((PSID *)&Ignore),
  1134. ((PULONG)&Ignore)
  1135. );
  1136. SepReleaseTokenReadLock( Token );
  1137. *TokenInformation = LocalGroups;
  1138. return STATUS_SUCCESS;
  1139. }
  1140. case TokenPrivileges:
  1141. {
  1142. PTOKEN_PRIVILEGES LocalPrivileges;
  1143. //
  1144. // Gain exclusive access to the token to prevent changes
  1145. // from occuring to the privileges.
  1146. //
  1147. SepAcquireTokenReadLock( Token );
  1148. //
  1149. // Return the length required now in case not enough buffer
  1150. // was provided by the caller and we have to return an error.
  1151. //
  1152. RequiredLength = (ULONG)sizeof(TOKEN_PRIVILEGES) +
  1153. ((Token->PrivilegeCount - ANYSIZE_ARRAY) *
  1154. ((ULONG)sizeof(LUID_AND_ATTRIBUTES)) );
  1155. LocalPrivileges = ExAllocatePool( PagedPool, RequiredLength );
  1156. if (LocalPrivileges == NULL) {
  1157. SepReleaseTokenReadLock( Token );
  1158. return( STATUS_INSUFFICIENT_RESOURCES );
  1159. }
  1160. //
  1161. // Return the token privileges.
  1162. //
  1163. LocalPrivileges->PrivilegeCount = Token->PrivilegeCount;
  1164. RtlCopyLuidAndAttributesArray(
  1165. Token->PrivilegeCount,
  1166. Token->Privileges,
  1167. LocalPrivileges->Privileges
  1168. );
  1169. SepReleaseTokenReadLock( Token );
  1170. *TokenInformation = LocalPrivileges;
  1171. return STATUS_SUCCESS;
  1172. }
  1173. case TokenOwner:
  1174. {
  1175. PTOKEN_OWNER LocalOwner;
  1176. //
  1177. // Gain exclusive access to the token to prevent changes
  1178. // from occuring to the owner.
  1179. //
  1180. SepAcquireTokenReadLock( Token );
  1181. //
  1182. // Return the length required now in case not enough buffer
  1183. // was provided by the caller and we have to return an error.
  1184. //
  1185. PSid = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
  1186. RequiredLength = (ULONG)sizeof(TOKEN_OWNER) +
  1187. SeLengthSid( PSid );
  1188. LocalOwner = ExAllocatePool( PagedPool, RequiredLength );
  1189. if (LocalOwner == NULL) {
  1190. SepReleaseTokenReadLock( Token );
  1191. return( STATUS_INSUFFICIENT_RESOURCES );
  1192. }
  1193. //
  1194. // Return the owner SID
  1195. //
  1196. PSid = (PSID)((ULONG_PTR)LocalOwner +
  1197. (ULONG)sizeof(TOKEN_OWNER));
  1198. LocalOwner->Owner = PSid;
  1199. Status = RtlCopySid(
  1200. (RequiredLength - (ULONG)sizeof(TOKEN_OWNER)),
  1201. PSid,
  1202. Token->UserAndGroups[Token->DefaultOwnerIndex].Sid
  1203. );
  1204. ASSERT( NT_SUCCESS(Status) );
  1205. SepReleaseTokenReadLock( Token );
  1206. *TokenInformation = LocalOwner;
  1207. return STATUS_SUCCESS;
  1208. }
  1209. case TokenPrimaryGroup:
  1210. {
  1211. PTOKEN_PRIMARY_GROUP LocalPrimaryGroup;
  1212. //
  1213. // Gain exclusive access to the token to prevent changes
  1214. // from occuring to the owner.
  1215. //
  1216. SepAcquireTokenReadLock( Token );
  1217. //
  1218. // Return the length required now in case not enough buffer
  1219. // was provided by the caller and we have to return an error.
  1220. //
  1221. RequiredLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP) +
  1222. SeLengthSid( Token->PrimaryGroup );
  1223. LocalPrimaryGroup = ExAllocatePool( PagedPool, RequiredLength );
  1224. if (LocalPrimaryGroup == NULL) {
  1225. SepReleaseTokenReadLock( Token );
  1226. return( STATUS_INSUFFICIENT_RESOURCES );
  1227. }
  1228. //
  1229. // Return the primary group SID
  1230. //
  1231. PSid = (PSID)((ULONG_PTR)LocalPrimaryGroup +
  1232. (ULONG)sizeof(TOKEN_PRIMARY_GROUP));
  1233. LocalPrimaryGroup->PrimaryGroup = PSid;
  1234. Status = RtlCopySid( (RequiredLength - (ULONG)sizeof(TOKEN_PRIMARY_GROUP)),
  1235. PSid,
  1236. Token->PrimaryGroup
  1237. );
  1238. ASSERT( NT_SUCCESS(Status) );
  1239. SepReleaseTokenReadLock( Token );
  1240. *TokenInformation = LocalPrimaryGroup;
  1241. return STATUS_SUCCESS;
  1242. }
  1243. case TokenDefaultDacl:
  1244. {
  1245. PTOKEN_DEFAULT_DACL LocalDefaultDacl;
  1246. RequiredLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  1247. //
  1248. // Gain exclusive access to the token to prevent changes
  1249. // from occuring to the owner.
  1250. //
  1251. SepAcquireTokenReadLock( Token );
  1252. //
  1253. // Return the length required now in case not enough buffer
  1254. // was provided by the caller and we have to return an error.
  1255. //
  1256. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  1257. RequiredLength += Token->DefaultDacl->AclSize;
  1258. }
  1259. LocalDefaultDacl = ExAllocatePool( PagedPool, RequiredLength );
  1260. if (LocalDefaultDacl == NULL) {
  1261. SepReleaseTokenReadLock( Token );
  1262. return( STATUS_INSUFFICIENT_RESOURCES );
  1263. }
  1264. //
  1265. // Return the default Dacl
  1266. //
  1267. PAcl = (PACL)((ULONG_PTR)LocalDefaultDacl +
  1268. (ULONG)sizeof(TOKEN_DEFAULT_DACL));
  1269. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  1270. LocalDefaultDacl->DefaultDacl = PAcl;
  1271. RtlCopyMemory( (PVOID)PAcl,
  1272. (PVOID)Token->DefaultDacl,
  1273. Token->DefaultDacl->AclSize
  1274. );
  1275. } else {
  1276. LocalDefaultDacl->DefaultDacl = NULL;
  1277. }
  1278. SepReleaseTokenReadLock( Token );
  1279. *TokenInformation = LocalDefaultDacl;
  1280. return STATUS_SUCCESS;
  1281. }
  1282. case TokenSource:
  1283. {
  1284. PTOKEN_SOURCE LocalSource;
  1285. //
  1286. // The type of a token can not be changed, so
  1287. // exclusive access to the token is not necessary.
  1288. //
  1289. //
  1290. // Return the length required now in case not enough buffer
  1291. // was provided by the caller and we have to return an error.
  1292. //
  1293. RequiredLength = (ULONG) sizeof(TOKEN_SOURCE);
  1294. LocalSource = ExAllocatePool( PagedPool, RequiredLength );
  1295. if (LocalSource == NULL) {
  1296. return( STATUS_INSUFFICIENT_RESOURCES );
  1297. }
  1298. //
  1299. // Return the token source
  1300. //
  1301. (*LocalSource) = Token->TokenSource;
  1302. *TokenInformation = LocalSource;
  1303. return STATUS_SUCCESS;
  1304. }
  1305. case TokenType:
  1306. {
  1307. PTOKEN_TYPE LocalType;
  1308. //
  1309. // The type of a token can not be changed, so
  1310. // exclusive access to the token is not necessary.
  1311. //
  1312. //
  1313. // Return the length required now in case not enough buffer
  1314. // was provided by the caller and we have to return an error.
  1315. //
  1316. RequiredLength = (ULONG) sizeof(TOKEN_TYPE);
  1317. LocalType = ExAllocatePool( PagedPool, RequiredLength );
  1318. if (LocalType == NULL) {
  1319. return( STATUS_INSUFFICIENT_RESOURCES );
  1320. }
  1321. //
  1322. // Return the token type
  1323. //
  1324. (*LocalType) = Token->TokenType;
  1325. *TokenInformation = LocalType;
  1326. return STATUS_SUCCESS;
  1327. }
  1328. case TokenImpersonationLevel:
  1329. {
  1330. PSECURITY_IMPERSONATION_LEVEL LocalImpersonationLevel;
  1331. //
  1332. // The impersonation level of a token can not be changed, so
  1333. // exclusive access to the token is not necessary.
  1334. //
  1335. //
  1336. // Make sure the token is an appropriate type to be retrieving
  1337. // the impersonation level from.
  1338. //
  1339. if (Token->TokenType != TokenImpersonation) {
  1340. return STATUS_INVALID_INFO_CLASS;
  1341. }
  1342. //
  1343. // Return the length required now in case not enough buffer
  1344. // was provided by the caller and we have to return an error.
  1345. //
  1346. RequiredLength = (ULONG) sizeof(SECURITY_IMPERSONATION_LEVEL);
  1347. LocalImpersonationLevel = ExAllocatePool( PagedPool, RequiredLength );
  1348. if (LocalImpersonationLevel == NULL) {
  1349. return( STATUS_INSUFFICIENT_RESOURCES );
  1350. }
  1351. //
  1352. // Return the impersonation level
  1353. //
  1354. (*LocalImpersonationLevel) = Token->ImpersonationLevel;
  1355. *TokenInformation = LocalImpersonationLevel;
  1356. return STATUS_SUCCESS;
  1357. }
  1358. case TokenStatistics:
  1359. {
  1360. PTOKEN_STATISTICS LocalStatistics;
  1361. ULONG Size;
  1362. //
  1363. // Return the length required now in case not enough buffer
  1364. // was provided by the caller and we have to return an error.
  1365. //
  1366. RequiredLength = (ULONG)sizeof( TOKEN_STATISTICS );
  1367. LocalStatistics = ExAllocatePool( PagedPool, RequiredLength );
  1368. if (LocalStatistics == NULL) {
  1369. return( STATUS_INSUFFICIENT_RESOURCES );
  1370. }
  1371. //
  1372. // Gain exclusive access to the token.
  1373. //
  1374. SepAcquireTokenReadLock( Token );
  1375. //
  1376. // Return the statistics
  1377. //
  1378. LocalStatistics->TokenId = Token->TokenId;
  1379. LocalStatistics->AuthenticationId = Token->AuthenticationId;
  1380. LocalStatistics->ExpirationTime = Token->ExpirationTime;
  1381. LocalStatistics->TokenType = Token->TokenType;
  1382. LocalStatistics->ImpersonationLevel = Token->ImpersonationLevel;
  1383. LocalStatistics->DynamicCharged = Token->DynamicCharged;
  1384. Size = Token->DynamicCharged - SeLengthSid( Token->PrimaryGroup );
  1385. if (Token->DefaultDacl) {
  1386. Size -= Token->DefaultDacl->AclSize;
  1387. }
  1388. LocalStatistics->DynamicAvailable = Size;
  1389. LocalStatistics->DynamicAvailable = Token->DynamicAvailable;
  1390. LocalStatistics->GroupCount = Token->UserAndGroupCount-1;
  1391. LocalStatistics->PrivilegeCount = Token->PrivilegeCount;
  1392. LocalStatistics->ModifiedId = Token->ModifiedId;
  1393. SepReleaseTokenReadLock( Token );
  1394. *TokenInformation = LocalStatistics;
  1395. return STATUS_SUCCESS;
  1396. }
  1397. case TokenSessionId:
  1398. /*
  1399. * Get SessionId for the token
  1400. */
  1401. SeQuerySessionIdToken( (PACCESS_TOKEN)Token,
  1402. (PULONG)TokenInformation );
  1403. return( STATUS_SUCCESS );
  1404. default:
  1405. return STATUS_INVALID_INFO_CLASS;
  1406. }
  1407. }
  1408. NTSTATUS
  1409. SeQuerySessionIdToken(
  1410. PACCESS_TOKEN Token,
  1411. PULONG SessionId
  1412. )
  1413. /*++
  1414. Routine Description:
  1415. Gets the SessionId from the specified token object.
  1416. Arguments:
  1417. Token (input)
  1418. Opaque kernel ACCESS_TOKEN pointer
  1419. SessionId (output)
  1420. pointer to location to return SessionId
  1421. Return Value:
  1422. STATUS_SUCCESS - no error
  1423. --*/
  1424. {
  1425. PAGED_CODE();
  1426. /*
  1427. * Get the SessionId.
  1428. */
  1429. SepAcquireTokenReadLock( ((PTOKEN)Token) );
  1430. (*SessionId) = ((PTOKEN)Token)->SessionId;
  1431. SepReleaseTokenReadLock( ((PTOKEN)Token) );
  1432. return( STATUS_SUCCESS );
  1433. }