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
);
82 NTSTATUS
SeExchangePrimaryToken(PEPROCESS Process
,
83 PACCESS_TOKEN NewTokenP
,
84 PACCESS_TOKEN
* OldTokenP
)
87 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
91 if (NewToken
->TokenType
!= TokenPrimary
)
93 return(STATUS_UNSUCCESSFUL
);
95 if (NewToken
->TokenInUse
!= 0)
97 return(STATUS_UNSUCCESSFUL
);
99 OldToken
= Process
->Token
;
100 Process
->Token
= NewToken
;
101 NewToken
->TokenInUse
= 1;
102 ObReferenceObjectByPointer(NewToken
,
106 OldToken
->TokenInUse
= 0;
107 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
108 return(STATUS_SUCCESS
);
112 RtlLengthSidAndAttributes(ULONG Count
,
113 PSID_AND_ATTRIBUTES Src
)
120 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
121 for (i
= 0; i
< Count
; i
++)
122 uLength
+= RtlLengthSid(Src
[i
].Sid
);
129 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
135 Token
->PrimaryGroup
= 0;
139 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
142 /* Validate and set the primary group and user pointers */
143 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
146 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
148 Token
->DefaultOwnerIndex
= i
;
151 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
153 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
157 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
159 return(STATUS_INVALID_OWNER
);
162 if (Token
->PrimaryGroup
== 0)
164 return(STATUS_INVALID_PRIMARY_GROUP
);
167 return(STATUS_SUCCESS
);
173 SepDuplicateToken(PTOKEN Token
,
174 POBJECT_ATTRIBUTES ObjectAttributes
,
175 BOOLEAN EffectiveOnly
,
176 TOKEN_TYPE TokenType
,
177 SECURITY_IMPERSONATION_LEVEL Level
,
178 KPROCESSOR_MODE PreviousMode
,
179 PTOKEN
* NewAccessToken
)
189 Status
= ObCreateObject(PreviousMode
,
197 (PVOID
*)&AccessToken
);
198 if (!NT_SUCCESS(Status
))
200 DPRINT1("ObCreateObject() failed (Status %lx)\n");
204 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
205 if (!NT_SUCCESS(Status
))
207 ObDereferenceObject(AccessToken
);
211 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
212 if (!NT_SUCCESS(Status
))
214 ObDereferenceObject(AccessToken
);
218 AccessToken
->TokenLock
= &SepTokenLock
;
220 AccessToken
->TokenInUse
= 0;
221 AccessToken
->TokenType
= TokenType
;
222 AccessToken
->ImpersonationLevel
= Level
;
223 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
225 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
226 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
227 memcpy(AccessToken
->TokenSource
.SourceName
,
228 Token
->TokenSource
.SourceName
,
229 sizeof(Token
->TokenSource
.SourceName
));
230 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
231 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
232 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
234 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
235 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
236 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
238 AccessToken
->UserAndGroups
=
239 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
241 TAG('T', 'O', 'K', 'u'));
243 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
245 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
246 Token
->UserAndGroups
,
248 AccessToken
->UserAndGroups
,
252 if (NT_SUCCESS(Status
))
254 Status
= SepFindPrimaryGroupAndDefaultOwner(
260 if (NT_SUCCESS(Status
))
262 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
264 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
265 AccessToken
->Privileges
=
266 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
268 TAG('T', 'O', 'K', 'p'));
270 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
272 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
273 &Token
->Privileges
[i
].Luid
);
274 AccessToken
->Privileges
[i
].Attributes
=
275 Token
->Privileges
[i
].Attributes
;
278 if ( Token
->DefaultDacl
)
280 AccessToken
->DefaultDacl
=
281 (PACL
) ExAllocatePoolWithTag(PagedPool
,
282 Token
->DefaultDacl
->AclSize
,
283 TAG('T', 'O', 'K', 'd'));
284 memcpy(AccessToken
->DefaultDacl
,
286 Token
->DefaultDacl
->AclSize
);
290 AccessToken
->DefaultDacl
= 0;
294 if ( NT_SUCCESS(Status
) )
296 *NewAccessToken
= AccessToken
;
297 return(STATUS_SUCCESS
);
300 ObDereferenceObject(AccessToken
);
310 PACCESS_STATE AccessState
,
311 PPRIVILEGE_SET Privileges
315 return STATUS_NOT_IMPLEMENTED
;
320 SeCopyClientToken(PACCESS_TOKEN Token
,
321 SECURITY_IMPERSONATION_LEVEL Level
,
322 KPROCESSOR_MODE PreviousMode
,
323 PACCESS_TOKEN
* NewToken
)
326 OBJECT_ATTRIBUTES ObjectAttributes
;
330 InitializeObjectAttributes(&ObjectAttributes
,
335 Status
= SepDuplicateToken(Token
,
351 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
352 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
353 IN BOOLEAN RemoteClient
,
354 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
356 TOKEN_TYPE TokenType
;
358 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
361 PACCESS_TOKEN NewToken
;
365 Token
= PsReferenceEffectiveToken(Thread
,
368 &ImpersonationLevel
);
369 if (TokenType
!= TokenImpersonation
)
371 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
375 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
379 ObDereferenceObject(Token
);
381 return(STATUS_UNSUCCESSFUL
);
383 if (ImpersonationLevel
== SecurityAnonymous
||
384 ImpersonationLevel
== SecurityIdentification
||
385 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
389 ObDereferenceObject(Token
);
391 return(STATUS_UNSUCCESSFUL
);
394 Qos
->EffectiveOnly
!= 0)
396 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
400 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
404 if (Qos
->ContextTrackingMode
== 0)
406 ClientContext
->DirectlyAccessClientToken
= FALSE
;
407 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
410 // ObDeleteCapturedInsertInfo(NewToken);
412 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
414 ObDereferenceObject(Token
);
423 ClientContext
->DirectlyAccessClientToken
= TRUE
;
424 if (RemoteClient
!= FALSE
)
426 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
430 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
431 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
432 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
433 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
434 ClientContext
->ServerIsRemote
= RemoteClient
;
435 ClientContext
->ClientToken
= NewToken
;
437 return(STATUS_SUCCESS
);
445 SeCreateClientSecurityFromSubjectContext(
446 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
447 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
448 IN BOOLEAN ServerIsRemote
,
449 OUT PSECURITY_CLIENT_CONTEXT ClientContext
453 return STATUS_NOT_IMPLEMENTED
;
462 IN PACCESS_TOKEN ExistingToken
,
464 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
465 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
466 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
467 OUT PACCESS_TOKEN
* FilteredToken
471 return STATUS_NOT_IMPLEMENTED
;
480 IN PPRIVILEGE_SET Privileges
492 SeImpersonateClientEx(
493 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
494 IN PETHREAD ServerThread OPTIONAL
498 return STATUS_NOT_IMPLEMENTED
;
505 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
506 IN PETHREAD ServerThread OPTIONAL
)
512 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
514 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
518 b
= ClientContext
->DirectAccessEffectiveOnly
;
520 if (ServerThread
== NULL
)
522 ServerThread
= PsGetCurrentThread();
524 PsImpersonateClient(ServerThread
,
525 ClientContext
->ClientToken
,
528 ClientContext
->SecurityQos
.ImpersonationLevel
);
533 SepDeleteToken(PVOID ObjectBody
)
535 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
537 if (AccessToken
->UserAndGroups
)
538 ExFreePool(AccessToken
->UserAndGroups
);
540 if (AccessToken
->Privileges
)
541 ExFreePool(AccessToken
->Privileges
);
543 if (AccessToken
->DefaultDacl
)
544 ExFreePool(AccessToken
->DefaultDacl
);
549 SepInitializeTokenImplementation(VOID
)
551 ExInitializeResource(&SepTokenLock
);
553 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
555 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
556 SepTokenObjectType
->PeakObjects
= 0;
557 SepTokenObjectType
->PeakHandles
= 0;
558 SepTokenObjectType
->TotalObjects
= 0;
559 SepTokenObjectType
->TotalHandles
= 0;
560 SepTokenObjectType
->PagedPoolCharge
= 0;
561 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(TOKEN
);
562 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
563 SepTokenObjectType
->Dump
= NULL
;
564 SepTokenObjectType
->Open
= NULL
;
565 SepTokenObjectType
->Close
= NULL
;
566 SepTokenObjectType
->Delete
= SepDeleteToken
;
567 SepTokenObjectType
->Parse
= NULL
;
568 SepTokenObjectType
->Security
= NULL
;
569 SepTokenObjectType
->QueryName
= NULL
;
570 SepTokenObjectType
->OkayToClose
= NULL
;
571 SepTokenObjectType
->Create
= NULL
;
572 SepTokenObjectType
->DuplicationNotify
= NULL
;
574 RtlInitUnicodeString(&SepTokenObjectType
->TypeName
, L
"Token");
575 ObpCreateTypeObject (SepTokenObjectType
);
583 NtQueryInformationToken(IN HANDLE TokenHandle
,
584 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
585 OUT PVOID TokenInformation
,
586 IN ULONG TokenInformationLength
,
587 OUT PULONG ReturnLength
)
595 ULONG RequiredLength
;
596 KPROCESSOR_MODE PreviousMode
;
597 NTSTATUS Status
= STATUS_SUCCESS
;
601 PreviousMode
= ExGetPreviousMode();
603 /* Check buffers and class validity */
604 DefaultQueryInfoBufferCheck(TokenInformationClass
,
605 SeTokenInformationClass
,
607 TokenInformationLength
,
612 if(!NT_SUCCESS(Status
))
614 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
618 Status
= ObReferenceObjectByHandle(TokenHandle
,
619 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
624 if (NT_SUCCESS(Status
))
626 switch (TokenInformationClass
)
630 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
632 DPRINT("NtQueryInformationToken(TokenUser)\n");
633 RequiredLength
= sizeof(TOKEN_USER
) +
634 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
638 if(TokenInformationLength
>= RequiredLength
)
640 Status
= RtlCopySidAndAttributesArray(1,
641 &Token
->UserAndGroups
[0],
642 RequiredLength
- sizeof(TOKEN_USER
),
650 Status
= STATUS_BUFFER_TOO_SMALL
;
653 if(ReturnLength
!= NULL
)
655 *ReturnLength
= RequiredLength
;
660 Status
= _SEH_GetExceptionCode();
669 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
671 DPRINT("NtQueryInformationToken(TokenGroups)\n");
672 RequiredLength
= sizeof(tg
->GroupCount
) +
673 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
677 if(TokenInformationLength
>= RequiredLength
)
679 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
680 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
681 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
682 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
684 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
685 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
686 &Token
->UserAndGroups
[1],
695 Status
= STATUS_BUFFER_TOO_SMALL
;
698 if(ReturnLength
!= NULL
)
700 *ReturnLength
= RequiredLength
;
705 Status
= _SEH_GetExceptionCode();
712 case TokenPrivileges
:
714 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
716 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
717 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
718 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
722 if(TokenInformationLength
>= RequiredLength
)
724 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
725 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
731 Status
= STATUS_BUFFER_TOO_SMALL
;
734 if(ReturnLength
!= NULL
)
736 *ReturnLength
= RequiredLength
;
741 Status
= _SEH_GetExceptionCode();
751 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
753 DPRINT("NtQueryInformationToken(TokenOwner)\n");
754 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
755 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
759 if(TokenInformationLength
>= RequiredLength
)
761 to
->Owner
= (PSID
)(to
+ 1);
762 Status
= RtlCopySid(SidLen
,
764 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
768 Status
= STATUS_BUFFER_TOO_SMALL
;
771 if(ReturnLength
!= NULL
)
773 *ReturnLength
= RequiredLength
;
778 Status
= _SEH_GetExceptionCode();
785 case TokenPrimaryGroup
:
788 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
790 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
791 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
792 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
796 if(TokenInformationLength
>= RequiredLength
)
798 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
799 Status
= RtlCopySid(SidLen
,
801 Token
->PrimaryGroup
);
805 Status
= STATUS_BUFFER_TOO_SMALL
;
808 if(ReturnLength
!= NULL
)
810 *ReturnLength
= RequiredLength
;
815 Status
= _SEH_GetExceptionCode();
822 case TokenDefaultDacl
:
824 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
826 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
827 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
829 if(Token
->DefaultDacl
!= NULL
)
831 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
836 if(TokenInformationLength
>= RequiredLength
)
838 if(Token
->DefaultDacl
!= NULL
)
840 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
841 RtlCopyMemory(tdd
->DefaultDacl
,
843 Token
->DefaultDacl
->AclSize
);
847 tdd
->DefaultDacl
= NULL
;
852 Status
= STATUS_BUFFER_TOO_SMALL
;
855 if(ReturnLength
!= NULL
)
857 *ReturnLength
= RequiredLength
;
862 Status
= _SEH_GetExceptionCode();
871 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
873 DPRINT("NtQueryInformationToken(TokenSource)\n");
874 RequiredLength
= sizeof(TOKEN_SOURCE
);
878 if(TokenInformationLength
>= RequiredLength
)
880 *ts
= Token
->TokenSource
;
884 Status
= STATUS_BUFFER_TOO_SMALL
;
887 if(ReturnLength
!= NULL
)
889 *ReturnLength
= RequiredLength
;
894 Status
= _SEH_GetExceptionCode();
903 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
905 DPRINT("NtQueryInformationToken(TokenType)\n");
906 RequiredLength
= sizeof(TOKEN_TYPE
);
910 if(TokenInformationLength
>= RequiredLength
)
912 *tt
= Token
->TokenType
;
916 Status
= STATUS_BUFFER_TOO_SMALL
;
919 if(ReturnLength
!= NULL
)
921 *ReturnLength
= RequiredLength
;
926 Status
= _SEH_GetExceptionCode();
933 case TokenImpersonationLevel
:
935 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
937 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
938 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
942 if(TokenInformationLength
>= RequiredLength
)
944 *sil
= Token
->ImpersonationLevel
;
948 Status
= STATUS_BUFFER_TOO_SMALL
;
951 if(ReturnLength
!= NULL
)
953 *ReturnLength
= RequiredLength
;
958 Status
= _SEH_GetExceptionCode();
965 case TokenStatistics
:
967 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
969 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
970 RequiredLength
= sizeof(TOKEN_STATISTICS
);
974 if(TokenInformationLength
>= RequiredLength
)
976 ts
->TokenId
= Token
->TokenId
;
977 ts
->AuthenticationId
= Token
->AuthenticationId
;
978 ts
->ExpirationTime
= Token
->ExpirationTime
;
979 ts
->TokenType
= Token
->TokenType
;
980 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
981 ts
->DynamicCharged
= Token
->DynamicCharged
;
982 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
983 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
984 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
985 ts
->ModifiedId
= Token
->ModifiedId
;
989 Status
= STATUS_BUFFER_TOO_SMALL
;
992 if(ReturnLength
!= NULL
)
994 *ReturnLength
= RequiredLength
;
999 Status
= _SEH_GetExceptionCode();
1008 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1010 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1011 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1015 if(TokenInformationLength
>= RequiredLength
)
1017 RtlCopyLuid(&to
->OriginatingLogonSession
,
1018 &Token
->AuthenticationId
);
1022 Status
= STATUS_BUFFER_TOO_SMALL
;
1025 if(ReturnLength
!= NULL
)
1027 *ReturnLength
= RequiredLength
;
1032 Status
= _SEH_GetExceptionCode();
1039 case TokenGroupsAndPrivileges
:
1040 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1041 Status
= STATUS_NOT_IMPLEMENTED
;
1044 case TokenRestrictedSids
:
1045 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
1046 Status
= STATUS_NOT_IMPLEMENTED
;
1049 case TokenSandBoxInert
:
1050 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1051 Status
= STATUS_NOT_IMPLEMENTED
;
1054 case TokenSessionId
:
1056 ULONG SessionId
= 0;
1058 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1060 Status
= SeQuerySessionIdToken(Token
,
1063 if(NT_SUCCESS(Status
))
1067 /* buffer size was already verified, no need to check here again */
1068 *(PULONG
)TokenInformation
= SessionId
;
1070 if(ReturnLength
!= NULL
)
1072 *ReturnLength
= sizeof(ULONG
);
1077 Status
= _SEH_GetExceptionCode();
1086 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1087 Status
= STATUS_INVALID_INFO_CLASS
;
1091 ObDereferenceObject(Token
);
1102 SeQueryInformationToken(
1103 IN PACCESS_TOKEN Token
,
1104 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1105 OUT PVOID
*TokenInformation
1109 return STATUS_NOT_IMPLEMENTED
;
1117 SeQuerySessionIdToken(
1118 IN PACCESS_TOKEN Token
,
1119 IN PULONG pSessionId
1122 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1123 return STATUS_SUCCESS
;
1127 * NtSetTokenInformation: Partly implemented.
1129 * TokenOrigin, TokenDefaultDacl
1133 NtSetInformationToken(IN HANDLE TokenHandle
,
1134 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1135 OUT PVOID TokenInformation
,
1136 IN ULONG TokenInformationLength
)
1139 KPROCESSOR_MODE PreviousMode
;
1140 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1141 NTSTATUS Status
= STATUS_SUCCESS
;
1145 PreviousMode
= ExGetPreviousMode();
1147 DefaultSetInfoBufferCheck(TokenInformationClass
,
1148 SeTokenInformationClass
,
1150 TokenInformationLength
,
1154 if(!NT_SUCCESS(Status
))
1156 /* Invalid buffers */
1157 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1161 if(TokenInformationClass
== TokenSessionId
)
1163 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1166 Status
= ObReferenceObjectByHandle(TokenHandle
,
1172 if (NT_SUCCESS(Status
))
1174 switch (TokenInformationClass
)
1178 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1180 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1181 PSID InputSid
= NULL
;
1185 InputSid
= to
->Owner
;
1189 Status
= _SEH_GetExceptionCode();
1193 if(NT_SUCCESS(Status
))
1197 Status
= SepCaptureSid(InputSid
,
1202 if(NT_SUCCESS(Status
))
1204 RtlCopySid(RtlLengthSid(CapturedSid
),
1205 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1207 SepReleaseSid(CapturedSid
,
1215 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1220 case TokenPrimaryGroup
:
1222 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1224 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1225 PSID InputSid
= NULL
;
1229 InputSid
= tpg
->PrimaryGroup
;
1233 Status
= _SEH_GetExceptionCode();
1237 if(NT_SUCCESS(Status
))
1241 Status
= SepCaptureSid(InputSid
,
1246 if(NT_SUCCESS(Status
))
1248 RtlCopySid(RtlLengthSid(CapturedSid
),
1249 Token
->PrimaryGroup
,
1251 SepReleaseSid(CapturedSid
,
1259 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1264 case TokenDefaultDacl
:
1266 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1268 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1269 PACL InputAcl
= NULL
;
1273 InputAcl
= tdd
->DefaultDacl
;
1277 Status
= _SEH_GetExceptionCode();
1281 if(NT_SUCCESS(Status
))
1283 if(InputAcl
!= NULL
)
1287 /* capture and copy the dacl */
1288 Status
= SepCaptureAcl(InputAcl
,
1293 if(NT_SUCCESS(Status
))
1295 /* free the previous dacl if present */
1296 if(Token
->DefaultDacl
!= NULL
)
1298 ExFreePool(Token
->DefaultDacl
);
1301 /* set the new dacl */
1302 Token
->DefaultDacl
= CapturedAcl
;
1307 /* clear and free the default dacl if present */
1308 if(Token
->DefaultDacl
!= NULL
)
1310 ExFreePool(Token
->DefaultDacl
);
1311 Token
->DefaultDacl
= NULL
;
1318 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1323 case TokenSessionId
:
1325 ULONG SessionId
= 0;
1329 /* buffer size was already verified, no need to check here again */
1330 SessionId
= *(PULONG
)TokenInformation
;
1334 Status
= _SEH_GetExceptionCode();
1338 if(NT_SUCCESS(Status
))
1340 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1343 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1347 Token
->SessionId
= SessionId
;
1354 Status
= STATUS_NOT_IMPLEMENTED
;
1359 ObDereferenceObject(Token
);
1369 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1370 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1371 * is correct either. -Gunnar
1372 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1375 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1376 IN ACCESS_MASK DesiredAccess
,
1377 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1378 IN BOOLEAN EffectiveOnly
,
1379 IN TOKEN_TYPE TokenType
,
1380 OUT PHANDLE NewTokenHandle
)
1382 KPROCESSOR_MODE PreviousMode
;
1386 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1388 NTSTATUS Status
= STATUS_SUCCESS
;
1392 PreviousMode
= KeGetPreviousMode();
1394 if(PreviousMode
!= KernelMode
)
1398 ProbeForWrite(NewTokenHandle
,
1404 Status
= _SEH_GetExceptionCode();
1408 if(!NT_SUCCESS(Status
))
1414 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1418 &CapturedSecurityQualityOfService
,
1420 if(!NT_SUCCESS(Status
))
1422 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1426 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1432 if (NT_SUCCESS(Status
))
1434 Status
= SepDuplicateToken(Token
,
1438 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1442 ObDereferenceObject(Token
);
1444 if (NT_SUCCESS(Status
))
1446 Status
= ObInsertObject((PVOID
)NewToken
,
1453 ObDereferenceObject(NewToken
);
1455 if (NT_SUCCESS(Status
))
1459 *NewTokenHandle
= hToken
;
1463 Status
= _SEH_GetExceptionCode();
1470 /* free the captured structure */
1471 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1479 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1481 BOOLEAN ResetToDefault
,
1482 PSID_AND_ATTRIBUTES Groups
,
1484 KPROCESSOR_MODE PreviousMode
,
1495 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1496 IN BOOLEAN ResetToDefault
,
1497 IN PTOKEN_GROUPS NewState
,
1498 IN ULONG BufferLength
,
1499 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1500 OUT PULONG ReturnLength
)
1504 PACCESS_TOKEN Token
;
1511 Status
= ObReferenceObjectByHandle(TokenHandle
,
1519 SepAdjustGroups(Token
,
1531 return(STATUS_NOT_IMPLEMENTED
);
1538 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1540 KPROCESSOR_MODE PreviousMode
,
1541 ULONG PrivilegeCount
,
1542 PLUID_AND_ATTRIBUTES Privileges
,
1543 PTOKEN_PRIVILEGES
* PreviousState
,
1552 if (Token
->PrivilegeCount
> 0)
1554 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1556 if (PreviousMode
!= KernelMode
)
1558 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1562 if (PreviousState
!= NULL
)
1564 memcpy(&PreviousState
[i
],
1565 &Token
->Privileges
[i
],
1566 sizeof(LUID_AND_ATTRIBUTES
));
1568 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1575 if (PreviousMode
!= KernelMode
)
1577 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1581 if (PrivilegeCount
<= ?)
1594 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1595 IN BOOLEAN DisableAllPrivileges
,
1596 IN PTOKEN_PRIVILEGES NewState
,
1597 IN ULONG BufferLength
,
1598 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1599 OUT PULONG ReturnLength OPTIONAL
)
1601 // PLUID_AND_ATTRIBUTES Privileges;
1602 KPROCESSOR_MODE PreviousMode
;
1603 ULONG PrivilegeCount
;
1619 DPRINT ("NtAdjustPrivilegesToken() called\n");
1621 // PrivilegeCount = NewState->PrivilegeCount;
1622 PreviousMode
= KeGetPreviousMode ();
1623 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1633 Status
= ObReferenceObjectByHandle (TokenHandle
,
1634 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1639 if (!NT_SUCCESS(Status
))
1641 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1642 // SeReleaseLuidAndAttributesArray(Privileges,
1650 SepAdjustPrivileges(Token
,
1661 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1662 sizeof(LUID_AND_ATTRIBUTES
);
1664 if (PreviousState
!= NULL
)
1665 PreviousState
->PrivilegeCount
= 0;
1668 if (DisableAllPrivileges
== TRUE
)
1670 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1672 if (Token
->Privileges
[i
].Attributes
!= 0)
1674 DPRINT ("Attributes differ\n");
1676 /* Save current privilege */
1677 if (PreviousState
!= NULL
)
1679 if (k
< PrivilegeCount
)
1681 PreviousState
->PrivilegeCount
++;
1682 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1683 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1687 /* FIXME: Should revert all the changes, calculate how
1688 * much space would be needed, set ResultLength
1689 * accordingly and fail.
1695 /* Update current privlege */
1696 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1699 Status
= STATUS_SUCCESS
;
1704 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1706 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1708 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1709 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1711 DPRINT ("Found privilege\n");
1713 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1714 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1716 DPRINT ("Attributes differ\n");
1717 DPRINT ("Current attributes %lx desired attributes %lx\n",
1718 Token
->Privileges
[i
].Attributes
,
1719 NewState
->Privileges
[j
].Attributes
);
1721 /* Save current privilege */
1722 if (PreviousState
!= NULL
)
1724 if (k
< PrivilegeCount
)
1726 PreviousState
->PrivilegeCount
++;
1727 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1728 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1732 /* FIXME: Should revert all the changes, calculate how
1733 * much space would be needed, set ResultLength
1734 * accordingly and fail.
1740 /* Update current privlege */
1741 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1742 Token
->Privileges
[i
].Attributes
|=
1743 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1744 DPRINT ("New attributes %lx\n",
1745 Token
->Privileges
[i
].Attributes
);
1751 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1754 if (ReturnLength
!= NULL
)
1756 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1757 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1760 ObDereferenceObject (Token
);
1762 // SeReleaseLuidAndAttributesArray(Privileges,
1766 DPRINT ("NtAdjustPrivilegesToken() done\n");
1773 SepCreateSystemProcessToken(VOID
)
1781 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1782 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1783 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1784 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1791 * Initialize the token
1793 Status
= ObCreateObject(KernelMode
,
1801 (PVOID
*)&AccessToken
);
1802 if (!NT_SUCCESS(Status
))
1807 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1808 if (!NT_SUCCESS(Status
))
1810 ObDereferenceObject(AccessToken
);
1814 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1815 if (!NT_SUCCESS(Status
))
1817 ObDereferenceObject(AccessToken
);
1821 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1822 if (!NT_SUCCESS(Status
))
1824 ObDereferenceObject(AccessToken
);
1828 AccessToken
->TokenLock
= &SepTokenLock
;
1830 AccessToken
->TokenType
= TokenPrimary
;
1831 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1832 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1833 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1834 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1835 AccessToken
->ExpirationTime
.QuadPart
= -1;
1836 AccessToken
->UserAndGroupCount
= 4;
1838 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1839 uSize
+= uLocalSystemLength
;
1840 uSize
+= uWorldLength
;
1841 uSize
+= uAuthUserLength
;
1842 uSize
+= uAdminsLength
;
1844 AccessToken
->UserAndGroups
=
1845 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1847 TAG('T', 'O', 'K', 'u'));
1848 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1851 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1852 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1853 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1854 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1856 AccessToken
->DefaultOwnerIndex
= i
;
1857 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1858 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1859 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1860 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1861 SidArea
= (char*)SidArea
+ uAdminsLength
;
1863 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1864 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1865 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1866 SidArea
= (char*)SidArea
+ uWorldLength
;
1868 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1869 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1870 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1871 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1873 AccessToken
->PrivilegeCount
= 20;
1875 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1876 AccessToken
->Privileges
=
1877 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1879 TAG('T', 'O', 'K', 'p'));
1882 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1883 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1885 AccessToken
->Privileges
[i
].Attributes
= 0;
1886 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1888 AccessToken
->Privileges
[i
].Attributes
= 0;
1889 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1891 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1892 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1894 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1895 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1897 AccessToken
->Privileges
[i
].Attributes
= 0;
1898 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1900 AccessToken
->Privileges
[i
].Attributes
= 0;
1901 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1903 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1904 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1906 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1907 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1909 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1910 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1912 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1913 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1915 AccessToken
->Privileges
[i
].Attributes
= 0;
1916 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1918 AccessToken
->Privileges
[i
].Attributes
= 0;
1919 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1921 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1922 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1924 AccessToken
->Privileges
[i
].Attributes
= 0;
1925 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1927 AccessToken
->Privileges
[i
].Attributes
= 0;
1928 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1930 AccessToken
->Privileges
[i
].Attributes
= 0;
1931 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1933 AccessToken
->Privileges
[i
].Attributes
= 0;
1934 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1936 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1937 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1939 AccessToken
->Privileges
[i
].Attributes
= 0;
1940 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1942 AccessToken
->Privileges
[i
].Attributes
= 0;
1943 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1945 AccessToken
->Privileges
[i
].Attributes
= 0;
1946 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1951 uSize
= sizeof(ACL
);
1952 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1953 uSize
+= sizeof(ACE
) + uAdminsLength
;
1954 uSize
= (uSize
& (~3)) + 8;
1955 AccessToken
->DefaultDacl
=
1956 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1958 TAG('T', 'O', 'K', 'd'));
1959 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1960 if ( NT_SUCCESS(Status
) )
1962 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1965 if ( NT_SUCCESS(Status
) )
1967 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1970 if ( ! NT_SUCCESS(Status
) )
1972 ObDereferenceObject(AccessToken
);
1981 NtCreateToken(OUT PHANDLE TokenHandle
,
1982 IN ACCESS_MASK DesiredAccess
,
1983 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1984 IN TOKEN_TYPE TokenType
,
1985 IN PLUID AuthenticationId
,
1986 IN PLARGE_INTEGER ExpirationTime
,
1987 IN PTOKEN_USER TokenUser
,
1988 IN PTOKEN_GROUPS TokenGroups
,
1989 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1990 IN PTOKEN_OWNER TokenOwner
,
1991 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1992 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1993 IN PTOKEN_SOURCE TokenSource
)
2002 KPROCESSOR_MODE PreviousMode
;
2003 NTSTATUS Status
= STATUS_SUCCESS
;
2007 PreviousMode
= ExGetPreviousMode();
2009 if(PreviousMode
!= KernelMode
)
2013 ProbeForWrite(TokenHandle
,
2016 ProbeForRead(AuthenticationId
,
2019 ProbeForRead(ExpirationTime
,
2020 sizeof(LARGE_INTEGER
),
2022 ProbeForRead(TokenUser
,
2025 ProbeForRead(TokenGroups
,
2026 sizeof(TOKEN_GROUPS
),
2028 ProbeForRead(TokenPrivileges
,
2029 sizeof(TOKEN_PRIVILEGES
),
2031 ProbeForRead(TokenOwner
,
2032 sizeof(TOKEN_OWNER
),
2034 ProbeForRead(TokenPrimaryGroup
,
2035 sizeof(TOKEN_PRIMARY_GROUP
),
2037 ProbeForRead(TokenDefaultDacl
,
2038 sizeof(TOKEN_DEFAULT_DACL
),
2040 ProbeForRead(TokenSource
,
2041 sizeof(TOKEN_SOURCE
),
2046 Status
= _SEH_GetExceptionCode();
2050 if(!NT_SUCCESS(Status
))
2056 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2057 if (!NT_SUCCESS(Status
))
2060 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2061 if (!NT_SUCCESS(Status
))
2064 Status
= ObCreateObject(PreviousMode
,
2072 (PVOID
*)&AccessToken
);
2073 if (!NT_SUCCESS(Status
))
2075 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2079 AccessToken
->TokenLock
= &SepTokenLock
;
2081 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2082 &TokenSource
->SourceIdentifier
);
2083 memcpy(AccessToken
->TokenSource
.SourceName
,
2084 TokenSource
->SourceName
,
2085 sizeof(TokenSource
->SourceName
));
2087 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2088 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2089 AccessToken
->ExpirationTime
= *ExpirationTime
;
2090 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2092 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2093 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2094 AccessToken
->UserAndGroups
= 0;
2095 AccessToken
->Privileges
= 0;
2097 AccessToken
->TokenType
= TokenType
;
2098 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2099 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2102 * Normally we would just point these members into the variable information
2103 * area; however, our ObCreateObject() call can't allocate a variable information
2104 * area, so we allocate them seperately and provide a destroy function.
2107 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2108 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2109 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2110 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2112 AccessToken
->UserAndGroups
=
2113 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2115 TAG('T', 'O', 'K', 'u'));
2117 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2119 Status
= RtlCopySidAndAttributesArray(1,
2122 AccessToken
->UserAndGroups
,
2126 if (NT_SUCCESS(Status
))
2128 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2129 TokenGroups
->Groups
,
2131 &AccessToken
->UserAndGroups
[1],
2137 if (NT_SUCCESS(Status
))
2139 Status
= SepFindPrimaryGroupAndDefaultOwner(
2141 TokenPrimaryGroup
->PrimaryGroup
,
2145 if (NT_SUCCESS(Status
))
2147 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2148 AccessToken
->Privileges
=
2149 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2151 TAG('T', 'O', 'K', 'p'));
2153 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
2155 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
2156 &TokenPrivileges
->Privileges
[i
],
2157 sizeof(LUID_AND_ATTRIBUTES
));
2158 if (!NT_SUCCESS(Status
))
2163 if (NT_SUCCESS(Status
))
2165 AccessToken
->DefaultDacl
=
2166 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2167 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2168 TAG('T', 'O', 'K', 'd'));
2169 memcpy(AccessToken
->DefaultDacl
,
2170 TokenDefaultDacl
->DefaultDacl
,
2171 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2174 Status
= ObInsertObject ((PVOID
)AccessToken
,
2180 if (!NT_SUCCESS(Status
))
2182 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2185 ObDereferenceObject(AccessToken
);
2187 if (NT_SUCCESS(Status
))
2191 *TokenHandle
= hToken
;
2195 Status
= _SEH_GetExceptionCode();
2208 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
2213 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
2215 return STATUS_SUCCESS
;
2222 SECURITY_IMPERSONATION_LEVEL
2224 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
2228 return ((PTOKEN
)Token
)->ImpersonationLevel
;
2236 SeTokenType(IN PACCESS_TOKEN Token
)
2240 return ((PTOKEN
)Token
)->TokenType
;
2250 IN PACCESS_TOKEN Token
2262 SeTokenIsRestricted(
2263 IN PACCESS_TOKEN Token
2275 SeTokenIsWriteRestricted(
2276 IN PACCESS_TOKEN Token
2289 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2290 IN ACCESS_MASK DesiredAccess
,
2291 IN BOOLEAN OpenAsSelf
,
2292 IN ULONG HandleAttributes
,
2293 OUT PHANDLE TokenHandle
)
2297 PTOKEN Token
, NewToken
, PrimaryToken
;
2298 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2299 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2300 SE_IMPERSONATION_STATE ImpersonationState
;
2301 OBJECT_ATTRIBUTES ObjectAttributes
;
2302 SECURITY_DESCRIPTOR SecurityDescriptor
;
2304 KPROCESSOR_MODE PreviousMode
;
2305 NTSTATUS Status
= STATUS_SUCCESS
;
2309 PreviousMode
= ExGetPreviousMode();
2311 if(PreviousMode
!= KernelMode
)
2315 ProbeForWrite(TokenHandle
,
2321 Status
= _SEH_GetExceptionCode();
2325 if(!NT_SUCCESS(Status
))
2332 * At first open the thread token for information access and verify
2333 * that the token associated with thread is valid.
2336 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2337 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2339 if (!NT_SUCCESS(Status
))
2344 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2345 &ImpersonationLevel
);
2348 ObfDereferenceObject(Thread
);
2349 return STATUS_NO_TOKEN
;
2352 ObDereferenceObject(Thread
);
2354 if (ImpersonationLevel
== SecurityAnonymous
)
2356 ObfDereferenceObject(Token
);
2357 return STATUS_CANT_OPEN_ANONYMOUS
;
2361 * Revert to self if OpenAsSelf is specified.
2366 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2371 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2372 PsThreadType
, PreviousMode
,
2373 (PVOID
*)&Thread
, NULL
);
2374 if (!NT_SUCCESS(Status
))
2376 ObfDereferenceObject(Token
);
2379 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2384 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2385 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2386 ObfDereferenceObject(PrimaryToken
);
2387 ObfDereferenceObject(Thread
);
2388 if (!NT_SUCCESS(Status
))
2390 ObfDereferenceObject(Token
);
2393 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2398 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2399 SECURITY_DESCRIPTOR_REVISION
);
2400 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2403 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2404 NULL
, &SecurityDescriptor
);
2406 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2407 TokenImpersonation
, ImpersonationLevel
,
2408 KernelMode
, &NewToken
);
2410 if (!NT_SUCCESS(Status
))
2412 ObfDereferenceObject(Token
);
2415 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2420 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2423 ObfDereferenceObject(NewToken
);
2427 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2428 NULL
, DesiredAccess
, SepTokenObjectType
,
2429 PreviousMode
, &hToken
);
2432 ObfDereferenceObject(Token
);
2436 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2439 if(NT_SUCCESS(Status
))
2443 *TokenHandle
= hToken
;
2447 Status
= _SEH_GetExceptionCode();
2459 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2460 IN ACCESS_MASK DesiredAccess
,
2461 IN BOOLEAN OpenAsSelf
,
2462 OUT PHANDLE TokenHandle
)
2464 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,