3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/token.c
6 * PURPOSE: Security manager
8 * PROGRAMMERS: David Welch <welch@cwcom.net>
11 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, SepInitializeTokenImplementation)
23 /* GLOBALS *******************************************************************/
25 POBJECT_TYPE SepTokenObjectType
= NULL
;
26 ERESOURCE SepTokenLock
;
28 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
33 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
35 /* Class 0 not used, blame M$! */
36 ICI_SQ_SAME( 0, 0, 0),
39 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
41 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
43 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
45 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
46 /* TokenPrimaryGroup */
47 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
48 /* TokenDefaultDacl */
49 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
51 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
53 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
54 /* TokenImpersonationLevel */
55 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
57 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
58 /* TokenRestrictedSids */
59 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
61 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
62 /* TokenGroupsAndPrivileges */
63 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
64 /* TokenSessionReference */
65 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
66 /* TokenSandBoxInert */
67 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
68 /* TokenAuditPolicy */
69 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
71 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
74 /* FUNCTIONS *****************************************************************/
78 SepFreeProxyData(PVOID ProxyData
)
85 SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
88 return(STATUS_NOT_IMPLEMENTED
);
93 SeExchangePrimaryToken(PEPROCESS Process
,
94 PACCESS_TOKEN NewTokenP
,
95 PACCESS_TOKEN
* OldTokenP
)
98 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
102 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
103 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
105 /* Mark new token in use */
106 NewToken
->TokenInUse
= 1;
108 /* Reference the New Token */
109 ObReferenceObject(NewToken
);
111 /* Replace the old with the new */
112 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
114 /* Mark the Old Token as free */
115 OldToken
->TokenInUse
= 0;
117 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
118 return STATUS_SUCCESS
;
123 SeDeassignPrimaryToken(PEPROCESS Process
)
127 /* Remove the Token */
128 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
130 /* Mark the Old Token as free */
131 OldToken
->TokenInUse
= 0;
135 RtlLengthSidAndAttributes(ULONG Count
,
136 PSID_AND_ATTRIBUTES Src
)
143 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
144 for (i
= 0; i
< Count
; i
++)
145 uLength
+= RtlLengthSid(Src
[i
].Sid
);
153 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
159 Token
->PrimaryGroup
= 0;
163 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
166 /* Validate and set the primary group and user pointers */
167 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
170 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
172 Token
->DefaultOwnerIndex
= i
;
175 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
177 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
181 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
183 return(STATUS_INVALID_OWNER
);
186 if (Token
->PrimaryGroup
== 0)
188 return(STATUS_INVALID_PRIMARY_GROUP
);
191 return(STATUS_SUCCESS
);
197 SepDuplicateToken(PTOKEN Token
,
198 POBJECT_ATTRIBUTES ObjectAttributes
,
199 BOOLEAN EffectiveOnly
,
200 TOKEN_TYPE TokenType
,
201 SECURITY_IMPERSONATION_LEVEL Level
,
202 KPROCESSOR_MODE PreviousMode
,
203 PTOKEN
* NewAccessToken
)
213 Status
= ObCreateObject(PreviousMode
,
221 (PVOID
*)&AccessToken
);
222 if (!NT_SUCCESS(Status
))
224 DPRINT1("ObCreateObject() failed (Status %lx)\n");
228 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
229 if (!NT_SUCCESS(Status
))
231 ObDereferenceObject(AccessToken
);
235 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
236 if (!NT_SUCCESS(Status
))
238 ObDereferenceObject(AccessToken
);
242 AccessToken
->TokenLock
= &SepTokenLock
;
244 AccessToken
->TokenInUse
= 0;
245 AccessToken
->TokenType
= TokenType
;
246 AccessToken
->ImpersonationLevel
= Level
;
247 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
249 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
250 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
251 memcpy(AccessToken
->TokenSource
.SourceName
,
252 Token
->TokenSource
.SourceName
,
253 sizeof(Token
->TokenSource
.SourceName
));
254 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
255 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
256 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
258 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
259 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
260 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
262 AccessToken
->UserAndGroups
=
263 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
265 TAG('T', 'O', 'K', 'u'));
267 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
269 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
270 Token
->UserAndGroups
,
272 AccessToken
->UserAndGroups
,
276 if (NT_SUCCESS(Status
))
278 Status
= SepFindPrimaryGroupAndDefaultOwner(
284 if (NT_SUCCESS(Status
))
286 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
288 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
289 AccessToken
->Privileges
=
290 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
292 TAG('T', 'O', 'K', 'p'));
294 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
296 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
297 &Token
->Privileges
[i
].Luid
);
298 AccessToken
->Privileges
[i
].Attributes
=
299 Token
->Privileges
[i
].Attributes
;
302 if ( Token
->DefaultDacl
)
304 AccessToken
->DefaultDacl
=
305 (PACL
) ExAllocatePoolWithTag(PagedPool
,
306 Token
->DefaultDacl
->AclSize
,
307 TAG('T', 'O', 'K', 'd'));
308 memcpy(AccessToken
->DefaultDacl
,
310 Token
->DefaultDacl
->AclSize
);
314 AccessToken
->DefaultDacl
= 0;
318 if ( NT_SUCCESS(Status
) )
320 *NewAccessToken
= AccessToken
;
321 return(STATUS_SUCCESS
);
324 ObDereferenceObject(AccessToken
);
334 PACCESS_STATE AccessState
,
335 PPRIVILEGE_SET Privileges
339 return STATUS_NOT_IMPLEMENTED
;
344 SeCopyClientToken(PACCESS_TOKEN Token
,
345 SECURITY_IMPERSONATION_LEVEL Level
,
346 KPROCESSOR_MODE PreviousMode
,
347 PACCESS_TOKEN
* NewToken
)
350 OBJECT_ATTRIBUTES ObjectAttributes
;
354 InitializeObjectAttributes(&ObjectAttributes
,
359 Status
= SepDuplicateToken(Token
,
375 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
376 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
377 IN BOOLEAN RemoteClient
,
378 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
380 TOKEN_TYPE TokenType
;
382 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
385 PACCESS_TOKEN NewToken
;
389 Token
= PsReferenceEffectiveToken(Thread
,
392 &ImpersonationLevel
);
393 if (TokenType
!= TokenImpersonation
)
395 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
399 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
403 ObDereferenceObject(Token
);
405 return(STATUS_UNSUCCESSFUL
);
407 if (ImpersonationLevel
== SecurityAnonymous
||
408 ImpersonationLevel
== SecurityIdentification
||
409 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
413 ObDereferenceObject(Token
);
415 return(STATUS_UNSUCCESSFUL
);
418 Qos
->EffectiveOnly
!= 0)
420 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
424 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
428 if (Qos
->ContextTrackingMode
== 0)
430 ClientContext
->DirectlyAccessClientToken
= FALSE
;
431 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
434 // ObDeleteCapturedInsertInfo(NewToken);
436 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
438 ObDereferenceObject(Token
);
447 ClientContext
->DirectlyAccessClientToken
= TRUE
;
448 if (RemoteClient
!= FALSE
)
450 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
454 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
455 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
456 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
457 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
458 ClientContext
->ServerIsRemote
= RemoteClient
;
459 ClientContext
->ClientToken
= NewToken
;
461 return(STATUS_SUCCESS
);
469 SeCreateClientSecurityFromSubjectContext(
470 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
471 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
472 IN BOOLEAN ServerIsRemote
,
473 OUT PSECURITY_CLIENT_CONTEXT ClientContext
477 return STATUS_NOT_IMPLEMENTED
;
486 IN PACCESS_TOKEN ExistingToken
,
488 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
489 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
490 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
491 OUT PACCESS_TOKEN
* FilteredToken
495 return STATUS_NOT_IMPLEMENTED
;
504 IN PPRIVILEGE_SET Privileges
516 SeImpersonateClientEx(
517 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
518 IN PETHREAD ServerThread OPTIONAL
522 return STATUS_NOT_IMPLEMENTED
;
529 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
530 IN PETHREAD ServerThread OPTIONAL
)
536 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
538 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
542 b
= ClientContext
->DirectAccessEffectiveOnly
;
544 if (ServerThread
== NULL
)
546 ServerThread
= PsGetCurrentThread();
548 PsImpersonateClient(ServerThread
,
549 ClientContext
->ClientToken
,
552 ClientContext
->SecurityQos
.ImpersonationLevel
);
557 SepDeleteToken(PVOID ObjectBody
)
559 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
561 if (AccessToken
->UserAndGroups
)
562 ExFreePool(AccessToken
->UserAndGroups
);
564 if (AccessToken
->Privileges
)
565 ExFreePool(AccessToken
->Privileges
);
567 if (AccessToken
->DefaultDacl
)
568 ExFreePool(AccessToken
->DefaultDacl
);
575 SepInitializeTokenImplementation(VOID
)
578 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
580 ExInitializeResource(&SepTokenLock
);
582 DPRINT("Creating Token Object Type\n");
584 /* Initialize the Token type */
585 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
586 RtlInitUnicodeString(&Name
, L
"Token");
587 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
588 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
589 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
590 ObjectTypeInitializer
.PoolType
= PagedPool
;
591 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
592 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
593 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
594 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &SepTokenObjectType
);
602 NtQueryInformationToken(IN HANDLE TokenHandle
,
603 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
604 OUT PVOID TokenInformation
,
605 IN ULONG TokenInformationLength
,
606 OUT PULONG ReturnLength
)
614 ULONG RequiredLength
;
615 KPROCESSOR_MODE PreviousMode
;
616 NTSTATUS Status
= STATUS_SUCCESS
;
620 PreviousMode
= ExGetPreviousMode();
622 /* Check buffers and class validity */
623 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
624 SeTokenInformationClass
,
625 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
627 TokenInformationLength
,
631 if(!NT_SUCCESS(Status
))
633 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
637 Status
= ObReferenceObjectByHandle(TokenHandle
,
638 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
643 if (NT_SUCCESS(Status
))
645 switch (TokenInformationClass
)
649 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
651 DPRINT("NtQueryInformationToken(TokenUser)\n");
652 RequiredLength
= sizeof(TOKEN_USER
) +
653 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
657 if(TokenInformationLength
>= RequiredLength
)
659 Status
= RtlCopySidAndAttributesArray(1,
660 &Token
->UserAndGroups
[0],
661 RequiredLength
- sizeof(TOKEN_USER
),
669 Status
= STATUS_BUFFER_TOO_SMALL
;
672 if(ReturnLength
!= NULL
)
674 *ReturnLength
= RequiredLength
;
679 Status
= _SEH_GetExceptionCode();
688 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
690 DPRINT("NtQueryInformationToken(TokenGroups)\n");
691 RequiredLength
= sizeof(tg
->GroupCount
) +
692 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
696 if(TokenInformationLength
>= RequiredLength
)
698 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
699 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
700 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
701 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
703 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
704 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
705 &Token
->UserAndGroups
[1],
714 Status
= STATUS_BUFFER_TOO_SMALL
;
717 if(ReturnLength
!= NULL
)
719 *ReturnLength
= RequiredLength
;
724 Status
= _SEH_GetExceptionCode();
731 case TokenPrivileges
:
733 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
735 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
736 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
737 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
741 if(TokenInformationLength
>= RequiredLength
)
743 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
744 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
750 Status
= STATUS_BUFFER_TOO_SMALL
;
753 if(ReturnLength
!= NULL
)
755 *ReturnLength
= RequiredLength
;
760 Status
= _SEH_GetExceptionCode();
770 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
772 DPRINT("NtQueryInformationToken(TokenOwner)\n");
773 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
774 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
778 if(TokenInformationLength
>= RequiredLength
)
780 to
->Owner
= (PSID
)(to
+ 1);
781 Status
= RtlCopySid(SidLen
,
783 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
787 Status
= STATUS_BUFFER_TOO_SMALL
;
790 if(ReturnLength
!= NULL
)
792 *ReturnLength
= RequiredLength
;
797 Status
= _SEH_GetExceptionCode();
804 case TokenPrimaryGroup
:
807 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
809 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
810 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
811 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
815 if(TokenInformationLength
>= RequiredLength
)
817 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
818 Status
= RtlCopySid(SidLen
,
820 Token
->PrimaryGroup
);
824 Status
= STATUS_BUFFER_TOO_SMALL
;
827 if(ReturnLength
!= NULL
)
829 *ReturnLength
= RequiredLength
;
834 Status
= _SEH_GetExceptionCode();
841 case TokenDefaultDacl
:
843 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
845 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
846 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
848 if(Token
->DefaultDacl
!= NULL
)
850 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
855 if(TokenInformationLength
>= RequiredLength
)
857 if(Token
->DefaultDacl
!= NULL
)
859 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
860 RtlCopyMemory(tdd
->DefaultDacl
,
862 Token
->DefaultDacl
->AclSize
);
866 tdd
->DefaultDacl
= NULL
;
871 Status
= STATUS_BUFFER_TOO_SMALL
;
874 if(ReturnLength
!= NULL
)
876 *ReturnLength
= RequiredLength
;
881 Status
= _SEH_GetExceptionCode();
890 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
892 DPRINT("NtQueryInformationToken(TokenSource)\n");
893 RequiredLength
= sizeof(TOKEN_SOURCE
);
897 if(TokenInformationLength
>= RequiredLength
)
899 *ts
= Token
->TokenSource
;
903 Status
= STATUS_BUFFER_TOO_SMALL
;
906 if(ReturnLength
!= NULL
)
908 *ReturnLength
= RequiredLength
;
913 Status
= _SEH_GetExceptionCode();
922 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
924 DPRINT("NtQueryInformationToken(TokenType)\n");
925 RequiredLength
= sizeof(TOKEN_TYPE
);
929 if(TokenInformationLength
>= RequiredLength
)
931 *tt
= Token
->TokenType
;
935 Status
= STATUS_BUFFER_TOO_SMALL
;
938 if(ReturnLength
!= NULL
)
940 *ReturnLength
= RequiredLength
;
945 Status
= _SEH_GetExceptionCode();
952 case TokenImpersonationLevel
:
954 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
956 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
957 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
961 if(TokenInformationLength
>= RequiredLength
)
963 *sil
= Token
->ImpersonationLevel
;
967 Status
= STATUS_BUFFER_TOO_SMALL
;
970 if(ReturnLength
!= NULL
)
972 *ReturnLength
= RequiredLength
;
977 Status
= _SEH_GetExceptionCode();
984 case TokenStatistics
:
986 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
988 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
989 RequiredLength
= sizeof(TOKEN_STATISTICS
);
993 if(TokenInformationLength
>= RequiredLength
)
995 ts
->TokenId
= Token
->TokenId
;
996 ts
->AuthenticationId
= Token
->AuthenticationId
;
997 ts
->ExpirationTime
= Token
->ExpirationTime
;
998 ts
->TokenType
= Token
->TokenType
;
999 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1000 ts
->DynamicCharged
= Token
->DynamicCharged
;
1001 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1002 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1003 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1004 ts
->ModifiedId
= Token
->ModifiedId
;
1008 Status
= STATUS_BUFFER_TOO_SMALL
;
1011 if(ReturnLength
!= NULL
)
1013 *ReturnLength
= RequiredLength
;
1018 Status
= _SEH_GetExceptionCode();
1027 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1029 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1030 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1034 if(TokenInformationLength
>= RequiredLength
)
1036 RtlCopyLuid(&to
->OriginatingLogonSession
,
1037 &Token
->AuthenticationId
);
1041 Status
= STATUS_BUFFER_TOO_SMALL
;
1044 if(ReturnLength
!= NULL
)
1046 *ReturnLength
= RequiredLength
;
1051 Status
= _SEH_GetExceptionCode();
1058 case TokenGroupsAndPrivileges
:
1059 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1060 Status
= STATUS_NOT_IMPLEMENTED
;
1063 case TokenRestrictedSids
:
1065 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1067 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1068 RequiredLength
= sizeof(tg
->GroupCount
) +
1069 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1073 if(TokenInformationLength
>= RequiredLength
)
1075 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1076 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1077 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1078 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1080 tg
->GroupCount
= Token
->RestrictedSidCount
;
1081 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1082 Token
->RestrictedSids
,
1091 Status
= STATUS_BUFFER_TOO_SMALL
;
1094 if(ReturnLength
!= NULL
)
1096 *ReturnLength
= RequiredLength
;
1101 Status
= _SEH_GetExceptionCode();
1108 case TokenSandBoxInert
:
1109 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1110 Status
= STATUS_NOT_IMPLEMENTED
;
1113 case TokenSessionId
:
1115 ULONG SessionId
= 0;
1117 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1119 Status
= SeQuerySessionIdToken(Token
,
1122 if(NT_SUCCESS(Status
))
1126 /* buffer size was already verified, no need to check here again */
1127 *(PULONG
)TokenInformation
= SessionId
;
1129 if(ReturnLength
!= NULL
)
1131 *ReturnLength
= sizeof(ULONG
);
1136 Status
= _SEH_GetExceptionCode();
1145 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1146 Status
= STATUS_INVALID_INFO_CLASS
;
1150 ObDereferenceObject(Token
);
1161 SeQueryInformationToken(
1162 IN PACCESS_TOKEN Token
,
1163 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1164 OUT PVOID
*TokenInformation
1168 return STATUS_NOT_IMPLEMENTED
;
1176 SeQuerySessionIdToken(
1177 IN PACCESS_TOKEN Token
,
1178 IN PULONG pSessionId
1181 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1182 return STATUS_SUCCESS
;
1186 * NtSetTokenInformation: Partly implemented.
1188 * TokenOrigin, TokenDefaultDacl
1192 NtSetInformationToken(IN HANDLE TokenHandle
,
1193 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1194 OUT PVOID TokenInformation
,
1195 IN ULONG TokenInformationLength
)
1198 KPROCESSOR_MODE PreviousMode
;
1199 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1200 NTSTATUS Status
= STATUS_SUCCESS
;
1204 PreviousMode
= ExGetPreviousMode();
1206 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1207 SeTokenInformationClass
,
1208 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1210 TokenInformationLength
,
1213 if(!NT_SUCCESS(Status
))
1215 /* Invalid buffers */
1216 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1220 if(TokenInformationClass
== TokenSessionId
)
1222 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1225 Status
= ObReferenceObjectByHandle(TokenHandle
,
1231 if (NT_SUCCESS(Status
))
1233 switch (TokenInformationClass
)
1237 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1239 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1240 PSID InputSid
= NULL
;
1244 InputSid
= to
->Owner
;
1248 Status
= _SEH_GetExceptionCode();
1252 if(NT_SUCCESS(Status
))
1256 Status
= SepCaptureSid(InputSid
,
1261 if(NT_SUCCESS(Status
))
1263 RtlCopySid(RtlLengthSid(CapturedSid
),
1264 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1266 SepReleaseSid(CapturedSid
,
1274 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1279 case TokenPrimaryGroup
:
1281 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1283 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1284 PSID InputSid
= NULL
;
1288 InputSid
= tpg
->PrimaryGroup
;
1292 Status
= _SEH_GetExceptionCode();
1296 if(NT_SUCCESS(Status
))
1300 Status
= SepCaptureSid(InputSid
,
1305 if(NT_SUCCESS(Status
))
1307 RtlCopySid(RtlLengthSid(CapturedSid
),
1308 Token
->PrimaryGroup
,
1310 SepReleaseSid(CapturedSid
,
1318 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1323 case TokenDefaultDacl
:
1325 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1327 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1328 PACL InputAcl
= NULL
;
1332 InputAcl
= tdd
->DefaultDacl
;
1336 Status
= _SEH_GetExceptionCode();
1340 if(NT_SUCCESS(Status
))
1342 if(InputAcl
!= NULL
)
1346 /* capture and copy the dacl */
1347 Status
= SepCaptureAcl(InputAcl
,
1352 if(NT_SUCCESS(Status
))
1354 /* free the previous dacl if present */
1355 if(Token
->DefaultDacl
!= NULL
)
1357 ExFreePool(Token
->DefaultDacl
);
1360 /* set the new dacl */
1361 Token
->DefaultDacl
= CapturedAcl
;
1366 /* clear and free the default dacl if present */
1367 if(Token
->DefaultDacl
!= NULL
)
1369 ExFreePool(Token
->DefaultDacl
);
1370 Token
->DefaultDacl
= NULL
;
1377 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1382 case TokenSessionId
:
1384 ULONG SessionId
= 0;
1388 /* buffer size was already verified, no need to check here again */
1389 SessionId
= *(PULONG
)TokenInformation
;
1393 Status
= _SEH_GetExceptionCode();
1397 if(NT_SUCCESS(Status
))
1399 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1402 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1406 Token
->SessionId
= SessionId
;
1413 Status
= STATUS_NOT_IMPLEMENTED
;
1418 ObDereferenceObject(Token
);
1428 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1429 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1430 * is correct either. -Gunnar
1431 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1434 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1435 IN ACCESS_MASK DesiredAccess
,
1436 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1437 IN BOOLEAN EffectiveOnly
,
1438 IN TOKEN_TYPE TokenType
,
1439 OUT PHANDLE NewTokenHandle
)
1441 KPROCESSOR_MODE PreviousMode
;
1445 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1447 NTSTATUS Status
= STATUS_SUCCESS
;
1451 PreviousMode
= KeGetPreviousMode();
1453 if(PreviousMode
!= KernelMode
)
1457 ProbeForWriteHandle(NewTokenHandle
);
1461 Status
= _SEH_GetExceptionCode();
1465 if(!NT_SUCCESS(Status
))
1471 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1475 &CapturedSecurityQualityOfService
,
1477 if(!NT_SUCCESS(Status
))
1479 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1483 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1489 if (NT_SUCCESS(Status
))
1491 Status
= SepDuplicateToken(Token
,
1495 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1499 ObDereferenceObject(Token
);
1501 if (NT_SUCCESS(Status
))
1503 Status
= ObInsertObject((PVOID
)NewToken
,
1510 ObDereferenceObject(NewToken
);
1512 if (NT_SUCCESS(Status
))
1516 *NewTokenHandle
= hToken
;
1520 Status
= _SEH_GetExceptionCode();
1527 /* free the captured structure */
1528 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1536 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1538 BOOLEAN ResetToDefault
,
1539 PSID_AND_ATTRIBUTES Groups
,
1541 KPROCESSOR_MODE PreviousMode
,
1552 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1553 IN BOOLEAN ResetToDefault
,
1554 IN PTOKEN_GROUPS NewState
,
1555 IN ULONG BufferLength
,
1556 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1557 OUT PULONG ReturnLength
)
1561 PACCESS_TOKEN Token
;
1568 Status
= ObReferenceObjectByHandle(TokenHandle
,
1576 SepAdjustGroups(Token
,
1588 return(STATUS_NOT_IMPLEMENTED
);
1595 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1597 KPROCESSOR_MODE PreviousMode
,
1598 ULONG PrivilegeCount
,
1599 PLUID_AND_ATTRIBUTES Privileges
,
1600 PTOKEN_PRIVILEGES
* PreviousState
,
1609 if (Token
->PrivilegeCount
> 0)
1611 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1613 if (PreviousMode
!= KernelMode
)
1615 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1619 if (PreviousState
!= NULL
)
1621 memcpy(&PreviousState
[i
],
1622 &Token
->Privileges
[i
],
1623 sizeof(LUID_AND_ATTRIBUTES
));
1625 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1632 if (PreviousMode
!= KernelMode
)
1634 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1638 if (PrivilegeCount
<= ?)
1651 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1652 IN BOOLEAN DisableAllPrivileges
,
1653 IN PTOKEN_PRIVILEGES NewState
,
1654 IN ULONG BufferLength
,
1655 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1656 OUT PULONG ReturnLength OPTIONAL
)
1658 // PLUID_AND_ATTRIBUTES Privileges;
1659 KPROCESSOR_MODE PreviousMode
;
1660 ULONG PrivilegeCount
;
1676 DPRINT ("NtAdjustPrivilegesToken() called\n");
1678 // PrivilegeCount = NewState->PrivilegeCount;
1679 PreviousMode
= KeGetPreviousMode ();
1680 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1690 Status
= ObReferenceObjectByHandle (TokenHandle
,
1691 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1696 if (!NT_SUCCESS(Status
))
1698 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1699 // SeReleaseLuidAndAttributesArray(Privileges,
1707 SepAdjustPrivileges(Token
,
1718 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1719 sizeof(LUID_AND_ATTRIBUTES
);
1721 if (PreviousState
!= NULL
)
1722 PreviousState
->PrivilegeCount
= 0;
1725 if (DisableAllPrivileges
== TRUE
)
1727 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1729 if (Token
->Privileges
[i
].Attributes
!= 0)
1731 DPRINT ("Attributes differ\n");
1733 /* Save current privilege */
1734 if (PreviousState
!= NULL
)
1736 if (k
< PrivilegeCount
)
1738 PreviousState
->PrivilegeCount
++;
1739 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1740 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1744 /* FIXME: Should revert all the changes, calculate how
1745 * much space would be needed, set ResultLength
1746 * accordingly and fail.
1752 /* Update current privlege */
1753 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1756 Status
= STATUS_SUCCESS
;
1761 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1763 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1765 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1766 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1768 DPRINT ("Found privilege\n");
1770 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1771 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1773 DPRINT ("Attributes differ\n");
1774 DPRINT ("Current attributes %lx desired attributes %lx\n",
1775 Token
->Privileges
[i
].Attributes
,
1776 NewState
->Privileges
[j
].Attributes
);
1778 /* Save current privilege */
1779 if (PreviousState
!= NULL
)
1781 if (k
< PrivilegeCount
)
1783 PreviousState
->PrivilegeCount
++;
1784 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1785 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1789 /* FIXME: Should revert all the changes, calculate how
1790 * much space would be needed, set ResultLength
1791 * accordingly and fail.
1797 /* Update current privlege */
1798 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1799 Token
->Privileges
[i
].Attributes
|=
1800 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1801 DPRINT ("New attributes %lx\n",
1802 Token
->Privileges
[i
].Attributes
);
1808 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1811 if (ReturnLength
!= NULL
)
1813 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1814 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1817 ObDereferenceObject (Token
);
1819 // SeReleaseLuidAndAttributesArray(Privileges,
1823 DPRINT ("NtAdjustPrivilegesToken() done\n");
1830 SepCreateSystemProcessToken(VOID
)
1835 ULONG uLocalSystemLength
;
1837 ULONG uAuthUserLength
;
1838 ULONG uAdminsLength
;
1844 uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1845 uWorldLength
= RtlLengthSid(SeWorldSid
);
1846 uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1847 uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1850 * Initialize the token
1852 Status
= ObCreateObject(KernelMode
,
1860 (PVOID
*)&AccessToken
);
1861 if (!NT_SUCCESS(Status
))
1865 Status
= ObInsertObject(AccessToken
,
1872 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1873 if (!NT_SUCCESS(Status
))
1875 ObDereferenceObject(AccessToken
);
1879 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1880 if (!NT_SUCCESS(Status
))
1882 ObDereferenceObject(AccessToken
);
1886 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1887 if (!NT_SUCCESS(Status
))
1889 ObDereferenceObject(AccessToken
);
1893 AccessToken
->TokenLock
= &SepTokenLock
;
1895 AccessToken
->TokenType
= TokenPrimary
;
1896 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1897 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1898 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1899 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1900 AccessToken
->ExpirationTime
.QuadPart
= -1;
1901 AccessToken
->UserAndGroupCount
= 4;
1903 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1904 uSize
+= uLocalSystemLength
;
1905 uSize
+= uWorldLength
;
1906 uSize
+= uAuthUserLength
;
1907 uSize
+= uAdminsLength
;
1909 AccessToken
->UserAndGroups
=
1910 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1912 TAG('T', 'O', 'K', 'u'));
1913 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1916 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1917 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1918 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1919 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1921 AccessToken
->DefaultOwnerIndex
= i
;
1922 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1923 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1924 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1925 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1926 SidArea
= (char*)SidArea
+ uAdminsLength
;
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(uWorldLength
, SidArea
, SeWorldSid
);
1931 SidArea
= (char*)SidArea
+ uWorldLength
;
1933 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1934 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1935 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1936 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1938 AccessToken
->PrivilegeCount
= 20;
1940 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1941 AccessToken
->Privileges
=
1942 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
1944 TAG('T', 'O', 'K', 'p'));
1947 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1948 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1950 AccessToken
->Privileges
[i
].Attributes
= 0;
1951 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1953 AccessToken
->Privileges
[i
].Attributes
= 0;
1954 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1956 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1957 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1959 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1960 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1962 AccessToken
->Privileges
[i
].Attributes
= 0;
1963 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1965 AccessToken
->Privileges
[i
].Attributes
= 0;
1966 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1968 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1969 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1971 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1972 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1974 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1975 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1977 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1978 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1980 AccessToken
->Privileges
[i
].Attributes
= 0;
1981 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1983 AccessToken
->Privileges
[i
].Attributes
= 0;
1984 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1986 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1987 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1989 AccessToken
->Privileges
[i
].Attributes
= 0;
1990 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1992 AccessToken
->Privileges
[i
].Attributes
= 0;
1993 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1995 AccessToken
->Privileges
[i
].Attributes
= 0;
1996 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1998 AccessToken
->Privileges
[i
].Attributes
= 0;
1999 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
2001 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
2002 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
2004 AccessToken
->Privileges
[i
].Attributes
= 0;
2005 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
2007 AccessToken
->Privileges
[i
].Attributes
= 0;
2008 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
2010 AccessToken
->Privileges
[i
].Attributes
= 0;
2011 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
2016 uSize
= sizeof(ACL
);
2017 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
2018 uSize
+= sizeof(ACE
) + uAdminsLength
;
2019 uSize
= (uSize
& (~3)) + 8;
2020 AccessToken
->DefaultDacl
=
2021 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2023 TAG('T', 'O', 'K', 'd'));
2024 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
2025 if ( NT_SUCCESS(Status
) )
2027 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
2030 if ( NT_SUCCESS(Status
) )
2032 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
2035 if ( ! NT_SUCCESS(Status
) )
2037 ObDereferenceObject(AccessToken
);
2046 NtCreateToken(OUT PHANDLE TokenHandle
,
2047 IN ACCESS_MASK DesiredAccess
,
2048 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2049 IN TOKEN_TYPE TokenType
,
2050 IN PLUID AuthenticationId
,
2051 IN PLARGE_INTEGER ExpirationTime
,
2052 IN PTOKEN_USER TokenUser
,
2053 IN PTOKEN_GROUPS TokenGroups
,
2054 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2055 IN PTOKEN_OWNER TokenOwner
,
2056 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2057 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2058 IN PTOKEN_SOURCE TokenSource
)
2067 ULONG nTokenPrivileges
= 0;
2068 LARGE_INTEGER LocalExpirationTime
= {};
2069 KPROCESSOR_MODE PreviousMode
;
2070 NTSTATUS Status
= STATUS_SUCCESS
;
2074 PreviousMode
= ExGetPreviousMode();
2076 if(PreviousMode
!= KernelMode
)
2080 ProbeForWriteHandle(TokenHandle
);
2081 ProbeForRead(AuthenticationId
,
2084 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2085 ProbeForRead(TokenUser
,
2088 ProbeForRead(TokenGroups
,
2089 sizeof(TOKEN_GROUPS
),
2091 ProbeForRead(TokenPrivileges
,
2092 sizeof(TOKEN_PRIVILEGES
),
2094 ProbeForRead(TokenOwner
,
2095 sizeof(TOKEN_OWNER
),
2097 ProbeForRead(TokenPrimaryGroup
,
2098 sizeof(TOKEN_PRIMARY_GROUP
),
2100 ProbeForRead(TokenDefaultDacl
,
2101 sizeof(TOKEN_DEFAULT_DACL
),
2103 ProbeForRead(TokenSource
,
2104 sizeof(TOKEN_SOURCE
),
2106 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2110 Status
= _SEH_GetExceptionCode();
2114 if(!NT_SUCCESS(Status
))
2121 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2122 LocalExpirationTime
= *ExpirationTime
;
2125 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2126 if (!NT_SUCCESS(Status
))
2129 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2130 if (!NT_SUCCESS(Status
))
2133 Status
= ObCreateObject(PreviousMode
,
2141 (PVOID
*)&AccessToken
);
2142 if (!NT_SUCCESS(Status
))
2144 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2148 AccessToken
->TokenLock
= &SepTokenLock
;
2150 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2151 &TokenSource
->SourceIdentifier
);
2152 memcpy(AccessToken
->TokenSource
.SourceName
,
2153 TokenSource
->SourceName
,
2154 sizeof(TokenSource
->SourceName
));
2156 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2157 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2158 AccessToken
->ExpirationTime
= *ExpirationTime
;
2159 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2161 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2162 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2163 AccessToken
->UserAndGroups
= 0;
2164 AccessToken
->Privileges
= 0;
2166 AccessToken
->TokenType
= TokenType
;
2167 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2168 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2171 * Normally we would just point these members into the variable information
2172 * area; however, our ObCreateObject() call can't allocate a variable information
2173 * area, so we allocate them seperately and provide a destroy function.
2176 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2177 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2178 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2179 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2181 AccessToken
->UserAndGroups
=
2182 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2184 TAG('T', 'O', 'K', 'u'));
2186 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2188 Status
= RtlCopySidAndAttributesArray(1,
2191 AccessToken
->UserAndGroups
,
2195 if (NT_SUCCESS(Status
))
2197 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2198 TokenGroups
->Groups
,
2200 &AccessToken
->UserAndGroups
[1],
2206 if (NT_SUCCESS(Status
))
2208 Status
= SepFindPrimaryGroupAndDefaultOwner(
2210 TokenPrimaryGroup
->PrimaryGroup
,
2214 if (NT_SUCCESS(Status
))
2216 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2217 AccessToken
->Privileges
=
2218 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2220 TAG('T', 'O', 'K', 'p'));
2222 if (PreviousMode
!= KernelMode
)
2226 RtlCopyMemory(AccessToken
->Privileges
,
2227 TokenPrivileges
->Privileges
,
2228 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2232 Status
= _SEH_GetExceptionCode();
2238 RtlCopyMemory(AccessToken
->Privileges
,
2239 TokenPrivileges
->Privileges
,
2240 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2244 if (NT_SUCCESS(Status
))
2246 AccessToken
->DefaultDacl
=
2247 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2248 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2249 TAG('T', 'O', 'K', 'd'));
2250 memcpy(AccessToken
->DefaultDacl
,
2251 TokenDefaultDacl
->DefaultDacl
,
2252 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2255 Status
= ObInsertObject ((PVOID
)AccessToken
,
2261 if (!NT_SUCCESS(Status
))
2263 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2266 ObDereferenceObject(AccessToken
);
2268 if (NT_SUCCESS(Status
))
2272 *TokenHandle
= hToken
;
2276 Status
= _SEH_GetExceptionCode();
2289 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
2294 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
2296 return STATUS_SUCCESS
;
2303 SECURITY_IMPERSONATION_LEVEL
2305 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
2309 return ((PTOKEN
)Token
)->ImpersonationLevel
;
2317 SeTokenType(IN PACCESS_TOKEN Token
)
2321 return ((PTOKEN
)Token
)->TokenType
;
2331 IN PACCESS_TOKEN Token
2343 SeTokenIsRestricted(
2344 IN PACCESS_TOKEN Token
2356 SeTokenIsWriteRestricted(
2357 IN PACCESS_TOKEN Token
2370 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2371 IN ACCESS_MASK DesiredAccess
,
2372 IN BOOLEAN OpenAsSelf
,
2373 IN ULONG HandleAttributes
,
2374 OUT PHANDLE TokenHandle
)
2378 PTOKEN Token
, NewToken
, PrimaryToken
;
2379 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2380 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2381 SE_IMPERSONATION_STATE ImpersonationState
;
2382 OBJECT_ATTRIBUTES ObjectAttributes
;
2383 SECURITY_DESCRIPTOR SecurityDescriptor
;
2385 KPROCESSOR_MODE PreviousMode
;
2386 NTSTATUS Status
= STATUS_SUCCESS
;
2390 PreviousMode
= ExGetPreviousMode();
2392 if(PreviousMode
!= KernelMode
)
2396 ProbeForWriteHandle(TokenHandle
);
2400 Status
= _SEH_GetExceptionCode();
2404 if(!NT_SUCCESS(Status
))
2411 * At first open the thread token for information access and verify
2412 * that the token associated with thread is valid.
2415 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2416 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2418 if (!NT_SUCCESS(Status
))
2423 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2424 &ImpersonationLevel
);
2427 ObfDereferenceObject(Thread
);
2428 return STATUS_NO_TOKEN
;
2431 ObDereferenceObject(Thread
);
2433 if (ImpersonationLevel
== SecurityAnonymous
)
2435 ObfDereferenceObject(Token
);
2436 return STATUS_CANT_OPEN_ANONYMOUS
;
2440 * Revert to self if OpenAsSelf is specified.
2445 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2450 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2451 PsThreadType
, PreviousMode
,
2452 (PVOID
*)&Thread
, NULL
);
2453 if (!NT_SUCCESS(Status
))
2455 ObfDereferenceObject(Token
);
2458 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2463 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2464 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2465 ObfDereferenceObject(PrimaryToken
);
2466 ObfDereferenceObject(Thread
);
2467 if (!NT_SUCCESS(Status
))
2469 ObfDereferenceObject(Token
);
2472 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2477 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2478 SECURITY_DESCRIPTOR_REVISION
);
2479 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2482 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2483 NULL
, &SecurityDescriptor
);
2485 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2486 TokenImpersonation
, ImpersonationLevel
,
2487 KernelMode
, &NewToken
);
2489 if (!NT_SUCCESS(Status
))
2491 ObfDereferenceObject(Token
);
2494 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2499 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2502 ObfDereferenceObject(NewToken
);
2506 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2507 NULL
, DesiredAccess
, SepTokenObjectType
,
2508 PreviousMode
, &hToken
);
2511 ObfDereferenceObject(Token
);
2515 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2518 if(NT_SUCCESS(Status
))
2522 *TokenHandle
= hToken
;
2526 Status
= _SEH_GetExceptionCode();
2538 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2539 IN ACCESS_MASK DesiredAccess
,
2540 IN BOOLEAN OpenAsSelf
,
2541 OUT PHANDLE TokenHandle
)
2543 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,