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
;
22 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
27 /* FUNCTIONS *****************************************************************/
29 VOID
SepFreeProxyData(PVOID ProxyData
)
34 NTSTATUS
SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
37 return(STATUS_NOT_IMPLEMENTED
);
40 NTSTATUS
SeExchangePrimaryToken(PEPROCESS Process
,
41 PACCESS_TOKEN NewTokenP
,
42 PACCESS_TOKEN
* OldTokenP
)
45 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
47 if (NewToken
->TokenType
!= TokenPrimary
)
49 return(STATUS_UNSUCCESSFUL
);
51 if (NewToken
->TokenInUse
!= 0)
53 return(STATUS_UNSUCCESSFUL
);
55 OldToken
= Process
->Token
;
56 Process
->Token
= NewToken
;
57 NewToken
->TokenInUse
= 1;
58 ObReferenceObjectByPointer(NewToken
,
62 OldToken
->TokenInUse
= 0;
63 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
64 return(STATUS_SUCCESS
);
68 RtlLengthSidAndAttributes(ULONG Count
,
69 PSID_AND_ATTRIBUTES Src
)
74 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
75 for (i
= 0; i
< Count
; i
++)
76 uLength
+= RtlLengthSid(Src
[i
].Sid
);
83 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
89 Token
->PrimaryGroup
= 0;
93 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
96 /* Validate and set the primary group and user pointers */
97 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
100 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
102 Token
->DefaultOwnerIndex
= i
;
105 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
107 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
111 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
113 return(STATUS_INVALID_OWNER
);
116 if (Token
->PrimaryGroup
== 0)
118 return(STATUS_INVALID_PRIMARY_GROUP
);
121 return(STATUS_SUCCESS
);
126 SepDuplicateToken(PTOKEN Token
,
127 POBJECT_ATTRIBUTES ObjectAttributes
,
128 BOOLEAN EffectiveOnly
,
129 TOKEN_TYPE TokenType
,
130 SECURITY_IMPERSONATION_LEVEL Level
,
131 KPROCESSOR_MODE PreviousMode
,
132 PTOKEN
* NewAccessToken
)
142 Status
= ObCreateObject(PreviousMode
,
150 (PVOID
*)&AccessToken
);
151 if (!NT_SUCCESS(Status
))
153 DPRINT1("ObCreateObject() failed (Status %lx)\n");
157 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
158 if (!NT_SUCCESS(Status
))
160 ObDereferenceObject(AccessToken
);
164 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
165 if (!NT_SUCCESS(Status
))
167 ObDereferenceObject(AccessToken
);
171 AccessToken
->TokenInUse
= 0;
172 AccessToken
->TokenType
= TokenType
;
173 AccessToken
->ImpersonationLevel
= Level
;
174 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
176 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
177 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
178 memcpy(AccessToken
->TokenSource
.SourceName
,
179 Token
->TokenSource
.SourceName
,
180 sizeof(Token
->TokenSource
.SourceName
));
181 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
182 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
183 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
185 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
186 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
187 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
189 AccessToken
->UserAndGroups
=
190 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
192 TAG('T', 'O', 'K', 'u'));
194 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
196 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
197 Token
->UserAndGroups
,
199 AccessToken
->UserAndGroups
,
203 if (NT_SUCCESS(Status
))
205 Status
= SepFindPrimaryGroupAndDefaultOwner(
211 if (NT_SUCCESS(Status
))
213 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
215 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
216 AccessToken
->Privileges
=
217 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
219 TAG('T', 'O', 'K', 'p'));
221 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
223 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
224 &Token
->Privileges
[i
].Luid
);
225 AccessToken
->Privileges
[i
].Attributes
=
226 Token
->Privileges
[i
].Attributes
;
229 if ( Token
->DefaultDacl
)
231 AccessToken
->DefaultDacl
=
232 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
233 Token
->DefaultDacl
->AclSize
,
234 TAG('T', 'O', 'K', 'd'));
235 memcpy(AccessToken
->DefaultDacl
,
237 Token
->DefaultDacl
->AclSize
);
241 AccessToken
->DefaultDacl
= 0;
245 if ( NT_SUCCESS(Status
) )
247 *NewAccessToken
= AccessToken
;
248 return(STATUS_SUCCESS
);
251 ObDereferenceObject(AccessToken
);
257 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
258 struct _EPROCESS
* ParentProcess
)
264 OBJECT_ATTRIBUTES ObjectAttributes
;
266 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
268 InitializeObjectAttributes(&ObjectAttributes
,
274 Status
= SepDuplicateToken(pParentToken
,
278 pParentToken
->ImpersonationLevel
,
281 if ( ! NT_SUCCESS(Status
) )
284 NewProcess
->Token
= pNewToken
;
285 return(STATUS_SUCCESS
);
294 PACCESS_STATE AccessState
,
295 PPRIVILEGE_SET Privileges
299 return STATUS_NOT_IMPLEMENTED
;
304 SeCopyClientToken(PACCESS_TOKEN Token
,
305 SECURITY_IMPERSONATION_LEVEL Level
,
306 KPROCESSOR_MODE PreviousMode
,
307 PACCESS_TOKEN
* NewToken
)
310 OBJECT_ATTRIBUTES ObjectAttributes
;
312 InitializeObjectAttributes(&ObjectAttributes
,
317 Status
= SepDuplicateToken(Token
,
333 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
334 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
335 IN BOOLEAN RemoteClient
,
336 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
338 TOKEN_TYPE TokenType
;
340 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
343 PACCESS_TOKEN NewToken
;
345 Token
= PsReferenceEffectiveToken(Thread
,
348 &ImpersonationLevel
);
349 if (TokenType
!= TokenImpersonation
)
351 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
355 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
359 ObDereferenceObject(Token
);
361 return(STATUS_UNSUCCESSFUL
);
363 if (ImpersonationLevel
== SecurityAnonymous
||
364 ImpersonationLevel
== SecurityIdentification
||
365 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
369 ObDereferenceObject(Token
);
371 return(STATUS_UNSUCCESSFUL
);
374 Qos
->EffectiveOnly
!= 0)
376 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
380 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
384 if (Qos
->ContextTrackingMode
== 0)
386 ClientContext
->DirectlyAccessClientToken
= FALSE
;
387 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
390 // ObDeleteCapturedInsertInfo(NewToken);
392 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
394 ObDereferenceObject(Token
);
403 ClientContext
->DirectlyAccessClientToken
= TRUE
;
404 if (RemoteClient
!= FALSE
)
406 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
410 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
411 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
412 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
413 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
414 ClientContext
->ServerIsRemote
= RemoteClient
;
415 ClientContext
->ClientToken
= NewToken
;
417 return(STATUS_SUCCESS
);
425 SeCreateClientSecurityFromSubjectContext(
426 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
427 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
428 IN BOOLEAN ServerIsRemote
,
429 OUT PSECURITY_CLIENT_CONTEXT ClientContext
433 return STATUS_NOT_IMPLEMENTED
;
442 IN PACCESS_TOKEN ExistingToken
,
444 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
445 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
446 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
447 OUT PACCESS_TOKEN
* FilteredToken
451 return STATUS_NOT_IMPLEMENTED
;
460 IN PPRIVILEGE_SET Privileges
472 SeImpersonateClientEx(
473 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
474 IN PETHREAD ServerThread OPTIONAL
478 return STATUS_NOT_IMPLEMENTED
;
485 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
486 IN PETHREAD ServerThread OPTIONAL
)
490 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
492 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
496 b
= ClientContext
->DirectAccessEffectiveOnly
;
498 if (ServerThread
== NULL
)
500 ServerThread
= PsGetCurrentThread();
502 PsImpersonateClient(ServerThread
,
503 ClientContext
->ClientToken
,
506 ClientContext
->SecurityQos
.ImpersonationLevel
);
511 SepDeleteToken(PVOID ObjectBody
)
513 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
515 if (AccessToken
->UserAndGroups
)
516 ExFreePool(AccessToken
->UserAndGroups
);
518 if (AccessToken
->Privileges
)
519 ExFreePool(AccessToken
->Privileges
);
521 if (AccessToken
->DefaultDacl
)
522 ExFreePool(AccessToken
->DefaultDacl
);
527 SepInitializeTokenImplementation(VOID
)
529 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
531 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
532 SepTokenObjectType
->PeakObjects
= 0;
533 SepTokenObjectType
->PeakHandles
= 0;
534 SepTokenObjectType
->TotalObjects
= 0;
535 SepTokenObjectType
->TotalHandles
= 0;
536 SepTokenObjectType
->PagedPoolCharge
= 0;
537 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(TOKEN
);
538 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
539 SepTokenObjectType
->Dump
= NULL
;
540 SepTokenObjectType
->Open
= NULL
;
541 SepTokenObjectType
->Close
= NULL
;
542 SepTokenObjectType
->Delete
= SepDeleteToken
;
543 SepTokenObjectType
->Parse
= NULL
;
544 SepTokenObjectType
->Security
= NULL
;
545 SepTokenObjectType
->QueryName
= NULL
;
546 SepTokenObjectType
->OkayToClose
= NULL
;
547 SepTokenObjectType
->Create
= NULL
;
548 SepTokenObjectType
->DuplicationNotify
= NULL
;
550 RtlCreateUnicodeString(&SepTokenObjectType
->TypeName
,
552 ObpCreateTypeObject (SepTokenObjectType
);
560 NtQueryInformationToken(IN HANDLE TokenHandle
,
561 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
562 OUT PVOID TokenInformation
,
563 IN ULONG TokenInformationLength
,
564 OUT PULONG ReturnLength
)
566 NTSTATUS Status
, LengthStatus
;
571 PTOKEN_GROUPS PtrTokenGroups
;
572 PTOKEN_DEFAULT_DACL PtrDefaultDacl
;
573 PTOKEN_STATISTICS PtrTokenStatistics
;
575 Status
= ObReferenceObjectByHandle(TokenHandle
,
576 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
581 if (!NT_SUCCESS(Status
))
586 switch (TokenInformationClass
)
589 DPRINT("NtQueryInformationToken(TokenUser)\n");
590 Length
= RtlLengthSidAndAttributes(1, Token
->UserAndGroups
);
591 if (TokenInformationLength
< Length
)
593 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
594 if (NT_SUCCESS(Status
))
595 Status
= STATUS_BUFFER_TOO_SMALL
;
599 Status
= RtlCopySidAndAttributesArray(1,
600 Token
->UserAndGroups
,
601 TokenInformationLength
,
603 (char*)TokenInformation
+ 8,
606 if (NT_SUCCESS(Status
))
608 Length
= TokenInformationLength
- Length
;
609 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
615 DPRINT("NtQueryInformationToken(TokenGroups)\n");
616 Length
= RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]) + sizeof(ULONG
);
617 if (TokenInformationLength
< Length
)
619 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
620 if (NT_SUCCESS(Status
))
621 Status
= STATUS_BUFFER_TOO_SMALL
;
625 EndMem
= (char*)TokenInformation
+ Token
->UserAndGroupCount
* sizeof(SID_AND_ATTRIBUTES
);
626 PtrTokenGroups
= (PTOKEN_GROUPS
)TokenInformation
;
627 PtrTokenGroups
->GroupCount
= Token
->UserAndGroupCount
- 1;
628 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
629 &Token
->UserAndGroups
[1],
630 TokenInformationLength
,
631 PtrTokenGroups
->Groups
,
635 if (NT_SUCCESS(Status
))
637 Length
= TokenInformationLength
- Length
;
638 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
643 case TokenPrivileges
:
644 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
645 Length
= sizeof(ULONG
) + Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
646 if (TokenInformationLength
< Length
)
648 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
649 if (NT_SUCCESS(Status
))
650 Status
= STATUS_BUFFER_TOO_SMALL
;
655 TOKEN_PRIVILEGES
* pPriv
= (TOKEN_PRIVILEGES
*)TokenInformation
;
657 pPriv
->PrivilegeCount
= Token
->PrivilegeCount
;
658 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
660 RtlCopyLuid(&pPriv
->Privileges
[i
].Luid
, &Token
->Privileges
[i
].Luid
);
661 pPriv
->Privileges
[i
].Attributes
= Token
->Privileges
[i
].Attributes
;
663 Status
= STATUS_SUCCESS
;
668 DPRINT("NtQueryInformationToken(TokenOwner)\n");
669 Length
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
) + sizeof(TOKEN_OWNER
);
670 if (TokenInformationLength
< Length
)
672 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
673 if (NT_SUCCESS(Status
))
674 Status
= STATUS_BUFFER_TOO_SMALL
;
678 ((PTOKEN_OWNER
)TokenInformation
)->Owner
=
679 (PSID
)(((PTOKEN_OWNER
)TokenInformation
) + 1);
680 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
681 ((PTOKEN_OWNER
)TokenInformation
)->Owner
,
682 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
683 Status
= STATUS_SUCCESS
;
687 case TokenPrimaryGroup
:
688 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
689 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
690 Length
= RtlLengthSid(Token
->PrimaryGroup
) + sizeof(TOKEN_PRIMARY_GROUP
);
691 if (TokenInformationLength
< Length
)
693 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
694 if (NT_SUCCESS(Status
))
695 Status
= STATUS_BUFFER_TOO_SMALL
;
699 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
=
700 (PSID
)(((PTOKEN_PRIMARY_GROUP
)TokenInformation
) + 1);
701 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
702 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
,
703 Token
->PrimaryGroup
);
704 Status
= STATUS_SUCCESS
;
708 case TokenDefaultDacl
:
709 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
710 PtrDefaultDacl
= (PTOKEN_DEFAULT_DACL
) TokenInformation
;
711 Length
= (Token
->DefaultDacl
? Token
->DefaultDacl
->AclSize
: 0) + sizeof(TOKEN_DEFAULT_DACL
);
712 if (TokenInformationLength
< Length
)
714 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
715 if (NT_SUCCESS(Status
))
716 Status
= STATUS_BUFFER_TOO_SMALL
;
718 else if (!Token
->DefaultDacl
)
720 PtrDefaultDacl
->DefaultDacl
= 0;
721 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
725 PtrDefaultDacl
->DefaultDacl
= (PACL
) (PtrDefaultDacl
+ 1);
726 memmove(PtrDefaultDacl
->DefaultDacl
,
728 Token
->DefaultDacl
->AclSize
);
729 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
734 DPRINT("NtQueryInformationToken(TokenSource)\n");
735 if (TokenInformationLength
< sizeof(TOKEN_SOURCE
))
737 Length
= sizeof(TOKEN_SOURCE
);
738 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
739 if (NT_SUCCESS(Status
))
740 Status
= STATUS_BUFFER_TOO_SMALL
;
744 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenSource
, sizeof(TOKEN_SOURCE
));
749 DPRINT("NtQueryInformationToken(TokenType)\n");
750 if (TokenInformationLength
< sizeof(TOKEN_TYPE
))
752 Length
= sizeof(TOKEN_TYPE
);
753 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
754 if (NT_SUCCESS(Status
))
755 Status
= STATUS_BUFFER_TOO_SMALL
;
759 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenType
, sizeof(TOKEN_TYPE
));
763 case TokenImpersonationLevel
:
764 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
765 if (TokenInformationLength
< sizeof(SECURITY_IMPERSONATION_LEVEL
))
767 Length
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
768 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
769 if (NT_SUCCESS(Status
))
770 Status
= STATUS_BUFFER_TOO_SMALL
;
774 Status
= MmCopyToCaller(TokenInformation
, &Token
->ImpersonationLevel
, sizeof(SECURITY_IMPERSONATION_LEVEL
));
778 case TokenStatistics
:
779 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
780 if (TokenInformationLength
< sizeof(TOKEN_STATISTICS
))
782 Length
= sizeof(TOKEN_STATISTICS
);
783 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
784 if (NT_SUCCESS(Status
))
785 Status
= STATUS_BUFFER_TOO_SMALL
;
789 PtrTokenStatistics
= (PTOKEN_STATISTICS
)TokenInformation
;
790 PtrTokenStatistics
->TokenId
= Token
->TokenId
;
791 PtrTokenStatistics
->AuthenticationId
= Token
->AuthenticationId
;
792 PtrTokenStatistics
->ExpirationTime
= Token
->ExpirationTime
;
793 PtrTokenStatistics
->TokenType
= Token
->TokenType
;
794 PtrTokenStatistics
->ImpersonationLevel
= Token
->ImpersonationLevel
;
795 PtrTokenStatistics
->DynamicCharged
= Token
->DynamicCharged
;
796 PtrTokenStatistics
->DynamicAvailable
= Token
->DynamicAvailable
;
797 PtrTokenStatistics
->GroupCount
= Token
->UserAndGroupCount
- 1;
798 PtrTokenStatistics
->PrivilegeCount
= Token
->PrivilegeCount
;
799 PtrTokenStatistics
->ModifiedId
= Token
->ModifiedId
;
801 Status
= STATUS_SUCCESS
;
806 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
807 if (TokenInformationLength
< sizeof(TOKEN_ORIGIN
))
809 Status
= STATUS_BUFFER_TOO_SMALL
;
813 Status
= MmCopyToCaller(&((PTOKEN_ORIGIN
)TokenInformation
)->OriginatingLogonSession
,
814 &Token
->AuthenticationId
, sizeof(LUID
));
816 Length
= sizeof(TOKEN_ORIGIN
);
817 LengthStatus
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
818 if (NT_SUCCESS(Status
))
820 Status
= LengthStatus
;
824 case TokenGroupsAndPrivileges
:
825 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
826 Status
= STATUS_NOT_IMPLEMENTED
;
829 case TokenRestrictedSids
:
830 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
831 Status
= STATUS_NOT_IMPLEMENTED
;
834 case TokenSandBoxInert
:
835 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
836 Status
= STATUS_NOT_IMPLEMENTED
;
840 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
841 if (TokenInformationLength
< sizeof(ULONG
))
843 Length
= sizeof(ULONG
);
844 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
845 if (NT_SUCCESS(Status
))
846 Status
= STATUS_BUFFER_TOO_SMALL
;
850 Status
= MmCopyToCaller(TokenInformation
, &Token
->SessionId
, sizeof(ULONG
));
855 DPRINT1("NtQueryInformationToken(%d) invalid parameter\n");
856 Status
= STATUS_INVALID_PARAMETER
;
860 ObDereferenceObject(Token
);
870 SeQueryInformationToken(
871 IN PACCESS_TOKEN Token
,
872 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
873 OUT PVOID
*TokenInformation
877 return STATUS_NOT_IMPLEMENTED
;
885 SeQuerySessionIdToken(
886 IN PACCESS_TOKEN Token
,
891 return STATUS_NOT_IMPLEMENTED
;
895 * NtSetTokenInformation: Partly implemented.
897 * TokenOrigin, TokenDefaultDacl, TokenSessionId
901 NtSetInformationToken(IN HANDLE TokenHandle
,
902 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
903 OUT PVOID TokenInformation
,
904 IN ULONG TokenInformationLength
)
908 TOKEN_OWNER TokenOwnerSet
= { 0 };
909 TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet
= { 0 };
910 DWORD NeededAccess
= 0;
912 switch (TokenInformationClass
)
915 case TokenPrimaryGroup
:
916 NeededAccess
= TOKEN_ADJUST_DEFAULT
;
919 case TokenDefaultDacl
:
920 if (TokenInformationLength
< sizeof(TOKEN_DEFAULT_DACL
))
921 return STATUS_BUFFER_TOO_SMALL
;
922 NeededAccess
= TOKEN_ADJUST_DEFAULT
;
926 DPRINT1("NtSetInformationToken: lying about success (stub) - %x\n", TokenInformationClass
);
927 return STATUS_SUCCESS
;
931 Status
= ObReferenceObjectByHandle(TokenHandle
,
937 if (!NT_SUCCESS(Status
))
942 switch (TokenInformationClass
)
945 MmCopyFromCaller( &TokenOwnerSet
, TokenInformation
,
946 min(sizeof(TokenOwnerSet
),TokenInformationLength
) );
947 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
948 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
949 TokenOwnerSet
.Owner
);
950 Status
= STATUS_SUCCESS
;
951 DPRINT("NtSetInformationToken(TokenOwner)\n");
954 case TokenPrimaryGroup
:
955 MmCopyFromCaller( &TokenPrimaryGroupSet
, TokenInformation
,
956 min(sizeof(TokenPrimaryGroupSet
),
957 TokenInformationLength
) );
958 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
960 TokenPrimaryGroupSet
.PrimaryGroup
);
961 Status
= STATUS_SUCCESS
;
962 DPRINT("NtSetInformationToken(TokenPrimaryGroup),"
963 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
966 case TokenDefaultDacl
:
968 TOKEN_DEFAULT_DACL TokenDefaultDacl
= { 0 };
972 Status
= MmCopyFromCaller( &TokenDefaultDacl
, TokenInformation
,
973 sizeof(TOKEN_DEFAULT_DACL
) );
974 if (!NT_SUCCESS(Status
))
976 Status
= STATUS_INVALID_PARAMETER
;
980 Status
= MmCopyFromCaller( &OldAcl
, TokenDefaultDacl
.DefaultDacl
,
982 if (!NT_SUCCESS(Status
))
984 Status
= STATUS_INVALID_PARAMETER
;
988 NewAcl
= ExAllocatePool(NonPagedPool
, sizeof(ACL
));
991 Status
= STATUS_INSUFFICIENT_RESOURCES
;
995 Status
= MmCopyFromCaller( NewAcl
, TokenDefaultDacl
.DefaultDacl
,
997 if (!NT_SUCCESS(Status
))
999 Status
= STATUS_INVALID_PARAMETER
;
1004 if (Token
->DefaultDacl
)
1006 ExFreePool(Token
->DefaultDacl
);
1009 Token
->DefaultDacl
= NewAcl
;
1011 Status
= STATUS_SUCCESS
;
1016 Status
= STATUS_NOT_IMPLEMENTED
;
1020 ObDereferenceObject(Token
);
1029 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1030 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1031 * is correct either. -Gunnar
1032 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1035 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1036 IN ACCESS_MASK DesiredAccess
,
1037 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
/*is it really optional?*/,
1038 IN BOOLEAN EffectiveOnly
,
1039 IN TOKEN_TYPE TokenType
,
1040 OUT PHANDLE NewTokenHandle
)
1042 KPROCESSOR_MODE PreviousMode
;
1047 PreviousMode
= KeGetPreviousMode();
1048 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1054 if (!NT_SUCCESS(Status
))
1056 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
1060 Status
= SepDuplicateToken(Token
,
1064 ObjectAttributes
->SecurityQualityOfService
?
1065 ((PSECURITY_QUALITY_OF_SERVICE
)(ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
:
1066 0 /*SecurityAnonymous*/,
1070 ObDereferenceObject(Token
);
1072 if (!NT_SUCCESS(Status
))
1074 DPRINT1("Failed to duplicate token (Status %lx)\n", Status
);
1078 Status
= ObInsertObject((PVOID
)NewToken
,
1085 ObDereferenceObject(NewToken
);
1087 if (!NT_SUCCESS(Status
))
1089 DPRINT1("Failed to create token handle (Status %lx)\n");
1093 return STATUS_SUCCESS
;
1097 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1099 BOOLEAN ResetToDefault
,
1100 PSID_AND_ATTRIBUTES Groups
,
1102 KPROCESSOR_MODE PreviousMode
,
1113 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1114 IN BOOLEAN ResetToDefault
,
1115 IN PTOKEN_GROUPS NewState
,
1116 IN ULONG BufferLength
,
1117 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1118 OUT PULONG ReturnLength
)
1122 PACCESS_TOKEN Token
;
1127 Status
= ObReferenceObjectByHandle(TokenHandle
,
1135 SepAdjustGroups(Token
,
1147 return(STATUS_NOT_IMPLEMENTED
);
1154 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1156 KPROCESSOR_MODE PreviousMode
,
1157 ULONG PrivilegeCount
,
1158 PLUID_AND_ATTRIBUTES Privileges
,
1159 PTOKEN_PRIVILEGES
* PreviousState
,
1168 if (Token
->PrivilegeCount
> 0)
1170 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1172 if (PreviousMode
!= KernelMode
)
1174 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1178 if (PreviousState
!= NULL
)
1180 memcpy(&PreviousState
[i
],
1181 &Token
->Privileges
[i
],
1182 sizeof(LUID_AND_ATTRIBUTES
));
1184 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1191 if (PreviousMode
!= KernelMode
)
1193 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1197 if (PrivilegeCount
<= ?)
1210 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1211 IN BOOLEAN DisableAllPrivileges
,
1212 IN PTOKEN_PRIVILEGES NewState
,
1213 IN ULONG BufferLength
,
1214 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1215 OUT PULONG ReturnLength OPTIONAL
)
1217 // PLUID_AND_ATTRIBUTES Privileges;
1218 KPROCESSOR_MODE PreviousMode
;
1219 // ULONG PrivilegeCount;
1233 DPRINT ("NtAdjustPrivilegesToken() called\n");
1235 // PrivilegeCount = NewState->PrivilegeCount;
1236 PreviousMode
= KeGetPreviousMode ();
1237 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1247 Status
= ObReferenceObjectByHandle (TokenHandle
,
1248 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1253 if (!NT_SUCCESS(Status
))
1255 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1256 // SeReleaseLuidAndAttributesArray(Privileges,
1264 SepAdjustPrivileges(Token
,
1276 if (DisableAllPrivileges
== TRUE
)
1278 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1280 if (Token
->Privileges
[i
].Attributes
!= 0)
1282 DPRINT ("Attributes differ\n");
1284 /* Save current privilege */
1285 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1287 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1288 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1292 /* Update current privlege */
1293 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1296 Status
= STATUS_SUCCESS
;
1301 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1303 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1305 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1306 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1308 DPRINT ("Found privilege\n");
1310 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1311 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1313 DPRINT ("Attributes differ\n");
1314 DPRINT ("Current attributes %lx desired attributes %lx\n",
1315 Token
->Privileges
[i
].Attributes
,
1316 NewState
->Privileges
[j
].Attributes
);
1318 /* Save current privilege */
1319 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1321 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1322 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1326 /* Update current privlege */
1327 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1328 Token
->Privileges
[i
].Attributes
|=
1329 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1330 DPRINT ("New attributes %lx\n",
1331 Token
->Privileges
[i
].Attributes
);
1337 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1340 if (ReturnLength
!= NULL
)
1342 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1343 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1346 ObDereferenceObject (Token
);
1348 // SeReleaseLuidAndAttributesArray(Privileges,
1352 DPRINT ("NtAdjustPrivilegesToken() done\n");
1359 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
1365 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1366 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1367 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1368 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1375 * Initialize the token
1377 Status
= ObCreateObject(KernelMode
,
1385 (PVOID
*)&AccessToken
);
1386 if (!NT_SUCCESS(Status
))
1391 Status
= NtAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1392 if (!NT_SUCCESS(Status
))
1394 ObDereferenceObject(AccessToken
);
1398 Status
= NtAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1399 if (!NT_SUCCESS(Status
))
1401 ObDereferenceObject(AccessToken
);
1405 Status
= NtAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1406 if (!NT_SUCCESS(Status
))
1408 ObDereferenceObject(AccessToken
);
1412 AccessToken
->TokenType
= TokenPrimary
;
1413 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1414 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1415 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1416 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1417 AccessToken
->ExpirationTime
.QuadPart
= -1;
1418 AccessToken
->UserAndGroupCount
= 4;
1420 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1421 uSize
+= uLocalSystemLength
;
1422 uSize
+= uWorldLength
;
1423 uSize
+= uAuthUserLength
;
1424 uSize
+= uAdminsLength
;
1426 AccessToken
->UserAndGroups
=
1427 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1429 TAG('T', 'O', 'K', 'u'));
1430 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1433 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1434 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1435 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1436 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1438 AccessToken
->DefaultOwnerIndex
= i
;
1439 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1440 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1441 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1442 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1443 SidArea
= (char*)SidArea
+ uAdminsLength
;
1445 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1446 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1447 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1448 SidArea
= (char*)SidArea
+ uWorldLength
;
1450 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1451 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1452 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1453 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1455 AccessToken
->PrivilegeCount
= 20;
1457 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1458 AccessToken
->Privileges
=
1459 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1461 TAG('T', 'O', 'K', 'p'));
1464 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1465 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1467 AccessToken
->Privileges
[i
].Attributes
= 0;
1468 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1470 AccessToken
->Privileges
[i
].Attributes
= 0;
1471 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1473 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1474 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1476 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1477 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1479 AccessToken
->Privileges
[i
].Attributes
= 0;
1480 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1482 AccessToken
->Privileges
[i
].Attributes
= 0;
1483 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1485 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1486 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1488 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1489 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1491 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1492 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1494 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1495 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1497 AccessToken
->Privileges
[i
].Attributes
= 0;
1498 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1500 AccessToken
->Privileges
[i
].Attributes
= 0;
1501 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1503 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1504 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1506 AccessToken
->Privileges
[i
].Attributes
= 0;
1507 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1509 AccessToken
->Privileges
[i
].Attributes
= 0;
1510 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1512 AccessToken
->Privileges
[i
].Attributes
= 0;
1513 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1515 AccessToken
->Privileges
[i
].Attributes
= 0;
1516 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1518 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1519 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1521 AccessToken
->Privileges
[i
].Attributes
= 0;
1522 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1524 AccessToken
->Privileges
[i
].Attributes
= 0;
1525 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1527 AccessToken
->Privileges
[i
].Attributes
= 0;
1528 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1533 uSize
= sizeof(ACL
);
1534 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1535 uSize
+= sizeof(ACE
) + uAdminsLength
;
1536 uSize
= (uSize
& (~3)) + 8;
1537 AccessToken
->DefaultDacl
=
1538 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1540 TAG('T', 'O', 'K', 'd'));
1541 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1542 if ( NT_SUCCESS(Status
) )
1544 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1547 if ( NT_SUCCESS(Status
) )
1549 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1552 if ( ! NT_SUCCESS(Status
) )
1554 ObDereferenceObject(AccessToken
);
1558 Process
->Token
= AccessToken
;
1559 return(STATUS_SUCCESS
);
1564 NtCreateToken(OUT PHANDLE UnsafeTokenHandle
,
1565 IN ACCESS_MASK DesiredAccess
,
1566 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1567 IN TOKEN_TYPE TokenType
,
1568 IN PLUID AuthenticationId
,
1569 IN PLARGE_INTEGER ExpirationTime
,
1570 IN PTOKEN_USER TokenUser
,
1571 IN PTOKEN_GROUPS TokenGroups
,
1572 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1573 IN PTOKEN_OWNER TokenOwner
,
1574 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1575 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1576 IN PTOKEN_SOURCE TokenSource
)
1587 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
1588 if (!NT_SUCCESS(Status
))
1591 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
1592 if (!NT_SUCCESS(Status
))
1595 Status
= ObCreateObject(ExGetPreviousMode(),
1598 ExGetPreviousMode(),
1603 (PVOID
*)&AccessToken
);
1604 if (!NT_SUCCESS(Status
))
1606 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1610 Status
= ObInsertObject ((PVOID
)AccessToken
,
1616 if (!NT_SUCCESS(Status
))
1618 DPRINT1("ObInsertObject() failed (Status %lx)\n");
1619 ObDereferenceObject (AccessToken
);
1623 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
1624 &TokenSource
->SourceIdentifier
);
1625 memcpy(AccessToken
->TokenSource
.SourceName
,
1626 TokenSource
->SourceName
,
1627 sizeof(TokenSource
->SourceName
));
1629 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
1630 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
1631 AccessToken
->ExpirationTime
= *ExpirationTime
;
1632 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
1634 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
1635 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
1636 AccessToken
->UserAndGroups
= 0;
1637 AccessToken
->Privileges
= 0;
1639 AccessToken
->TokenType
= TokenType
;
1640 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
1641 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
1644 * Normally we would just point these members into the variable information
1645 * area; however, our ObCreateObject() call can't allocate a variable information
1646 * area, so we allocate them seperately and provide a destroy function.
1649 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1650 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
1651 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
1652 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
1654 AccessToken
->UserAndGroups
=
1655 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1657 TAG('T', 'O', 'K', 'u'));
1659 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1661 Status
= RtlCopySidAndAttributesArray(1,
1664 AccessToken
->UserAndGroups
,
1668 if (NT_SUCCESS(Status
))
1670 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
1671 TokenGroups
->Groups
,
1673 &AccessToken
->UserAndGroups
[1],
1679 if (NT_SUCCESS(Status
))
1681 Status
= SepFindPrimaryGroupAndDefaultOwner(
1683 TokenPrimaryGroup
->PrimaryGroup
,
1687 if (NT_SUCCESS(Status
))
1689 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1690 AccessToken
->Privileges
=
1691 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1693 TAG('T', 'O', 'K', 'p'));
1695 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
1697 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
1698 &TokenPrivileges
->Privileges
[i
],
1699 sizeof(LUID_AND_ATTRIBUTES
));
1700 if (!NT_SUCCESS(Status
))
1705 if (NT_SUCCESS(Status
))
1707 AccessToken
->DefaultDacl
=
1708 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1709 TokenDefaultDacl
->DefaultDacl
->AclSize
,
1710 TAG('T', 'O', 'K', 'd'));
1711 memcpy(AccessToken
->DefaultDacl
,
1712 TokenDefaultDacl
->DefaultDacl
,
1713 TokenDefaultDacl
->DefaultDacl
->AclSize
);
1716 ObDereferenceObject(AccessToken
);
1718 if (NT_SUCCESS(Status
))
1720 Status
= MmCopyToCaller(UnsafeTokenHandle
,
1725 if (!NT_SUCCESS(Status
))
1727 ZwClose(TokenHandle
);
1731 return(STATUS_SUCCESS
);
1739 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1742 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
1744 return STATUS_SUCCESS
;
1751 SECURITY_IMPERSONATION_LEVEL
1753 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1755 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1763 SeTokenType(IN PACCESS_TOKEN Token
)
1765 return ((PTOKEN
)Token
)->TokenType
;
1775 IN PACCESS_TOKEN Token
1787 SeTokenIsRestricted(
1788 IN PACCESS_TOKEN Token
1800 SeTokenIsWriteRestricted(
1801 IN PACCESS_TOKEN Token
1814 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
1815 IN ACCESS_MASK DesiredAccess
,
1816 IN BOOLEAN OpenAsSelf
,
1817 IN ULONG HandleAttributes
,
1818 OUT PHANDLE TokenHandle
)
1821 PTOKEN Token
, NewToken
, PrimaryToken
;
1822 BOOLEAN CopyOnOpen
, EffectiveOnly
;
1823 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
1824 SE_IMPERSONATION_STATE ImpersonationState
;
1825 OBJECT_ATTRIBUTES ObjectAttributes
;
1826 SECURITY_DESCRIPTOR SecurityDescriptor
;
1831 * At first open the thread token for information access and verify
1832 * that the token associated with thread is valid.
1835 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
1836 PsThreadType
, UserMode
, (PVOID
*)&Thread
,
1838 if (!NT_SUCCESS(Status
))
1843 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
1844 &ImpersonationLevel
);
1847 ObfDereferenceObject(Thread
);
1848 return STATUS_NO_TOKEN
;
1851 ObDereferenceObject(Thread
);
1853 if (ImpersonationLevel
== SecurityAnonymous
)
1855 ObfDereferenceObject(Token
);
1856 return STATUS_CANT_OPEN_ANONYMOUS
;
1860 * Revert to self if OpenAsSelf is specified.
1865 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1870 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
1871 PsThreadType
, UserMode
,
1872 (PVOID
*)&Thread
, NULL
);
1873 if (!NT_SUCCESS(Status
))
1875 ObfDereferenceObject(Token
);
1878 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1883 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
1884 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
1885 ObfDereferenceObject(PrimaryToken
);
1886 ObfDereferenceObject(Thread
);
1887 if (!NT_SUCCESS(Status
))
1889 ObfDereferenceObject(Token
);
1892 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1897 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
1898 SECURITY_DESCRIPTOR_REVISION
);
1899 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
1902 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
1903 NULL
, &SecurityDescriptor
);
1905 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
1906 TokenImpersonation
, ImpersonationLevel
,
1907 KernelMode
, &NewToken
);
1909 if (!NT_SUCCESS(Status
))
1911 ObfDereferenceObject(Token
);
1914 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1919 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
1922 ObfDereferenceObject(NewToken
);
1926 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
1927 NULL
, DesiredAccess
, SepTokenObjectType
,
1928 ExGetPreviousMode(), TokenHandle
);
1931 ObfDereferenceObject(Token
);
1935 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1945 NtOpenThreadToken(IN HANDLE ThreadHandle
,
1946 IN ACCESS_MASK DesiredAccess
,
1947 IN BOOLEAN OpenAsSelf
,
1948 OUT PHANDLE TokenHandle
)
1950 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,