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( sizeof(ULONG
), sizeof(ULONG
), ICIF_SET
| 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 SepUpdateSinglePrivilegeFlagToken(
107 _Inout_ PTOKEN Token
,
111 NT_ASSERT(Index
< Token
->PrivilegeCount
);
113 /* The high part of all values we are interested in is 0 */
114 if (Token
->Privileges
[Index
].Luid
.HighPart
!= 0)
119 /* Check for certain privileges to update flags */
120 if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_CHANGE_NOTIFY_PRIVILEGE
)
122 TokenFlag
= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
124 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_BACKUP_PRIVILEGE
)
126 TokenFlag
= TOKEN_HAS_BACKUP_PRIVILEGE
;
128 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_RESTORE_PRIVILEGE
)
130 TokenFlag
= TOKEN_HAS_RESTORE_PRIVILEGE
;
132 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_IMPERSONATE_PRIVILEGE
)
134 TokenFlag
= TOKEN_HAS_IMPERSONATE_PRIVILEGE
;
142 /* Check if the specified privilege is enabled */
143 if (Token
->Privileges
[Index
].Attributes
& SE_PRIVILEGE_ENABLED
)
145 /* It is enabled, so set the flag */
146 Token
->TokenFlags
|= TokenFlag
;
150 /* Is is disabled, so remove the flag */
151 Token
->TokenFlags
&= ~TokenFlag
;
157 SepUpdatePrivilegeFlagsToken(
158 _Inout_ PTOKEN Token
)
162 /* Loop all privileges */
163 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
165 /* Updates the flags dor this privilege */
166 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
172 SepRemovePrivilegeToken(
173 _Inout_ PTOKEN Token
,
177 NT_ASSERT(Index
< Token
->PrivilegeCount
);
179 /* Calculate the number of trailing privileges */
180 MoveCount
= Token
->PrivilegeCount
- Index
- 1;
183 /* Move them one location ahead */
184 RtlMoveMemory(&Token
->Privileges
[Index
],
185 &Token
->Privileges
[Index
+ 1],
186 MoveCount
* sizeof(LUID_AND_ATTRIBUTES
));
189 /* Update privilege count */
190 Token
->PrivilegeCount
--;
195 SepFreeProxyData(PVOID ProxyData
)
202 SepCopyProxyData(PVOID
* Dest
,
206 return STATUS_NOT_IMPLEMENTED
;
211 SeExchangePrimaryToken(PEPROCESS Process
,
212 PACCESS_TOKEN NewTokenP
,
213 PACCESS_TOKEN
* OldTokenP
)
216 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
220 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
221 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
223 /* Mark new token in use */
224 NewToken
->TokenInUse
= 1;
226 /* Reference the New Token */
227 ObReferenceObject(NewToken
);
229 /* Replace the old with the new */
230 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
232 /* Mark the Old Token as free */
233 OldToken
->TokenInUse
= 0;
235 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
236 return STATUS_SUCCESS
;
241 SeDeassignPrimaryToken(PEPROCESS Process
)
245 /* Remove the Token */
246 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
248 /* Mark the Old Token as free */
249 OldToken
->TokenInUse
= 0;
253 RtlLengthSidAndAttributes(ULONG Count
,
254 PSID_AND_ATTRIBUTES Src
)
261 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
262 for (i
= 0; i
< Count
; i
++)
263 uLength
+= RtlLengthSid(Src
[i
].Sid
);
271 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
277 Token
->PrimaryGroup
= 0;
281 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
284 /* Validate and set the primary group and user pointers */
285 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
288 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
290 Token
->DefaultOwnerIndex
= i
;
293 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
295 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
299 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
301 return(STATUS_INVALID_OWNER
);
304 if (Token
->PrimaryGroup
== 0)
306 return(STATUS_INVALID_PRIMARY_GROUP
);
309 return STATUS_SUCCESS
;
315 SepDuplicateToken(PTOKEN Token
,
316 POBJECT_ATTRIBUTES ObjectAttributes
,
317 BOOLEAN EffectiveOnly
,
318 TOKEN_TYPE TokenType
,
319 SECURITY_IMPERSONATION_LEVEL Level
,
320 KPROCESSOR_MODE PreviousMode
,
321 PTOKEN
* NewAccessToken
)
326 PTOKEN AccessToken
= NULL
;
331 Status
= ObCreateObject(PreviousMode
,
339 (PVOID
*)&AccessToken
);
340 if (!NT_SUCCESS(Status
))
342 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
346 /* Zero out the buffer */
347 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
349 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
350 if (!NT_SUCCESS(Status
))
352 ObDereferenceObject(AccessToken
);
356 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
357 if (!NT_SUCCESS(Status
))
359 ObDereferenceObject(AccessToken
);
363 AccessToken
->TokenLock
= &SepTokenLock
;
365 AccessToken
->TokenType
= TokenType
;
366 AccessToken
->ImpersonationLevel
= Level
;
367 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
369 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
370 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
371 memcpy(AccessToken
->TokenSource
.SourceName
,
372 Token
->TokenSource
.SourceName
,
373 sizeof(Token
->TokenSource
.SourceName
));
374 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
375 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
376 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
378 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
379 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
380 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
382 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
385 if (AccessToken
->UserAndGroups
== NULL
)
387 Status
= STATUS_INSUFFICIENT_RESOURCES
;
391 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
393 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
394 Token
->UserAndGroups
,
396 AccessToken
->UserAndGroups
,
400 if (!NT_SUCCESS(Status
))
403 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
406 if (!NT_SUCCESS(Status
))
409 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
411 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
412 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
414 TAG_TOKEN_PRIVILAGES
);
415 if (AccessToken
->Privileges
== NULL
)
417 Status
= STATUS_INSUFFICIENT_RESOURCES
;
421 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
423 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
424 &Token
->Privileges
[i
].Luid
);
425 AccessToken
->Privileges
[i
].Attributes
=
426 Token
->Privileges
[i
].Attributes
;
429 if (Token
->DefaultDacl
)
431 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
432 Token
->DefaultDacl
->AclSize
,
434 if (AccessToken
->DefaultDacl
== NULL
)
436 Status
= STATUS_INSUFFICIENT_RESOURCES
;
440 memcpy(AccessToken
->DefaultDacl
,
442 Token
->DefaultDacl
->AclSize
);
445 *NewAccessToken
= AccessToken
;
448 if (!NT_SUCCESS(Status
))
452 if (AccessToken
->UserAndGroups
)
453 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
455 if (AccessToken
->Privileges
)
456 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
458 if (AccessToken
->DefaultDacl
)
459 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
461 ObDereferenceObject(AccessToken
);
470 SeSubProcessToken(IN PTOKEN ParentToken
,
476 OBJECT_ATTRIBUTES ObjectAttributes
;
479 /* Initialize the attributes and duplicate it */
480 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
481 Status
= SepDuplicateToken(ParentToken
,
485 ParentToken
->ImpersonationLevel
,
488 if (NT_SUCCESS(Status
))
491 Status
= ObInsertObject(NewToken
,
497 if (NT_SUCCESS(Status
))
499 /* Set the session ID */
500 NewToken
->SessionId
= SessionId
;
501 NewToken
->TokenInUse
= InUse
;
503 /* Return the token */
514 SeIsTokenChild(IN PTOKEN Token
,
515 OUT PBOOLEAN IsChild
)
518 LUID ProcessLuid
, CallerLuid
;
523 /* Reference the process token */
524 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
527 ProcessLuid
= ProcessToken
->TokenId
;
529 /* Dereference the token */
530 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
533 CallerLuid
= Token
->TokenId
;
535 /* Compare the LUIDs */
536 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
539 return STATUS_SUCCESS
;
544 SeCopyClientToken(IN PACCESS_TOKEN Token
,
545 IN SECURITY_IMPERSONATION_LEVEL Level
,
546 IN KPROCESSOR_MODE PreviousMode
,
547 OUT PACCESS_TOKEN
* NewToken
)
550 OBJECT_ATTRIBUTES ObjectAttributes
;
554 InitializeObjectAttributes(&ObjectAttributes
,
559 Status
= SepDuplicateToken(Token
,
572 SepDeleteToken(PVOID ObjectBody
)
574 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
576 if (AccessToken
->UserAndGroups
)
577 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
579 if (AccessToken
->Privileges
)
580 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
582 if (AccessToken
->DefaultDacl
)
583 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
590 SepInitializeTokenImplementation(VOID
)
593 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
595 ExInitializeResource(&SepTokenLock
);
597 DPRINT("Creating Token Object Type\n");
599 /* Initialize the Token type */
600 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
601 RtlInitUnicodeString(&Name
, L
"Token");
602 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
603 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
604 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
605 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
606 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
607 ObjectTypeInitializer
.PoolType
= PagedPool
;
608 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
609 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
610 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
611 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SeTokenObjectType
);
616 SeAssignPrimaryToken(IN PEPROCESS Process
,
622 ASSERT(Token
->TokenType
== TokenPrimary
);
623 ASSERT(!Token
->TokenInUse
);
625 /* Clean any previous token */
626 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
628 /* Set the new token */
629 ObReferenceObject(Token
);
630 Token
->TokenInUse
= TRUE
;
631 ObInitializeFastReference(&Process
->Token
, Token
);
637 SepCreateToken(OUT PHANDLE TokenHandle
,
638 IN KPROCESSOR_MODE PreviousMode
,
639 IN ACCESS_MASK DesiredAccess
,
640 IN POBJECT_ATTRIBUTES ObjectAttributes
,
641 IN TOKEN_TYPE TokenType
,
642 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
643 IN PLUID AuthenticationId
,
644 IN PLARGE_INTEGER ExpirationTime
,
645 IN PSID_AND_ATTRIBUTES User
,
647 IN PSID_AND_ATTRIBUTES Groups
,
648 IN ULONG GroupLength
,
649 IN ULONG PrivilegeCount
,
650 IN PLUID_AND_ATTRIBUTES Privileges
,
652 IN PSID PrimaryGroup
,
654 IN PTOKEN_SOURCE TokenSource
,
655 IN BOOLEAN SystemToken
)
664 ULONG TokenFlags
= 0;
666 /* Loop all groups */
667 for (i
= 0; i
< GroupCount
; i
++)
669 /* Check for mandatory groups */
670 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
672 /* Force them to be enabled */
673 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
676 /* Check of the group is an admin group */
677 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
679 /* Remember this so we can optimize queries later */
680 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
684 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
685 if (!NT_SUCCESS(Status
))
688 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
689 if (!NT_SUCCESS(Status
))
692 Status
= ObCreateObject(PreviousMode
,
700 (PVOID
*)&AccessToken
);
701 if (!NT_SUCCESS(Status
))
703 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
707 /* Zero out the buffer */
708 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
710 AccessToken
->TokenLock
= &SepTokenLock
;
712 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
713 &TokenSource
->SourceIdentifier
);
714 memcpy(AccessToken
->TokenSource
.SourceName
,
715 TokenSource
->SourceName
,
716 sizeof(TokenSource
->SourceName
));
718 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
719 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
720 AccessToken
->ExpirationTime
= *ExpirationTime
;
721 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
723 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
724 AccessToken
->PrivilegeCount
= PrivilegeCount
;
726 AccessToken
->TokenFlags
= TokenFlags
;
727 AccessToken
->TokenType
= TokenType
;
728 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
731 * Normally we would just point these members into the variable information
732 * area; however, our ObCreateObject() call can't allocate a variable information
733 * area, so we allocate them seperately and provide a destroy function.
736 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
737 uLength
+= RtlLengthSid(User
->Sid
);
738 for (i
= 0; i
< GroupCount
; i
++)
739 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
741 // FIXME: should use the object itself
742 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
745 if (AccessToken
->UserAndGroups
== NULL
)
747 Status
= STATUS_INSUFFICIENT_RESOURCES
;
751 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
753 Status
= RtlCopySidAndAttributesArray(1,
756 AccessToken
->UserAndGroups
,
760 if (!NT_SUCCESS(Status
))
763 Status
= RtlCopySidAndAttributesArray(GroupCount
,
766 &AccessToken
->UserAndGroups
[1],
770 if (!NT_SUCCESS(Status
))
773 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
776 if (!NT_SUCCESS(Status
))
779 // FIXME: should use the object itself
780 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
781 if (uLength
== 0) uLength
= sizeof(PVOID
);
782 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
784 TAG_TOKEN_PRIVILAGES
);
785 if (AccessToken
->Privileges
== NULL
)
787 Status
= STATUS_INSUFFICIENT_RESOURCES
;
791 if (PreviousMode
!= KernelMode
)
795 RtlCopyMemory(AccessToken
->Privileges
,
797 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
799 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
801 Status
= _SEH2_GetExceptionCode();
807 RtlCopyMemory(AccessToken
->Privileges
,
809 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
812 if (!NT_SUCCESS(Status
))
815 /* Update privilege flags */
816 SepUpdatePrivilegeFlagsToken(AccessToken
);
818 if (DefaultDacl
!= NULL
)
820 // FIXME: should use the object itself
821 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
822 DefaultDacl
->AclSize
,
824 if (AccessToken
->DefaultDacl
== NULL
)
826 Status
= STATUS_INSUFFICIENT_RESOURCES
;
830 RtlCopyMemory(AccessToken
->DefaultDacl
,
832 DefaultDacl
->AclSize
);
836 AccessToken
->DefaultDacl
= NULL
;
841 Status
= ObInsertObject((PVOID
)AccessToken
,
847 if (!NT_SUCCESS(Status
))
849 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
854 /* Return pointer instead of handle */
855 *TokenHandle
= (HANDLE
)AccessToken
;
859 if (!NT_SUCCESS(Status
))
863 /* Dereference the token, the delete procedure will clean up */
864 ObDereferenceObject(AccessToken
);
873 SepCreateSystemProcessToken(VOID
)
875 LUID_AND_ATTRIBUTES Privileges
[25];
876 ULONG GroupAttributes
, OwnerAttributes
;
877 SID_AND_ATTRIBUTES Groups
[32];
878 LARGE_INTEGER Expiration
;
879 SID_AND_ATTRIBUTES UserSid
;
882 OBJECT_ATTRIBUTES ObjectAttributes
;
888 /* Don't ever expire */
889 Expiration
.QuadPart
= -1;
891 /* All groups mandatory and enabled */
892 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
893 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
896 UserSid
.Sid
= SeLocalSystemSid
;
897 UserSid
.Attributes
= 0;
899 /* Primary group is local system */
900 PrimaryGroup
= SeLocalSystemSid
;
902 /* Owner is admins */
903 Owner
= SeAliasAdminsSid
;
905 /* Groups are admins, world, and authenticated users */
906 Groups
[0].Sid
= SeAliasAdminsSid
;
907 Groups
[0].Attributes
= OwnerAttributes
;
908 Groups
[1].Sid
= SeWorldSid
;
909 Groups
[1].Attributes
= GroupAttributes
;
910 Groups
[2].Sid
= SeAuthenticatedUserSid
;
911 Groups
[2].Attributes
= OwnerAttributes
;
912 GroupLength
= sizeof(SID_AND_ATTRIBUTES
) +
913 SeLengthSid(Groups
[0].Sid
) +
914 SeLengthSid(Groups
[1].Sid
) +
915 SeLengthSid(Groups
[2].Sid
);
916 ASSERT(GroupLength
<= sizeof(Groups
));
918 /* Setup the privileges */
920 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
921 Privileges
[i
++].Luid
= SeTcbPrivilege
;
923 Privileges
[i
].Attributes
= 0;
924 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
926 Privileges
[i
].Attributes
= 0;
927 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
929 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
930 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
932 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
933 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
935 Privileges
[i
].Attributes
= 0;
936 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
938 Privileges
[i
].Attributes
= 0;
939 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
941 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
942 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
944 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
945 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
947 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
948 Privileges
[i
++].Luid
= SeDebugPrivilege
;
950 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
951 Privileges
[i
++].Luid
= SeAuditPrivilege
;
953 Privileges
[i
].Attributes
= 0;
954 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
956 Privileges
[i
].Attributes
= 0;
957 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
959 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
960 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
962 Privileges
[i
].Attributes
= 0;
963 Privileges
[i
++].Luid
= SeBackupPrivilege
;
965 Privileges
[i
].Attributes
= 0;
966 Privileges
[i
++].Luid
= SeRestorePrivilege
;
968 Privileges
[i
].Attributes
= 0;
969 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
971 Privileges
[i
].Attributes
= 0;
972 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
974 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
975 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
977 Privileges
[i
].Attributes
= 0;
978 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
981 /* Setup the object attributes */
982 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
983 ASSERT(SeSystemDefaultDacl
!= NULL
);
985 /* Create the token */
986 Status
= SepCreateToken((PHANDLE
)&Token
,
992 &SeSystemAuthenticationId
,
1002 SeSystemDefaultDacl
,
1003 &SeSystemTokenSource
,
1005 ASSERT(Status
== STATUS_SUCCESS
);
1007 /* Return the token */
1011 /* PUBLIC FUNCTIONS ***********************************************************/
1018 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
1020 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
1021 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
1022 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
1023 OUT PACCESS_TOKEN
* FilteredToken
)
1026 return STATUS_NOT_IMPLEMENTED
;
1034 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
1035 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1036 OUT PVOID
*TokenInformation
)
1039 return STATUS_NOT_IMPLEMENTED
;
1047 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
1048 IN PULONG pSessionId
)
1050 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1051 return STATUS_SUCCESS
;
1059 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1064 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
1066 return STATUS_SUCCESS
;
1073 SECURITY_IMPERSONATION_LEVEL
1075 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1079 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1087 SeTokenType(IN PACCESS_TOKEN Token
)
1091 return ((PTOKEN
)Token
)->TokenType
;
1100 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
1104 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
1112 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
1116 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
1124 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
1128 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
1131 /* SYSTEM CALLS ***************************************************************/
1137 NtQueryInformationToken(IN HANDLE TokenHandle
,
1138 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1139 OUT PVOID TokenInformation
,
1140 IN ULONG TokenInformationLength
,
1141 OUT PULONG ReturnLength
)
1149 ULONG RequiredLength
;
1150 KPROCESSOR_MODE PreviousMode
;
1155 PreviousMode
= ExGetPreviousMode();
1157 /* Check buffers and class validity */
1158 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1159 SeTokenInformationClass
,
1160 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1162 TokenInformationLength
,
1166 if (!NT_SUCCESS(Status
))
1168 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1172 Status
= ObReferenceObjectByHandle(TokenHandle
,
1173 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1178 if (NT_SUCCESS(Status
))
1180 switch (TokenInformationClass
)
1184 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1186 DPRINT("NtQueryInformationToken(TokenUser)\n");
1187 RequiredLength
= sizeof(TOKEN_USER
) +
1188 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1192 if (TokenInformationLength
>= RequiredLength
)
1194 Status
= RtlCopySidAndAttributesArray(1,
1195 &Token
->UserAndGroups
[0],
1196 RequiredLength
- sizeof(TOKEN_USER
),
1204 Status
= STATUS_BUFFER_TOO_SMALL
;
1207 if (ReturnLength
!= NULL
)
1209 *ReturnLength
= RequiredLength
;
1212 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1214 Status
= _SEH2_GetExceptionCode();
1223 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1225 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1226 RequiredLength
= sizeof(tg
->GroupCount
) +
1227 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1231 if (TokenInformationLength
>= RequiredLength
)
1233 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1234 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1235 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1236 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1238 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1239 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1240 &Token
->UserAndGroups
[1],
1249 Status
= STATUS_BUFFER_TOO_SMALL
;
1252 if (ReturnLength
!= NULL
)
1254 *ReturnLength
= RequiredLength
;
1257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1259 Status
= _SEH2_GetExceptionCode();
1266 case TokenPrivileges
:
1268 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1270 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1271 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1272 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1276 if (TokenInformationLength
>= RequiredLength
)
1278 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1279 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1281 &tp
->Privileges
[0]);
1285 Status
= STATUS_BUFFER_TOO_SMALL
;
1288 if (ReturnLength
!= NULL
)
1290 *ReturnLength
= RequiredLength
;
1293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1295 Status
= _SEH2_GetExceptionCode();
1305 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1307 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1308 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1309 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1313 if (TokenInformationLength
>= RequiredLength
)
1315 to
->Owner
= (PSID
)(to
+ 1);
1316 Status
= RtlCopySid(SidLen
,
1318 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1322 Status
= STATUS_BUFFER_TOO_SMALL
;
1325 if (ReturnLength
!= NULL
)
1327 *ReturnLength
= RequiredLength
;
1330 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1332 Status
= _SEH2_GetExceptionCode();
1339 case TokenPrimaryGroup
:
1342 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1344 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1345 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1346 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1350 if (TokenInformationLength
>= RequiredLength
)
1352 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1353 Status
= RtlCopySid(SidLen
,
1355 Token
->PrimaryGroup
);
1359 Status
= STATUS_BUFFER_TOO_SMALL
;
1362 if (ReturnLength
!= NULL
)
1364 *ReturnLength
= RequiredLength
;
1367 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1369 Status
= _SEH2_GetExceptionCode();
1376 case TokenDefaultDacl
:
1378 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1380 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1381 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1383 if (Token
->DefaultDacl
!= NULL
)
1385 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1390 if (TokenInformationLength
>= RequiredLength
)
1392 if (Token
->DefaultDacl
!= NULL
)
1394 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1395 RtlCopyMemory(tdd
->DefaultDacl
,
1397 Token
->DefaultDacl
->AclSize
);
1401 tdd
->DefaultDacl
= NULL
;
1406 Status
= STATUS_BUFFER_TOO_SMALL
;
1409 if (ReturnLength
!= NULL
)
1411 *ReturnLength
= RequiredLength
;
1414 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1416 Status
= _SEH2_GetExceptionCode();
1425 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1427 DPRINT("NtQueryInformationToken(TokenSource)\n");
1428 RequiredLength
= sizeof(TOKEN_SOURCE
);
1432 if (TokenInformationLength
>= RequiredLength
)
1434 *ts
= Token
->TokenSource
;
1438 Status
= STATUS_BUFFER_TOO_SMALL
;
1441 if (ReturnLength
!= NULL
)
1443 *ReturnLength
= RequiredLength
;
1446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1448 Status
= _SEH2_GetExceptionCode();
1457 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1459 DPRINT("NtQueryInformationToken(TokenType)\n");
1460 RequiredLength
= sizeof(TOKEN_TYPE
);
1464 if (TokenInformationLength
>= RequiredLength
)
1466 *tt
= Token
->TokenType
;
1470 Status
= STATUS_BUFFER_TOO_SMALL
;
1473 if (ReturnLength
!= NULL
)
1475 *ReturnLength
= RequiredLength
;
1478 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1480 Status
= _SEH2_GetExceptionCode();
1487 case TokenImpersonationLevel
:
1489 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1491 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1493 /* Fail if the token is not an impersonation token */
1494 if (Token
->TokenType
!= TokenImpersonation
)
1496 Status
= STATUS_INVALID_INFO_CLASS
;
1500 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1504 if (TokenInformationLength
>= RequiredLength
)
1506 *sil
= Token
->ImpersonationLevel
;
1510 Status
= STATUS_BUFFER_TOO_SMALL
;
1513 if (ReturnLength
!= NULL
)
1515 *ReturnLength
= RequiredLength
;
1518 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1520 Status
= _SEH2_GetExceptionCode();
1527 case TokenStatistics
:
1529 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1531 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1532 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1536 if (TokenInformationLength
>= RequiredLength
)
1538 ts
->TokenId
= Token
->TokenId
;
1539 ts
->AuthenticationId
= Token
->AuthenticationId
;
1540 ts
->ExpirationTime
= Token
->ExpirationTime
;
1541 ts
->TokenType
= Token
->TokenType
;
1542 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1543 ts
->DynamicCharged
= Token
->DynamicCharged
;
1544 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1545 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1546 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1547 ts
->ModifiedId
= Token
->ModifiedId
;
1551 Status
= STATUS_BUFFER_TOO_SMALL
;
1554 if (ReturnLength
!= NULL
)
1556 *ReturnLength
= RequiredLength
;
1559 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1561 Status
= _SEH2_GetExceptionCode();
1570 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1572 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1573 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1577 if (TokenInformationLength
>= RequiredLength
)
1579 RtlCopyLuid(&to
->OriginatingLogonSession
,
1580 &Token
->AuthenticationId
);
1584 Status
= STATUS_BUFFER_TOO_SMALL
;
1587 if (ReturnLength
!= NULL
)
1589 *ReturnLength
= RequiredLength
;
1592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1594 Status
= _SEH2_GetExceptionCode();
1601 case TokenGroupsAndPrivileges
:
1602 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1603 Status
= STATUS_NOT_IMPLEMENTED
;
1606 case TokenRestrictedSids
:
1608 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1610 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1611 RequiredLength
= sizeof(tg
->GroupCount
) +
1612 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1616 if (TokenInformationLength
>= RequiredLength
)
1618 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1619 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1620 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1621 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1623 tg
->GroupCount
= Token
->RestrictedSidCount
;
1624 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1625 Token
->RestrictedSids
,
1634 Status
= STATUS_BUFFER_TOO_SMALL
;
1637 if (ReturnLength
!= NULL
)
1639 *ReturnLength
= RequiredLength
;
1642 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1644 Status
= _SEH2_GetExceptionCode();
1651 case TokenSandBoxInert
:
1652 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1653 Status
= STATUS_NOT_IMPLEMENTED
;
1656 case TokenSessionId
:
1658 ULONG SessionId
= 0;
1660 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1662 Status
= SeQuerySessionIdToken(Token
,
1665 if (NT_SUCCESS(Status
))
1669 /* buffer size was already verified, no need to check here again */
1670 *(PULONG
)TokenInformation
= SessionId
;
1672 if (ReturnLength
!= NULL
)
1674 *ReturnLength
= sizeof(ULONG
);
1677 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1679 Status
= _SEH2_GetExceptionCode();
1688 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1689 Status
= STATUS_INVALID_INFO_CLASS
;
1693 ObDereferenceObject(Token
);
1701 * NtSetTokenInformation: Partly implemented.
1703 * TokenOrigin, TokenDefaultDacl
1707 NtSetInformationToken(IN HANDLE TokenHandle
,
1708 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1709 OUT PVOID TokenInformation
,
1710 IN ULONG TokenInformationLength
)
1713 KPROCESSOR_MODE PreviousMode
;
1714 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1719 PreviousMode
= ExGetPreviousMode();
1721 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1722 SeTokenInformationClass
,
1723 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1725 TokenInformationLength
,
1727 if (!NT_SUCCESS(Status
))
1729 /* Invalid buffers */
1730 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1734 if (TokenInformationClass
== TokenSessionId
)
1736 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1739 Status
= ObReferenceObjectByHandle(TokenHandle
,
1745 if (NT_SUCCESS(Status
))
1747 switch (TokenInformationClass
)
1751 if (TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1753 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1754 PSID InputSid
= NULL
, CapturedSid
;
1758 InputSid
= to
->Owner
;
1760 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1762 Status
= _SEH2_GetExceptionCode();
1767 Status
= SepCaptureSid(InputSid
,
1772 if (NT_SUCCESS(Status
))
1774 RtlCopySid(RtlLengthSid(CapturedSid
),
1775 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1777 SepReleaseSid(CapturedSid
,
1784 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1789 case TokenPrimaryGroup
:
1791 if (TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1793 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1794 PSID InputSid
= NULL
, CapturedSid
;
1798 InputSid
= tpg
->PrimaryGroup
;
1800 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1802 Status
= _SEH2_GetExceptionCode();
1807 Status
= SepCaptureSid(InputSid
,
1812 if (NT_SUCCESS(Status
))
1814 RtlCopySid(RtlLengthSid(CapturedSid
),
1815 Token
->PrimaryGroup
,
1817 SepReleaseSid(CapturedSid
,
1824 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1829 case TokenDefaultDacl
:
1831 if (TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1833 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1834 PACL InputAcl
= NULL
;
1838 InputAcl
= tdd
->DefaultDacl
;
1840 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1842 Status
= _SEH2_GetExceptionCode();
1847 if (InputAcl
!= NULL
)
1851 /* Capture and copy the dacl */
1852 Status
= SepCaptureAcl(InputAcl
,
1857 if (NT_SUCCESS(Status
))
1859 /* Free the previous dacl if present */
1860 if(Token
->DefaultDacl
!= NULL
)
1862 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
1865 /* Set the new dacl */
1866 Token
->DefaultDacl
= CapturedAcl
;
1871 /* Clear and free the default dacl if present */
1872 if (Token
->DefaultDacl
!= NULL
)
1874 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
1875 Token
->DefaultDacl
= NULL
;
1881 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1886 case TokenSessionId
:
1888 ULONG SessionId
= 0;
1892 /* Buffer size was already verified, no need to check here again */
1893 SessionId
= *(PULONG
)TokenInformation
;
1895 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1897 Status
= _SEH2_GetExceptionCode();
1902 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1905 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1909 Token
->SessionId
= SessionId
;
1913 case TokenSessionReference
:
1915 ULONG SessionReference
;
1919 /* Buffer size was already verified, no need to check here again */
1920 SessionReference
= *(PULONG
)TokenInformation
;
1922 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1924 Status
= _SEH2_GetExceptionCode();
1929 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1931 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1935 /* Check if it is 0 */
1936 if (SessionReference
== 0)
1938 /* Atomically set the flag in the token */
1939 RtlInterlockedSetBits(&Token
->TokenFlags
,
1940 TOKEN_SESSION_NOT_REFERENCED
);
1949 DPRINT1("Unhandled TokenInformationClass: 0x%lx\n",
1950 TokenInformationClass
);
1951 Status
= STATUS_NOT_IMPLEMENTED
;
1956 ObDereferenceObject(Token
);
1966 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1967 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1968 * is correct either. -Gunnar
1969 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1972 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1973 IN ACCESS_MASK DesiredAccess
,
1974 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1975 IN BOOLEAN EffectiveOnly
,
1976 IN TOKEN_TYPE TokenType
,
1977 OUT PHANDLE NewTokenHandle
)
1979 KPROCESSOR_MODE PreviousMode
;
1983 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1985 OBJECT_HANDLE_INFORMATION HandleInformation
;
1990 if (TokenType
!= TokenImpersonation
&&
1991 TokenType
!= TokenPrimary
)
1992 return STATUS_INVALID_PARAMETER
;
1994 PreviousMode
= KeGetPreviousMode();
1996 if (PreviousMode
!= KernelMode
)
2000 ProbeForWriteHandle(NewTokenHandle
);
2002 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2004 /* Return the exception code */
2005 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2010 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
2014 &CapturedSecurityQualityOfService
,
2016 if (!NT_SUCCESS(Status
))
2018 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
2022 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
2027 &HandleInformation
);
2028 if (!NT_SUCCESS(Status
))
2030 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2037 * Fail, if the original token is an impersonation token and the caller
2038 * tries to raise the impersonation level of the new token above the
2039 * impersonation level of the original token.
2041 if (Token
->TokenType
== TokenImpersonation
)
2044 CapturedSecurityQualityOfService
->ImpersonationLevel
>Token
->ImpersonationLevel
)
2046 ObDereferenceObject(Token
);
2047 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2050 return STATUS_BAD_IMPERSONATION_LEVEL
;
2055 * Fail, if a primary token is to be created from an impersonation token
2056 * and and the impersonation level of the impersonation token is below SecurityImpersonation.
2058 if (Token
->TokenType
== TokenImpersonation
&&
2059 TokenType
== TokenPrimary
&&
2060 Token
->ImpersonationLevel
< SecurityImpersonation
)
2062 ObDereferenceObject(Token
);
2063 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2066 return STATUS_BAD_IMPERSONATION_LEVEL
;
2069 Status
= SepDuplicateToken(Token
,
2073 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
2077 ObDereferenceObject(Token
);
2079 if (NT_SUCCESS(Status
))
2081 Status
= ObInsertObject((PVOID
)NewToken
,
2083 (DesiredAccess
? DesiredAccess
: HandleInformation
.GrantedAccess
),
2087 if (NT_SUCCESS(Status
))
2091 *NewTokenHandle
= hToken
;
2093 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2095 Status
= _SEH2_GetExceptionCode();
2101 /* Free the captured structure */
2102 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2110 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
2111 IN BOOLEAN ResetToDefault
,
2112 IN PTOKEN_GROUPS NewState
,
2113 IN ULONG BufferLength
,
2114 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
2115 OUT PULONG ReturnLength
)
2118 return(STATUS_NOT_IMPLEMENTED
);
2124 SepAdjustPrivileges(
2125 _Inout_ PTOKEN Token
,
2126 _In_ BOOLEAN DisableAllPrivileges
,
2127 _In_opt_ PLUID_AND_ATTRIBUTES NewState
,
2128 _In_ ULONG NewStateCount
,
2129 _Out_opt_ PTOKEN_PRIVILEGES PreviousState
,
2130 _In_ BOOLEAN ApplyChanges
,
2131 _Out_ PULONG ChangedPrivileges
)
2133 ULONG i
, j
, PrivilegeCount
, ChangeCount
, NewAttributes
;
2135 /* Count the found privileges and those that need to be changed */
2139 /* Loop all privileges in the token */
2140 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2142 /* Shall all of them be disabled? */
2143 if (DisableAllPrivileges
)
2145 /* The new attributes are the old ones, but disabled */
2146 NewAttributes
= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2150 /* Otherwise loop all provided privileges */
2151 for (j
= 0; j
< NewStateCount
; j
++)
2153 /* Check if this is the LUID we are looking for */
2154 if (RtlEqualLuid(&Token
->Privileges
[i
].Luid
, &NewState
[j
].Luid
))
2156 DPRINT("Found privilege\n");
2158 /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
2159 NewAttributes
= NewState
[j
].Attributes
;
2160 NewAttributes
&= (SE_PRIVILEGE_ENABLED
| SE_PRIVILEGE_REMOVED
);
2161 NewAttributes
|= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2168 /* Check if we didn't find the privilege */
2169 if (j
== NewStateCount
)
2171 /* Continue with the token's next privilege */
2176 /* We found a privilege, count it */
2179 /* Does the privilege need to be changed? */
2180 if (Token
->Privileges
[i
].Attributes
!= NewAttributes
)
2182 /* Does the caller want the old privileges? */
2183 if (PreviousState
!= NULL
)
2185 /* Copy the old privilege */
2186 PreviousState
->Privileges
[ChangeCount
] = Token
->Privileges
[i
];
2189 /* Does the caller want to apply the changes? */
2192 /* Shall we remove the privilege? */
2193 if (NewAttributes
& SE_PRIVILEGE_REMOVED
)
2195 /* Set the token as disabled and update flags for it */
2196 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2197 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2199 /* Remove the privilege */
2200 SepRemovePrivilegeToken(Token
, i
);
2202 /* Fix the running index */
2205 /* Continue with next */
2209 /* Set the new attributes and update flags */
2210 Token
->Privileges
[i
].Attributes
= NewAttributes
;
2211 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2214 /* Increment the change count */
2219 /* Set the number of saved privileges */
2220 if (PreviousState
!= NULL
)
2221 PreviousState
->PrivilegeCount
= ChangeCount
;
2223 /* Return the number of changed privileges */
2224 *ChangedPrivileges
= ChangeCount
;
2226 /* Check if we missed some */
2227 if (!DisableAllPrivileges
&& (PrivilegeCount
< NewStateCount
))
2229 return STATUS_NOT_ALL_ASSIGNED
;
2232 return STATUS_SUCCESS
;
2239 _Must_inspect_result_
2243 NtAdjustPrivilegesToken(
2244 _In_ HANDLE TokenHandle
,
2245 _In_ BOOLEAN DisableAllPrivileges
,
2246 _In_opt_ PTOKEN_PRIVILEGES NewState
,
2247 _In_ ULONG BufferLength
,
2248 _Out_writes_bytes_to_opt_(BufferLength
,*ReturnLength
)
2249 PTOKEN_PRIVILEGES PreviousState
,
2250 _When_(PreviousState
!=NULL
, _Out_
) PULONG ReturnLength
)
2252 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2253 KPROCESSOR_MODE PreviousMode
;
2254 ULONG CapturedCount
= 0;
2255 ULONG CapturedLength
= 0;
2256 ULONG NewStateSize
= 0;
2258 ULONG RequiredLength
;
2263 DPRINT("NtAdjustPrivilegesToken() called\n");
2265 /* Fail, if we do not disable all privileges but NewState is NULL */
2266 if (DisableAllPrivileges
== FALSE
&& NewState
== NULL
)
2267 return STATUS_INVALID_PARAMETER
;
2269 PreviousMode
= KeGetPreviousMode ();
2270 if (PreviousMode
!= KernelMode
)
2274 /* Probe NewState */
2275 if (DisableAllPrivileges
== FALSE
)
2277 /* First probe the header */
2278 ProbeForRead(NewState
, sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
));
2280 CapturedCount
= NewState
->PrivilegeCount
;
2281 NewStateSize
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[CapturedCount
]);
2283 ProbeForRead(NewState
, NewStateSize
, sizeof(ULONG
));
2286 /* Probe PreviousState and ReturnLength */
2287 if (PreviousState
!= NULL
)
2289 ProbeForWrite(PreviousState
, BufferLength
, sizeof(ULONG
));
2290 ProbeForWrite(ReturnLength
, sizeof(ULONG
), sizeof(ULONG
));
2293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2295 /* Return the exception code */
2296 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2302 /* This is kernel mode, we trust the caller */
2303 if (DisableAllPrivileges
== FALSE
)
2304 CapturedCount
= NewState
->PrivilegeCount
;
2307 /* Do we need to capture the new state? */
2308 if (DisableAllPrivileges
== FALSE
)
2312 /* Capture the new state array of privileges */
2313 Status
= SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
2320 &CapturedPrivileges
,
2323 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2325 /* Return the exception code */
2326 Status
= _SEH2_GetExceptionCode();
2330 if (!NT_SUCCESS(Status
))
2334 /* Reference the token */
2335 Status
= ObReferenceObjectByHandle(TokenHandle
,
2336 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
2341 if (!NT_SUCCESS(Status
))
2343 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
2345 /* Release the captured privileges */
2346 if (CapturedPrivileges
!= NULL
)
2347 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2354 /* Lock the token */
2355 ExEnterCriticalRegionAndAcquireResourceExclusive(Token
->TokenLock
);
2357 /* Count the privileges that need to be changed, do not apply them yet */
2358 Status
= SepAdjustPrivileges(Token
,
2359 DisableAllPrivileges
,
2366 /* Check if the caller asked for the previous state */
2367 if (PreviousState
!= NULL
)
2369 /* Calculate the required length */
2370 RequiredLength
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[ChangeCount
]);
2372 /* Try to return the required buffer length */
2375 *ReturnLength
= RequiredLength
;
2377 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2379 /* Do cleanup and return the exception code */
2380 Status
= _SEH2_GetExceptionCode();
2385 /* Fail, if the buffer length is smaller than the required length */
2386 if (BufferLength
< RequiredLength
)
2388 Status
= STATUS_BUFFER_TOO_SMALL
;
2393 /* Now enter SEH, since we might return the old privileges */
2396 /* This time apply the changes */
2397 Status
= SepAdjustPrivileges(Token
,
2398 DisableAllPrivileges
,
2405 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2407 /* Do cleanup and return the exception code */
2408 Status
= _SEH2_GetExceptionCode();
2414 /* Unlock and dereference the token */
2415 ExReleaseResourceAndLeaveCriticalRegion(Token
->TokenLock
);
2416 ObDereferenceObject(Token
);
2418 /* Release the captured privileges */
2419 if (CapturedPrivileges
!= NULL
)
2420 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2424 DPRINT ("NtAdjustPrivilegesToken() done\n");
2431 _Out_ PHANDLE TokenHandle
,
2432 _In_ ACCESS_MASK DesiredAccess
,
2433 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
,
2434 _In_ TOKEN_TYPE TokenType
,
2435 _In_ PLUID AuthenticationId
,
2436 _In_ PLARGE_INTEGER ExpirationTime
,
2437 _In_ PTOKEN_USER TokenUser
,
2438 _In_ PTOKEN_GROUPS TokenGroups
,
2439 _In_ PTOKEN_PRIVILEGES TokenPrivileges
,
2440 _In_opt_ PTOKEN_OWNER TokenOwner
,
2441 _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2442 _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2443 _In_ PTOKEN_SOURCE TokenSource
)
2446 KPROCESSOR_MODE PreviousMode
;
2447 ULONG PrivilegeCount
, GroupCount
;
2448 PSID OwnerSid
, PrimaryGroupSid
;
2450 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
2451 LUID LocalAuthenticationId
;
2452 TOKEN_SOURCE LocalTokenSource
;
2453 SECURITY_QUALITY_OF_SERVICE LocalSecurityQos
;
2454 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2455 PSID_AND_ATTRIBUTES CapturedUser
= NULL
;
2456 PSID_AND_ATTRIBUTES CapturedGroups
= NULL
;
2457 PSID CapturedOwnerSid
= NULL
;
2458 PSID CapturedPrimaryGroupSid
= NULL
;
2459 PACL CapturedDefaultDacl
= NULL
;
2460 ULONG PrivilegesLength
, UserLength
, GroupsLength
;
2465 PreviousMode
= ExGetPreviousMode();
2467 if (PreviousMode
!= KernelMode
)
2471 ProbeForWriteHandle(TokenHandle
);
2473 if (ObjectAttributes
!= NULL
)
2475 ProbeForRead(ObjectAttributes
,
2476 sizeof(OBJECT_ATTRIBUTES
),
2478 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
2481 ProbeForRead(AuthenticationId
,
2484 LocalAuthenticationId
= *AuthenticationId
;
2486 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2488 ProbeForRead(TokenUser
,
2492 ProbeForRead(TokenGroups
,
2493 sizeof(TOKEN_GROUPS
),
2495 GroupCount
= TokenGroups
->GroupCount
;
2497 ProbeForRead(TokenPrivileges
,
2498 sizeof(TOKEN_PRIVILEGES
),
2500 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2502 if (TokenOwner
!= NULL
)
2504 ProbeForRead(TokenOwner
,
2505 sizeof(TOKEN_OWNER
),
2507 OwnerSid
= TokenOwner
->Owner
;
2514 ProbeForRead(TokenPrimaryGroup
,
2515 sizeof(TOKEN_PRIMARY_GROUP
),
2517 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
2519 if (TokenDefaultDacl
!= NULL
)
2521 ProbeForRead(TokenDefaultDacl
,
2522 sizeof(TOKEN_DEFAULT_DACL
),
2524 DefaultDacl
= TokenDefaultDacl
->DefaultDacl
;
2531 ProbeForRead(TokenSource
,
2532 sizeof(TOKEN_SOURCE
),
2534 LocalTokenSource
= *TokenSource
;
2536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2538 /* Return the exception code */
2539 return _SEH2_GetExceptionCode();
2545 if (ObjectAttributes
!= NULL
)
2546 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
2547 LocalAuthenticationId
= *AuthenticationId
;
2548 LocalExpirationTime
= *ExpirationTime
;
2549 GroupCount
= TokenGroups
->GroupCount
;
2550 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2551 OwnerSid
= TokenOwner
? TokenOwner
->Owner
: NULL
;
2552 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
2553 DefaultDacl
= TokenDefaultDacl
? TokenDefaultDacl
->DefaultDacl
: NULL
;
2554 LocalTokenSource
= *TokenSource
;
2557 /* Check token type */
2558 if ((TokenType
< TokenPrimary
) ||
2559 (TokenType
> TokenImpersonation
))
2561 return STATUS_BAD_TOKEN_TYPE
;
2564 /* Capture the user SID and attributes */
2565 Status
= SeCaptureSidAndAttributesArray(&TokenUser
->User
,
2574 if (!NT_SUCCESS(Status
))
2579 /* Capture the groups SID and attributes array */
2580 Status
= SeCaptureSidAndAttributesArray(&TokenGroups
->Groups
[0],
2589 if (!NT_SUCCESS(Status
))
2594 /* Capture privileges */
2595 Status
= SeCaptureLuidAndAttributesArray(&TokenPrivileges
->Privileges
[0],
2602 &CapturedPrivileges
,
2604 if (!NT_SUCCESS(Status
))
2609 /* Capture the token owner SID */
2610 if (TokenOwner
!= NULL
)
2612 Status
= SepCaptureSid(OwnerSid
,
2617 if (!NT_SUCCESS(Status
))
2623 /* Capture the token primary group SID */
2624 Status
= SepCaptureSid(PrimaryGroupSid
,
2628 &CapturedPrimaryGroupSid
);
2629 if (!NT_SUCCESS(Status
))
2634 /* Capture DefaultDacl */
2635 if (DefaultDacl
!= NULL
)
2637 Status
= SepCaptureAcl(DefaultDacl
,
2641 &CapturedDefaultDacl
);
2644 /* Call the internal function */
2645 Status
= SepCreateToken(&hToken
,
2650 LocalSecurityQos
.ImpersonationLevel
,
2651 &LocalAuthenticationId
,
2652 &LocalExpirationTime
,
2656 0, // FIXME: Should capture
2660 CapturedPrimaryGroupSid
,
2661 CapturedDefaultDacl
,
2664 if (NT_SUCCESS(Status
))
2668 *TokenHandle
= hToken
;
2670 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2672 Status
= _SEH2_GetExceptionCode();
2679 /* Release what we captured */
2680 SeReleaseSidAndAttributesArray(CapturedUser
, PreviousMode
, FALSE
);
2681 SeReleaseSidAndAttributesArray(CapturedGroups
, PreviousMode
, FALSE
);
2682 SeReleaseLuidAndAttributesArray(CapturedPrivileges
, PreviousMode
, FALSE
);
2683 SepReleaseSid(CapturedOwnerSid
, PreviousMode
, FALSE
);
2684 SepReleaseSid(CapturedPrimaryGroupSid
, PreviousMode
, FALSE
);
2685 SepReleaseAcl(CapturedDefaultDacl
, PreviousMode
, FALSE
);
2695 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2696 IN ACCESS_MASK DesiredAccess
,
2697 IN BOOLEAN OpenAsSelf
,
2698 IN ULONG HandleAttributes
,
2699 OUT PHANDLE TokenHandle
)
2701 PETHREAD Thread
, NewThread
;
2703 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
2704 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2705 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2706 SE_IMPERSONATION_STATE ImpersonationState
;
2707 OBJECT_ATTRIBUTES ObjectAttributes
;
2708 SECURITY_DESCRIPTOR SecurityDescriptor
;
2710 KPROCESSOR_MODE PreviousMode
;
2712 BOOLEAN RestoreImpersonation
= FALSE
;
2716 PreviousMode
= ExGetPreviousMode();
2718 if (PreviousMode
!= KernelMode
)
2722 ProbeForWriteHandle(TokenHandle
);
2724 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2726 /* Return the exception code */
2727 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2733 * At first open the thread token for information access and verify
2734 * that the token associated with thread is valid.
2737 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2738 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2740 if (!NT_SUCCESS(Status
))
2745 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2746 &ImpersonationLevel
);
2749 ObDereferenceObject(Thread
);
2750 return STATUS_NO_TOKEN
;
2753 if (ImpersonationLevel
== SecurityAnonymous
)
2755 PsDereferenceImpersonationToken(Token
);
2756 ObDereferenceObject(Thread
);
2757 return STATUS_CANT_OPEN_ANONYMOUS
;
2761 * Revert to self if OpenAsSelf is specified.
2766 RestoreImpersonation
= PsDisableImpersonation(PsGetCurrentThread(),
2767 &ImpersonationState
);
2772 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2773 PsThreadType
, KernelMode
,
2774 (PVOID
*)&NewThread
, NULL
);
2775 if (NT_SUCCESS(Status
))
2777 PrimaryToken
= PsReferencePrimaryToken(NewThread
->ThreadsProcess
);
2779 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2781 ObFastDereferenceObject(&NewThread
->ThreadsProcess
->Token
, PrimaryToken
);
2783 if (NT_SUCCESS(Status
))
2787 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2788 SECURITY_DESCRIPTOR_REVISION
);
2789 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2793 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2794 NULL
, Dacl
? &SecurityDescriptor
: NULL
);
2797 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2798 TokenImpersonation
, ImpersonationLevel
,
2799 KernelMode
, &NewToken
);
2800 if (NT_SUCCESS(Status
))
2802 ObReferenceObject(NewToken
);
2803 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2811 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2812 NULL
, DesiredAccess
, SeTokenObjectType
,
2813 PreviousMode
, &hToken
);
2816 if (Dacl
) ExFreePoolWithTag(Dacl
, TAG_TOKEN_ACL
);
2818 if (RestoreImpersonation
)
2820 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2823 ObDereferenceObject(Token
);
2825 if (NT_SUCCESS(Status
) && CopyOnOpen
)
2827 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
2830 if (NewToken
) ObDereferenceObject(NewToken
);
2832 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
2834 if (NT_SUCCESS(Status
))
2838 *TokenHandle
= hToken
;
2840 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2842 Status
= _SEH2_GetExceptionCode();
2854 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2855 IN ACCESS_MASK DesiredAccess
,
2856 IN BOOLEAN OpenAsSelf
,
2857 OUT PHANDLE TokenHandle
)
2859 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2870 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2871 IN HANDLE SecondTokenHandle
,
2874 KPROCESSOR_MODE PreviousMode
;
2875 PTOKEN FirstToken
, SecondToken
;
2881 PreviousMode
= ExGetPreviousMode();
2883 if (PreviousMode
!= KernelMode
)
2887 ProbeForWriteBoolean(Equal
);
2889 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2891 /* Return the exception code */
2892 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2897 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2901 (PVOID
*)&FirstToken
,
2903 if (!NT_SUCCESS(Status
))
2906 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2910 (PVOID
*)&SecondToken
,
2912 if (!NT_SUCCESS(Status
))
2914 ObDereferenceObject(FirstToken
);
2918 if (FirstToken
!= SecondToken
)
2920 Status
= SepCompareTokens(FirstToken
,
2927 ObDereferenceObject(FirstToken
);
2928 ObDereferenceObject(SecondToken
);
2930 if (NT_SUCCESS(Status
))
2936 _SEH2_EXCEPT(ExSystemExceptionFilter())
2938 Status
= _SEH2_GetExceptionCode();
2948 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2950 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2951 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2952 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2953 OUT PHANDLE NewTokenHandle
)
2956 return STATUS_NOT_IMPLEMENTED
;
2964 NtImpersonateAnonymousToken(IN HANDLE Thread
)
2967 return STATUS_NOT_IMPLEMENTED
;