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)
20 /* GLOBALS ********************************************************************/
22 POBJECT_TYPE SeTokenObjectType
= NULL
;
23 ERESOURCE SepTokenLock
;
25 TOKEN_SOURCE SeSystemTokenSource
= {"*SYSTEM*", {0}};
26 LUID SeSystemAuthenticationId
= SYSTEM_LUID
;
28 static GENERIC_MAPPING SepTokenMapping
= {
35 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
37 /* Class 0 not used, blame M$! */
38 ICI_SQ_SAME( 0, 0, 0),
41 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
43 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
45 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
47 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
48 /* TokenPrimaryGroup */
49 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
50 /* TokenDefaultDacl */
51 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
53 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
55 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
56 /* TokenImpersonationLevel */
57 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
59 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
60 /* TokenRestrictedSids */
61 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
63 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
64 /* TokenGroupsAndPrivileges */
65 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
66 /* TokenSessionReference */
67 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
68 /* TokenSandBoxInert */
69 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
70 /* TokenAuditPolicy */
71 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
73 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
76 /* FUNCTIONS *****************************************************************/
79 SepCompareTokens(IN PTOKEN FirstToken
,
80 IN PTOKEN SecondToken
,
83 BOOLEAN Restricted
, IsEqual
= FALSE
;
85 ASSERT(FirstToken
!= SecondToken
);
87 /* FIXME: Check if every SID that is present in either token is also present in the other one */
89 Restricted
= SeTokenIsRestricted(FirstToken
);
90 if (Restricted
== SeTokenIsRestricted(SecondToken
))
94 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
97 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
101 return STATUS_SUCCESS
;
106 SepFreeProxyData(PVOID ProxyData
)
113 SepCopyProxyData(PVOID
* Dest
,
117 return STATUS_NOT_IMPLEMENTED
;
122 SeExchangePrimaryToken(PEPROCESS Process
,
123 PACCESS_TOKEN NewTokenP
,
124 PACCESS_TOKEN
* OldTokenP
)
127 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
131 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
132 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
134 /* Mark new token in use */
135 NewToken
->TokenInUse
= 1;
137 /* Reference the New Token */
138 ObReferenceObject(NewToken
);
140 /* Replace the old with the new */
141 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
143 /* Mark the Old Token as free */
144 OldToken
->TokenInUse
= 0;
146 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
147 return STATUS_SUCCESS
;
152 SeDeassignPrimaryToken(PEPROCESS Process
)
156 /* Remove the Token */
157 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
159 /* Mark the Old Token as free */
160 OldToken
->TokenInUse
= 0;
164 RtlLengthSidAndAttributes(ULONG Count
,
165 PSID_AND_ATTRIBUTES Src
)
172 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
173 for (i
= 0; i
< Count
; i
++)
174 uLength
+= RtlLengthSid(Src
[i
].Sid
);
182 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
188 Token
->PrimaryGroup
= 0;
192 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
195 /* Validate and set the primary group and user pointers */
196 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
199 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
201 Token
->DefaultOwnerIndex
= i
;
204 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
206 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
210 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
212 return(STATUS_INVALID_OWNER
);
215 if (Token
->PrimaryGroup
== 0)
217 return(STATUS_INVALID_PRIMARY_GROUP
);
220 return STATUS_SUCCESS
;
226 SepDuplicateToken(PTOKEN Token
,
227 POBJECT_ATTRIBUTES ObjectAttributes
,
228 BOOLEAN EffectiveOnly
,
229 TOKEN_TYPE TokenType
,
230 SECURITY_IMPERSONATION_LEVEL Level
,
231 KPROCESSOR_MODE PreviousMode
,
232 PTOKEN
* NewAccessToken
)
237 PTOKEN AccessToken
= NULL
;
242 Status
= ObCreateObject(PreviousMode
,
250 (PVOID
*)&AccessToken
);
251 if (!NT_SUCCESS(Status
))
253 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
257 /* Zero out the buffer */
258 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
260 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
261 if (!NT_SUCCESS(Status
))
263 ObDereferenceObject(AccessToken
);
267 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
268 if (!NT_SUCCESS(Status
))
270 ObDereferenceObject(AccessToken
);
274 AccessToken
->TokenLock
= &SepTokenLock
;
276 AccessToken
->TokenType
= TokenType
;
277 AccessToken
->ImpersonationLevel
= Level
;
278 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
280 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
281 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
282 memcpy(AccessToken
->TokenSource
.SourceName
,
283 Token
->TokenSource
.SourceName
,
284 sizeof(Token
->TokenSource
.SourceName
));
285 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
286 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
287 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
289 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
290 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
291 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
293 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
296 if (AccessToken
->UserAndGroups
== NULL
)
298 Status
= STATUS_INSUFFICIENT_RESOURCES
;
302 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
304 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
305 Token
->UserAndGroups
,
307 AccessToken
->UserAndGroups
,
311 if (!NT_SUCCESS(Status
))
314 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
317 if (!NT_SUCCESS(Status
))
320 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
322 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
323 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
325 TAG_TOKEN_PRIVILAGES
);
326 if (AccessToken
->Privileges
== NULL
)
328 Status
= STATUS_INSUFFICIENT_RESOURCES
;
332 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
334 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
335 &Token
->Privileges
[i
].Luid
);
336 AccessToken
->Privileges
[i
].Attributes
=
337 Token
->Privileges
[i
].Attributes
;
340 if (Token
->DefaultDacl
)
342 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
343 Token
->DefaultDacl
->AclSize
,
345 if (AccessToken
->DefaultDacl
== NULL
)
347 Status
= STATUS_INSUFFICIENT_RESOURCES
;
351 memcpy(AccessToken
->DefaultDacl
,
353 Token
->DefaultDacl
->AclSize
);
356 *NewAccessToken
= AccessToken
;
359 if (!NT_SUCCESS(Status
))
363 if (AccessToken
->UserAndGroups
)
364 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
366 if (AccessToken
->Privileges
)
367 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
369 if (AccessToken
->DefaultDacl
)
370 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
372 ObDereferenceObject(AccessToken
);
381 SeSubProcessToken(IN PTOKEN ParentToken
,
387 OBJECT_ATTRIBUTES ObjectAttributes
;
390 /* Initialize the attributes and duplicate it */
391 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
392 Status
= SepDuplicateToken(ParentToken
,
396 ParentToken
->ImpersonationLevel
,
399 if (NT_SUCCESS(Status
))
402 Status
= ObInsertObject(NewToken
,
408 if (NT_SUCCESS(Status
))
410 /* Set the session ID */
411 NewToken
->SessionId
= SessionId
;
412 NewToken
->TokenInUse
= InUse
;
414 /* Return the token */
425 SeIsTokenChild(IN PTOKEN Token
,
426 OUT PBOOLEAN IsChild
)
429 LUID ProcessLuid
, CallerLuid
;
434 /* Reference the process token */
435 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
438 ProcessLuid
= ProcessToken
->TokenId
;
440 /* Dereference the token */
441 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
444 CallerLuid
= Token
->TokenId
;
446 /* Compare the LUIDs */
447 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
450 return STATUS_SUCCESS
;
455 SeCopyClientToken(IN PACCESS_TOKEN Token
,
456 IN SECURITY_IMPERSONATION_LEVEL Level
,
457 IN KPROCESSOR_MODE PreviousMode
,
458 OUT PACCESS_TOKEN
* NewToken
)
461 OBJECT_ATTRIBUTES ObjectAttributes
;
465 InitializeObjectAttributes(&ObjectAttributes
,
470 Status
= SepDuplicateToken(Token
,
483 SepDeleteToken(PVOID ObjectBody
)
485 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
487 if (AccessToken
->UserAndGroups
)
488 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
490 if (AccessToken
->Privileges
)
491 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
493 if (AccessToken
->DefaultDacl
)
494 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
501 SepInitializeTokenImplementation(VOID
)
504 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
506 ExInitializeResource(&SepTokenLock
);
508 DPRINT("Creating Token Object Type\n");
510 /* Initialize the Token type */
511 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
512 RtlInitUnicodeString(&Name
, L
"Token");
513 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
514 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
515 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
516 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
517 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
518 ObjectTypeInitializer
.PoolType
= PagedPool
;
519 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
520 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
521 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
522 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SeTokenObjectType
);
527 SeAssignPrimaryToken(IN PEPROCESS Process
,
533 ASSERT(Token
->TokenType
== TokenPrimary
);
534 ASSERT(!Token
->TokenInUse
);
536 /* Clean any previous token */
537 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
539 /* Set the new token */
540 ObReferenceObject(Token
);
541 Token
->TokenInUse
= TRUE
;
542 ObInitializeFastReference(&Process
->Token
, Token
);
548 SepCreateToken(OUT PHANDLE TokenHandle
,
549 IN KPROCESSOR_MODE PreviousMode
,
550 IN ACCESS_MASK DesiredAccess
,
551 IN POBJECT_ATTRIBUTES ObjectAttributes
,
552 IN TOKEN_TYPE TokenType
,
553 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
554 IN PLUID AuthenticationId
,
555 IN PLARGE_INTEGER ExpirationTime
,
556 IN PSID_AND_ATTRIBUTES User
,
558 IN PSID_AND_ATTRIBUTES Groups
,
559 IN ULONG GroupLength
,
560 IN ULONG PrivilegeCount
,
561 IN PLUID_AND_ATTRIBUTES Privileges
,
563 IN PSID PrimaryGroup
,
565 IN PTOKEN_SOURCE TokenSource
,
566 IN BOOLEAN SystemToken
)
575 ULONG TokenFlags
= 0;
577 /* Loop all groups */
578 for (i
= 0; i
< GroupCount
; i
++)
580 /* Check for mandatory groups */
581 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
583 /* Force them to be enabled */
584 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
587 /* Check of the group is an admin group */
588 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
590 /* Remember this so we can optimize queries later */
591 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
595 /* Loop all privileges */
596 for (i
= 0; i
< PrivilegeCount
; i
++)
598 /* For optimization, check for change notify and impersonate rights */
599 if (((RtlEqualLuid(&Privileges
[i
].Luid
, &SeChangeNotifyPrivilege
)) &&
600 (Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)))
602 /* Remember token has traverse */
603 TokenFlags
|= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
607 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
608 if (!NT_SUCCESS(Status
))
611 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
612 if (!NT_SUCCESS(Status
))
615 Status
= ObCreateObject(PreviousMode
,
623 (PVOID
*)&AccessToken
);
624 if (!NT_SUCCESS(Status
))
626 DPRINT1("ObCreateObject() failed (Status %lx)\n");
630 /* Zero out the buffer */
631 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
633 AccessToken
->TokenLock
= &SepTokenLock
;
635 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
636 &TokenSource
->SourceIdentifier
);
637 memcpy(AccessToken
->TokenSource
.SourceName
,
638 TokenSource
->SourceName
,
639 sizeof(TokenSource
->SourceName
));
641 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
642 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
643 AccessToken
->ExpirationTime
= *ExpirationTime
;
644 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
646 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
647 AccessToken
->PrivilegeCount
= PrivilegeCount
;
649 AccessToken
->TokenFlags
= TokenFlags
;
650 AccessToken
->TokenType
= TokenType
;
651 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
654 * Normally we would just point these members into the variable information
655 * area; however, our ObCreateObject() call can't allocate a variable information
656 * area, so we allocate them seperately and provide a destroy function.
659 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
660 uLength
+= RtlLengthSid(User
);
661 for (i
= 0; i
< GroupCount
; i
++)
662 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
664 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
667 if (AccessToken
->UserAndGroups
== NULL
)
669 Status
= STATUS_INSUFFICIENT_RESOURCES
;
673 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
675 Status
= RtlCopySidAndAttributesArray(1,
678 AccessToken
->UserAndGroups
,
682 if (!NT_SUCCESS(Status
))
685 Status
= RtlCopySidAndAttributesArray(GroupCount
,
688 &AccessToken
->UserAndGroups
[1],
692 if (!NT_SUCCESS(Status
))
695 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
698 if (!NT_SUCCESS(Status
))
701 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
702 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
704 TAG_TOKEN_PRIVILAGES
);
705 if (AccessToken
->Privileges
== NULL
)
707 Status
= STATUS_INSUFFICIENT_RESOURCES
;
711 if (PreviousMode
!= KernelMode
)
715 RtlCopyMemory(AccessToken
->Privileges
,
717 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
719 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
721 Status
= _SEH2_GetExceptionCode();
727 RtlCopyMemory(AccessToken
->Privileges
,
729 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
732 if (!NT_SUCCESS(Status
))
735 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
736 DefaultDacl
->AclSize
,
738 if (AccessToken
->DefaultDacl
== NULL
)
740 Status
= STATUS_INSUFFICIENT_RESOURCES
;
744 RtlCopyMemory(AccessToken
->DefaultDacl
,
746 DefaultDacl
->AclSize
);
750 Status
= ObInsertObject((PVOID
)AccessToken
,
756 if (!NT_SUCCESS(Status
))
758 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
763 /* Return pointer instead of handle */
764 *TokenHandle
= (HANDLE
)AccessToken
;
768 if (!NT_SUCCESS(Status
))
772 if (AccessToken
->UserAndGroups
)
773 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
775 if (AccessToken
->Privileges
)
776 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
778 if (AccessToken
->DefaultDacl
)
779 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
781 ObDereferenceObject(AccessToken
);
790 SepCreateSystemProcessToken(VOID
)
792 LUID_AND_ATTRIBUTES Privileges
[25];
793 ULONG GroupAttributes
, OwnerAttributes
;
794 SID_AND_ATTRIBUTES Groups
[32];
795 LARGE_INTEGER Expiration
;
796 SID_AND_ATTRIBUTES UserSid
;
799 OBJECT_ATTRIBUTES ObjectAttributes
;
805 /* Don't ever expire */
806 Expiration
.QuadPart
= -1;
808 /* All groups mandatory and enabled */
809 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
810 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
813 UserSid
.Sid
= SeLocalSystemSid
;
814 UserSid
.Attributes
= 0;
816 /* Primary group is local system */
817 PrimaryGroup
= SeLocalSystemSid
;
819 /* Owner is admins */
820 Owner
= SeAliasAdminsSid
;
822 /* Groups are admins, world, and authenticated users */
823 Groups
[0].Sid
= SeAliasAdminsSid
;
824 Groups
[0].Attributes
= OwnerAttributes
;
825 Groups
[1].Sid
= SeWorldSid
;
826 Groups
[1].Attributes
= GroupAttributes
;
827 Groups
[2].Sid
= SeAuthenticatedUserSid
;
828 Groups
[2].Attributes
= OwnerAttributes
;
829 GroupLength
= sizeof(SID_AND_ATTRIBUTES
) +
830 SeLengthSid(Groups
[0].Sid
) +
831 SeLengthSid(Groups
[1].Sid
) +
832 SeLengthSid(Groups
[2].Sid
);
833 ASSERT(GroupLength
<= sizeof(Groups
));
835 /* Setup the privileges */
837 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
838 Privileges
[i
++].Luid
= SeTcbPrivilege
;
840 Privileges
[i
].Attributes
= 0;
841 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
843 Privileges
[i
].Attributes
= 0;
844 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
846 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
847 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
849 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
850 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
852 Privileges
[i
].Attributes
= 0;
853 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
855 Privileges
[i
].Attributes
= 0;
856 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
858 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
859 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
861 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
862 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
864 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
865 Privileges
[i
++].Luid
= SeDebugPrivilege
;
867 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
868 Privileges
[i
++].Luid
= SeAuditPrivilege
;
870 Privileges
[i
].Attributes
= 0;
871 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
873 Privileges
[i
].Attributes
= 0;
874 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
876 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
877 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
879 Privileges
[i
].Attributes
= 0;
880 Privileges
[i
++].Luid
= SeBackupPrivilege
;
882 Privileges
[i
].Attributes
= 0;
883 Privileges
[i
++].Luid
= SeRestorePrivilege
;
885 Privileges
[i
].Attributes
= 0;
886 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
888 Privileges
[i
].Attributes
= 0;
889 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
891 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
892 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
894 Privileges
[i
].Attributes
= 0;
895 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
898 /* Setup the object attributes */
899 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
900 ASSERT(SeSystemDefaultDacl
!= NULL
);
902 /* Create the token */
903 Status
= SepCreateToken((PHANDLE
)&Token
,
909 &SeSystemAuthenticationId
,
920 &SeSystemTokenSource
,
922 ASSERT(Status
== STATUS_SUCCESS
);
924 /* Return the token */
928 /* PUBLIC FUNCTIONS ***********************************************************/
935 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
937 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
938 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
939 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
940 OUT PACCESS_TOKEN
* FilteredToken
)
943 return STATUS_NOT_IMPLEMENTED
;
951 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
952 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
953 OUT PVOID
*TokenInformation
)
956 return STATUS_NOT_IMPLEMENTED
;
964 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
965 IN PULONG pSessionId
)
967 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
968 return STATUS_SUCCESS
;
976 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
981 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
983 return STATUS_SUCCESS
;
990 SECURITY_IMPERSONATION_LEVEL
992 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
996 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1004 SeTokenType(IN PACCESS_TOKEN Token
)
1008 return ((PTOKEN
)Token
)->TokenType
;
1017 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
1021 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
1029 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
1033 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
1041 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
1045 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
1048 /* SYSTEM CALLS ***************************************************************/
1054 NtQueryInformationToken(IN HANDLE TokenHandle
,
1055 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1056 OUT PVOID TokenInformation
,
1057 IN ULONG TokenInformationLength
,
1058 OUT PULONG ReturnLength
)
1066 ULONG RequiredLength
;
1067 KPROCESSOR_MODE PreviousMode
;
1068 NTSTATUS Status
= STATUS_SUCCESS
;
1072 PreviousMode
= ExGetPreviousMode();
1074 /* Check buffers and class validity */
1075 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1076 SeTokenInformationClass
,
1077 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1079 TokenInformationLength
,
1083 if (!NT_SUCCESS(Status
))
1085 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1089 Status
= ObReferenceObjectByHandle(TokenHandle
,
1090 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1095 if (NT_SUCCESS(Status
))
1097 switch (TokenInformationClass
)
1101 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1103 DPRINT("NtQueryInformationToken(TokenUser)\n");
1104 RequiredLength
= sizeof(TOKEN_USER
) +
1105 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1109 if (TokenInformationLength
>= RequiredLength
)
1111 Status
= RtlCopySidAndAttributesArray(1,
1112 &Token
->UserAndGroups
[0],
1113 RequiredLength
- sizeof(TOKEN_USER
),
1121 Status
= STATUS_BUFFER_TOO_SMALL
;
1124 if (ReturnLength
!= NULL
)
1126 *ReturnLength
= RequiredLength
;
1129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1131 Status
= _SEH2_GetExceptionCode();
1140 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1142 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1143 RequiredLength
= sizeof(tg
->GroupCount
) +
1144 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1148 if (TokenInformationLength
>= RequiredLength
)
1150 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1151 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1152 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1153 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1155 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1156 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1157 &Token
->UserAndGroups
[1],
1166 Status
= STATUS_BUFFER_TOO_SMALL
;
1169 if (ReturnLength
!= NULL
)
1171 *ReturnLength
= RequiredLength
;
1174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1176 Status
= _SEH2_GetExceptionCode();
1183 case TokenPrivileges
:
1185 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1187 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1188 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1189 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1193 if (TokenInformationLength
>= RequiredLength
)
1195 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1196 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1198 &tp
->Privileges
[0]);
1202 Status
= STATUS_BUFFER_TOO_SMALL
;
1205 if (ReturnLength
!= NULL
)
1207 *ReturnLength
= RequiredLength
;
1210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1212 Status
= _SEH2_GetExceptionCode();
1222 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1224 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1225 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1226 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1230 if (TokenInformationLength
>= RequiredLength
)
1232 to
->Owner
= (PSID
)(to
+ 1);
1233 Status
= RtlCopySid(SidLen
,
1235 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1239 Status
= STATUS_BUFFER_TOO_SMALL
;
1242 if (ReturnLength
!= NULL
)
1244 *ReturnLength
= RequiredLength
;
1247 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1249 Status
= _SEH2_GetExceptionCode();
1256 case TokenPrimaryGroup
:
1259 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1261 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1262 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1263 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1267 if (TokenInformationLength
>= RequiredLength
)
1269 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1270 Status
= RtlCopySid(SidLen
,
1272 Token
->PrimaryGroup
);
1276 Status
= STATUS_BUFFER_TOO_SMALL
;
1279 if (ReturnLength
!= NULL
)
1281 *ReturnLength
= RequiredLength
;
1284 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1286 Status
= _SEH2_GetExceptionCode();
1293 case TokenDefaultDacl
:
1295 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1297 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1298 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1300 if (Token
->DefaultDacl
!= NULL
)
1302 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1307 if (TokenInformationLength
>= RequiredLength
)
1309 if (Token
->DefaultDacl
!= NULL
)
1311 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1312 RtlCopyMemory(tdd
->DefaultDacl
,
1314 Token
->DefaultDacl
->AclSize
);
1318 tdd
->DefaultDacl
= NULL
;
1323 Status
= STATUS_BUFFER_TOO_SMALL
;
1326 if (ReturnLength
!= NULL
)
1328 *ReturnLength
= RequiredLength
;
1331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1333 Status
= _SEH2_GetExceptionCode();
1342 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1344 DPRINT("NtQueryInformationToken(TokenSource)\n");
1345 RequiredLength
= sizeof(TOKEN_SOURCE
);
1349 if (TokenInformationLength
>= RequiredLength
)
1351 *ts
= Token
->TokenSource
;
1355 Status
= STATUS_BUFFER_TOO_SMALL
;
1358 if (ReturnLength
!= NULL
)
1360 *ReturnLength
= RequiredLength
;
1363 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1365 Status
= _SEH2_GetExceptionCode();
1374 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1376 DPRINT("NtQueryInformationToken(TokenType)\n");
1377 RequiredLength
= sizeof(TOKEN_TYPE
);
1381 if (TokenInformationLength
>= RequiredLength
)
1383 *tt
= Token
->TokenType
;
1387 Status
= STATUS_BUFFER_TOO_SMALL
;
1390 if (ReturnLength
!= NULL
)
1392 *ReturnLength
= RequiredLength
;
1395 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1397 Status
= _SEH2_GetExceptionCode();
1404 case TokenImpersonationLevel
:
1406 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1408 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1410 /* Fail if the token is not an impersonation token */
1411 if (Token
->TokenType
!= TokenImpersonation
)
1413 Status
= STATUS_INVALID_INFO_CLASS
;
1417 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1421 if (TokenInformationLength
>= RequiredLength
)
1423 *sil
= Token
->ImpersonationLevel
;
1427 Status
= STATUS_BUFFER_TOO_SMALL
;
1430 if (ReturnLength
!= NULL
)
1432 *ReturnLength
= RequiredLength
;
1435 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1437 Status
= _SEH2_GetExceptionCode();
1444 case TokenStatistics
:
1446 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1448 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1449 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1453 if (TokenInformationLength
>= RequiredLength
)
1455 ts
->TokenId
= Token
->TokenId
;
1456 ts
->AuthenticationId
= Token
->AuthenticationId
;
1457 ts
->ExpirationTime
= Token
->ExpirationTime
;
1458 ts
->TokenType
= Token
->TokenType
;
1459 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1460 ts
->DynamicCharged
= Token
->DynamicCharged
;
1461 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1462 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1463 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1464 ts
->ModifiedId
= Token
->ModifiedId
;
1468 Status
= STATUS_BUFFER_TOO_SMALL
;
1471 if (ReturnLength
!= NULL
)
1473 *ReturnLength
= RequiredLength
;
1476 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1478 Status
= _SEH2_GetExceptionCode();
1487 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1489 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1490 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1494 if (TokenInformationLength
>= RequiredLength
)
1496 RtlCopyLuid(&to
->OriginatingLogonSession
,
1497 &Token
->AuthenticationId
);
1501 Status
= STATUS_BUFFER_TOO_SMALL
;
1504 if (ReturnLength
!= NULL
)
1506 *ReturnLength
= RequiredLength
;
1509 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1511 Status
= _SEH2_GetExceptionCode();
1518 case TokenGroupsAndPrivileges
:
1519 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1520 Status
= STATUS_NOT_IMPLEMENTED
;
1523 case TokenRestrictedSids
:
1525 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1527 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1528 RequiredLength
= sizeof(tg
->GroupCount
) +
1529 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1533 if (TokenInformationLength
>= RequiredLength
)
1535 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1536 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1537 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1538 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1540 tg
->GroupCount
= Token
->RestrictedSidCount
;
1541 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1542 Token
->RestrictedSids
,
1551 Status
= STATUS_BUFFER_TOO_SMALL
;
1554 if (ReturnLength
!= NULL
)
1556 *ReturnLength
= RequiredLength
;
1559 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1561 Status
= _SEH2_GetExceptionCode();
1568 case TokenSandBoxInert
:
1569 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1570 Status
= STATUS_NOT_IMPLEMENTED
;
1573 case TokenSessionId
:
1575 ULONG SessionId
= 0;
1577 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1579 Status
= SeQuerySessionIdToken(Token
,
1582 if (NT_SUCCESS(Status
))
1586 /* buffer size was already verified, no need to check here again */
1587 *(PULONG
)TokenInformation
= SessionId
;
1589 if (ReturnLength
!= NULL
)
1591 *ReturnLength
= sizeof(ULONG
);
1594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1596 Status
= _SEH2_GetExceptionCode();
1605 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1606 Status
= STATUS_INVALID_INFO_CLASS
;
1610 ObDereferenceObject(Token
);
1618 * NtSetTokenInformation: Partly implemented.
1620 * TokenOrigin, TokenDefaultDacl
1624 NtSetInformationToken(IN HANDLE TokenHandle
,
1625 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1626 OUT PVOID TokenInformation
,
1627 IN ULONG TokenInformationLength
)
1630 KPROCESSOR_MODE PreviousMode
;
1631 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1636 PreviousMode
= ExGetPreviousMode();
1638 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1639 SeTokenInformationClass
,
1640 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1642 TokenInformationLength
,
1644 if (!NT_SUCCESS(Status
))
1646 /* Invalid buffers */
1647 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1651 if (TokenInformationClass
== TokenSessionId
)
1653 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1656 Status
= ObReferenceObjectByHandle(TokenHandle
,
1662 if (NT_SUCCESS(Status
))
1664 switch (TokenInformationClass
)
1668 if (TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1670 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1671 PSID InputSid
= NULL
, CapturedSid
;
1675 InputSid
= to
->Owner
;
1677 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1679 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1683 Status
= SepCaptureSid(InputSid
,
1688 if (NT_SUCCESS(Status
))
1690 RtlCopySid(RtlLengthSid(CapturedSid
),
1691 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1693 SepReleaseSid(CapturedSid
,
1700 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1705 case TokenPrimaryGroup
:
1707 if (TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1709 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1710 PSID InputSid
= NULL
, CapturedSid
;
1714 InputSid
= tpg
->PrimaryGroup
;
1716 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1718 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1722 Status
= SepCaptureSid(InputSid
,
1727 if (NT_SUCCESS(Status
))
1729 RtlCopySid(RtlLengthSid(CapturedSid
),
1730 Token
->PrimaryGroup
,
1732 SepReleaseSid(CapturedSid
,
1739 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1744 case TokenDefaultDacl
:
1746 if (TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1748 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1749 PACL InputAcl
= NULL
;
1753 InputAcl
= tdd
->DefaultDacl
;
1755 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1757 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1761 if (InputAcl
!= NULL
)
1765 /* Capture and copy the dacl */
1766 Status
= SepCaptureAcl(InputAcl
,
1771 if (NT_SUCCESS(Status
))
1773 /* Free the previous dacl if present */
1774 if(Token
->DefaultDacl
!= NULL
)
1776 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
1779 /* Set the new dacl */
1780 Token
->DefaultDacl
= CapturedAcl
;
1785 /* Clear and free the default dacl if present */
1786 if (Token
->DefaultDacl
!= NULL
)
1788 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
1789 Token
->DefaultDacl
= NULL
;
1795 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1800 case TokenSessionId
:
1802 ULONG SessionId
= 0;
1806 /* Buffer size was already verified, no need to check here again */
1807 SessionId
= *(PULONG
)TokenInformation
;
1809 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1811 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1815 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1818 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1822 Token
->SessionId
= SessionId
;
1828 Status
= STATUS_NOT_IMPLEMENTED
;
1833 ObDereferenceObject(Token
);
1843 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1844 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1845 * is correct either. -Gunnar
1846 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1849 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1850 IN ACCESS_MASK DesiredAccess
,
1851 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1852 IN BOOLEAN EffectiveOnly
,
1853 IN TOKEN_TYPE TokenType
,
1854 OUT PHANDLE NewTokenHandle
)
1856 KPROCESSOR_MODE PreviousMode
;
1860 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1862 OBJECT_HANDLE_INFORMATION HandleInformation
;
1867 if (TokenType
!= TokenImpersonation
&&
1868 TokenType
!= TokenPrimary
)
1869 return STATUS_INVALID_PARAMETER
;
1871 PreviousMode
= KeGetPreviousMode();
1873 if (PreviousMode
!= KernelMode
)
1877 ProbeForWriteHandle(NewTokenHandle
);
1879 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1881 /* Return the exception code */
1882 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1887 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1891 &CapturedSecurityQualityOfService
,
1893 if (!NT_SUCCESS(Status
))
1895 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1899 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1904 &HandleInformation
);
1905 if (!NT_SUCCESS(Status
))
1907 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1914 * Fail, if the original token is an impersonation token and the caller
1915 * tries to raise the impersonation level of the new token above the
1916 * impersonation level of the original token.
1918 if (Token
->TokenType
== TokenImpersonation
)
1921 CapturedSecurityQualityOfService
->ImpersonationLevel
>Token
->ImpersonationLevel
)
1923 ObDereferenceObject(Token
);
1924 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1927 return STATUS_BAD_IMPERSONATION_LEVEL
;
1932 * Fail, if a primary token is to be created from an impersonation token
1933 * and and the impersonation level of the impersonation token is below SecurityImpersonation.
1935 if (Token
->TokenType
== TokenImpersonation
&&
1936 TokenType
== TokenPrimary
&&
1937 Token
->ImpersonationLevel
< SecurityImpersonation
)
1939 ObDereferenceObject(Token
);
1940 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1943 return STATUS_BAD_IMPERSONATION_LEVEL
;
1946 Status
= SepDuplicateToken(Token
,
1950 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1954 ObDereferenceObject(Token
);
1956 if (NT_SUCCESS(Status
))
1958 Status
= ObInsertObject((PVOID
)NewToken
,
1960 (DesiredAccess
? DesiredAccess
: HandleInformation
.GrantedAccess
),
1964 if (NT_SUCCESS(Status
))
1968 *NewTokenHandle
= hToken
;
1970 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1972 Status
= _SEH2_GetExceptionCode();
1978 /* Free the captured structure */
1979 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1987 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1988 IN BOOLEAN ResetToDefault
,
1989 IN PTOKEN_GROUPS NewState
,
1990 IN ULONG BufferLength
,
1991 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1992 OUT PULONG ReturnLength
)
1995 return(STATUS_NOT_IMPLEMENTED
);
2002 NtAdjustPrivilegesToken(IN HANDLE TokenHandle
,
2003 IN BOOLEAN DisableAllPrivileges
,
2004 IN PTOKEN_PRIVILEGES NewState
,
2005 IN ULONG BufferLength
,
2006 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
2007 OUT PULONG ReturnLength OPTIONAL
)
2009 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2010 KPROCESSOR_MODE PreviousMode
;
2011 ULONG CapturedCount
= 0;
2012 ULONG CapturedLength
= 0;
2013 ULONG NewStateSize
= 0;
2022 DPRINT ("NtAdjustPrivilegesToken() called\n");
2024 /* Fail, if we do not disable all privileges but NewState is NULL */
2025 if (DisableAllPrivileges
== FALSE
&& NewState
== NULL
)
2026 return STATUS_INVALID_PARAMETER
;
2028 PreviousMode
= KeGetPreviousMode ();
2029 if (PreviousMode
!= KernelMode
)
2033 /* Probe NewState */
2034 if (DisableAllPrivileges
== FALSE
)
2036 ProbeForRead(NewState
,
2037 sizeof(TOKEN_PRIVILEGES
),
2040 CapturedCount
= NewState
->PrivilegeCount
;
2041 NewStateSize
= (ULONG
)sizeof(TOKEN_PRIVILEGES
) +
2042 ((CapturedCount
- ANYSIZE_ARRAY
) * (ULONG
)sizeof(LUID_AND_ATTRIBUTES
));
2044 ProbeForRead(NewState
,
2049 /* Probe PreviousState and ReturnLength */
2050 if (PreviousState
!= NULL
)
2052 ProbeForWrite(PreviousState
,
2056 ProbeForWrite(ReturnLength
,
2061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2063 /* Return the exception code */
2064 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2070 if (DisableAllPrivileges
== FALSE
)
2071 CapturedCount
= NewState
->PrivilegeCount
;
2074 if (DisableAllPrivileges
== FALSE
)
2078 /* Capture the new state array of privileges */
2079 Status
= SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
2086 &CapturedPrivileges
,
2089 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2091 /* Return the exception code */
2092 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2096 if (!NT_SUCCESS(Status
))
2100 /* Reference the token */
2101 Status
= ObReferenceObjectByHandle(TokenHandle
,
2102 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
2107 if (!NT_SUCCESS(Status
))
2109 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
2111 /* Release the captured privileges */
2112 if (CapturedPrivileges
!= NULL
)
2113 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2120 /* Count the privileges that need to be changed */
2122 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2124 if (DisableAllPrivileges
)
2126 if (Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
2128 DPRINT("Privilege enabled\n");
2135 for (j
= 0; j
< CapturedCount
; j
++)
2137 if (Token
->Privileges
[i
].Luid
.LowPart
== CapturedPrivileges
[j
].Luid
.LowPart
&&
2138 Token
->Privileges
[i
].Luid
.HighPart
== CapturedPrivileges
[j
].Luid
.HighPart
)
2140 DPRINT("Found privilege\n");
2142 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
2143 (CapturedPrivileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
2145 DPRINT("Attributes differ\n");
2146 DPRINT("Current attributes %lx New attributes %lx\n",
2147 Token
->Privileges
[i
].Attributes
,
2148 CapturedPrivileges
[j
].Attributes
);
2158 * Return the required buffer size and
2159 * check if the available buffer is large enough
2161 if (PreviousState
!= NULL
)
2163 ULONG RequiredLength
= (ULONG
)sizeof(TOKEN_PRIVILEGES
) +
2164 ((ChangeCount
- ANYSIZE_ARRAY
) * (ULONG
)sizeof(LUID_AND_ATTRIBUTES
));
2166 /* Try to return the required buffer length */
2169 *ReturnLength
= RequiredLength
;
2171 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2173 /* Dereference the token */
2174 ObDereferenceObject(Token
);
2176 /* Release the captured privileges */
2177 if (CapturedPrivileges
!= NULL
)
2178 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2182 /* Return the exception code */
2183 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2187 /* Fail, if the buffer length is smaller than the required length */
2188 if (BufferLength
< RequiredLength
)
2190 /* Dereference the token */
2191 ObDereferenceObject(Token
);
2193 /* Release the captured privileges */
2194 if (CapturedPrivileges
!= NULL
)
2195 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2199 return STATUS_BUFFER_TOO_SMALL
;
2203 /* Change the privilege attributes */
2207 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2209 if (DisableAllPrivileges
== TRUE
)
2211 if (Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
2213 DPRINT("Privilege enabled\n");
2215 /* Save the current privilege */
2216 if (PreviousState
!= NULL
)
2218 PreviousState
->Privileges
[ChangeCount
].Luid
= Token
->Privileges
[i
].Luid
;
2219 PreviousState
->Privileges
[ChangeCount
].Attributes
= Token
->Privileges
[i
].Attributes
;
2222 /* Disable the current privlege */
2223 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2230 for (j
= 0; j
< CapturedCount
; j
++)
2232 if (Token
->Privileges
[i
].Luid
.LowPart
== CapturedPrivileges
[j
].Luid
.LowPart
&&
2233 Token
->Privileges
[i
].Luid
.HighPart
== CapturedPrivileges
[j
].Luid
.HighPart
)
2235 DPRINT("Found privilege\n");
2237 /* Check whether the attributes differ */
2238 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
2239 (CapturedPrivileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
2241 DPRINT("Attributes differ\n");
2242 DPRINT("Current attributes %lx New attributes %lx\n",
2243 Token
->Privileges
[i
].Attributes
,
2244 CapturedPrivileges
[j
].Attributes
);
2246 /* Save the current privilege */
2247 if (PreviousState
!= NULL
)
2249 PreviousState
->Privileges
[ChangeCount
].Luid
= Token
->Privileges
[i
].Luid
;
2250 PreviousState
->Privileges
[ChangeCount
].Attributes
= Token
->Privileges
[i
].Attributes
;
2253 /* Update the current privlege */
2254 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2255 Token
->Privileges
[i
].Attributes
|=
2256 (CapturedPrivileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
2257 DPRINT("New attributes %lx\n",
2258 Token
->Privileges
[i
].Attributes
);
2267 /* Set the number of saved privileges */
2268 if (PreviousState
!= NULL
)
2269 PreviousState
->PrivilegeCount
= ChangeCount
;
2271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2273 /* Dereference the token */
2274 ObDereferenceObject(Token
);
2276 /* Release the captured privileges */
2277 if (CapturedPrivileges
!= NULL
)
2278 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2282 /* Return the exception code */
2283 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2287 /* Set the status */
2288 Status
= (ChangeCount
< CapturedCount
) ? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
2290 /* Dereference the token */
2291 ObDereferenceObject (Token
);
2293 /* Release the captured privileges */
2294 if (CapturedPrivileges
!= NULL
)
2295 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2299 DPRINT ("NtAdjustPrivilegesToken() done\n");
2306 NtCreateToken(OUT PHANDLE TokenHandle
,
2307 IN ACCESS_MASK DesiredAccess
,
2308 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2309 IN TOKEN_TYPE TokenType
,
2310 IN PLUID AuthenticationId
,
2311 IN PLARGE_INTEGER ExpirationTime
,
2312 IN PTOKEN_USER TokenUser
,
2313 IN PTOKEN_GROUPS TokenGroups
,
2314 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2315 IN PTOKEN_OWNER TokenOwner
,
2316 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2317 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2318 IN PTOKEN_SOURCE TokenSource
)
2321 KPROCESSOR_MODE PreviousMode
;
2322 ULONG nTokenPrivileges
= 0;
2323 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
2328 PreviousMode
= ExGetPreviousMode();
2330 if (PreviousMode
!= KernelMode
)
2334 ProbeForWriteHandle(TokenHandle
);
2335 ProbeForRead(AuthenticationId
,
2338 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2339 ProbeForRead(TokenUser
,
2342 ProbeForRead(TokenGroups
,
2343 sizeof(TOKEN_GROUPS
),
2345 ProbeForRead(TokenPrivileges
,
2346 sizeof(TOKEN_PRIVILEGES
),
2348 ProbeForRead(TokenOwner
,
2349 sizeof(TOKEN_OWNER
),
2351 ProbeForRead(TokenPrimaryGroup
,
2352 sizeof(TOKEN_PRIMARY_GROUP
),
2354 ProbeForRead(TokenDefaultDacl
,
2355 sizeof(TOKEN_DEFAULT_DACL
),
2357 ProbeForRead(TokenSource
,
2358 sizeof(TOKEN_SOURCE
),
2360 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2362 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2364 /* Return the exception code */
2365 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2371 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2372 LocalExpirationTime
= *ExpirationTime
;
2375 Status
= SepCreateToken(&hToken
,
2380 ((PSECURITY_QUALITY_OF_SERVICE
)(ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
,
2382 &LocalExpirationTime
,
2384 TokenGroups
->GroupCount
,
2385 TokenGroups
->Groups
,
2386 0, // FIXME: Should capture
2388 TokenPrivileges
->Privileges
,
2390 TokenPrimaryGroup
->PrimaryGroup
,
2391 TokenDefaultDacl
->DefaultDacl
,
2394 if (NT_SUCCESS(Status
))
2398 *TokenHandle
= hToken
;
2400 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2402 Status
= _SEH2_GetExceptionCode();
2415 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2416 IN ACCESS_MASK DesiredAccess
,
2417 IN BOOLEAN OpenAsSelf
,
2418 IN ULONG HandleAttributes
,
2419 OUT PHANDLE TokenHandle
)
2421 PETHREAD Thread
, NewThread
;
2423 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
2424 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2425 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2426 SE_IMPERSONATION_STATE ImpersonationState
;
2427 OBJECT_ATTRIBUTES ObjectAttributes
;
2428 SECURITY_DESCRIPTOR SecurityDescriptor
;
2430 KPROCESSOR_MODE PreviousMode
;
2435 PreviousMode
= ExGetPreviousMode();
2437 if (PreviousMode
!= KernelMode
)
2441 ProbeForWriteHandle(TokenHandle
);
2443 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2445 /* Return the exception code */
2446 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2452 * At first open the thread token for information access and verify
2453 * that the token associated with thread is valid.
2456 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2457 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2459 if (!NT_SUCCESS(Status
))
2464 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2465 &ImpersonationLevel
);
2468 ObDereferenceObject(Thread
);
2469 return STATUS_NO_TOKEN
;
2472 if (ImpersonationLevel
== SecurityAnonymous
)
2474 PsDereferenceImpersonationToken(Token
);
2475 ObDereferenceObject(Thread
);
2476 return STATUS_CANT_OPEN_ANONYMOUS
;
2480 * Revert to self if OpenAsSelf is specified.
2485 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2490 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2491 PsThreadType
, KernelMode
,
2492 (PVOID
*)&NewThread
, NULL
);
2493 if (NT_SUCCESS(Status
))
2495 PrimaryToken
= PsReferencePrimaryToken(NewThread
->ThreadsProcess
);
2497 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2499 ObFastDereferenceObject(&NewThread
->ThreadsProcess
->Token
, PrimaryToken
);
2501 if (NT_SUCCESS(Status
))
2505 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2506 SECURITY_DESCRIPTOR_REVISION
);
2507 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2511 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2512 NULL
, Dacl
? &SecurityDescriptor
: NULL
);
2515 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2516 TokenImpersonation
, ImpersonationLevel
,
2517 KernelMode
, &NewToken
);
2518 if (NT_SUCCESS(Status
))
2520 ObReferenceObject(NewToken
);
2521 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2529 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2530 NULL
, DesiredAccess
, SeTokenObjectType
,
2531 PreviousMode
, &hToken
);
2534 if (Dacl
) ExFreePoolWithTag(Dacl
, TAG_TOKEN_ACL
);
2538 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2541 ObDereferenceObject(Token
);
2543 if (NT_SUCCESS(Status
) && CopyOnOpen
)
2545 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
2548 if (NewToken
) ObDereferenceObject(NewToken
);
2550 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
2552 if (NT_SUCCESS(Status
))
2556 *TokenHandle
= hToken
;
2558 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2560 Status
= _SEH2_GetExceptionCode();
2572 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2573 IN ACCESS_MASK DesiredAccess
,
2574 IN BOOLEAN OpenAsSelf
,
2575 OUT PHANDLE TokenHandle
)
2577 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2588 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2589 IN HANDLE SecondTokenHandle
,
2592 KPROCESSOR_MODE PreviousMode
;
2593 PTOKEN FirstToken
, SecondToken
;
2599 PreviousMode
= ExGetPreviousMode();
2601 if (PreviousMode
!= KernelMode
)
2605 ProbeForWriteBoolean(Equal
);
2607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2609 /* Return the exception code */
2610 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2615 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2619 (PVOID
*)&FirstToken
,
2621 if (!NT_SUCCESS(Status
))
2624 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2628 (PVOID
*)&SecondToken
,
2630 if (!NT_SUCCESS(Status
))
2632 ObDereferenceObject(FirstToken
);
2636 if (FirstToken
!= SecondToken
)
2638 Status
= SepCompareTokens(FirstToken
,
2645 ObDereferenceObject(FirstToken
);
2646 ObDereferenceObject(SecondToken
);
2648 if (NT_SUCCESS(Status
))
2654 _SEH2_EXCEPT(ExSystemExceptionFilter())
2656 Status
= _SEH2_GetExceptionCode();
2666 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2668 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2669 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2670 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2671 OUT PHANDLE NewTokenHandle
)
2674 return STATUS_NOT_IMPLEMENTED
;
2682 NtImpersonateAnonymousToken(IN HANDLE Thread
)
2685 return STATUS_NOT_IMPLEMENTED
;