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 SepTokenObjectType
= 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
)
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
=
294 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
298 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
300 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
301 Token
->UserAndGroups
,
303 AccessToken
->UserAndGroups
,
307 if (NT_SUCCESS(Status
))
309 Status
= SepFindPrimaryGroupAndDefaultOwner(
315 if (NT_SUCCESS(Status
))
317 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
319 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
320 AccessToken
->Privileges
=
321 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
325 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
327 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
328 &Token
->Privileges
[i
].Luid
);
329 AccessToken
->Privileges
[i
].Attributes
=
330 Token
->Privileges
[i
].Attributes
;
333 if (Token
->DefaultDacl
)
335 AccessToken
->DefaultDacl
=
336 (PACL
) ExAllocatePoolWithTag(PagedPool
,
337 Token
->DefaultDacl
->AclSize
,
339 memcpy(AccessToken
->DefaultDacl
,
341 Token
->DefaultDacl
->AclSize
);
345 if (NT_SUCCESS(Status
))
347 *NewAccessToken
= AccessToken
;
348 return(STATUS_SUCCESS
);
356 SeSubProcessToken(IN PTOKEN ParentToken
,
362 OBJECT_ATTRIBUTES ObjectAttributes
;
365 /* Initialize the attributes and duplicate it */
366 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
367 Status
= SepDuplicateToken(ParentToken
,
371 ParentToken
->ImpersonationLevel
,
374 if (NT_SUCCESS(Status
))
377 Status
= ObInsertObject(NewToken
,
383 if (NT_SUCCESS(Status
))
385 /* Set the session ID */
386 NewToken
->SessionId
= SessionId
;
387 NewToken
->TokenInUse
= InUse
;
389 /* Return the token */
400 SeIsTokenChild(IN PTOKEN Token
,
401 OUT PBOOLEAN IsChild
)
404 LUID ProcessLuid
, CallerLuid
;
409 /* Reference the process token */
410 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
413 ProcessLuid
= ProcessToken
->TokenId
;
415 /* Dereference the token */
416 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
419 CallerLuid
= Token
->TokenId
;
421 /* Compare the LUIDs */
422 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
425 return STATUS_SUCCESS
;
430 SeCopyClientToken(IN PACCESS_TOKEN Token
,
431 IN SECURITY_IMPERSONATION_LEVEL Level
,
432 IN KPROCESSOR_MODE PreviousMode
,
433 OUT PACCESS_TOKEN
* NewToken
)
436 OBJECT_ATTRIBUTES ObjectAttributes
;
440 InitializeObjectAttributes(&ObjectAttributes
,
445 Status
= SepDuplicateToken(Token
,
458 SepDeleteToken(PVOID ObjectBody
)
460 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
462 if (AccessToken
->UserAndGroups
)
463 ExFreePool(AccessToken
->UserAndGroups
);
465 if (AccessToken
->Privileges
)
466 ExFreePool(AccessToken
->Privileges
);
468 if (AccessToken
->DefaultDacl
)
469 ExFreePool(AccessToken
->DefaultDacl
);
476 SepInitializeTokenImplementation(VOID
)
479 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
481 ExInitializeResource(&SepTokenLock
);
483 DPRINT("Creating Token Object Type\n");
485 /* Initialize the Token type */
486 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
487 RtlInitUnicodeString(&Name
, L
"Token");
488 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
489 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
490 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
491 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
492 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
493 ObjectTypeInitializer
.PoolType
= PagedPool
;
494 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
495 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
496 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
497 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SepTokenObjectType
);
502 SeAssignPrimaryToken(IN PEPROCESS Process
,
508 ASSERT(Token
->TokenType
== TokenPrimary
);
509 ASSERT(!Token
->TokenInUse
);
511 /* Clean any previous token */
512 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
514 /* Set the new token */
515 ObReferenceObject(Token
);
516 Token
->TokenInUse
= TRUE
;
517 ObInitializeFastReference(&Process
->Token
, Token
);
523 SepCreateToken(OUT PHANDLE TokenHandle
,
524 IN KPROCESSOR_MODE PreviousMode
,
525 IN ACCESS_MASK DesiredAccess
,
526 IN POBJECT_ATTRIBUTES ObjectAttributes
,
527 IN TOKEN_TYPE TokenType
,
528 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
529 IN PLUID AuthenticationId
,
530 IN PLARGE_INTEGER ExpirationTime
,
531 IN PSID_AND_ATTRIBUTES User
,
533 IN PSID_AND_ATTRIBUTES Groups
,
534 IN ULONG GroupLength
,
535 IN ULONG PrivilegeCount
,
536 IN PLUID_AND_ATTRIBUTES Privileges
,
538 IN PSID PrimaryGroup
,
540 IN PTOKEN_SOURCE TokenSource
,
541 IN BOOLEAN SystemToken
)
550 ULONG TokenFlags
= 0;
552 /* Loop all groups */
553 for (i
= 0; i
< GroupCount
; i
++)
555 /* Check for mandatory groups */
556 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
558 /* Force them to be enabled */
559 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
562 /* Check of the group is an admin group */
563 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
565 /* Remember this so we can optimize queries later */
566 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
570 /* Loop all privileges */
571 for (i
= 0; i
< PrivilegeCount
; i
++)
573 /* For optimization, check for change notify and impersonate rights */
574 if (((RtlEqualLuid(&Privileges
[i
].Luid
, &SeChangeNotifyPrivilege
)) &&
575 (Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)))
577 /* Remember token has traverse */
578 TokenFlags
|= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
582 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
583 if (!NT_SUCCESS(Status
))
586 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
587 if (!NT_SUCCESS(Status
))
590 Status
= ObCreateObject(PreviousMode
,
598 (PVOID
*)&AccessToken
);
599 if (!NT_SUCCESS(Status
))
601 DPRINT1("ObCreateObject() failed (Status %lx)\n");
605 /* Zero out the buffer */
606 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
608 AccessToken
->TokenLock
= &SepTokenLock
;
610 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
611 &TokenSource
->SourceIdentifier
);
612 memcpy(AccessToken
->TokenSource
.SourceName
,
613 TokenSource
->SourceName
,
614 sizeof(TokenSource
->SourceName
));
616 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
617 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
618 AccessToken
->ExpirationTime
= *ExpirationTime
;
619 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
621 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
622 AccessToken
->PrivilegeCount
= PrivilegeCount
;
624 AccessToken
->TokenFlags
= TokenFlags
;
625 AccessToken
->TokenType
= TokenType
;
626 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
629 * Normally we would just point these members into the variable information
630 * area; however, our ObCreateObject() call can't allocate a variable information
631 * area, so we allocate them seperately and provide a destroy function.
634 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
635 uLength
+= RtlLengthSid(User
);
636 for (i
= 0; i
< GroupCount
; i
++)
637 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
639 AccessToken
->UserAndGroups
=
640 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
644 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
646 Status
= RtlCopySidAndAttributesArray(1,
649 AccessToken
->UserAndGroups
,
653 if (NT_SUCCESS(Status
))
655 Status
= RtlCopySidAndAttributesArray(GroupCount
,
658 &AccessToken
->UserAndGroups
[1],
664 if (NT_SUCCESS(Status
))
666 Status
= SepFindPrimaryGroupAndDefaultOwner(
672 if (NT_SUCCESS(Status
))
674 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
675 AccessToken
->Privileges
=
676 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
680 if (PreviousMode
!= KernelMode
)
684 RtlCopyMemory(AccessToken
->Privileges
,
686 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
690 Status
= _SEH2_GetExceptionCode();
696 RtlCopyMemory(AccessToken
->Privileges
,
698 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
702 if (NT_SUCCESS(Status
))
704 AccessToken
->DefaultDacl
=
705 (PACL
) ExAllocatePoolWithTag(PagedPool
,
706 DefaultDacl
->AclSize
,
708 memcpy(AccessToken
->DefaultDacl
,
710 DefaultDacl
->AclSize
);
715 Status
= ObInsertObject((PVOID
)AccessToken
,
721 if (!NT_SUCCESS(Status
))
723 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
728 /* Return pointer instead of handle */
729 *TokenHandle
= (HANDLE
)AccessToken
;
737 SepCreateSystemProcessToken(VOID
)
739 LUID_AND_ATTRIBUTES Privileges
[25];
740 ULONG GroupAttributes
, OwnerAttributes
;
741 SID_AND_ATTRIBUTES Groups
[32];
742 LARGE_INTEGER Expiration
;
743 SID_AND_ATTRIBUTES UserSid
;
746 OBJECT_ATTRIBUTES ObjectAttributes
;
752 /* Don't ever expire */
753 Expiration
.QuadPart
= -1;
755 /* All groups mandatory and enabled */
756 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
757 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
760 UserSid
.Sid
= SeLocalSystemSid
;
761 UserSid
.Attributes
= 0;
763 /* Primary group is local system */
764 PrimaryGroup
= SeLocalSystemSid
;
766 /* Owner is admins */
767 Owner
= SeAliasAdminsSid
;
769 /* Groups are admins, world, and authenticated users */
770 Groups
[0].Sid
= SeAliasAdminsSid
;
771 Groups
[0].Attributes
= OwnerAttributes
;
772 Groups
[1].Sid
= SeWorldSid
;
773 Groups
[1].Attributes
= GroupAttributes
;
774 Groups
[2].Sid
= SeAuthenticatedUserSid
;
775 Groups
[2].Attributes
= OwnerAttributes
;
776 GroupLength
= sizeof(SID_AND_ATTRIBUTES
) +
777 SeLengthSid(Groups
[0].Sid
) +
778 SeLengthSid(Groups
[1].Sid
) +
779 SeLengthSid(Groups
[2].Sid
);
780 ASSERT(GroupLength
<= sizeof(Groups
));
782 /* Setup the privileges */
784 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
785 Privileges
[i
++].Luid
= SeTcbPrivilege
;
787 Privileges
[i
].Attributes
= 0;
788 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
790 Privileges
[i
].Attributes
= 0;
791 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
793 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
794 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
796 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
797 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
799 Privileges
[i
].Attributes
= 0;
800 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
802 Privileges
[i
].Attributes
= 0;
803 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
805 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
806 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
808 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
809 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
811 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
812 Privileges
[i
++].Luid
= SeDebugPrivilege
;
814 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
815 Privileges
[i
++].Luid
= SeAuditPrivilege
;
817 Privileges
[i
].Attributes
= 0;
818 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
820 Privileges
[i
].Attributes
= 0;
821 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
823 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
824 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
826 Privileges
[i
].Attributes
= 0;
827 Privileges
[i
++].Luid
= SeBackupPrivilege
;
829 Privileges
[i
].Attributes
= 0;
830 Privileges
[i
++].Luid
= SeRestorePrivilege
;
832 Privileges
[i
].Attributes
= 0;
833 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
835 Privileges
[i
].Attributes
= 0;
836 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
838 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
839 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
841 Privileges
[i
].Attributes
= 0;
842 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
845 /* Setup the object attributes */
846 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
847 ASSERT(SeSystemDefaultDacl
!= NULL
);
849 /* Create the token */
850 Status
= SepCreateToken((PHANDLE
)&Token
,
856 &SeSystemAuthenticationId
,
867 &SeSystemTokenSource
,
869 ASSERT(Status
== STATUS_SUCCESS
);
871 /* Return the token */
875 /* PUBLIC FUNCTIONS ***********************************************************/
882 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
884 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
885 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
886 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
887 OUT PACCESS_TOKEN
* FilteredToken
)
890 return STATUS_NOT_IMPLEMENTED
;
898 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
899 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
900 OUT PVOID
*TokenInformation
)
903 return STATUS_NOT_IMPLEMENTED
;
911 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
912 IN PULONG pSessionId
)
914 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
915 return STATUS_SUCCESS
;
923 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
928 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
930 return STATUS_SUCCESS
;
937 SECURITY_IMPERSONATION_LEVEL
939 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
943 return ((PTOKEN
)Token
)->ImpersonationLevel
;
951 SeTokenType(IN PACCESS_TOKEN Token
)
955 return ((PTOKEN
)Token
)->TokenType
;
964 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
968 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
976 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
980 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
988 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
992 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
995 /* SYSTEM CALLS ***************************************************************/
1001 NtQueryInformationToken(IN HANDLE TokenHandle
,
1002 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1003 OUT PVOID TokenInformation
,
1004 IN ULONG TokenInformationLength
,
1005 OUT PULONG ReturnLength
)
1013 ULONG RequiredLength
;
1014 KPROCESSOR_MODE PreviousMode
;
1015 NTSTATUS Status
= STATUS_SUCCESS
;
1019 PreviousMode
= ExGetPreviousMode();
1021 /* Check buffers and class validity */
1022 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1023 SeTokenInformationClass
,
1024 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1026 TokenInformationLength
,
1030 if (!NT_SUCCESS(Status
))
1032 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1036 Status
= ObReferenceObjectByHandle(TokenHandle
,
1037 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1042 if (NT_SUCCESS(Status
))
1044 switch (TokenInformationClass
)
1048 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1050 DPRINT("NtQueryInformationToken(TokenUser)\n");
1051 RequiredLength
= sizeof(TOKEN_USER
) +
1052 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1056 if (TokenInformationLength
>= RequiredLength
)
1058 Status
= RtlCopySidAndAttributesArray(1,
1059 &Token
->UserAndGroups
[0],
1060 RequiredLength
- sizeof(TOKEN_USER
),
1068 Status
= STATUS_BUFFER_TOO_SMALL
;
1071 if (ReturnLength
!= NULL
)
1073 *ReturnLength
= RequiredLength
;
1076 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1078 Status
= _SEH2_GetExceptionCode();
1087 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1089 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1090 RequiredLength
= sizeof(tg
->GroupCount
) +
1091 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1095 if (TokenInformationLength
>= RequiredLength
)
1097 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1098 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1099 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1100 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1102 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1103 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1104 &Token
->UserAndGroups
[1],
1113 Status
= STATUS_BUFFER_TOO_SMALL
;
1116 if (ReturnLength
!= NULL
)
1118 *ReturnLength
= RequiredLength
;
1121 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1123 Status
= _SEH2_GetExceptionCode();
1130 case TokenPrivileges
:
1132 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1134 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1135 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1136 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1140 if (TokenInformationLength
>= RequiredLength
)
1142 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1143 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1145 &tp
->Privileges
[0]);
1149 Status
= STATUS_BUFFER_TOO_SMALL
;
1152 if (ReturnLength
!= NULL
)
1154 *ReturnLength
= RequiredLength
;
1157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1159 Status
= _SEH2_GetExceptionCode();
1169 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1171 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1172 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1173 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1177 if (TokenInformationLength
>= RequiredLength
)
1179 to
->Owner
= (PSID
)(to
+ 1);
1180 Status
= RtlCopySid(SidLen
,
1182 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1186 Status
= STATUS_BUFFER_TOO_SMALL
;
1189 if (ReturnLength
!= NULL
)
1191 *ReturnLength
= RequiredLength
;
1194 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1196 Status
= _SEH2_GetExceptionCode();
1203 case TokenPrimaryGroup
:
1206 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1208 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1209 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1210 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1214 if (TokenInformationLength
>= RequiredLength
)
1216 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1217 Status
= RtlCopySid(SidLen
,
1219 Token
->PrimaryGroup
);
1223 Status
= STATUS_BUFFER_TOO_SMALL
;
1226 if (ReturnLength
!= NULL
)
1228 *ReturnLength
= RequiredLength
;
1231 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1233 Status
= _SEH2_GetExceptionCode();
1240 case TokenDefaultDacl
:
1242 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1244 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1245 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1247 if (Token
->DefaultDacl
!= NULL
)
1249 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1254 if (TokenInformationLength
>= RequiredLength
)
1256 if (Token
->DefaultDacl
!= NULL
)
1258 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1259 RtlCopyMemory(tdd
->DefaultDacl
,
1261 Token
->DefaultDacl
->AclSize
);
1265 tdd
->DefaultDacl
= NULL
;
1270 Status
= STATUS_BUFFER_TOO_SMALL
;
1273 if (ReturnLength
!= NULL
)
1275 *ReturnLength
= RequiredLength
;
1278 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1280 Status
= _SEH2_GetExceptionCode();
1289 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1291 DPRINT("NtQueryInformationToken(TokenSource)\n");
1292 RequiredLength
= sizeof(TOKEN_SOURCE
);
1296 if (TokenInformationLength
>= RequiredLength
)
1298 *ts
= Token
->TokenSource
;
1302 Status
= STATUS_BUFFER_TOO_SMALL
;
1305 if (ReturnLength
!= NULL
)
1307 *ReturnLength
= RequiredLength
;
1310 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1312 Status
= _SEH2_GetExceptionCode();
1321 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1323 DPRINT("NtQueryInformationToken(TokenType)\n");
1324 RequiredLength
= sizeof(TOKEN_TYPE
);
1328 if (TokenInformationLength
>= RequiredLength
)
1330 *tt
= Token
->TokenType
;
1334 Status
= STATUS_BUFFER_TOO_SMALL
;
1337 if (ReturnLength
!= NULL
)
1339 *ReturnLength
= RequiredLength
;
1342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1344 Status
= _SEH2_GetExceptionCode();
1351 case TokenImpersonationLevel
:
1353 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1355 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1357 /* Fail if the token is not an impersonation token */
1358 if (Token
->TokenType
!= TokenImpersonation
)
1360 Status
= STATUS_INVALID_INFO_CLASS
;
1364 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1368 if (TokenInformationLength
>= RequiredLength
)
1370 *sil
= Token
->ImpersonationLevel
;
1374 Status
= STATUS_BUFFER_TOO_SMALL
;
1377 if (ReturnLength
!= NULL
)
1379 *ReturnLength
= RequiredLength
;
1382 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1384 Status
= _SEH2_GetExceptionCode();
1391 case TokenStatistics
:
1393 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1395 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1396 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1400 if (TokenInformationLength
>= RequiredLength
)
1402 ts
->TokenId
= Token
->TokenId
;
1403 ts
->AuthenticationId
= Token
->AuthenticationId
;
1404 ts
->ExpirationTime
= Token
->ExpirationTime
;
1405 ts
->TokenType
= Token
->TokenType
;
1406 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1407 ts
->DynamicCharged
= Token
->DynamicCharged
;
1408 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1409 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1410 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1411 ts
->ModifiedId
= Token
->ModifiedId
;
1415 Status
= STATUS_BUFFER_TOO_SMALL
;
1418 if (ReturnLength
!= NULL
)
1420 *ReturnLength
= RequiredLength
;
1423 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1425 Status
= _SEH2_GetExceptionCode();
1434 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1436 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1437 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1441 if (TokenInformationLength
>= RequiredLength
)
1443 RtlCopyLuid(&to
->OriginatingLogonSession
,
1444 &Token
->AuthenticationId
);
1448 Status
= STATUS_BUFFER_TOO_SMALL
;
1451 if (ReturnLength
!= NULL
)
1453 *ReturnLength
= RequiredLength
;
1456 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1458 Status
= _SEH2_GetExceptionCode();
1465 case TokenGroupsAndPrivileges
:
1466 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1467 Status
= STATUS_NOT_IMPLEMENTED
;
1470 case TokenRestrictedSids
:
1472 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1474 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1475 RequiredLength
= sizeof(tg
->GroupCount
) +
1476 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1480 if (TokenInformationLength
>= RequiredLength
)
1482 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1483 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1484 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1485 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1487 tg
->GroupCount
= Token
->RestrictedSidCount
;
1488 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1489 Token
->RestrictedSids
,
1498 Status
= STATUS_BUFFER_TOO_SMALL
;
1501 if (ReturnLength
!= NULL
)
1503 *ReturnLength
= RequiredLength
;
1506 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1508 Status
= _SEH2_GetExceptionCode();
1515 case TokenSandBoxInert
:
1516 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1517 Status
= STATUS_NOT_IMPLEMENTED
;
1520 case TokenSessionId
:
1522 ULONG SessionId
= 0;
1524 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1526 Status
= SeQuerySessionIdToken(Token
,
1529 if (NT_SUCCESS(Status
))
1533 /* buffer size was already verified, no need to check here again */
1534 *(PULONG
)TokenInformation
= SessionId
;
1536 if (ReturnLength
!= NULL
)
1538 *ReturnLength
= sizeof(ULONG
);
1541 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1543 Status
= _SEH2_GetExceptionCode();
1552 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1553 Status
= STATUS_INVALID_INFO_CLASS
;
1557 ObDereferenceObject(Token
);
1565 * NtSetTokenInformation: Partly implemented.
1567 * TokenOrigin, TokenDefaultDacl
1571 NtSetInformationToken(IN HANDLE TokenHandle
,
1572 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1573 OUT PVOID TokenInformation
,
1574 IN ULONG TokenInformationLength
)
1577 KPROCESSOR_MODE PreviousMode
;
1578 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1583 PreviousMode
= ExGetPreviousMode();
1585 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1586 SeTokenInformationClass
,
1587 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1589 TokenInformationLength
,
1591 if (!NT_SUCCESS(Status
))
1593 /* Invalid buffers */
1594 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1598 if (TokenInformationClass
== TokenSessionId
)
1600 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1603 Status
= ObReferenceObjectByHandle(TokenHandle
,
1609 if (NT_SUCCESS(Status
))
1611 switch (TokenInformationClass
)
1615 if (TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1617 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1618 PSID InputSid
= NULL
, CapturedSid
;
1622 InputSid
= to
->Owner
;
1624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1626 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1630 Status
= SepCaptureSid(InputSid
,
1635 if (NT_SUCCESS(Status
))
1637 RtlCopySid(RtlLengthSid(CapturedSid
),
1638 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1640 SepReleaseSid(CapturedSid
,
1647 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1652 case TokenPrimaryGroup
:
1654 if (TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1656 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1657 PSID InputSid
= NULL
, CapturedSid
;
1661 InputSid
= tpg
->PrimaryGroup
;
1663 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1665 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1669 Status
= SepCaptureSid(InputSid
,
1674 if (NT_SUCCESS(Status
))
1676 RtlCopySid(RtlLengthSid(CapturedSid
),
1677 Token
->PrimaryGroup
,
1679 SepReleaseSid(CapturedSid
,
1686 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1691 case TokenDefaultDacl
:
1693 if (TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1695 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1696 PACL InputAcl
= NULL
;
1700 InputAcl
= tdd
->DefaultDacl
;
1702 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1704 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1708 if (InputAcl
!= NULL
)
1712 /* Capture and copy the dacl */
1713 Status
= SepCaptureAcl(InputAcl
,
1718 if (NT_SUCCESS(Status
))
1720 /* Free the previous dacl if present */
1721 if(Token
->DefaultDacl
!= NULL
)
1723 ExFreePool(Token
->DefaultDacl
);
1726 /* Set the new dacl */
1727 Token
->DefaultDacl
= CapturedAcl
;
1732 /* Clear and free the default dacl if present */
1733 if (Token
->DefaultDacl
!= NULL
)
1735 ExFreePool(Token
->DefaultDacl
);
1736 Token
->DefaultDacl
= NULL
;
1742 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1747 case TokenSessionId
:
1749 ULONG SessionId
= 0;
1753 /* Buffer size was already verified, no need to check here again */
1754 SessionId
= *(PULONG
)TokenInformation
;
1756 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1758 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1762 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1765 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1769 Token
->SessionId
= SessionId
;
1775 Status
= STATUS_NOT_IMPLEMENTED
;
1780 ObDereferenceObject(Token
);
1790 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1791 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1792 * is correct either. -Gunnar
1793 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1796 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1797 IN ACCESS_MASK DesiredAccess
,
1798 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1799 IN BOOLEAN EffectiveOnly
,
1800 IN TOKEN_TYPE TokenType
,
1801 OUT PHANDLE NewTokenHandle
)
1803 KPROCESSOR_MODE PreviousMode
;
1807 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1809 OBJECT_HANDLE_INFORMATION HandleInformation
;
1814 if (TokenType
!= TokenImpersonation
&&
1815 TokenType
!= TokenPrimary
)
1816 return STATUS_INVALID_PARAMETER
;
1818 PreviousMode
= KeGetPreviousMode();
1820 if (PreviousMode
!= KernelMode
)
1824 ProbeForWriteHandle(NewTokenHandle
);
1826 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1828 /* Return the exception code */
1829 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1834 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1838 &CapturedSecurityQualityOfService
,
1840 if (!NT_SUCCESS(Status
))
1842 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1846 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1851 &HandleInformation
);
1852 if (!NT_SUCCESS(Status
))
1854 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1861 * Fail, if the original token is an impersonation token and the caller
1862 * tries to raise the impersonation level of the new token above the
1863 * impersonation level of the original token.
1865 if (Token
->TokenType
== TokenImpersonation
)
1868 CapturedSecurityQualityOfService
->ImpersonationLevel
>Token
->ImpersonationLevel
)
1870 ObDereferenceObject(Token
);
1871 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1874 return STATUS_BAD_IMPERSONATION_LEVEL
;
1879 * Fail, if a primary token is to be created from an impersonation token
1880 * and and the impersonation level of the impersonation token is below SecurityImpersonation.
1882 if (Token
->TokenType
== TokenImpersonation
&&
1883 TokenType
== TokenPrimary
&&
1884 Token
->ImpersonationLevel
< SecurityImpersonation
)
1886 ObDereferenceObject(Token
);
1887 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1890 return STATUS_BAD_IMPERSONATION_LEVEL
;
1893 Status
= SepDuplicateToken(Token
,
1897 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1901 ObDereferenceObject(Token
);
1903 if (NT_SUCCESS(Status
))
1905 Status
= ObInsertObject((PVOID
)NewToken
,
1907 (DesiredAccess
? DesiredAccess
: HandleInformation
.GrantedAccess
),
1911 if (NT_SUCCESS(Status
))
1915 *NewTokenHandle
= hToken
;
1917 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1919 Status
= _SEH2_GetExceptionCode();
1925 /* Free the captured structure */
1926 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1934 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1935 IN BOOLEAN ResetToDefault
,
1936 IN PTOKEN_GROUPS NewState
,
1937 IN ULONG BufferLength
,
1938 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1939 OUT PULONG ReturnLength
)
1942 return(STATUS_NOT_IMPLEMENTED
);
1949 NtAdjustPrivilegesToken(IN HANDLE TokenHandle
,
1950 IN BOOLEAN DisableAllPrivileges
,
1951 IN PTOKEN_PRIVILEGES NewState
,
1952 IN ULONG BufferLength
,
1953 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1954 OUT PULONG ReturnLength OPTIONAL
)
1956 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
1957 KPROCESSOR_MODE PreviousMode
;
1958 ULONG CapturedCount
= 0;
1959 ULONG CapturedLength
= 0;
1960 ULONG NewStateSize
= 0;
1969 DPRINT ("NtAdjustPrivilegesToken() called\n");
1971 /* Fail, if we do not disable all privileges but NewState is NULL */
1972 if (DisableAllPrivileges
== FALSE
&& NewState
== NULL
)
1973 return STATUS_INVALID_PARAMETER
;
1975 PreviousMode
= KeGetPreviousMode ();
1976 if (PreviousMode
!= KernelMode
)
1980 /* Probe NewState */
1981 if (DisableAllPrivileges
== FALSE
)
1983 ProbeForRead(NewState
,
1984 sizeof(TOKEN_PRIVILEGES
),
1987 CapturedCount
= NewState
->PrivilegeCount
;
1988 NewStateSize
= (ULONG
)sizeof(TOKEN_PRIVILEGES
) +
1989 ((CapturedCount
- ANYSIZE_ARRAY
) * (ULONG
)sizeof(LUID_AND_ATTRIBUTES
));
1991 ProbeForRead(NewState
,
1996 /* Probe PreviousState and ReturnLength */
1997 if (PreviousState
!= NULL
)
1999 ProbeForWrite(PreviousState
,
2003 ProbeForWrite(ReturnLength
,
2008 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2010 /* Return the exception code */
2011 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2017 if (DisableAllPrivileges
== FALSE
)
2018 CapturedCount
= NewState
->PrivilegeCount
;
2021 if (DisableAllPrivileges
== FALSE
)
2025 /* Capture the new state array of privileges */
2026 Status
= SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
2033 &CapturedPrivileges
,
2036 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2038 /* Return the exception code */
2039 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2043 if (!NT_SUCCESS(Status
))
2047 /* Reference the token */
2048 Status
= ObReferenceObjectByHandle(TokenHandle
,
2049 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
2054 if (!NT_SUCCESS(Status
))
2056 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
2058 /* Release the captured privileges */
2059 if (CapturedPrivileges
!= NULL
)
2060 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2067 /* Count the privileges that need to be changed */
2069 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2071 if (DisableAllPrivileges
)
2073 if (Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
2075 DPRINT("Privilege enabled\n");
2082 for (j
= 0; j
< CapturedCount
; j
++)
2084 if (Token
->Privileges
[i
].Luid
.LowPart
== CapturedPrivileges
[j
].Luid
.LowPart
&&
2085 Token
->Privileges
[i
].Luid
.HighPart
== CapturedPrivileges
[j
].Luid
.HighPart
)
2087 DPRINT("Found privilege\n");
2089 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
2090 (CapturedPrivileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
2092 DPRINT("Attributes differ\n");
2093 DPRINT("Current attributes %lx New attributes %lx\n",
2094 Token
->Privileges
[i
].Attributes
,
2095 CapturedPrivileges
[j
].Attributes
);
2105 * Return the required buffer size and
2106 * check if the available buffer is large enough
2108 if (PreviousState
!= NULL
)
2110 ULONG RequiredLength
= (ULONG
)sizeof(TOKEN_PRIVILEGES
) +
2111 ((ChangeCount
- ANYSIZE_ARRAY
) * (ULONG
)sizeof(LUID_AND_ATTRIBUTES
));
2113 /* Try to return the required buffer length */
2116 *ReturnLength
= RequiredLength
;
2118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2120 /* Dereference the token */
2121 ObDereferenceObject(Token
);
2123 /* Release the captured privileges */
2124 if (CapturedPrivileges
!= NULL
)
2125 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2129 /* Return the exception code */
2130 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2134 /* Fail, if the buffer length is smaller than the required length */
2135 if (BufferLength
< RequiredLength
)
2137 /* Dereference the token */
2138 ObDereferenceObject(Token
);
2140 /* Release the captured privileges */
2141 if (CapturedPrivileges
!= NULL
)
2142 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2146 return STATUS_BUFFER_TOO_SMALL
;
2150 /* Change the privilege attributes */
2154 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2156 if (DisableAllPrivileges
== TRUE
)
2158 if (Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
2160 DPRINT("Privilege enabled\n");
2162 /* Save the current privilege */
2163 if (PreviousState
!= NULL
)
2165 PreviousState
->Privileges
[ChangeCount
].Luid
= Token
->Privileges
[i
].Luid
;
2166 PreviousState
->Privileges
[ChangeCount
].Attributes
= Token
->Privileges
[i
].Attributes
;
2169 /* Disable the current privlege */
2170 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2177 for (j
= 0; j
< CapturedCount
; j
++)
2179 if (Token
->Privileges
[i
].Luid
.LowPart
== CapturedPrivileges
[j
].Luid
.LowPart
&&
2180 Token
->Privileges
[i
].Luid
.HighPart
== CapturedPrivileges
[j
].Luid
.HighPart
)
2182 DPRINT("Found privilege\n");
2184 /* Check whether the attributes differ */
2185 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
2186 (CapturedPrivileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
2188 DPRINT("Attributes differ\n");
2189 DPRINT("Current attributes %lx New attributes %lx\n",
2190 Token
->Privileges
[i
].Attributes
,
2191 CapturedPrivileges
[j
].Attributes
);
2193 /* Save the current privilege */
2194 if (PreviousState
!= NULL
)
2196 PreviousState
->Privileges
[ChangeCount
].Luid
= Token
->Privileges
[i
].Luid
;
2197 PreviousState
->Privileges
[ChangeCount
].Attributes
= Token
->Privileges
[i
].Attributes
;
2200 /* Update the current privlege */
2201 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2202 Token
->Privileges
[i
].Attributes
|=
2203 (CapturedPrivileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
2204 DPRINT("New attributes %lx\n",
2205 Token
->Privileges
[i
].Attributes
);
2214 /* Set the number of saved privileges */
2215 if (PreviousState
!= NULL
)
2216 PreviousState
->PrivilegeCount
= ChangeCount
;
2218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2220 /* Dereference the token */
2221 ObDereferenceObject(Token
);
2223 /* Release the captured privileges */
2224 if (CapturedPrivileges
!= NULL
)
2225 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2229 /* Return the exception code */
2230 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2234 /* Set the status */
2235 Status
= (ChangeCount
< CapturedCount
) ? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
2237 /* Dereference the token */
2238 ObDereferenceObject (Token
);
2240 /* Release the captured privileges */
2241 if (CapturedPrivileges
!= NULL
)
2242 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2246 DPRINT ("NtAdjustPrivilegesToken() done\n");
2253 NtCreateToken(OUT PHANDLE TokenHandle
,
2254 IN ACCESS_MASK DesiredAccess
,
2255 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2256 IN TOKEN_TYPE TokenType
,
2257 IN PLUID AuthenticationId
,
2258 IN PLARGE_INTEGER ExpirationTime
,
2259 IN PTOKEN_USER TokenUser
,
2260 IN PTOKEN_GROUPS TokenGroups
,
2261 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2262 IN PTOKEN_OWNER TokenOwner
,
2263 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2264 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2265 IN PTOKEN_SOURCE TokenSource
)
2268 KPROCESSOR_MODE PreviousMode
;
2269 ULONG nTokenPrivileges
= 0;
2270 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
2275 PreviousMode
= ExGetPreviousMode();
2277 if (PreviousMode
!= KernelMode
)
2281 ProbeForWriteHandle(TokenHandle
);
2282 ProbeForRead(AuthenticationId
,
2285 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2286 ProbeForRead(TokenUser
,
2289 ProbeForRead(TokenGroups
,
2290 sizeof(TOKEN_GROUPS
),
2292 ProbeForRead(TokenPrivileges
,
2293 sizeof(TOKEN_PRIVILEGES
),
2295 ProbeForRead(TokenOwner
,
2296 sizeof(TOKEN_OWNER
),
2298 ProbeForRead(TokenPrimaryGroup
,
2299 sizeof(TOKEN_PRIMARY_GROUP
),
2301 ProbeForRead(TokenDefaultDacl
,
2302 sizeof(TOKEN_DEFAULT_DACL
),
2304 ProbeForRead(TokenSource
,
2305 sizeof(TOKEN_SOURCE
),
2307 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2311 /* Return the exception code */
2312 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2318 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2319 LocalExpirationTime
= *ExpirationTime
;
2322 Status
= SepCreateToken(&hToken
,
2327 ((PSECURITY_QUALITY_OF_SERVICE
)(ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
,
2329 &LocalExpirationTime
,
2331 TokenGroups
->GroupCount
,
2332 TokenGroups
->Groups
,
2333 0, // FIXME: Should capture
2335 TokenPrivileges
->Privileges
,
2337 TokenPrimaryGroup
->PrimaryGroup
,
2338 TokenDefaultDacl
->DefaultDacl
,
2341 if (NT_SUCCESS(Status
))
2345 *TokenHandle
= hToken
;
2347 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2349 Status
= _SEH2_GetExceptionCode();
2362 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2363 IN ACCESS_MASK DesiredAccess
,
2364 IN BOOLEAN OpenAsSelf
,
2365 IN ULONG HandleAttributes
,
2366 OUT PHANDLE TokenHandle
)
2368 PETHREAD Thread
, NewThread
;
2370 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
2371 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2372 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2373 SE_IMPERSONATION_STATE ImpersonationState
;
2374 OBJECT_ATTRIBUTES ObjectAttributes
;
2375 SECURITY_DESCRIPTOR SecurityDescriptor
;
2377 KPROCESSOR_MODE PreviousMode
;
2382 PreviousMode
= ExGetPreviousMode();
2384 if (PreviousMode
!= KernelMode
)
2388 ProbeForWriteHandle(TokenHandle
);
2390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2392 /* Return the exception code */
2393 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2399 * At first open the thread token for information access and verify
2400 * that the token associated with thread is valid.
2403 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2404 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2406 if (!NT_SUCCESS(Status
))
2411 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2412 &ImpersonationLevel
);
2415 ObDereferenceObject(Thread
);
2416 return STATUS_NO_TOKEN
;
2419 if (ImpersonationLevel
== SecurityAnonymous
)
2421 PsDereferenceImpersonationToken(Token
);
2422 ObDereferenceObject(Thread
);
2423 return STATUS_CANT_OPEN_ANONYMOUS
;
2427 * Revert to self if OpenAsSelf is specified.
2432 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2437 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2438 PsThreadType
, KernelMode
,
2439 (PVOID
*)&NewThread
, NULL
);
2440 if (NT_SUCCESS(Status
))
2442 PrimaryToken
= PsReferencePrimaryToken(NewThread
->ThreadsProcess
);
2444 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2446 ObFastDereferenceObject(&NewThread
->ThreadsProcess
->Token
, PrimaryToken
);
2448 if (NT_SUCCESS(Status
))
2452 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2453 SECURITY_DESCRIPTOR_REVISION
);
2454 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2458 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2459 NULL
, Dacl
? &SecurityDescriptor
: NULL
);
2462 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2463 TokenImpersonation
, ImpersonationLevel
,
2464 KernelMode
, &NewToken
);
2465 if (NT_SUCCESS(Status
))
2467 ObReferenceObject(NewToken
);
2468 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2476 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2477 NULL
, DesiredAccess
, SepTokenObjectType
,
2478 PreviousMode
, &hToken
);
2481 if (Dacl
) ExFreePool(Dacl
);
2485 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2488 ObDereferenceObject(Token
);
2490 if (NT_SUCCESS(Status
) && CopyOnOpen
)
2492 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
2495 if (NewToken
) ObDereferenceObject(NewToken
);
2497 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
2499 if (NT_SUCCESS(Status
))
2503 *TokenHandle
= hToken
;
2505 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2507 Status
= _SEH2_GetExceptionCode();
2519 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2520 IN ACCESS_MASK DesiredAccess
,
2521 IN BOOLEAN OpenAsSelf
,
2522 OUT PHANDLE TokenHandle
)
2524 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2535 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2536 IN HANDLE SecondTokenHandle
,
2539 KPROCESSOR_MODE PreviousMode
;
2540 PTOKEN FirstToken
, SecondToken
;
2546 PreviousMode
= ExGetPreviousMode();
2548 if (PreviousMode
!= KernelMode
)
2552 ProbeForWriteBoolean(Equal
);
2554 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2556 /* Return the exception code */
2557 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2562 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2566 (PVOID
*)&FirstToken
,
2568 if (!NT_SUCCESS(Status
))
2571 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2575 (PVOID
*)&SecondToken
,
2577 if (!NT_SUCCESS(Status
))
2579 ObDereferenceObject(FirstToken
);
2583 if (FirstToken
!= SecondToken
)
2585 Status
= SepCompareTokens(FirstToken
,
2592 ObDereferenceObject(FirstToken
);
2593 ObDereferenceObject(SecondToken
);
2595 if (NT_SUCCESS(Status
))
2601 _SEH2_EXCEPT(ExSystemExceptionFilter())
2603 Status
= _SEH2_GetExceptionCode();
2613 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2615 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2616 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2617 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2618 OUT PHANDLE NewTokenHandle
)
2621 return STATUS_NOT_IMPLEMENTED
;
2629 NtImpersonateAnonymousToken(IN HANDLE Thread
)
2632 return STATUS_NOT_IMPLEMENTED
;