ReactOS 0.4.16-dev-290-g89a3b8f
tokencls.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <ntlsa.h>
Include dependency graph for tokencls.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS NTAPI SeQueryInformationToken (_In_ PACCESS_TOKEN AccessToken, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
 Queries information details about the given token to the call. The difference between NtQueryInformationToken and this routine is that the system call has user mode buffer data probing and additional protection checks whereas this routine doesn't have any of these. The routine is used exclusively in kernel mode.
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken (_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
 Queries a specific type of information in regard of an access token based upon the information class. The calling thread must have specific access rights in order to obtain specific information about the token.
 
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtSetInformationToken (_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _In_reads_bytes_(TokenInformationLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength)
 Sets (modifies) some specific information in regard of an access token. The calling thread must have specific access rights in order to modify token's information data.
 

Variables

static const INFORMATION_CLASS_INFO SeTokenInformationClass []
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file tokencls.c.

Function Documentation

◆ NtQueryInformationToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken ( _In_ HANDLE  TokenHandle,
_In_ TOKEN_INFORMATION_CLASS  TokenInformationClass,
_Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID  TokenInformation,
_In_ ULONG  TokenInformationLength,
_Out_ PULONG  ReturnLength 
)

Queries a specific type of information in regard of an access token based upon the information class. The calling thread must have specific access rights in order to obtain specific information about the token.

Parameters
[in]TokenHandleA handle of a token where information is to be gathered.
[in]TokenInformationClassToken information class.
[out]TokenInformationA returned output buffer with token information, which information is arbitrarily upon the information class chosen.
[in]TokenInformationLengthLength of the token information buffer, in bytes.
[out]ReturnLengthA pointer to a variable provided by the caller that receives the actual length of the buffer pointed by TokenInformation, in bytes. If TokenInformation is NULL and TokenInformationLength is 0, this parameter receives the required length needed to store the buffer information in memory. This parameter must not be NULL!
Returns
Returns STATUS_SUCCESS if information querying has completed successfully. STATUS_BUFFER_TOO_SMALL is returned if the information length that represents the token information buffer is not greater than the required length. STATUS_INVALID_HANDLE is returned if the token handle is not a valid one. STATUS_INVALID_INFO_CLASS is returned if the information class is not a valid one (that is, the class doesn't belong to TOKEN_INFORMATION_CLASS). STATUS_ACCESS_VIOLATION is returned if ReturnLength is NULL. A failure NTSTATUS code is returned otherwise.

Definition at line 473 of file tokencls.c.

480{
485 union
486 {
487 PSID PSid;
488 ULONG Ulong;
489 } Unused;
490
491 PAGED_CODE();
492
494
495 /* Check buffers and class validity */
500 TokenInformation,
503 NULL,
505 if (!NT_SUCCESS(Status))
506 {
507 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status);
508 return Status;
509 }
510
515 (PVOID*)&Token,
516 NULL);
517 if (NT_SUCCESS(Status))
518 {
519 /* Lock the token */
521
522 switch (TokenInformationClass)
523 {
524 case TokenUser:
525 {
526 PTOKEN_USER tu = (PTOKEN_USER)TokenInformation;
527
528 DPRINT("NtQueryInformationToken(TokenUser)\n");
529 RequiredLength = sizeof(TOKEN_USER) +
530 RtlLengthSid(Token->UserAndGroups[0].Sid);
531
533 {
535 {
537 &Token->UserAndGroups[0],
538 RequiredLength - sizeof(TOKEN_USER),
539 &tu->User,
540 (PSID)(tu + 1),
541 &Unused.PSid,
542 &Unused.Ulong);
543 }
544 else
545 {
547 }
548
550 }
552 {
554 }
555 _SEH2_END;
556
557 break;
558 }
559
560 case TokenGroups:
561 {
562 PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
563
564 DPRINT("NtQueryInformationToken(TokenGroups)\n");
565 RequiredLength = sizeof(tg->GroupCount) +
566 RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
567
569 {
571 {
572 ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
573 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
574 PSID Sid = (PSID_AND_ATTRIBUTES)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
575 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
576
577 tg->GroupCount = Token->UserAndGroupCount - 1;
578 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
579 &Token->UserAndGroups[1],
580 SidLen,
581 &tg->Groups[0],
582 Sid,
583 &Unused.PSid,
584 &Unused.Ulong);
585 }
586 else
587 {
589 }
590
592 }
594 {
596 }
597 _SEH2_END;
598
599 break;
600 }
601
602 case TokenPrivileges:
603 {
604 PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)TokenInformation;
605
606 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
607 RequiredLength = sizeof(tp->PrivilegeCount) +
608 (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
609
611 {
613 {
614 tp->PrivilegeCount = Token->PrivilegeCount;
615 RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
616 Token->Privileges,
617 &tp->Privileges[0]);
618 }
619 else
620 {
622 }
623
625 }
627 {
629 }
630 _SEH2_END;
631
632 break;
633 }
634
635 case TokenOwner:
636 {
637 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
638 ULONG SidLen;
639
640 DPRINT("NtQueryInformationToken(TokenOwner)\n");
641 SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
642 RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
643
645 {
647 {
648 to->Owner = (PSID)(to + 1);
649 Status = RtlCopySid(SidLen,
650 to->Owner,
651 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
652 }
653 else
654 {
656 }
657
659 }
661 {
663 }
664 _SEH2_END;
665
666 break;
667 }
668
670 {
671 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
672 ULONG SidLen;
673
674 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
675 SidLen = RtlLengthSid(Token->PrimaryGroup);
676 RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
677
679 {
681 {
682 tpg->PrimaryGroup = (PSID)(tpg + 1);
683 Status = RtlCopySid(SidLen,
684 tpg->PrimaryGroup,
685 Token->PrimaryGroup);
686 }
687 else
688 {
690 }
691
693 }
695 {
697 }
698 _SEH2_END;
699
700 break;
701 }
702
703 case TokenDefaultDacl:
704 {
705 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
706
707 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
709
710 if (Token->DefaultDacl != NULL)
711 RequiredLength += Token->DefaultDacl->AclSize;
712
714 {
716 {
717 if (Token->DefaultDacl != NULL)
718 {
719 tdd->DefaultDacl = (PACL)(tdd + 1);
721 Token->DefaultDacl,
722 Token->DefaultDacl->AclSize);
723 }
724 else
725 {
726 tdd->DefaultDacl = NULL;
727 }
728 }
729 else
730 {
732 }
733
735 }
737 {
739 }
740 _SEH2_END;
741
742 break;
743 }
744
745 case TokenSource:
746 {
747 PTOKEN_SOURCE ts = (PTOKEN_SOURCE)TokenInformation;
748
749 DPRINT("NtQueryInformationToken(TokenSource)\n");
751
753 {
755 {
756 *ts = Token->TokenSource;
757 }
758 else
759 {
761 }
762
764 }
766 {
768 }
769 _SEH2_END;
770
771 break;
772 }
773
774 case TokenType:
775 {
776 PTOKEN_TYPE tt = (PTOKEN_TYPE)TokenInformation;
777
778 DPRINT("NtQueryInformationToken(TokenType)\n");
779 RequiredLength = sizeof(TOKEN_TYPE);
780
782 {
784 {
785 *tt = Token->TokenType;
786 }
787 else
788 {
790 }
791
793 }
795 {
797 }
798 _SEH2_END;
799
800 break;
801 }
802
804 {
806
807 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
808
809 /* Fail if the token is not an impersonation token */
810 if (Token->TokenType != TokenImpersonation)
811 {
813 break;
814 }
815
817
819 {
821 {
822 *sil = Token->ImpersonationLevel;
823 }
824 else
825 {
827 }
828
830 }
832 {
834 }
835 _SEH2_END;
836
837 break;
838 }
839
840 case TokenStatistics:
841 {
842 PTOKEN_STATISTICS ts = (PTOKEN_STATISTICS)TokenInformation;
843
844 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
846
848 {
850 {
851 ts->TokenId = Token->TokenId;
852 ts->AuthenticationId = Token->AuthenticationId;
853 ts->ExpirationTime = Token->ExpirationTime;
854 ts->TokenType = Token->TokenType;
855 ts->ImpersonationLevel = Token->ImpersonationLevel;
856 ts->DynamicCharged = Token->DynamicCharged;
857 ts->DynamicAvailable = SepComputeAvailableDynamicSpace(Token->DynamicCharged, Token->PrimaryGroup, Token->DefaultDacl);
858 ts->GroupCount = Token->UserAndGroupCount - 1;
859 ts->PrivilegeCount = Token->PrivilegeCount;
860 ts->ModifiedId = Token->ModifiedId;
861 }
862 else
863 {
865 }
866
868 }
870 {
872 }
873 _SEH2_END;
874
875 break;
876 }
877
878 case TokenOrigin:
879 {
880 PTOKEN_ORIGIN to = (PTOKEN_ORIGIN)TokenInformation;
881
882 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
884
886 {
888 {
889 to->OriginatingLogonSession = Token->AuthenticationId;
890 }
891 else
892 {
894 }
895
897 }
899 {
901 }
902 _SEH2_END;
903
904 break;
905 }
906
908 {
909 PSID Sid, RestrictedSid;
910 ULONG SidLen, RestrictedSidLen;
911 ULONG UserGroupLength, RestrictedSidLength, PrivilegeLength;
912 PTOKEN_GROUPS_AND_PRIVILEGES GroupsAndPrivs = (PTOKEN_GROUPS_AND_PRIVILEGES)TokenInformation;
913
914 DPRINT("NtQueryInformationToken(TokenGroupsAndPrivileges)\n");
915 UserGroupLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount, Token->UserAndGroups);
916 RestrictedSidLength = RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
917 PrivilegeLength = Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
918
920 UserGroupLength + RestrictedSidLength + PrivilegeLength;
921
923 {
925 {
926 GroupsAndPrivs->SidCount = Token->UserAndGroupCount;
927 GroupsAndPrivs->SidLength = UserGroupLength;
928 GroupsAndPrivs->Sids = (PSID_AND_ATTRIBUTES)(GroupsAndPrivs + 1);
929
930 Sid = (PSID)((ULONG_PTR)GroupsAndPrivs->Sids + (Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES)));
931 SidLen = UserGroupLength - (Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES));
932 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount,
933 Token->UserAndGroups,
934 SidLen,
935 GroupsAndPrivs->Sids,
936 Sid,
937 &Unused.PSid,
938 &Unused.Ulong);
940
941 GroupsAndPrivs->RestrictedSidCount = Token->RestrictedSidCount;
942 GroupsAndPrivs->RestrictedSidLength = RestrictedSidLength;
943 GroupsAndPrivs->RestrictedSids = NULL;
945 {
946 GroupsAndPrivs->RestrictedSids = (PSID_AND_ATTRIBUTES)((ULONG_PTR)GroupsAndPrivs->Sids + UserGroupLength);
947
948 RestrictedSid = (PSID)((ULONG_PTR)GroupsAndPrivs->RestrictedSids + (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
949 RestrictedSidLen = RestrictedSidLength - (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
950 Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
951 Token->RestrictedSids,
952 RestrictedSidLen,
953 GroupsAndPrivs->RestrictedSids,
954 RestrictedSid,
955 &Unused.PSid,
956 &Unused.Ulong);
958 }
959
960 GroupsAndPrivs->PrivilegeCount = Token->PrivilegeCount;
961 GroupsAndPrivs->PrivilegeLength = PrivilegeLength;
962 GroupsAndPrivs->Privileges = (PLUID_AND_ATTRIBUTES)((ULONG_PTR)(GroupsAndPrivs + 1) +
963 UserGroupLength + RestrictedSidLength);
964 RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
965 Token->Privileges,
966 GroupsAndPrivs->Privileges);
967
968 GroupsAndPrivs->AuthenticationId = Token->AuthenticationId;
969 }
970 else
971 {
973 }
974
976 }
978 {
980 }
981 _SEH2_END;
982
983 break;
984 }
985
987 {
988 PTOKEN_GROUPS tg = (PTOKEN_GROUPS)TokenInformation;
989
990 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
991 RequiredLength = sizeof(tg->GroupCount) +
992 RtlLengthSidAndAttributes(Token->RestrictedSidCount, Token->RestrictedSids);
993
995 {
997 {
998 ULONG SidLen = RequiredLength - sizeof(tg->GroupCount) -
999 (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
1000 PSID Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
1001 (Token->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES)));
1002
1003 tg->GroupCount = Token->RestrictedSidCount;
1004 Status = RtlCopySidAndAttributesArray(Token->RestrictedSidCount,
1005 Token->RestrictedSids,
1006 SidLen,
1007 &tg->Groups[0],
1008 Sid,
1009 &Unused.PSid,
1010 &Unused.Ulong);
1011 }
1012 else
1013 {
1015 }
1016
1018 }
1020 {
1022 }
1023 _SEH2_END;
1024
1025 break;
1026 }
1027
1028 case TokenSandBoxInert:
1029 {
1030 ULONG IsTokenSandBoxInert;
1031
1032 DPRINT("NtQueryInformationToken(TokenSandBoxInert)\n");
1033
1034 IsTokenSandBoxInert = SeTokenIsInert(Token);
1035 _SEH2_TRY
1036 {
1037 /* Buffer size was already verified, no need to check here again */
1038 *(PULONG)TokenInformation = IsTokenSandBoxInert;
1039 *ReturnLength = sizeof(ULONG);
1040 }
1042 {
1044 }
1045 _SEH2_END;
1046
1047 break;
1048 }
1049
1050 case TokenSessionId:
1051 {
1052 ULONG SessionId = 0;
1053
1054 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1055
1057 if (NT_SUCCESS(Status))
1058 {
1059 _SEH2_TRY
1060 {
1061 /* Buffer size was already verified, no need to check here again */
1062 *(PULONG)TokenInformation = SessionId;
1064 }
1066 {
1068 }
1069 _SEH2_END;
1070 }
1071
1072 break;
1073 }
1074
1075 default:
1076 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
1078 break;
1079 }
1080
1081 /* Unlock and dereference the token */
1084 }
1085
1086 return Status;
1087}
#define PAGED_CODE()
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
TOKEN_TYPE
Definition: asmpp.cpp:29
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG SessionId
Definition: dllmain.c:28
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define ExGetPreviousMode
Definition: ex.h:140
Status
Definition: gdiplustypes.h:25
#define ICIF_FORCE_RETURN_LENGTH_PROBE
Definition: icif.h:26
#define ICIF_PROBE_READ_WRITE
Definition: icif.h:24
NTSYSAPI BOOLEAN WINAPI RtlCopySid(DWORD, PSID, PSID)
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define Unused(x)
Definition: atlwin.h:28
enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL
enum _SECURITY_IMPERSONATION_LEVEL * PSECURITY_IMPERSONATION_LEVEL
struct _TOKEN_SOURCE * PTOKEN_SOURCE
@ TokenImpersonation
Definition: imports.h:274
struct _TOKEN_SOURCE TOKEN_SOURCE
struct _SID * PSID
Definition: eventlog.c:35
struct _ACL * PACL
Definition: security.c:105
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:726
NTSYSAPI VOID NTAPI RtlCopyLuidAndAttributesArray(ULONG Count, PLUID_AND_ATTRIBUTES Src, PLUID_AND_ATTRIBUTES Dest)
Definition: luid.c:33
NTSYSAPI NTSTATUS NTAPI RtlCopySidAndAttributesArray(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src, _In_ ULONG SidAreaSize, _In_ PSID_AND_ATTRIBUTES Dest, _In_ PSID SidArea, _Out_ PSID *RemainingSidArea, _Out_ PULONG RemainingSidAreaSize)
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1145
_In_ TOKEN_INFORMATION_CLASS TokenInformationClass
Definition: sefuncs.h:317
_In_ TOKEN_INFORMATION_CLASS _In_ ULONG TokenInformationLength
Definition: sefuncs.h:319
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:411
static __inline NTSTATUS DefaultQueryInfoBufferCheck(_In_ ULONG Class, _In_ const INFORMATION_CLASS_INFO *ClassList, _In_ ULONG ClassListEntries, _In_ ULONG Flags, _In_opt_ PVOID Buffer, _In_ ULONG BufferLength, _In_opt_ PULONG ReturnLength, _In_opt_ PULONG_PTR ReturnLengthPtr, _In_ KPROCESSOR_MODE PreviousMode)
Probe helper that validates the provided parameters whenever a NtQuery*** system call is invoked from...
Definition: probe.h:219
BOOLEAN NTAPI SeTokenIsInert(_In_ PTOKEN Token)
Determines if a token is a sandbox inert token or not, based upon the token flags.
Definition: token.c:1583
#define SepAcquireTokenLockShared(Token)
Definition: se.h:290
ULONG RtlLengthSidAndAttributes(_In_ ULONG Count, _In_ PSID_AND_ATTRIBUTES Src)
Computes the length size of a SID.
Definition: token.c:965
ULONG SepComputeAvailableDynamicSpace(_In_ ULONG DynamicCharged, _In_ PSID PrimaryGroup, _In_opt_ PACL DefaultDacl)
Computes the exact available dynamic area of an access token whilst querying token statistics.
Definition: token.c:659
#define SepReleaseTokenLock(Token)
Definition: se.h:296
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
NTSTATUS NTAPI SeQuerySessionIdToken(_In_ PACCESS_TOKEN Token, _Out_ PULONG pSessionId)
Queries the session ID of an access token.
Definition: token.c:2004
BOOLEAN NTAPI SeTokenIsRestricted(_In_ PACCESS_TOKEN Token)
Determines if a token is restricted or not, based upon the token flags.
Definition: token.c:2126
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
PSID_AND_ATTRIBUTES Sids
Definition: setypes.h:1042
PSID_AND_ATTRIBUTES RestrictedSids
Definition: setypes.h:1045
PLUID_AND_ATTRIBUTES Privileges
Definition: setypes.h:1048
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:1018
$ULONG GroupCount
Definition: setypes.h:1014
LUID OriginatingLogonSession
Definition: setypes.h:1107
PSID Owner
Definition: setypes.h:1028
LUID AuthenticationId
Definition: setypes.h:1087
TOKEN_TYPE TokenType
Definition: setypes.h:1089
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:1090
LARGE_INTEGER ExpirationTime
Definition: setypes.h:1088
$ULONG DynamicAvailable
Definition: setypes.h:1092
$ULONG PrivilegeCount
Definition: setypes.h:1094
$ULONG DynamicCharged
Definition: setypes.h:1091
$ULONG GroupCount
Definition: setypes.h:1093
SID_AND_ATTRIBUTES User
Definition: setypes.h:1010
static const INFORMATION_CLASS_INFO SeTokenInformationClass[]
Definition: tokencls.c:19
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
unsigned long Ulong
Definition: utypes.h:42
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NT_ASSERT
Definition: rtlfuncs.h:3327
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define TOKEN_QUERY_SOURCE
Definition: setypes.h:929
struct _TOKEN_PRIMARY_GROUP TOKEN_PRIMARY_GROUP
struct _SID_AND_ATTRIBUTES * PSID_AND_ATTRIBUTES
Definition: security.c:130
struct _TOKEN_GROUPS * PTOKEN_GROUPS
struct _TOKEN_PRIMARY_GROUP * PTOKEN_PRIMARY_GROUP
struct _TOKEN_USER TOKEN_USER
struct _TOKEN_STATISTICS * PTOKEN_STATISTICS
struct _TOKEN_DEFAULT_DACL * PTOKEN_DEFAULT_DACL
struct _TOKEN_USER * PTOKEN_USER
struct _TOKEN_ORIGIN TOKEN_ORIGIN
struct _TOKEN_ORIGIN * PTOKEN_ORIGIN
#define TOKEN_QUERY
Definition: setypes.h:928
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES
struct _TOKEN_GROUPS_AND_PRIVILEGES * PTOKEN_GROUPS_AND_PRIVILEGES
struct _LUID_AND_ATTRIBUTES * PLUID_AND_ATTRIBUTES
@ TokenDefaultDacl
Definition: setypes.h:971
@ TokenGroupsAndPrivileges
Definition: setypes.h:978
@ TokenSource
Definition: setypes.h:972
@ TokenStatistics
Definition: setypes.h:975
@ TokenImpersonationLevel
Definition: setypes.h:974
@ TokenSandBoxInert
Definition: setypes.h:980
@ TokenRestrictedSids
Definition: setypes.h:976
@ TokenGroups
Definition: setypes.h:967
@ TokenPrivileges
Definition: setypes.h:968
@ TokenUser
Definition: setypes.h:966
@ TokenOrigin
Definition: setypes.h:982
@ TokenPrimaryGroup
Definition: setypes.h:970
@ TokenSessionId
Definition: setypes.h:977
@ TokenOwner
Definition: setypes.h:969
struct _TOKEN_STATISTICS TOKEN_STATISTICS
struct _TOKEN_PRIVILEGES * PTOKEN_PRIVILEGES
struct _SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES
enum _TOKEN_TYPE * PTOKEN_TYPE
struct _TOKEN_DEFAULT_DACL TOKEN_DEFAULT_DACL
struct _TOKEN_GROUPS_AND_PRIVILEGES TOKEN_GROUPS_AND_PRIVILEGES
struct _TOKEN_OWNER TOKEN_OWNER
struct _TOKEN_OWNER * PTOKEN_OWNER

