2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/token.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
10 /* INCLUDES *******************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitializeTokenImplementation)
22 typedef struct _TOKEN_AUDIT_POLICY_INFORMATION
30 } TOKEN_AUDIT_POLICY_INFORMATION
, *PTOKEN_AUDIT_POLICY_INFORMATION
;
32 /* GLOBALS ********************************************************************/
34 POBJECT_TYPE SeTokenObjectType
= NULL
;
35 ERESOURCE SepTokenLock
;
37 TOKEN_SOURCE SeSystemTokenSource
= {"*SYSTEM*", {0}};
38 LUID SeSystemAuthenticationId
= SYSTEM_LUID
;
39 LUID SeAnonymousAuthenticationId
= ANONYMOUS_LOGON_LUID
;
41 static GENERIC_MAPPING SepTokenMapping
= {
48 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
50 /* Class 0 not used, blame M$! */
51 ICI_SQ_SAME( 0, 0, 0),
54 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
56 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
58 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
60 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
61 /* TokenPrimaryGroup */
62 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
63 /* TokenDefaultDacl */
64 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
66 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
68 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
69 /* TokenImpersonationLevel */
70 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
72 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET_SIZE_VARIABLE
),
73 /* TokenRestrictedSids */
74 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
76 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
77 /* TokenGroupsAndPrivileges */
78 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
79 /* TokenSessionReference */
80 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_SET
| ICIF_QUERY_SIZE_VARIABLE
),
81 /* TokenSandBoxInert */
82 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
83 /* TokenAuditPolicy */
84 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
| ICIF_QUERY_SIZE_VARIABLE
),
86 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
| ICIF_QUERY_SIZE_VARIABLE
),
89 /* FUNCTIONS *****************************************************************/
92 SepCompareTokens(IN PTOKEN FirstToken
,
93 IN PTOKEN SecondToken
,
96 BOOLEAN Restricted
, IsEqual
= FALSE
;
98 ASSERT(FirstToken
!= SecondToken
);
100 /* FIXME: Check if every SID that is present in either token is also present in the other one */
102 Restricted
= SeTokenIsRestricted(FirstToken
);
103 if (Restricted
== SeTokenIsRestricted(SecondToken
))
107 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
110 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
111 DPRINT1("FIXME: Pretending tokens are equal!\n");
116 return STATUS_SUCCESS
;
121 SepUpdateSinglePrivilegeFlagToken(
122 _Inout_ PTOKEN Token
,
126 NT_ASSERT(Index
< Token
->PrivilegeCount
);
128 /* The high part of all values we are interested in is 0 */
129 if (Token
->Privileges
[Index
].Luid
.HighPart
!= 0)
134 /* Check for certain privileges to update flags */
135 if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_CHANGE_NOTIFY_PRIVILEGE
)
137 TokenFlag
= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
139 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_BACKUP_PRIVILEGE
)
141 TokenFlag
= TOKEN_HAS_BACKUP_PRIVILEGE
;
143 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_RESTORE_PRIVILEGE
)
145 TokenFlag
= TOKEN_HAS_RESTORE_PRIVILEGE
;
147 else if (Token
->Privileges
[Index
].Luid
.LowPart
== SE_IMPERSONATE_PRIVILEGE
)
149 TokenFlag
= TOKEN_HAS_IMPERSONATE_PRIVILEGE
;
157 /* Check if the specified privilege is enabled */
158 if (Token
->Privileges
[Index
].Attributes
& SE_PRIVILEGE_ENABLED
)
160 /* It is enabled, so set the flag */
161 Token
->TokenFlags
|= TokenFlag
;
165 /* Is is disabled, so remove the flag */
166 Token
->TokenFlags
&= ~TokenFlag
;
172 SepUpdatePrivilegeFlagsToken(
173 _Inout_ PTOKEN Token
)
177 /* Loop all privileges */
178 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
180 /* Updates the flags dor this privilege */
181 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
187 SepRemovePrivilegeToken(
188 _Inout_ PTOKEN Token
,
192 NT_ASSERT(Index
< Token
->PrivilegeCount
);
194 /* Calculate the number of trailing privileges */
195 MoveCount
= Token
->PrivilegeCount
- Index
- 1;
198 /* Move them one location ahead */
199 RtlMoveMemory(&Token
->Privileges
[Index
],
200 &Token
->Privileges
[Index
+ 1],
201 MoveCount
* sizeof(LUID_AND_ATTRIBUTES
));
204 /* Update privilege count */
205 Token
->PrivilegeCount
--;
210 SepFreeProxyData(PVOID ProxyData
)
217 SepCopyProxyData(PVOID
* Dest
,
221 return STATUS_NOT_IMPLEMENTED
;
226 SeExchangePrimaryToken(PEPROCESS Process
,
227 PACCESS_TOKEN NewTokenP
,
228 PACCESS_TOKEN
* OldTokenP
)
231 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
235 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
236 if (NewToken
->TokenInUse
)
241 /* Maybe we're trying to set the same token */
242 OldToken
= PsReferencePrimaryToken(Process
);
243 if (OldToken
== NewToken
)
246 *OldTokenP
= OldToken
;
247 return STATUS_SUCCESS
;
250 Status
= SepCompareTokens(OldToken
, NewToken
, &IsEqual
);
251 if (!NT_SUCCESS(Status
))
254 PsDereferencePrimaryToken(OldToken
);
261 PsDereferencePrimaryToken(OldToken
);
262 return STATUS_TOKEN_ALREADY_IN_USE
;
264 /* Silently return STATUS_SUCCESS but do not set the new token,
265 * as it's already in use elsewhere. */
266 *OldTokenP
= OldToken
;
267 return STATUS_SUCCESS
;
270 /* Mark new token in use */
271 NewToken
->TokenInUse
= 1;
273 /* Reference the New Token */
274 ObReferenceObject(NewToken
);
276 /* Replace the old with the new */
277 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
279 /* Mark the Old Token as free */
280 OldToken
->TokenInUse
= 0;
282 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
283 return STATUS_SUCCESS
;
288 SeDeassignPrimaryToken(PEPROCESS Process
)
292 /* Remove the Token */
293 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
295 /* Mark the Old Token as free */
296 OldToken
->TokenInUse
= 0;
300 RtlLengthSidAndAttributes(ULONG Count
,
301 PSID_AND_ATTRIBUTES Src
)
308 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
309 for (i
= 0; i
< Count
; i
++)
310 uLength
+= RtlLengthSid(Src
[i
].Sid
);
318 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
324 Token
->PrimaryGroup
= 0;
328 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
331 /* Validate and set the primary group and user pointers */
332 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
335 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
337 Token
->DefaultOwnerIndex
= i
;
340 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
342 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
346 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
348 return(STATUS_INVALID_OWNER
);
351 if (Token
->PrimaryGroup
== 0)
353 return(STATUS_INVALID_PRIMARY_GROUP
);
356 return STATUS_SUCCESS
;
362 SepDuplicateToken(PTOKEN Token
,
363 POBJECT_ATTRIBUTES ObjectAttributes
,
364 BOOLEAN EffectiveOnly
,
365 TOKEN_TYPE TokenType
,
366 SECURITY_IMPERSONATION_LEVEL Level
,
367 KPROCESSOR_MODE PreviousMode
,
368 PTOKEN
* NewAccessToken
)
373 PTOKEN AccessToken
= NULL
;
378 Status
= ObCreateObject(PreviousMode
,
386 (PVOID
*)&AccessToken
);
387 if (!NT_SUCCESS(Status
))
389 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
393 /* Zero out the buffer */
394 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
396 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
397 if (!NT_SUCCESS(Status
))
399 ObDereferenceObject(AccessToken
);
403 AccessToken
->TokenLock
= &SepTokenLock
;
405 AccessToken
->TokenType
= TokenType
;
406 AccessToken
->ImpersonationLevel
= Level
;
407 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
408 RtlCopyLuid(&AccessToken
->ModifiedId
, &Token
->ModifiedId
);
410 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
411 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
412 memcpy(AccessToken
->TokenSource
.SourceName
,
413 Token
->TokenSource
.SourceName
,
414 sizeof(Token
->TokenSource
.SourceName
));
415 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
416 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
417 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
419 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
420 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
421 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
423 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
426 if (AccessToken
->UserAndGroups
== NULL
)
428 Status
= STATUS_INSUFFICIENT_RESOURCES
;
432 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
434 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
435 Token
->UserAndGroups
,
437 AccessToken
->UserAndGroups
,
441 if (!NT_SUCCESS(Status
))
444 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
447 if (!NT_SUCCESS(Status
))
450 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
452 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
453 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
455 TAG_TOKEN_PRIVILAGES
);
456 if (AccessToken
->Privileges
== NULL
)
458 Status
= STATUS_INSUFFICIENT_RESOURCES
;
462 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
464 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
465 &Token
->Privileges
[i
].Luid
);
466 AccessToken
->Privileges
[i
].Attributes
=
467 Token
->Privileges
[i
].Attributes
;
470 if (Token
->DefaultDacl
)
472 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
473 Token
->DefaultDacl
->AclSize
,
475 if (AccessToken
->DefaultDacl
== NULL
)
477 Status
= STATUS_INSUFFICIENT_RESOURCES
;
481 memcpy(AccessToken
->DefaultDacl
,
483 Token
->DefaultDacl
->AclSize
);
486 *NewAccessToken
= AccessToken
;
489 if (!NT_SUCCESS(Status
))
493 if (AccessToken
->UserAndGroups
)
494 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
496 if (AccessToken
->Privileges
)
497 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
499 if (AccessToken
->DefaultDacl
)
500 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
502 ObDereferenceObject(AccessToken
);
511 SeSubProcessToken(IN PTOKEN ParentToken
,
517 OBJECT_ATTRIBUTES ObjectAttributes
;
520 /* Initialize the attributes and duplicate it */
521 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
522 Status
= SepDuplicateToken(ParentToken
,
526 ParentToken
->ImpersonationLevel
,
529 if (NT_SUCCESS(Status
))
532 Status
= ObInsertObject(NewToken
,
538 if (NT_SUCCESS(Status
))
540 /* Set the session ID */
541 NewToken
->SessionId
= SessionId
;
542 NewToken
->TokenInUse
= InUse
;
544 /* Return the token */
555 SeIsTokenChild(IN PTOKEN Token
,
556 OUT PBOOLEAN IsChild
)
559 LUID ProcessLuid
, CallerLuid
;
564 /* Reference the process token */
565 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
568 ProcessLuid
= ProcessToken
->AuthenticationId
;
570 /* Dereference the token */
571 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
574 CallerLuid
= Token
->AuthenticationId
;
576 /* Compare the LUIDs */
577 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
580 return STATUS_SUCCESS
;
585 SeCopyClientToken(IN PACCESS_TOKEN Token
,
586 IN SECURITY_IMPERSONATION_LEVEL Level
,
587 IN KPROCESSOR_MODE PreviousMode
,
588 OUT PACCESS_TOKEN
* NewToken
)
591 OBJECT_ATTRIBUTES ObjectAttributes
;
595 InitializeObjectAttributes(&ObjectAttributes
,
600 Status
= SepDuplicateToken(Token
,
613 SepDeleteToken(PVOID ObjectBody
)
615 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
617 if (AccessToken
->UserAndGroups
)
618 ExFreePoolWithTag(AccessToken
->UserAndGroups
, TAG_TOKEN_USERS
);
620 if (AccessToken
->Privileges
)
621 ExFreePoolWithTag(AccessToken
->Privileges
, TAG_TOKEN_PRIVILAGES
);
623 if (AccessToken
->DefaultDacl
)
624 ExFreePoolWithTag(AccessToken
->DefaultDacl
, TAG_TOKEN_ACL
);
631 SepInitializeTokenImplementation(VOID
)
634 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
636 ExInitializeResource(&SepTokenLock
);
638 DPRINT("Creating Token Object Type\n");
640 /* Initialize the Token type */
641 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
642 RtlInitUnicodeString(&Name
, L
"Token");
643 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
644 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
645 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
646 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
647 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
648 ObjectTypeInitializer
.PoolType
= PagedPool
;
649 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
650 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
651 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
652 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SeTokenObjectType
);
657 SeAssignPrimaryToken(IN PEPROCESS Process
,
663 ASSERT(Token
->TokenType
== TokenPrimary
);
664 ASSERT(!Token
->TokenInUse
);
666 /* Clean any previous token */
667 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
669 /* Set the new token */
670 ObReferenceObject(Token
);
671 Token
->TokenInUse
= TRUE
;
672 ObInitializeFastReference(&Process
->Token
, Token
);
678 SepCreateToken(OUT PHANDLE TokenHandle
,
679 IN KPROCESSOR_MODE PreviousMode
,
680 IN ACCESS_MASK DesiredAccess
,
681 IN POBJECT_ATTRIBUTES ObjectAttributes
,
682 IN TOKEN_TYPE TokenType
,
683 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
684 IN PLUID AuthenticationId
,
685 IN PLARGE_INTEGER ExpirationTime
,
686 IN PSID_AND_ATTRIBUTES User
,
688 IN PSID_AND_ATTRIBUTES Groups
,
689 IN ULONG GroupLength
,
690 IN ULONG PrivilegeCount
,
691 IN PLUID_AND_ATTRIBUTES Privileges
,
693 IN PSID PrimaryGroup
,
695 IN PTOKEN_SOURCE TokenSource
,
696 IN BOOLEAN SystemToken
)
705 ULONG TokenFlags
= 0;
707 /* Loop all groups */
708 for (i
= 0; i
< GroupCount
; i
++)
710 /* Check for mandatory groups */
711 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
713 /* Force them to be enabled */
714 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
717 /* Check of the group is an admin group */
718 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
720 /* Remember this so we can optimize queries later */
721 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
725 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
726 if (!NT_SUCCESS(Status
))
729 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
730 if (!NT_SUCCESS(Status
))
733 Status
= ObCreateObject(PreviousMode
,
741 (PVOID
*)&AccessToken
);
742 if (!NT_SUCCESS(Status
))
744 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
748 /* Zero out the buffer */
749 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
751 AccessToken
->TokenLock
= &SepTokenLock
;
753 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
754 &TokenSource
->SourceIdentifier
);
755 memcpy(AccessToken
->TokenSource
.SourceName
,
756 TokenSource
->SourceName
,
757 sizeof(TokenSource
->SourceName
));
759 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
760 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
761 AccessToken
->ExpirationTime
= *ExpirationTime
;
762 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
764 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
765 AccessToken
->PrivilegeCount
= PrivilegeCount
;
767 AccessToken
->TokenFlags
= TokenFlags
;
768 AccessToken
->TokenType
= TokenType
;
769 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
772 * Normally we would just point these members into the variable information
773 * area; however, our ObCreateObject() call can't allocate a variable information
774 * area, so we allocate them seperately and provide a destroy function.
777 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
778 uLength
+= RtlLengthSid(User
->Sid
);
779 for (i
= 0; i
< GroupCount
; i
++)
780 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
782 // FIXME: should use the object itself
783 AccessToken
->UserAndGroups
= ExAllocatePoolWithTag(PagedPool
,
786 if (AccessToken
->UserAndGroups
== NULL
)
788 Status
= STATUS_INSUFFICIENT_RESOURCES
;
792 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
794 Status
= RtlCopySidAndAttributesArray(1,
797 AccessToken
->UserAndGroups
,
801 if (!NT_SUCCESS(Status
))
804 Status
= RtlCopySidAndAttributesArray(GroupCount
,
807 &AccessToken
->UserAndGroups
[1],
811 if (!NT_SUCCESS(Status
))
814 Status
= SepFindPrimaryGroupAndDefaultOwner(AccessToken
,
817 if (!NT_SUCCESS(Status
))
820 // FIXME: should use the object itself
821 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
822 if (uLength
== 0) uLength
= sizeof(PVOID
);
823 AccessToken
->Privileges
= ExAllocatePoolWithTag(PagedPool
,
825 TAG_TOKEN_PRIVILAGES
);
826 if (AccessToken
->Privileges
== NULL
)
828 Status
= STATUS_INSUFFICIENT_RESOURCES
;
832 if (PreviousMode
!= KernelMode
)
836 RtlCopyMemory(AccessToken
->Privileges
,
838 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
840 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
842 Status
= _SEH2_GetExceptionCode();
848 RtlCopyMemory(AccessToken
->Privileges
,
850 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
853 if (!NT_SUCCESS(Status
))
856 /* Update privilege flags */
857 SepUpdatePrivilegeFlagsToken(AccessToken
);
859 if (DefaultDacl
!= NULL
)
861 // FIXME: should use the object itself
862 AccessToken
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
863 DefaultDacl
->AclSize
,
865 if (AccessToken
->DefaultDacl
== NULL
)
867 Status
= STATUS_INSUFFICIENT_RESOURCES
;
871 RtlCopyMemory(AccessToken
->DefaultDacl
,
873 DefaultDacl
->AclSize
);
877 AccessToken
->DefaultDacl
= NULL
;
882 Status
= ObInsertObject((PVOID
)AccessToken
,
888 if (!NT_SUCCESS(Status
))
890 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
895 /* Return pointer instead of handle */
896 *TokenHandle
= (HANDLE
)AccessToken
;
900 if (!NT_SUCCESS(Status
))
904 /* Dereference the token, the delete procedure will clean up */
905 ObDereferenceObject(AccessToken
);
914 SepCreateSystemProcessToken(VOID
)
916 LUID_AND_ATTRIBUTES Privileges
[25];
917 ULONG GroupAttributes
, OwnerAttributes
;
918 SID_AND_ATTRIBUTES Groups
[32];
919 LARGE_INTEGER Expiration
;
920 SID_AND_ATTRIBUTES UserSid
;
923 OBJECT_ATTRIBUTES ObjectAttributes
;
929 /* Don't ever expire */
930 Expiration
.QuadPart
= -1;
932 /* All groups mandatory and enabled */
933 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
934 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
937 UserSid
.Sid
= SeLocalSystemSid
;
938 UserSid
.Attributes
= 0;
940 /* Primary group is local system */
941 PrimaryGroup
= SeLocalSystemSid
;
943 /* Owner is admins */
944 Owner
= SeAliasAdminsSid
;
946 /* Groups are admins, world, and authenticated users */
947 Groups
[0].Sid
= SeAliasAdminsSid
;
948 Groups
[0].Attributes
= OwnerAttributes
;
949 Groups
[1].Sid
= SeWorldSid
;
950 Groups
[1].Attributes
= GroupAttributes
;
951 Groups
[2].Sid
= SeAuthenticatedUserSid
;
952 Groups
[2].Attributes
= OwnerAttributes
;
953 GroupLength
= sizeof(SID_AND_ATTRIBUTES
) +
954 SeLengthSid(Groups
[0].Sid
) +
955 SeLengthSid(Groups
[1].Sid
) +
956 SeLengthSid(Groups
[2].Sid
);
957 ASSERT(GroupLength
<= sizeof(Groups
));
959 /* Setup the privileges */
961 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
962 Privileges
[i
++].Luid
= SeTcbPrivilege
;
964 Privileges
[i
].Attributes
= 0;
965 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
967 Privileges
[i
].Attributes
= 0;
968 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
970 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
971 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
973 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
974 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
976 Privileges
[i
].Attributes
= 0;
977 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
979 Privileges
[i
].Attributes
= 0;
980 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
982 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
983 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
985 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
986 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
988 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
989 Privileges
[i
++].Luid
= SeDebugPrivilege
;
991 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
992 Privileges
[i
++].Luid
= SeAuditPrivilege
;
994 Privileges
[i
].Attributes
= 0;
995 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
997 Privileges
[i
].Attributes
= 0;
998 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1000 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
1001 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1003 Privileges
[i
].Attributes
= 0;
1004 Privileges
[i
++].Luid
= SeBackupPrivilege
;
1006 Privileges
[i
].Attributes
= 0;
1007 Privileges
[i
++].Luid
= SeRestorePrivilege
;
1009 Privileges
[i
].Attributes
= 0;
1010 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1012 Privileges
[i
].Attributes
= 0;
1013 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1015 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
1016 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1018 Privileges
[i
].Attributes
= 0;
1019 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1022 /* Setup the object attributes */
1023 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1024 ASSERT(SeSystemDefaultDacl
!= NULL
);
1026 /* Create the token */
1027 Status
= SepCreateToken((PHANDLE
)&Token
,
1033 &SeSystemAuthenticationId
,
1043 SeSystemDefaultDacl
,
1044 &SeSystemTokenSource
,
1046 ASSERT(Status
== STATUS_SUCCESS
);
1048 /* Return the token */
1052 /* PUBLIC FUNCTIONS ***********************************************************/
1059 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
1061 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
1062 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
1063 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
1064 OUT PACCESS_TOKEN
* FilteredToken
)
1067 return STATUS_NOT_IMPLEMENTED
;
1075 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
1076 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1077 OUT PVOID
*TokenInformation
)
1080 return STATUS_NOT_IMPLEMENTED
;
1088 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
1089 IN PULONG pSessionId
)
1091 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1092 return STATUS_SUCCESS
;
1100 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1105 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
1107 return STATUS_SUCCESS
;
1114 SECURITY_IMPERSONATION_LEVEL
1116 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1120 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1128 SeTokenType(IN PACCESS_TOKEN Token
)
1132 return ((PTOKEN
)Token
)->TokenType
;
1141 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
1145 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
1153 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
1157 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
1165 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
1169 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
1172 /* SYSTEM CALLS ***************************************************************/
1178 NtQueryInformationToken(IN HANDLE TokenHandle
,
1179 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1180 OUT PVOID TokenInformation
,
1181 IN ULONG TokenInformationLength
,
1182 OUT PULONG ReturnLength
)
1190 ULONG RequiredLength
;
1191 KPROCESSOR_MODE PreviousMode
;
1196 PreviousMode
= ExGetPreviousMode();
1198 /* Check buffers and class validity */
1199 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1200 SeTokenInformationClass
,
1201 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1203 TokenInformationLength
,
1207 if (!NT_SUCCESS(Status
))
1209 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1213 Status
= ObReferenceObjectByHandle(TokenHandle
,
1214 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1219 if (NT_SUCCESS(Status
))
1221 switch (TokenInformationClass
)
1225 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1227 DPRINT("NtQueryInformationToken(TokenUser)\n");
1228 RequiredLength
= sizeof(TOKEN_USER
) +
1229 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1233 if (TokenInformationLength
>= RequiredLength
)
1235 Status
= RtlCopySidAndAttributesArray(1,
1236 &Token
->UserAndGroups
[0],
1237 RequiredLength
- sizeof(TOKEN_USER
),
1245 Status
= STATUS_BUFFER_TOO_SMALL
;
1248 if (ReturnLength
!= NULL
)
1250 *ReturnLength
= RequiredLength
;
1253 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1255 Status
= _SEH2_GetExceptionCode();
1264 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1266 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1267 RequiredLength
= sizeof(tg
->GroupCount
) +
1268 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1272 if (TokenInformationLength
>= RequiredLength
)
1274 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1275 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1276 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1277 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1279 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1280 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1281 &Token
->UserAndGroups
[1],
1290 Status
= STATUS_BUFFER_TOO_SMALL
;
1293 if (ReturnLength
!= NULL
)
1295 *ReturnLength
= RequiredLength
;
1298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1300 Status
= _SEH2_GetExceptionCode();
1307 case TokenPrivileges
:
1309 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1311 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1312 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1313 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1317 if (TokenInformationLength
>= RequiredLength
)
1319 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1320 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1322 &tp
->Privileges
[0]);
1326 Status
= STATUS_BUFFER_TOO_SMALL
;
1329 if (ReturnLength
!= NULL
)
1331 *ReturnLength
= RequiredLength
;
1334 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1336 Status
= _SEH2_GetExceptionCode();
1346 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1348 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1349 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1350 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1354 if (TokenInformationLength
>= RequiredLength
)
1356 to
->Owner
= (PSID
)(to
+ 1);
1357 Status
= RtlCopySid(SidLen
,
1359 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1363 Status
= STATUS_BUFFER_TOO_SMALL
;
1366 if (ReturnLength
!= NULL
)
1368 *ReturnLength
= RequiredLength
;
1371 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1373 Status
= _SEH2_GetExceptionCode();
1380 case TokenPrimaryGroup
:
1383 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1385 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1386 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1387 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1391 if (TokenInformationLength
>= RequiredLength
)
1393 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1394 Status
= RtlCopySid(SidLen
,
1396 Token
->PrimaryGroup
);
1400 Status
= STATUS_BUFFER_TOO_SMALL
;
1403 if (ReturnLength
!= NULL
)
1405 *ReturnLength
= RequiredLength
;
1408 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1410 Status
= _SEH2_GetExceptionCode();
1417 case TokenDefaultDacl
:
1419 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1421 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1422 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1424 if (Token
->DefaultDacl
!= NULL
)
1426 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1431 if (TokenInformationLength
>= RequiredLength
)
1433 if (Token
->DefaultDacl
!= NULL
)
1435 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1436 RtlCopyMemory(tdd
->DefaultDacl
,
1438 Token
->DefaultDacl
->AclSize
);
1442 tdd
->DefaultDacl
= NULL
;
1447 Status
= STATUS_BUFFER_TOO_SMALL
;
1450 if (ReturnLength
!= NULL
)
1452 *ReturnLength
= RequiredLength
;
1455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1457 Status
= _SEH2_GetExceptionCode();
1466 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1468 DPRINT("NtQueryInformationToken(TokenSource)\n");
1469 RequiredLength
= sizeof(TOKEN_SOURCE
);
1473 if (TokenInformationLength
>= RequiredLength
)
1475 *ts
= Token
->TokenSource
;
1479 Status
= STATUS_BUFFER_TOO_SMALL
;
1482 if (ReturnLength
!= NULL
)
1484 *ReturnLength
= RequiredLength
;
1487 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1489 Status
= _SEH2_GetExceptionCode();
1498 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1500 DPRINT("NtQueryInformationToken(TokenType)\n");
1501 RequiredLength
= sizeof(TOKEN_TYPE
);
1505 if (TokenInformationLength
>= RequiredLength
)
1507 *tt
= Token
->TokenType
;
1511 Status
= STATUS_BUFFER_TOO_SMALL
;
1514 if (ReturnLength
!= NULL
)
1516 *ReturnLength
= RequiredLength
;
1519 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1521 Status
= _SEH2_GetExceptionCode();
1528 case TokenImpersonationLevel
:
1530 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1532 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1534 /* Fail if the token is not an impersonation token */
1535 if (Token
->TokenType
!= TokenImpersonation
)
1537 Status
= STATUS_INVALID_INFO_CLASS
;
1541 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1545 if (TokenInformationLength
>= RequiredLength
)
1547 *sil
= Token
->ImpersonationLevel
;
1551 Status
= STATUS_BUFFER_TOO_SMALL
;
1554 if (ReturnLength
!= NULL
)
1556 *ReturnLength
= RequiredLength
;
1559 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1561 Status
= _SEH2_GetExceptionCode();
1568 case TokenStatistics
:
1570 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1572 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1573 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1577 if (TokenInformationLength
>= RequiredLength
)
1579 ts
->TokenId
= Token
->TokenId
;
1580 ts
->AuthenticationId
= Token
->AuthenticationId
;
1581 ts
->ExpirationTime
= Token
->ExpirationTime
;
1582 ts
->TokenType
= Token
->TokenType
;
1583 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1584 ts
->DynamicCharged
= Token
->DynamicCharged
;
1585 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1586 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1587 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1588 ts
->ModifiedId
= Token
->ModifiedId
;
1592 Status
= STATUS_BUFFER_TOO_SMALL
;
1595 if (ReturnLength
!= NULL
)
1597 *ReturnLength
= RequiredLength
;
1600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1602 Status
= _SEH2_GetExceptionCode();
1611 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1613 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1614 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1618 if (TokenInformationLength
>= RequiredLength
)
1620 RtlCopyLuid(&to
->OriginatingLogonSession
,
1621 &Token
->AuthenticationId
);
1625 Status
= STATUS_BUFFER_TOO_SMALL
;
1628 if (ReturnLength
!= NULL
)
1630 *ReturnLength
= RequiredLength
;
1633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1635 Status
= _SEH2_GetExceptionCode();
1642 case TokenGroupsAndPrivileges
:
1643 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1644 Status
= STATUS_NOT_IMPLEMENTED
;
1647 case TokenRestrictedSids
:
1649 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1651 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1652 RequiredLength
= sizeof(tg
->GroupCount
) +
1653 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1657 if (TokenInformationLength
>= RequiredLength
)
1659 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1660 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1661 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1662 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1664 tg
->GroupCount
= Token
->RestrictedSidCount
;
1665 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1666 Token
->RestrictedSids
,
1675 Status
= STATUS_BUFFER_TOO_SMALL
;
1678 if (ReturnLength
!= NULL
)
1680 *ReturnLength
= RequiredLength
;
1683 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1685 Status
= _SEH2_GetExceptionCode();
1692 case TokenSandBoxInert
:
1693 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1694 Status
= STATUS_NOT_IMPLEMENTED
;
1697 case TokenSessionId
:
1699 ULONG SessionId
= 0;
1701 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1703 Status
= SeQuerySessionIdToken(Token
,
1706 if (NT_SUCCESS(Status
))
1710 /* buffer size was already verified, no need to check here again */
1711 *(PULONG
)TokenInformation
= SessionId
;
1713 if (ReturnLength
!= NULL
)
1715 *ReturnLength
= sizeof(ULONG
);
1718 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1720 Status
= _SEH2_GetExceptionCode();
1729 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1730 Status
= STATUS_INVALID_INFO_CLASS
;
1734 ObDereferenceObject(Token
);
1742 * NtSetTokenInformation: Partly implemented.
1744 * TokenOrigin, TokenDefaultDacl
1748 NtSetInformationToken(IN HANDLE TokenHandle
,
1749 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1750 OUT PVOID TokenInformation
,
1751 IN ULONG TokenInformationLength
)
1754 KPROCESSOR_MODE PreviousMode
;
1755 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1760 PreviousMode
= ExGetPreviousMode();
1762 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1763 SeTokenInformationClass
,
1764 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1766 TokenInformationLength
,
1768 if (!NT_SUCCESS(Status
))
1770 /* Invalid buffers */
1771 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1775 if (TokenInformationClass
== TokenSessionId
)
1777 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1780 Status
= ObReferenceObjectByHandle(TokenHandle
,
1786 if (NT_SUCCESS(Status
))
1788 switch (TokenInformationClass
)
1792 if (TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1794 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1795 PSID InputSid
= NULL
, CapturedSid
;
1799 InputSid
= to
->Owner
;
1801 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1803 Status
= _SEH2_GetExceptionCode();
1808 Status
= SepCaptureSid(InputSid
,
1813 if (NT_SUCCESS(Status
))
1815 RtlCopySid(RtlLengthSid(CapturedSid
),
1816 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1818 SepReleaseSid(CapturedSid
,
1825 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1830 case TokenPrimaryGroup
:
1832 if (TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1834 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1835 PSID InputSid
= NULL
, CapturedSid
;
1839 InputSid
= tpg
->PrimaryGroup
;
1841 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1843 Status
= _SEH2_GetExceptionCode();
1848 Status
= SepCaptureSid(InputSid
,
1853 if (NT_SUCCESS(Status
))
1855 RtlCopySid(RtlLengthSid(CapturedSid
),
1856 Token
->PrimaryGroup
,
1858 SepReleaseSid(CapturedSid
,
1865 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1870 case TokenDefaultDacl
:
1872 if (TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1874 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1875 PACL InputAcl
= NULL
;
1879 InputAcl
= tdd
->DefaultDacl
;
1881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1883 Status
= _SEH2_GetExceptionCode();
1888 if (InputAcl
!= NULL
)
1892 /* Capture and copy the dacl */
1893 Status
= SepCaptureAcl(InputAcl
,
1898 if (NT_SUCCESS(Status
))
1900 /* Free the previous dacl if present */
1901 if(Token
->DefaultDacl
!= NULL
)
1903 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
1906 Token
->DefaultDacl
= ExAllocatePoolWithTag(PagedPool
,
1907 CapturedAcl
->AclSize
,
1909 if (!Token
->DefaultDacl
)
1911 ExFreePoolWithTag(CapturedAcl
, TAG_ACL
);
1912 Status
= STATUS_NO_MEMORY
;
1916 /* Set the new dacl */
1917 RtlCopyMemory(Token
->DefaultDacl
, CapturedAcl
, CapturedAcl
->AclSize
);
1918 ExFreePoolWithTag(CapturedAcl
, TAG_ACL
);
1924 /* Clear and free the default dacl if present */
1925 if (Token
->DefaultDacl
!= NULL
)
1927 ExFreePoolWithTag(Token
->DefaultDacl
, TAG_TOKEN_ACL
);
1928 Token
->DefaultDacl
= NULL
;
1934 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1939 case TokenSessionId
:
1941 ULONG SessionId
= 0;
1945 /* Buffer size was already verified, no need to check here again */
1946 SessionId
= *(PULONG
)TokenInformation
;
1948 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1950 Status
= _SEH2_GetExceptionCode();
1955 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1958 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1962 Token
->SessionId
= SessionId
;
1966 case TokenSessionReference
:
1968 ULONG SessionReference
;
1972 /* Buffer size was already verified, no need to check here again */
1973 SessionReference
= *(PULONG
)TokenInformation
;
1975 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1977 Status
= _SEH2_GetExceptionCode();
1982 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1984 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1988 /* Check if it is 0 */
1989 if (SessionReference
== 0)
1991 /* Atomically set the flag in the token */
1992 RtlInterlockedSetBits(&Token
->TokenFlags
,
1993 TOKEN_SESSION_NOT_REFERENCED
);
2001 case TokenAuditPolicy
:
2003 PTOKEN_AUDIT_POLICY_INFORMATION PolicyInformation
=
2004 (PTOKEN_AUDIT_POLICY_INFORMATION
)TokenInformation
;
2005 SEP_AUDIT_POLICY AuditPolicy
;
2010 ProbeForRead(PolicyInformation
,
2011 FIELD_OFFSET(TOKEN_AUDIT_POLICY_INFORMATION
,
2012 Policies
[PolicyInformation
->PolicyCount
]),
2015 /* Loop all policies in the structure */
2016 for (i
= 0; i
< PolicyInformation
->PolicyCount
; i
++)
2018 /* Set the corresponding bits in the packed structure */
2019 switch (PolicyInformation
->Policies
[i
].Category
)
2021 case AuditCategorySystem
:
2022 AuditPolicy
.PolicyElements
.System
= PolicyInformation
->Policies
[i
].Value
;
2025 case AuditCategoryLogon
:
2026 AuditPolicy
.PolicyElements
.Logon
= PolicyInformation
->Policies
[i
].Value
;
2029 case AuditCategoryObjectAccess
:
2030 AuditPolicy
.PolicyElements
.ObjectAccess
= PolicyInformation
->Policies
[i
].Value
;
2033 case AuditCategoryPrivilegeUse
:
2034 AuditPolicy
.PolicyElements
.PrivilegeUse
= PolicyInformation
->Policies
[i
].Value
;
2037 case AuditCategoryDetailedTracking
:
2038 AuditPolicy
.PolicyElements
.DetailedTracking
= PolicyInformation
->Policies
[i
].Value
;
2041 case AuditCategoryPolicyChange
:
2042 AuditPolicy
.PolicyElements
.PolicyChange
= PolicyInformation
->Policies
[i
].Value
;
2045 case AuditCategoryAccountManagement
:
2046 AuditPolicy
.PolicyElements
.AccountManagement
= PolicyInformation
->Policies
[i
].Value
;
2049 case AuditCategoryDirectoryServiceAccess
:
2050 AuditPolicy
.PolicyElements
.DirectoryServiceAccess
= PolicyInformation
->Policies
[i
].Value
;
2053 case AuditCategoryAccountLogon
:
2054 AuditPolicy
.PolicyElements
.AccountLogon
= PolicyInformation
->Policies
[i
].Value
;
2059 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2061 Status
= _SEH2_GetExceptionCode();
2066 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2069 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2073 /* Lock the token */
2074 SepAcquireTokenLockExclusive(Token
);
2076 /* Set the new audit policy */
2077 Token
->AuditPolicy
= AuditPolicy
;
2079 /* Unlock the token */
2080 SepReleaseTokenLock(Token
);
2087 TOKEN_ORIGIN TokenOrigin
;
2091 /* Copy the token origin */
2092 TokenOrigin
= *(PTOKEN_ORIGIN
)TokenInformation
;
2094 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2096 Status
= _SEH2_GetExceptionCode();
2101 /* Check for TCB privilege */
2102 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
2104 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2108 /* Lock the token */
2109 SepAcquireTokenLockExclusive(Token
);
2111 /* Check if there is no token origin set yet */
2112 if ((Token
->OriginatingLogonSession
.LowPart
== 0) &&
2113 (Token
->OriginatingLogonSession
.HighPart
== 0))
2115 /* Set the token origin */
2116 Token
->OriginatingLogonSession
=
2117 TokenOrigin
.OriginatingLogonSession
;
2120 /* Unlock the token */
2121 SepReleaseTokenLock(Token
);
2128 DPRINT1("Invalid TokenInformationClass: 0x%lx\n",
2129 TokenInformationClass
);
2130 Status
= STATUS_INVALID_INFO_CLASS
;
2135 ObDereferenceObject(Token
);
2138 if (!NT_SUCCESS(Status
))
2140 DPRINT1("NtSetInformationToken failed with Status 0x%lx\n", Status
);
2150 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
2151 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
2152 * is correct either. -Gunnar
2153 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
2156 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
2157 IN ACCESS_MASK DesiredAccess
,
2158 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
2159 IN BOOLEAN EffectiveOnly
,
2160 IN TOKEN_TYPE TokenType
,
2161 OUT PHANDLE NewTokenHandle
)
2163 KPROCESSOR_MODE PreviousMode
;
2167 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
2169 OBJECT_HANDLE_INFORMATION HandleInformation
;
2174 if (TokenType
!= TokenImpersonation
&&
2175 TokenType
!= TokenPrimary
)
2176 return STATUS_INVALID_PARAMETER
;
2178 PreviousMode
= KeGetPreviousMode();
2180 if (PreviousMode
!= KernelMode
)
2184 ProbeForWriteHandle(NewTokenHandle
);
2186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2188 /* Return the exception code */
2189 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2194 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
2198 &CapturedSecurityQualityOfService
,
2200 if (!NT_SUCCESS(Status
))
2202 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
2206 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
2211 &HandleInformation
);
2212 if (!NT_SUCCESS(Status
))
2214 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2221 * Fail, if the original token is an impersonation token and the caller
2222 * tries to raise the impersonation level of the new token above the
2223 * impersonation level of the original token.
2225 if (Token
->TokenType
== TokenImpersonation
)
2228 CapturedSecurityQualityOfService
->ImpersonationLevel
>Token
->ImpersonationLevel
)
2230 ObDereferenceObject(Token
);
2231 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2234 return STATUS_BAD_IMPERSONATION_LEVEL
;
2239 * Fail, if a primary token is to be created from an impersonation token
2240 * and and the impersonation level of the impersonation token is below SecurityImpersonation.
2242 if (Token
->TokenType
== TokenImpersonation
&&
2243 TokenType
== TokenPrimary
&&
2244 Token
->ImpersonationLevel
< SecurityImpersonation
)
2246 ObDereferenceObject(Token
);
2247 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2250 return STATUS_BAD_IMPERSONATION_LEVEL
;
2253 Status
= SepDuplicateToken(Token
,
2257 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
2261 ObDereferenceObject(Token
);
2263 if (NT_SUCCESS(Status
))
2265 Status
= ObInsertObject((PVOID
)NewToken
,
2267 (DesiredAccess
? DesiredAccess
: HandleInformation
.GrantedAccess
),
2271 if (NT_SUCCESS(Status
))
2275 *NewTokenHandle
= hToken
;
2277 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2279 Status
= _SEH2_GetExceptionCode();
2285 /* Free the captured structure */
2286 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
2294 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
2295 IN BOOLEAN ResetToDefault
,
2296 IN PTOKEN_GROUPS NewState
,
2297 IN ULONG BufferLength
,
2298 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
2299 OUT PULONG ReturnLength
)
2302 return(STATUS_NOT_IMPLEMENTED
);
2308 SepAdjustPrivileges(
2309 _Inout_ PTOKEN Token
,
2310 _In_ BOOLEAN DisableAllPrivileges
,
2311 _In_opt_ PLUID_AND_ATTRIBUTES NewState
,
2312 _In_ ULONG NewStateCount
,
2313 _Out_opt_ PTOKEN_PRIVILEGES PreviousState
,
2314 _In_ BOOLEAN ApplyChanges
,
2315 _Out_ PULONG ChangedPrivileges
)
2317 ULONG i
, j
, PrivilegeCount
, ChangeCount
, NewAttributes
;
2319 /* Count the found privileges and those that need to be changed */
2323 /* Loop all privileges in the token */
2324 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2326 /* Shall all of them be disabled? */
2327 if (DisableAllPrivileges
)
2329 /* The new attributes are the old ones, but disabled */
2330 NewAttributes
= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2334 /* Otherwise loop all provided privileges */
2335 for (j
= 0; j
< NewStateCount
; j
++)
2337 /* Check if this is the LUID we are looking for */
2338 if (RtlEqualLuid(&Token
->Privileges
[i
].Luid
, &NewState
[j
].Luid
))
2340 DPRINT("Found privilege\n");
2342 /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */
2343 NewAttributes
= NewState
[j
].Attributes
;
2344 NewAttributes
&= (SE_PRIVILEGE_ENABLED
| SE_PRIVILEGE_REMOVED
);
2345 NewAttributes
|= Token
->Privileges
[i
].Attributes
& ~SE_PRIVILEGE_ENABLED
;
2352 /* Check if we didn't find the privilege */
2353 if (j
== NewStateCount
)
2355 /* Continue with the token's next privilege */
2360 /* We found a privilege, count it */
2363 /* Does the privilege need to be changed? */
2364 if (Token
->Privileges
[i
].Attributes
!= NewAttributes
)
2366 /* Does the caller want the old privileges? */
2367 if (PreviousState
!= NULL
)
2369 /* Copy the old privilege */
2370 PreviousState
->Privileges
[ChangeCount
] = Token
->Privileges
[i
];
2373 /* Does the caller want to apply the changes? */
2376 /* Shall we remove the privilege? */
2377 if (NewAttributes
& SE_PRIVILEGE_REMOVED
)
2379 /* Set the token as disabled and update flags for it */
2380 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2381 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2383 /* Remove the privilege */
2384 SepRemovePrivilegeToken(Token
, i
);
2386 /* Fix the running index */
2389 /* Continue with next */
2393 /* Set the new attributes and update flags */
2394 Token
->Privileges
[i
].Attributes
= NewAttributes
;
2395 SepUpdateSinglePrivilegeFlagToken(Token
, i
);
2398 /* Increment the change count */
2403 /* Set the number of saved privileges */
2404 if (PreviousState
!= NULL
)
2405 PreviousState
->PrivilegeCount
= ChangeCount
;
2407 /* Return the number of changed privileges */
2408 *ChangedPrivileges
= ChangeCount
;
2410 /* Check if we missed some */
2411 if (!DisableAllPrivileges
&& (PrivilegeCount
< NewStateCount
))
2413 return STATUS_NOT_ALL_ASSIGNED
;
2416 return STATUS_SUCCESS
;
2423 _Must_inspect_result_
2427 NtAdjustPrivilegesToken(
2428 _In_ HANDLE TokenHandle
,
2429 _In_ BOOLEAN DisableAllPrivileges
,
2430 _In_opt_ PTOKEN_PRIVILEGES NewState
,
2431 _In_ ULONG BufferLength
,
2432 _Out_writes_bytes_to_opt_(BufferLength
,*ReturnLength
)
2433 PTOKEN_PRIVILEGES PreviousState
,
2434 _When_(PreviousState
!=NULL
, _Out_
) PULONG ReturnLength
)
2436 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2437 KPROCESSOR_MODE PreviousMode
;
2438 ULONG CapturedCount
= 0;
2439 ULONG CapturedLength
= 0;
2440 ULONG NewStateSize
= 0;
2442 ULONG RequiredLength
;
2447 DPRINT("NtAdjustPrivilegesToken() called\n");
2449 /* Fail, if we do not disable all privileges but NewState is NULL */
2450 if (DisableAllPrivileges
== FALSE
&& NewState
== NULL
)
2451 return STATUS_INVALID_PARAMETER
;
2453 PreviousMode
= KeGetPreviousMode ();
2454 if (PreviousMode
!= KernelMode
)
2458 /* Probe NewState */
2459 if (DisableAllPrivileges
== FALSE
)
2461 /* First probe the header */
2462 ProbeForRead(NewState
, sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
));
2464 CapturedCount
= NewState
->PrivilegeCount
;
2465 NewStateSize
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[CapturedCount
]);
2467 ProbeForRead(NewState
, NewStateSize
, sizeof(ULONG
));
2470 /* Probe PreviousState and ReturnLength */
2471 if (PreviousState
!= NULL
)
2473 ProbeForWrite(PreviousState
, BufferLength
, sizeof(ULONG
));
2474 ProbeForWrite(ReturnLength
, sizeof(ULONG
), sizeof(ULONG
));
2477 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2479 /* Return the exception code */
2480 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2486 /* This is kernel mode, we trust the caller */
2487 if (DisableAllPrivileges
== FALSE
)
2488 CapturedCount
= NewState
->PrivilegeCount
;
2491 /* Do we need to capture the new state? */
2492 if (DisableAllPrivileges
== FALSE
)
2496 /* Capture the new state array of privileges */
2497 Status
= SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
2504 &CapturedPrivileges
,
2507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2509 /* Return the exception code */
2510 Status
= _SEH2_GetExceptionCode();
2514 if (!NT_SUCCESS(Status
))
2518 /* Reference the token */
2519 Status
= ObReferenceObjectByHandle(TokenHandle
,
2520 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
2525 if (!NT_SUCCESS(Status
))
2527 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
2529 /* Release the captured privileges */
2530 if (CapturedPrivileges
!= NULL
)
2531 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2538 /* Lock the token */
2539 ExEnterCriticalRegionAndAcquireResourceExclusive(Token
->TokenLock
);
2541 /* Count the privileges that need to be changed, do not apply them yet */
2542 Status
= SepAdjustPrivileges(Token
,
2543 DisableAllPrivileges
,
2550 /* Check if the caller asked for the previous state */
2551 if (PreviousState
!= NULL
)
2553 /* Calculate the required length */
2554 RequiredLength
= FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
[ChangeCount
]);
2556 /* Try to return the required buffer length */
2559 *ReturnLength
= RequiredLength
;
2561 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2563 /* Do cleanup and return the exception code */
2564 Status
= _SEH2_GetExceptionCode();
2569 /* Fail, if the buffer length is smaller than the required length */
2570 if (BufferLength
< RequiredLength
)
2572 Status
= STATUS_BUFFER_TOO_SMALL
;
2577 /* Now enter SEH, since we might return the old privileges */
2580 /* This time apply the changes */
2581 Status
= SepAdjustPrivileges(Token
,
2582 DisableAllPrivileges
,
2589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2591 /* Do cleanup and return the exception code */
2592 Status
= _SEH2_GetExceptionCode();
2598 /* Unlock and dereference the token */
2599 ExReleaseResourceAndLeaveCriticalRegion(Token
->TokenLock
);
2600 ObDereferenceObject(Token
);
2602 /* Release the captured privileges */
2603 if (CapturedPrivileges
!= NULL
)
2604 SeReleaseLuidAndAttributesArray(CapturedPrivileges
,
2608 DPRINT ("NtAdjustPrivilegesToken() done\n");
2615 _Out_ PHANDLE TokenHandle
,
2616 _In_ ACCESS_MASK DesiredAccess
,
2617 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
,
2618 _In_ TOKEN_TYPE TokenType
,
2619 _In_ PLUID AuthenticationId
,
2620 _In_ PLARGE_INTEGER ExpirationTime
,
2621 _In_ PTOKEN_USER TokenUser
,
2622 _In_ PTOKEN_GROUPS TokenGroups
,
2623 _In_ PTOKEN_PRIVILEGES TokenPrivileges
,
2624 _In_opt_ PTOKEN_OWNER TokenOwner
,
2625 _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2626 _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2627 _In_ PTOKEN_SOURCE TokenSource
)
2630 KPROCESSOR_MODE PreviousMode
;
2631 ULONG PrivilegeCount
, GroupCount
;
2632 PSID OwnerSid
, PrimaryGroupSid
;
2634 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
2635 LUID LocalAuthenticationId
;
2636 TOKEN_SOURCE LocalTokenSource
;
2637 SECURITY_QUALITY_OF_SERVICE LocalSecurityQos
;
2638 PLUID_AND_ATTRIBUTES CapturedPrivileges
= NULL
;
2639 PSID_AND_ATTRIBUTES CapturedUser
= NULL
;
2640 PSID_AND_ATTRIBUTES CapturedGroups
= NULL
;
2641 PSID CapturedOwnerSid
= NULL
;
2642 PSID CapturedPrimaryGroupSid
= NULL
;
2643 PACL CapturedDefaultDacl
= NULL
;
2644 ULONG PrivilegesLength
, UserLength
, GroupsLength
;
2649 PreviousMode
= ExGetPreviousMode();
2651 if (PreviousMode
!= KernelMode
)
2655 ProbeForWriteHandle(TokenHandle
);
2657 if (ObjectAttributes
!= NULL
)
2659 ProbeForRead(ObjectAttributes
,
2660 sizeof(OBJECT_ATTRIBUTES
),
2662 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
2665 ProbeForRead(AuthenticationId
,
2668 LocalAuthenticationId
= *AuthenticationId
;
2670 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2672 ProbeForRead(TokenUser
,
2676 ProbeForRead(TokenGroups
,
2677 sizeof(TOKEN_GROUPS
),
2679 GroupCount
= TokenGroups
->GroupCount
;
2681 ProbeForRead(TokenPrivileges
,
2682 sizeof(TOKEN_PRIVILEGES
),
2684 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2686 if (TokenOwner
!= NULL
)
2688 ProbeForRead(TokenOwner
,
2689 sizeof(TOKEN_OWNER
),
2691 OwnerSid
= TokenOwner
->Owner
;
2698 ProbeForRead(TokenPrimaryGroup
,
2699 sizeof(TOKEN_PRIMARY_GROUP
),
2701 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
2703 if (TokenDefaultDacl
!= NULL
)
2705 ProbeForRead(TokenDefaultDacl
,
2706 sizeof(TOKEN_DEFAULT_DACL
),
2708 DefaultDacl
= TokenDefaultDacl
->DefaultDacl
;
2715 ProbeForRead(TokenSource
,
2716 sizeof(TOKEN_SOURCE
),
2718 LocalTokenSource
= *TokenSource
;
2720 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2722 /* Return the exception code */
2723 return _SEH2_GetExceptionCode();
2729 if (ObjectAttributes
!= NULL
)
2730 LocalSecurityQos
= *(SECURITY_QUALITY_OF_SERVICE
*)ObjectAttributes
->SecurityQualityOfService
;
2731 LocalAuthenticationId
= *AuthenticationId
;
2732 LocalExpirationTime
= *ExpirationTime
;
2733 GroupCount
= TokenGroups
->GroupCount
;
2734 PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2735 OwnerSid
= TokenOwner
? TokenOwner
->Owner
: NULL
;
2736 PrimaryGroupSid
= TokenPrimaryGroup
->PrimaryGroup
;
2737 DefaultDacl
= TokenDefaultDacl
? TokenDefaultDacl
->DefaultDacl
: NULL
;
2738 LocalTokenSource
= *TokenSource
;
2741 /* Check token type */
2742 if ((TokenType
< TokenPrimary
) ||
2743 (TokenType
> TokenImpersonation
))
2745 return STATUS_BAD_TOKEN_TYPE
;
2748 /* Capture the user SID and attributes */
2749 Status
= SeCaptureSidAndAttributesArray(&TokenUser
->User
,
2758 if (!NT_SUCCESS(Status
))
2763 /* Capture the groups SID and attributes array */
2764 Status
= SeCaptureSidAndAttributesArray(&TokenGroups
->Groups
[0],
2773 if (!NT_SUCCESS(Status
))
2778 /* Capture privileges */
2779 Status
= SeCaptureLuidAndAttributesArray(&TokenPrivileges
->Privileges
[0],
2786 &CapturedPrivileges
,
2788 if (!NT_SUCCESS(Status
))
2793 /* Capture the token owner SID */
2794 if (TokenOwner
!= NULL
)
2796 Status
= SepCaptureSid(OwnerSid
,
2801 if (!NT_SUCCESS(Status
))
2807 /* Capture the token primary group SID */
2808 Status
= SepCaptureSid(PrimaryGroupSid
,
2812 &CapturedPrimaryGroupSid
);
2813 if (!NT_SUCCESS(Status
))
2818 /* Capture DefaultDacl */
2819 if (DefaultDacl
!= NULL
)
2821 Status
= SepCaptureAcl(DefaultDacl
,
2825 &CapturedDefaultDacl
);
2828 /* Call the internal function */
2829 Status
= SepCreateToken(&hToken
,
2834 LocalSecurityQos
.ImpersonationLevel
,
2835 &LocalAuthenticationId
,
2836 &LocalExpirationTime
,
2840 0, // FIXME: Should capture
2844 CapturedPrimaryGroupSid
,
2845 CapturedDefaultDacl
,
2848 if (NT_SUCCESS(Status
))
2852 *TokenHandle
= hToken
;
2854 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2856 Status
= _SEH2_GetExceptionCode();
2863 /* Release what we captured */
2864 SeReleaseSidAndAttributesArray(CapturedUser
, PreviousMode
, FALSE
);
2865 SeReleaseSidAndAttributesArray(CapturedGroups
, PreviousMode
, FALSE
);
2866 SeReleaseLuidAndAttributesArray(CapturedPrivileges
, PreviousMode
, FALSE
);
2867 SepReleaseSid(CapturedOwnerSid
, PreviousMode
, FALSE
);
2868 SepReleaseSid(CapturedPrimaryGroupSid
, PreviousMode
, FALSE
);
2869 SepReleaseAcl(CapturedDefaultDacl
, PreviousMode
, FALSE
);
2879 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2880 IN ACCESS_MASK DesiredAccess
,
2881 IN BOOLEAN OpenAsSelf
,
2882 IN ULONG HandleAttributes
,
2883 OUT PHANDLE TokenHandle
)
2885 PETHREAD Thread
, NewThread
;
2887 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
2888 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2889 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2890 SE_IMPERSONATION_STATE ImpersonationState
;
2891 OBJECT_ATTRIBUTES ObjectAttributes
;
2892 SECURITY_DESCRIPTOR SecurityDescriptor
;
2894 KPROCESSOR_MODE PreviousMode
;
2896 BOOLEAN RestoreImpersonation
= FALSE
;
2900 PreviousMode
= ExGetPreviousMode();
2902 if (PreviousMode
!= KernelMode
)
2906 ProbeForWriteHandle(TokenHandle
);
2908 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2910 /* Return the exception code */
2911 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2917 * At first open the thread token for information access and verify
2918 * that the token associated with thread is valid.
2921 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2922 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2924 if (!NT_SUCCESS(Status
))
2929 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2930 &ImpersonationLevel
);
2933 ObDereferenceObject(Thread
);
2934 return STATUS_NO_TOKEN
;
2937 if (ImpersonationLevel
== SecurityAnonymous
)
2939 PsDereferenceImpersonationToken(Token
);
2940 ObDereferenceObject(Thread
);
2941 return STATUS_CANT_OPEN_ANONYMOUS
;
2945 * Revert to self if OpenAsSelf is specified.
2950 RestoreImpersonation
= PsDisableImpersonation(PsGetCurrentThread(),
2951 &ImpersonationState
);
2956 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2957 PsThreadType
, KernelMode
,
2958 (PVOID
*)&NewThread
, NULL
);
2959 if (NT_SUCCESS(Status
))
2961 PrimaryToken
= PsReferencePrimaryToken(NewThread
->ThreadsProcess
);
2963 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2965 ObFastDereferenceObject(&NewThread
->ThreadsProcess
->Token
, PrimaryToken
);
2967 if (NT_SUCCESS(Status
))
2971 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2972 SECURITY_DESCRIPTOR_REVISION
);
2973 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2977 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2978 NULL
, Dacl
? &SecurityDescriptor
: NULL
);
2981 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2982 TokenImpersonation
, ImpersonationLevel
,
2983 KernelMode
, &NewToken
);
2984 if (NT_SUCCESS(Status
))
2986 ObReferenceObject(NewToken
);
2987 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2995 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2996 NULL
, DesiredAccess
, SeTokenObjectType
,
2997 PreviousMode
, &hToken
);
3000 if (Dacl
) ExFreePoolWithTag(Dacl
, TAG_TOKEN_ACL
);
3002 if (RestoreImpersonation
)
3004 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
3007 ObDereferenceObject(Token
);
3009 if (NT_SUCCESS(Status
) && CopyOnOpen
)
3011 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
3014 if (NewToken
) ObDereferenceObject(NewToken
);
3016 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
3018 ObDereferenceObject(Thread
);
3020 if (NT_SUCCESS(Status
))
3024 *TokenHandle
= hToken
;
3026 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3028 Status
= _SEH2_GetExceptionCode();
3040 NtOpenThreadToken(IN HANDLE ThreadHandle
,
3041 IN ACCESS_MASK DesiredAccess
,
3042 IN BOOLEAN OpenAsSelf
,
3043 OUT PHANDLE TokenHandle
)
3045 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
3056 NtCompareTokens(IN HANDLE FirstTokenHandle
,
3057 IN HANDLE SecondTokenHandle
,
3060 KPROCESSOR_MODE PreviousMode
;
3061 PTOKEN FirstToken
, SecondToken
;
3067 PreviousMode
= ExGetPreviousMode();
3069 if (PreviousMode
!= KernelMode
)
3073 ProbeForWriteBoolean(Equal
);
3075 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3077 /* Return the exception code */
3078 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3083 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
3087 (PVOID
*)&FirstToken
,
3089 if (!NT_SUCCESS(Status
))
3092 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
3096 (PVOID
*)&SecondToken
,
3098 if (!NT_SUCCESS(Status
))
3100 ObDereferenceObject(FirstToken
);
3104 if (FirstToken
!= SecondToken
)
3106 Status
= SepCompareTokens(FirstToken
,
3113 ObDereferenceObject(FirstToken
);
3114 ObDereferenceObject(SecondToken
);
3116 if (NT_SUCCESS(Status
))
3122 _SEH2_EXCEPT(ExSystemExceptionFilter())
3124 Status
= _SEH2_GetExceptionCode();
3134 NtFilterToken(IN HANDLE ExistingTokenHandle
,
3136 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
3137 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
3138 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
3139 OUT PHANDLE NewTokenHandle
)
3142 return STATUS_NOT_IMPLEMENTED
;
3150 NtImpersonateAnonymousToken(IN HANDLE Thread
)
3153 return STATUS_NOT_IMPLEMENTED
;