3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/token.c
6 * PURPOSE: Security manager
8 * PROGRAMMERS: David Welch <welch@cwcom.net>
11 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, SepInitializeTokenImplementation)
23 /* GLOBALS *******************************************************************/
25 POBJECT_TYPE SepTokenObjectType
= NULL
;
26 ERESOURCE SepTokenLock
;
28 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
33 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
35 /* Class 0 not used, blame M$! */
36 ICI_SQ_SAME( 0, 0, 0),
39 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
41 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
43 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
45 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
46 /* TokenPrimaryGroup */
47 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
48 /* TokenDefaultDacl */
49 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
51 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
53 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
54 /* TokenImpersonationLevel */
55 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
57 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
58 /* TokenRestrictedSids */
59 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
61 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
62 /* TokenGroupsAndPrivileges */
63 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
64 /* TokenSessionReference */
65 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
66 /* TokenSandBoxInert */
67 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
68 /* TokenAuditPolicy */
69 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
71 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
74 /* FUNCTIONS *****************************************************************/
78 SepFreeProxyData(PVOID ProxyData
)
85 SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
88 return(STATUS_NOT_IMPLEMENTED
);
93 SeExchangePrimaryToken(PEPROCESS Process
,
94 PACCESS_TOKEN NewTokenP
,
95 PACCESS_TOKEN
* OldTokenP
)
98 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
102 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
103 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
105 /* Mark new token in use */
106 NewToken
->TokenInUse
= 1;
108 /* Reference the New Token */
109 ObReferenceObject(NewToken
);
111 /* Replace the old with the new */
112 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
114 /* Mark the Old Token as free */
115 OldToken
->TokenInUse
= 0;
117 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
118 return STATUS_SUCCESS
;
123 SeDeassignPrimaryToken(PEPROCESS Process
)
127 /* Remove the Token */
128 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
130 /* Mark the Old Token as free */
131 OldToken
->TokenInUse
= 0;
135 RtlLengthSidAndAttributes(ULONG Count
,
136 PSID_AND_ATTRIBUTES Src
)
143 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
144 for (i
= 0; i
< Count
; i
++)
145 uLength
+= RtlLengthSid(Src
[i
].Sid
);
153 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
159 Token
->PrimaryGroup
= 0;
163 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
166 /* Validate and set the primary group and user pointers */
167 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
170 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
172 Token
->DefaultOwnerIndex
= i
;
175 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
177 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
181 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
183 return(STATUS_INVALID_OWNER
);
186 if (Token
->PrimaryGroup
== 0)
188 return(STATUS_INVALID_PRIMARY_GROUP
);
191 return(STATUS_SUCCESS
);
197 SepDuplicateToken(PTOKEN Token
,
198 POBJECT_ATTRIBUTES ObjectAttributes
,
199 BOOLEAN EffectiveOnly
,
200 TOKEN_TYPE TokenType
,
201 SECURITY_IMPERSONATION_LEVEL Level
,
202 KPROCESSOR_MODE PreviousMode
,
203 PTOKEN
* NewAccessToken
)
213 Status
= ObCreateObject(PreviousMode
,
221 (PVOID
*)&AccessToken
);
222 if (!NT_SUCCESS(Status
))
224 DPRINT1("ObCreateObject() failed (Status %lx)\n");
228 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
229 if (!NT_SUCCESS(Status
))
231 ObDereferenceObject(AccessToken
);
235 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
236 if (!NT_SUCCESS(Status
))
238 ObDereferenceObject(AccessToken
);
242 AccessToken
->TokenLock
= &SepTokenLock
;
244 AccessToken
->TokenInUse
= 0;
245 AccessToken
->TokenType
= TokenType
;
246 AccessToken
->ImpersonationLevel
= Level
;
247 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
249 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
250 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
251 memcpy(AccessToken
->TokenSource
.SourceName
,
252 Token
->TokenSource
.SourceName
,
253 sizeof(Token
->TokenSource
.SourceName
));
254 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
255 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
256 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
258 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
259 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
260 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
262 AccessToken
->UserAndGroups
=
263 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
265 TAG('T', 'O', 'K', 'u'));
267 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
269 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
270 Token
->UserAndGroups
,
272 AccessToken
->UserAndGroups
,
276 if (NT_SUCCESS(Status
))
278 Status
= SepFindPrimaryGroupAndDefaultOwner(
284 if (NT_SUCCESS(Status
))
286 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
288 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
289 AccessToken
->Privileges
=
290 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
292 TAG('T', 'O', 'K', 'p'));
294 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
296 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
297 &Token
->Privileges
[i
].Luid
);
298 AccessToken
->Privileges
[i
].Attributes
=
299 Token
->Privileges
[i
].Attributes
;
302 if ( Token
->DefaultDacl
)
304 AccessToken
->DefaultDacl
=
305 (PACL
) ExAllocatePoolWithTag(PagedPool
,
306 Token
->DefaultDacl
->AclSize
,
307 TAG('T', 'O', 'K', 'd'));
308 memcpy(AccessToken
->DefaultDacl
,
310 Token
->DefaultDacl
->AclSize
);
314 AccessToken
->DefaultDacl
= 0;
318 if ( NT_SUCCESS(Status
) )
320 *NewAccessToken
= AccessToken
;
321 return(STATUS_SUCCESS
);
329 SeSubProcessToken(IN PTOKEN ParentToken
,
335 OBJECT_ATTRIBUTES ObjectAttributes
;
338 /* Initialize the attributes and duplicate it */
339 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
340 Status
= SepDuplicateToken(ParentToken
,
344 ParentToken
->ImpersonationLevel
,
347 if (NT_SUCCESS(Status
))
350 Status
= ObInsertObject(NewToken
,
356 if (NT_SUCCESS(Status
))
358 /* Set the session ID */
359 NewToken
->SessionId
= SessionId
;
360 NewToken
->TokenInUse
= InUse
;
362 /* Return the token */
373 SeIsTokenChild(IN PTOKEN Token
,
374 OUT PBOOLEAN IsChild
)
377 LUID ProcessLuid
, CallerLuid
;
382 /* Reference the process token */
383 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
386 ProcessLuid
= ProcessToken
->TokenId
;
388 /* Dereference the token */
389 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
392 CallerLuid
= Token
->TokenId
;
394 /* Compare the LUIDs */
395 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
398 return STATUS_SUCCESS
;
407 PACCESS_STATE AccessState
,
408 PPRIVILEGE_SET Privileges
412 return STATUS_NOT_IMPLEMENTED
;
417 SeCopyClientToken(PACCESS_TOKEN Token
,
418 SECURITY_IMPERSONATION_LEVEL Level
,
419 KPROCESSOR_MODE PreviousMode
,
420 PACCESS_TOKEN
* NewToken
)
423 OBJECT_ATTRIBUTES ObjectAttributes
;
427 InitializeObjectAttributes(&ObjectAttributes
,
432 Status
= SepDuplicateToken(Token
,
448 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
449 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
450 IN BOOLEAN RemoteClient
,
451 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
453 TOKEN_TYPE TokenType
;
455 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
458 PACCESS_TOKEN NewToken
;
462 Token
= PsReferenceEffectiveToken(Thread
,
465 &ImpersonationLevel
);
466 if (TokenType
!= TokenImpersonation
)
468 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
472 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
476 ObDereferenceObject(Token
);
478 return(STATUS_UNSUCCESSFUL
);
480 if (ImpersonationLevel
== SecurityAnonymous
||
481 ImpersonationLevel
== SecurityIdentification
||
482 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
486 ObDereferenceObject(Token
);
488 return(STATUS_UNSUCCESSFUL
);
491 Qos
->EffectiveOnly
!= 0)
493 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
497 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
501 if (Qos
->ContextTrackingMode
== 0)
503 ClientContext
->DirectlyAccessClientToken
= FALSE
;
504 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
507 // ObDeleteCapturedInsertInfo(NewToken);
509 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
511 ObDereferenceObject(Token
);
520 ClientContext
->DirectlyAccessClientToken
= TRUE
;
521 if (RemoteClient
!= FALSE
)
523 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
527 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
528 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
529 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
530 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
531 ClientContext
->ServerIsRemote
= RemoteClient
;
532 ClientContext
->ClientToken
= NewToken
;
534 return(STATUS_SUCCESS
);
542 SeCreateClientSecurityFromSubjectContext(
543 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
544 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
545 IN BOOLEAN ServerIsRemote
,
546 OUT PSECURITY_CLIENT_CONTEXT ClientContext
550 return STATUS_NOT_IMPLEMENTED
;
559 IN PACCESS_TOKEN ExistingToken
,
561 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
562 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
563 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
564 OUT PACCESS_TOKEN
* FilteredToken
568 return STATUS_NOT_IMPLEMENTED
;
577 IN PPRIVILEGE_SET Privileges
589 SeImpersonateClientEx(
590 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
591 IN PETHREAD ServerThread OPTIONAL
595 return STATUS_NOT_IMPLEMENTED
;
602 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
603 IN PETHREAD ServerThread OPTIONAL
)
609 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
611 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
615 b
= ClientContext
->DirectAccessEffectiveOnly
;
617 if (ServerThread
== NULL
)
619 ServerThread
= PsGetCurrentThread();
621 PsImpersonateClient(ServerThread
,
622 ClientContext
->ClientToken
,
625 ClientContext
->SecurityQos
.ImpersonationLevel
);
630 SepDeleteToken(PVOID ObjectBody
)
632 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
634 if (AccessToken
->UserAndGroups
)
635 ExFreePool(AccessToken
->UserAndGroups
);
637 if (AccessToken
->Privileges
)
638 ExFreePool(AccessToken
->Privileges
);
640 if (AccessToken
->DefaultDacl
)
641 ExFreePool(AccessToken
->DefaultDacl
);
648 SepInitializeTokenImplementation(VOID
)
651 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
653 ExInitializeResource(&SepTokenLock
);
655 DPRINT("Creating Token Object Type\n");
657 /* Initialize the Token type */
658 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
659 RtlInitUnicodeString(&Name
, L
"Token");
660 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
661 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
662 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
663 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
664 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
665 ObjectTypeInitializer
.PoolType
= PagedPool
;
666 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
667 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
668 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
669 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SepTokenObjectType
);
677 NtQueryInformationToken(IN HANDLE TokenHandle
,
678 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
679 OUT PVOID TokenInformation
,
680 IN ULONG TokenInformationLength
,
681 OUT PULONG ReturnLength
)
689 ULONG RequiredLength
;
690 KPROCESSOR_MODE PreviousMode
;
691 NTSTATUS Status
= STATUS_SUCCESS
;
695 PreviousMode
= ExGetPreviousMode();
697 /* Check buffers and class validity */
698 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
699 SeTokenInformationClass
,
700 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
702 TokenInformationLength
,
706 if(!NT_SUCCESS(Status
))
708 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
712 Status
= ObReferenceObjectByHandle(TokenHandle
,
713 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
718 if (NT_SUCCESS(Status
))
720 switch (TokenInformationClass
)
724 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
726 DPRINT("NtQueryInformationToken(TokenUser)\n");
727 RequiredLength
= sizeof(TOKEN_USER
) +
728 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
732 if(TokenInformationLength
>= RequiredLength
)
734 Status
= RtlCopySidAndAttributesArray(1,
735 &Token
->UserAndGroups
[0],
736 RequiredLength
- sizeof(TOKEN_USER
),
744 Status
= STATUS_BUFFER_TOO_SMALL
;
747 if(ReturnLength
!= NULL
)
749 *ReturnLength
= RequiredLength
;
754 Status
= _SEH_GetExceptionCode();
763 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
765 DPRINT("NtQueryInformationToken(TokenGroups)\n");
766 RequiredLength
= sizeof(tg
->GroupCount
) +
767 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
771 if(TokenInformationLength
>= RequiredLength
)
773 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
774 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
775 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
776 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
778 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
779 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
780 &Token
->UserAndGroups
[1],
789 Status
= STATUS_BUFFER_TOO_SMALL
;
792 if(ReturnLength
!= NULL
)
794 *ReturnLength
= RequiredLength
;
799 Status
= _SEH_GetExceptionCode();
806 case TokenPrivileges
:
808 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
810 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
811 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
812 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
816 if(TokenInformationLength
>= RequiredLength
)
818 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
819 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
825 Status
= STATUS_BUFFER_TOO_SMALL
;
828 if(ReturnLength
!= NULL
)
830 *ReturnLength
= RequiredLength
;
835 Status
= _SEH_GetExceptionCode();
845 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
847 DPRINT("NtQueryInformationToken(TokenOwner)\n");
848 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
849 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
853 if(TokenInformationLength
>= RequiredLength
)
855 to
->Owner
= (PSID
)(to
+ 1);
856 Status
= RtlCopySid(SidLen
,
858 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
862 Status
= STATUS_BUFFER_TOO_SMALL
;
865 if(ReturnLength
!= NULL
)
867 *ReturnLength
= RequiredLength
;
872 Status
= _SEH_GetExceptionCode();
879 case TokenPrimaryGroup
:
882 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
884 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
885 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
886 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
890 if(TokenInformationLength
>= RequiredLength
)
892 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
893 Status
= RtlCopySid(SidLen
,
895 Token
->PrimaryGroup
);
899 Status
= STATUS_BUFFER_TOO_SMALL
;
902 if(ReturnLength
!= NULL
)
904 *ReturnLength
= RequiredLength
;
909 Status
= _SEH_GetExceptionCode();
916 case TokenDefaultDacl
:
918 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
920 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
921 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
923 if(Token
->DefaultDacl
!= NULL
)
925 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
930 if(TokenInformationLength
>= RequiredLength
)
932 if(Token
->DefaultDacl
!= NULL
)
934 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
935 RtlCopyMemory(tdd
->DefaultDacl
,
937 Token
->DefaultDacl
->AclSize
);
941 tdd
->DefaultDacl
= NULL
;
946 Status
= STATUS_BUFFER_TOO_SMALL
;
949 if(ReturnLength
!= NULL
)
951 *ReturnLength
= RequiredLength
;
956 Status
= _SEH_GetExceptionCode();
965 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
967 DPRINT("NtQueryInformationToken(TokenSource)\n");
968 RequiredLength
= sizeof(TOKEN_SOURCE
);
972 if(TokenInformationLength
>= RequiredLength
)
974 *ts
= Token
->TokenSource
;
978 Status
= STATUS_BUFFER_TOO_SMALL
;
981 if(ReturnLength
!= NULL
)
983 *ReturnLength
= RequiredLength
;
988 Status
= _SEH_GetExceptionCode();
997 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
999 DPRINT("NtQueryInformationToken(TokenType)\n");
1000 RequiredLength
= sizeof(TOKEN_TYPE
);
1004 if(TokenInformationLength
>= RequiredLength
)
1006 *tt
= Token
->TokenType
;
1010 Status
= STATUS_BUFFER_TOO_SMALL
;
1013 if(ReturnLength
!= NULL
)
1015 *ReturnLength
= RequiredLength
;
1020 Status
= _SEH_GetExceptionCode();
1027 case TokenImpersonationLevel
:
1029 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1031 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1032 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1036 if(TokenInformationLength
>= RequiredLength
)
1038 *sil
= Token
->ImpersonationLevel
;
1042 Status
= STATUS_BUFFER_TOO_SMALL
;
1045 if(ReturnLength
!= NULL
)
1047 *ReturnLength
= RequiredLength
;
1052 Status
= _SEH_GetExceptionCode();
1059 case TokenStatistics
:
1061 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1063 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1064 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1068 if(TokenInformationLength
>= RequiredLength
)
1070 ts
->TokenId
= Token
->TokenId
;
1071 ts
->AuthenticationId
= Token
->AuthenticationId
;
1072 ts
->ExpirationTime
= Token
->ExpirationTime
;
1073 ts
->TokenType
= Token
->TokenType
;
1074 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1075 ts
->DynamicCharged
= Token
->DynamicCharged
;
1076 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1077 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1078 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1079 ts
->ModifiedId
= Token
->ModifiedId
;
1083 Status
= STATUS_BUFFER_TOO_SMALL
;
1086 if(ReturnLength
!= NULL
)
1088 *ReturnLength
= RequiredLength
;
1093 Status
= _SEH_GetExceptionCode();
1102 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1104 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1105 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1109 if(TokenInformationLength
>= RequiredLength
)
1111 RtlCopyLuid(&to
->OriginatingLogonSession
,
1112 &Token
->AuthenticationId
);
1116 Status
= STATUS_BUFFER_TOO_SMALL
;
1119 if(ReturnLength
!= NULL
)
1121 *ReturnLength
= RequiredLength
;
1126 Status
= _SEH_GetExceptionCode();
1133 case TokenGroupsAndPrivileges
:
1134 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1135 Status
= STATUS_NOT_IMPLEMENTED
;
1138 case TokenRestrictedSids
:
1140 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1142 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1143 RequiredLength
= sizeof(tg
->GroupCount
) +
1144 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1148 if(TokenInformationLength
>= RequiredLength
)
1150 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1151 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1152 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1153 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1155 tg
->GroupCount
= Token
->RestrictedSidCount
;
1156 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1157 Token
->RestrictedSids
,
1166 Status
= STATUS_BUFFER_TOO_SMALL
;
1169 if(ReturnLength
!= NULL
)
1171 *ReturnLength
= RequiredLength
;
1176 Status
= _SEH_GetExceptionCode();
1183 case TokenSandBoxInert
:
1184 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1185 Status
= STATUS_NOT_IMPLEMENTED
;
1188 case TokenSessionId
:
1190 ULONG SessionId
= 0;
1192 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1194 Status
= SeQuerySessionIdToken(Token
,
1197 if(NT_SUCCESS(Status
))
1201 /* buffer size was already verified, no need to check here again */
1202 *(PULONG
)TokenInformation
= SessionId
;
1204 if(ReturnLength
!= NULL
)
1206 *ReturnLength
= sizeof(ULONG
);
1211 Status
= _SEH_GetExceptionCode();
1220 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1221 Status
= STATUS_INVALID_INFO_CLASS
;
1225 ObDereferenceObject(Token
);
1236 SeQueryInformationToken(
1237 IN PACCESS_TOKEN Token
,
1238 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1239 OUT PVOID
*TokenInformation
1243 return STATUS_NOT_IMPLEMENTED
;
1251 SeQuerySessionIdToken(
1252 IN PACCESS_TOKEN Token
,
1253 IN PULONG pSessionId
1256 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1257 return STATUS_SUCCESS
;
1261 * NtSetTokenInformation: Partly implemented.
1263 * TokenOrigin, TokenDefaultDacl
1267 NtSetInformationToken(IN HANDLE TokenHandle
,
1268 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1269 OUT PVOID TokenInformation
,
1270 IN ULONG TokenInformationLength
)
1273 KPROCESSOR_MODE PreviousMode
;
1274 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1275 NTSTATUS Status
= STATUS_SUCCESS
;
1279 PreviousMode
= ExGetPreviousMode();
1281 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1282 SeTokenInformationClass
,
1283 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1285 TokenInformationLength
,
1288 if(!NT_SUCCESS(Status
))
1290 /* Invalid buffers */
1291 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1295 if(TokenInformationClass
== TokenSessionId
)
1297 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1300 Status
= ObReferenceObjectByHandle(TokenHandle
,
1306 if (NT_SUCCESS(Status
))
1308 switch (TokenInformationClass
)
1312 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1314 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1315 PSID InputSid
= NULL
;
1319 InputSid
= to
->Owner
;
1323 Status
= _SEH_GetExceptionCode();
1327 if(NT_SUCCESS(Status
))
1331 Status
= SepCaptureSid(InputSid
,
1336 if(NT_SUCCESS(Status
))
1338 RtlCopySid(RtlLengthSid(CapturedSid
),
1339 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1341 SepReleaseSid(CapturedSid
,
1349 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1354 case TokenPrimaryGroup
:
1356 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1358 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1359 PSID InputSid
= NULL
;
1363 InputSid
= tpg
->PrimaryGroup
;
1367 Status
= _SEH_GetExceptionCode();
1371 if(NT_SUCCESS(Status
))
1375 Status
= SepCaptureSid(InputSid
,
1380 if(NT_SUCCESS(Status
))
1382 RtlCopySid(RtlLengthSid(CapturedSid
),
1383 Token
->PrimaryGroup
,
1385 SepReleaseSid(CapturedSid
,
1393 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1398 case TokenDefaultDacl
:
1400 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1402 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1403 PACL InputAcl
= NULL
;
1407 InputAcl
= tdd
->DefaultDacl
;
1411 Status
= _SEH_GetExceptionCode();
1415 if(NT_SUCCESS(Status
))
1417 if(InputAcl
!= NULL
)
1421 /* capture and copy the dacl */
1422 Status
= SepCaptureAcl(InputAcl
,
1427 if(NT_SUCCESS(Status
))
1429 /* free the previous dacl if present */
1430 if(Token
->DefaultDacl
!= NULL
)
1432 ExFreePool(Token
->DefaultDacl
);
1435 /* set the new dacl */
1436 Token
->DefaultDacl
= CapturedAcl
;
1441 /* clear and free the default dacl if present */
1442 if(Token
->DefaultDacl
!= NULL
)
1444 ExFreePool(Token
->DefaultDacl
);
1445 Token
->DefaultDacl
= NULL
;
1452 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1457 case TokenSessionId
:
1459 ULONG SessionId
= 0;
1463 /* buffer size was already verified, no need to check here again */
1464 SessionId
= *(PULONG
)TokenInformation
;
1468 Status
= _SEH_GetExceptionCode();
1472 if(NT_SUCCESS(Status
))
1474 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1477 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1481 Token
->SessionId
= SessionId
;
1488 Status
= STATUS_NOT_IMPLEMENTED
;
1493 ObDereferenceObject(Token
);
1503 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1504 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1505 * is correct either. -Gunnar
1506 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1509 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1510 IN ACCESS_MASK DesiredAccess
,
1511 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1512 IN BOOLEAN EffectiveOnly
,
1513 IN TOKEN_TYPE TokenType
,
1514 OUT PHANDLE NewTokenHandle
)
1516 KPROCESSOR_MODE PreviousMode
;
1520 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1522 NTSTATUS Status
= STATUS_SUCCESS
;
1526 PreviousMode
= KeGetPreviousMode();
1528 if(PreviousMode
!= KernelMode
)
1532 ProbeForWriteHandle(NewTokenHandle
);
1536 Status
= _SEH_GetExceptionCode();
1540 if(!NT_SUCCESS(Status
))
1546 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1550 &CapturedSecurityQualityOfService
,
1552 if(!NT_SUCCESS(Status
))
1554 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1558 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1564 if (NT_SUCCESS(Status
))
1566 Status
= SepDuplicateToken(Token
,
1570 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1574 ObDereferenceObject(Token
);
1576 if (NT_SUCCESS(Status
))
1578 Status
= ObInsertObject((PVOID
)NewToken
,
1585 if (NT_SUCCESS(Status
))
1589 *NewTokenHandle
= hToken
;
1593 Status
= _SEH_GetExceptionCode();
1600 /* free the captured structure */
1601 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1609 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1611 BOOLEAN ResetToDefault
,
1612 PSID_AND_ATTRIBUTES Groups
,
1614 KPROCESSOR_MODE PreviousMode
,
1625 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1626 IN BOOLEAN ResetToDefault
,
1627 IN PTOKEN_GROUPS NewState
,
1628 IN ULONG BufferLength
,
1629 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1630 OUT PULONG ReturnLength
)
1634 PACCESS_TOKEN Token
;
1641 Status
= ObReferenceObjectByHandle(TokenHandle
,
1649 SepAdjustGroups(Token
,
1661 return(STATUS_NOT_IMPLEMENTED
);
1668 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1670 KPROCESSOR_MODE PreviousMode
,
1671 ULONG PrivilegeCount
,
1672 PLUID_AND_ATTRIBUTES Privileges
,
1673 PTOKEN_PRIVILEGES
* PreviousState
,
1682 if (Token
->PrivilegeCount
> 0)
1684 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1686 if (PreviousMode
!= KernelMode
)
1688 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1692 if (PreviousState
!= NULL
)
1694 memcpy(&PreviousState
[i
],
1695 &Token
->Privileges
[i
],
1696 sizeof(LUID_AND_ATTRIBUTES
));
1698 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1705 if (PreviousMode
!= KernelMode
)
1707 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1711 if (PrivilegeCount
<= ?)
1724 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1725 IN BOOLEAN DisableAllPrivileges
,
1726 IN PTOKEN_PRIVILEGES NewState
,
1727 IN ULONG BufferLength
,
1728 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1729 OUT PULONG ReturnLength OPTIONAL
)
1731 // PLUID_AND_ATTRIBUTES Privileges;
1732 KPROCESSOR_MODE PreviousMode
;
1733 ULONG PrivilegeCount
;
1749 DPRINT ("NtAdjustPrivilegesToken() called\n");
1751 // PrivilegeCount = NewState->PrivilegeCount;
1752 PreviousMode
= KeGetPreviousMode ();
1753 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1763 Status
= ObReferenceObjectByHandle (TokenHandle
,
1764 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1769 if (!NT_SUCCESS(Status
))
1771 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1772 // SeReleaseLuidAndAttributesArray(Privileges,
1780 SepAdjustPrivileges(Token
,
1791 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1792 sizeof(LUID_AND_ATTRIBUTES
);
1794 if (PreviousState
!= NULL
)
1795 PreviousState
->PrivilegeCount
= 0;
1798 if (DisableAllPrivileges
== TRUE
)
1800 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1802 if (Token
->Privileges
[i
].Attributes
!= 0)
1804 DPRINT ("Attributes differ\n");
1806 /* Save current privilege */
1807 if (PreviousState
!= NULL
)
1809 if (k
< PrivilegeCount
)
1811 PreviousState
->PrivilegeCount
++;
1812 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1813 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1817 /* FIXME: Should revert all the changes, calculate how
1818 * much space would be needed, set ResultLength
1819 * accordingly and fail.
1825 /* Update current privlege */
1826 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1829 Status
= STATUS_SUCCESS
;
1834 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1836 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1838 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1839 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1841 DPRINT ("Found privilege\n");
1843 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1844 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1846 DPRINT ("Attributes differ\n");
1847 DPRINT ("Current attributes %lx desired attributes %lx\n",
1848 Token
->Privileges
[i
].Attributes
,
1849 NewState
->Privileges
[j
].Attributes
);
1851 /* Save current privilege */
1852 if (PreviousState
!= NULL
)
1854 if (k
< PrivilegeCount
)
1856 PreviousState
->PrivilegeCount
++;
1857 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1858 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1862 /* FIXME: Should revert all the changes, calculate how
1863 * much space would be needed, set ResultLength
1864 * accordingly and fail.
1870 /* Update current privlege */
1871 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1872 Token
->Privileges
[i
].Attributes
|=
1873 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1874 DPRINT ("New attributes %lx\n",
1875 Token
->Privileges
[i
].Attributes
);
1881 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1884 if (ReturnLength
!= NULL
)
1886 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1887 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1890 ObDereferenceObject (Token
);
1892 // SeReleaseLuidAndAttributesArray(Privileges,
1896 DPRINT ("NtAdjustPrivilegesToken() done\n");
1903 SeAssignPrimaryToken(IN PEPROCESS Process
,
1909 ASSERT(Token
->TokenType
== TokenPrimary
);
1910 ASSERT(!Token
->TokenInUse
);
1912 /* Clean any previous token */
1913 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
1915 /* Set the new token */
1916 ObReferenceObject(Token
);
1917 Token
->TokenInUse
= TRUE
;
1918 ObInitializeFastReference(&Process
->Token
, Token
);
1923 SepCreateSystemProcessToken(VOID
)
1928 ULONG uLocalSystemLength
;
1930 ULONG uAuthUserLength
;
1931 ULONG uAdminsLength
;
1937 uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1938 uWorldLength
= RtlLengthSid(SeWorldSid
);
1939 uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1940 uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1943 * Initialize the token
1945 Status
= ObCreateObject(KernelMode
,
1953 (PVOID
*)&AccessToken
);
1954 if (!NT_SUCCESS(Status
))
1959 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1960 if (!NT_SUCCESS(Status
))
1962 ObDereferenceObject(AccessToken
);
1966 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1967 if (!NT_SUCCESS(Status
))
1969 ObDereferenceObject(AccessToken
);
1973 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1974 if (!NT_SUCCESS(Status
))
1976 ObDereferenceObject(AccessToken
);
1980 AccessToken
->TokenLock
= &SepTokenLock
;
1982 AccessToken
->TokenType
= TokenPrimary
;
1983 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1984 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1985 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1986 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1987 AccessToken
->ExpirationTime
.QuadPart
= -1;
1988 AccessToken
->UserAndGroupCount
= 4;
1990 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1991 uSize
+= uLocalSystemLength
;
1992 uSize
+= uWorldLength
;
1993 uSize
+= uAuthUserLength
;
1994 uSize
+= uAdminsLength
;
1996 AccessToken
->UserAndGroups
=
1997 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1999 TAG('T', 'O', 'K', 'u'));
2000 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2003 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
2004 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
2005 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
2006 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
2008 AccessToken
->DefaultOwnerIndex
= i
;
2009 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
2010 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
2011 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
2012 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
2013 SidArea
= (char*)SidArea
+ uAdminsLength
;
2015 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
2016 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
2017 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
2018 SidArea
= (char*)SidArea
+ uWorldLength
;
2020 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
2021 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
2022 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
2023 SidArea
= (char*)SidArea
+ uAuthUserLength
;
2025 AccessToken
->PrivilegeCount
= 20;
2027 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2028 AccessToken
->Privileges
=
2029 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2031 TAG('T', 'O', 'K', 'p'));
2034 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2035 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
2037 AccessToken
->Privileges
[i
].Attributes
= 0;
2038 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
2040 AccessToken
->Privileges
[i
].Attributes
= 0;
2041 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
2043 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2044 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
2046 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2047 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
2049 AccessToken
->Privileges
[i
].Attributes
= 0;
2050 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
2052 AccessToken
->Privileges
[i
].Attributes
= 0;
2053 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
2055 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2056 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
2058 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2059 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
2061 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2062 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
2064 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2065 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
2067 AccessToken
->Privileges
[i
].Attributes
= 0;
2068 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
2070 AccessToken
->Privileges
[i
].Attributes
= 0;
2071 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
2073 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2074 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
2076 AccessToken
->Privileges
[i
].Attributes
= 0;
2077 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
2079 AccessToken
->Privileges
[i
].Attributes
= 0;
2080 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
2082 AccessToken
->Privileges
[i
].Attributes
= 0;
2083 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
2085 AccessToken
->Privileges
[i
].Attributes
= 0;
2086 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
2088 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2089 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
2091 AccessToken
->Privileges
[i
].Attributes
= 0;
2092 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
2094 AccessToken
->Privileges
[i
].Attributes
= 0;
2095 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
2097 AccessToken
->Privileges
[i
].Attributes
= 0;
2098 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
2103 uSize
= sizeof(ACL
);
2104 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
2105 uSize
+= sizeof(ACE
) + uAdminsLength
;
2106 uSize
= (uSize
& (~3)) + 8;
2107 AccessToken
->DefaultDacl
=
2108 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2110 TAG('T', 'O', 'K', 'd'));
2111 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
2112 if ( NT_SUCCESS(Status
) )
2114 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
2117 if ( NT_SUCCESS(Status
) )
2119 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
2122 if ( ! NT_SUCCESS(Status
) )
2124 ObDereferenceObject(AccessToken
);
2133 NtCreateToken(OUT PHANDLE TokenHandle
,
2134 IN ACCESS_MASK DesiredAccess
,
2135 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2136 IN TOKEN_TYPE TokenType
,
2137 IN PLUID AuthenticationId
,
2138 IN PLARGE_INTEGER ExpirationTime
,
2139 IN PTOKEN_USER TokenUser
,
2140 IN PTOKEN_GROUPS TokenGroups
,
2141 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2142 IN PTOKEN_OWNER TokenOwner
,
2143 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2144 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2145 IN PTOKEN_SOURCE TokenSource
)
2154 KPROCESSOR_MODE PreviousMode
;
2155 ULONG nTokenPrivileges
= 0;
2156 LARGE_INTEGER LocalExpirationTime
= {{0}};
2157 NTSTATUS Status
= STATUS_SUCCESS
;
2161 PreviousMode
= ExGetPreviousMode();
2163 if(PreviousMode
!= KernelMode
)
2167 ProbeForWriteHandle(TokenHandle
);
2168 ProbeForRead(AuthenticationId
,
2171 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2172 ProbeForRead(TokenUser
,
2175 ProbeForRead(TokenGroups
,
2176 sizeof(TOKEN_GROUPS
),
2178 ProbeForRead(TokenPrivileges
,
2179 sizeof(TOKEN_PRIVILEGES
),
2181 ProbeForRead(TokenOwner
,
2182 sizeof(TOKEN_OWNER
),
2184 ProbeForRead(TokenPrimaryGroup
,
2185 sizeof(TOKEN_PRIMARY_GROUP
),
2187 ProbeForRead(TokenDefaultDacl
,
2188 sizeof(TOKEN_DEFAULT_DACL
),
2190 ProbeForRead(TokenSource
,
2191 sizeof(TOKEN_SOURCE
),
2193 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2197 Status
= _SEH_GetExceptionCode();
2201 if(!NT_SUCCESS(Status
))
2208 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2209 LocalExpirationTime
= *ExpirationTime
;
2212 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2213 if (!NT_SUCCESS(Status
))
2216 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2217 if (!NT_SUCCESS(Status
))
2220 Status
= ObCreateObject(PreviousMode
,
2228 (PVOID
*)&AccessToken
);
2229 if (!NT_SUCCESS(Status
))
2231 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2235 AccessToken
->TokenLock
= &SepTokenLock
;
2237 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2238 &TokenSource
->SourceIdentifier
);
2239 memcpy(AccessToken
->TokenSource
.SourceName
,
2240 TokenSource
->SourceName
,
2241 sizeof(TokenSource
->SourceName
));
2243 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2244 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2245 AccessToken
->ExpirationTime
= *ExpirationTime
;
2246 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2248 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2249 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2250 AccessToken
->UserAndGroups
= 0;
2251 AccessToken
->Privileges
= 0;
2253 AccessToken
->TokenType
= TokenType
;
2254 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2255 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2258 * Normally we would just point these members into the variable information
2259 * area; however, our ObCreateObject() call can't allocate a variable information
2260 * area, so we allocate them seperately and provide a destroy function.
2263 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2264 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2265 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2266 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2268 AccessToken
->UserAndGroups
=
2269 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2271 TAG('T', 'O', 'K', 'u'));
2273 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2275 Status
= RtlCopySidAndAttributesArray(1,
2278 AccessToken
->UserAndGroups
,
2282 if (NT_SUCCESS(Status
))
2284 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2285 TokenGroups
->Groups
,
2287 &AccessToken
->UserAndGroups
[1],
2293 if (NT_SUCCESS(Status
))
2295 Status
= SepFindPrimaryGroupAndDefaultOwner(
2297 TokenPrimaryGroup
->PrimaryGroup
,
2301 if (NT_SUCCESS(Status
))
2303 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2304 AccessToken
->Privileges
=
2305 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2307 TAG('T', 'O', 'K', 'p'));
2309 if (PreviousMode
!= KernelMode
)
2313 RtlCopyMemory(AccessToken
->Privileges
,
2314 TokenPrivileges
->Privileges
,
2315 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2319 Status
= _SEH_GetExceptionCode();
2325 RtlCopyMemory(AccessToken
->Privileges
,
2326 TokenPrivileges
->Privileges
,
2327 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2331 if (NT_SUCCESS(Status
))
2333 AccessToken
->DefaultDacl
=
2334 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2335 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2336 TAG('T', 'O', 'K', 'd'));
2337 memcpy(AccessToken
->DefaultDacl
,
2338 TokenDefaultDacl
->DefaultDacl
,
2339 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2342 Status
= ObInsertObject ((PVOID
)AccessToken
,
2348 if (!NT_SUCCESS(Status
))
2350 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2353 if (NT_SUCCESS(Status
))
2357 *TokenHandle
= hToken
;
2361 Status
= _SEH_GetExceptionCode();
2374 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
2379 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
2381 return STATUS_SUCCESS
;
2388 SECURITY_IMPERSONATION_LEVEL
2390 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
2394 return ((PTOKEN
)Token
)->ImpersonationLevel
;
2402 SeTokenType(IN PACCESS_TOKEN Token
)
2406 return ((PTOKEN
)Token
)->TokenType
;
2416 IN PACCESS_TOKEN Token
2420 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
2428 SeTokenIsRestricted(
2429 IN PACCESS_TOKEN Token
2433 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
2441 SeTokenIsWriteRestricted(
2442 IN PACCESS_TOKEN Token
2446 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
2455 NtImpersonateAnonymousToken(
2460 return STATUS_NOT_IMPLEMENTED
;
2469 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2470 IN ACCESS_MASK DesiredAccess
,
2471 IN BOOLEAN OpenAsSelf
,
2472 IN ULONG HandleAttributes
,
2473 OUT PHANDLE TokenHandle
)
2477 PTOKEN Token
, NewToken
, PrimaryToken
;
2478 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2479 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2480 SE_IMPERSONATION_STATE ImpersonationState
;
2481 OBJECT_ATTRIBUTES ObjectAttributes
;
2482 SECURITY_DESCRIPTOR SecurityDescriptor
;
2484 KPROCESSOR_MODE PreviousMode
;
2485 NTSTATUS Status
= STATUS_SUCCESS
;
2489 PreviousMode
= ExGetPreviousMode();
2491 if(PreviousMode
!= KernelMode
)
2495 ProbeForWriteHandle(TokenHandle
);
2499 Status
= _SEH_GetExceptionCode();
2503 if(!NT_SUCCESS(Status
))
2510 * At first open the thread token for information access and verify
2511 * that the token associated with thread is valid.
2514 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2515 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2517 if (!NT_SUCCESS(Status
))
2522 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2523 &ImpersonationLevel
);
2526 ObfDereferenceObject(Thread
);
2527 return STATUS_NO_TOKEN
;
2530 ObDereferenceObject(Thread
);
2532 if (ImpersonationLevel
== SecurityAnonymous
)
2534 ObfDereferenceObject(Token
);
2535 return STATUS_CANT_OPEN_ANONYMOUS
;
2539 * Revert to self if OpenAsSelf is specified.
2544 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2549 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2550 PsThreadType
, PreviousMode
,
2551 (PVOID
*)&Thread
, NULL
);
2552 if (!NT_SUCCESS(Status
))
2554 ObfDereferenceObject(Token
);
2557 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2562 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2563 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2565 ObfDereferenceObject(PrimaryToken
);
2566 ObfDereferenceObject(Thread
);
2567 if (!NT_SUCCESS(Status
))
2569 ObfDereferenceObject(Token
);
2572 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2577 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2578 SECURITY_DESCRIPTOR_REVISION
);
2579 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2582 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2583 NULL
, &SecurityDescriptor
);
2585 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2586 TokenImpersonation
, ImpersonationLevel
,
2587 KernelMode
, &NewToken
);
2589 if (!NT_SUCCESS(Status
))
2591 ObfDereferenceObject(Token
);
2594 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2599 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2605 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2606 NULL
, DesiredAccess
, SepTokenObjectType
,
2607 PreviousMode
, &hToken
);
2610 ObfDereferenceObject(Token
);
2614 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2617 if(NT_SUCCESS(Status
))
2621 *TokenHandle
= hToken
;
2625 Status
= _SEH_GetExceptionCode();
2637 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2638 IN ACCESS_MASK DesiredAccess
,
2639 IN BOOLEAN OpenAsSelf
,
2640 OUT PHANDLE TokenHandle
)
2642 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2647 SepCompareTokens(IN PTOKEN FirstToken
,
2648 IN PTOKEN SecondToken
,
2651 BOOLEAN Restricted
, IsEqual
= FALSE
;
2653 ASSERT(FirstToken
!= SecondToken
);
2655 /* FIXME: Check if every SID that is present in either token is also present in the other one */
2657 Restricted
= SeTokenIsRestricted(FirstToken
);
2658 if (Restricted
== SeTokenIsRestricted(SecondToken
))
2662 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
2665 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
2669 return STATUS_SUCCESS
;
2677 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2678 IN HANDLE SecondTokenHandle
,
2681 KPROCESSOR_MODE PreviousMode
;
2682 PTOKEN FirstToken
, SecondToken
;
2684 NTSTATUS Status
= STATUS_SUCCESS
;
2688 PreviousMode
= ExGetPreviousMode();
2690 if (PreviousMode
!= KernelMode
)
2694 ProbeForWriteBoolean(Equal
);
2698 Status
= _SEH_GetExceptionCode();
2702 if (!NT_SUCCESS(Status
))
2706 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2710 (PVOID
*)&FirstToken
,
2712 if (!NT_SUCCESS(Status
))
2715 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2719 (PVOID
*)&SecondToken
,
2721 if (!NT_SUCCESS(Status
))
2723 ObDereferenceObject(FirstToken
);
2727 if (FirstToken
!= SecondToken
)
2729 Status
= SepCompareTokens(FirstToken
,
2736 ObDereferenceObject(FirstToken
);
2737 ObDereferenceObject(SecondToken
);
2739 if (NT_SUCCESS(Status
))
2745 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
2747 Status
= _SEH_GetExceptionCode();
2757 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2759 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2760 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2761 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2762 OUT PHANDLE NewTokenHandle
)
2765 return STATUS_NOT_IMPLEMENTED
;