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 *****************************************************************/
71 VOID
SepFreeProxyData(PVOID ProxyData
)
76 NTSTATUS
SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
79 return(STATUS_NOT_IMPLEMENTED
);
83 SeExchangePrimaryToken(PEPROCESS Process
,
84 PACCESS_TOKEN NewTokenP
,
85 PACCESS_TOKEN
* OldTokenP
)
88 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
92 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
93 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
95 /* Mark new token in use */
96 NewToken
->TokenInUse
= 1;
98 /* Reference the New Token */
99 ObReferenceObject(NewToken
);
101 /* Replace the old with the new */
102 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
104 /* Mark the Old Token as free */
105 OldToken
->TokenInUse
= 0;
107 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
108 return STATUS_SUCCESS
;
112 SeDeassignPrimaryToken(PEPROCESS Process
)
116 /* Remove the Token */
117 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
119 /* Mark the Old Token as free */
120 OldToken
->TokenInUse
= 0;
124 RtlLengthSidAndAttributes(ULONG Count
,
125 PSID_AND_ATTRIBUTES Src
)
132 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
133 for (i
= 0; i
< Count
; i
++)
134 uLength
+= RtlLengthSid(Src
[i
].Sid
);
141 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
147 Token
->PrimaryGroup
= 0;
151 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
154 /* Validate and set the primary group and user pointers */
155 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
158 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
160 Token
->DefaultOwnerIndex
= i
;
163 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
165 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
169 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
171 return(STATUS_INVALID_OWNER
);
174 if (Token
->PrimaryGroup
== 0)
176 return(STATUS_INVALID_PRIMARY_GROUP
);
179 return(STATUS_SUCCESS
);
185 SepDuplicateToken(PTOKEN Token
,
186 POBJECT_ATTRIBUTES ObjectAttributes
,
187 BOOLEAN EffectiveOnly
,
188 TOKEN_TYPE TokenType
,
189 SECURITY_IMPERSONATION_LEVEL Level
,
190 KPROCESSOR_MODE PreviousMode
,
191 PTOKEN
* NewAccessToken
)
201 Status
= ObCreateObject(PreviousMode
,
209 (PVOID
*)&AccessToken
);
210 if (!NT_SUCCESS(Status
))
212 DPRINT1("ObCreateObject() failed (Status %lx)\n");
216 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
217 if (!NT_SUCCESS(Status
))
219 ObDereferenceObject(AccessToken
);
223 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
224 if (!NT_SUCCESS(Status
))
226 ObDereferenceObject(AccessToken
);
230 AccessToken
->TokenLock
= &SepTokenLock
;
232 AccessToken
->TokenInUse
= 0;
233 AccessToken
->TokenType
= TokenType
;
234 AccessToken
->ImpersonationLevel
= Level
;
235 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
237 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
238 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
239 memcpy(AccessToken
->TokenSource
.SourceName
,
240 Token
->TokenSource
.SourceName
,
241 sizeof(Token
->TokenSource
.SourceName
));
242 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
243 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
244 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
246 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
247 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
248 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
250 AccessToken
->UserAndGroups
=
251 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
253 TAG('T', 'O', 'K', 'u'));
255 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
257 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
258 Token
->UserAndGroups
,
260 AccessToken
->UserAndGroups
,
264 if (NT_SUCCESS(Status
))
266 Status
= SepFindPrimaryGroupAndDefaultOwner(
272 if (NT_SUCCESS(Status
))
274 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
276 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
277 AccessToken
->Privileges
=
278 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
280 TAG('T', 'O', 'K', 'p'));
282 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
284 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
285 &Token
->Privileges
[i
].Luid
);
286 AccessToken
->Privileges
[i
].Attributes
=
287 Token
->Privileges
[i
].Attributes
;
290 if ( Token
->DefaultDacl
)
292 AccessToken
->DefaultDacl
=
293 (PACL
) ExAllocatePoolWithTag(PagedPool
,
294 Token
->DefaultDacl
->AclSize
,
295 TAG('T', 'O', 'K', 'd'));
296 memcpy(AccessToken
->DefaultDacl
,
298 Token
->DefaultDacl
->AclSize
);
302 AccessToken
->DefaultDacl
= 0;
306 if ( NT_SUCCESS(Status
) )
308 *NewAccessToken
= AccessToken
;
309 return(STATUS_SUCCESS
);
312 ObDereferenceObject(AccessToken
);
322 PACCESS_STATE AccessState
,
323 PPRIVILEGE_SET Privileges
327 return STATUS_NOT_IMPLEMENTED
;
332 SeCopyClientToken(PACCESS_TOKEN Token
,
333 SECURITY_IMPERSONATION_LEVEL Level
,
334 KPROCESSOR_MODE PreviousMode
,
335 PACCESS_TOKEN
* NewToken
)
338 OBJECT_ATTRIBUTES ObjectAttributes
;
342 InitializeObjectAttributes(&ObjectAttributes
,
347 Status
= SepDuplicateToken(Token
,
363 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
364 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
365 IN BOOLEAN RemoteClient
,
366 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
368 TOKEN_TYPE TokenType
;
370 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
373 PACCESS_TOKEN NewToken
;
377 Token
= PsReferenceEffectiveToken(Thread
,
380 &ImpersonationLevel
);
381 if (TokenType
!= TokenImpersonation
)
383 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
387 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
391 ObDereferenceObject(Token
);
393 return(STATUS_UNSUCCESSFUL
);
395 if (ImpersonationLevel
== SecurityAnonymous
||
396 ImpersonationLevel
== SecurityIdentification
||
397 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
401 ObDereferenceObject(Token
);
403 return(STATUS_UNSUCCESSFUL
);
406 Qos
->EffectiveOnly
!= 0)
408 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
412 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
416 if (Qos
->ContextTrackingMode
== 0)
418 ClientContext
->DirectlyAccessClientToken
= FALSE
;
419 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
422 // ObDeleteCapturedInsertInfo(NewToken);
424 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
426 ObDereferenceObject(Token
);
435 ClientContext
->DirectlyAccessClientToken
= TRUE
;
436 if (RemoteClient
!= FALSE
)
438 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
442 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
443 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
444 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
445 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
446 ClientContext
->ServerIsRemote
= RemoteClient
;
447 ClientContext
->ClientToken
= NewToken
;
449 return(STATUS_SUCCESS
);
457 SeCreateClientSecurityFromSubjectContext(
458 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
459 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
460 IN BOOLEAN ServerIsRemote
,
461 OUT PSECURITY_CLIENT_CONTEXT ClientContext
465 return STATUS_NOT_IMPLEMENTED
;
474 IN PACCESS_TOKEN ExistingToken
,
476 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
477 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
478 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
479 OUT PACCESS_TOKEN
* FilteredToken
483 return STATUS_NOT_IMPLEMENTED
;
492 IN PPRIVILEGE_SET Privileges
504 SeImpersonateClientEx(
505 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
506 IN PETHREAD ServerThread OPTIONAL
510 return STATUS_NOT_IMPLEMENTED
;
517 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
518 IN PETHREAD ServerThread OPTIONAL
)
524 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
526 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
530 b
= ClientContext
->DirectAccessEffectiveOnly
;
532 if (ServerThread
== NULL
)
534 ServerThread
= PsGetCurrentThread();
536 PsImpersonateClient(ServerThread
,
537 ClientContext
->ClientToken
,
540 ClientContext
->SecurityQos
.ImpersonationLevel
);
545 SepDeleteToken(PVOID ObjectBody
)
547 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
549 if (AccessToken
->UserAndGroups
)
550 ExFreePool(AccessToken
->UserAndGroups
);
552 if (AccessToken
->Privileges
)
553 ExFreePool(AccessToken
->Privileges
);
555 if (AccessToken
->DefaultDacl
)
556 ExFreePool(AccessToken
->DefaultDacl
);
561 SepInitializeTokenImplementation(VOID
)
564 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
566 ExInitializeResource(&SepTokenLock
);
568 DPRINT("Creating Token Object Type\n");
570 /* Initialize the Token type */
571 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
572 RtlInitUnicodeString(&Name
, L
"Token");
573 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
574 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
575 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
576 ObjectTypeInitializer
.PoolType
= PagedPool
;
577 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
578 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
579 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
580 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &SepTokenObjectType
);
588 NtQueryInformationToken(IN HANDLE TokenHandle
,
589 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
590 OUT PVOID TokenInformation
,
591 IN ULONG TokenInformationLength
,
592 OUT PULONG ReturnLength
)
600 ULONG RequiredLength
;
601 KPROCESSOR_MODE PreviousMode
;
602 NTSTATUS Status
= STATUS_SUCCESS
;
606 PreviousMode
= ExGetPreviousMode();
608 /* Check buffers and class validity */
609 DefaultQueryInfoBufferCheck(TokenInformationClass
,
610 SeTokenInformationClass
,
612 TokenInformationLength
,
617 if(!NT_SUCCESS(Status
))
619 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
623 Status
= ObReferenceObjectByHandle(TokenHandle
,
624 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
629 if (NT_SUCCESS(Status
))
631 switch (TokenInformationClass
)
635 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
637 DPRINT("NtQueryInformationToken(TokenUser)\n");
638 RequiredLength
= sizeof(TOKEN_USER
) +
639 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
643 if(TokenInformationLength
>= RequiredLength
)
645 Status
= RtlCopySidAndAttributesArray(1,
646 &Token
->UserAndGroups
[0],
647 RequiredLength
- sizeof(TOKEN_USER
),
655 Status
= STATUS_BUFFER_TOO_SMALL
;
658 if(ReturnLength
!= NULL
)
660 *ReturnLength
= RequiredLength
;
665 Status
= _SEH_GetExceptionCode();
674 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
676 DPRINT("NtQueryInformationToken(TokenGroups)\n");
677 RequiredLength
= sizeof(tg
->GroupCount
) +
678 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
682 if(TokenInformationLength
>= RequiredLength
)
684 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
685 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
686 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
687 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
689 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
690 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
691 &Token
->UserAndGroups
[1],
700 Status
= STATUS_BUFFER_TOO_SMALL
;
703 if(ReturnLength
!= NULL
)
705 *ReturnLength
= RequiredLength
;
710 Status
= _SEH_GetExceptionCode();
717 case TokenPrivileges
:
719 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
721 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
722 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
723 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
727 if(TokenInformationLength
>= RequiredLength
)
729 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
730 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
736 Status
= STATUS_BUFFER_TOO_SMALL
;
739 if(ReturnLength
!= NULL
)
741 *ReturnLength
= RequiredLength
;
746 Status
= _SEH_GetExceptionCode();
756 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
758 DPRINT("NtQueryInformationToken(TokenOwner)\n");
759 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
760 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
764 if(TokenInformationLength
>= RequiredLength
)
766 to
->Owner
= (PSID
)(to
+ 1);
767 Status
= RtlCopySid(SidLen
,
769 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
773 Status
= STATUS_BUFFER_TOO_SMALL
;
776 if(ReturnLength
!= NULL
)
778 *ReturnLength
= RequiredLength
;
783 Status
= _SEH_GetExceptionCode();
790 case TokenPrimaryGroup
:
793 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
795 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
796 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
797 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
801 if(TokenInformationLength
>= RequiredLength
)
803 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
804 Status
= RtlCopySid(SidLen
,
806 Token
->PrimaryGroup
);
810 Status
= STATUS_BUFFER_TOO_SMALL
;
813 if(ReturnLength
!= NULL
)
815 *ReturnLength
= RequiredLength
;
820 Status
= _SEH_GetExceptionCode();
827 case TokenDefaultDacl
:
829 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
831 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
832 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
834 if(Token
->DefaultDacl
!= NULL
)
836 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
841 if(TokenInformationLength
>= RequiredLength
)
843 if(Token
->DefaultDacl
!= NULL
)
845 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
846 RtlCopyMemory(tdd
->DefaultDacl
,
848 Token
->DefaultDacl
->AclSize
);
852 tdd
->DefaultDacl
= NULL
;
857 Status
= STATUS_BUFFER_TOO_SMALL
;
860 if(ReturnLength
!= NULL
)
862 *ReturnLength
= RequiredLength
;
867 Status
= _SEH_GetExceptionCode();
876 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
878 DPRINT("NtQueryInformationToken(TokenSource)\n");
879 RequiredLength
= sizeof(TOKEN_SOURCE
);
883 if(TokenInformationLength
>= RequiredLength
)
885 *ts
= Token
->TokenSource
;
889 Status
= STATUS_BUFFER_TOO_SMALL
;
892 if(ReturnLength
!= NULL
)
894 *ReturnLength
= RequiredLength
;
899 Status
= _SEH_GetExceptionCode();
908 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
910 DPRINT("NtQueryInformationToken(TokenType)\n");
911 RequiredLength
= sizeof(TOKEN_TYPE
);
915 if(TokenInformationLength
>= RequiredLength
)
917 *tt
= Token
->TokenType
;
921 Status
= STATUS_BUFFER_TOO_SMALL
;
924 if(ReturnLength
!= NULL
)
926 *ReturnLength
= RequiredLength
;
931 Status
= _SEH_GetExceptionCode();
938 case TokenImpersonationLevel
:
940 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
942 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
943 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
947 if(TokenInformationLength
>= RequiredLength
)
949 *sil
= Token
->ImpersonationLevel
;
953 Status
= STATUS_BUFFER_TOO_SMALL
;
956 if(ReturnLength
!= NULL
)
958 *ReturnLength
= RequiredLength
;
963 Status
= _SEH_GetExceptionCode();
970 case TokenStatistics
:
972 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
974 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
975 RequiredLength
= sizeof(TOKEN_STATISTICS
);
979 if(TokenInformationLength
>= RequiredLength
)
981 ts
->TokenId
= Token
->TokenId
;
982 ts
->AuthenticationId
= Token
->AuthenticationId
;
983 ts
->ExpirationTime
= Token
->ExpirationTime
;
984 ts
->TokenType
= Token
->TokenType
;
985 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
986 ts
->DynamicCharged
= Token
->DynamicCharged
;
987 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
988 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
989 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
990 ts
->ModifiedId
= Token
->ModifiedId
;
994 Status
= STATUS_BUFFER_TOO_SMALL
;
997 if(ReturnLength
!= NULL
)
999 *ReturnLength
= RequiredLength
;
1004 Status
= _SEH_GetExceptionCode();
1013 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1015 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1016 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1020 if(TokenInformationLength
>= RequiredLength
)
1022 RtlCopyLuid(&to
->OriginatingLogonSession
,
1023 &Token
->AuthenticationId
);
1027 Status
= STATUS_BUFFER_TOO_SMALL
;
1030 if(ReturnLength
!= NULL
)
1032 *ReturnLength
= RequiredLength
;
1037 Status
= _SEH_GetExceptionCode();
1044 case TokenGroupsAndPrivileges
:
1045 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1046 Status
= STATUS_NOT_IMPLEMENTED
;
1049 case TokenRestrictedSids
:
1050 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
1051 Status
= STATUS_NOT_IMPLEMENTED
;
1054 case TokenSandBoxInert
:
1055 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1056 Status
= STATUS_NOT_IMPLEMENTED
;
1059 case TokenSessionId
:
1061 ULONG SessionId
= 0;
1063 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1065 Status
= SeQuerySessionIdToken(Token
,
1068 if(NT_SUCCESS(Status
))
1072 /* buffer size was already verified, no need to check here again */
1073 *(PULONG
)TokenInformation
= SessionId
;
1075 if(ReturnLength
!= NULL
)
1077 *ReturnLength
= sizeof(ULONG
);
1082 Status
= _SEH_GetExceptionCode();
1091 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1092 Status
= STATUS_INVALID_INFO_CLASS
;
1096 ObDereferenceObject(Token
);
1107 SeQueryInformationToken(
1108 IN PACCESS_TOKEN Token
,
1109 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1110 OUT PVOID
*TokenInformation
1114 return STATUS_NOT_IMPLEMENTED
;
1122 SeQuerySessionIdToken(
1123 IN PACCESS_TOKEN Token
,
1124 IN PULONG pSessionId
1127 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1128 return STATUS_SUCCESS
;
1132 * NtSetTokenInformation: Partly implemented.
1134 * TokenOrigin, TokenDefaultDacl
1138 NtSetInformationToken(IN HANDLE TokenHandle
,
1139 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1140 OUT PVOID TokenInformation
,
1141 IN ULONG TokenInformationLength
)
1144 KPROCESSOR_MODE PreviousMode
;
1145 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1146 NTSTATUS Status
= STATUS_SUCCESS
;
1150 PreviousMode
= ExGetPreviousMode();
1152 DefaultSetInfoBufferCheck(TokenInformationClass
,
1153 SeTokenInformationClass
,
1155 TokenInformationLength
,
1159 if(!NT_SUCCESS(Status
))
1161 /* Invalid buffers */
1162 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1166 if(TokenInformationClass
== TokenSessionId
)
1168 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1171 Status
= ObReferenceObjectByHandle(TokenHandle
,
1177 if (NT_SUCCESS(Status
))
1179 switch (TokenInformationClass
)
1183 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1185 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1186 PSID InputSid
= NULL
;
1190 InputSid
= to
->Owner
;
1194 Status
= _SEH_GetExceptionCode();
1198 if(NT_SUCCESS(Status
))
1202 Status
= SepCaptureSid(InputSid
,
1207 if(NT_SUCCESS(Status
))
1209 RtlCopySid(RtlLengthSid(CapturedSid
),
1210 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1212 SepReleaseSid(CapturedSid
,
1220 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1225 case TokenPrimaryGroup
:
1227 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1229 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1230 PSID InputSid
= NULL
;
1234 InputSid
= tpg
->PrimaryGroup
;
1238 Status
= _SEH_GetExceptionCode();
1242 if(NT_SUCCESS(Status
))
1246 Status
= SepCaptureSid(InputSid
,
1251 if(NT_SUCCESS(Status
))
1253 RtlCopySid(RtlLengthSid(CapturedSid
),
1254 Token
->PrimaryGroup
,
1256 SepReleaseSid(CapturedSid
,
1264 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1269 case TokenDefaultDacl
:
1271 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1273 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1274 PACL InputAcl
= NULL
;
1278 InputAcl
= tdd
->DefaultDacl
;
1282 Status
= _SEH_GetExceptionCode();
1286 if(NT_SUCCESS(Status
))
1288 if(InputAcl
!= NULL
)
1292 /* capture and copy the dacl */
1293 Status
= SepCaptureAcl(InputAcl
,
1298 if(NT_SUCCESS(Status
))
1300 /* free the previous dacl if present */
1301 if(Token
->DefaultDacl
!= NULL
)
1303 ExFreePool(Token
->DefaultDacl
);
1306 /* set the new dacl */
1307 Token
->DefaultDacl
= CapturedAcl
;
1312 /* clear and free the default dacl if present */
1313 if(Token
->DefaultDacl
!= NULL
)
1315 ExFreePool(Token
->DefaultDacl
);
1316 Token
->DefaultDacl
= NULL
;
1323 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1328 case TokenSessionId
:
1330 ULONG SessionId
= 0;
1334 /* buffer size was already verified, no need to check here again */
1335 SessionId
= *(PULONG
)TokenInformation
;
1339 Status
= _SEH_GetExceptionCode();
1343 if(NT_SUCCESS(Status
))
1345 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1348 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1352 Token
->SessionId
= SessionId
;
1359 Status
= STATUS_NOT_IMPLEMENTED
;
1364 ObDereferenceObject(Token
);
1374 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1375 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1376 * is correct either. -Gunnar
1377 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1380 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1381 IN ACCESS_MASK DesiredAccess
,
1382 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1383 IN BOOLEAN EffectiveOnly
,
1384 IN TOKEN_TYPE TokenType
,
1385 OUT PHANDLE NewTokenHandle
)
1387 KPROCESSOR_MODE PreviousMode
;
1391 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1393 NTSTATUS Status
= STATUS_SUCCESS
;
1397 PreviousMode
= KeGetPreviousMode();
1399 if(PreviousMode
!= KernelMode
)
1403 ProbeForWrite(NewTokenHandle
,
1409 Status
= _SEH_GetExceptionCode();
1413 if(!NT_SUCCESS(Status
))
1419 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1423 &CapturedSecurityQualityOfService
,
1425 if(!NT_SUCCESS(Status
))
1427 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1431 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1437 if (NT_SUCCESS(Status
))
1439 Status
= SepDuplicateToken(Token
,
1443 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1447 ObDereferenceObject(Token
);
1449 if (NT_SUCCESS(Status
))
1451 Status
= ObInsertObject((PVOID
)NewToken
,
1458 ObDereferenceObject(NewToken
);
1460 if (NT_SUCCESS(Status
))
1464 *NewTokenHandle
= hToken
;
1468 Status
= _SEH_GetExceptionCode();
1475 /* free the captured structure */
1476 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1484 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1486 BOOLEAN ResetToDefault
,
1487 PSID_AND_ATTRIBUTES Groups
,
1489 KPROCESSOR_MODE PreviousMode
,
1500 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1501 IN BOOLEAN ResetToDefault
,
1502 IN PTOKEN_GROUPS NewState
,
1503 IN ULONG BufferLength
,
1504 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1505 OUT PULONG ReturnLength
)
1509 PACCESS_TOKEN Token
;
1516 Status
= ObReferenceObjectByHandle(TokenHandle
,
1524 SepAdjustGroups(Token
,
1536 return(STATUS_NOT_IMPLEMENTED
);
1543 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1545 KPROCESSOR_MODE PreviousMode
,
1546 ULONG PrivilegeCount
,
1547 PLUID_AND_ATTRIBUTES Privileges
,
1548 PTOKEN_PRIVILEGES
* PreviousState
,
1557 if (Token
->PrivilegeCount
> 0)
1559 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1561 if (PreviousMode
!= KernelMode
)
1563 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1567 if (PreviousState
!= NULL
)
1569 memcpy(&PreviousState
[i
],
1570 &Token
->Privileges
[i
],
1571 sizeof(LUID_AND_ATTRIBUTES
));
1573 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1580 if (PreviousMode
!= KernelMode
)
1582 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1586 if (PrivilegeCount
<= ?)
1599 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1600 IN BOOLEAN DisableAllPrivileges
,
1601 IN PTOKEN_PRIVILEGES NewState
,
1602 IN ULONG BufferLength
,
1603 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1604 OUT PULONG ReturnLength OPTIONAL
)
1606 // PLUID_AND_ATTRIBUTES Privileges;
1607 KPROCESSOR_MODE PreviousMode
;
1608 ULONG PrivilegeCount
;
1624 DPRINT ("NtAdjustPrivilegesToken() called\n");
1626 // PrivilegeCount = NewState->PrivilegeCount;
1627 PreviousMode
= KeGetPreviousMode ();
1628 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1638 Status
= ObReferenceObjectByHandle (TokenHandle
,
1639 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1644 if (!NT_SUCCESS(Status
))
1646 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1647 // SeReleaseLuidAndAttributesArray(Privileges,
1655 SepAdjustPrivileges(Token
,
1666 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1667 sizeof(LUID_AND_ATTRIBUTES
);
1669 if (PreviousState
!= NULL
)
1670 PreviousState
->PrivilegeCount
= 0;
1673 if (DisableAllPrivileges
== TRUE
)
1675 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1677 if (Token
->Privileges
[i
].Attributes
!= 0)
1679 DPRINT ("Attributes differ\n");
1681 /* Save current privilege */
1682 if (PreviousState
!= NULL
)
1684 if (k
< PrivilegeCount
)
1686 PreviousState
->PrivilegeCount
++;
1687 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1688 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1692 /* FIXME: Should revert all the changes, calculate how
1693 * much space would be needed, set ResultLength
1694 * accordingly and fail.
1700 /* Update current privlege */
1701 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1704 Status
= STATUS_SUCCESS
;
1709 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1711 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1713 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1714 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1716 DPRINT ("Found privilege\n");
1718 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1719 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1721 DPRINT ("Attributes differ\n");
1722 DPRINT ("Current attributes %lx desired attributes %lx\n",
1723 Token
->Privileges
[i
].Attributes
,
1724 NewState
->Privileges
[j
].Attributes
);
1726 /* Save current privilege */
1727 if (PreviousState
!= NULL
)
1729 if (k
< PrivilegeCount
)
1731 PreviousState
->PrivilegeCount
++;
1732 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1733 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1737 /* FIXME: Should revert all the changes, calculate how
1738 * much space would be needed, set ResultLength
1739 * accordingly and fail.
1745 /* Update current privlege */
1746 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1747 Token
->Privileges
[i
].Attributes
|=
1748 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1749 DPRINT ("New attributes %lx\n",
1750 Token
->Privileges
[i
].Attributes
);
1756 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1759 if (ReturnLength
!= NULL
)
1761 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1762 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1765 ObDereferenceObject (Token
);
1767 // SeReleaseLuidAndAttributesArray(Privileges,
1771 DPRINT ("NtAdjustPrivilegesToken() done\n");
1778 SepCreateSystemProcessToken(VOID
)
1786 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1787 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1788 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1789 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1796 * Initialize the token
1798 Status
= ObCreateObject(KernelMode
,
1806 (PVOID
*)&AccessToken
);
1807 if (!NT_SUCCESS(Status
))
1811 Status
= ObInsertObject(AccessToken
,
1818 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1819 if (!NT_SUCCESS(Status
))
1821 ObDereferenceObject(AccessToken
);
1825 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1826 if (!NT_SUCCESS(Status
))
1828 ObDereferenceObject(AccessToken
);
1832 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1833 if (!NT_SUCCESS(Status
))
1835 ObDereferenceObject(AccessToken
);
1839 AccessToken
->TokenLock
= &SepTokenLock
;
1841 AccessToken
->TokenType
= TokenPrimary
;
1842 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1843 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1844 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1845 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1846 AccessToken
->ExpirationTime
.QuadPart
= -1;
1847 AccessToken
->UserAndGroupCount
= 4;
1849 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1850 uSize
+= uLocalSystemLength
;
1851 uSize
+= uWorldLength
;
1852 uSize
+= uAuthUserLength
;
1853 uSize
+= uAdminsLength
;
1855 AccessToken
->UserAndGroups
=
1856 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1858 TAG('T', 'O', 'K', 'u'));
1859 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1862 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1863 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1864 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1865 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1867 AccessToken
->DefaultOwnerIndex
= i
;
1868 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1869 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1870 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1871 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1872 SidArea
= (char*)SidArea
+ uAdminsLength
;
1874 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1875 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1876 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1877 SidArea
= (char*)SidArea
+ uWorldLength
;
1879 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1880 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1881 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1882 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1884 AccessToken
->PrivilegeCount
= 20;
1886 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1887 AccessToken
->Privileges
=
1888 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1890 TAG('T', 'O', 'K', 'p'));
1893 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1894 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1896 AccessToken
->Privileges
[i
].Attributes
= 0;
1897 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1899 AccessToken
->Privileges
[i
].Attributes
= 0;
1900 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1902 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1903 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1905 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1906 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1908 AccessToken
->Privileges
[i
].Attributes
= 0;
1909 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1911 AccessToken
->Privileges
[i
].Attributes
= 0;
1912 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1914 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1915 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1917 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1918 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1920 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1921 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1923 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1924 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1926 AccessToken
->Privileges
[i
].Attributes
= 0;
1927 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1929 AccessToken
->Privileges
[i
].Attributes
= 0;
1930 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1932 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1933 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1935 AccessToken
->Privileges
[i
].Attributes
= 0;
1936 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1938 AccessToken
->Privileges
[i
].Attributes
= 0;
1939 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1941 AccessToken
->Privileges
[i
].Attributes
= 0;
1942 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1944 AccessToken
->Privileges
[i
].Attributes
= 0;
1945 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1947 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1948 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1950 AccessToken
->Privileges
[i
].Attributes
= 0;
1951 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1953 AccessToken
->Privileges
[i
].Attributes
= 0;
1954 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1956 AccessToken
->Privileges
[i
].Attributes
= 0;
1957 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1962 uSize
= sizeof(ACL
);
1963 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1964 uSize
+= sizeof(ACE
) + uAdminsLength
;
1965 uSize
= (uSize
& (~3)) + 8;
1966 AccessToken
->DefaultDacl
=
1967 (PACL
) ExAllocatePoolWithTag(PagedPool
,
1969 TAG('T', 'O', 'K', 'd'));
1970 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1971 if ( NT_SUCCESS(Status
) )
1973 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1976 if ( NT_SUCCESS(Status
) )
1978 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1981 if ( ! NT_SUCCESS(Status
) )
1983 ObDereferenceObject(AccessToken
);
1992 NtCreateToken(OUT PHANDLE TokenHandle
,
1993 IN ACCESS_MASK DesiredAccess
,
1994 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1995 IN TOKEN_TYPE TokenType
,
1996 IN PLUID AuthenticationId
,
1997 IN PLARGE_INTEGER ExpirationTime
,
1998 IN PTOKEN_USER TokenUser
,
1999 IN PTOKEN_GROUPS TokenGroups
,
2000 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2001 IN PTOKEN_OWNER TokenOwner
,
2002 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2003 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2004 IN PTOKEN_SOURCE TokenSource
)
2013 KPROCESSOR_MODE PreviousMode
;
2014 NTSTATUS Status
= STATUS_SUCCESS
;
2018 PreviousMode
= ExGetPreviousMode();
2020 if(PreviousMode
!= KernelMode
)
2024 ProbeForWrite(TokenHandle
,
2027 ProbeForRead(AuthenticationId
,
2030 ProbeForRead(ExpirationTime
,
2031 sizeof(LARGE_INTEGER
),
2033 ProbeForRead(TokenUser
,
2036 ProbeForRead(TokenGroups
,
2037 sizeof(TOKEN_GROUPS
),
2039 ProbeForRead(TokenPrivileges
,
2040 sizeof(TOKEN_PRIVILEGES
),
2042 ProbeForRead(TokenOwner
,
2043 sizeof(TOKEN_OWNER
),
2045 ProbeForRead(TokenPrimaryGroup
,
2046 sizeof(TOKEN_PRIMARY_GROUP
),
2048 ProbeForRead(TokenDefaultDacl
,
2049 sizeof(TOKEN_DEFAULT_DACL
),
2051 ProbeForRead(TokenSource
,
2052 sizeof(TOKEN_SOURCE
),
2057 Status
= _SEH_GetExceptionCode();
2061 if(!NT_SUCCESS(Status
))
2067 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2068 if (!NT_SUCCESS(Status
))
2071 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2072 if (!NT_SUCCESS(Status
))
2075 Status
= ObCreateObject(PreviousMode
,
2083 (PVOID
*)&AccessToken
);
2084 if (!NT_SUCCESS(Status
))
2086 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2090 AccessToken
->TokenLock
= &SepTokenLock
;
2092 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2093 &TokenSource
->SourceIdentifier
);
2094 memcpy(AccessToken
->TokenSource
.SourceName
,
2095 TokenSource
->SourceName
,
2096 sizeof(TokenSource
->SourceName
));
2098 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2099 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2100 AccessToken
->ExpirationTime
= *ExpirationTime
;
2101 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2103 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2104 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2105 AccessToken
->UserAndGroups
= 0;
2106 AccessToken
->Privileges
= 0;
2108 AccessToken
->TokenType
= TokenType
;
2109 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2110 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2113 * Normally we would just point these members into the variable information
2114 * area; however, our ObCreateObject() call can't allocate a variable information
2115 * area, so we allocate them seperately and provide a destroy function.
2118 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2119 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2120 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2121 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2123 AccessToken
->UserAndGroups
=
2124 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2126 TAG('T', 'O', 'K', 'u'));
2128 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2130 Status
= RtlCopySidAndAttributesArray(1,
2133 AccessToken
->UserAndGroups
,
2137 if (NT_SUCCESS(Status
))
2139 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2140 TokenGroups
->Groups
,
2142 &AccessToken
->UserAndGroups
[1],
2148 if (NT_SUCCESS(Status
))
2150 Status
= SepFindPrimaryGroupAndDefaultOwner(
2152 TokenPrimaryGroup
->PrimaryGroup
,
2156 if (NT_SUCCESS(Status
))
2158 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2159 AccessToken
->Privileges
=
2160 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2162 TAG('T', 'O', 'K', 'p'));
2164 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
2166 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
2167 &TokenPrivileges
->Privileges
[i
],
2168 sizeof(LUID_AND_ATTRIBUTES
));
2169 if (!NT_SUCCESS(Status
))
2174 if (NT_SUCCESS(Status
))
2176 AccessToken
->DefaultDacl
=
2177 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2178 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2179 TAG('T', 'O', 'K', 'd'));
2180 memcpy(AccessToken
->DefaultDacl
,
2181 TokenDefaultDacl
->DefaultDacl
,
2182 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2185 Status
= ObInsertObject ((PVOID
)AccessToken
,
2191 if (!NT_SUCCESS(Status
))
2193 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2196 ObDereferenceObject(AccessToken
);
2198 if (NT_SUCCESS(Status
))
2202 *TokenHandle
= hToken
;
2206 Status
= _SEH_GetExceptionCode();
2219 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
2224 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
2226 return STATUS_SUCCESS
;
2233 SECURITY_IMPERSONATION_LEVEL
2235 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
2239 return ((PTOKEN
)Token
)->ImpersonationLevel
;
2247 SeTokenType(IN PACCESS_TOKEN Token
)
2251 return ((PTOKEN
)Token
)->TokenType
;
2261 IN PACCESS_TOKEN Token
2273 SeTokenIsRestricted(
2274 IN PACCESS_TOKEN Token
2286 SeTokenIsWriteRestricted(
2287 IN PACCESS_TOKEN Token
2300 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2301 IN ACCESS_MASK DesiredAccess
,
2302 IN BOOLEAN OpenAsSelf
,
2303 IN ULONG HandleAttributes
,
2304 OUT PHANDLE TokenHandle
)
2308 PTOKEN Token
, NewToken
, PrimaryToken
;
2309 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2310 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2311 SE_IMPERSONATION_STATE ImpersonationState
;
2312 OBJECT_ATTRIBUTES ObjectAttributes
;
2313 SECURITY_DESCRIPTOR SecurityDescriptor
;
2315 KPROCESSOR_MODE PreviousMode
;
2316 NTSTATUS Status
= STATUS_SUCCESS
;
2320 PreviousMode
= ExGetPreviousMode();
2322 if(PreviousMode
!= KernelMode
)
2326 ProbeForWrite(TokenHandle
,
2332 Status
= _SEH_GetExceptionCode();
2336 if(!NT_SUCCESS(Status
))
2343 * At first open the thread token for information access and verify
2344 * that the token associated with thread is valid.
2347 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2348 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2350 if (!NT_SUCCESS(Status
))
2355 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2356 &ImpersonationLevel
);
2359 ObfDereferenceObject(Thread
);
2360 return STATUS_NO_TOKEN
;
2363 ObDereferenceObject(Thread
);
2365 if (ImpersonationLevel
== SecurityAnonymous
)
2367 ObfDereferenceObject(Token
);
2368 return STATUS_CANT_OPEN_ANONYMOUS
;
2372 * Revert to self if OpenAsSelf is specified.
2377 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2382 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2383 PsThreadType
, PreviousMode
,
2384 (PVOID
*)&Thread
, NULL
);
2385 if (!NT_SUCCESS(Status
))
2387 ObfDereferenceObject(Token
);
2390 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2395 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2396 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2397 ObfDereferenceObject(PrimaryToken
);
2398 ObfDereferenceObject(Thread
);
2399 if (!NT_SUCCESS(Status
))
2401 ObfDereferenceObject(Token
);
2404 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2409 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2410 SECURITY_DESCRIPTOR_REVISION
);
2411 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2414 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2415 NULL
, &SecurityDescriptor
);
2417 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2418 TokenImpersonation
, ImpersonationLevel
,
2419 KernelMode
, &NewToken
);
2421 if (!NT_SUCCESS(Status
))
2423 ObfDereferenceObject(Token
);
2426 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2431 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2434 ObfDereferenceObject(NewToken
);
2438 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2439 NULL
, DesiredAccess
, SepTokenObjectType
,
2440 PreviousMode
, &hToken
);
2443 ObfDereferenceObject(Token
);
2447 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2450 if(NT_SUCCESS(Status
))
2454 *TokenHandle
= hToken
;
2458 Status
= _SEH_GetExceptionCode();
2470 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2471 IN ACCESS_MASK DesiredAccess
,
2472 IN BOOLEAN OpenAsSelf
,
2473 OUT PHANDLE TokenHandle
)
2475 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,