2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/token.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
10 /* INCLUDES *******************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitializeTokenImplementation)
22 typedef struct _TOKEN_AUDIT_POLICY_INFORMATION
30 } TOKEN_AUDIT_POLICY_INFORMATION
, *PTOKEN_AUDIT_POLICY_INFORMATION
;
32 /* GLOBALS ********************************************************************/
34 POBJECT_TYPE SeTokenObjectType
= NULL
;
35 ERESOURCE SepTokenLock
;
37 TOKEN_SOURCE SeSystemTokenSource
= {"*SYSTEM*", {0}};
38 LUID SeSystemAuthenticationId
= SYSTEM_LUID
;
39 LUID SeAnonymousAuthenticationId
= ANONYMOUS_LOGON_LUID
;
41 static GENERIC_MAPPING SepTokenMapping
= {
48 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
50 /* Class 0 not used, blame M$! */
51 ICI_SQ_SAME( 0, 0, 0),
54 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
56 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
58 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
60 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
61 /* TokenPrimaryGroup */
62 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
63 /* TokenDefaultDacl */
64 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
66 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
68 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
69 /* TokenImpersonationLevel */
70 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
72 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
73 /* TokenRestrictedSids */
74 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
76 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
77 /* TokenGroupsAndPrivileges */
78 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
79 /* TokenSessionReference */
80 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_SET
| ICIF_QUERY_SIZE_VARIABLE
),
81 /* TokenSandBoxInert */
82 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
83 /* TokenAuditPolicy */
84 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
| ICIF_QUERY_SIZE_VARIABLE
),
86 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
| ICIF_QUERY_SIZE_VARIABLE
),
89 /* FUNCTIONS *****************************************************************/
92 SepCompareTokens(IN PTOKEN FirstToken
,
93 IN PTOKEN SecondToken
,
96 BOOLEAN Restricted
, IsEqual
= FALSE
;
98 ASSERT(FirstToken
!= SecondToken
);
100 /* FIXME: Check if every SID that is present in either token is also present in the other one */
102 Restricted
= SeTokenIsRestricted(FirstToken
);
103 if (Restricted
== SeTokenIsRestricted(SecondToken
))
107 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
110 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
111 DPRINT1("FIXME: Pretending tokens are equal!\n");
116 return STATUS_SUCCESS
;
121 SepUpdateSinglePrivilegeFlagToken(
122 _Inout_ PTOKEN Token
,
126 ASSERT(Index
< Token
->PrivilegeCount
);
128 /* The high part of all values we are interested in is 0 */
129 if (Token
->Privileges
[Index
].Luid
.HighPart
!= 0)
134 /* Check for certain privileges to update flags */
135 if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_CHANGE_NOTIFY_PRIVILEGE
)
137 TokenFlag
= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
139 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_BACKUP_PRIVILEGE
)
141 TokenFlag
= TOKEN_HAS_BACKUP_PRIVILEGE
;
143 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_RESTORE_PRIVILEGE
)
145 TokenFlag
= TOKEN_HAS_RESTORE_PRIVILEGE
;
147 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_IMPERSONATE_PRIVILEGE
)
149 TokenFlag
= TOKEN_HAS_IMPERSONATE_PRIVILEGE
;
157 /* Check if the specified privilege is enabled */
158 if (Token
->Privileges
[Index
].Attributes
& SE_PRIVILEGE_ENABLED
)
160 /* It is enabled, so set the flag */
161 Token
->TokenFlags
|= TokenFlag
;
165 /* Is is disabled, so remove the flag */
166 Token
->TokenFlags
&= ~TokenFlag
;
172 SepUpdatePrivilegeFlagsToken(
173 _Inout_ PTOKEN Token
)
177 /* Loop all privileges */
178 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
180 /* Updates the flags dor this privilege */
181 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
187 SepRemovePrivilegeToken(
188 _Inout_ PTOKEN Token
,
192 ASSERT(Index
< Token
->PrivilegeCount
);
194 /* Calculate the number of trailing privileges */
195 MoveCount
= Token
->PrivilegeCount
- Index
- 1;
198 /* Move them one location ahead */
199 RtlMoveMemory(&Token
->Privileges
[Index
],
200 &Token
->Privileges
[Index
+ 1],
201 MoveCount
* sizeof(LUID_AND_ATTRIBUTES
));
204 /* Update privilege count */
205 Token
->PrivilegeCount
--;
210 SepFreeProxyData(PVOID ProxyData
)
217 SepCopyProxyData(PVOID
* Dest
,
221 return STATUS_NOT_IMPLEMENTED
;
226 SeExchangePrimaryToken(PEPROCESS Process
,
227 PACCESS_TOKEN NewTokenP
,
228 PACCESS_TOKEN
* OldTokenP
)
231 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
235 if (NewToken
->TokenType
!= TokenPrimary
) return STATUS_BAD_TOKEN_TYPE
;
236 if (NewToken
->TokenInUse
)
241 /* Maybe we're trying to set the same token */
242 OldToken
= PsReferencePrimaryToken(Process
);
243 if (OldToken
== NewToken
)
246 *OldTokenP
= OldToken
;
247 return STATUS_SUCCESS
;
250 Status
= SepCompareTokens(OldToken
, NewToken
, &IsEqual
);
251 if (!NT_SUCCESS(Status
))
254 PsDereferencePrimaryToken(OldToken
);
261 PsDereferencePrimaryToken(OldToken
);
262 return STATUS_TOKEN_ALREADY_IN_USE
;
264 /* Silently return STATUS_SUCCESS but do not set the new token,
265 * as it's already in use elsewhere. */
266 *OldTokenP
= OldToken
;
267 return STATUS_SUCCESS
;
270 /* Mark new token in use */
271 NewToken
->TokenInUse
= 1;
273 /* Reference the New Token */
274 ObReferenceObject(NewToken
);
276 /* Replace the old with the new */
277 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
279 /* Mark the Old Token as free */
280 OldToken
->TokenInUse
= 0;
282 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
283 return STATUS_SUCCESS
;
288 SeDeassignPrimaryToken(PEPROCESS Process
)
292 /* Remove the Token */
293 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
295 /* Mark the Old Token as free */
296 OldToken
->TokenInUse
= 0;
298 /* Dereference the Token */
299 ObDereferenceObject(OldToken
);
303 RtlLengthSidAndAttributes(ULONG Count
,
304 PSID_AND_ATTRIBUTES Src
)
311 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
312 for (i
= 0; i
< Count
; i
++)
313 uLength
+= RtlLengthSid(Src
[i
].Sid
);
321 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
327 Token
->PrimaryGroup
= 0;
331 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
334 /* Validate and set the primary group and user pointers */
335 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
338 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
340 Token
->DefaultOwnerIndex
= i
;
343 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
345 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
349 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
351 return STATUS_INVALID_OWNER
;
354 if (Token
->PrimaryGroup
== 0)
356 return STATUS_INVALID_PRIMARY_GROUP
;
359 return STATUS_SUCCESS
;
365 SepDuplicateToken(PTOKEN Token
,
366 POBJECT_ATTRIBUTES ObjectAttributes
,
367 BOOLEAN EffectiveOnly
,
368 TOKEN_TYPE TokenType
,
369 SECURITY_IMPERSONATION_LEVEL Level
,
370 KPROCESSOR_MODE PreviousMode
,
371 PTOKEN
* NewAccessToken
)
381 Status
= ObCreateObject(PreviousMode
,
389 (PVOID
*)&AccessToken
);
390 if (!NT_SUCCESS(Status
))
392 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
396 /* Zero out the buffer */
397 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
399 ExAllocateLocallyUniqueId(&AccessToken
->TokenId
);
401 AccessToken
->TokenLock
= &SepTokenLock
;
403 /* Copy and reference the logon session */
404 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
405 SepRmReferenceLogonSession(&AccessToken
->AuthenticationId
);
407 AccessToken
->TokenType
= TokenType
;
408 AccessToken
->ImpersonationLevel
= Level
;
409 RtlCopyLuid(&AccessToken
->ModifiedId
, &Token
->ModifiedId
);
411 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
412 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
413 memcpy(AccessToken
->TokenSource
.SourceName
,
414 Token
->TokenSource
.SourceName
,
415 sizeof(Token
->TokenSource
.SourceName
));
416 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
417 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
418 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
420 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
421 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
422 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
424 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
427 if (AccessToken
->UserAndGroups
== NULL
)
429 Status
= STATUS_INSUFFICIENT_RESOURCES
;
433 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
435 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
436 Token
->UserAndGroups
,
438 AccessToken
->UserAndGroups
,
442 if (!NT_SUCCESS(Status
))
445 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
448 if (!NT_SUCCESS(Status
))
451 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
453 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
454 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
456 TAG_TOKEN_PRIVILAGES
);
457 if (AccessToken
->Privileges
== NULL
)
459 Status
= STATUS_INSUFFICIENT_RESOURCES
;
463 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
465 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
466 &Token
->Privileges
[i
].Luid
);
467 AccessToken
->Privileges
[i
].Attributes
=
468 Token
->Privileges
[i
].Attributes
;
471 if (Token
->DefaultDacl
)
473 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
474 Token
->DefaultDacl
->AclSize
,
476 if (AccessToken
->DefaultDacl
== NULL
)
478 Status
= STATUS_INSUFFICIENT_RESOURCES
;
482 memcpy(AccessToken
->DefaultDacl
,
484 Token
->DefaultDacl
->AclSize
);
487 *NewAccessToken
= AccessToken
;
490 if (!NT_SUCCESS(Status
))
492 /* Dereference the token, the delete procedure will clean up */
493 ObDereferenceObject(AccessToken
);
501 SeSubProcessToken(IN PTOKEN ParentToken
,
507 OBJECT_ATTRIBUTES ObjectAttributes
;
510 /* Initialize the attributes and duplicate it */
511 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
512 Status
= SepDuplicateToken(ParentToken
,
516 ParentToken
->ImpersonationLevel
,
519 if (NT_SUCCESS(Status
))
522 Status
= ObInsertObject(NewToken
,
528 if (NT_SUCCESS(Status
))
530 /* Set the session ID */
531 NewToken
->SessionId
= SessionId
;
532 NewToken
->TokenInUse
= InUse
;
534 /* Return the token */
545 SeIsTokenChild(IN PTOKEN Token
,
546 OUT PBOOLEAN IsChild
)
549 LUID ProcessLuid
, CallerLuid
;
554 /* Reference the process token */
555 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
558 ProcessLuid
= ProcessToken
->AuthenticationId
;
560 /* Dereference the token */
561 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
564 CallerLuid
= Token
->AuthenticationId
;
566 /* Compare the LUIDs */
567 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
570 return STATUS_SUCCESS
;
575 SeCopyClientToken(IN PACCESS_TOKEN Token
,
576 IN SECURITY_IMPERSONATION_LEVEL Level
,
577 IN KPROCESSOR_MODE PreviousMode
,
578 OUT PACCESS_TOKEN
* NewToken
)
581 OBJECT_ATTRIBUTES ObjectAttributes
;
585 InitializeObjectAttributes(&ObjectAttributes
,
590 Status
= SepDuplicateToken(Token
,
603 SepDeleteToken(PVOID ObjectBody
)
605 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
607 DPRINT("SepDeleteToken()\n");
609 /* Dereference the logon session */
610 SepRmDereferenceLogonSession(&AccessToken
->AuthenticationId
);
612 if (AccessToken
->UserAndGroups
)
613 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
615 if (AccessToken
->Privileges
)
616 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
618 if (AccessToken
->DefaultDacl
)
619 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
626 SepInitializeTokenImplementation(VOID
)
629 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
631 ExInitializeResource(&SepTokenLock
);
633 DPRINT("Creating Token Object Type\n");
635 /* Initialize the Token type */
636 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
637 RtlInitUnicodeString(&Name
, L
"Token");
638 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
639 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
640 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
641 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
642 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
643 ObjectTypeInitializer
.PoolType
= PagedPool
;
644 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
645 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
646 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
647 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SeTokenObjectType
);
652 SeAssignPrimaryToken(IN PEPROCESS Process
,
658 ASSERT(Token
->TokenType
== TokenPrimary
);
659 ASSERT(!Token
->TokenInUse
);
661 /* Clean any previous token */
662 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
664 /* Set the new token */
665 ObReferenceObject(Token
);
666 Token
->TokenInUse
= TRUE
;
667 ObInitializeFastReference(&Process
->Token
, Token
);
673 SepCreateToken(OUT PHANDLE TokenHandle
,
674 IN KPROCESSOR_MODE PreviousMode
,
675 IN ACCESS_MASK DesiredAccess
,
676 IN POBJECT_ATTRIBUTES ObjectAttributes
,
677 IN TOKEN_TYPE TokenType
,
678 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
679 IN PLUID AuthenticationId
,
680 IN PLARGE_INTEGER ExpirationTime
,
681 IN PSID_AND_ATTRIBUTES User
,
683 IN PSID_AND_ATTRIBUTES Groups
,
684 IN ULONG GroupLength
,
685 IN ULONG PrivilegeCount
,
686 IN PLUID_AND_ATTRIBUTES Privileges
,
688 IN PSID PrimaryGroup
,
690 IN PTOKEN_SOURCE TokenSource
,
691 IN BOOLEAN SystemToken
)
700 ULONG TokenFlags
= 0;
704 /* Loop all groups */
705 for (i
= 0; i
< GroupCount
; i
++)
707 /* Check for mandatory groups */
708 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
710 /* Force them to be enabled */
711 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
714 /* Check of the group is an admin group */
715 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
717 /* Remember this so we can optimize queries later */
718 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
722 ExAllocateLocallyUniqueId(&TokenId
);
723 ExAllocateLocallyUniqueId(&ModifiedId
);
725 Status
= ObCreateObject(PreviousMode
,
733 (PVOID
*)&AccessToken
);
734 if (!NT_SUCCESS(Status
))
736 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
740 /* Zero out the buffer */
741 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
743 AccessToken
->TokenLock
= &SepTokenLock
;
745 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
746 &TokenSource
->SourceIdentifier
);
747 memcpy(AccessToken
->TokenSource
.SourceName
,
748 TokenSource
->SourceName
,
749 sizeof(TokenSource
->SourceName
));
751 /* Copy and reference the logon session */
752 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
753 SepRmReferenceLogonSession(&AccessToken
->AuthenticationId
);
755 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
756 AccessToken
->ExpirationTime
= *ExpirationTime
;
757 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
759 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
760 AccessToken
->PrivilegeCount
= PrivilegeCount
;
762 AccessToken
->TokenFlags
= TokenFlags
;
763 AccessToken
->TokenType
= TokenType
;
764 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
767 * Normally we would just point these members into the variable information
768 * area; however, our ObCreateObject() call can't allocate a variable information
769 * area, so we allocate them seperately and provide a destroy function.
772 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
773 uLength
+= RtlLengthSid(User
->Sid
);
774 for (i
= 0; i
< GroupCount
; i
++)
775 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
777 // FIXME: should use the object itself
778 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
781 if (AccessToken
->UserAndGroups
== NULL
)
783 Status
= STATUS_INSUFFICIENT_RESOURCES
;
787 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
789 Status
= RtlCopySidAndAttributesArray(1,
792 AccessToken
->UserAndGroups
,
796 if (!NT_SUCCESS(Status
))
799 Status
= RtlCopySidAndAttributesArray(GroupCount
,
802 &AccessToken
->UserAndGroups
[1],
806 if (!NT_SUCCESS(Status
))
809 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
812 if (!NT_SUCCESS(Status
))
815 // FIXME: should use the object itself
816 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
817 if (uLength
== 0) uLength
= sizeof(PVOID
);
818 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
820 TAG_TOKEN_PRIVILAGES
);
821 if (AccessToken
->Privileges
== NULL
)
823 Status
= STATUS_INSUFFICIENT_RESOURCES
;
827 if (PreviousMode
!= KernelMode
)
831 RtlCopyMemory(AccessToken
->Privileges
,
833 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
835 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
837 Status
= _SEH2_GetExceptionCode();
843 RtlCopyMemory(AccessToken
->Privileges
,
845 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
848 if (!NT_SUCCESS(Status
))
851 /* Update privilege flags */
852 SepUpdatePrivilegeFlagsToken(AccessToken
);
854 if (DefaultDacl
!= NULL
)
856 // FIXME: should use the object itself
857 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
858 DefaultDacl
->AclSize
,
860 if (AccessToken
->DefaultDacl
== NULL
)
862 Status
= STATUS_INSUFFICIENT_RESOURCES
;
866 RtlCopyMemory(AccessToken
->DefaultDacl
,
868 DefaultDacl
->AclSize
);
872 AccessToken
->DefaultDacl
= NULL
;
877 Status
= ObInsertObject((PVOID
)AccessToken
,
883 if (!NT_SUCCESS(Status
))
885 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
890 /* Return pointer instead of handle */
891 *TokenHandle
= (HANDLE
)AccessToken
;
895 if (!NT_SUCCESS(Status
))
897 /* Dereference the token, the delete procedure will clean up */
898 ObDereferenceObject(AccessToken
);
906 SepCreateSystemProcessToken(VOID
)
908 LUID_AND_ATTRIBUTES Privileges
[25];
909 ULONG GroupAttributes
, OwnerAttributes
;
910 SID_AND_ATTRIBUTES Groups
[32];
911 LARGE_INTEGER Expiration
;
912 SID_AND_ATTRIBUTES UserSid
;
915 OBJECT_ATTRIBUTES ObjectAttributes
;
921 /* Don't ever expire */
922 Expiration
.QuadPart
= -1;
924 /* All groups mandatory and enabled */
925 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
926 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
929 UserSid
.Sid
= SeLocalSystemSid
;
930 UserSid
.Attributes
= 0;
932 /* Primary group is local system */
933 PrimaryGroup
= SeLocalSystemSid
;
935 /* Owner is admins */
936 Owner
= SeAliasAdminsSid
;
938 /* Groups are admins, world, and authenticated users */
939 Groups
[0].Sid
= SeAliasAdminsSid
;
940 Groups
[0].Attributes
= OwnerAttributes
;
941 Groups
[1].Sid
= SeWorldSid
;
942 Groups
[1].Attributes
= GroupAttributes
;
943 Groups
[2].Sid
= SeAuthenticatedUserSid
;
944 Groups
[2].Attributes
= OwnerAttributes
;
945 GroupLength
= sizeof(SID_AND_ATTRIBUTES
) +
946 SeLengthSid(Groups
[0].Sid
) +
947 SeLengthSid(Groups
[1].Sid
) +
948 SeLengthSid(Groups
[2].Sid
);
949 ASSERT(GroupLength
<= sizeof(Groups
));
951 /* Setup the privileges */
953 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
954 Privileges
[i
++].Luid
= SeTcbPrivilege
;
956 Privileges
[i
].Attributes
= 0;
957 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
959 Privileges
[i
].Attributes
= 0;
960 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
962 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
963 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
965 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
966 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
968 Privileges
[i
].Attributes
= 0;
969 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
971 Privileges
[i
].Attributes
= 0;
972 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
974 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
975 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
977 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
978 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
980 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
981 Privileges
[i
++].Luid
= SeDebugPrivilege
;
983 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
984 Privileges
[i
++].Luid
= SeAuditPrivilege
;
986 Privileges
[i
].Attributes
= 0;
987 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
989 Privileges
[i
].Attributes
= 0;
990 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
992 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
993 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
995 Privileges
[i
].Attributes
= 0;
996 Privileges
[i
++].Luid
= SeBackupPrivilege
;
998 Privileges
[i
].Attributes
= 0;
999 Privileges
[i
++].Luid
= SeRestorePrivilege
;
1001 Privileges
[i
].Attributes
= 0;
1002 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1004 Privileges
[i
].Attributes
= 0;
1005 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1007 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
1008 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1010 Privileges
[i
].Attributes
= 0;
1011 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1014 /* Setup the object attributes */
1015 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1016 ASSERT(SeSystemDefaultDacl
!= NULL
);
1018 /* Create the token */
1019 Status
= SepCreateToken((PHANDLE
)&Token
,
1025 &SeSystemAuthenticationId
,
1035 SeSystemDefaultDacl
,
1036 &SeSystemTokenSource
,
1038 ASSERT(Status
== STATUS_SUCCESS
);
1040 /* Return the token */
1044 /* PUBLIC FUNCTIONS ***********************************************************/
1051 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
1053 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
1054 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
1055 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
1056 OUT PACCESS_TOKEN
* FilteredToken
)
1059 return STATUS_NOT_IMPLEMENTED
;
1065 * NOTE: SeQueryInformationToken is just NtQueryInformationToken without all
1066 * the bells and whistles needed for user-mode buffer access protection.
1070 SeQueryInformationToken(IN PACCESS_TOKEN AccessToken
,
1071 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1072 OUT PVOID
*TokenInformation
)
1075 PTOKEN Token
= (PTOKEN
)AccessToken
;
1076 ULONG RequiredLength
;
1085 if (TokenInformationClass
>= MaxTokenInfoClass
)
1087 DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1088 return STATUS_INVALID_INFO_CLASS
;
1091 switch (TokenInformationClass
)
1097 DPRINT("SeQueryInformationToken(TokenUser)\n");
1098 RequiredLength
= sizeof(TOKEN_USER
) +
1099 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1101 /* Allocate the output buffer */
1102 tu
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1105 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1109 Status
= RtlCopySidAndAttributesArray(1,
1110 &Token
->UserAndGroups
[0],
1111 RequiredLength
- sizeof(TOKEN_USER
),
1117 /* Return the structure */
1118 *TokenInformation
= tu
;
1119 Status
= STATUS_SUCCESS
;
1129 DPRINT("SeQueryInformationToken(TokenGroups)\n");
1130 RequiredLength
= sizeof(tg
->GroupCount
) +
1131 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1133 SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1134 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1136 /* Allocate the output buffer */
1137 tg
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1140 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1144 Sid
= (PSID
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
1145 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1147 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1148 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1149 &Token
->UserAndGroups
[1],
1156 /* Return the structure */
1157 *TokenInformation
= tg
;
1158 Status
= STATUS_SUCCESS
;
1162 case TokenPrivileges
:
1164 PTOKEN_PRIVILEGES tp
;
1166 DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
1167 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1168 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1170 /* Allocate the output buffer */
1171 tp
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1174 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1178 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1179 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1181 &tp
->Privileges
[0]);
1183 /* Return the structure */
1184 *TokenInformation
= tp
;
1185 Status
= STATUS_SUCCESS
;
1194 DPRINT("SeQueryInformationToken(TokenOwner)\n");
1195 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1196 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1198 /* Allocate the output buffer */
1199 to
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1202 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1206 to
->Owner
= (PSID
)(to
+ 1);
1207 Status
= RtlCopySid(SidLen
,
1209 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1211 /* Return the structure */
1212 *TokenInformation
= to
;
1213 Status
= STATUS_SUCCESS
;
1217 case TokenPrimaryGroup
:
1219 PTOKEN_PRIMARY_GROUP tpg
;
1222 DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
1223 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1224 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1226 /* Allocate the output buffer */
1227 tpg
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1230 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1234 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1235 Status
= RtlCopySid(SidLen
,
1237 Token
->PrimaryGroup
);
1239 /* Return the structure */
1240 *TokenInformation
= tpg
;
1241 Status
= STATUS_SUCCESS
;
1245 case TokenDefaultDacl
:
1247 PTOKEN_DEFAULT_DACL tdd
;
1249 DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
1250 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1252 if (Token
->DefaultDacl
!= NULL
)
1253 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1255 /* Allocate the output buffer */
1256 tdd
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1259 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1263 if (Token
->DefaultDacl
!= NULL
)
1265 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1266 RtlCopyMemory(tdd
->DefaultDacl
,
1268 Token
->DefaultDacl
->AclSize
);
1272 tdd
->DefaultDacl
= NULL
;
1275 /* Return the structure */
1276 *TokenInformation
= tdd
;
1277 Status
= STATUS_SUCCESS
;
1285 DPRINT("SeQueryInformationToken(TokenSource)\n");
1286 RequiredLength
= sizeof(TOKEN_SOURCE
);
1288 /* Allocate the output buffer */
1289 ts
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1292 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1296 *ts
= Token
->TokenSource
;
1298 /* Return the structure */
1299 *TokenInformation
= ts
;
1300 Status
= STATUS_SUCCESS
;
1308 DPRINT("SeQueryInformationToken(TokenType)\n");
1309 RequiredLength
= sizeof(TOKEN_TYPE
);
1311 /* Allocate the output buffer */
1312 tt
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1315 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1319 *tt
= Token
->TokenType
;
1321 /* Return the structure */
1322 *TokenInformation
= tt
;
1323 Status
= STATUS_SUCCESS
;
1327 case TokenImpersonationLevel
:
1329 PSECURITY_IMPERSONATION_LEVEL sil
;
1331 DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
1332 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1334 /* Fail if the token is not an impersonation token */
1335 if (Token
->TokenType
!= TokenImpersonation
)
1337 Status
= STATUS_INVALID_INFO_CLASS
;
1341 /* Allocate the output buffer */
1342 sil
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1345 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1349 *sil
= Token
->ImpersonationLevel
;
1351 /* Return the structure */
1352 *TokenInformation
= sil
;
1353 Status
= STATUS_SUCCESS
;
1357 case TokenStatistics
:
1359 PTOKEN_STATISTICS ts
;
1361 DPRINT("SeQueryInformationToken(TokenStatistics)\n");
1362 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1364 /* Allocate the output buffer */
1365 ts
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1368 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1372 ts
->TokenId
= Token
->TokenId
;
1373 ts
->AuthenticationId
= Token
->AuthenticationId
;
1374 ts
->ExpirationTime
= Token
->ExpirationTime
;
1375 ts
->TokenType
= Token
->TokenType
;
1376 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1377 ts
->DynamicCharged
= Token
->DynamicCharged
;
1378 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1379 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1380 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1381 ts
->ModifiedId
= Token
->ModifiedId
;
1383 /* Return the structure */
1384 *TokenInformation
= ts
;
1385 Status
= STATUS_SUCCESS
;
1390 * The following 4 cases are only implemented in NtQueryInformationToken
1398 DPRINT("SeQueryInformationToken(TokenOrigin)\n");
1399 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1401 /* Allocate the output buffer */
1402 to
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1405 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1409 RtlCopyLuid(&to
->OriginatingLogonSession
,
1410 &Token
->AuthenticationId
);
1412 /* Return the structure */
1413 *TokenInformation
= to
;
1414 Status
= STATUS_SUCCESS
;
1418 case TokenGroupsAndPrivileges
:
1419 DPRINT1("SeQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1420 Status
= STATUS_NOT_IMPLEMENTED
;
1423 case TokenRestrictedSids
:
1425 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1429 DPRINT("SeQueryInformationToken(TokenRestrictedSids)\n");
1430 RequiredLength
= sizeof(tg
->GroupCount
) +
1431 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1433 SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1434 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1436 /* Allocate the output buffer */
1437 tg
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1440 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1444 Sid
= (PSID
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
1445 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1447 tg
->GroupCount
= Token
->RestrictedSidCount
;
1448 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1449 Token
->RestrictedSids
,
1456 /* Return the structure */
1457 *TokenInformation
= tg
;
1458 Status
= STATUS_SUCCESS
;
1462 case TokenSandBoxInert
:
1463 DPRINT1("SeQueryInformationToken(TokenSandboxInert) not implemented\n");
1464 Status
= STATUS_NOT_IMPLEMENTED
;
1469 case TokenSessionId
:
1471 DPRINT("SeQueryInformationToken(TokenSessionId)\n");
1473 Status
= SeQuerySessionIdToken(Token
, (PULONG
)TokenInformation
);
1475 // Status = STATUS_SUCCESS;
1480 DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1481 Status
= STATUS_INVALID_INFO_CLASS
;
1493 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
1494 IN PULONG pSessionId
)
1496 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1497 return STATUS_SUCCESS
;
1505 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1510 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
1512 return STATUS_SUCCESS
;
1519 SECURITY_IMPERSONATION_LEVEL
1521 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1525 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1533 SeTokenType(IN PACCESS_TOKEN Token
)
1537 return ((PTOKEN
)Token
)->TokenType
;
1546 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
1550 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
1558 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
1562 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
1570 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
1574 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
1577 /* SYSTEM CALLS ***************************************************************/
1583 NtQueryInformationToken(IN HANDLE TokenHandle
,
1584 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1585 OUT PVOID TokenInformation
,
1586 IN ULONG TokenInformationLength
,
1587 OUT PULONG ReturnLength
)
1590 KPROCESSOR_MODE PreviousMode
;
1592 ULONG RequiredLength
;
1601 PreviousMode
= ExGetPreviousMode();
1603 /* Check buffers and class validity */
1604 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1605 SeTokenInformationClass
,
1606 RTL_NUMBER_OF(SeTokenInformationClass
),
1608 TokenInformationLength
,
1612 if (!NT_SUCCESS(Status
))
1614 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1618 Status
= ObReferenceObjectByHandle(TokenHandle
,
1619 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1624 if (NT_SUCCESS(Status
))
1626 switch (TokenInformationClass
)
1630 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1632 DPRINT("NtQueryInformationToken(TokenUser)\n");
1633 RequiredLength
= sizeof(TOKEN_USER
) +
1634 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1638 if (TokenInformationLength
>= RequiredLength
)
1640 Status
= RtlCopySidAndAttributesArray(1,
1641 &Token
->UserAndGroups
[0],
1642 RequiredLength
- sizeof(TOKEN_USER
),
1650 Status
= STATUS_BUFFER_TOO_SMALL
;
1653 if (ReturnLength
!= NULL
)
1655 *ReturnLength
= RequiredLength
;
1658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1660 Status
= _SEH2_GetExceptionCode();
1669 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1671 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1672 RequiredLength
= sizeof(tg
->GroupCount
) +
1673 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1677 if (TokenInformationLength
>= RequiredLength
)
1679 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1680 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1681 PSID Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
1682 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1684 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1685 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1686 &Token
->UserAndGroups
[1],
1695 Status
= STATUS_BUFFER_TOO_SMALL
;
1698 if (ReturnLength
!= NULL
)
1700 *ReturnLength
= RequiredLength
;
1703 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1705 Status
= _SEH2_GetExceptionCode();
1712 case TokenPrivileges
:
1714 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1716 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1717 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1718 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1722 if (TokenInformationLength
>= RequiredLength
)
1724 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1725 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1727 &tp
->Privileges
[0]);
1731 Status
= STATUS_BUFFER_TOO_SMALL
;
1734 if (ReturnLength
!= NULL
)
1736 *ReturnLength
= RequiredLength
;
1739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1741 Status
= _SEH2_GetExceptionCode();
1750 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1753 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1754 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1755 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1759 if (TokenInformationLength
>= RequiredLength
)
1761 to
->Owner
= (PSID
)(to
+ 1);
1762 Status
= RtlCopySid(SidLen
,
1764 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1768 Status
= STATUS_BUFFER_TOO_SMALL
;
1771 if (ReturnLength
!= NULL
)
1773 *ReturnLength
= RequiredLength
;
1776 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1778 Status
= _SEH2_GetExceptionCode();
1785 case TokenPrimaryGroup
:
1787 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1790 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1791 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1792 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1796 if (TokenInformationLength
>= RequiredLength
)
1798 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1799 Status
= RtlCopySid(SidLen
,
1801 Token
->PrimaryGroup
);
1805 Status
= STATUS_BUFFER_TOO_SMALL
;
1808 if (ReturnLength
!= NULL
)
1810 *ReturnLength
= RequiredLength
;
1813 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1815 Status
= _SEH2_GetExceptionCode();
1822 case TokenDefaultDacl
:
1824 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1826 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1827 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1829 if (Token
->DefaultDacl
!= NULL
)
1830 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1834 if (TokenInformationLength
>= RequiredLength
)
1836 if (Token
->DefaultDacl
!= NULL
)
1838 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1839 RtlCopyMemory(tdd
->DefaultDacl
,
1841 Token
->DefaultDacl
->AclSize
);
1845 tdd
->DefaultDacl
= NULL
;
1850 Status
= STATUS_BUFFER_TOO_SMALL
;
1853 if (ReturnLength
!= NULL
)
1855 *ReturnLength
= RequiredLength
;
1858 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1860 Status
= _SEH2_GetExceptionCode();
1869 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1871 DPRINT("NtQueryInformationToken(TokenSource)\n");
1872 RequiredLength
= sizeof(TOKEN_SOURCE
);
1876 if (TokenInformationLength
>= RequiredLength
)
1878 *ts
= Token
->TokenSource
;
1882 Status
= STATUS_BUFFER_TOO_SMALL
;
1885 if (ReturnLength
!= NULL
)
1887 *ReturnLength
= RequiredLength
;
1890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1892 Status
= _SEH2_GetExceptionCode();
1901 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1903 DPRINT("NtQueryInformationToken(TokenType)\n");
1904 RequiredLength
= sizeof(TOKEN_TYPE
);
1908 if (TokenInformationLength
>= RequiredLength
)
1910 *tt
= Token
->TokenType
;
1914 Status
= STATUS_BUFFER_TOO_SMALL
;
1917 if (ReturnLength
!= NULL
)
1919 *ReturnLength
= RequiredLength
;
1922 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1924 Status
= _SEH2_GetExceptionCode();
1931 case TokenImpersonationLevel
:
1933 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1935 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1937 /* Fail if the token is not an impersonation token */
1938 if (Token
->TokenType
!= TokenImpersonation
)
1940 Status
= STATUS_INVALID_INFO_CLASS
;
1944 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1948 if (TokenInformationLength
>= RequiredLength
)
1950 *sil
= Token
->ImpersonationLevel
;
1954 Status
= STATUS_BUFFER_TOO_SMALL
;
1957 if (ReturnLength
!= NULL
)
1959 *ReturnLength
= RequiredLength
;
1962 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1964 Status
= _SEH2_GetExceptionCode();
1971 case TokenStatistics
:
1973 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1975 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1976 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1980 if (TokenInformationLength
>= RequiredLength
)
1982 ts
->TokenId
= Token
->TokenId
;
1983 ts
->AuthenticationId
= Token
->AuthenticationId
;
1984 ts
->ExpirationTime
= Token
->ExpirationTime
;
1985 ts
->TokenType
= Token
->TokenType
;
1986 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1987 ts
->DynamicCharged
= Token
->DynamicCharged
;
1988 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1989 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1990 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1991 ts
->ModifiedId
= Token
->ModifiedId
;
1995 Status
= STATUS_BUFFER_TOO_SMALL
;
1998 if (ReturnLength
!= NULL
)
2000 *ReturnLength
= RequiredLength
;
2003 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2005 Status
= _SEH2_GetExceptionCode();
2014 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
2016 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
2017 RequiredLength
= sizeof(TOKEN_ORIGIN
);
2021 if (TokenInformationLength
>= RequiredLength
)
2023 RtlCopyLuid(&to
->OriginatingLogonSession
,
2024 &Token
->AuthenticationId
);
2028 Status
= STATUS_BUFFER_TOO_SMALL
;
2031 if (ReturnLength
!= NULL
)
2033 *ReturnLength
= RequiredLength
;
2036 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2038 Status
= _SEH2_GetExceptionCode();
2045 case TokenGroupsAndPrivileges
:
2046 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
2047 Status
= STATUS_NOT_IMPLEMENTED
;
2050 case TokenRestrictedSids
:
2052 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
2054 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
2055 RequiredLength
= sizeof(tg
->GroupCount
) +
2056 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
2060 if (TokenInformationLength
>= RequiredLength
)
2062 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
2063 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
2064 PSID Sid
= (PSID
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
2065 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
2067 tg
->GroupCount
= Token
->RestrictedSidCount
;
2068 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
2069 Token
->RestrictedSids
,
2078 Status
= STATUS_BUFFER_TOO_SMALL
;
2081 if (ReturnLength
!= NULL
)
2083 *ReturnLength
= RequiredLength
;
2086 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2088 Status
= _SEH2_GetExceptionCode();
2095 case TokenSandBoxInert
:
2096 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
2097 Status
= STATUS_NOT_IMPLEMENTED
;
2100 case TokenSessionId
:
2102 ULONG SessionId
= 0;
2104 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
2106 Status
= SeQuerySessionIdToken(Token
, &SessionId
);
2107 if (NT_SUCCESS(Status
))
2111 /* Buffer size was already verified, no need to check here again */
2112 *(PULONG
)TokenInformation
= SessionId
;
2114 if (ReturnLength
!= NULL
)
2116 *ReturnLength
= sizeof(ULONG
);
2119 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2121 Status
= _SEH2_GetExceptionCode();
2130 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
2131 Status
= STATUS_INVALID_INFO_CLASS
;
2135 ObDereferenceObject(Token
);
2143 * NtSetTokenInformation: Partly implemented.
2145 * TokenOrigin, TokenDefaultDacl
2149 NtSetInformationToken(IN HANDLE TokenHandle
,
2150 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
2151 IN PVOID TokenInformation
,
2152 IN ULONG TokenInformationLength
)
2155 KPROCESSOR_MODE PreviousMode
;
2156 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
2161 PreviousMode
= ExGetPreviousMode();
2163 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
2164 SeTokenInformationClass
,
2165 RTL_NUMBER_OF(SeTokenInformationClass
),
2167 TokenInformationLength
,
2169 if (!NT_SUCCESS(Status
))
2171 /* Invalid buffers */
2172 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
2176 if (TokenInformationClass
== TokenSessionId
)
2178 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
2181 Status
= ObReferenceObjectByHandle(TokenHandle
,
2187 if (NT_SUCCESS(Status
))
2189 switch (TokenInformationClass
)
2193 if (TokenInformationLength
>= sizeof(TOKEN_OWNER
))
2195 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
2196 PSID InputSid
= NULL
, CapturedSid
;
2200 InputSid
= to
->Owner
;
2202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2204 Status
= _SEH2_GetExceptionCode();
2205 _SEH2_YIELD(goto Cleanup
);
2209 Status
= SepCaptureSid(InputSid
,
2214 if (NT_SUCCESS(Status
))
2216 RtlCopySid(RtlLengthSid(CapturedSid
),
2217 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
2219 SepReleaseSid(CapturedSid
,
2226 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2231 case TokenPrimaryGroup
:
2233 if (TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
2235 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
2236 PSID InputSid
= NULL
, CapturedSid
;
2240 InputSid
= tpg
->PrimaryGroup
;
2242 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2244 Status
= _SEH2_GetExceptionCode();
2245 _SEH2_YIELD(goto Cleanup
);
2249 Status
= SepCaptureSid(InputSid
,
2254 if (NT_SUCCESS(Status
))
2256 RtlCopySid(RtlLengthSid(CapturedSid
),
2257 Token
->PrimaryGroup
,
2259 SepReleaseSid(CapturedSid
,
2266 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2271 case TokenDefaultDacl
:
2273 if (TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
2275 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
2276 PACL InputAcl
= NULL
;
2280 InputAcl
= tdd
->DefaultDacl
;
2282 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2284 Status
= _SEH2_GetExceptionCode();
2285 _SEH2_YIELD(goto Cleanup
);
2289 if (InputAcl
!= NULL
)
2293 /* Capture and copy the dacl */
2294 Status
= SepCaptureAcl(InputAcl
,
2299 if (NT_SUCCESS(Status
))
2301 /* Free the previous dacl if present */
2302 if(Token
->DefaultDacl
!= NULL
)
2304 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
2307 Token
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
2308 CapturedAcl
->AclSize
,
2310 if (!Token
->DefaultDacl
)
2312 ExFreePoolWithTag(CapturedAcl
, TAG_ACL
);
2313 Status
= STATUS_NO_MEMORY
;
2317 /* Set the new dacl */
2318 RtlCopyMemory(Token
->DefaultDacl
, CapturedAcl
, CapturedAcl
->AclSize
);
2319 ExFreePoolWithTag(CapturedAcl
, TAG_ACL
);
2325 /* Clear and free the default dacl if present */
2326 if (Token
->DefaultDacl
!= NULL
)
2328 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
2329 Token
->DefaultDacl
= NULL
;
2335 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2340 case TokenSessionId
:
2342 ULONG SessionId
= 0;
2346 /* Buffer size was already verified, no need to check here again */
2347 SessionId
= *(PULONG
)TokenInformation
;
2349 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2351 Status
= _SEH2_GetExceptionCode();
2352 _SEH2_YIELD(goto Cleanup
);
2356 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2359 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2363 Token
->SessionId
= SessionId
;
2367 case TokenSessionReference
:
2369 ULONG SessionReference
;
2373 /* Buffer size was already verified, no need to check here again */
2374 SessionReference
= *(PULONG
)TokenInformation
;
2376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2378 Status
= _SEH2_GetExceptionCode();
2379 _SEH2_YIELD(goto Cleanup
);
2383 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
2385 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2389 /* Check if it is 0 */
2390 if (SessionReference
== 0)
2392 /* Atomically set the flag in the token */
2393 RtlInterlockedSetBits(&Token
->TokenFlags
,
2394 TOKEN_SESSION_NOT_REFERENCED
);
2402 case TokenAuditPolicy
:
2404 PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation
=
2405 (PTOKEN_AUDIT_POLICY_INFORMATION
)TokenInformation
;
2406 SEP_AUDIT_POLICY AuditPolicy
;
2411 ProbeForRead(PolicyInformation
,
2412 FIELD_OFFSET(TOKEN_AUDIT_POLICY_INFORMATION
,
2413 Policies
[PolicyInformation
->PolicyCount
]),
2416 /* Loop all policies in the structure */
2417 for (i
= 0; i
< PolicyInformation
->PolicyCount
; i
++)
2419 /* Set the corresponding bits in the packed structure */
2420 switch (PolicyInformation
->Policies
[i
].Category
)
2422 case AuditCategorySystem
:
2423 AuditPolicy
.PolicyElements
.System
= PolicyInformation
->Policies
[i
].Value
;
2426 case AuditCategoryLogon
:
2427 AuditPolicy
.PolicyElements
.Logon
= PolicyInformation
->Policies
[i
].Value
;
2430 case AuditCategoryObjectAccess
:
2431 AuditPolicy
.PolicyElements
.ObjectAccess
= PolicyInformation
->Policies
[i
].Value
;
2434 case AuditCategoryPrivilegeUse
:
2435 AuditPolicy
.PolicyElements
.PrivilegeUse
= PolicyInformation
->Policies
[i
].Value
;
2438 case AuditCategoryDetailedTracking
:
2439 AuditPolicy
.PolicyElements
.DetailedTracking
= PolicyInformation
->Policies
[i
].Value
;
2442 case AuditCategoryPolicyChange
:
2443 AuditPolicy
.PolicyElements
.PolicyChange
= PolicyInformation
->Policies
[i
].Value
;
2446 case AuditCategoryAccountManagement
:
2447 AuditPolicy
.PolicyElements
.AccountManagement
= PolicyInformation
->Policies
[i
].Value
;
2450 case AuditCategoryDirectoryServiceAccess
:
2451 AuditPolicy
.PolicyElements
.DirectoryServiceAccess
= PolicyInformation
->Policies
[i
].Value
;
2454 case AuditCategoryAccountLogon
:
2455 AuditPolicy
.PolicyElements
.AccountLogon
= PolicyInformation
->Policies
[i
].Value
;
2460 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2462 Status
= _SEH2_GetExceptionCode();
2463 _SEH2_YIELD(goto Cleanup
);
2467 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2470 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2474 /* Lock the token */
2475 SepAcquireTokenLockExclusive(Token
);
2477 /* Set the new audit policy */
2478 Token
->AuditPolicy
= AuditPolicy
;
2480 /* Unlock the token */
2481 SepReleaseTokenLock(Token
);
2488 TOKEN_ORIGIN TokenOrigin
;
2492 /* Copy the token origin */
2493 TokenOrigin
= *(PTOKEN_ORIGIN
)TokenInformation
;
2495 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2497 Status
= _SEH2_GetExceptionCode();
2498 _SEH2_YIELD(goto Cleanup
);
2502 /* Check for TCB privilege */
2503 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
2505 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2509 /* Lock the token */
2510 SepAcquireTokenLockExclusive(Token
);
2512 /* Check if there is no token origin set yet */
2513 if ((Token
->OriginatingLogonSession
.LowPart
== 0) &&
2514 (Token
->OriginatingLogonSession
.HighPart
== 0))
2516 /* Set the token origin */
2517 Token
->OriginatingLogonSession
=
2518 TokenOrigin
.OriginatingLogonSession
;
2521 /* Unlock the token */
2522 SepReleaseTokenLock(Token
);
2529 DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
2530 TokenInformationClass
);
2531 Status
= STATUS_INVALID_INFO_CLASS
;
2536 ObDereferenceObject(Token
);
2539 if (!NT_SUCCESS(Status
))
2541 DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status
);
2551 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
2552 * this is certainly NOT true, although I can't say for sure that EffectiveOnly
2553 * is correct either. -Gunnar
2554 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
2555 * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore
2556 * wrong in that regard.
2559 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
2560 IN ACCESS_MASK DesiredAccess
,
2561 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
2562 IN BOOLEAN EffectiveOnly
,
2563 IN TOKEN_TYPE TokenType
,
2564 OUT PHANDLE NewTokenHandle
)
2566 KPROCESSOR_MODE PreviousMode
;
2570 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
2572 OBJECT_HANDLE_INFORMATION HandleInformation
;
2577 if (TokenType
!= TokenImpersonation
&&
2578 TokenType
!= TokenPrimary
)
2579 return STATUS_INVALID_PARAMETER
;
2581 PreviousMode
= KeGetPreviousMode();
2583 if (PreviousMode
!= KernelMode
)
2587 ProbeForWriteHandle(NewTokenHandle
);
2589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2591 /* Return the exception code */
2592 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2597 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
2601 &CapturedSecurityQualityOfService
,
2603 if (!NT_SUCCESS(Status
))
2605 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
2609 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
2614 &HandleInformation
);
2615 if (!NT_SUCCESS(Status
))
2617 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2624 * Fail, if the original token is an impersonation token and the caller
2625 * tries to raise the impersonation level of the new token above the
2626 * impersonation level of the original token.
2628 if (Token
->TokenType
== TokenImpersonation
)
2631 CapturedSecurityQualityOfService
->ImpersonationLevel
>Token
->ImpersonationLevel
)
2633 ObDereferenceObject(Token
);
2634 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2637 return STATUS_BAD_IMPERSONATION_LEVEL
;
2642 * Fail, if a primary token is to be created from an impersonation token
2643 * and and the impersonation level of the impersonation token is below SecurityImpersonation.
2645 if (Token
->TokenType
== TokenImpersonation
&&
2646 TokenType
== TokenPrimary
&&
2647 Token
->ImpersonationLevel
< SecurityImpersonation
)
2649 ObDereferenceObject(Token
);
2650 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2653 return STATUS_BAD_IMPERSONATION_LEVEL
;
2656 Status
= SepDuplicateToken(Token
,
2660 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
2664 ObDereferenceObject(Token
);
2666 if (NT_SUCCESS(Status
))
2668 Status
= ObInsertObject((PVOID
)NewToken
,
2670 (DesiredAccess
? DesiredAccess
: HandleInformation
.GrantedAccess
),
2674 if (NT_SUCCESS(Status
))
2678 *NewTokenHandle
= hToken
;
2680 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2682 Status
= _SEH2_GetExceptionCode();
2688 /* Free the captured structure */
2689 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2697 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
2698 IN BOOLEAN ResetToDefault
,
2699 IN PTOKEN_GROUPS NewState
,
2700 IN ULONG BufferLength
,
2701 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
2702 OUT PULONG ReturnLength
)
2705 return STATUS_NOT_IMPLEMENTED
;
2711 SepAdjustPrivileges(
2712 _Inout_ PTOKEN Token
,
2713 _In_ BOOLEAN DisableAllPrivileges
,
2714 _In_opt_ PLUID_AND_ATTRIBUTES NewState
,
2715 _In_ ULONG NewStateCount
,
2716 _Out_opt_ PTOKEN_PRIVILEGES PreviousState
,
2717 _In_ BOOLEAN ApplyChanges
,
2718 _Out_ PULONG ChangedPrivileges
)
2720 ULONG i
, j
, PrivilegeCount
, ChangeCount
, NewAttributes
;
2722 /* Count the found privileges and those that need to be changed */
2726 /* Loop all privileges in the token */
2727 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2729 /* Shall all of them be disabled? */
2730 if (DisableAllPrivileges
)
2732 /* The new attributes are the old ones, but disabled */
2733 NewAttributes
= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2737 /* Otherwise loop all provided privileges */
2738 for (j
= 0; j
< NewStateCount
; j
++)
2740 /* Check if this is the LUID we are looking for */
2741 if (RtlEqualLuid(&Token
->Privileges
[i
].Luid
, &NewState
[j
].Luid
))
2743 DPRINT("Found privilege\n");
2745 /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
2746 NewAttributes
= NewState
[j
].Attributes
;
2747 NewAttributes
&= (SE_PRIVILEGE_ENABLED
| SE_PRIVILEGE_REMOVED
);
2748 NewAttributes
|= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2755 /* Check if we didn't find the privilege */
2756 if (j
== NewStateCount
)
2758 /* Continue with the token's next privilege */
2763 /* We found a privilege, count it */
2766 /* Does the privilege need to be changed? */
2767 if (Token
->Privileges
[i
].Attributes
!= NewAttributes
)
2769 /* Does the caller want the old privileges? */
2770 if (PreviousState
!= NULL
)
2772 /* Copy the old privilege */
2773 PreviousState
->Privileges
[ChangeCount
] = Token
->Privileges
[i
];
2776 /* Does the caller want to apply the changes? */
2779 /* Shall we remove the privilege? */
2780 if (NewAttributes
& SE_PRIVILEGE_REMOVED
)
2782 /* Set the token as disabled and update flags for it */
2783 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2784 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2786 /* Remove the privilege */
2787 SepRemovePrivilegeToken(Token
, i
);
2789 /* Fix the running index */
2792 /* Continue with next */
2796 /* Set the new attributes and update flags */
2797 Token
->Privileges
[i
].Attributes
= NewAttributes
;
2798 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2801 /* Increment the change count */
2806 /* Set the number of saved privileges */
2807 if (PreviousState
!= NULL
)
2808 PreviousState
->PrivilegeCount
= ChangeCount
;
2810 /* Return the number of changed privileges */
2811 *ChangedPrivileges
= ChangeCount
;
2813 /* Check if we missed some */
2814 if (!DisableAllPrivileges
&& (PrivilegeCount
< NewStateCount
))
2816 return STATUS_NOT_ALL_ASSIGNED
;
2819 return STATUS_SUCCESS
;
2826 _Must_inspect_result_
2830 NtAdjustPrivilegesToken(
2831 _In_ HANDLE TokenHandle
,
2832 _In_ BOOLEAN DisableAllPrivileges
,
2833 _In_opt_ PTOKEN_PRIVILEGES NewState
,
2834 _In_ ULONG BufferLength
,
2835 _Out_writes_bytes_to_opt_(BufferLength
,*ReturnLength
)
2836 PTOKEN_PRIVILEGES PreviousState
,
2837 _When_(PreviousState
!=NULL
, _Out_
) PULONG ReturnLength
)
2839 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2840 KPROCESSOR_MODE PreviousMode
;
2841 ULONG CapturedCount
= 0;
2842 ULONG CapturedLength
= 0;
2843 ULONG NewStateSize
= 0;
2845 ULONG RequiredLength
;
2850 DPRINT("NtAdjustPrivilegesToken() called\n");
2852 /* Fail, if we do not disable all privileges but NewState is NULL */
2853 if (DisableAllPrivileges
== FALSE
&& NewState
== NULL
)
2854 return STATUS_INVALID_PARAMETER
;
2856 PreviousMode
= KeGetPreviousMode ();
2857 if (PreviousMode
!= KernelMode
)
2861 /* Probe NewState */
2862 if (DisableAllPrivileges
== FALSE
)
2864 /* First probe the header */
2865 ProbeForRead(NewState
, sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
));
2867 CapturedCount
= NewState
->PrivilegeCount
;
2868 NewStateSize
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[CapturedCount
]);
2870 ProbeForRead(NewState
, NewStateSize
, sizeof(ULONG
));
2873 /* Probe PreviousState and ReturnLength */
2874 if (PreviousState
!= NULL
)
2876 ProbeForWrite(PreviousState
, BufferLength
, sizeof(ULONG
));
2877 ProbeForWrite(ReturnLength
, sizeof(ULONG
), sizeof(ULONG
));
2880 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2882 /* Return the exception code */
2883 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2889 /* This is kernel mode, we trust the caller */
2890 if (DisableAllPrivileges
== FALSE
)
2891 CapturedCount
= NewState
->PrivilegeCount
;
2894 /* Do we need to capture the new state? */
2895 if (DisableAllPrivileges
== FALSE
)
2899 /* Capture the new state array of privileges */
2900 Status
= SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
2907 &CapturedPrivileges
,
2910 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2912 /* Return the exception code */
2913 Status
= _SEH2_GetExceptionCode();
2917 if (!NT_SUCCESS(Status
))
2921 /* Reference the token */
2922 Status
= ObReferenceObjectByHandle(TokenHandle
,
2923 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
2928 if (!NT_SUCCESS(Status
))
2930 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
2932 /* Release the captured privileges */
2933 if (CapturedPrivileges
!= NULL
)
2934 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2941 /* Lock the token */
2942 ExEnterCriticalRegionAndAcquireResourceExclusive(Token
->TokenLock
);
2944 /* Count the privileges that need to be changed, do not apply them yet */
2945 Status
= SepAdjustPrivileges(Token
,
2946 DisableAllPrivileges
,
2953 /* Check if the caller asked for the previous state */
2954 if (PreviousState
!= NULL
)
2956 /* Calculate the required length */
2957 RequiredLength
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[ChangeCount
]);
2959 /* Try to return the required buffer length */
2962 *ReturnLength
= RequiredLength
;
2964 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2966 /* Do cleanup and return the exception code */
2967 Status
= _SEH2_GetExceptionCode();
2968 _SEH2_YIELD(goto Cleanup
);
2972 /* Fail, if the buffer length is smaller than the required length */
2973 if (BufferLength
< RequiredLength
)
2975 Status
= STATUS_BUFFER_TOO_SMALL
;
2980 /* Now enter SEH, since we might return the old privileges */
2983 /* This time apply the changes */
2984 Status
= SepAdjustPrivileges(Token
,
2985 DisableAllPrivileges
,
2992 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2994 /* Do cleanup and return the exception code */
2995 Status
= _SEH2_GetExceptionCode();
2996 _SEH2_YIELD(goto Cleanup
);
3001 /* Unlock and dereference the token */
3002 ExReleaseResourceAndLeaveCriticalRegion(Token
->TokenLock
);
3003 ObDereferenceObject(Token
);
3005 /* Release the captured privileges */
3006 if (CapturedPrivileges
!= NULL
)
3007 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
3011 DPRINT ("NtAdjustPrivilegesToken() done\n");
3018 _Out_ PHANDLE TokenHandle
,
3019 _In_ ACCESS_MASK DesiredAccess
,
3020 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
,
3021 _In_ TOKEN_TYPE TokenType
,
3022 _In_ PLUID AuthenticationId
,
3023 _In_ PLARGE_INTEGER ExpirationTime
,
3024 _In_ PTOKEN_USER TokenUser
,
3025 _In_ PTOKEN_GROUPS TokenGroups
,
3026 _In_ PTOKEN_PRIVILEGES TokenPrivileges
,
3027 _In_opt_ PTOKEN_OWNER TokenOwner
,
3028 _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
3029 _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
3030 _In_ PTOKEN_SOURCE TokenSource
)
3033 KPROCESSOR_MODE PreviousMode
;
3034 ULONG PrivilegeCount
, GroupCount
;
3035 PSID OwnerSid
, PrimaryGroupSid
;
3037 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
3038 LUID LocalAuthenticationId
;
3039 TOKEN_SOURCE LocalTokenSource
;
3040 SECURITY_QUALITY_OF_SERVICE LocalSecurityQos
;
3041 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
3042 PSID_AND_ATTRIBUTES CapturedUser
= NULL
;
3043 PSID_AND_ATTRIBUTES CapturedGroups
= NULL
;
3044 PSID CapturedOwnerSid
= NULL
;
3045 PSID CapturedPrimaryGroupSid
= NULL
;
3046 PACL CapturedDefaultDacl
= NULL
;
3047 ULONG PrivilegesLength
, UserLength
, GroupsLength
;
3052 PreviousMode
= ExGetPreviousMode();
3054 if (PreviousMode
!= KernelMode
)
3058 ProbeForWriteHandle(TokenHandle
);
3060 if (ObjectAttributes
!= NULL
)
3062 ProbeForRead(ObjectAttributes
,
3063 sizeof(OBJECT_ATTRIBUTES
),
3065 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
3068 ProbeForRead(AuthenticationId
,
3071 LocalAuthenticationId
= *AuthenticationId
;
3073 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
3075 ProbeForRead(TokenUser
,
3079 ProbeForRead(TokenGroups
,
3080 sizeof(TOKEN_GROUPS
),
3082 GroupCount
= TokenGroups
->GroupCount
;
3084 ProbeForRead(TokenPrivileges
,
3085 sizeof(TOKEN_PRIVILEGES
),
3087 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
3089 if (TokenOwner
!= NULL
)
3091 ProbeForRead(TokenOwner
,
3092 sizeof(TOKEN_OWNER
),
3094 OwnerSid
= TokenOwner
->Owner
;
3101 ProbeForRead(TokenPrimaryGroup
,
3102 sizeof(TOKEN_PRIMARY_GROUP
),
3104 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
3106 if (TokenDefaultDacl
!= NULL
)
3108 ProbeForRead(TokenDefaultDacl
,
3109 sizeof(TOKEN_DEFAULT_DACL
),
3111 DefaultDacl
= TokenDefaultDacl
->DefaultDacl
;
3118 ProbeForRead(TokenSource
,
3119 sizeof(TOKEN_SOURCE
),
3121 LocalTokenSource
= *TokenSource
;
3123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3125 /* Return the exception code */
3126 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3132 if (ObjectAttributes
!= NULL
)
3133 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
3134 LocalAuthenticationId
= *AuthenticationId
;
3135 LocalExpirationTime
= *ExpirationTime
;
3136 GroupCount
= TokenGroups
->GroupCount
;
3137 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
3138 OwnerSid
= TokenOwner
? TokenOwner
->Owner
: NULL
;
3139 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
3140 DefaultDacl
= TokenDefaultDacl
? TokenDefaultDacl
->DefaultDacl
: NULL
;
3141 LocalTokenSource
= *TokenSource
;
3144 /* Check token type */
3145 if ((TokenType
< TokenPrimary
) ||
3146 (TokenType
> TokenImpersonation
))
3148 return STATUS_BAD_TOKEN_TYPE
;
3151 /* Capture the user SID and attributes */
3152 Status
= SeCaptureSidAndAttributesArray(&TokenUser
->User
,
3161 if (!NT_SUCCESS(Status
))
3166 /* Capture the groups SID and attributes array */
3167 Status
= SeCaptureSidAndAttributesArray(&TokenGroups
->Groups
[0],
3176 if (!NT_SUCCESS(Status
))
3181 /* Capture privileges */
3182 Status
= SeCaptureLuidAndAttributesArray(&TokenPrivileges
->Privileges
[0],
3189 &CapturedPrivileges
,
3191 if (!NT_SUCCESS(Status
))
3196 /* Capture the token owner SID */
3197 if (TokenOwner
!= NULL
)
3199 Status
= SepCaptureSid(OwnerSid
,
3204 if (!NT_SUCCESS(Status
))
3210 /* Capture the token primary group SID */
3211 Status
= SepCaptureSid(PrimaryGroupSid
,
3215 &CapturedPrimaryGroupSid
);
3216 if (!NT_SUCCESS(Status
))
3221 /* Capture DefaultDacl */
3222 if (DefaultDacl
!= NULL
)
3224 Status
= SepCaptureAcl(DefaultDacl
,
3228 &CapturedDefaultDacl
);
3229 if (!NT_SUCCESS(Status
))
3235 /* Call the internal function */
3236 Status
= SepCreateToken(&hToken
,
3241 LocalSecurityQos
.ImpersonationLevel
,
3242 &LocalAuthenticationId
,
3243 &LocalExpirationTime
,
3247 0, // FIXME: Should capture
3251 CapturedPrimaryGroupSid
,
3252 CapturedDefaultDacl
,
3255 if (NT_SUCCESS(Status
))
3259 *TokenHandle
= hToken
;
3261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3263 Status
= _SEH2_GetExceptionCode();
3270 /* Release what we captured */
3271 SeReleaseSidAndAttributesArray(CapturedUser
, PreviousMode
, FALSE
);
3272 SeReleaseSidAndAttributesArray(CapturedGroups
, PreviousMode
, FALSE
);
3273 SeReleaseLuidAndAttributesArray(CapturedPrivileges
, PreviousMode
, FALSE
);
3274 SepReleaseSid(CapturedOwnerSid
, PreviousMode
, FALSE
);
3275 SepReleaseSid(CapturedPrimaryGroupSid
, PreviousMode
, FALSE
);
3276 SepReleaseAcl(CapturedDefaultDacl
, PreviousMode
, FALSE
);
3286 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
3287 IN ACCESS_MASK DesiredAccess
,
3288 IN BOOLEAN OpenAsSelf
,
3289 IN ULONG HandleAttributes
,
3290 OUT PHANDLE TokenHandle
)
3292 PETHREAD Thread
, NewThread
;
3294 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
3295 BOOLEAN CopyOnOpen
, EffectiveOnly
;
3296 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
3297 SE_IMPERSONATION_STATE ImpersonationState
;
3298 OBJECT_ATTRIBUTES ObjectAttributes
;
3299 SECURITY_DESCRIPTOR SecurityDescriptor
;
3301 KPROCESSOR_MODE PreviousMode
;
3303 BOOLEAN RestoreImpersonation
= FALSE
;
3307 PreviousMode
= ExGetPreviousMode();
3309 if (PreviousMode
!= KernelMode
)
3313 ProbeForWriteHandle(TokenHandle
);
3315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3317 /* Return the exception code */
3318 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3323 /* Validate object attributes */
3324 HandleAttributes
= ObpValidateAttributes(HandleAttributes
, PreviousMode
);
3327 * At first open the thread token for information access and verify
3328 * that the token associated with thread is valid. */
3330 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
3331 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
3333 if (!NT_SUCCESS(Status
))
3338 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
3339 &ImpersonationLevel
);
3342 ObDereferenceObject(Thread
);
3343 return STATUS_NO_TOKEN
;
3346 if (ImpersonationLevel
== SecurityAnonymous
)
3348 PsDereferenceImpersonationToken(Token
);
3349 ObDereferenceObject(Thread
);
3350 return STATUS_CANT_OPEN_ANONYMOUS
;
3354 * Revert to self if OpenAsSelf is specified.
3359 RestoreImpersonation
= PsDisableImpersonation(PsGetCurrentThread(),
3360 &ImpersonationState
);
3365 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
3366 PsThreadType
, KernelMode
,
3367 (PVOID
*)&NewThread
, NULL
);
3368 if (NT_SUCCESS(Status
))
3370 PrimaryToken
= PsReferencePrimaryToken(NewThread
->ThreadsProcess
);
3372 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
3374 ObFastDereferenceObject(&NewThread
->ThreadsProcess
->Token
, PrimaryToken
);
3376 if (NT_SUCCESS(Status
))
3380 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
3381 SECURITY_DESCRIPTOR_REVISION
);
3382 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
3386 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
3387 NULL
, Dacl
? &SecurityDescriptor
: NULL
);
3390 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
3391 TokenImpersonation
, ImpersonationLevel
,
3392 KernelMode
, &NewToken
);
3393 if (NT_SUCCESS(Status
))
3395 ObReferenceObject(NewToken
);
3396 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
3404 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
3405 NULL
, DesiredAccess
, SeTokenObjectType
,
3406 PreviousMode
, &hToken
);
3409 if (Dacl
) ExFreePoolWithTag(Dacl
, TAG_TOKEN_ACL
);
3411 if (RestoreImpersonation
)
3413 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
3416 ObDereferenceObject(Token
);
3418 if (NT_SUCCESS(Status
) && CopyOnOpen
)
3420 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
3423 if (NewToken
) ObDereferenceObject(NewToken
);
3425 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
3427 ObDereferenceObject(Thread
);
3429 if (NT_SUCCESS(Status
))
3433 *TokenHandle
= hToken
;
3435 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3437 Status
= _SEH2_GetExceptionCode();
3449 NtOpenThreadToken(IN HANDLE ThreadHandle
,
3450 IN ACCESS_MASK DesiredAccess
,
3451 IN BOOLEAN OpenAsSelf
,
3452 OUT PHANDLE TokenHandle
)
3454 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
3465 NtCompareTokens(IN HANDLE FirstTokenHandle
,
3466 IN HANDLE SecondTokenHandle
,
3469 KPROCESSOR_MODE PreviousMode
;
3470 PTOKEN FirstToken
, SecondToken
;
3476 PreviousMode
= ExGetPreviousMode();
3478 if (PreviousMode
!= KernelMode
)
3482 ProbeForWriteBoolean(Equal
);
3484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3486 /* Return the exception code */
3487 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3492 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
3496 (PVOID
*)&FirstToken
,
3498 if (!NT_SUCCESS(Status
))
3501 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
3505 (PVOID
*)&SecondToken
,
3507 if (!NT_SUCCESS(Status
))
3509 ObDereferenceObject(FirstToken
);
3513 if (FirstToken
!= SecondToken
)
3515 Status
= SepCompareTokens(FirstToken
,
3522 ObDereferenceObject(FirstToken
);
3523 ObDereferenceObject(SecondToken
);
3525 if (NT_SUCCESS(Status
))
3531 _SEH2_EXCEPT(ExSystemExceptionFilter())
3533 Status
= _SEH2_GetExceptionCode();
3543 NtFilterToken(IN HANDLE ExistingTokenHandle
,
3545 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
3546 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
3547 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
3548 OUT PHANDLE NewTokenHandle
)
3551 return STATUS_NOT_IMPLEMENTED
;
3559 NtImpersonateAnonymousToken(IN HANDLE Thread
)
3562 return STATUS_NOT_IMPLEMENTED
;