Referenced by CreateDefaultProcessSecurityCommon(), CreateProcessAsUserCommon(), CsrGetProcessLuid(), CsrSetProcessSecurity(), DoAdminUnlock(), DuplicateTokenAsEffective(), GetCallerLuid(), GetSiteSidFromToken(), GetTokenInformation(), GetUserSid(), GetUserSidStringFromToken(), ImpersonateLoggedOnUser(), IsTokenRestricted(), LsapIsTrustedClient(), QueryOriginalDefaultDacl(), QueryTokenDefaultDaclTests(), QueryTokenGroupsTests(), QueryTokenImpersonationTests(), QueryTokenIsSandboxInert(), QueryTokenOriginTests(), QueryTokenOwnerTests(), QueryTokenPrimaryGroupTests(), QueryTokenPrivilegesAndGroupsTests(), QueryTokenPrivilegesTests(), QueryTokenRestrictedSidsTest(), QueryTokenSessionIdTests(), QueryTokenSourceTests(), QueryTokenStatisticsTests(), QueryTokenTypeTests(), QueryTokenUserTests(), RegOpenUserClassesRoot(), RtlDefaultNpAcl(), RtlNewInstanceSecurityObject(), RtlNewSecurityGrantedAccess(), and START_TEST().

◆ NtSetInformationToken()

