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 /* GLOBALS *******************************************************************/
20 POBJECT_TYPE SepTokenObjectType
= NULL
;
21 ERESOURCE SepTokenLock
;
23 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
28 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
30 /* Class 0 not used, blame M$! */
31 ICI_SQ_SAME( 0, 0, 0),
34 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
36 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
38 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
40 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
41 /* TokenPrimaryGroup */
42 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
43 /* TokenDefaultDacl */
44 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
46 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
48 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
49 /* TokenImpersonationLevel */
50 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
52 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
53 /* TokenRestrictedSids */
54 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
56 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
57 /* TokenGroupsAndPrivileges */
58 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
59 /* TokenSessionReference */
60 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
61 /* TokenSandBoxInert */
62 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
63 /* TokenAuditPolicy */
64 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
66 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
69 /* FUNCTIONS *****************************************************************/
73 SepFreeProxyData(PVOID ProxyData
)
80 SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
83 return(STATUS_NOT_IMPLEMENTED
);
88 SeExchangePrimaryToken(PEPROCESS Process
,
89 PACCESS_TOKEN NewTokenP
,
90 PACCESS_TOKEN
* OldTokenP
)
93 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
97 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
98 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
100 /* Mark new token in use */
101 NewToken
->TokenInUse
= 1;
103 /* Reference the New Token */
104 ObReferenceObject(NewToken
);
106 /* Replace the old with the new */
107 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
109 /* Mark the Old Token as free */
110 OldToken
->TokenInUse
= 0;
112 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
113 return STATUS_SUCCESS
;
118 SeDeassignPrimaryToken(PEPROCESS Process
)
122 /* Remove the Token */
123 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
125 /* Mark the Old Token as free */
126 OldToken
->TokenInUse
= 0;
130 RtlLengthSidAndAttributes(ULONG Count
,
131 PSID_AND_ATTRIBUTES Src
)
138 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
139 for (i
= 0; i
< Count
; i
++)
140 uLength
+= RtlLengthSid(Src
[i
].Sid
);
148 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
154 Token
->PrimaryGroup
= 0;
158 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
161 /* Validate and set the primary group and user pointers */
162 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
165 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
167 Token
->DefaultOwnerIndex
= i
;
170 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
172 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
176 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
178 return(STATUS_INVALID_OWNER
);
181 if (Token
->PrimaryGroup
== 0)
183 return(STATUS_INVALID_PRIMARY_GROUP
);
186 return(STATUS_SUCCESS
);
192 SepDuplicateToken(PTOKEN Token
,
193 POBJECT_ATTRIBUTES ObjectAttributes
,
194 BOOLEAN EffectiveOnly
,
195 TOKEN_TYPE TokenType
,
196 SECURITY_IMPERSONATION_LEVEL Level
,
197 KPROCESSOR_MODE PreviousMode
,
198 PTOKEN
* NewAccessToken
)
208 Status
= ObCreateObject(PreviousMode
,
216 (PVOID
*)&AccessToken
);
217 if (!NT_SUCCESS(Status
))
219 DPRINT1("ObCreateObject() failed (Status %lx)\n");
223 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
224 if (!NT_SUCCESS(Status
))
226 ObDereferenceObject(AccessToken
);
230 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
231 if (!NT_SUCCESS(Status
))
233 ObDereferenceObject(AccessToken
);
237 AccessToken
->TokenLock
= &SepTokenLock
;
239 AccessToken
->TokenInUse
= 0;
240 AccessToken
->TokenType
= TokenType
;
241 AccessToken
->ImpersonationLevel
= Level
;
242 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
244 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
245 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
246 memcpy(AccessToken
->TokenSource
.SourceName
,
247 Token
->TokenSource
.SourceName
,
248 sizeof(Token
->TokenSource
.SourceName
));
249 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
250 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
251 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
253 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
254 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
255 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
257 AccessToken
->UserAndGroups
=
258 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
260 TAG('T', 'O', 'K', 'u'));
262 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
264 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
265 Token
->UserAndGroups
,
267 AccessToken
->UserAndGroups
,
271 if (NT_SUCCESS(Status
))
273 Status
= SepFindPrimaryGroupAndDefaultOwner(
279 if (NT_SUCCESS(Status
))
281 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
283 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
284 AccessToken
->Privileges
=
285 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
287 TAG('T', 'O', 'K', 'p'));
289 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
291 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
292 &Token
->Privileges
[i
].Luid
);
293 AccessToken
->Privileges
[i
].Attributes
=
294 Token
->Privileges
[i
].Attributes
;
297 if ( Token
->DefaultDacl
)
299 AccessToken
->DefaultDacl
=
300 (PACL
) ExAllocatePoolWithTag(PagedPool
,
301 Token
->DefaultDacl
->AclSize
,
302 TAG('T', 'O', 'K', 'd'));
303 memcpy(AccessToken
->DefaultDacl
,
305 Token
->DefaultDacl
->AclSize
);
309 AccessToken
->DefaultDacl
= 0;
313 if ( NT_SUCCESS(Status
) )
315 *NewAccessToken
= AccessToken
;
316 return(STATUS_SUCCESS
);
319 ObDereferenceObject(AccessToken
);
329 PACCESS_STATE AccessState
,
330 PPRIVILEGE_SET Privileges
334 return STATUS_NOT_IMPLEMENTED
;
339 SeCopyClientToken(PACCESS_TOKEN Token
,
340 SECURITY_IMPERSONATION_LEVEL Level
,
341 KPROCESSOR_MODE PreviousMode
,
342 PACCESS_TOKEN
* NewToken
)
345 OBJECT_ATTRIBUTES ObjectAttributes
;
349 InitializeObjectAttributes(&ObjectAttributes
,
354 Status
= SepDuplicateToken(Token
,
370 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
371 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
372 IN BOOLEAN RemoteClient
,
373 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
375 TOKEN_TYPE TokenType
;
377 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
380 PACCESS_TOKEN NewToken
;
384 Token
= PsReferenceEffectiveToken(Thread
,
387 &ImpersonationLevel
);
388 if (TokenType
!= TokenImpersonation
)
390 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
394 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
398 ObDereferenceObject(Token
);
400 return(STATUS_UNSUCCESSFUL
);
402 if (ImpersonationLevel
== SecurityAnonymous
||
403 ImpersonationLevel
== SecurityIdentification
||
404 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
408 ObDereferenceObject(Token
);
410 return(STATUS_UNSUCCESSFUL
);
413 Qos
->EffectiveOnly
!= 0)
415 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
419 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
423 if (Qos
->ContextTrackingMode
== 0)
425 ClientContext
->DirectlyAccessClientToken
= FALSE
;
426 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
429 // ObDeleteCapturedInsertInfo(NewToken);
431 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
433 ObDereferenceObject(Token
);
442 ClientContext
->DirectlyAccessClientToken
= TRUE
;
443 if (RemoteClient
!= FALSE
)
445 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
449 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
450 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
451 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
452 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
453 ClientContext
->ServerIsRemote
= RemoteClient
;
454 ClientContext
->ClientToken
= NewToken
;
456 return(STATUS_SUCCESS
);
464 SeCreateClientSecurityFromSubjectContext(
465 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
466 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
467 IN BOOLEAN ServerIsRemote
,
468 OUT PSECURITY_CLIENT_CONTEXT ClientContext
472 return STATUS_NOT_IMPLEMENTED
;
481 IN PACCESS_TOKEN ExistingToken
,
483 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
484 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
485 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
486 OUT PACCESS_TOKEN
* FilteredToken
490 return STATUS_NOT_IMPLEMENTED
;
499 IN PPRIVILEGE_SET Privileges
511 SeImpersonateClientEx(
512 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
513 IN PETHREAD ServerThread OPTIONAL
517 return STATUS_NOT_IMPLEMENTED
;
524 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
525 IN PETHREAD ServerThread OPTIONAL
)
531 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
533 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
537 b
= ClientContext
->DirectAccessEffectiveOnly
;
539 if (ServerThread
== NULL
)
541 ServerThread
= PsGetCurrentThread();
543 PsImpersonateClient(ServerThread
,
544 ClientContext
->ClientToken
,
547 ClientContext
->SecurityQos
.ImpersonationLevel
);
552 SepDeleteToken(PVOID ObjectBody
)
554 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
556 if (AccessToken
->UserAndGroups
)
557 ExFreePool(AccessToken
->UserAndGroups
);
559 if (AccessToken
->Privileges
)
560 ExFreePool(AccessToken
->Privileges
);
562 if (AccessToken
->DefaultDacl
)
563 ExFreePool(AccessToken
->DefaultDacl
);
570 SepInitializeTokenImplementation(VOID
)
573 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
575 ExInitializeResource(&SepTokenLock
);
577 DPRINT("Creating Token Object Type\n");
579 /* Initialize the Token type */
580 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
581 RtlInitUnicodeString(&Name
, L
"Token");
582 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
583 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
584 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
585 ObjectTypeInitializer
.PoolType
= PagedPool
;
586 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
587 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
588 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
589 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &SepTokenObjectType
);
597 NtQueryInformationToken(IN HANDLE TokenHandle
,
598 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
599 OUT PVOID TokenInformation
,
600 IN ULONG TokenInformationLength
,
601 OUT PULONG ReturnLength
)
609 ULONG RequiredLength
;
610 KPROCESSOR_MODE PreviousMode
;
611 NTSTATUS Status
= STATUS_SUCCESS
;
615 PreviousMode
= ExGetPreviousMode();
617 /* Check buffers and class validity */
618 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
619 SeTokenInformationClass
,
620 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
622 TokenInformationLength
,
626 if(!NT_SUCCESS(Status
))
628 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
632 Status
= ObReferenceObjectByHandle(TokenHandle
,
633 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
638 if (NT_SUCCESS(Status
))
640 switch (TokenInformationClass
)
644 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
646 DPRINT("NtQueryInformationToken(TokenUser)\n");
647 RequiredLength
= sizeof(TOKEN_USER
) +
648 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
652 if(TokenInformationLength
>= RequiredLength
)
654 Status
= RtlCopySidAndAttributesArray(1,
655 &Token
->UserAndGroups
[0],
656 RequiredLength
- sizeof(TOKEN_USER
),
664 Status
= STATUS_BUFFER_TOO_SMALL
;
667 if(ReturnLength
!= NULL
)
669 *ReturnLength
= RequiredLength
;
674 Status
= _SEH_GetExceptionCode();
683 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
685 DPRINT("NtQueryInformationToken(TokenGroups)\n");
686 RequiredLength
= sizeof(tg
->GroupCount
) +
687 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
691 if(TokenInformationLength
>= RequiredLength
)
693 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
694 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
695 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
696 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
698 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
699 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
700 &Token
->UserAndGroups
[1],
709 Status
= STATUS_BUFFER_TOO_SMALL
;
712 if(ReturnLength
!= NULL
)
714 *ReturnLength
= RequiredLength
;
719 Status
= _SEH_GetExceptionCode();
726 case TokenPrivileges
:
728 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
730 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
731 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
732 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
736 if(TokenInformationLength
>= RequiredLength
)
738 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
739 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
745 Status
= STATUS_BUFFER_TOO_SMALL
;
748 if(ReturnLength
!= NULL
)
750 *ReturnLength
= RequiredLength
;
755 Status
= _SEH_GetExceptionCode();
765 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
767 DPRINT("NtQueryInformationToken(TokenOwner)\n");
768 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
769 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
773 if(TokenInformationLength
>= RequiredLength
)
775 to
->Owner
= (PSID
)(to
+ 1);
776 Status
= RtlCopySid(SidLen
,
778 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
782 Status
= STATUS_BUFFER_TOO_SMALL
;
785 if(ReturnLength
!= NULL
)
787 *ReturnLength
= RequiredLength
;
792 Status
= _SEH_GetExceptionCode();
799 case TokenPrimaryGroup
:
802 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
804 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
805 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
806 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
810 if(TokenInformationLength
>= RequiredLength
)
812 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
813 Status
= RtlCopySid(SidLen
,
815 Token
->PrimaryGroup
);
819 Status
= STATUS_BUFFER_TOO_SMALL
;
822 if(ReturnLength
!= NULL
)
824 *ReturnLength
= RequiredLength
;
829 Status
= _SEH_GetExceptionCode();
836 case TokenDefaultDacl
:
838 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
840 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
841 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
843 if(Token
->DefaultDacl
!= NULL
)
845 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
850 if(TokenInformationLength
>= RequiredLength
)
852 if(Token
->DefaultDacl
!= NULL
)
854 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
855 RtlCopyMemory(tdd
->DefaultDacl
,
857 Token
->DefaultDacl
->AclSize
);
861 tdd
->DefaultDacl
= NULL
;
866 Status
= STATUS_BUFFER_TOO_SMALL
;
869 if(ReturnLength
!= NULL
)
871 *ReturnLength
= RequiredLength
;
876 Status
= _SEH_GetExceptionCode();
885 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
887 DPRINT("NtQueryInformationToken(TokenSource)\n");
888 RequiredLength
= sizeof(TOKEN_SOURCE
);
892 if(TokenInformationLength
>= RequiredLength
)
894 *ts
= Token
->TokenSource
;
898 Status
= STATUS_BUFFER_TOO_SMALL
;
901 if(ReturnLength
!= NULL
)
903 *ReturnLength
= RequiredLength
;
908 Status
= _SEH_GetExceptionCode();
917 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
919 DPRINT("NtQueryInformationToken(TokenType)\n");
920 RequiredLength
= sizeof(TOKEN_TYPE
);
924 if(TokenInformationLength
>= RequiredLength
)
926 *tt
= Token
->TokenType
;
930 Status
= STATUS_BUFFER_TOO_SMALL
;
933 if(ReturnLength
!= NULL
)
935 *ReturnLength
= RequiredLength
;
940 Status
= _SEH_GetExceptionCode();
947 case TokenImpersonationLevel
:
949 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
951 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
952 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
956 if(TokenInformationLength
>= RequiredLength
)
958 *sil
= Token
->ImpersonationLevel
;
962 Status
= STATUS_BUFFER_TOO_SMALL
;
965 if(ReturnLength
!= NULL
)
967 *ReturnLength
= RequiredLength
;
972 Status
= _SEH_GetExceptionCode();
979 case TokenStatistics
:
981 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
983 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
984 RequiredLength
= sizeof(TOKEN_STATISTICS
);
988 if(TokenInformationLength
>= RequiredLength
)
990 ts
->TokenId
= Token
->TokenId
;
991 ts
->AuthenticationId
= Token
->AuthenticationId
;
992 ts
->ExpirationTime
= Token
->ExpirationTime
;
993 ts
->TokenType
= Token
->TokenType
;
994 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
995 ts
->DynamicCharged
= Token
->DynamicCharged
;
996 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
997 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
998 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
999 ts
->ModifiedId
= Token
->ModifiedId
;
1003 Status
= STATUS_BUFFER_TOO_SMALL
;
1006 if(ReturnLength
!= NULL
)
1008 *ReturnLength
= RequiredLength
;
1013 Status
= _SEH_GetExceptionCode();
1022 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1024 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1025 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1029 if(TokenInformationLength
>= RequiredLength
)
1031 RtlCopyLuid(&to
->OriginatingLogonSession
,
1032 &Token
->AuthenticationId
);
1036 Status
= STATUS_BUFFER_TOO_SMALL
;
1039 if(ReturnLength
!= NULL
)
1041 *ReturnLength
= RequiredLength
;
1046 Status
= _SEH_GetExceptionCode();
1053 case TokenGroupsAndPrivileges
:
1054 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1055 Status
= STATUS_NOT_IMPLEMENTED
;
1058 case TokenRestrictedSids
:
1060 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1062 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1063 RequiredLength
= sizeof(tg
->GroupCount
) +
1064 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1068 if(TokenInformationLength
>= RequiredLength
)
1070 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1071 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1072 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1073 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1075 tg
->GroupCount
= Token
->RestrictedSidCount
;
1076 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1077 Token
->RestrictedSids
,
1086 Status
= STATUS_BUFFER_TOO_SMALL
;
1089 if(ReturnLength
!= NULL
)
1091 *ReturnLength
= RequiredLength
;
1096 Status
= _SEH_GetExceptionCode();
1103 case TokenSandBoxInert
:
1104 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1105 Status
= STATUS_NOT_IMPLEMENTED
;
1108 case TokenSessionId
:
1110 ULONG SessionId
= 0;
1112 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1114 Status
= SeQuerySessionIdToken(Token
,
1117 if(NT_SUCCESS(Status
))
1121 /* buffer size was already verified, no need to check here again */
1122 *(PULONG
)TokenInformation
= SessionId
;
1124 if(ReturnLength
!= NULL
)
1126 *ReturnLength
= sizeof(ULONG
);
1131 Status
= _SEH_GetExceptionCode();
1140 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1141 Status
= STATUS_INVALID_INFO_CLASS
;
1145 ObDereferenceObject(Token
);
1156 SeQueryInformationToken(
1157 IN PACCESS_TOKEN Token
,
1158 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1159 OUT PVOID
*TokenInformation
1163 return STATUS_NOT_IMPLEMENTED
;
1171 SeQuerySessionIdToken(
1172 IN PACCESS_TOKEN Token
,
1173 IN PULONG pSessionId
1176 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1177 return STATUS_SUCCESS
;
1181 * NtSetTokenInformation: Partly implemented.
1183 * TokenOrigin, TokenDefaultDacl
1187 NtSetInformationToken(IN HANDLE TokenHandle
,
1188 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1189 OUT PVOID TokenInformation
,
1190 IN ULONG TokenInformationLength
)
1193 KPROCESSOR_MODE PreviousMode
;
1194 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1195 NTSTATUS Status
= STATUS_SUCCESS
;
1199 PreviousMode
= ExGetPreviousMode();
1201 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1202 SeTokenInformationClass
,
1203 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1205 TokenInformationLength
,
1208 if(!NT_SUCCESS(Status
))
1210 /* Invalid buffers */
1211 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1215 if(TokenInformationClass
== TokenSessionId
)
1217 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1220 Status
= ObReferenceObjectByHandle(TokenHandle
,
1226 if (NT_SUCCESS(Status
))
1228 switch (TokenInformationClass
)
1232 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1234 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1235 PSID InputSid
= NULL
;
1239 InputSid
= to
->Owner
;
1243 Status
= _SEH_GetExceptionCode();
1247 if(NT_SUCCESS(Status
))
1251 Status
= SepCaptureSid(InputSid
,
1256 if(NT_SUCCESS(Status
))
1258 RtlCopySid(RtlLengthSid(CapturedSid
),
1259 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1261 SepReleaseSid(CapturedSid
,
1269 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1274 case TokenPrimaryGroup
:
1276 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1278 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1279 PSID InputSid
= NULL
;
1283 InputSid
= tpg
->PrimaryGroup
;
1287 Status
= _SEH_GetExceptionCode();
1291 if(NT_SUCCESS(Status
))
1295 Status
= SepCaptureSid(InputSid
,
1300 if(NT_SUCCESS(Status
))
1302 RtlCopySid(RtlLengthSid(CapturedSid
),
1303 Token
->PrimaryGroup
,
1305 SepReleaseSid(CapturedSid
,
1313 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1318 case TokenDefaultDacl
:
1320 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1322 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1323 PACL InputAcl
= NULL
;
1327 InputAcl
= tdd
->DefaultDacl
;
1331 Status
= _SEH_GetExceptionCode();
1335 if(NT_SUCCESS(Status
))
1337 if(InputAcl
!= NULL
)
1341 /* capture and copy the dacl */
1342 Status
= SepCaptureAcl(InputAcl
,
1347 if(NT_SUCCESS(Status
))
1349 /* free the previous dacl if present */
1350 if(Token
->DefaultDacl
!= NULL
)
1352 ExFreePool(Token
->DefaultDacl
);
1355 /* set the new dacl */
1356 Token
->DefaultDacl
= CapturedAcl
;
1361 /* clear and free the default dacl if present */
1362 if(Token
->DefaultDacl
!= NULL
)
1364 ExFreePool(Token
->DefaultDacl
);
1365 Token
->DefaultDacl
= NULL
;
1372 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1377 case TokenSessionId
:
1379 ULONG SessionId
= 0;
1383 /* buffer size was already verified, no need to check here again */
1384 SessionId
= *(PULONG
)TokenInformation
;
1388 Status
= _SEH_GetExceptionCode();
1392 if(NT_SUCCESS(Status
))
1394 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1397 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1401 Token
->SessionId
= SessionId
;
1408 Status
= STATUS_NOT_IMPLEMENTED
;
1413 ObDereferenceObject(Token
);
1423 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1424 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1425 * is correct either. -Gunnar
1426 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1429 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1430 IN ACCESS_MASK DesiredAccess
,
1431 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1432 IN BOOLEAN EffectiveOnly
,
1433 IN TOKEN_TYPE TokenType
,
1434 OUT PHANDLE NewTokenHandle
)
1436 KPROCESSOR_MODE PreviousMode
;
1440 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1442 NTSTATUS Status
= STATUS_SUCCESS
;
1446 PreviousMode
= KeGetPreviousMode();
1448 if(PreviousMode
!= KernelMode
)
1452 ProbeForWriteHandle(NewTokenHandle
);
1456 Status
= _SEH_GetExceptionCode();
1460 if(!NT_SUCCESS(Status
))
1466 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1470 &CapturedSecurityQualityOfService
,
1472 if(!NT_SUCCESS(Status
))
1474 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1478 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1484 if (NT_SUCCESS(Status
))
1486 Status
= SepDuplicateToken(Token
,
1490 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1494 ObDereferenceObject(Token
);
1496 if (NT_SUCCESS(Status
))
1498 Status
= ObInsertObject((PVOID
)NewToken
,
1505 ObDereferenceObject(NewToken
);
1507 if (NT_SUCCESS(Status
))
1511 *NewTokenHandle
= hToken
;
1515 Status
= _SEH_GetExceptionCode();
1522 /* free the captured structure */
1523 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1531 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1533 BOOLEAN ResetToDefault
,
1534 PSID_AND_ATTRIBUTES Groups
,
1536 KPROCESSOR_MODE PreviousMode
,
1547 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1548 IN BOOLEAN ResetToDefault
,
1549 IN PTOKEN_GROUPS NewState
,
1550 IN ULONG BufferLength
,
1551 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1552 OUT PULONG ReturnLength
)
1556 PACCESS_TOKEN Token
;
1563 Status
= ObReferenceObjectByHandle(TokenHandle
,
1571 SepAdjustGroups(Token
,
1583 return(STATUS_NOT_IMPLEMENTED
);
1590 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1592 KPROCESSOR_MODE PreviousMode
,
1593 ULONG PrivilegeCount
,
1594 PLUID_AND_ATTRIBUTES Privileges
,
1595 PTOKEN_PRIVILEGES
* PreviousState
,
1604 if (Token
->PrivilegeCount
> 0)
1606 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1608 if (PreviousMode
!= KernelMode
)
1610 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1614 if (PreviousState
!= NULL
)
1616 memcpy(&PreviousState
[i
],
1617 &Token
->Privileges
[i
],
1618 sizeof(LUID_AND_ATTRIBUTES
));
1620 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1627 if (PreviousMode
!= KernelMode
)
1629 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1633 if (PrivilegeCount
<= ?)
1646 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1647 IN BOOLEAN DisableAllPrivileges
,
1648 IN PTOKEN_PRIVILEGES NewState
,
1649 IN ULONG BufferLength
,
1650 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1651 OUT PULONG ReturnLength OPTIONAL
)
1653 // PLUID_AND_ATTRIBUTES Privileges;
1654 KPROCESSOR_MODE PreviousMode
;
1655 ULONG PrivilegeCount
;
1671 DPRINT ("NtAdjustPrivilegesToken() called\n");
1673 // PrivilegeCount = NewState->PrivilegeCount;
1674 PreviousMode
= KeGetPreviousMode ();
1675 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1685 Status
= ObReferenceObjectByHandle (TokenHandle
,
1686 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1691 if (!NT_SUCCESS(Status
))
1693 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1694 // SeReleaseLuidAndAttributesArray(Privileges,
1702 SepAdjustPrivileges(Token
,
1713 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1714 sizeof(LUID_AND_ATTRIBUTES
);
1716 if (PreviousState
!= NULL
)
1717 PreviousState
->PrivilegeCount
= 0;
1720 if (DisableAllPrivileges
== TRUE
)
1722 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1724 if (Token
->Privileges
[i
].Attributes
!= 0)
1726 DPRINT ("Attributes differ\n");
1728 /* Save current privilege */
1729 if (PreviousState
!= NULL
)
1731 if (k
< PrivilegeCount
)
1733 PreviousState
->PrivilegeCount
++;
1734 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1735 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1739 /* FIXME: Should revert all the changes, calculate how
1740 * much space would be needed, set ResultLength
1741 * accordingly and fail.
1747 /* Update current privlege */
1748 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1751 Status
= STATUS_SUCCESS
;
1756 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1758 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1760 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1761 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1763 DPRINT ("Found privilege\n");
1765 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1766 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1768 DPRINT ("Attributes differ\n");
1769 DPRINT ("Current attributes %lx desired attributes %lx\n",
1770 Token
->Privileges
[i
].Attributes
,
1771 NewState
->Privileges
[j
].Attributes
);
1773 /* Save current privilege */
1774 if (PreviousState
!= NULL
)
1776 if (k
< PrivilegeCount
)
1778 PreviousState
->PrivilegeCount
++;
1779 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1780 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1784 /* FIXME: Should revert all the changes, calculate how
1785 * much space would be needed, set ResultLength
1786 * accordingly and fail.
1792 /* Update current privlege */
1793 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1794 Token
->Privileges
[i
].Attributes
|=
1795 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1796 DPRINT ("New attributes %lx\n",
1797 Token
->Privileges
[i
].Attributes
);
1803 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1806 if (ReturnLength
!= NULL
)
1808 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1809 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1812 ObDereferenceObject (Token
);
1814 // SeReleaseLuidAndAttributesArray(Privileges,
1818 DPRINT ("NtAdjustPrivilegesToken() done\n");
1825 SepCreateSystemProcessToken(VOID
)
1830 ULONG uLocalSystemLength
;
1832 ULONG uAuthUserLength
;
1833 ULONG uAdminsLength
;
1839 uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1840 uWorldLength
= RtlLengthSid(SeWorldSid
);
1841 uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1842 uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1845 * Initialize the token
1847 Status
= ObCreateObject(KernelMode
,
1855 (PVOID
*)&AccessToken
);
1856 if (!NT_SUCCESS(Status
))
1860 Status
= ObInsertObject(AccessToken
,
1867 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1868 if (!NT_SUCCESS(Status
))
1870 ObDereferenceObject(AccessToken
);
1874 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1875 if (!NT_SUCCESS(Status
))
1877 ObDereferenceObject(AccessToken
);
1881 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1882 if (!NT_SUCCESS(Status
))
1884 ObDereferenceObject(AccessToken
);
1888 AccessToken
->TokenLock
= &SepTokenLock
;
1890 AccessToken
->TokenType
= TokenPrimary
;
1891 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1892 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1893 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1894 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1895 AccessToken
->ExpirationTime
.QuadPart
= -1;
1896 AccessToken
->UserAndGroupCount
= 4;
1898 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1899 uSize
+= uLocalSystemLength
;
1900 uSize
+= uWorldLength
;
1901 uSize
+= uAuthUserLength
;
1902 uSize
+= uAdminsLength
;
1904 AccessToken
->UserAndGroups
=
1905 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1907 TAG('T', 'O', 'K', 'u'));
1908 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1911 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1912 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1913 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1914 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1916 AccessToken
->DefaultOwnerIndex
= i
;
1917 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1918 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1919 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1920 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1921 SidArea
= (char*)SidArea
+ uAdminsLength
;
1923 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1924 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1925 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1926 SidArea
= (char*)SidArea
+ uWorldLength
;
1928 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1929 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1930 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1931 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1933 AccessToken
->PrivilegeCount
= 20;
1935 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1936 AccessToken
->Privileges
=
1937 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1939 TAG('T', 'O', 'K', 'p'));
1942 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1943 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1945 AccessToken
->Privileges
[i
].Attributes
= 0;
1946 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1948 AccessToken
->Privileges
[i
].Attributes
= 0;
1949 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1951 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1952 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1954 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1955 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1957 AccessToken
->Privileges
[i
].Attributes
= 0;
1958 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1960 AccessToken
->Privileges
[i
].Attributes
= 0;
1961 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1963 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1964 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1966 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1967 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1969 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1970 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1972 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1973 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1975 AccessToken
->Privileges
[i
].Attributes
= 0;
1976 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1978 AccessToken
->Privileges
[i
].Attributes
= 0;
1979 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1981 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1982 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1984 AccessToken
->Privileges
[i
].Attributes
= 0;
1985 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1987 AccessToken
->Privileges
[i
].Attributes
= 0;
1988 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1990 AccessToken
->Privileges
[i
].Attributes
= 0;
1991 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1993 AccessToken
->Privileges
[i
].Attributes
= 0;
1994 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1996 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1997 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1999 AccessToken
->Privileges
[i
].Attributes
= 0;
2000 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
2002 AccessToken
->Privileges
[i
].Attributes
= 0;
2003 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
2005 AccessToken
->Privileges
[i
].Attributes
= 0;
2006 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
2011 uSize
= sizeof(ACL
);
2012 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
2013 uSize
+= sizeof(ACE
) + uAdminsLength
;
2014 uSize
= (uSize
& (~3)) + 8;
2015 AccessToken
->DefaultDacl
=
2016 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2018 TAG('T', 'O', 'K', 'd'));
2019 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
2020 if ( NT_SUCCESS(Status
) )
2022 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
2025 if ( NT_SUCCESS(Status
) )
2027 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
2030 if ( ! NT_SUCCESS(Status
) )
2032 ObDereferenceObject(AccessToken
);
2041 NtCreateToken(OUT PHANDLE TokenHandle
,
2042 IN ACCESS_MASK DesiredAccess
,
2043 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2044 IN TOKEN_TYPE TokenType
,
2045 IN PLUID AuthenticationId
,
2046 IN PLARGE_INTEGER ExpirationTime
,
2047 IN PTOKEN_USER TokenUser
,
2048 IN PTOKEN_GROUPS TokenGroups
,
2049 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2050 IN PTOKEN_OWNER TokenOwner
,
2051 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2052 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2053 IN PTOKEN_SOURCE TokenSource
)
2062 ULONG nTokenPrivileges
= 0;
2063 LARGE_INTEGER LocalExpirationTime
= {};
2064 KPROCESSOR_MODE PreviousMode
;
2065 NTSTATUS Status
= STATUS_SUCCESS
;
2069 PreviousMode
= ExGetPreviousMode();
2071 if(PreviousMode
!= KernelMode
)
2075 ProbeForWriteHandle(TokenHandle
);
2076 ProbeForRead(AuthenticationId
,
2079 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2080 ProbeForRead(TokenUser
,
2083 ProbeForRead(TokenGroups
,
2084 sizeof(TOKEN_GROUPS
),
2086 ProbeForRead(TokenPrivileges
,
2087 sizeof(TOKEN_PRIVILEGES
),
2089 ProbeForRead(TokenOwner
,
2090 sizeof(TOKEN_OWNER
),
2092 ProbeForRead(TokenPrimaryGroup
,
2093 sizeof(TOKEN_PRIMARY_GROUP
),
2095 ProbeForRead(TokenDefaultDacl
,
2096 sizeof(TOKEN_DEFAULT_DACL
),
2098 ProbeForRead(TokenSource
,
2099 sizeof(TOKEN_SOURCE
),
2101 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2105 Status
= _SEH_GetExceptionCode();
2109 if(!NT_SUCCESS(Status
))
2116 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2117 LocalExpirationTime
= *ExpirationTime
;
2120 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2121 if (!NT_SUCCESS(Status
))
2124 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2125 if (!NT_SUCCESS(Status
))
2128 Status
= ObCreateObject(PreviousMode
,
2136 (PVOID
*)&AccessToken
);
2137 if (!NT_SUCCESS(Status
))
2139 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2143 AccessToken
->TokenLock
= &SepTokenLock
;
2145 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2146 &TokenSource
->SourceIdentifier
);
2147 memcpy(AccessToken
->TokenSource
.SourceName
,
2148 TokenSource
->SourceName
,
2149 sizeof(TokenSource
->SourceName
));
2151 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2152 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2153 AccessToken
->ExpirationTime
= *ExpirationTime
;
2154 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2156 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2157 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2158 AccessToken
->UserAndGroups
= 0;
2159 AccessToken
->Privileges
= 0;
2161 AccessToken
->TokenType
= TokenType
;
2162 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2163 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2166 * Normally we would just point these members into the variable information
2167 * area; however, our ObCreateObject() call can't allocate a variable information
2168 * area, so we allocate them seperately and provide a destroy function.
2171 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2172 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2173 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2174 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2176 AccessToken
->UserAndGroups
=
2177 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2179 TAG('T', 'O', 'K', 'u'));
2181 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2183 Status
= RtlCopySidAndAttributesArray(1,
2186 AccessToken
->UserAndGroups
,
2190 if (NT_SUCCESS(Status
))
2192 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2193 TokenGroups
->Groups
,
2195 &AccessToken
->UserAndGroups
[1],
2201 if (NT_SUCCESS(Status
))
2203 Status
= SepFindPrimaryGroupAndDefaultOwner(
2205 TokenPrimaryGroup
->PrimaryGroup
,
2209 if (NT_SUCCESS(Status
))
2211 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2212 AccessToken
->Privileges
=
2213 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2215 TAG('T', 'O', 'K', 'p'));
2217 if (PreviousMode
!= KernelMode
)
2221 RtlCopyMemory(AccessToken
->Privileges
,
2222 TokenPrivileges
->Privileges
,
2223 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2227 Status
= _SEH_GetExceptionCode();
2233 RtlCopyMemory(AccessToken
->Privileges
,
2234 TokenPrivileges
->Privileges
,
2235 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2239 if (NT_SUCCESS(Status
))
2241 AccessToken
->DefaultDacl
=
2242 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2243 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2244 TAG('T', 'O', 'K', 'd'));
2245 memcpy(AccessToken
->DefaultDacl
,
2246 TokenDefaultDacl
->DefaultDacl
,
2247 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2250 Status
= ObInsertObject ((PVOID
)AccessToken
,
2256 if (!NT_SUCCESS(Status
))
2258 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2261 ObDereferenceObject(AccessToken
);
2263 if (NT_SUCCESS(Status
))
2267 *TokenHandle
= hToken
;
2271 Status
= _SEH_GetExceptionCode();
2284 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
2289 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
2291 return STATUS_SUCCESS
;
2298 SECURITY_IMPERSONATION_LEVEL
2300 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
2304 return ((PTOKEN
)Token
)->ImpersonationLevel
;
2312 SeTokenType(IN PACCESS_TOKEN Token
)
2316 return ((PTOKEN
)Token
)->TokenType
;
2326 IN PACCESS_TOKEN Token
2338 SeTokenIsRestricted(
2339 IN PACCESS_TOKEN Token
2351 SeTokenIsWriteRestricted(
2352 IN PACCESS_TOKEN Token
2365 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2366 IN ACCESS_MASK DesiredAccess
,
2367 IN BOOLEAN OpenAsSelf
,
2368 IN ULONG HandleAttributes
,
2369 OUT PHANDLE TokenHandle
)
2373 PTOKEN Token
, NewToken
, PrimaryToken
;
2374 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2375 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2376 SE_IMPERSONATION_STATE ImpersonationState
;
2377 OBJECT_ATTRIBUTES ObjectAttributes
;
2378 SECURITY_DESCRIPTOR SecurityDescriptor
;
2380 KPROCESSOR_MODE PreviousMode
;
2381 NTSTATUS Status
= STATUS_SUCCESS
;
2385 PreviousMode
= ExGetPreviousMode();
2387 if(PreviousMode
!= KernelMode
)
2391 ProbeForWriteHandle(TokenHandle
);
2395 Status
= _SEH_GetExceptionCode();
2399 if(!NT_SUCCESS(Status
))
2406 * At first open the thread token for information access and verify
2407 * that the token associated with thread is valid.
2410 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2411 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2413 if (!NT_SUCCESS(Status
))
2418 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2419 &ImpersonationLevel
);
2422 ObfDereferenceObject(Thread
);
2423 return STATUS_NO_TOKEN
;
2426 ObDereferenceObject(Thread
);
2428 if (ImpersonationLevel
== SecurityAnonymous
)
2430 ObfDereferenceObject(Token
);
2431 return STATUS_CANT_OPEN_ANONYMOUS
;
2435 * Revert to self if OpenAsSelf is specified.
2440 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2445 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2446 PsThreadType
, PreviousMode
,
2447 (PVOID
*)&Thread
, NULL
);
2448 if (!NT_SUCCESS(Status
))
2450 ObfDereferenceObject(Token
);
2453 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2458 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2459 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2460 ObfDereferenceObject(PrimaryToken
);
2461 ObfDereferenceObject(Thread
);
2462 if (!NT_SUCCESS(Status
))
2464 ObfDereferenceObject(Token
);
2467 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2472 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2473 SECURITY_DESCRIPTOR_REVISION
);
2474 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2477 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2478 NULL
, &SecurityDescriptor
);
2480 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2481 TokenImpersonation
, ImpersonationLevel
,
2482 KernelMode
, &NewToken
);
2484 if (!NT_SUCCESS(Status
))
2486 ObfDereferenceObject(Token
);
2489 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2494 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2497 ObfDereferenceObject(NewToken
);
2501 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2502 NULL
, DesiredAccess
, SepTokenObjectType
,
2503 PreviousMode
, &hToken
);
2506 ObfDereferenceObject(Token
);
2510 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2513 if(NT_SUCCESS(Status
))
2517 *TokenHandle
= hToken
;
2521 Status
= _SEH_GetExceptionCode();
2533 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2534 IN ACCESS_MASK DesiredAccess
,
2535 IN BOOLEAN OpenAsSelf
,
2536 OUT PHANDLE TokenHandle
)
2538 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,