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 MS! */
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
= TRUE
;
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
= FALSE
;
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
= FALSE
;
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
= NULL
;
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
== NULL
)
356 return STATUS_INVALID_PRIMARY_GROUP
;
359 return STATUS_SUCCESS
;
367 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
,
368 _In_ BOOLEAN EffectiveOnly
,
369 _In_ TOKEN_TYPE TokenType
,
370 _In_ SECURITY_IMPERSONATION_LEVEL Level
,
371 _In_ KPROCESSOR_MODE PreviousMode
,
372 _Out_ PTOKEN
* NewAccessToken
)
382 Status
= ObCreateObject(PreviousMode
,
390 (PVOID
*)&AccessToken
);
391 if (!NT_SUCCESS(Status
))
393 DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status
);
397 /* Zero out the buffer */
398 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
400 ExAllocateLocallyUniqueId(&AccessToken
->TokenId
);
402 AccessToken
->TokenLock
= &SepTokenLock
;
404 /* Copy and reference the logon session */
405 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
406 SepRmReferenceLogonSession(&AccessToken
->AuthenticationId
);
408 AccessToken
->TokenType
= TokenType
;
409 AccessToken
->ImpersonationLevel
= Level
;
410 RtlCopyLuid(&AccessToken
->ModifiedId
, &Token
->ModifiedId
);
412 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
413 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
414 memcpy(AccessToken
->TokenSource
.SourceName
,
415 Token
->TokenSource
.SourceName
,
416 sizeof(Token
->TokenSource
.SourceName
));
417 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
418 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
419 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
421 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
422 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
423 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
425 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
428 if (AccessToken
->UserAndGroups
== NULL
)
430 Status
= STATUS_INSUFFICIENT_RESOURCES
;
434 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
436 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
437 Token
->UserAndGroups
,
439 AccessToken
->UserAndGroups
,
443 if (!NT_SUCCESS(Status
))
446 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
449 if (!NT_SUCCESS(Status
))
452 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
454 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
455 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
457 TAG_TOKEN_PRIVILAGES
);
458 if (AccessToken
->Privileges
== NULL
)
460 Status
= STATUS_INSUFFICIENT_RESOURCES
;
464 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
466 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
467 &Token
->Privileges
[i
].Luid
);
468 AccessToken
->Privileges
[i
].Attributes
=
469 Token
->Privileges
[i
].Attributes
;
472 if (Token
->DefaultDacl
)
474 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
475 Token
->DefaultDacl
->AclSize
,
477 if (AccessToken
->DefaultDacl
== NULL
)
479 Status
= STATUS_INSUFFICIENT_RESOURCES
;
483 memcpy(AccessToken
->DefaultDacl
,
485 Token
->DefaultDacl
->AclSize
);
488 *NewAccessToken
= AccessToken
;
491 if (!NT_SUCCESS(Status
))
493 /* Dereference the token, the delete procedure will clean up */
494 ObDereferenceObject(AccessToken
);
502 SeSubProcessToken(IN PTOKEN ParentToken
,
508 OBJECT_ATTRIBUTES ObjectAttributes
;
511 /* Initialize the attributes and duplicate it */
512 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
513 Status
= SepDuplicateToken(ParentToken
,
517 ParentToken
->ImpersonationLevel
,
520 if (NT_SUCCESS(Status
))
523 Status
= ObInsertObject(NewToken
,
529 if (NT_SUCCESS(Status
))
531 /* Set the session ID */
532 NewToken
->SessionId
= SessionId
;
533 NewToken
->TokenInUse
= InUse
;
535 /* Return the token */
546 SeIsTokenChild(IN PTOKEN Token
,
547 OUT PBOOLEAN IsChild
)
550 LUID ProcessLuid
, CallerLuid
;
555 /* Reference the process token */
556 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
559 ProcessLuid
= ProcessToken
->AuthenticationId
;
561 /* Dereference the token */
562 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
565 CallerLuid
= Token
->AuthenticationId
;
567 /* Compare the LUIDs */
568 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
571 return STATUS_SUCCESS
;
576 SeCopyClientToken(IN PACCESS_TOKEN Token
,
577 IN SECURITY_IMPERSONATION_LEVEL Level
,
578 IN KPROCESSOR_MODE PreviousMode
,
579 OUT PACCESS_TOKEN
* NewToken
)
582 OBJECT_ATTRIBUTES ObjectAttributes
;
586 InitializeObjectAttributes(&ObjectAttributes
,
592 Status
= SepDuplicateToken(Token
,
605 SepDeleteToken(PVOID ObjectBody
)
607 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
609 DPRINT("SepDeleteToken()\n");
611 /* Dereference the logon session */
612 SepRmDereferenceLogonSession(&AccessToken
->AuthenticationId
);
614 if (AccessToken
->UserAndGroups
)
615 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
617 if (AccessToken
->Privileges
)
618 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
620 if (AccessToken
->DefaultDacl
)
621 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
628 SepInitializeTokenImplementation(VOID
)
631 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
633 ExInitializeResource(&SepTokenLock
);
635 DPRINT("Creating Token Object Type\n");
637 /* Initialize the Token type */
638 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
639 RtlInitUnicodeString(&Name
, L
"Token");
640 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
641 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
642 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
643 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
644 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
645 ObjectTypeInitializer
.PoolType
= PagedPool
;
646 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
647 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
648 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
649 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SeTokenObjectType
);
654 SeAssignPrimaryToken(IN PEPROCESS Process
,
660 ASSERT(Token
->TokenType
== TokenPrimary
);
661 ASSERT(!Token
->TokenInUse
);
663 /* Clean any previous token */
664 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
666 /* Set the new token */
667 ObReferenceObject(Token
);
668 Token
->TokenInUse
= TRUE
;
669 ObInitializeFastReference(&Process
->Token
, Token
);
675 _Out_ PHANDLE TokenHandle
,
676 _In_ KPROCESSOR_MODE PreviousMode
,
677 _In_ ACCESS_MASK DesiredAccess
,
678 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
,
679 _In_ TOKEN_TYPE TokenType
,
680 _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
681 _In_ PLUID AuthenticationId
,
682 _In_ PLARGE_INTEGER ExpirationTime
,
683 _In_ PSID_AND_ATTRIBUTES User
,
684 _In_ ULONG GroupCount
,
685 _In_ PSID_AND_ATTRIBUTES Groups
,
686 _In_ ULONG GroupsLength
,
687 _In_ ULONG PrivilegeCount
,
688 _In_ PLUID_AND_ATTRIBUTES Privileges
,
690 _In_ PSID PrimaryGroup
,
691 _In_opt_ PACL DefaultDacl
,
692 _In_ PTOKEN_SOURCE TokenSource
,
693 _In_ BOOLEAN SystemToken
)
702 ULONG TokenFlags
= 0;
706 /* Loop all groups */
707 for (i
= 0; i
< GroupCount
; i
++)
709 /* Check for mandatory groups */
710 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
712 /* Force them to be enabled */
713 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
716 /* Check of the group is an admin group */
717 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
719 /* Remember this so we can optimize queries later */
720 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
724 ExAllocateLocallyUniqueId(&TokenId
);
725 ExAllocateLocallyUniqueId(&ModifiedId
);
727 Status
= ObCreateObject(PreviousMode
,
735 (PVOID
*)&AccessToken
);
736 if (!NT_SUCCESS(Status
))
738 DPRINT1("ObCreateObject() failed (Status 0x%lx)\n", Status
);
742 /* Zero out the buffer */
743 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
745 AccessToken
->TokenLock
= &SepTokenLock
;
747 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
748 &TokenSource
->SourceIdentifier
);
749 memcpy(AccessToken
->TokenSource
.SourceName
,
750 TokenSource
->SourceName
,
751 sizeof(TokenSource
->SourceName
));
753 /* Copy and reference the logon session */
754 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
755 SepRmReferenceLogonSession(&AccessToken
->AuthenticationId
);
757 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
758 AccessToken
->ExpirationTime
= *ExpirationTime
;
759 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
761 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
762 AccessToken
->PrivilegeCount
= PrivilegeCount
;
764 AccessToken
->TokenFlags
= TokenFlags
;
765 AccessToken
->TokenType
= TokenType
;
766 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
769 * Normally we would just point these members into the variable information
770 * area; however, our ObCreateObject() call can't allocate a variable information
771 * area, so we allocate them seperately and provide a destroy function.
774 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
775 uLength
+= RtlLengthSid(User
->Sid
);
776 for (i
= 0; i
< GroupCount
; i
++)
777 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
779 // FIXME: should use the object itself
780 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
783 if (AccessToken
->UserAndGroups
== NULL
)
785 Status
= STATUS_INSUFFICIENT_RESOURCES
;
789 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
791 Status
= RtlCopySidAndAttributesArray(1,
794 AccessToken
->UserAndGroups
,
798 if (!NT_SUCCESS(Status
))
801 Status
= RtlCopySidAndAttributesArray(GroupCount
,
804 &AccessToken
->UserAndGroups
[1],
808 if (!NT_SUCCESS(Status
))
811 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
814 if (!NT_SUCCESS(Status
))
817 // FIXME: should use the object itself
818 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
819 if (uLength
== 0) uLength
= sizeof(PVOID
);
820 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
822 TAG_TOKEN_PRIVILAGES
);
823 if (AccessToken
->Privileges
== NULL
)
825 Status
= STATUS_INSUFFICIENT_RESOURCES
;
829 if (PreviousMode
!= KernelMode
)
833 RtlCopyMemory(AccessToken
->Privileges
,
835 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
837 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
839 Status
= _SEH2_GetExceptionCode();
845 RtlCopyMemory(AccessToken
->Privileges
,
847 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
850 if (!NT_SUCCESS(Status
))
853 /* Update privilege flags */
854 SepUpdatePrivilegeFlagsToken(AccessToken
);
856 if (DefaultDacl
!= NULL
)
858 // FIXME: should use the object itself
859 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
860 DefaultDacl
->AclSize
,
862 if (AccessToken
->DefaultDacl
== NULL
)
864 Status
= STATUS_INSUFFICIENT_RESOURCES
;
868 RtlCopyMemory(AccessToken
->DefaultDacl
,
870 DefaultDacl
->AclSize
);
874 AccessToken
->DefaultDacl
= NULL
;
879 Status
= ObInsertObject(AccessToken
,
885 if (!NT_SUCCESS(Status
))
887 DPRINT1("ObInsertObject() failed (Status 0x%lx)\n", Status
);
892 /* Return pointer instead of handle */
893 *TokenHandle
= (HANDLE
)AccessToken
;
897 if (!NT_SUCCESS(Status
))
899 /* Dereference the token, the delete procedure will clean up */
900 ObDereferenceObject(AccessToken
);
908 SepCreateSystemProcessToken(VOID
)
910 LUID_AND_ATTRIBUTES Privileges
[25];
911 ULONG GroupAttributes
, OwnerAttributes
;
912 SID_AND_ATTRIBUTES Groups
[32];
913 LARGE_INTEGER Expiration
;
914 SID_AND_ATTRIBUTES UserSid
;
917 OBJECT_ATTRIBUTES ObjectAttributes
;
923 /* Don't ever expire */
924 Expiration
.QuadPart
= -1;
926 /* All groups mandatory and enabled */
927 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
928 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
931 UserSid
.Sid
= SeLocalSystemSid
;
932 UserSid
.Attributes
= 0;
934 /* Primary group is local system */
935 PrimaryGroup
= SeLocalSystemSid
;
937 /* Owner is admins */
938 Owner
= SeAliasAdminsSid
;
940 /* Groups are admins, world, and authenticated users */
941 Groups
[0].Sid
= SeAliasAdminsSid
;
942 Groups
[0].Attributes
= OwnerAttributes
;
943 Groups
[1].Sid
= SeWorldSid
;
944 Groups
[1].Attributes
= GroupAttributes
;
945 Groups
[2].Sid
= SeAuthenticatedUserSid
;
946 Groups
[2].Attributes
= OwnerAttributes
;
947 GroupsLength
= sizeof(SID_AND_ATTRIBUTES
) +
948 SeLengthSid(Groups
[0].Sid
) +
949 SeLengthSid(Groups
[1].Sid
) +
950 SeLengthSid(Groups
[2].Sid
);
951 ASSERT(GroupsLength
<= sizeof(Groups
));
953 /* Setup the privileges */
955 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
956 Privileges
[i
++].Luid
= SeTcbPrivilege
;
958 Privileges
[i
].Attributes
= 0;
959 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
961 Privileges
[i
].Attributes
= 0;
962 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
964 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
965 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
967 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
968 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
970 Privileges
[i
].Attributes
= 0;
971 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
973 Privileges
[i
].Attributes
= 0;
974 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
976 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
977 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
979 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
980 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
982 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
983 Privileges
[i
++].Luid
= SeDebugPrivilege
;
985 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
986 Privileges
[i
++].Luid
= SeAuditPrivilege
;
988 Privileges
[i
].Attributes
= 0;
989 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
991 Privileges
[i
].Attributes
= 0;
992 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
994 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
995 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
997 Privileges
[i
].Attributes
= 0;
998 Privileges
[i
++].Luid
= SeBackupPrivilege
;
1000 Privileges
[i
].Attributes
= 0;
1001 Privileges
[i
++].Luid
= SeRestorePrivilege
;
1003 Privileges
[i
].Attributes
= 0;
1004 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1006 Privileges
[i
].Attributes
= 0;
1007 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1009 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
1010 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1012 Privileges
[i
].Attributes
= 0;
1013 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1016 /* Setup the object attributes */
1017 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1018 ASSERT(SeSystemDefaultDacl
!= NULL
);
1020 /* Create the token */
1021 Status
= SepCreateToken((PHANDLE
)&Token
,
1027 &SeSystemAuthenticationId
,
1037 SeSystemDefaultDacl
,
1038 &SeSystemTokenSource
,
1040 ASSERT(Status
== STATUS_SUCCESS
);
1042 /* Return the token */
1046 /* PUBLIC FUNCTIONS ***********************************************************/
1053 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
1055 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
1056 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
1057 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
1058 OUT PACCESS_TOKEN
* FilteredToken
)
1061 return STATUS_NOT_IMPLEMENTED
;
1067 * NOTE: SeQueryInformationToken is just NtQueryInformationToken without all
1068 * the bells and whistles needed for user-mode buffer access protection.
1072 SeQueryInformationToken(IN PACCESS_TOKEN AccessToken
,
1073 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1074 OUT PVOID
*TokenInformation
)
1077 PTOKEN Token
= (PTOKEN
)AccessToken
;
1078 ULONG RequiredLength
;
1087 if (TokenInformationClass
>= MaxTokenInfoClass
)
1089 DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1090 return STATUS_INVALID_INFO_CLASS
;
1093 switch (TokenInformationClass
)
1099 DPRINT("SeQueryInformationToken(TokenUser)\n");
1100 RequiredLength
= sizeof(TOKEN_USER
) +
1101 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1103 /* Allocate the output buffer */
1104 tu
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1107 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1111 Status
= RtlCopySidAndAttributesArray(1,
1112 &Token
->UserAndGroups
[0],
1113 RequiredLength
- sizeof(TOKEN_USER
),
1119 /* Return the structure */
1120 *TokenInformation
= tu
;
1121 Status
= STATUS_SUCCESS
;
1131 DPRINT("SeQueryInformationToken(TokenGroups)\n");
1132 RequiredLength
= sizeof(tg
->GroupCount
) +
1133 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1135 SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1136 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1138 /* Allocate the output buffer */
1139 tg
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1142 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1146 Sid
= (PSID
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
1147 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1149 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1150 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1151 &Token
->UserAndGroups
[1],
1158 /* Return the structure */
1159 *TokenInformation
= tg
;
1160 Status
= STATUS_SUCCESS
;
1164 case TokenPrivileges
:
1166 PTOKEN_PRIVILEGES tp
;
1168 DPRINT("SeQueryInformationToken(TokenPrivileges)\n");
1169 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1170 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1172 /* Allocate the output buffer */
1173 tp
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1176 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1180 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1181 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1183 &tp
->Privileges
[0]);
1185 /* Return the structure */
1186 *TokenInformation
= tp
;
1187 Status
= STATUS_SUCCESS
;
1196 DPRINT("SeQueryInformationToken(TokenOwner)\n");
1197 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1198 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1200 /* Allocate the output buffer */
1201 to
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1204 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1208 to
->Owner
= (PSID
)(to
+ 1);
1209 Status
= RtlCopySid(SidLen
,
1211 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1213 /* Return the structure */
1214 *TokenInformation
= to
;
1215 Status
= STATUS_SUCCESS
;
1219 case TokenPrimaryGroup
:
1221 PTOKEN_PRIMARY_GROUP tpg
;
1224 DPRINT("SeQueryInformationToken(TokenPrimaryGroup)\n");
1225 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1226 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1228 /* Allocate the output buffer */
1229 tpg
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1232 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1236 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1237 Status
= RtlCopySid(SidLen
,
1239 Token
->PrimaryGroup
);
1241 /* Return the structure */
1242 *TokenInformation
= tpg
;
1243 Status
= STATUS_SUCCESS
;
1247 case TokenDefaultDacl
:
1249 PTOKEN_DEFAULT_DACL tdd
;
1251 DPRINT("SeQueryInformationToken(TokenDefaultDacl)\n");
1252 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1254 if (Token
->DefaultDacl
!= NULL
)
1255 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1257 /* Allocate the output buffer */
1258 tdd
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1261 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1265 if (Token
->DefaultDacl
!= NULL
)
1267 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1268 RtlCopyMemory(tdd
->DefaultDacl
,
1270 Token
->DefaultDacl
->AclSize
);
1274 tdd
->DefaultDacl
= NULL
;
1277 /* Return the structure */
1278 *TokenInformation
= tdd
;
1279 Status
= STATUS_SUCCESS
;
1287 DPRINT("SeQueryInformationToken(TokenSource)\n");
1288 RequiredLength
= sizeof(TOKEN_SOURCE
);
1290 /* Allocate the output buffer */
1291 ts
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1294 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1298 *ts
= Token
->TokenSource
;
1300 /* Return the structure */
1301 *TokenInformation
= ts
;
1302 Status
= STATUS_SUCCESS
;
1310 DPRINT("SeQueryInformationToken(TokenType)\n");
1311 RequiredLength
= sizeof(TOKEN_TYPE
);
1313 /* Allocate the output buffer */
1314 tt
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1317 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1321 *tt
= Token
->TokenType
;
1323 /* Return the structure */
1324 *TokenInformation
= tt
;
1325 Status
= STATUS_SUCCESS
;
1329 case TokenImpersonationLevel
:
1331 PSECURITY_IMPERSONATION_LEVEL sil
;
1333 DPRINT("SeQueryInformationToken(TokenImpersonationLevel)\n");
1334 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1336 /* Fail if the token is not an impersonation token */
1337 if (Token
->TokenType
!= TokenImpersonation
)
1339 Status
= STATUS_INVALID_INFO_CLASS
;
1343 /* Allocate the output buffer */
1344 sil
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1347 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1351 *sil
= Token
->ImpersonationLevel
;
1353 /* Return the structure */
1354 *TokenInformation
= sil
;
1355 Status
= STATUS_SUCCESS
;
1359 case TokenStatistics
:
1361 PTOKEN_STATISTICS ts
;
1363 DPRINT("SeQueryInformationToken(TokenStatistics)\n");
1364 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1366 /* Allocate the output buffer */
1367 ts
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1370 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1374 ts
->TokenId
= Token
->TokenId
;
1375 ts
->AuthenticationId
= Token
->AuthenticationId
;
1376 ts
->ExpirationTime
= Token
->ExpirationTime
;
1377 ts
->TokenType
= Token
->TokenType
;
1378 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1379 ts
->DynamicCharged
= Token
->DynamicCharged
;
1380 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1381 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1382 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1383 ts
->ModifiedId
= Token
->ModifiedId
;
1385 /* Return the structure */
1386 *TokenInformation
= ts
;
1387 Status
= STATUS_SUCCESS
;
1392 * The following 4 cases are only implemented in NtQueryInformationToken
1400 DPRINT("SeQueryInformationToken(TokenOrigin)\n");
1401 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1403 /* Allocate the output buffer */
1404 to
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1407 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1411 RtlCopyLuid(&to
->OriginatingLogonSession
,
1412 &Token
->AuthenticationId
);
1414 /* Return the structure */
1415 *TokenInformation
= to
;
1416 Status
= STATUS_SUCCESS
;
1420 case TokenGroupsAndPrivileges
:
1421 DPRINT1("SeQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1422 Status
= STATUS_NOT_IMPLEMENTED
;
1425 case TokenRestrictedSids
:
1427 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1431 DPRINT("SeQueryInformationToken(TokenRestrictedSids)\n");
1432 RequiredLength
= sizeof(tg
->GroupCount
) +
1433 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1435 SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1436 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1438 /* Allocate the output buffer */
1439 tg
= ExAllocatePoolWithTag(PagedPool
, RequiredLength
, TAG_SE
);
1442 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1446 Sid
= (PSID
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
1447 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1449 tg
->GroupCount
= Token
->RestrictedSidCount
;
1450 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1451 Token
->RestrictedSids
,
1458 /* Return the structure */
1459 *TokenInformation
= tg
;
1460 Status
= STATUS_SUCCESS
;
1464 case TokenSandBoxInert
:
1465 DPRINT1("SeQueryInformationToken(TokenSandboxInert) not implemented\n");
1466 Status
= STATUS_NOT_IMPLEMENTED
;
1471 case TokenSessionId
:
1473 DPRINT("SeQueryInformationToken(TokenSessionId)\n");
1475 Status
= SeQuerySessionIdToken(Token
, (PULONG
)TokenInformation
);
1477 // Status = STATUS_SUCCESS;
1482 DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1483 Status
= STATUS_INVALID_INFO_CLASS
;
1495 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
1496 IN PULONG pSessionId
)
1498 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1499 return STATUS_SUCCESS
;
1507 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1512 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
1514 return STATUS_SUCCESS
;
1521 SECURITY_IMPERSONATION_LEVEL
1523 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1527 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1535 SeTokenType(IN PACCESS_TOKEN Token
)
1539 return ((PTOKEN
)Token
)->TokenType
;
1548 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
1552 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
1560 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
1564 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
1572 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
1576 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
1579 /* SYSTEM CALLS ***************************************************************/
1585 NtQueryInformationToken(IN HANDLE TokenHandle
,
1586 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1587 OUT PVOID TokenInformation
,
1588 IN ULONG TokenInformationLength
,
1589 OUT PULONG ReturnLength
)
1592 KPROCESSOR_MODE PreviousMode
;
1594 ULONG RequiredLength
;
1603 PreviousMode
= ExGetPreviousMode();
1605 /* Check buffers and class validity */
1606 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1607 SeTokenInformationClass
,
1608 RTL_NUMBER_OF(SeTokenInformationClass
),
1610 TokenInformationLength
,
1614 if (!NT_SUCCESS(Status
))
1616 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1620 Status
= ObReferenceObjectByHandle(TokenHandle
,
1621 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1626 if (NT_SUCCESS(Status
))
1628 switch (TokenInformationClass
)
1632 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1634 DPRINT("NtQueryInformationToken(TokenUser)\n");
1635 RequiredLength
= sizeof(TOKEN_USER
) +
1636 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1640 if (TokenInformationLength
>= RequiredLength
)
1642 Status
= RtlCopySidAndAttributesArray(1,
1643 &Token
->UserAndGroups
[0],
1644 RequiredLength
- sizeof(TOKEN_USER
),
1652 Status
= STATUS_BUFFER_TOO_SMALL
;
1655 if (ReturnLength
!= NULL
)
1657 *ReturnLength
= RequiredLength
;
1660 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1662 Status
= _SEH2_GetExceptionCode();
1671 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1673 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1674 RequiredLength
= sizeof(tg
->GroupCount
) +
1675 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1679 if (TokenInformationLength
>= RequiredLength
)
1681 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1682 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1683 PSID Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
1684 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1686 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1687 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1688 &Token
->UserAndGroups
[1],
1697 Status
= STATUS_BUFFER_TOO_SMALL
;
1700 if (ReturnLength
!= NULL
)
1702 *ReturnLength
= RequiredLength
;
1705 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1707 Status
= _SEH2_GetExceptionCode();
1714 case TokenPrivileges
:
1716 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1718 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1719 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1720 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1724 if (TokenInformationLength
>= RequiredLength
)
1726 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1727 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1729 &tp
->Privileges
[0]);
1733 Status
= STATUS_BUFFER_TOO_SMALL
;
1736 if (ReturnLength
!= NULL
)
1738 *ReturnLength
= RequiredLength
;
1741 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1743 Status
= _SEH2_GetExceptionCode();
1752 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1755 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1756 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1757 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1761 if (TokenInformationLength
>= RequiredLength
)
1763 to
->Owner
= (PSID
)(to
+ 1);
1764 Status
= RtlCopySid(SidLen
,
1766 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1770 Status
= STATUS_BUFFER_TOO_SMALL
;
1773 if (ReturnLength
!= NULL
)
1775 *ReturnLength
= RequiredLength
;
1778 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1780 Status
= _SEH2_GetExceptionCode();
1787 case TokenPrimaryGroup
:
1789 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1792 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1793 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1794 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1798 if (TokenInformationLength
>= RequiredLength
)
1800 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1801 Status
= RtlCopySid(SidLen
,
1803 Token
->PrimaryGroup
);
1807 Status
= STATUS_BUFFER_TOO_SMALL
;
1810 if (ReturnLength
!= NULL
)
1812 *ReturnLength
= RequiredLength
;
1815 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1817 Status
= _SEH2_GetExceptionCode();
1824 case TokenDefaultDacl
:
1826 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1828 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1829 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1831 if (Token
->DefaultDacl
!= NULL
)
1832 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1836 if (TokenInformationLength
>= RequiredLength
)
1838 if (Token
->DefaultDacl
!= NULL
)
1840 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1841 RtlCopyMemory(tdd
->DefaultDacl
,
1843 Token
->DefaultDacl
->AclSize
);
1847 tdd
->DefaultDacl
= NULL
;
1852 Status
= STATUS_BUFFER_TOO_SMALL
;
1855 if (ReturnLength
!= NULL
)
1857 *ReturnLength
= RequiredLength
;
1860 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1862 Status
= _SEH2_GetExceptionCode();
1871 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1873 DPRINT("NtQueryInformationToken(TokenSource)\n");
1874 RequiredLength
= sizeof(TOKEN_SOURCE
);
1878 if (TokenInformationLength
>= RequiredLength
)
1880 *ts
= Token
->TokenSource
;
1884 Status
= STATUS_BUFFER_TOO_SMALL
;
1887 if (ReturnLength
!= NULL
)
1889 *ReturnLength
= RequiredLength
;
1892 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1894 Status
= _SEH2_GetExceptionCode();
1903 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1905 DPRINT("NtQueryInformationToken(TokenType)\n");
1906 RequiredLength
= sizeof(TOKEN_TYPE
);
1910 if (TokenInformationLength
>= RequiredLength
)
1912 *tt
= Token
->TokenType
;
1916 Status
= STATUS_BUFFER_TOO_SMALL
;
1919 if (ReturnLength
!= NULL
)
1921 *ReturnLength
= RequiredLength
;
1924 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1926 Status
= _SEH2_GetExceptionCode();
1933 case TokenImpersonationLevel
:
1935 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1937 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1939 /* Fail if the token is not an impersonation token */
1940 if (Token
->TokenType
!= TokenImpersonation
)
1942 Status
= STATUS_INVALID_INFO_CLASS
;
1946 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1950 if (TokenInformationLength
>= RequiredLength
)
1952 *sil
= Token
->ImpersonationLevel
;
1956 Status
= STATUS_BUFFER_TOO_SMALL
;
1959 if (ReturnLength
!= NULL
)
1961 *ReturnLength
= RequiredLength
;
1964 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1966 Status
= _SEH2_GetExceptionCode();
1973 case TokenStatistics
:
1975 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1977 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1978 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1982 if (TokenInformationLength
>= RequiredLength
)
1984 ts
->TokenId
= Token
->TokenId
;
1985 ts
->AuthenticationId
= Token
->AuthenticationId
;
1986 ts
->ExpirationTime
= Token
->ExpirationTime
;
1987 ts
->TokenType
= Token
->TokenType
;
1988 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1989 ts
->DynamicCharged
= Token
->DynamicCharged
;
1990 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1991 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1992 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1993 ts
->ModifiedId
= Token
->ModifiedId
;
1997 Status
= STATUS_BUFFER_TOO_SMALL
;
2000 if (ReturnLength
!= NULL
)
2002 *ReturnLength
= RequiredLength
;
2005 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2007 Status
= _SEH2_GetExceptionCode();
2016 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
2018 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
2019 RequiredLength
= sizeof(TOKEN_ORIGIN
);
2023 if (TokenInformationLength
>= RequiredLength
)
2025 RtlCopyLuid(&to
->OriginatingLogonSession
,
2026 &Token
->AuthenticationId
);
2030 Status
= STATUS_BUFFER_TOO_SMALL
;
2033 if (ReturnLength
!= NULL
)
2035 *ReturnLength
= RequiredLength
;
2038 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2040 Status
= _SEH2_GetExceptionCode();
2047 case TokenGroupsAndPrivileges
:
2048 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
2049 Status
= STATUS_NOT_IMPLEMENTED
;
2052 case TokenRestrictedSids
:
2054 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
2056 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
2057 RequiredLength
= sizeof(tg
->GroupCount
) +
2058 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
2062 if (TokenInformationLength
>= RequiredLength
)
2064 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
2065 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
2066 PSID Sid
= (PSID
)((ULONG_PTR
)tg
+ sizeof(tg
->GroupCount
) +
2067 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
2069 tg
->GroupCount
= Token
->RestrictedSidCount
;
2070 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
2071 Token
->RestrictedSids
,
2080 Status
= STATUS_BUFFER_TOO_SMALL
;
2083 if (ReturnLength
!= NULL
)
2085 *ReturnLength
= RequiredLength
;
2088 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2090 Status
= _SEH2_GetExceptionCode();
2097 case TokenSandBoxInert
:
2098 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
2099 Status
= STATUS_NOT_IMPLEMENTED
;
2102 case TokenSessionId
:
2104 ULONG SessionId
= 0;
2106 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
2108 Status
= SeQuerySessionIdToken(Token
, &SessionId
);
2109 if (NT_SUCCESS(Status
))
2113 /* Buffer size was already verified, no need to check here again */
2114 *(PULONG
)TokenInformation
= SessionId
;
2116 if (ReturnLength
!= NULL
)
2118 *ReturnLength
= sizeof(ULONG
);
2121 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2123 Status
= _SEH2_GetExceptionCode();
2132 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
2133 Status
= STATUS_INVALID_INFO_CLASS
;
2137 ObDereferenceObject(Token
);
2145 * NtSetTokenInformation: Partly implemented.
2147 * TokenOrigin, TokenDefaultDacl
2150 NtSetInformationToken(IN HANDLE TokenHandle
,
2151 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
2152 IN PVOID TokenInformation
,
2153 IN ULONG TokenInformationLength
)
2156 KPROCESSOR_MODE PreviousMode
;
2157 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
2162 PreviousMode
= ExGetPreviousMode();
2164 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
2165 SeTokenInformationClass
,
2166 RTL_NUMBER_OF(SeTokenInformationClass
),
2168 TokenInformationLength
,
2170 if (!NT_SUCCESS(Status
))
2172 /* Invalid buffers */
2173 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
2177 if (TokenInformationClass
== TokenSessionId
)
2179 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
2182 Status
= ObReferenceObjectByHandle(TokenHandle
,
2188 if (NT_SUCCESS(Status
))
2190 switch (TokenInformationClass
)
2194 if (TokenInformationLength
>= sizeof(TOKEN_OWNER
))
2196 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
2197 PSID InputSid
= NULL
, CapturedSid
;
2201 InputSid
= to
->Owner
;
2203 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2205 Status
= _SEH2_GetExceptionCode();
2206 _SEH2_YIELD(goto Cleanup
);
2210 Status
= SepCaptureSid(InputSid
,
2215 if (NT_SUCCESS(Status
))
2217 RtlCopySid(RtlLengthSid(CapturedSid
),
2218 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
2220 SepReleaseSid(CapturedSid
,
2227 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2232 case TokenPrimaryGroup
:
2234 if (TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
2236 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
2237 PSID InputSid
= NULL
, CapturedSid
;
2241 InputSid
= tpg
->PrimaryGroup
;
2243 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2245 Status
= _SEH2_GetExceptionCode();
2246 _SEH2_YIELD(goto Cleanup
);
2250 Status
= SepCaptureSid(InputSid
,
2255 if (NT_SUCCESS(Status
))
2257 RtlCopySid(RtlLengthSid(CapturedSid
),
2258 Token
->PrimaryGroup
,
2260 SepReleaseSid(CapturedSid
,
2267 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2272 case TokenDefaultDacl
:
2274 if (TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
2276 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
2277 PACL InputAcl
= NULL
;
2281 InputAcl
= tdd
->DefaultDacl
;
2283 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2285 Status
= _SEH2_GetExceptionCode();
2286 _SEH2_YIELD(goto Cleanup
);
2290 if (InputAcl
!= NULL
)
2294 /* Capture and copy the dacl */
2295 Status
= SepCaptureAcl(InputAcl
,
2300 if (NT_SUCCESS(Status
))
2302 /* Free the previous dacl if present */
2303 if(Token
->DefaultDacl
!= NULL
)
2305 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
2308 Token
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
2309 CapturedAcl
->AclSize
,
2311 if (!Token
->DefaultDacl
)
2313 ExFreePoolWithTag(CapturedAcl
, TAG_ACL
);
2314 Status
= STATUS_NO_MEMORY
;
2318 /* Set the new dacl */
2319 RtlCopyMemory(Token
->DefaultDacl
, CapturedAcl
, CapturedAcl
->AclSize
);
2320 ExFreePoolWithTag(CapturedAcl
, TAG_ACL
);
2326 /* Clear and free the default dacl if present */
2327 if (Token
->DefaultDacl
!= NULL
)
2329 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
2330 Token
->DefaultDacl
= NULL
;
2336 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2341 case TokenSessionId
:
2343 ULONG SessionId
= 0;
2347 /* Buffer size was already verified, no need to check here again */
2348 SessionId
= *(PULONG
)TokenInformation
;
2350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2352 Status
= _SEH2_GetExceptionCode();
2353 _SEH2_YIELD(goto Cleanup
);
2357 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2360 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2364 Token
->SessionId
= SessionId
;
2368 case TokenSessionReference
:
2370 ULONG SessionReference
;
2374 /* Buffer size was already verified, no need to check here again */
2375 SessionReference
= *(PULONG
)TokenInformation
;
2377 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2379 Status
= _SEH2_GetExceptionCode();
2380 _SEH2_YIELD(goto Cleanup
);
2384 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
2386 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2390 /* Check if it is 0 */
2391 if (SessionReference
== 0)
2393 /* Atomically set the flag in the token */
2394 RtlInterlockedSetBits(&Token
->TokenFlags
,
2395 TOKEN_SESSION_NOT_REFERENCED
);
2401 case TokenAuditPolicy
:
2403 PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation
=
2404 (PTOKEN_AUDIT_POLICY_INFORMATION
)TokenInformation
;
2405 SEP_AUDIT_POLICY AuditPolicy
;
2410 ProbeForRead(PolicyInformation
,
2411 FIELD_OFFSET(TOKEN_AUDIT_POLICY_INFORMATION
,
2412 Policies
[PolicyInformation
->PolicyCount
]),
2415 /* Loop all policies in the structure */
2416 for (i
= 0; i
< PolicyInformation
->PolicyCount
; i
++)
2418 /* Set the corresponding bits in the packed structure */
2419 switch (PolicyInformation
->Policies
[i
].Category
)
2421 case AuditCategorySystem
:
2422 AuditPolicy
.PolicyElements
.System
= PolicyInformation
->Policies
[i
].Value
;
2425 case AuditCategoryLogon
:
2426 AuditPolicy
.PolicyElements
.Logon
= PolicyInformation
->Policies
[i
].Value
;
2429 case AuditCategoryObjectAccess
:
2430 AuditPolicy
.PolicyElements
.ObjectAccess
= PolicyInformation
->Policies
[i
].Value
;
2433 case AuditCategoryPrivilegeUse
:
2434 AuditPolicy
.PolicyElements
.PrivilegeUse
= PolicyInformation
->Policies
[i
].Value
;
2437 case AuditCategoryDetailedTracking
:
2438 AuditPolicy
.PolicyElements
.DetailedTracking
= PolicyInformation
->Policies
[i
].Value
;
2441 case AuditCategoryPolicyChange
:
2442 AuditPolicy
.PolicyElements
.PolicyChange
= PolicyInformation
->Policies
[i
].Value
;
2445 case AuditCategoryAccountManagement
:
2446 AuditPolicy
.PolicyElements
.AccountManagement
= PolicyInformation
->Policies
[i
].Value
;
2449 case AuditCategoryDirectoryServiceAccess
:
2450 AuditPolicy
.PolicyElements
.DirectoryServiceAccess
= PolicyInformation
->Policies
[i
].Value
;
2453 case AuditCategoryAccountLogon
:
2454 AuditPolicy
.PolicyElements
.AccountLogon
= PolicyInformation
->Policies
[i
].Value
;
2459 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2461 Status
= _SEH2_GetExceptionCode();
2462 _SEH2_YIELD(goto Cleanup
);
2466 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2469 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2473 /* Lock the token */
2474 SepAcquireTokenLockExclusive(Token
);
2476 /* Set the new audit policy */
2477 Token
->AuditPolicy
= AuditPolicy
;
2479 /* Unlock the token */
2480 SepReleaseTokenLock(Token
);
2487 TOKEN_ORIGIN TokenOrigin
;
2491 /* Copy the token origin */
2492 TokenOrigin
= *(PTOKEN_ORIGIN
)TokenInformation
;
2494 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2496 Status
= _SEH2_GetExceptionCode();
2497 _SEH2_YIELD(goto Cleanup
);
2501 /* Check for TCB privilege */
2502 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
2504 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2508 /* Lock the token */
2509 SepAcquireTokenLockExclusive(Token
);
2511 /* Check if there is no token origin set yet */
2512 if ((Token
->OriginatingLogonSession
.LowPart
== 0) &&
2513 (Token
->OriginatingLogonSession
.HighPart
== 0))
2515 /* Set the token origin */
2516 Token
->OriginatingLogonSession
=
2517 TokenOrigin
.OriginatingLogonSession
;
2520 /* Unlock the token */
2521 SepReleaseTokenLock(Token
);
2528 DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
2529 TokenInformationClass
);
2530 Status
= STATUS_INVALID_INFO_CLASS
;
2535 ObDereferenceObject(Token
);
2538 if (!NT_SUCCESS(Status
))
2540 DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status
);
2550 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
2551 * this is certainly NOT true, although I can't say for sure that EffectiveOnly
2552 * is correct either. -Gunnar
2553 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
2554 * NOTE for readers: http://hex.pp.ua/nt/NtDuplicateToken.php is therefore
2555 * wrong in that regard.
2558 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
2559 IN ACCESS_MASK DesiredAccess
,
2560 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
2561 IN BOOLEAN EffectiveOnly
,
2562 IN TOKEN_TYPE TokenType
,
2563 OUT PHANDLE NewTokenHandle
)
2565 KPROCESSOR_MODE PreviousMode
;
2569 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
2571 OBJECT_HANDLE_INFORMATION HandleInformation
;
2576 if (TokenType
!= TokenImpersonation
&&
2577 TokenType
!= TokenPrimary
)
2578 return STATUS_INVALID_PARAMETER
;
2580 PreviousMode
= KeGetPreviousMode();
2582 if (PreviousMode
!= KernelMode
)
2586 ProbeForWriteHandle(NewTokenHandle
);
2588 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2590 /* Return the exception code */
2591 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2596 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
2600 &CapturedSecurityQualityOfService
,
2602 if (!NT_SUCCESS(Status
))
2604 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
2608 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
2613 &HandleInformation
);
2614 if (!NT_SUCCESS(Status
))
2616 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2623 * Fail, if the original token is an impersonation token and the caller
2624 * tries to raise the impersonation level of the new token above the
2625 * impersonation level of the original token.
2627 if (Token
->TokenType
== TokenImpersonation
)
2630 CapturedSecurityQualityOfService
->ImpersonationLevel
>Token
->ImpersonationLevel
)
2632 ObDereferenceObject(Token
);
2633 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2636 return STATUS_BAD_IMPERSONATION_LEVEL
;
2641 * Fail, if a primary token is to be created from an impersonation token
2642 * and and the impersonation level of the impersonation token is below SecurityImpersonation.
2644 if (Token
->TokenType
== TokenImpersonation
&&
2645 TokenType
== TokenPrimary
&&
2646 Token
->ImpersonationLevel
< SecurityImpersonation
)
2648 ObDereferenceObject(Token
);
2649 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2652 return STATUS_BAD_IMPERSONATION_LEVEL
;
2655 Status
= SepDuplicateToken(Token
,
2659 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
2663 ObDereferenceObject(Token
);
2665 if (NT_SUCCESS(Status
))
2667 Status
= ObInsertObject(NewToken
,
2669 (DesiredAccess
? DesiredAccess
: HandleInformation
.GrantedAccess
),
2673 if (NT_SUCCESS(Status
))
2677 *NewTokenHandle
= hToken
;
2679 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2681 Status
= _SEH2_GetExceptionCode();
2687 /* Free the captured structure */
2688 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2696 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
2697 IN BOOLEAN ResetToDefault
,
2698 IN PTOKEN_GROUPS NewState
,
2699 IN ULONG BufferLength
,
2700 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
2701 OUT PULONG ReturnLength
)
2704 return STATUS_NOT_IMPLEMENTED
;
2710 SepAdjustPrivileges(
2711 _Inout_ PTOKEN Token
,
2712 _In_ BOOLEAN DisableAllPrivileges
,
2713 _In_opt_ PLUID_AND_ATTRIBUTES NewState
,
2714 _In_ ULONG NewStateCount
,
2715 _Out_opt_ PTOKEN_PRIVILEGES PreviousState
,
2716 _In_ BOOLEAN ApplyChanges
,
2717 _Out_ PULONG ChangedPrivileges
)
2719 ULONG i
, j
, PrivilegeCount
, ChangeCount
, NewAttributes
;
2721 /* Count the found privileges and those that need to be changed */
2725 /* Loop all privileges in the token */
2726 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2728 /* Shall all of them be disabled? */
2729 if (DisableAllPrivileges
)
2731 /* The new attributes are the old ones, but disabled */
2732 NewAttributes
= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2736 /* Otherwise loop all provided privileges */
2737 for (j
= 0; j
< NewStateCount
; j
++)
2739 /* Check if this is the LUID we are looking for */
2740 if (RtlEqualLuid(&Token
->Privileges
[i
].Luid
, &NewState
[j
].Luid
))
2742 DPRINT("Found privilege\n");
2744 /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
2745 NewAttributes
= NewState
[j
].Attributes
;
2746 NewAttributes
&= (SE_PRIVILEGE_ENABLED
| SE_PRIVILEGE_REMOVED
);
2747 NewAttributes
|= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2754 /* Check if we didn't find the privilege */
2755 if (j
== NewStateCount
)
2757 /* Continue with the token's next privilege */
2762 /* We found a privilege, count it */
2765 /* Does the privilege need to be changed? */
2766 if (Token
->Privileges
[i
].Attributes
!= NewAttributes
)
2768 /* Does the caller want the old privileges? */
2769 if (PreviousState
!= NULL
)
2771 /* Copy the old privilege */
2772 PreviousState
->Privileges
[ChangeCount
] = Token
->Privileges
[i
];
2775 /* Does the caller want to apply the changes? */
2778 /* Shall we remove the privilege? */
2779 if (NewAttributes
& SE_PRIVILEGE_REMOVED
)
2781 /* Set the token as disabled and update flags for it */
2782 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2783 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2785 /* Remove the privilege */
2786 SepRemovePrivilegeToken(Token
, i
);
2788 /* Fix the running index */
2791 /* Continue with next */
2795 /* Set the new attributes and update flags */
2796 Token
->Privileges
[i
].Attributes
= NewAttributes
;
2797 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2800 /* Increment the change count */
2805 /* Set the number of saved privileges */
2806 if (PreviousState
!= NULL
)
2807 PreviousState
->PrivilegeCount
= ChangeCount
;
2809 /* Return the number of changed privileges */
2810 *ChangedPrivileges
= ChangeCount
;
2812 /* Check if we missed some */
2813 if (!DisableAllPrivileges
&& (PrivilegeCount
< NewStateCount
))
2815 return STATUS_NOT_ALL_ASSIGNED
;
2818 return STATUS_SUCCESS
;
2825 _Must_inspect_result_
2829 NtAdjustPrivilegesToken(
2830 _In_ HANDLE TokenHandle
,
2831 _In_ BOOLEAN DisableAllPrivileges
,
2832 _In_opt_ PTOKEN_PRIVILEGES NewState
,
2833 _In_ ULONG BufferLength
,
2834 _Out_writes_bytes_to_opt_(BufferLength
,*ReturnLength
)
2835 PTOKEN_PRIVILEGES PreviousState
,
2836 _When_(PreviousState
!=NULL
, _Out_
) PULONG ReturnLength
)
2838 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2839 KPROCESSOR_MODE PreviousMode
;
2840 ULONG CapturedCount
= 0;
2841 ULONG CapturedLength
= 0;
2842 ULONG NewStateSize
= 0;
2844 ULONG RequiredLength
;
2849 DPRINT("NtAdjustPrivilegesToken() called\n");
2851 /* Fail, if we do not disable all privileges but NewState is NULL */
2852 if (DisableAllPrivileges
== FALSE
&& NewState
== NULL
)
2853 return STATUS_INVALID_PARAMETER
;
2855 PreviousMode
= KeGetPreviousMode();
2856 if (PreviousMode
!= KernelMode
)
2860 /* Probe NewState */
2861 if (DisableAllPrivileges
== FALSE
)
2863 /* First probe the header */
2864 ProbeForRead(NewState
, sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
));
2866 CapturedCount
= NewState
->PrivilegeCount
;
2867 NewStateSize
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[CapturedCount
]);
2869 ProbeForRead(NewState
, NewStateSize
, sizeof(ULONG
));
2872 /* Probe PreviousState and ReturnLength */
2873 if (PreviousState
!= NULL
)
2875 ProbeForWrite(PreviousState
, BufferLength
, sizeof(ULONG
));
2876 ProbeForWrite(ReturnLength
, sizeof(ULONG
), sizeof(ULONG
));
2879 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2881 /* Return the exception code */
2882 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2888 /* This is kernel mode, we trust the caller */
2889 if (DisableAllPrivileges
== FALSE
)
2890 CapturedCount
= NewState
->PrivilegeCount
;
2893 /* Do we need to capture the new state? */
2894 if (DisableAllPrivileges
== FALSE
)
2898 /* Capture the new state array of privileges */
2899 Status
= SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
2906 &CapturedPrivileges
,
2909 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2911 /* Return the exception code */
2912 Status
= _SEH2_GetExceptionCode();
2916 if (!NT_SUCCESS(Status
))
2920 /* Reference the token */
2921 Status
= ObReferenceObjectByHandle(TokenHandle
,
2922 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
2927 if (!NT_SUCCESS(Status
))
2929 DPRINT1("Failed to reference token (Status 0x%lx)\n", Status
);
2931 /* Release the captured privileges */
2932 if (CapturedPrivileges
!= NULL
)
2933 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2940 /* Lock the token */
2941 ExEnterCriticalRegionAndAcquireResourceExclusive(Token
->TokenLock
);
2943 /* Count the privileges that need to be changed, do not apply them yet */
2944 Status
= SepAdjustPrivileges(Token
,
2945 DisableAllPrivileges
,
2952 /* Check if the caller asked for the previous state */
2953 if (PreviousState
!= NULL
)
2955 /* Calculate the required length */
2956 RequiredLength
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[ChangeCount
]);
2958 /* Try to return the required buffer length */
2961 *ReturnLength
= RequiredLength
;
2963 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2965 /* Do cleanup and return the exception code */
2966 Status
= _SEH2_GetExceptionCode();
2967 _SEH2_YIELD(goto Cleanup
);
2971 /* Fail, if the buffer length is smaller than the required length */
2972 if (BufferLength
< RequiredLength
)
2974 Status
= STATUS_BUFFER_TOO_SMALL
;
2979 /* Now enter SEH, since we might return the old privileges */
2982 /* This time apply the changes */
2983 Status
= SepAdjustPrivileges(Token
,
2984 DisableAllPrivileges
,
2991 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2993 /* Do cleanup and return the exception code */
2994 Status
= _SEH2_GetExceptionCode();
2995 _SEH2_YIELD(goto Cleanup
);
3000 /* Unlock and dereference the token */
3001 ExReleaseResourceAndLeaveCriticalRegion(Token
->TokenLock
);
3002 ObDereferenceObject(Token
);
3004 /* Release the captured privileges */
3005 if (CapturedPrivileges
!= NULL
)
3006 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
3010 DPRINT ("NtAdjustPrivilegesToken() done\n");
3017 _Out_ PHANDLE TokenHandle
,
3018 _In_ ACCESS_MASK DesiredAccess
,
3019 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
,
3020 _In_ TOKEN_TYPE TokenType
,
3021 _In_ PLUID AuthenticationId
,
3022 _In_ PLARGE_INTEGER ExpirationTime
,
3023 _In_ PTOKEN_USER TokenUser
,
3024 _In_ PTOKEN_GROUPS TokenGroups
,
3025 _In_ PTOKEN_PRIVILEGES TokenPrivileges
,
3026 _In_opt_ PTOKEN_OWNER TokenOwner
,
3027 _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
3028 _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
3029 _In_ PTOKEN_SOURCE TokenSource
)
3032 KPROCESSOR_MODE PreviousMode
;
3033 ULONG PrivilegeCount
, GroupCount
;
3034 PSID OwnerSid
, PrimaryGroupSid
;
3036 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
3037 LUID LocalAuthenticationId
;
3038 TOKEN_SOURCE LocalTokenSource
;
3039 SECURITY_QUALITY_OF_SERVICE LocalSecurityQos
;
3040 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
3041 PSID_AND_ATTRIBUTES CapturedUser
= NULL
;
3042 PSID_AND_ATTRIBUTES CapturedGroups
= NULL
;
3043 PSID CapturedOwnerSid
= NULL
;
3044 PSID CapturedPrimaryGroupSid
= NULL
;
3045 PACL CapturedDefaultDacl
= NULL
;
3046 ULONG PrivilegesLength
, UserLength
, GroupsLength
;
3051 PreviousMode
= ExGetPreviousMode();
3053 if (PreviousMode
!= KernelMode
)
3057 ProbeForWriteHandle(TokenHandle
);
3059 if (ObjectAttributes
!= NULL
)
3061 ProbeForRead(ObjectAttributes
,
3062 sizeof(OBJECT_ATTRIBUTES
),
3064 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
3067 ProbeForRead(AuthenticationId
,
3070 LocalAuthenticationId
= *AuthenticationId
;
3072 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
3074 ProbeForRead(TokenUser
,
3078 ProbeForRead(TokenGroups
,
3079 sizeof(TOKEN_GROUPS
),
3081 GroupCount
= TokenGroups
->GroupCount
;
3083 ProbeForRead(TokenPrivileges
,
3084 sizeof(TOKEN_PRIVILEGES
),
3086 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
3088 if (TokenOwner
!= NULL
)
3090 ProbeForRead(TokenOwner
,
3091 sizeof(TOKEN_OWNER
),
3093 OwnerSid
= TokenOwner
->Owner
;
3100 ProbeForRead(TokenPrimaryGroup
,
3101 sizeof(TOKEN_PRIMARY_GROUP
),
3103 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
3105 if (TokenDefaultDacl
!= NULL
)
3107 ProbeForRead(TokenDefaultDacl
,
3108 sizeof(TOKEN_DEFAULT_DACL
),
3110 DefaultDacl
= TokenDefaultDacl
->DefaultDacl
;
3117 ProbeForRead(TokenSource
,
3118 sizeof(TOKEN_SOURCE
),
3120 LocalTokenSource
= *TokenSource
;
3122 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3124 /* Return the exception code */
3125 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3131 if (ObjectAttributes
!= NULL
)
3132 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
3133 LocalAuthenticationId
= *AuthenticationId
;
3134 LocalExpirationTime
= *ExpirationTime
;
3135 GroupCount
= TokenGroups
->GroupCount
;
3136 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
3137 OwnerSid
= TokenOwner
? TokenOwner
->Owner
: NULL
;
3138 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
3139 DefaultDacl
= TokenDefaultDacl
? TokenDefaultDacl
->DefaultDacl
: NULL
;
3140 LocalTokenSource
= *TokenSource
;
3143 /* Check token type */
3144 if ((TokenType
< TokenPrimary
) ||
3145 (TokenType
> TokenImpersonation
))
3147 return STATUS_BAD_TOKEN_TYPE
;
3150 /* Capture the user SID and attributes */
3151 Status
= SeCaptureSidAndAttributesArray(&TokenUser
->User
,
3160 if (!NT_SUCCESS(Status
))
3165 /* Capture the groups SID and attributes array */
3166 Status
= SeCaptureSidAndAttributesArray(&TokenGroups
->Groups
[0],
3175 if (!NT_SUCCESS(Status
))
3180 /* Capture privileges */
3181 Status
= SeCaptureLuidAndAttributesArray(&TokenPrivileges
->Privileges
[0],
3188 &CapturedPrivileges
,
3190 if (!NT_SUCCESS(Status
))
3195 /* Capture the token owner SID */
3196 if (TokenOwner
!= NULL
)
3198 Status
= SepCaptureSid(OwnerSid
,
3203 if (!NT_SUCCESS(Status
))
3209 /* Capture the token primary group SID */
3210 Status
= SepCaptureSid(PrimaryGroupSid
,
3214 &CapturedPrimaryGroupSid
);
3215 if (!NT_SUCCESS(Status
))
3220 /* Capture DefaultDacl */
3221 if (DefaultDacl
!= NULL
)
3223 Status
= SepCaptureAcl(DefaultDacl
,
3227 &CapturedDefaultDacl
);
3228 if (!NT_SUCCESS(Status
))
3234 /* Call the internal function */
3235 Status
= SepCreateToken(&hToken
,
3240 LocalSecurityQos
.ImpersonationLevel
,
3241 &LocalAuthenticationId
,
3242 &LocalExpirationTime
,
3246 0, // FIXME: Should capture
3250 CapturedPrimaryGroupSid
,
3251 CapturedDefaultDacl
,
3254 if (NT_SUCCESS(Status
))
3258 *TokenHandle
= hToken
;
3260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3262 Status
= _SEH2_GetExceptionCode();
3269 /* Release what we captured */
3270 SeReleaseSidAndAttributesArray(CapturedUser
, PreviousMode
, FALSE
);
3271 SeReleaseSidAndAttributesArray(CapturedGroups
, PreviousMode
, FALSE
);
3272 SeReleaseLuidAndAttributesArray(CapturedPrivileges
, PreviousMode
, FALSE
);
3273 SepReleaseSid(CapturedOwnerSid
, PreviousMode
, FALSE
);
3274 SepReleaseSid(CapturedPrimaryGroupSid
, PreviousMode
, FALSE
);
3275 SepReleaseAcl(CapturedDefaultDacl
, PreviousMode
, FALSE
);
3285 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
3286 IN ACCESS_MASK DesiredAccess
,
3287 IN BOOLEAN OpenAsSelf
,
3288 IN ULONG HandleAttributes
,
3289 OUT PHANDLE TokenHandle
)
3291 PETHREAD Thread
, NewThread
;
3293 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
3294 BOOLEAN CopyOnOpen
, EffectiveOnly
;
3295 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
3296 SE_IMPERSONATION_STATE ImpersonationState
;
3297 OBJECT_ATTRIBUTES ObjectAttributes
;
3298 SECURITY_DESCRIPTOR SecurityDescriptor
;
3300 KPROCESSOR_MODE PreviousMode
;
3302 BOOLEAN RestoreImpersonation
= FALSE
;
3306 PreviousMode
= ExGetPreviousMode();
3308 if (PreviousMode
!= KernelMode
)
3312 ProbeForWriteHandle(TokenHandle
);
3314 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3316 /* Return the exception code */
3317 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3322 /* Validate object attributes */
3323 HandleAttributes
= ObpValidateAttributes(HandleAttributes
, PreviousMode
);
3326 * At first open the thread token for information access and verify
3327 * 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
);
3389 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
3390 TokenImpersonation
, ImpersonationLevel
,
3391 KernelMode
, &NewToken
);
3392 if (NT_SUCCESS(Status
))
3394 ObReferenceObject(NewToken
);
3395 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
3403 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
3404 NULL
, DesiredAccess
, SeTokenObjectType
,
3405 PreviousMode
, &hToken
);
3408 if (Dacl
) ExFreePoolWithTag(Dacl
, TAG_ACL
);
3410 if (RestoreImpersonation
)
3412 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
3415 ObDereferenceObject(Token
);
3417 if (NT_SUCCESS(Status
) && CopyOnOpen
)
3419 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
3422 if (NewToken
) ObDereferenceObject(NewToken
);
3424 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
3426 ObDereferenceObject(Thread
);
3428 if (NT_SUCCESS(Status
))
3432 *TokenHandle
= hToken
;
3434 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3436 Status
= _SEH2_GetExceptionCode();
3448 NtOpenThreadToken(IN HANDLE ThreadHandle
,
3449 IN ACCESS_MASK DesiredAccess
,
3450 IN BOOLEAN OpenAsSelf
,
3451 OUT PHANDLE TokenHandle
)
3453 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
3462 NtCompareTokens(IN HANDLE FirstTokenHandle
,
3463 IN HANDLE SecondTokenHandle
,
3466 KPROCESSOR_MODE PreviousMode
;
3467 PTOKEN FirstToken
, SecondToken
;
3473 PreviousMode
= ExGetPreviousMode();
3475 if (PreviousMode
!= KernelMode
)
3479 ProbeForWriteBoolean(Equal
);
3481 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3483 /* Return the exception code */
3484 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3489 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
3493 (PVOID
*)&FirstToken
,
3495 if (!NT_SUCCESS(Status
))
3498 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
3502 (PVOID
*)&SecondToken
,
3504 if (!NT_SUCCESS(Status
))
3506 ObDereferenceObject(FirstToken
);
3510 if (FirstToken
!= SecondToken
)
3512 Status
= SepCompareTokens(FirstToken
,
3521 ObDereferenceObject(FirstToken
);
3522 ObDereferenceObject(SecondToken
);
3524 if (NT_SUCCESS(Status
))
3530 _SEH2_EXCEPT(ExSystemExceptionFilter())
3532 Status
= _SEH2_GetExceptionCode();
3542 NtFilterToken(IN HANDLE ExistingTokenHandle
,
3544 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
3545 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
3546 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
3547 OUT PHANDLE NewTokenHandle
)
3550 return STATUS_NOT_IMPLEMENTED
;
3558 NtImpersonateAnonymousToken(IN HANDLE Thread
)
3561 return STATUS_NOT_IMPLEMENTED
;