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
);
172 SepDuplicateToken(PTOKEN Token
,
173 POBJECT_ATTRIBUTES ObjectAttributes
,
174 BOOLEAN EffectiveOnly
,
175 TOKEN_TYPE TokenType
,
176 SECURITY_IMPERSONATION_LEVEL Level
,
177 KPROCESSOR_MODE PreviousMode
,
178 PTOKEN
* NewAccessToken
)
188 Status
= ObCreateObject(PreviousMode
,
196 (PVOID
*)&AccessToken
);
197 if (!NT_SUCCESS(Status
))
199 DPRINT1("ObCreateObject() failed (Status %lx)\n");
203 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
204 if (!NT_SUCCESS(Status
))
206 ObDereferenceObject(AccessToken
);
210 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
211 if (!NT_SUCCESS(Status
))
213 ObDereferenceObject(AccessToken
);
217 AccessToken
->TokenLock
= &SepTokenLock
;
219 AccessToken
->TokenInUse
= 0;
220 AccessToken
->TokenType
= TokenType
;
221 AccessToken
->ImpersonationLevel
= Level
;
222 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
224 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
225 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
226 memcpy(AccessToken
->TokenSource
.SourceName
,
227 Token
->TokenSource
.SourceName
,
228 sizeof(Token
->TokenSource
.SourceName
));
229 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
230 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
231 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
233 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
234 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
235 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
237 AccessToken
->UserAndGroups
=
238 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
240 TAG('T', 'O', 'K', 'u'));
242 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
244 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
245 Token
->UserAndGroups
,
247 AccessToken
->UserAndGroups
,
251 if (NT_SUCCESS(Status
))
253 Status
= SepFindPrimaryGroupAndDefaultOwner(
259 if (NT_SUCCESS(Status
))
261 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
263 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
264 AccessToken
->Privileges
=
265 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
267 TAG('T', 'O', 'K', 'p'));
269 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
271 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
272 &Token
->Privileges
[i
].Luid
);
273 AccessToken
->Privileges
[i
].Attributes
=
274 Token
->Privileges
[i
].Attributes
;
277 if ( Token
->DefaultDacl
)
279 AccessToken
->DefaultDacl
=
280 (PACL
) ExAllocatePoolWithTag(PagedPool
,
281 Token
->DefaultDacl
->AclSize
,
282 TAG('T', 'O', 'K', 'd'));
283 memcpy(AccessToken
->DefaultDacl
,
285 Token
->DefaultDacl
->AclSize
);
289 AccessToken
->DefaultDacl
= 0;
293 if ( NT_SUCCESS(Status
) )
295 *NewAccessToken
= AccessToken
;
296 return(STATUS_SUCCESS
);
299 ObDereferenceObject(AccessToken
);
305 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
306 struct _EPROCESS
* ParentProcess
)
312 OBJECT_ATTRIBUTES ObjectAttributes
;
314 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
316 InitializeObjectAttributes(&ObjectAttributes
,
322 Status
= SepDuplicateToken(pParentToken
,
326 pParentToken
->ImpersonationLevel
,
329 if ( ! NT_SUCCESS(Status
) )
332 NewProcess
->Token
= pNewToken
;
333 return(STATUS_SUCCESS
);
342 PACCESS_STATE AccessState
,
343 PPRIVILEGE_SET Privileges
347 return STATUS_NOT_IMPLEMENTED
;
352 SeCopyClientToken(PACCESS_TOKEN Token
,
353 SECURITY_IMPERSONATION_LEVEL Level
,
354 KPROCESSOR_MODE PreviousMode
,
355 PACCESS_TOKEN
* NewToken
)
358 OBJECT_ATTRIBUTES ObjectAttributes
;
362 InitializeObjectAttributes(&ObjectAttributes
,
367 Status
= SepDuplicateToken(Token
,
383 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
384 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
385 IN BOOLEAN RemoteClient
,
386 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
388 TOKEN_TYPE TokenType
;
390 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
393 PACCESS_TOKEN NewToken
;
397 Token
= PsReferenceEffectiveToken(Thread
,
400 &ImpersonationLevel
);
401 if (TokenType
!= TokenImpersonation
)
403 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
407 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
411 ObDereferenceObject(Token
);
413 return(STATUS_UNSUCCESSFUL
);
415 if (ImpersonationLevel
== SecurityAnonymous
||
416 ImpersonationLevel
== SecurityIdentification
||
417 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
421 ObDereferenceObject(Token
);
423 return(STATUS_UNSUCCESSFUL
);
426 Qos
->EffectiveOnly
!= 0)
428 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
432 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
436 if (Qos
->ContextTrackingMode
== 0)
438 ClientContext
->DirectlyAccessClientToken
= FALSE
;
439 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
442 // ObDeleteCapturedInsertInfo(NewToken);
444 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
446 ObDereferenceObject(Token
);
455 ClientContext
->DirectlyAccessClientToken
= TRUE
;
456 if (RemoteClient
!= FALSE
)
458 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
462 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
463 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
464 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
465 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
466 ClientContext
->ServerIsRemote
= RemoteClient
;
467 ClientContext
->ClientToken
= NewToken
;
469 return(STATUS_SUCCESS
);
477 SeCreateClientSecurityFromSubjectContext(
478 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
479 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
480 IN BOOLEAN ServerIsRemote
,
481 OUT PSECURITY_CLIENT_CONTEXT ClientContext
485 return STATUS_NOT_IMPLEMENTED
;
494 IN PACCESS_TOKEN ExistingToken
,
496 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
497 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
498 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
499 OUT PACCESS_TOKEN
* FilteredToken
503 return STATUS_NOT_IMPLEMENTED
;
512 IN PPRIVILEGE_SET Privileges
524 SeImpersonateClientEx(
525 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
526 IN PETHREAD ServerThread OPTIONAL
530 return STATUS_NOT_IMPLEMENTED
;
537 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
538 IN PETHREAD ServerThread OPTIONAL
)
544 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
546 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
550 b
= ClientContext
->DirectAccessEffectiveOnly
;
552 if (ServerThread
== NULL
)
554 ServerThread
= PsGetCurrentThread();
556 PsImpersonateClient(ServerThread
,
557 ClientContext
->ClientToken
,
560 ClientContext
->SecurityQos
.ImpersonationLevel
);
565 SepDeleteToken(PVOID ObjectBody
)
567 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
569 if (AccessToken
->UserAndGroups
)
570 ExFreePool(AccessToken
->UserAndGroups
);
572 if (AccessToken
->Privileges
)
573 ExFreePool(AccessToken
->Privileges
);
575 if (AccessToken
->DefaultDacl
)
576 ExFreePool(AccessToken
->DefaultDacl
);
581 SepInitializeTokenImplementation(VOID
)
583 ExInitializeResource(&SepTokenLock
);
585 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
587 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
588 SepTokenObjectType
->PeakObjects
= 0;
589 SepTokenObjectType
->PeakHandles
= 0;
590 SepTokenObjectType
->TotalObjects
= 0;
591 SepTokenObjectType
->TotalHandles
= 0;
592 SepTokenObjectType
->PagedPoolCharge
= 0;
593 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(TOKEN
);
594 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
595 SepTokenObjectType
->Dump
= NULL
;
596 SepTokenObjectType
->Open
= NULL
;
597 SepTokenObjectType
->Close
= NULL
;
598 SepTokenObjectType
->Delete
= SepDeleteToken
;
599 SepTokenObjectType
->Parse
= NULL
;
600 SepTokenObjectType
->Security
= NULL
;
601 SepTokenObjectType
->QueryName
= NULL
;
602 SepTokenObjectType
->OkayToClose
= NULL
;
603 SepTokenObjectType
->Create
= NULL
;
604 SepTokenObjectType
->DuplicationNotify
= NULL
;
606 RtlInitUnicodeString(&SepTokenObjectType
->TypeName
, L
"Token");
607 ObpCreateTypeObject (SepTokenObjectType
);
615 NtQueryInformationToken(IN HANDLE TokenHandle
,
616 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
617 OUT PVOID TokenInformation
,
618 IN ULONG TokenInformationLength
,
619 OUT PULONG ReturnLength
)
627 ULONG RequiredLength
;
628 KPROCESSOR_MODE PreviousMode
;
629 NTSTATUS Status
= STATUS_SUCCESS
;
633 PreviousMode
= ExGetPreviousMode();
635 /* Check buffers and class validity */
636 DefaultQueryInfoBufferCheck(TokenInformationClass
,
637 SeTokenInformationClass
,
639 TokenInformationLength
,
644 if(!NT_SUCCESS(Status
))
646 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
650 Status
= ObReferenceObjectByHandle(TokenHandle
,
651 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
656 if (NT_SUCCESS(Status
))
658 switch (TokenInformationClass
)
662 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
664 DPRINT("NtQueryInformationToken(TokenUser)\n");
665 RequiredLength
= sizeof(TOKEN_USER
) +
666 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
670 if(TokenInformationLength
>= RequiredLength
)
672 Status
= RtlCopySidAndAttributesArray(1,
673 &Token
->UserAndGroups
[0],
674 RequiredLength
- sizeof(TOKEN_USER
),
682 Status
= STATUS_BUFFER_TOO_SMALL
;
685 if(ReturnLength
!= NULL
)
687 *ReturnLength
= RequiredLength
;
692 Status
= _SEH_GetExceptionCode();
701 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
703 DPRINT("NtQueryInformationToken(TokenGroups)\n");
704 RequiredLength
= sizeof(tg
->GroupCount
) +
705 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
709 if(TokenInformationLength
>= RequiredLength
)
711 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
712 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
713 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
714 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
716 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
717 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
718 &Token
->UserAndGroups
[1],
727 Status
= STATUS_BUFFER_TOO_SMALL
;
730 if(ReturnLength
!= NULL
)
732 *ReturnLength
= RequiredLength
;
737 Status
= _SEH_GetExceptionCode();
744 case TokenPrivileges
:
746 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
748 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
749 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
750 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
754 if(TokenInformationLength
>= RequiredLength
)
756 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
757 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
763 Status
= STATUS_BUFFER_TOO_SMALL
;
766 if(ReturnLength
!= NULL
)
768 *ReturnLength
= RequiredLength
;
773 Status
= _SEH_GetExceptionCode();
783 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
785 DPRINT("NtQueryInformationToken(TokenOwner)\n");
786 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
787 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
791 if(TokenInformationLength
>= RequiredLength
)
793 to
->Owner
= (PSID
)(to
+ 1);
794 Status
= RtlCopySid(SidLen
,
796 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
800 Status
= STATUS_BUFFER_TOO_SMALL
;
803 if(ReturnLength
!= NULL
)
805 *ReturnLength
= RequiredLength
;
810 Status
= _SEH_GetExceptionCode();
817 case TokenPrimaryGroup
:
820 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
822 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
823 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
824 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
828 if(TokenInformationLength
>= RequiredLength
)
830 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
831 Status
= RtlCopySid(SidLen
,
833 Token
->PrimaryGroup
);
837 Status
= STATUS_BUFFER_TOO_SMALL
;
840 if(ReturnLength
!= NULL
)
842 *ReturnLength
= RequiredLength
;
847 Status
= _SEH_GetExceptionCode();
854 case TokenDefaultDacl
:
856 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
858 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
859 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
861 if(Token
->DefaultDacl
!= NULL
)
863 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
868 if(TokenInformationLength
>= RequiredLength
)
870 if(Token
->DefaultDacl
!= NULL
)
872 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
873 RtlCopyMemory(tdd
->DefaultDacl
,
875 Token
->DefaultDacl
->AclSize
);
879 tdd
->DefaultDacl
= NULL
;
884 Status
= STATUS_BUFFER_TOO_SMALL
;
887 if(ReturnLength
!= NULL
)
889 *ReturnLength
= RequiredLength
;
894 Status
= _SEH_GetExceptionCode();
903 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
905 DPRINT("NtQueryInformationToken(TokenSource)\n");
906 RequiredLength
= sizeof(TOKEN_SOURCE
);
910 if(TokenInformationLength
>= RequiredLength
)
912 *ts
= Token
->TokenSource
;
916 Status
= STATUS_BUFFER_TOO_SMALL
;
919 if(ReturnLength
!= NULL
)
921 *ReturnLength
= RequiredLength
;
926 Status
= _SEH_GetExceptionCode();
935 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
937 DPRINT("NtQueryInformationToken(TokenType)\n");
938 RequiredLength
= sizeof(TOKEN_TYPE
);
942 if(TokenInformationLength
>= RequiredLength
)
944 *tt
= Token
->TokenType
;
948 Status
= STATUS_BUFFER_TOO_SMALL
;
951 if(ReturnLength
!= NULL
)
953 *ReturnLength
= RequiredLength
;
958 Status
= _SEH_GetExceptionCode();
965 case TokenImpersonationLevel
:
967 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
969 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
970 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
974 if(TokenInformationLength
>= RequiredLength
)
976 *sil
= Token
->ImpersonationLevel
;
980 Status
= STATUS_BUFFER_TOO_SMALL
;
983 if(ReturnLength
!= NULL
)
985 *ReturnLength
= RequiredLength
;
990 Status
= _SEH_GetExceptionCode();
997 case TokenStatistics
:
999 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1001 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1002 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1006 if(TokenInformationLength
>= RequiredLength
)
1008 ts
->TokenId
= Token
->TokenId
;
1009 ts
->AuthenticationId
= Token
->AuthenticationId
;
1010 ts
->ExpirationTime
= Token
->ExpirationTime
;
1011 ts
->TokenType
= Token
->TokenType
;
1012 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1013 ts
->DynamicCharged
= Token
->DynamicCharged
;
1014 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1015 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1016 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1017 ts
->ModifiedId
= Token
->ModifiedId
;
1021 Status
= STATUS_BUFFER_TOO_SMALL
;
1024 if(ReturnLength
!= NULL
)
1026 *ReturnLength
= RequiredLength
;
1031 Status
= _SEH_GetExceptionCode();
1040 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1042 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1043 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1047 if(TokenInformationLength
>= RequiredLength
)
1049 RtlCopyLuid(&to
->OriginatingLogonSession
,
1050 &Token
->AuthenticationId
);
1054 Status
= STATUS_BUFFER_TOO_SMALL
;
1057 if(ReturnLength
!= NULL
)
1059 *ReturnLength
= RequiredLength
;
1064 Status
= _SEH_GetExceptionCode();
1071 case TokenGroupsAndPrivileges
:
1072 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1073 Status
= STATUS_NOT_IMPLEMENTED
;
1076 case TokenRestrictedSids
:
1077 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
1078 Status
= STATUS_NOT_IMPLEMENTED
;
1081 case TokenSandBoxInert
:
1082 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1083 Status
= STATUS_NOT_IMPLEMENTED
;
1086 case TokenSessionId
:
1088 ULONG SessionId
= 0;
1090 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1092 Status
= SeQuerySessionIdToken(Token
,
1095 if(NT_SUCCESS(Status
))
1099 /* buffer size was already verified, no need to check here again */
1100 *(PULONG
)TokenInformation
= SessionId
;
1102 if(ReturnLength
!= NULL
)
1104 *ReturnLength
= sizeof(ULONG
);
1109 Status
= _SEH_GetExceptionCode();
1118 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1119 Status
= STATUS_INVALID_INFO_CLASS
;
1123 ObDereferenceObject(Token
);
1134 SeQueryInformationToken(
1135 IN PACCESS_TOKEN Token
,
1136 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1137 OUT PVOID
*TokenInformation
1141 return STATUS_NOT_IMPLEMENTED
;
1149 SeQuerySessionIdToken(
1150 IN PACCESS_TOKEN Token
,
1151 IN PULONG pSessionId
1154 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
1155 return STATUS_SUCCESS
;
1159 * NtSetTokenInformation: Partly implemented.
1161 * TokenOrigin, TokenDefaultDacl
1165 NtSetInformationToken(IN HANDLE TokenHandle
,
1166 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1167 OUT PVOID TokenInformation
,
1168 IN ULONG TokenInformationLength
)
1171 KPROCESSOR_MODE PreviousMode
;
1172 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1173 NTSTATUS Status
= STATUS_SUCCESS
;
1177 PreviousMode
= ExGetPreviousMode();
1179 DefaultSetInfoBufferCheck(TokenInformationClass
,
1180 SeTokenInformationClass
,
1182 TokenInformationLength
,
1186 if(!NT_SUCCESS(Status
))
1188 /* Invalid buffers */
1189 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1193 if(TokenInformationClass
== TokenSessionId
)
1195 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1198 Status
= ObReferenceObjectByHandle(TokenHandle
,
1204 if (NT_SUCCESS(Status
))
1206 switch (TokenInformationClass
)
1210 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1212 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1213 PSID InputSid
= NULL
;
1217 InputSid
= to
->Owner
;
1221 Status
= _SEH_GetExceptionCode();
1225 if(NT_SUCCESS(Status
))
1229 Status
= SepCaptureSid(InputSid
,
1234 if(NT_SUCCESS(Status
))
1236 RtlCopySid(RtlLengthSid(CapturedSid
),
1237 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1239 SepReleaseSid(CapturedSid
,
1247 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1252 case TokenPrimaryGroup
:
1254 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1256 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1257 PSID InputSid
= NULL
;
1261 InputSid
= tpg
->PrimaryGroup
;
1265 Status
= _SEH_GetExceptionCode();
1269 if(NT_SUCCESS(Status
))
1273 Status
= SepCaptureSid(InputSid
,
1278 if(NT_SUCCESS(Status
))
1280 RtlCopySid(RtlLengthSid(CapturedSid
),
1281 Token
->PrimaryGroup
,
1283 SepReleaseSid(CapturedSid
,
1291 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1296 case TokenDefaultDacl
:
1298 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1300 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1301 PACL InputAcl
= NULL
;
1305 InputAcl
= tdd
->DefaultDacl
;
1309 Status
= _SEH_GetExceptionCode();
1313 if(NT_SUCCESS(Status
))
1315 if(InputAcl
!= NULL
)
1319 /* capture and copy the dacl */
1320 Status
= SepCaptureAcl(InputAcl
,
1325 if(NT_SUCCESS(Status
))
1327 /* free the previous dacl if present */
1328 if(Token
->DefaultDacl
!= NULL
)
1330 ExFreePool(Token
->DefaultDacl
);
1333 /* set the new dacl */
1334 Token
->DefaultDacl
= CapturedAcl
;
1339 /* clear and free the default dacl if present */
1340 if(Token
->DefaultDacl
!= NULL
)
1342 ExFreePool(Token
->DefaultDacl
);
1343 Token
->DefaultDacl
= NULL
;
1350 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1355 case TokenSessionId
:
1357 ULONG SessionId
= 0;
1361 /* buffer size was already verified, no need to check here again */
1362 SessionId
= *(PULONG
)TokenInformation
;
1366 Status
= _SEH_GetExceptionCode();
1370 if(NT_SUCCESS(Status
))
1372 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1375 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1379 Token
->SessionId
= SessionId
;
1386 Status
= STATUS_NOT_IMPLEMENTED
;
1391 ObDereferenceObject(Token
);
1401 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1402 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1403 * is correct either. -Gunnar
1404 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1407 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1408 IN ACCESS_MASK DesiredAccess
,
1409 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1410 IN BOOLEAN EffectiveOnly
,
1411 IN TOKEN_TYPE TokenType
,
1412 OUT PHANDLE NewTokenHandle
)
1414 KPROCESSOR_MODE PreviousMode
;
1418 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1420 NTSTATUS Status
= STATUS_SUCCESS
;
1424 PreviousMode
= KeGetPreviousMode();
1426 if(PreviousMode
!= KernelMode
)
1430 ProbeForWrite(NewTokenHandle
,
1436 Status
= _SEH_GetExceptionCode();
1440 if(!NT_SUCCESS(Status
))
1446 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1450 &CapturedSecurityQualityOfService
,
1452 if(!NT_SUCCESS(Status
))
1454 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1458 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1464 if (NT_SUCCESS(Status
))
1466 Status
= SepDuplicateToken(Token
,
1470 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1474 ObDereferenceObject(Token
);
1476 if (NT_SUCCESS(Status
))
1478 Status
= ObInsertObject((PVOID
)NewToken
,
1485 ObDereferenceObject(NewToken
);
1487 if (NT_SUCCESS(Status
))
1491 *NewTokenHandle
= hToken
;
1495 Status
= _SEH_GetExceptionCode();
1502 /* free the captured structure */
1503 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1511 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1513 BOOLEAN ResetToDefault
,
1514 PSID_AND_ATTRIBUTES Groups
,
1516 KPROCESSOR_MODE PreviousMode
,
1527 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1528 IN BOOLEAN ResetToDefault
,
1529 IN PTOKEN_GROUPS NewState
,
1530 IN ULONG BufferLength
,
1531 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1532 OUT PULONG ReturnLength
)
1536 PACCESS_TOKEN Token
;
1543 Status
= ObReferenceObjectByHandle(TokenHandle
,
1551 SepAdjustGroups(Token
,
1563 return(STATUS_NOT_IMPLEMENTED
);
1570 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1572 KPROCESSOR_MODE PreviousMode
,
1573 ULONG PrivilegeCount
,
1574 PLUID_AND_ATTRIBUTES Privileges
,
1575 PTOKEN_PRIVILEGES
* PreviousState
,
1584 if (Token
->PrivilegeCount
> 0)
1586 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1588 if (PreviousMode
!= KernelMode
)
1590 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1594 if (PreviousState
!= NULL
)
1596 memcpy(&PreviousState
[i
],
1597 &Token
->Privileges
[i
],
1598 sizeof(LUID_AND_ATTRIBUTES
));
1600 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1607 if (PreviousMode
!= KernelMode
)
1609 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1613 if (PrivilegeCount
<= ?)
1626 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1627 IN BOOLEAN DisableAllPrivileges
,
1628 IN PTOKEN_PRIVILEGES NewState
,
1629 IN ULONG BufferLength
,
1630 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1631 OUT PULONG ReturnLength OPTIONAL
)
1633 // PLUID_AND_ATTRIBUTES Privileges;
1634 KPROCESSOR_MODE PreviousMode
;
1635 ULONG PrivilegeCount
;
1651 DPRINT ("NtAdjustPrivilegesToken() called\n");
1653 // PrivilegeCount = NewState->PrivilegeCount;
1654 PreviousMode
= KeGetPreviousMode ();
1655 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1665 Status
= ObReferenceObjectByHandle (TokenHandle
,
1666 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1671 if (!NT_SUCCESS(Status
))
1673 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1674 // SeReleaseLuidAndAttributesArray(Privileges,
1682 SepAdjustPrivileges(Token
,
1693 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1694 sizeof(LUID_AND_ATTRIBUTES
);
1696 if (PreviousState
!= NULL
)
1697 PreviousState
->PrivilegeCount
= 0;
1700 if (DisableAllPrivileges
== TRUE
)
1702 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1704 if (Token
->Privileges
[i
].Attributes
!= 0)
1706 DPRINT ("Attributes differ\n");
1708 /* Save current privilege */
1709 if (PreviousState
!= NULL
)
1711 if (k
< PrivilegeCount
)
1713 PreviousState
->PrivilegeCount
++;
1714 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1715 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1719 /* FIXME: Should revert all the changes, calculate how
1720 * much space would be needed, set ResultLength
1721 * accordingly and fail.
1727 /* Update current privlege */
1728 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1731 Status
= STATUS_SUCCESS
;
1736 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1738 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1740 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1741 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1743 DPRINT ("Found privilege\n");
1745 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1746 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1748 DPRINT ("Attributes differ\n");
1749 DPRINT ("Current attributes %lx desired attributes %lx\n",
1750 Token
->Privileges
[i
].Attributes
,
1751 NewState
->Privileges
[j
].Attributes
);
1753 /* Save current privilege */
1754 if (PreviousState
!= NULL
)
1756 if (k
< PrivilegeCount
)
1758 PreviousState
->PrivilegeCount
++;
1759 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1760 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1764 /* FIXME: Should revert all the changes, calculate how
1765 * much space would be needed, set ResultLength
1766 * accordingly and fail.
1772 /* Update current privlege */
1773 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1774 Token
->Privileges
[i
].Attributes
|=
1775 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1776 DPRINT ("New attributes %lx\n",
1777 Token
->Privileges
[i
].Attributes
);
1783 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1786 if (ReturnLength
!= NULL
)
1788 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1789 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1792 ObDereferenceObject (Token
);
1794 // SeReleaseLuidAndAttributesArray(Privileges,
1798 DPRINT ("NtAdjustPrivilegesToken() done\n");
1805 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
1813 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1814 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1815 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1816 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1823 * Initialize the token
1825 Status
= ObCreateObject(KernelMode
,
1833 (PVOID
*)&AccessToken
);
1834 if (!NT_SUCCESS(Status
))
1839 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1840 if (!NT_SUCCESS(Status
))
1842 ObDereferenceObject(AccessToken
);
1846 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1847 if (!NT_SUCCESS(Status
))
1849 ObDereferenceObject(AccessToken
);
1853 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1854 if (!NT_SUCCESS(Status
))
1856 ObDereferenceObject(AccessToken
);
1860 AccessToken
->TokenLock
= &SepTokenLock
;
1862 AccessToken
->TokenType
= TokenPrimary
;
1863 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1864 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1865 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1866 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1867 AccessToken
->ExpirationTime
.QuadPart
= -1;
1868 AccessToken
->UserAndGroupCount
= 4;
1870 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1871 uSize
+= uLocalSystemLength
;
1872 uSize
+= uWorldLength
;
1873 uSize
+= uAuthUserLength
;
1874 uSize
+= uAdminsLength
;
1876 AccessToken
->UserAndGroups
=
1877 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1879 TAG('T', 'O', 'K', 'u'));
1880 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1883 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1884 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1885 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1886 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1888 AccessToken
->DefaultOwnerIndex
= i
;
1889 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1890 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1891 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1892 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1893 SidArea
= (char*)SidArea
+ uAdminsLength
;
1895 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1896 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1897 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1898 SidArea
= (char*)SidArea
+ uWorldLength
;
1900 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1901 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1902 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1903 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1905 AccessToken
->PrivilegeCount
= 20;
1907 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1908 AccessToken
->Privileges
=
1909 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1911 TAG('T', 'O', 'K', 'p'));
1914 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1915 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1917 AccessToken
->Privileges
[i
].Attributes
= 0;
1918 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1920 AccessToken
->Privileges
[i
].Attributes
= 0;
1921 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1923 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1924 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1926 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1927 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1929 AccessToken
->Privileges
[i
].Attributes
= 0;
1930 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1932 AccessToken
->Privileges
[i
].Attributes
= 0;
1933 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1935 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1936 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1938 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1939 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1941 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1942 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1944 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1945 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1947 AccessToken
->Privileges
[i
].Attributes
= 0;
1948 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1950 AccessToken
->Privileges
[i
].Attributes
= 0;
1951 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1953 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1954 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1956 AccessToken
->Privileges
[i
].Attributes
= 0;
1957 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1959 AccessToken
->Privileges
[i
].Attributes
= 0;
1960 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1962 AccessToken
->Privileges
[i
].Attributes
= 0;
1963 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1965 AccessToken
->Privileges
[i
].Attributes
= 0;
1966 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1968 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1969 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1971 AccessToken
->Privileges
[i
].Attributes
= 0;
1972 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1974 AccessToken
->Privileges
[i
].Attributes
= 0;
1975 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1977 AccessToken
->Privileges
[i
].Attributes
= 0;
1978 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1983 uSize
= sizeof(ACL
);
1984 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1985 uSize
+= sizeof(ACE
) + uAdminsLength
;
1986 uSize
= (uSize
& (~3)) + 8;
1987 AccessToken
->DefaultDacl
=
1988 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1990 TAG('T', 'O', 'K', 'd'));
1991 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1992 if ( NT_SUCCESS(Status
) )
1994 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1997 if ( NT_SUCCESS(Status
) )
1999 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
2002 if ( ! NT_SUCCESS(Status
) )
2004 ObDereferenceObject(AccessToken
);
2008 Process
->Token
= AccessToken
;
2009 return(STATUS_SUCCESS
);
2014 NtCreateToken(OUT PHANDLE TokenHandle
,
2015 IN ACCESS_MASK DesiredAccess
,
2016 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2017 IN TOKEN_TYPE TokenType
,
2018 IN PLUID AuthenticationId
,
2019 IN PLARGE_INTEGER ExpirationTime
,
2020 IN PTOKEN_USER TokenUser
,
2021 IN PTOKEN_GROUPS TokenGroups
,
2022 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2023 IN PTOKEN_OWNER TokenOwner
,
2024 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2025 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2026 IN PTOKEN_SOURCE TokenSource
)
2035 KPROCESSOR_MODE PreviousMode
;
2036 NTSTATUS Status
= STATUS_SUCCESS
;
2040 PreviousMode
= ExGetPreviousMode();
2042 if(PreviousMode
!= KernelMode
)
2046 ProbeForWrite(TokenHandle
,
2049 ProbeForRead(AuthenticationId
,
2052 ProbeForRead(ExpirationTime
,
2053 sizeof(LARGE_INTEGER
),
2055 ProbeForRead(TokenUser
,
2058 ProbeForRead(TokenGroups
,
2059 sizeof(TOKEN_GROUPS
),
2061 ProbeForRead(TokenPrivileges
,
2062 sizeof(TOKEN_PRIVILEGES
),
2064 ProbeForRead(TokenOwner
,
2065 sizeof(TOKEN_OWNER
),
2067 ProbeForRead(TokenPrimaryGroup
,
2068 sizeof(TOKEN_PRIMARY_GROUP
),
2070 ProbeForRead(TokenDefaultDacl
,
2071 sizeof(TOKEN_DEFAULT_DACL
),
2073 ProbeForRead(TokenSource
,
2074 sizeof(TOKEN_SOURCE
),
2079 Status
= _SEH_GetExceptionCode();
2083 if(!NT_SUCCESS(Status
))
2089 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2090 if (!NT_SUCCESS(Status
))
2093 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2094 if (!NT_SUCCESS(Status
))
2097 Status
= ObCreateObject(PreviousMode
,
2105 (PVOID
*)&AccessToken
);
2106 if (!NT_SUCCESS(Status
))
2108 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2112 AccessToken
->TokenLock
= &SepTokenLock
;
2114 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2115 &TokenSource
->SourceIdentifier
);
2116 memcpy(AccessToken
->TokenSource
.SourceName
,
2117 TokenSource
->SourceName
,
2118 sizeof(TokenSource
->SourceName
));
2120 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2121 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2122 AccessToken
->ExpirationTime
= *ExpirationTime
;
2123 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2125 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2126 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2127 AccessToken
->UserAndGroups
= 0;
2128 AccessToken
->Privileges
= 0;
2130 AccessToken
->TokenType
= TokenType
;
2131 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2132 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2135 * Normally we would just point these members into the variable information
2136 * area; however, our ObCreateObject() call can't allocate a variable information
2137 * area, so we allocate them seperately and provide a destroy function.
2140 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2141 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2142 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2143 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2145 AccessToken
->UserAndGroups
=
2146 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2148 TAG('T', 'O', 'K', 'u'));
2150 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2152 Status
= RtlCopySidAndAttributesArray(1,
2155 AccessToken
->UserAndGroups
,
2159 if (NT_SUCCESS(Status
))
2161 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2162 TokenGroups
->Groups
,
2164 &AccessToken
->UserAndGroups
[1],
2170 if (NT_SUCCESS(Status
))
2172 Status
= SepFindPrimaryGroupAndDefaultOwner(
2174 TokenPrimaryGroup
->PrimaryGroup
,
2178 if (NT_SUCCESS(Status
))
2180 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2181 AccessToken
->Privileges
=
2182 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2184 TAG('T', 'O', 'K', 'p'));
2186 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
2188 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
2189 &TokenPrivileges
->Privileges
[i
],
2190 sizeof(LUID_AND_ATTRIBUTES
));
2191 if (!NT_SUCCESS(Status
))
2196 if (NT_SUCCESS(Status
))
2198 AccessToken
->DefaultDacl
=
2199 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2200 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2201 TAG('T', 'O', 'K', 'd'));
2202 memcpy(AccessToken
->DefaultDacl
,
2203 TokenDefaultDacl
->DefaultDacl
,
2204 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2207 Status
= ObInsertObject ((PVOID
)AccessToken
,
2213 if (!NT_SUCCESS(Status
))
2215 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2218 ObDereferenceObject(AccessToken
);
2220 if (NT_SUCCESS(Status
))
2224 *TokenHandle
= hToken
;
2228 Status
= _SEH_GetExceptionCode();
2241 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
2246 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
2248 return STATUS_SUCCESS
;
2255 SECURITY_IMPERSONATION_LEVEL
2257 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
2261 return ((PTOKEN
)Token
)->ImpersonationLevel
;
2269 SeTokenType(IN PACCESS_TOKEN Token
)
2273 return ((PTOKEN
)Token
)->TokenType
;
2283 IN PACCESS_TOKEN Token
2295 SeTokenIsRestricted(
2296 IN PACCESS_TOKEN Token
2308 SeTokenIsWriteRestricted(
2309 IN PACCESS_TOKEN Token
2322 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2323 IN ACCESS_MASK DesiredAccess
,
2324 IN BOOLEAN OpenAsSelf
,
2325 IN ULONG HandleAttributes
,
2326 OUT PHANDLE TokenHandle
)
2330 PTOKEN Token
, NewToken
, PrimaryToken
;
2331 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2332 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2333 SE_IMPERSONATION_STATE ImpersonationState
;
2334 OBJECT_ATTRIBUTES ObjectAttributes
;
2335 SECURITY_DESCRIPTOR SecurityDescriptor
;
2337 KPROCESSOR_MODE PreviousMode
;
2338 NTSTATUS Status
= STATUS_SUCCESS
;
2342 PreviousMode
= ExGetPreviousMode();
2344 if(PreviousMode
!= KernelMode
)
2348 ProbeForWrite(TokenHandle
,
2354 Status
= _SEH_GetExceptionCode();
2358 if(!NT_SUCCESS(Status
))
2365 * At first open the thread token for information access and verify
2366 * that the token associated with thread is valid.
2369 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2370 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2372 if (!NT_SUCCESS(Status
))
2377 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2378 &ImpersonationLevel
);
2381 ObfDereferenceObject(Thread
);
2382 return STATUS_NO_TOKEN
;
2385 ObDereferenceObject(Thread
);
2387 if (ImpersonationLevel
== SecurityAnonymous
)
2389 ObfDereferenceObject(Token
);
2390 return STATUS_CANT_OPEN_ANONYMOUS
;
2394 * Revert to self if OpenAsSelf is specified.
2399 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2404 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2405 PsThreadType
, PreviousMode
,
2406 (PVOID
*)&Thread
, NULL
);
2407 if (!NT_SUCCESS(Status
))
2409 ObfDereferenceObject(Token
);
2412 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2417 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2418 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2419 ObfDereferenceObject(PrimaryToken
);
2420 ObfDereferenceObject(Thread
);
2421 if (!NT_SUCCESS(Status
))
2423 ObfDereferenceObject(Token
);
2426 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2431 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2432 SECURITY_DESCRIPTOR_REVISION
);
2433 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2436 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2437 NULL
, &SecurityDescriptor
);
2439 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2440 TokenImpersonation
, ImpersonationLevel
,
2441 KernelMode
, &NewToken
);
2443 if (!NT_SUCCESS(Status
))
2445 ObfDereferenceObject(Token
);
2448 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2453 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2456 ObfDereferenceObject(NewToken
);
2460 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2461 NULL
, DesiredAccess
, SepTokenObjectType
,
2462 PreviousMode
, &hToken
);
2465 ObfDereferenceObject(Token
);
2469 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2472 if(NT_SUCCESS(Status
))
2476 *TokenHandle
= hToken
;
2480 Status
= _SEH_GetExceptionCode();
2492 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2493 IN ACCESS_MASK DesiredAccess
,
2494 IN BOOLEAN OpenAsSelf
,
2495 OUT PHANDLE TokenHandle
)
2497 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,