Windows NT 4.0 source code leak
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.

1612 lines
46 KiB

4 years ago
  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 "sep.h"
  13. #include "seopaque.h"
  14. #include "tokenp.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE,NtQueryInformationToken)
  17. #pragma alloc_text(PAGE,SeQueryAuthenticationIdToken)
  18. #pragma alloc_text(PAGE,SeQueryInformationToken)
  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. TokenInformationLength - Indicates the length, in bytes, of the
  69. TokenInformation buffer.
  70. ReturnLength - This OUT parameter receives the actual length of
  71. the requested information. If this value is larger than that
  72. provided by the TokenInformationLength parameter, then the
  73. buffer provided to receive the requested information is not
  74. large enough to hold that data and no data is returned.
  75. If the queried class is TokenDefaultDacl and there is no
  76. default Dacl established for the token, then the return
  77. length will be returned as zero, and no data will be returned.
  78. Return Value:
  79. STATUS_SUCCESS - Indicates the operation was successful.
  80. STATUS_BUFFER_TOO_SMALL - if the requested information did not
  81. fit in the provided output buffer. In this case, the
  82. ReturnLength OUT parameter contains the number of bytes
  83. actually needed to store the requested information.
  84. --*/
  85. {
  86. KPROCESSOR_MODE PreviousMode;
  87. NTSTATUS Status;
  88. PTOKEN Token;
  89. ULONG RequiredLength;
  90. ULONG Index;
  91. PTOKEN_TYPE LocalType;
  92. PTOKEN_USER LocalUser;
  93. PTOKEN_GROUPS LocalGroups;
  94. PTOKEN_PRIVILEGES LocalPrivileges;
  95. PTOKEN_OWNER LocalOwner;
  96. PTOKEN_PRIMARY_GROUP LocalPrimaryGroup;
  97. PTOKEN_DEFAULT_DACL LocalDefaultDacl;
  98. PTOKEN_SOURCE LocalSource;
  99. PSECURITY_IMPERSONATION_LEVEL LocalImpersonationLevel;
  100. PTOKEN_STATISTICS LocalStatistics;
  101. PSID PSid;
  102. PACL PAcl;
  103. PVOID Ignore;
  104. PAGED_CODE();
  105. //
  106. // Get previous processor mode and probe output argument if necessary.
  107. //
  108. PreviousMode = KeGetPreviousMode();
  109. if (PreviousMode != KernelMode) {
  110. try {
  111. ProbeForWrite(
  112. TokenInformation,
  113. TokenInformationLength,
  114. sizeof(ULONG)
  115. );
  116. ProbeForWriteUlong(ReturnLength);
  117. } except(EXCEPTION_EXECUTE_HANDLER) {
  118. return GetExceptionCode();
  119. }
  120. }
  121. //
  122. // Case on information class.
  123. //
  124. switch ( TokenInformationClass ) {
  125. case TokenUser:
  126. LocalUser = (PTOKEN_USER)TokenInformation;
  127. Status = ObReferenceObjectByHandle(
  128. TokenHandle, // Handle
  129. TOKEN_QUERY, // DesiredAccess
  130. SepTokenObjectType, // ObjectType
  131. PreviousMode, // AccessMode
  132. (PVOID *)&Token, // Object
  133. NULL // GrantedAccess
  134. );
  135. if ( !NT_SUCCESS(Status) ) {
  136. return Status;
  137. }
  138. //
  139. // Gain exclusive access to the token.
  140. //
  141. SepAcquireTokenReadLock( Token );
  142. //
  143. // Return the length required now in case not enough buffer
  144. // was provided by the caller and we have to return an error.
  145. //
  146. RequiredLength = SeLengthSid( Token->UserAndGroups[0].Sid) +
  147. (ULONG)sizeof( TOKEN_USER );
  148. try {
  149. *ReturnLength = RequiredLength;
  150. } except(EXCEPTION_EXECUTE_HANDLER) {
  151. SepReleaseTokenReadLock( Token );
  152. ObDereferenceObject( Token );
  153. return GetExceptionCode();
  154. }
  155. if ( TokenInformationLength < RequiredLength ) {
  156. SepReleaseTokenReadLock( Token );
  157. ObDereferenceObject( Token );
  158. return STATUS_BUFFER_TOO_SMALL;
  159. }
  160. //
  161. // Return the user SID
  162. //
  163. try {
  164. //
  165. // Put SID immediately following TOKEN_USER data structure
  166. //
  167. PSid = (PSID)( (ULONG)LocalUser + (ULONG)sizeof(TOKEN_USER) );
  168. RtlCopySidAndAttributesArray(
  169. 1,
  170. Token->UserAndGroups,
  171. RequiredLength,
  172. &(LocalUser->User),
  173. PSid,
  174. ((PSID *)&Ignore),
  175. ((PULONG)&Ignore)
  176. );
  177. } except(EXCEPTION_EXECUTE_HANDLER) {
  178. SepReleaseTokenReadLock( Token );
  179. ObDereferenceObject( Token );
  180. return GetExceptionCode();
  181. }
  182. SepReleaseTokenReadLock( Token );
  183. ObDereferenceObject( Token );
  184. return STATUS_SUCCESS;
  185. case TokenGroups:
  186. LocalGroups = (PTOKEN_GROUPS)TokenInformation;
  187. Status = ObReferenceObjectByHandle(
  188. TokenHandle, // Handle
  189. TOKEN_QUERY, // DesiredAccess
  190. SepTokenObjectType, // ObjectType
  191. PreviousMode, // AccessMode
  192. (PVOID *)&Token, // Object
  193. NULL // GrantedAccess
  194. );
  195. if ( !NT_SUCCESS(Status) ) {
  196. return Status;
  197. }
  198. //
  199. // Gain exclusive access to the token.
  200. //
  201. SepAcquireTokenReadLock( Token );
  202. //
  203. // Figure out how much space is needed to return the group SIDs.
  204. // That's the size of TOKEN_GROUPS (without any array entries)
  205. // plus the size of an SID_AND_ATTRIBUTES times the number of groups.
  206. // The number of groups is Token->UserAndGroups-1 (since the count
  207. // includes the user ID). Then the lengths of each individual group
  208. // must be added.
  209. //
  210. RequiredLength = (ULONG)sizeof(TOKEN_GROUPS) +
  211. ((Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  212. ((ULONG)sizeof(SID_AND_ATTRIBUTES)) );
  213. Index = 1;
  214. while (Index < Token->UserAndGroupCount) {
  215. RequiredLength += SeLengthSid( Token->UserAndGroups[Index].Sid );
  216. Index += 1;
  217. } // endwhile
  218. //
  219. // Return the length required now in case not enough buffer
  220. // was provided by the caller and we have to return an error.
  221. //
  222. try {
  223. *ReturnLength = RequiredLength;
  224. } except(EXCEPTION_EXECUTE_HANDLER) {
  225. SepReleaseTokenReadLock( Token );
  226. ObDereferenceObject( Token );
  227. return GetExceptionCode();
  228. }
  229. if ( TokenInformationLength < RequiredLength ) {
  230. SepReleaseTokenReadLock( Token );
  231. ObDereferenceObject( Token );
  232. return STATUS_BUFFER_TOO_SMALL;
  233. }
  234. //
  235. // Now copy the groups.
  236. //
  237. try {
  238. LocalGroups->GroupCount = Token->UserAndGroupCount - 1;
  239. PSid = (PSID)( (ULONG)LocalGroups +
  240. (ULONG)sizeof(TOKEN_GROUPS) +
  241. ( (Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  242. (ULONG)sizeof(SID_AND_ATTRIBUTES) )
  243. );
  244. RtlCopySidAndAttributesArray(
  245. (ULONG)(Token->UserAndGroupCount - 1),
  246. &(Token->UserAndGroups[1]),
  247. RequiredLength,
  248. LocalGroups->Groups,
  249. PSid,
  250. ((PSID *)&Ignore),
  251. ((PULONG)&Ignore)
  252. );
  253. } except(EXCEPTION_EXECUTE_HANDLER) {
  254. SepReleaseTokenReadLock( Token );
  255. ObDereferenceObject( Token );
  256. return GetExceptionCode();
  257. }
  258. SepReleaseTokenReadLock( Token );
  259. ObDereferenceObject( Token );
  260. return STATUS_SUCCESS;
  261. case TokenPrivileges:
  262. LocalPrivileges = (PTOKEN_PRIVILEGES)TokenInformation;
  263. Status = ObReferenceObjectByHandle(
  264. TokenHandle, // Handle
  265. TOKEN_QUERY, // DesiredAccess
  266. SepTokenObjectType, // ObjectType
  267. PreviousMode, // AccessMode
  268. (PVOID *)&Token, // Object
  269. NULL // GrantedAccess
  270. );
  271. if ( !NT_SUCCESS(Status) ) {
  272. return Status;
  273. }
  274. //
  275. // Gain exclusive access to the token to prevent changes
  276. // from occuring to the privileges.
  277. //
  278. SepAcquireTokenReadLock( Token );
  279. //
  280. // Return the length required now in case not enough buffer
  281. // was provided by the caller and we have to return an error.
  282. //
  283. RequiredLength = (ULONG)sizeof(TOKEN_PRIVILEGES) +
  284. ((Token->PrivilegeCount - ANYSIZE_ARRAY) *
  285. ((ULONG)sizeof(LUID_AND_ATTRIBUTES)) );
  286. try {
  287. *ReturnLength = RequiredLength;
  288. } except(EXCEPTION_EXECUTE_HANDLER) {
  289. SepReleaseTokenReadLock( Token );
  290. ObDereferenceObject( Token );
  291. return GetExceptionCode();
  292. }
  293. if ( TokenInformationLength < RequiredLength ) {
  294. SepReleaseTokenReadLock( Token );
  295. ObDereferenceObject( Token );
  296. return STATUS_BUFFER_TOO_SMALL;
  297. }
  298. //
  299. // Return the token privileges.
  300. //
  301. try {
  302. LocalPrivileges->PrivilegeCount = Token->PrivilegeCount;
  303. RtlCopyLuidAndAttributesArray(
  304. Token->PrivilegeCount,
  305. Token->Privileges,
  306. LocalPrivileges->Privileges
  307. );
  308. } except(EXCEPTION_EXECUTE_HANDLER) {
  309. SepReleaseTokenReadLock( Token );
  310. ObDereferenceObject( Token );
  311. return GetExceptionCode();
  312. }
  313. SepReleaseTokenReadLock( Token );
  314. ObDereferenceObject( Token );
  315. return STATUS_SUCCESS;
  316. case TokenOwner:
  317. LocalOwner = (PTOKEN_OWNER)TokenInformation;
  318. Status = ObReferenceObjectByHandle(
  319. TokenHandle, // Handle
  320. TOKEN_QUERY, // DesiredAccess
  321. SepTokenObjectType, // ObjectType
  322. PreviousMode, // AccessMode
  323. (PVOID *)&Token, // Object
  324. NULL // GrantedAccess
  325. );
  326. if ( !NT_SUCCESS(Status) ) {
  327. return Status;
  328. }
  329. //
  330. // Gain exclusive access to the token to prevent changes
  331. // from occuring to the owner.
  332. //
  333. SepAcquireTokenReadLock( Token );
  334. //
  335. // Return the length required now in case not enough buffer
  336. // was provided by the caller and we have to return an error.
  337. //
  338. PSid = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
  339. RequiredLength = (ULONG)sizeof(TOKEN_OWNER) +
  340. SeLengthSid( PSid );
  341. try {
  342. *ReturnLength = RequiredLength;
  343. } except(EXCEPTION_EXECUTE_HANDLER) {
  344. SepReleaseTokenReadLock( Token );
  345. ObDereferenceObject( Token );
  346. return GetExceptionCode();
  347. }
  348. if ( TokenInformationLength < RequiredLength ) {
  349. SepReleaseTokenReadLock( Token );
  350. ObDereferenceObject( Token );
  351. return STATUS_BUFFER_TOO_SMALL;
  352. }
  353. //
  354. // Return the owner SID
  355. //
  356. PSid = (PSID)((ULONG)LocalOwner +
  357. (ULONG)sizeof(TOKEN_OWNER));
  358. try {
  359. LocalOwner->Owner = PSid;
  360. Status = RtlCopySid(
  361. (RequiredLength - (ULONG)sizeof(TOKEN_OWNER)),
  362. PSid,
  363. Token->UserAndGroups[Token->DefaultOwnerIndex].Sid
  364. );
  365. ASSERT( NT_SUCCESS(Status) );
  366. } except(EXCEPTION_EXECUTE_HANDLER) {
  367. SepReleaseTokenReadLock( Token );
  368. ObDereferenceObject( Token );
  369. return GetExceptionCode();
  370. }
  371. SepReleaseTokenReadLock( Token );
  372. ObDereferenceObject( Token );
  373. return STATUS_SUCCESS;
  374. case TokenPrimaryGroup:
  375. LocalPrimaryGroup = (PTOKEN_PRIMARY_GROUP)TokenInformation;
  376. Status = ObReferenceObjectByHandle(
  377. TokenHandle, // Handle
  378. TOKEN_QUERY, // DesiredAccess
  379. SepTokenObjectType, // ObjectType
  380. PreviousMode, // AccessMode
  381. (PVOID *)&Token, // Object
  382. NULL // GrantedAccess
  383. );
  384. if ( !NT_SUCCESS(Status) ) {
  385. return Status;
  386. }
  387. //
  388. // Gain exclusive access to the token to prevent changes
  389. // from occuring to the owner.
  390. //
  391. SepAcquireTokenReadLock( Token );
  392. //
  393. // Return the length required now in case not enough buffer
  394. // was provided by the caller and we have to return an error.
  395. //
  396. RequiredLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP) +
  397. SeLengthSid( Token->PrimaryGroup );
  398. try {
  399. *ReturnLength = RequiredLength;
  400. } except(EXCEPTION_EXECUTE_HANDLER) {
  401. SepReleaseTokenReadLock( Token );
  402. ObDereferenceObject( Token );
  403. return GetExceptionCode();
  404. }
  405. if ( TokenInformationLength < RequiredLength ) {
  406. SepReleaseTokenReadLock( Token );
  407. ObDereferenceObject( Token );
  408. return STATUS_BUFFER_TOO_SMALL;
  409. }
  410. //
  411. // Return the primary group SID
  412. //
  413. PSid = (PSID)((ULONG)LocalPrimaryGroup +
  414. (ULONG)sizeof(TOKEN_PRIMARY_GROUP));
  415. try {
  416. LocalPrimaryGroup->PrimaryGroup = PSid;
  417. Status = RtlCopySid( (RequiredLength - (ULONG)sizeof(TOKEN_PRIMARY_GROUP)),
  418. PSid,
  419. Token->PrimaryGroup
  420. );
  421. ASSERT( NT_SUCCESS(Status) );
  422. } except(EXCEPTION_EXECUTE_HANDLER) {
  423. SepReleaseTokenReadLock( Token );
  424. ObDereferenceObject( Token );
  425. return GetExceptionCode();
  426. }
  427. SepReleaseTokenReadLock( Token );
  428. ObDereferenceObject( Token );
  429. return STATUS_SUCCESS;
  430. case TokenDefaultDacl:
  431. LocalDefaultDacl = (PTOKEN_DEFAULT_DACL)TokenInformation;
  432. Status = ObReferenceObjectByHandle(
  433. TokenHandle, // Handle
  434. TOKEN_QUERY, // DesiredAccess
  435. SepTokenObjectType, // ObjectType
  436. PreviousMode, // AccessMode
  437. (PVOID *)&Token, // Object
  438. NULL // GrantedAccess
  439. );
  440. if ( !NT_SUCCESS(Status) ) {
  441. return Status;
  442. }
  443. //
  444. // Gain exclusive access to the token to prevent changes
  445. // from occuring to the owner.
  446. //
  447. SepAcquireTokenReadLock( Token );
  448. //
  449. // Return the length required now in case not enough buffer
  450. // was provided by the caller and we have to return an error.
  451. //
  452. RequiredLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  453. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  454. RequiredLength += Token->DefaultDacl->AclSize;
  455. }
  456. try {
  457. *ReturnLength = RequiredLength;
  458. } except(EXCEPTION_EXECUTE_HANDLER) {
  459. SepReleaseTokenReadLock( Token );
  460. ObDereferenceObject( Token );
  461. return GetExceptionCode();
  462. }
  463. if ( TokenInformationLength < RequiredLength ) {
  464. SepReleaseTokenReadLock( Token );
  465. ObDereferenceObject( Token );
  466. return STATUS_BUFFER_TOO_SMALL;
  467. }
  468. //
  469. // Return the default Dacl
  470. //
  471. PAcl = (PACL)((ULONG)LocalDefaultDacl +
  472. (ULONG)sizeof(TOKEN_DEFAULT_DACL));
  473. try {
  474. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  475. LocalDefaultDacl->DefaultDacl = PAcl;
  476. RtlMoveMemory( (PVOID)PAcl,
  477. (PVOID)Token->DefaultDacl,
  478. Token->DefaultDacl->AclSize
  479. );
  480. } else {
  481. LocalDefaultDacl->DefaultDacl = NULL;
  482. }
  483. } except(EXCEPTION_EXECUTE_HANDLER) {
  484. SepReleaseTokenReadLock( Token );
  485. ObDereferenceObject( Token );
  486. return GetExceptionCode();
  487. }
  488. SepReleaseTokenReadLock( Token );
  489. ObDereferenceObject( Token );
  490. return STATUS_SUCCESS;
  491. case TokenSource:
  492. LocalSource = (PTOKEN_SOURCE)TokenInformation;
  493. Status = ObReferenceObjectByHandle(
  494. TokenHandle, // Handle
  495. TOKEN_QUERY_SOURCE, // DesiredAccess
  496. SepTokenObjectType, // ObjectType
  497. PreviousMode, // AccessMode
  498. (PVOID *)&Token, // Object
  499. NULL // GrantedAccess
  500. );
  501. if ( !NT_SUCCESS(Status) ) {
  502. return Status;
  503. }
  504. //
  505. // The type of a token can not be changed, so
  506. // exclusive access to the token is not necessary.
  507. //
  508. //
  509. // Return the length required now in case not enough buffer
  510. // was provided by the caller and we have to return an error.
  511. //
  512. RequiredLength = (ULONG) sizeof(TOKEN_SOURCE);
  513. try {
  514. *ReturnLength = RequiredLength;
  515. } except(EXCEPTION_EXECUTE_HANDLER) {
  516. ObDereferenceObject( Token );
  517. return GetExceptionCode();
  518. }
  519. if ( TokenInformationLength < RequiredLength ) {
  520. ObDereferenceObject( Token );
  521. return STATUS_BUFFER_TOO_SMALL;
  522. }
  523. //
  524. // Return the token source
  525. //
  526. try {
  527. (*LocalSource) = Token->TokenSource;
  528. } except(EXCEPTION_EXECUTE_HANDLER) {
  529. ObDereferenceObject( Token );
  530. return GetExceptionCode();
  531. }
  532. ObDereferenceObject( Token );
  533. return STATUS_SUCCESS;
  534. case TokenType:
  535. LocalType = (PTOKEN_TYPE)TokenInformation;
  536. Status = ObReferenceObjectByHandle(
  537. TokenHandle, // Handle
  538. TOKEN_QUERY, // DesiredAccess
  539. SepTokenObjectType, // ObjectType
  540. PreviousMode, // AccessMode
  541. (PVOID *)&Token, // Object
  542. NULL // GrantedAccess
  543. );
  544. if ( !NT_SUCCESS(Status) ) {
  545. return Status;
  546. }
  547. //
  548. // The type of a token can not be changed, so
  549. // exclusive access to the token is not necessary.
  550. //
  551. //
  552. // Return the length required now in case not enough buffer
  553. // was provided by the caller and we have to return an error.
  554. //
  555. RequiredLength = (ULONG) sizeof(TOKEN_TYPE);
  556. try {
  557. *ReturnLength = RequiredLength;
  558. } except(EXCEPTION_EXECUTE_HANDLER) {
  559. ObDereferenceObject( Token );
  560. return GetExceptionCode();
  561. }
  562. if ( TokenInformationLength < RequiredLength ) {
  563. ObDereferenceObject( Token );
  564. return STATUS_BUFFER_TOO_SMALL;
  565. }
  566. //
  567. // Return the token type
  568. //
  569. try {
  570. (*LocalType) = Token->TokenType;
  571. } except(EXCEPTION_EXECUTE_HANDLER) {
  572. ObDereferenceObject( Token );
  573. return GetExceptionCode();
  574. }
  575. ObDereferenceObject( Token );
  576. return STATUS_SUCCESS;
  577. case TokenImpersonationLevel:
  578. LocalImpersonationLevel = (PSECURITY_IMPERSONATION_LEVEL)TokenInformation;
  579. Status = ObReferenceObjectByHandle(
  580. TokenHandle, // Handle
  581. TOKEN_QUERY, // DesiredAccess
  582. SepTokenObjectType, // ObjectType
  583. PreviousMode, // AccessMode
  584. (PVOID *)&Token, // Object
  585. NULL // GrantedAccess
  586. );
  587. if ( !NT_SUCCESS(Status) ) {
  588. return Status;
  589. }
  590. //
  591. // The impersonation level of a token can not be changed, so
  592. // exclusive access to the token is not necessary.
  593. //
  594. //
  595. // Make sure the token is an appropriate type to be retrieving
  596. // the impersonation level from.
  597. //
  598. if (Token->TokenType != TokenImpersonation) {
  599. ObDereferenceObject( Token );
  600. return STATUS_INVALID_INFO_CLASS;
  601. }
  602. //
  603. // Return the length required now in case not enough buffer
  604. // was provided by the caller and we have to return an error.
  605. //
  606. RequiredLength = (ULONG) sizeof(SECURITY_IMPERSONATION_LEVEL);
  607. try {
  608. *ReturnLength = RequiredLength;
  609. } except(EXCEPTION_EXECUTE_HANDLER) {
  610. ObDereferenceObject( Token );
  611. return GetExceptionCode();
  612. }
  613. if ( TokenInformationLength < RequiredLength ) {
  614. ObDereferenceObject( Token );
  615. return STATUS_BUFFER_TOO_SMALL;
  616. }
  617. //
  618. // Return the impersonation level
  619. //
  620. try {
  621. (*LocalImpersonationLevel) = Token->ImpersonationLevel;
  622. } except(EXCEPTION_EXECUTE_HANDLER) {
  623. ObDereferenceObject( Token );
  624. return GetExceptionCode();
  625. }
  626. ObDereferenceObject( Token );
  627. return STATUS_SUCCESS;
  628. case TokenStatistics:
  629. LocalStatistics = (PTOKEN_STATISTICS)TokenInformation;
  630. Status = ObReferenceObjectByHandle(
  631. TokenHandle, // Handle
  632. TOKEN_QUERY, // DesiredAccess
  633. SepTokenObjectType, // ObjectType
  634. PreviousMode, // AccessMode
  635. (PVOID *)&Token, // Object
  636. NULL // GrantedAccess
  637. );
  638. if ( !NT_SUCCESS(Status) ) {
  639. return Status;
  640. }
  641. //
  642. // Gain exclusive access to the token.
  643. //
  644. SepAcquireTokenReadLock( Token );
  645. //
  646. // Return the length required now in case not enough buffer
  647. // was provided by the caller and we have to return an error.
  648. //
  649. RequiredLength = (ULONG)sizeof( TOKEN_STATISTICS );
  650. try {
  651. *ReturnLength = RequiredLength;
  652. } except(EXCEPTION_EXECUTE_HANDLER) {
  653. SepReleaseTokenReadLock( Token );
  654. ObDereferenceObject( Token );
  655. return GetExceptionCode();
  656. }
  657. if ( TokenInformationLength < RequiredLength ) {
  658. SepReleaseTokenReadLock( Token );
  659. ObDereferenceObject( Token );
  660. return STATUS_BUFFER_TOO_SMALL;
  661. }
  662. //
  663. // Return the statistics
  664. //
  665. try {
  666. LocalStatistics->TokenId = Token->TokenId;
  667. LocalStatistics->AuthenticationId = Token->AuthenticationId;
  668. LocalStatistics->ExpirationTime = Token->ExpirationTime;
  669. LocalStatistics->TokenType = Token->TokenType;
  670. LocalStatistics->ImpersonationLevel = Token->ImpersonationLevel;
  671. LocalStatistics->DynamicCharged = Token->DynamicCharged;
  672. LocalStatistics->DynamicAvailable = Token->DynamicAvailable;
  673. LocalStatistics->GroupCount = Token->UserAndGroupCount-1;
  674. LocalStatistics->PrivilegeCount = Token->PrivilegeCount;
  675. LocalStatistics->ModifiedId = Token->ModifiedId;
  676. } except(EXCEPTION_EXECUTE_HANDLER) {
  677. SepReleaseTokenReadLock( Token );
  678. ObDereferenceObject( Token );
  679. return GetExceptionCode();
  680. }
  681. SepReleaseTokenReadLock( Token );
  682. ObDereferenceObject( Token );
  683. return STATUS_SUCCESS;
  684. default:
  685. return STATUS_INVALID_INFO_CLASS;
  686. }
  687. }
  688. NTSTATUS
  689. SeQueryAuthenticationIdToken(
  690. IN PACCESS_TOKEN Token,
  691. OUT PLUID AuthenticationId
  692. )
  693. /*++
  694. Routine Description:
  695. Retrieve authentication ID out of the token.
  696. Arguments:
  697. Token - Referenced pointer to a token.
  698. AutenticationId - Receives the token's authentication ID.
  699. Return Value:
  700. STATUS_SUCCESS - Indicates the operation was successful.
  701. This is the only expected status.
  702. --*/
  703. {
  704. PAGED_CODE();
  705. SepAcquireTokenReadLock( ((PTOKEN)Token) );
  706. (*AuthenticationId) = ((PTOKEN)Token)->AuthenticationId;
  707. SepReleaseTokenReadLock( ((PTOKEN)Token) );
  708. return(STATUS_SUCCESS);
  709. }
  710. NTSTATUS
  711. SeQueryInformationToken (
  712. IN PACCESS_TOKEN AccessToken,
  713. IN TOKEN_INFORMATION_CLASS TokenInformationClass,
  714. OUT PVOID *TokenInformation
  715. )
  716. /*++
  717. Routine Description:
  718. Retrieve information about a specified token.
  719. Arguments:
  720. TokenHandle - Provides a handle to the token to operate on.
  721. TokenInformationClass - The token information class about which
  722. to retrieve information.
  723. TokenInformation - Receives a pointer to the requested information.
  724. The actual structures returned are dependent upon the information
  725. class requested, as defined in the TokenInformationClass parameter
  726. description.
  727. TokenInformation Format By Information Class:
  728. TokenUser => TOKEN_USER data structure. TOKEN_QUERY
  729. access is needed to retrieve this information about a
  730. token.
  731. TokenGroups => TOKEN_GROUPS data structure. TOKEN_QUERY
  732. access is needed to retrieve this information about a
  733. token.
  734. TokenPrivileges => TOKEN_PRIVILEGES data structure.
  735. TOKEN_QUERY access is needed to retrieve this information
  736. about a token.
  737. TokenOwner => TOKEN_OWNER data structure. TOKEN_QUERY
  738. access is needed to retrieve this information about a
  739. token.
  740. TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure.
  741. TOKEN_QUERY access is needed to retrieve this information
  742. about a token.
  743. TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure.
  744. TOKEN_QUERY access is needed to retrieve this information
  745. about a token.
  746. TokenSource => TOKEN_SOURCE data structure.
  747. TOKEN_QUERY_SOURCE access is needed to retrieve this
  748. information about a token.
  749. TokenType => TOKEN_TYPE data structure.
  750. TOKEN_QUERY access is needed to retrieve this information
  751. about a token.
  752. TokenStatistics => TOKEN_STATISTICS data structure.
  753. TOKEN_QUERY access is needed to retrieve this
  754. information about a token.
  755. Return Value:
  756. STATUS_SUCCESS - Indicates the operation was successful.
  757. --*/
  758. {
  759. NTSTATUS Status;
  760. ULONG RequiredLength;
  761. ULONG Index;
  762. PSID PSid;
  763. PACL PAcl;
  764. PVOID Ignore;
  765. PTOKEN Token = (PTOKEN)AccessToken;
  766. PAGED_CODE();
  767. //
  768. // Case on information class.
  769. //
  770. switch ( TokenInformationClass ) {
  771. case TokenUser:
  772. {
  773. PTOKEN_USER LocalUser;
  774. LocalUser = (PTOKEN_USER)(*TokenInformation);
  775. //
  776. // Gain exclusive access to the token.
  777. //
  778. SepAcquireTokenReadLock( Token );
  779. //
  780. // Return the length required now in case not enough buffer
  781. // was provided by the caller and we have to return an error.
  782. //
  783. RequiredLength = SeLengthSid( Token->UserAndGroups[0].Sid) +
  784. (ULONG)sizeof( TOKEN_USER );
  785. LocalUser = ExAllocatePool( PagedPool, RequiredLength );
  786. if (LocalUser == NULL) {
  787. SepReleaseTokenReadLock( Token );
  788. return( STATUS_INSUFFICIENT_RESOURCES );
  789. }
  790. //
  791. // Return the user SID
  792. //
  793. // Put SID immediately following TOKEN_USER data structure
  794. //
  795. PSid = (PSID)( (ULONG)LocalUser + (ULONG)sizeof(TOKEN_USER) );
  796. RtlCopySidAndAttributesArray(
  797. 1,
  798. Token->UserAndGroups,
  799. RequiredLength,
  800. &(LocalUser->User),
  801. PSid,
  802. ((PSID *)&Ignore),
  803. ((PULONG)&Ignore)
  804. );
  805. SepReleaseTokenReadLock( Token );
  806. return STATUS_SUCCESS;
  807. }
  808. case TokenGroups:
  809. {
  810. PTOKEN_GROUPS LocalGroups;
  811. LocalGroups = (PTOKEN_GROUPS)(*TokenInformation);
  812. //
  813. // Gain exclusive access to the token.
  814. //
  815. SepAcquireTokenReadLock( Token );
  816. //
  817. // Figure out how much space is needed to return the group SIDs.
  818. // That's the size of TOKEN_GROUPS (without any array entries)
  819. // plus the size of an SID_AND_ATTRIBUTES times the number of groups.
  820. // The number of groups is Token->UserAndGroups-1 (since the count
  821. // includes the user ID). Then the lengths of each individual group
  822. // must be added.
  823. //
  824. RequiredLength = (ULONG)sizeof(TOKEN_GROUPS) +
  825. ((Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  826. ((ULONG)sizeof(SID_AND_ATTRIBUTES)) );
  827. Index = 1;
  828. while (Index < Token->UserAndGroupCount) {
  829. RequiredLength += SeLengthSid( Token->UserAndGroups[Index].Sid );
  830. Index += 1;
  831. } // endwhile
  832. LocalGroups = ExAllocatePool( PagedPool, RequiredLength );
  833. if (LocalGroups == NULL) {
  834. SepReleaseTokenReadLock( Token );
  835. return( STATUS_INSUFFICIENT_RESOURCES );
  836. }
  837. //
  838. // Now copy the groups.
  839. //
  840. LocalGroups->GroupCount = Token->UserAndGroupCount - 1;
  841. PSid = (PSID)( (ULONG)LocalGroups +
  842. (ULONG)sizeof(TOKEN_GROUPS) +
  843. ( (Token->UserAndGroupCount - ANYSIZE_ARRAY - 1) *
  844. (ULONG)sizeof(SID_AND_ATTRIBUTES) )
  845. );
  846. RtlCopySidAndAttributesArray(
  847. (ULONG)(Token->UserAndGroupCount - 1),
  848. &(Token->UserAndGroups[1]),
  849. RequiredLength,
  850. LocalGroups->Groups,
  851. PSid,
  852. ((PSID *)&Ignore),
  853. ((PULONG)&Ignore)
  854. );
  855. SepReleaseTokenReadLock( Token );
  856. return STATUS_SUCCESS;
  857. }
  858. case TokenPrivileges:
  859. {
  860. PTOKEN_PRIVILEGES LocalPrivileges;
  861. LocalPrivileges = (PTOKEN_PRIVILEGES)(*TokenInformation);
  862. //
  863. // Gain exclusive access to the token to prevent changes
  864. // from occuring to the privileges.
  865. //
  866. SepAcquireTokenReadLock( Token );
  867. //
  868. // Return the length required now in case not enough buffer
  869. // was provided by the caller and we have to return an error.
  870. //
  871. RequiredLength = (ULONG)sizeof(TOKEN_PRIVILEGES) +
  872. ((Token->PrivilegeCount - ANYSIZE_ARRAY) *
  873. ((ULONG)sizeof(LUID_AND_ATTRIBUTES)) );
  874. LocalPrivileges = ExAllocatePool( PagedPool, RequiredLength );
  875. if (LocalPrivileges == NULL) {
  876. SepReleaseTokenReadLock( Token );
  877. return( STATUS_INSUFFICIENT_RESOURCES );
  878. }
  879. //
  880. // Return the token privileges.
  881. //
  882. LocalPrivileges->PrivilegeCount = Token->PrivilegeCount;
  883. RtlCopyLuidAndAttributesArray(
  884. Token->PrivilegeCount,
  885. Token->Privileges,
  886. LocalPrivileges->Privileges
  887. );
  888. SepReleaseTokenReadLock( Token );
  889. return STATUS_SUCCESS;
  890. }
  891. case TokenOwner:
  892. {
  893. PTOKEN_OWNER LocalOwner;
  894. LocalOwner = (PTOKEN_OWNER)(*TokenInformation);
  895. //
  896. // Gain exclusive access to the token to prevent changes
  897. // from occuring to the owner.
  898. //
  899. SepAcquireTokenReadLock( Token );
  900. //
  901. // Return the length required now in case not enough buffer
  902. // was provided by the caller and we have to return an error.
  903. //
  904. PSid = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
  905. RequiredLength = (ULONG)sizeof(TOKEN_OWNER) +
  906. SeLengthSid( PSid );
  907. LocalOwner = ExAllocatePool( PagedPool, RequiredLength );
  908. if (LocalOwner == NULL) {
  909. SepReleaseTokenReadLock( Token );
  910. return( STATUS_INSUFFICIENT_RESOURCES );
  911. }
  912. //
  913. // Return the owner SID
  914. //
  915. PSid = (PSID)((ULONG)LocalOwner +
  916. (ULONG)sizeof(TOKEN_OWNER));
  917. LocalOwner->Owner = PSid;
  918. Status = RtlCopySid(
  919. (RequiredLength - (ULONG)sizeof(TOKEN_OWNER)),
  920. PSid,
  921. Token->UserAndGroups[Token->DefaultOwnerIndex].Sid
  922. );
  923. ASSERT( NT_SUCCESS(Status) );
  924. SepReleaseTokenReadLock( Token );
  925. return STATUS_SUCCESS;
  926. }
  927. case TokenPrimaryGroup:
  928. {
  929. PTOKEN_PRIMARY_GROUP LocalPrimaryGroup;
  930. LocalPrimaryGroup = (PTOKEN_PRIMARY_GROUP)(*TokenInformation);
  931. //
  932. // Gain exclusive access to the token to prevent changes
  933. // from occuring to the owner.
  934. //
  935. SepAcquireTokenReadLock( Token );
  936. //
  937. // Return the length required now in case not enough buffer
  938. // was provided by the caller and we have to return an error.
  939. //
  940. RequiredLength = (ULONG)sizeof(TOKEN_PRIMARY_GROUP) +
  941. SeLengthSid( Token->PrimaryGroup );
  942. LocalPrimaryGroup = ExAllocatePool( PagedPool, RequiredLength );
  943. if (LocalPrimaryGroup == NULL) {
  944. SepReleaseTokenReadLock( Token );
  945. return( STATUS_INSUFFICIENT_RESOURCES );
  946. }
  947. //
  948. // Return the primary group SID
  949. //
  950. PSid = (PSID)((ULONG)LocalPrimaryGroup +
  951. (ULONG)sizeof(TOKEN_PRIMARY_GROUP));
  952. LocalPrimaryGroup->PrimaryGroup = PSid;
  953. Status = RtlCopySid( (RequiredLength - (ULONG)sizeof(TOKEN_PRIMARY_GROUP)),
  954. PSid,
  955. Token->PrimaryGroup
  956. );
  957. ASSERT( NT_SUCCESS(Status) );
  958. SepReleaseTokenReadLock( Token );
  959. return STATUS_SUCCESS;
  960. }
  961. case TokenDefaultDacl:
  962. {
  963. PTOKEN_DEFAULT_DACL LocalDefaultDacl;
  964. LocalDefaultDacl = (PTOKEN_DEFAULT_DACL)(*TokenInformation);
  965. //
  966. // Gain exclusive access to the token to prevent changes
  967. // from occuring to the owner.
  968. //
  969. SepAcquireTokenReadLock( Token );
  970. //
  971. // Return the length required now in case not enough buffer
  972. // was provided by the caller and we have to return an error.
  973. //
  974. RequiredLength = (ULONG)sizeof(TOKEN_DEFAULT_DACL);
  975. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  976. RequiredLength += Token->DefaultDacl->AclSize;
  977. }
  978. LocalDefaultDacl = ExAllocatePool( PagedPool, RequiredLength );
  979. if (LocalDefaultDacl == NULL) {
  980. SepReleaseTokenReadLock( Token );
  981. return( STATUS_INSUFFICIENT_RESOURCES );
  982. }
  983. //
  984. // Return the default Dacl
  985. //
  986. PAcl = (PACL)((ULONG)LocalDefaultDacl +
  987. (ULONG)sizeof(TOKEN_DEFAULT_DACL));
  988. if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
  989. LocalDefaultDacl->DefaultDacl = PAcl;
  990. RtlMoveMemory( (PVOID)PAcl,
  991. (PVOID)Token->DefaultDacl,
  992. Token->DefaultDacl->AclSize
  993. );
  994. } else {
  995. LocalDefaultDacl->DefaultDacl = NULL;
  996. }
  997. SepReleaseTokenReadLock( Token );
  998. return STATUS_SUCCESS;
  999. }
  1000. case TokenSource:
  1001. {
  1002. PTOKEN_SOURCE LocalSource;
  1003. LocalSource = (PTOKEN_SOURCE)(*TokenInformation);
  1004. //
  1005. // The type of a token can not be changed, so
  1006. // exclusive access to the token is not necessary.
  1007. //
  1008. //
  1009. // Return the length required now in case not enough buffer
  1010. // was provided by the caller and we have to return an error.
  1011. //
  1012. RequiredLength = (ULONG) sizeof(TOKEN_SOURCE);
  1013. LocalSource = ExAllocatePool( PagedPool, RequiredLength );
  1014. if (LocalSource == NULL) {
  1015. return( STATUS_INSUFFICIENT_RESOURCES );
  1016. }
  1017. //
  1018. // Return the token source
  1019. //
  1020. (*LocalSource) = Token->TokenSource;
  1021. return STATUS_SUCCESS;
  1022. }
  1023. case TokenType:
  1024. {
  1025. PTOKEN_TYPE LocalType;
  1026. LocalType = (PTOKEN_TYPE)(*TokenInformation);
  1027. //
  1028. // The type of a token can not be changed, so
  1029. // exclusive access to the token is not necessary.
  1030. //
  1031. //
  1032. // Return the length required now in case not enough buffer
  1033. // was provided by the caller and we have to return an error.
  1034. //
  1035. RequiredLength = (ULONG) sizeof(TOKEN_TYPE);
  1036. LocalType = ExAllocatePool( PagedPool, RequiredLength );
  1037. if (LocalType == NULL) {
  1038. return( STATUS_INSUFFICIENT_RESOURCES );
  1039. }
  1040. //
  1041. // Return the token type
  1042. //
  1043. (*LocalType) = Token->TokenType;
  1044. return STATUS_SUCCESS;
  1045. }
  1046. case TokenImpersonationLevel:
  1047. {
  1048. PSECURITY_IMPERSONATION_LEVEL LocalImpersonationLevel;
  1049. LocalImpersonationLevel = (PSECURITY_IMPERSONATION_LEVEL)(*TokenInformation);
  1050. //
  1051. // The impersonation level of a token can not be changed, so
  1052. // exclusive access to the token is not necessary.
  1053. //
  1054. //
  1055. // Make sure the token is an appropriate type to be retrieving
  1056. // the impersonation level from.
  1057. //
  1058. if (Token->TokenType != TokenImpersonation) {
  1059. return STATUS_INVALID_INFO_CLASS;
  1060. }
  1061. //
  1062. // Return the length required now in case not enough buffer
  1063. // was provided by the caller and we have to return an error.
  1064. //
  1065. RequiredLength = (ULONG) sizeof(SECURITY_IMPERSONATION_LEVEL);
  1066. LocalImpersonationLevel = ExAllocatePool( PagedPool, RequiredLength );
  1067. if (LocalImpersonationLevel == NULL) {
  1068. return( STATUS_INSUFFICIENT_RESOURCES );
  1069. }
  1070. //
  1071. // Return the impersonation level
  1072. //
  1073. (*LocalImpersonationLevel) = Token->ImpersonationLevel;
  1074. return STATUS_SUCCESS;
  1075. }
  1076. case TokenStatistics:
  1077. {
  1078. PTOKEN_STATISTICS LocalStatistics;
  1079. LocalStatistics = (PTOKEN_STATISTICS)(*TokenInformation);
  1080. //
  1081. // Gain exclusive access to the token.
  1082. //
  1083. SepAcquireTokenReadLock( Token );
  1084. //
  1085. // Return the length required now in case not enough buffer
  1086. // was provided by the caller and we have to return an error.
  1087. //
  1088. RequiredLength = (ULONG)sizeof( TOKEN_STATISTICS );
  1089. LocalStatistics = ExAllocatePool( PagedPool, RequiredLength );
  1090. if (LocalStatistics == NULL) {
  1091. SepReleaseTokenReadLock( Token );
  1092. return( STATUS_INSUFFICIENT_RESOURCES );
  1093. }
  1094. //
  1095. // Return the statistics
  1096. //
  1097. LocalStatistics->TokenId = Token->TokenId;
  1098. LocalStatistics->AuthenticationId = Token->AuthenticationId;
  1099. LocalStatistics->ExpirationTime = Token->ExpirationTime;
  1100. LocalStatistics->TokenType = Token->TokenType;
  1101. LocalStatistics->ImpersonationLevel = Token->ImpersonationLevel;
  1102. LocalStatistics->DynamicCharged = Token->DynamicCharged;
  1103. LocalStatistics->DynamicAvailable = Token->DynamicAvailable;
  1104. LocalStatistics->GroupCount = Token->UserAndGroupCount-1;
  1105. LocalStatistics->PrivilegeCount = Token->PrivilegeCount;
  1106. LocalStatistics->ModifiedId = Token->ModifiedId;
  1107. SepReleaseTokenReadLock( Token );
  1108. return STATUS_SUCCESS;
  1109. }
  1110. default:
  1111. return STATUS_INVALID_INFO_CLASS;
  1112. }
  1113. }