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.

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