_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtSetInformationToken ( _In_ HANDLE  TokenHandle,
_In_ TOKEN_INFORMATION_CLASS  TokenInformationClass,
_In_reads_bytes_(TokenInformationLength) PVOID  TokenInformation,
_In_ ULONG  TokenInformationLength 
)

Sets (modifies) some specific information in regard of an access token. The calling thread must have specific access rights in order to modify token's information data.

@unimplemented

Parameters
[in]TokenHandleA handle of a token where information is to be modified.
[in]TokenInformationClassToken information class.
[in]TokenInformationAn arbitrary pointer to a buffer with token information to set. Such arbitrary buffer depends on the information class chosen that the caller wants to modify such information data of a token.
[in]TokenInformationLengthLength of the token information buffer, in bytes.
Returns
Returns STATUS_SUCCESS if information setting has completed successfully. STATUS_INFO_LENGTH_MISMATCH is returned if the information length of the buffer is less than the required length. STATUS_INSUFFICIENT_RESOURCES is returned if memory pool allocation has failed. STATUS_PRIVILEGE_NOT_HELD is returned if the calling thread hasn't the required privileges to perform the operation in question. A failure NTSTATUS code is returned otherwise.
Remarks
The function is partly implemented, mainly TokenOrigin.

Definition at line 1125 of file tokencls.c.

1130{
1132 PTOKEN Token;
1134 ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
1135
1136 PAGED_CODE();
1137
1139
1143 TokenInformation,
1145 PreviousMode);
1146 if (!NT_SUCCESS(Status))
1147 {
1148 /* Invalid buffers */
1149 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status);
1150 return Status;
1151 }
1152
1154 {
1155 NeededAccess |= TOKEN_ADJUST_SESSIONID;
1156 }
1157
1159 NeededAccess,
1162 (PVOID*)&Token,
1163 NULL);
1164 if (NT_SUCCESS(Status))
1165 {
1166 switch (TokenInformationClass)
1167 {
1168 case TokenOwner:
1169 {
1170 if (TokenInformationLength >= sizeof(TOKEN_OWNER))
1171 {
1172 PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
1173 PSID InputSid = NULL, CapturedSid;
1174 ULONG DefaultOwnerIndex;
1175
1176 _SEH2_TRY
1177 {
1178 InputSid = to->Owner;
1179 }
1181 {
1183 _SEH2_YIELD(goto Cleanup);
1184 }
1185 _SEH2_END;
1186
1187 Status = SepCaptureSid(InputSid,
1189 PagedPool,
1190 FALSE,
1191 &CapturedSid);
1192 if (NT_SUCCESS(Status))
1193 {
1194 /* Lock the token */
1196
1197 /* Find the owner amongst the existing token user and groups */
1199 NULL,
1200 CapturedSid,
1201 NULL,
1202 &DefaultOwnerIndex);
1203 if (NT_SUCCESS(Status))
1204 {
1205 /* Found it */
1206 Token->DefaultOwnerIndex = DefaultOwnerIndex;
1207 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1208 }
1209
1210 /* Unlock the token */
1212
1213 SepReleaseSid(CapturedSid,
1215 FALSE);
1216 }
1217 }
1218 else
1219 {
1221 }
1222 break;
1223 }
1224
1225 case TokenPrimaryGroup:
1226 {
1228 {
1229 PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
1230 ULONG AclSize;
1232 PSID InputSid = NULL, CapturedSid;
1233 ULONG PrimaryGroupIndex, NewDynamicLength;
1234
1235 _SEH2_TRY
1236 {
1237 InputSid = tpg->PrimaryGroup;
1238 }
1240 {
1242 _SEH2_YIELD(goto Cleanup);
1243 }
1244 _SEH2_END;
1245
1246 Status = SepCaptureSid(InputSid,
1248 PagedPool,
1249 FALSE,
1250 &CapturedSid);
1251 if (NT_SUCCESS(Status))
1252 {
1253 /* Lock the token */
1255
1256 /*
1257 * We can whack the token's primary group only if
1258 * the charged dynamic space boundary allows us
1259 * to do so. Exceeding this boundary and we're
1260 * busted out.
1261 */
1262 AclSize = Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0;
1263 NewDynamicLength = RtlLengthSid(CapturedSid) + AclSize;
1264 if (NewDynamicLength > Token->DynamicCharged)
1265 {
1267 SepReleaseSid(CapturedSid, PreviousMode, FALSE);
1269 DPRINT1("NtSetInformationToken(): Couldn't assign new primary group, space exceeded (current length %u, new length %lu)\n",
1270 Token->DynamicCharged, NewDynamicLength);
1271 goto Cleanup;
1272 }
1273
1274 /*
1275 * The dynamic part of the token may require a rebuild
1276 * if the current dynamic area is too small. If not then
1277 * we're pretty much good as is.
1278 */
1279 Status = SepRebuildDynamicPartOfToken(Token, NewDynamicLength);
1280 if (NT_SUCCESS(Status))
1281 {
1282 /* Find the primary group amongst the existing token user and groups */
1284 CapturedSid,
1285 NULL,
1286 &PrimaryGroupIndex,
1287 NULL);
1288 if (NT_SUCCESS(Status))
1289 {
1290 /*
1291 * We have found it. Add the length of
1292 * the previous primary group SID to the
1293 * available dynamic area.
1294 */
1295 Token->DynamicAvailable += RtlLengthSid(Token->PrimaryGroup);
1296
1297 /*
1298 * Move the default DACL if it's not at the
1299 * head of the dynamic part.
1300 */
1301 if ((Token->DefaultDacl) &&
1302 ((PULONG)(Token->DefaultDacl) != Token->DynamicPart))
1303 {
1304 RtlMoveMemory(Token->DynamicPart,
1305 Token->DefaultDacl,
1306 RtlLengthSid(Token->PrimaryGroup));
1307 Token->DefaultDacl = (PACL)(Token->DynamicPart);
1308 }
1309
1310 /* Take away available space from the dynamic area */
1311 Token->DynamicAvailable -= RtlLengthSid(Token->UserAndGroups[PrimaryGroupIndex].Sid);
1312
1313 /*
1314 * And assign the new primary group. For that
1315 * we have to make sure where the primary group
1316 * is going to stay in memory, so if this token
1317 * has a default DACL then add up its size with
1318 * the address of the dynamic part.
1319 */
1320 PrimaryGroup = (ULONG_PTR)(Token->DynamicPart) + AclSize;
1321 RtlCopySid(RtlLengthSid(Token->UserAndGroups[PrimaryGroupIndex].Sid),
1323 Token->UserAndGroups[PrimaryGroupIndex].Sid);
1324 Token->PrimaryGroup = (PSID)PrimaryGroup;
1325
1326 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1327 }
1328 }
1329
1330 /* Unlock the token */
1332
1333 SepReleaseSid(CapturedSid,
1335 FALSE);
1336 }
1337 }
1338 else
1339 {
1341 }
1342 break;
1343 }
1344
1345 case TokenDefaultDacl:
1346 {
1348 {
1349 PTOKEN_DEFAULT_DACL tdd = (PTOKEN_DEFAULT_DACL)TokenInformation;
1350 PACL InputAcl = NULL;
1351
1352 _SEH2_TRY
1353 {
1354 InputAcl = tdd->DefaultDacl;
1355 }
1357 {
1359 _SEH2_YIELD(goto Cleanup);
1360 }
1361 _SEH2_END;
1362
1363 if (InputAcl != NULL)
1364 {
1365 PACL CapturedAcl;
1366
1367 /* Capture, validate, and copy the DACL */
1368 Status = SepCaptureAcl(InputAcl,
1370 PagedPool,
1371 TRUE,
1372 &CapturedAcl);
1373 if (NT_SUCCESS(Status))
1374 {
1375 ULONG NewDynamicLength;
1376 ULONG_PTR Acl;
1377
1378 /* Lock the token */
1380
1381 /*
1382 * We can whack the token's default DACL only if
1383 * the charged dynamic space boundary allows us
1384 * to do so. Exceeding this boundary and we're
1385 * busted out.
1386 */
1387 NewDynamicLength = CapturedAcl->AclSize + RtlLengthSid(Token->PrimaryGroup);
1388 if (NewDynamicLength > Token->DynamicCharged)
1389 {
1391 SepReleaseAcl(CapturedAcl, PreviousMode, TRUE);
1393 DPRINT1("NtSetInformationToken(): Couldn't assign new default DACL, space exceeded (current length %u, new length %lu)\n",
1394 Token->DynamicCharged, NewDynamicLength);
1395 goto Cleanup;
1396 }
1397
1398 /*
1399 * The dynamic part of the token may require a rebuild
1400 * if the current dynamic area is too small. If not then
1401 * we're pretty much good as is.
1402 */
1403 Status = SepRebuildDynamicPartOfToken(Token, NewDynamicLength);
1404 if (NT_SUCCESS(Status))
1405 {
1406 /*
1407 * Before setting up a new DACL for the
1408 * token object we add up the size of
1409 * the old DACL to the available dynamic
1410 * area
1411 */
1412 if (Token->DefaultDacl)
1413 {
1414 Token->DynamicAvailable += Token->DefaultDacl->AclSize;
1415 }
1416
1417 /*
1418 * Move the primary group if it's not at the
1419 * head of the dynamic part.
1420 */
1421 if ((PULONG)(Token->PrimaryGroup) != Token->DynamicPart)
1422 {
1423 RtlMoveMemory(Token->DynamicPart,
1424 Token->PrimaryGroup,
1425 RtlLengthSid(Token->PrimaryGroup));
1426 Token->PrimaryGroup = (PSID)(Token->DynamicPart);
1427 }
1428
1429 /* Take away available space from the dynamic area */
1430 Token->DynamicAvailable -= CapturedAcl->AclSize;
1431
1432 /* Set the new dacl */
1433 Acl = (ULONG_PTR)(Token->DynamicPart) + RtlLengthSid(Token->PrimaryGroup);
1434 RtlCopyMemory((PVOID)Acl,
1435 CapturedAcl,
1436 CapturedAcl->AclSize);
1437 Token->DefaultDacl = (PACL)Acl;
1438
1439 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1440 }
1441
1442 /* Unlock the token and release the ACL */
1444 SepReleaseAcl(CapturedAcl, PreviousMode, TRUE);
1445 }
1446 }
1447 else
1448 {
1449 /* Lock the token */
1451
1452 /* Clear the default dacl if present */
1453 if (Token->DefaultDacl != NULL)
1454 {
1455 Token->DynamicAvailable += Token->DefaultDacl->AclSize;
1456 RtlZeroMemory(Token->DefaultDacl, Token->DefaultDacl->AclSize);
1457 Token->DefaultDacl = NULL;
1458
1459 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1460 }
1461
1462 /* Unlock the token */
1464 }
1465 }
1466 else
1467 {
1469 }
1470 break;
1471 }
1472
1473 case TokenSessionId:
1474 {
1475 ULONG SessionId = 0;
1476
1477 _SEH2_TRY
1478 {
1479 /* Buffer size was already verified, no need to check here again */
1480 SessionId = *(PULONG)TokenInformation;
1481 }
1483 {
1485 _SEH2_YIELD(goto Cleanup);
1486 }
1487 _SEH2_END;
1488
1489 /* Check for TCB privilege */
1491 {
1493 break;
1494 }
1495
1496 /* Lock the token */
1498
1499 Token->SessionId = SessionId;
1500 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1501
1502 /* Unlock the token */
1504
1505 break;
1506 }
1507
1509 {
1510 ULONG SessionReference;
1511
1512 _SEH2_TRY
1513 {
1514 /* Buffer size was already verified, no need to check here again */
1515 SessionReference = *(PULONG)TokenInformation;
1516 }
1518 {
1520 _SEH2_YIELD(goto Cleanup);
1521 }
1522 _SEH2_END;
1523
1524 /* Check for TCB privilege */
1526 {
1528 goto Cleanup;
1529 }
1530
1531 /* Check if it is 0 */
1532 if (SessionReference == 0)
1533 {
1534 ULONG OldTokenFlags;
1535
1536 /* Lock the token */
1538
1539 /* Atomically set the flag in the token */
1540 OldTokenFlags = RtlInterlockedSetBits(&Token->TokenFlags,
1542 /*
1543 * If the flag was already set, do not dereference again
1544 * the logon session. Use SessionReference as an indicator
1545 * to know whether to really dereference the session.
1546 */
1547 if (OldTokenFlags == Token->TokenFlags)
1548 SessionReference = ULONG_MAX;
1549
1550 /*
1551 * Otherwise if the flag was never set but just for this first time then
1552 * remove the referenced logon session data from the token and dereference
1553 * the logon session when needed.
1554 */
1555 if (SessionReference == 0)
1556 {
1558 SepRmDereferenceLogonSession(&Token->AuthenticationId);
1559 }
1560
1561 /* Unlock the token */
1563 }
1564 break;
1565 }
1566
1567 case TokenAuditPolicy:
1568 {
1569 PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation =
1570 (PTOKEN_AUDIT_POLICY_INFORMATION)TokenInformation;
1571 SEP_AUDIT_POLICY AuditPolicy;
1572 ULONG i;
1573
1574 _SEH2_TRY
1575 {
1576 ProbeForRead(PolicyInformation,
1578 Policies[PolicyInformation->PolicyCount]),
1579 sizeof(ULONG));
1580
1581 /* Loop all policies in the structure */
1582 for (i = 0; i < PolicyInformation->PolicyCount; i++)
1583 {
1584 /* Set the corresponding bits in the packed structure */
1585 switch (PolicyInformation->Policies[i].Category)
1586 {
1588 AuditPolicy.PolicyElements.System = PolicyInformation->Policies[i].Value;
1589 break;
1590
1591 case AuditCategoryLogon:
1592 AuditPolicy.PolicyElements.Logon = PolicyInformation->Policies[i].Value;
1593 break;
1594
1596 AuditPolicy.PolicyElements.ObjectAccess = PolicyInformation->Policies[i].Value;
1597 break;
1598
1600 AuditPolicy.PolicyElements.PrivilegeUse = PolicyInformation->Policies[i].Value;
1601 break;
1602
1604 AuditPolicy.PolicyElements.DetailedTracking = PolicyInformation->Policies[i].Value;
1605 break;
1606
1608 AuditPolicy.PolicyElements.PolicyChange = PolicyInformation->Policies[i].Value;
1609 break;
1610
1612 AuditPolicy.PolicyElements.AccountManagement = PolicyInformation->Policies[i].Value;
1613 break;
1614
1616 AuditPolicy.PolicyElements.DirectoryServiceAccess = PolicyInformation->Policies[i].Value;
1617 break;
1618
1620 AuditPolicy.PolicyElements.AccountLogon = PolicyInformation->Policies[i].Value;
1621 break;
1622 }
1623 }
1624 }
1626 {
1628 _SEH2_YIELD(goto Cleanup);
1629 }
1630 _SEH2_END;
1631
1632 /* Check for TCB privilege */
1634 {
1636 break;
1637 }
1638
1639 /* Lock the token */
1641
1642 /* Set the new audit policy */
1643 Token->AuditPolicy = AuditPolicy;
1644 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1645
1646 /* Unlock the token */
1648
1649 break;
1650 }
1651
1652 case TokenOrigin:
1653 {
1655
1656 _SEH2_TRY
1657 {
1658 /* Copy the token origin */
1659 TokenOrigin = *(PTOKEN_ORIGIN)TokenInformation;
1660 }
1662 {
1664 _SEH2_YIELD(goto Cleanup);
1665 }
1666 _SEH2_END;
1667
1668 /* Check for TCB privilege */
1670 {
1672 break;
1673 }
1674
1675 /* Lock the token */
1677
1678 /* Check if there is no token origin set yet */
1679 if (RtlIsZeroLuid(&Token->OriginatingLogonSession))
1680 {
1681 /* Set the token origin */
1682 Token->OriginatingLogonSession =
1683 TokenOrigin.OriginatingLogonSession;
1684
1685 ExAllocateLocallyUniqueId(&Token->ModifiedId);
1686 }
1687
1688 /* Unlock the token */
1690
1691 break;
1692 }
1693
1694 default:
1695 {
1696 DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
1699 break;
1700 }
1701 }
1702Cleanup:
1704 }
1705
1706 if (!NT_SUCCESS(Status))
1707 {
1708 DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status);
1709 }
1710
1711 return Status;
1712}
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR Cleanup[]
Definition: register.c:80
#define ULONG_PTR
Definition: config.h:101
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ULONG_MAX
Definition: intsafe.h:155
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID _Inout_ PULONG _Out_writes_bytes_to_opt_ PrimaryGroupSize PSID PrimaryGroup
Definition: rtlfuncs.h:1611
VOID NTAPI ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
Definition: uuid.c:335
static __inline NTSTATUS DefaultSetInfoBufferCheck(_In_ ULONG Class, _In_ const INFORMATION_CLASS_INFO *ClassList, _In_ ULONG ClassListEntries, _In_ PVOID Buffer, _In_ ULONG BufferLength, _In_ KPROCESSOR_MODE PreviousMode)
Probe helper that validates the provided parameters whenever a NtSet*** system call is invoked from u...
Definition: probe.h:70
NTSTATUS NTAPI SepRmRemoveLogonSessionFromToken(_Inout_ PTOKEN Token)
Removes a logon session from an access token.
Definition: srm.c:449
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:400
NTSTATUS SepRmDereferenceLogonSession(_Inout_ PLUID LogonLuid)
NTSTATUS NTAPI SepCaptureSid(_In_ PSID InputSid, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID *CapturedSid)
Captures a SID.
Definition: sid.c:314
NTSTATUS SepFindPrimaryGroupAndDefaultOwner(_In_ PTOKEN Token, _In_ PSID PrimaryGroup, _In_opt_ PSID DefaultOwner, _Out_opt_ PULONG PrimaryGroupIndex, _Out_opt_ PULONG DefaultOwnerIndex)
Finds the primary group and default owner entity based on the submitted primary group instance and an...
Definition: token.c:1011
VOID NTAPI SepReleaseAcl(_In_ PACL CapturedAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases (frees) a captured ACL from the memory pool.
Definition: acl.c:464
const LUID SeTcbPrivilege
Definition: priv.c:26
#define SepAcquireTokenLockExclusive(Token)
Definition: se.h:285
NTSTATUS NTAPI SepCaptureAcl(_In_ PACL InputAcl, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PACL *CapturedAcl)
Captures an access control list from an already valid input ACL.
Definition: acl.c:352
struct _TOKEN_AUDIT_POLICY_INFORMATION * PTOKEN_AUDIT_POLICY_INFORMATION
NTSTATUS SepRebuildDynamicPartOfToken(_In_ PTOKEN Token, _In_ ULONG NewDynamicPartSize)
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
@ AuditCategoryLogon
Definition: ntsecapi.h:261
@ AuditCategoryAccountManagement
Definition: ntsecapi.h:266
@ AuditCategoryAccountLogon
Definition: ntsecapi.h:268
@ AuditCategoryPolicyChange
Definition: ntsecapi.h:265
@ AuditCategorySystem
Definition: ntsecapi.h:260
@ AuditCategoryObjectAccess
Definition: ntsecapi.h:262
@ AuditCategoryDirectoryServiceAccess
Definition: ntsecapi.h:267
@ AuditCategoryDetailedTracking
Definition: ntsecapi.h:264
@ AuditCategoryPrivilegeUse
Definition: ntsecapi.h:263
#define STATUS_ALLOTTED_SPACE_EXCEEDED
Definition: ntstatus.h:389
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
USHORT AclSize
Definition: ms-dtyp.idl:296
SEP_AUDIT_POLICY_CATEGORIES PolicyElements
Definition: setypes.h:158
struct _TOKEN_AUDIT_POLICY_INFORMATION::@1814 Policies[1]
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define RtlIsZeroLuid(_L1)
Definition: rtlfuncs.h:764
#define RtlInterlockedSetBits(Flags, Flag)
Definition: rtlfuncs.h:3451
#define TOKEN_SESSION_NOT_REFERENCED
Definition: setypes.h:1184
#define TOKEN_ADJUST_SESSIONID
Definition: setypes.h:933
@ TokenAuditPolicy
Definition: setypes.h:981
@ TokenSessionReference
Definition: setypes.h:979
#define TOKEN_ADJUST_DEFAULT
Definition: setypes.h:932

Referenced by SetTokenDefaultDaclTests(), SetTokenInformation(), SetTokenSessionIdTests(), and START_TEST().

◆ SeQueryInformationToken()

NTSTATUS NTAPI SeQueryInformationToken ( _In_ PACCESS_TOKEN  AccessToken,
_In_ TOKEN_INFORMATION_CLASS  TokenInformationClass,
_Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID TokenInformation 
)

Queries information details about the given token to the call. The difference between NtQueryInformationToken and this routine is that the system call has user mode buffer data probing and additional protection checks whereas this routine doesn't have any of these. The routine is used exclusively in kernel mode.

Parameters
[in]AccessTokenAn access token to be given.
[in]TokenInformationClassToken information class.
[out]TokenInformationBuffer with retrieved information. Such information is arbitrary, depending on the requested information class.
Returns
Returns STATUS_SUCCESS if the operation to query the desired information has completed successfully. STATUS_INSUFFICIENT_RESOURCES is returned if pool memory allocation has failed to satisfy an operation. Otherwise STATUS_INVALID_INFO_CLASS is returned indicating that the information class provided is not supported by the routine.
Remarks
Only certain information classes are not implemented in this function and these are TokenOrigin, TokenGroupsAndPrivileges, TokenRestrictedSids and TokenSandBoxInert. The following classes are implemented in NtQueryInformationToken only.

Definition at line 95 of file tokencls.c.

99{
101 PTOKEN Token = (PTOKEN)AccessToken;
103 union
104 {
105 PSID PSid;
106 ULONG Ulong;
107 } Unused;
108
109 PAGED_CODE();
110
111 /* Lock the token */
113
114 switch (TokenInformationClass)
115 {
116 case TokenUser:
117 {
118 PTOKEN_USER tu;
119
120 DPRINT("SeQueryInformationToken(TokenUser)\n");
121 RequiredLength = sizeof(TOKEN_USER) +
122 RtlLengthSid(Token->UserAndGroups[0].Sid);
123
124 /* Allocate the output buffer */
126 if (tu == NULL)
127 {
129 break;
130 }
131
133 &Token->UserAndGroups[0],
134 RequiredLength - sizeof(TOKEN_USER),
135 &tu->User,
136 (PSID)(tu + 1),
137 &Unused.PSid,
138 &Unused.Ulong);
139
140 /* Return the structure */
141 *TokenInformation = tu;
143 break;
144 }
145
146 case TokenGroups:
147 {
148 PTOKEN_GROUPS tg;
149 ULONG SidLen;
150 PSID Sid;
151
152 DPRINT("SeQueryInformationToken(TokenGroups)\n");
153 RequiredLength = sizeof(tg->GroupCount) +
154 RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]);
155
156 SidLen = RequiredLength - sizeof(tg->GroupCount) -
157 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES));
158
159 /* Allocate the output buffer */
161 if (tg == NULL)
162 {
164 break;
165 }
166
167 Sid = (PSID)((ULONG_PTR)tg + sizeof(tg->GroupCount) +
168 ((Token->UserAndGroupCount - 1) * sizeof(SID_AND_ATTRIBUTES)));
169
170 tg->GroupCount = Token->UserAndGroupCount - 1;
171 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
172 &Token->UserAndGroups[1],
173 SidLen,
174 &tg->Groups[0],
175 Sid,
176 &Unused.PSid,
177 &Unused.Ulong);
178
179 /* Return the structure */
180 *TokenInformation = tg;
182 break;
183 }
184
185 case TokenPrivileges:
186 {
188
189 DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
190 RequiredLength = sizeof(tp->PrivilegeCount) +
191 (Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
192
193 /* Allocate the output buffer */
195 if (tp == NULL)
196 {
198 break;
199 }
200
201 tp->PrivilegeCount = Token->PrivilegeCount;
202 RtlCopyLuidAndAttributesArray(Token->PrivilegeCount,
203 Token->Privileges,
204 &tp->Privileges[0]);
205
206 /* Return the structure */
207 *TokenInformation = tp;
209 break;
210 }
211
212 case TokenOwner:
213 {
214 PTOKEN_OWNER to;
215 ULONG SidLen;
216
217 DPRINT("SeQueryInformationToken(TokenOwner)\n");
218 SidLen = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
219 RequiredLength = sizeof(TOKEN_OWNER) + SidLen;
220
221 /* Allocate the output buffer */
223 if (to == NULL)
224 {
226 break;
227 }
228
229 to->Owner = (PSID)(to + 1);
230 Status = RtlCopySid(SidLen,
231 to->Owner,
232 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
233
234 /* Return the structure */
235 *TokenInformation = to;
237 break;
238 }
239
241 {
243 ULONG SidLen;
244
245 DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
246 SidLen = RtlLengthSid(Token->PrimaryGroup);
247 RequiredLength = sizeof(TOKEN_PRIMARY_GROUP) + SidLen;
248
249 /* Allocate the output buffer */
251 if (tpg == NULL)
252 {
254 break;
255 }
256
257 tpg->PrimaryGroup = (PSID)(tpg + 1);
258 Status = RtlCopySid(SidLen,
259 tpg->PrimaryGroup,
260 Token->PrimaryGroup);
261
262 /* Return the structure */
263 *TokenInformation = tpg;
265 break;
266 }
267
268 case TokenDefaultDacl:
269 {
271
272 DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
274
275 if (Token->DefaultDacl != NULL)
276 RequiredLength += Token->DefaultDacl->AclSize;
277
278 /* Allocate the output buffer */
280 if (tdd == NULL)
281 {
283 break;
284 }
285
286 if (Token->DefaultDacl != NULL)
287 {
288 tdd->DefaultDacl = (PACL)(tdd + 1);
290 Token->DefaultDacl,
291 Token->DefaultDacl->AclSize);
292 }
293 else
294 {
295 tdd->DefaultDacl = NULL;
296 }
297
298 /* Return the structure */
299 *TokenInformation = tdd;
301 break;
302 }
303
304 case TokenSource:
305 {
306 PTOKEN_SOURCE ts;
307
308 DPRINT("SeQueryInformationToken(TokenSource)\n");
310
311 /* Allocate the output buffer */
313 if (ts == NULL)
314 {
316 break;
317 }
318
319 *ts = Token->TokenSource;
320
321 /* Return the structure */
322 *TokenInformation = ts;
324 break;
325 }
326
327 case TokenType:
328 {
329 PTOKEN_TYPE tt;
330
331 DPRINT("SeQueryInformationToken(TokenType)\n");
332 RequiredLength = sizeof(TOKEN_TYPE);
333
334 /* Allocate the output buffer */
336 if (tt == NULL)
337 {
339 break;
340 }
341
342 *tt = Token->TokenType;
343
344 /* Return the structure */
345 *TokenInformation = tt;
347 break;
348 }
349
351 {
353
354 DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
356
357 /* Fail if the token is not an impersonation token */
358 if (Token->TokenType != TokenImpersonation)
359 {
361 break;
362 }
363
364 /* Allocate the output buffer */
366 if (sil == NULL)
367 {
369 break;
370 }
371
372 *sil = Token->ImpersonationLevel;
373
374 /* Return the structure */
375 *TokenInformation = sil;
377 break;
378 }
379
380 case TokenStatistics:
381 {
383
384 DPRINT("SeQueryInformationToken(TokenStatistics)\n");
386
387 /* Allocate the output buffer */
389 if (ts == NULL)
390 {
392 break;
393 }
394
395 ts->TokenId = Token->TokenId;
396 ts->AuthenticationId = Token->AuthenticationId;
397 ts->ExpirationTime = Token->ExpirationTime;
398 ts->TokenType = Token->TokenType;
399 ts->ImpersonationLevel = Token->ImpersonationLevel;
400 ts->DynamicCharged = Token->DynamicCharged;
401 ts->DynamicAvailable = SepComputeAvailableDynamicSpace(Token->DynamicCharged, Token->PrimaryGroup, Token->DefaultDacl);
402 ts->GroupCount = Token->UserAndGroupCount - 1;
403 ts->PrivilegeCount = Token->PrivilegeCount;
404 ts->ModifiedId = Token->ModifiedId;
405
406 /* Return the structure */
407 *TokenInformation = ts;
409 break;
410 }
411
412 case TokenSessionId:
413 {
414 DPRINT("SeQueryInformationToken(TokenSessionId)\n");
415 Status = SeQuerySessionIdToken(Token, (PULONG)TokenInformation);
416 break;
417 }
418
419 default:
420 DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
422 break;
423 }
424
425 /* Release the lock of the token */
427
428 return Status;
429}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _TOKEN * PTOKEN
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TAG_SE
Definition: tag.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by find_gid(), NtSecureConnectPort(), START_TEST(), and TestsSeQueryInformationToken().

Variable Documentation

◆ SeTokenInformationClass

const INFORMATION_CLASS_INFO SeTokenInformationClass[]
static

Definition at line 19 of file tokencls.c.

Referenced by NtQueryInformationToken(), and NtSetInformationToken().