3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Security manager
6 * FILE: kernel/se/token.c
7 * PROGRAMER: David Welch <welch@cwcom.net>
9 * 26/07/98: Added stubs for security functions
12 /* INCLUDES *****************************************************************/
17 #include <internal/debug.h>
19 /* GLOBALS *******************************************************************/
21 POBJECT_TYPE SepTokenObjectType
= NULL
;
23 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
28 /* FUNCTIONS *****************************************************************/
30 VOID
SepFreeProxyData(PVOID ProxyData
)
35 NTSTATUS
SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
38 return(STATUS_NOT_IMPLEMENTED
);
41 NTSTATUS
SeExchangePrimaryToken(PEPROCESS Process
,
42 PACCESS_TOKEN NewTokenP
,
43 PACCESS_TOKEN
* OldTokenP
)
46 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
48 if (NewToken
->TokenType
!= TokenPrimary
)
50 return(STATUS_UNSUCCESSFUL
);
52 if (NewToken
->TokenInUse
!= 0)
54 return(STATUS_UNSUCCESSFUL
);
56 OldToken
= Process
->Token
;
57 Process
->Token
= NewToken
;
58 NewToken
->TokenInUse
= 1;
59 ObReferenceObjectByPointer(NewToken
,
63 OldToken
->TokenInUse
= 0;
64 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
65 return(STATUS_SUCCESS
);
69 RtlLengthSidAndAttributes(ULONG Count
,
70 PSID_AND_ATTRIBUTES Src
)
75 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
76 for (i
= 0; i
< Count
; i
++)
77 uLength
+= RtlLengthSid(Src
[i
].Sid
);
84 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
90 Token
->PrimaryGroup
= 0;
94 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
97 /* Validate and set the primary group and user pointers */
98 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
101 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
103 Token
->DefaultOwnerIndex
= i
;
106 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
108 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
112 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
114 return(STATUS_INVALID_OWNER
);
117 if (Token
->PrimaryGroup
== 0)
119 return(STATUS_INVALID_PRIMARY_GROUP
);
122 return(STATUS_SUCCESS
);
127 SepDuplicateToken(PTOKEN Token
,
128 POBJECT_ATTRIBUTES ObjectAttributes
,
129 BOOLEAN EffectiveOnly
,
130 TOKEN_TYPE TokenType
,
131 SECURITY_IMPERSONATION_LEVEL Level
,
132 KPROCESSOR_MODE PreviousMode
,
133 PTOKEN
* NewAccessToken
)
143 Status
= ObCreateObject(PreviousMode
,
151 (PVOID
*)&AccessToken
);
152 if (!NT_SUCCESS(Status
))
154 DPRINT1("ObCreateObject() failed (Status %lx)\n");
158 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
159 if (!NT_SUCCESS(Status
))
161 ObDereferenceObject(AccessToken
);
165 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
166 if (!NT_SUCCESS(Status
))
168 ObDereferenceObject(AccessToken
);
172 AccessToken
->TokenInUse
= 0;
173 AccessToken
->TokenType
= TokenType
;
174 AccessToken
->ImpersonationLevel
= Level
;
175 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
177 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
178 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
179 memcpy(AccessToken
->TokenSource
.SourceName
,
180 Token
->TokenSource
.SourceName
,
181 sizeof(Token
->TokenSource
.SourceName
));
182 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
183 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
184 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
186 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
187 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
188 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
190 AccessToken
->UserAndGroups
=
191 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
193 TAG('T', 'O', 'K', 'u'));
195 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
197 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
198 Token
->UserAndGroups
,
200 AccessToken
->UserAndGroups
,
204 if (NT_SUCCESS(Status
))
206 Status
= SepFindPrimaryGroupAndDefaultOwner(
212 if (NT_SUCCESS(Status
))
214 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
216 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
217 AccessToken
->Privileges
=
218 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
220 TAG('T', 'O', 'K', 'p'));
222 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
224 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
225 &Token
->Privileges
[i
].Luid
);
226 AccessToken
->Privileges
[i
].Attributes
=
227 Token
->Privileges
[i
].Attributes
;
230 if ( Token
->DefaultDacl
)
232 AccessToken
->DefaultDacl
=
233 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
234 Token
->DefaultDacl
->AclSize
,
235 TAG('T', 'O', 'K', 'd'));
236 memcpy(AccessToken
->DefaultDacl
,
238 Token
->DefaultDacl
->AclSize
);
242 AccessToken
->DefaultDacl
= 0;
246 if ( NT_SUCCESS(Status
) )
248 *NewAccessToken
= AccessToken
;
249 return(STATUS_SUCCESS
);
252 ObDereferenceObject(AccessToken
);
258 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
259 struct _EPROCESS
* ParentProcess
)
265 OBJECT_ATTRIBUTES ObjectAttributes
;
267 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
269 InitializeObjectAttributes(&ObjectAttributes
,
275 Status
= SepDuplicateToken(pParentToken
,
279 pParentToken
->ImpersonationLevel
,
282 if ( ! NT_SUCCESS(Status
) )
285 NewProcess
->Token
= pNewToken
;
286 return(STATUS_SUCCESS
);
295 PACCESS_STATE AccessState
,
296 PPRIVILEGE_SET Privileges
300 return STATUS_NOT_IMPLEMENTED
;
305 SeCopyClientToken(PACCESS_TOKEN Token
,
306 SECURITY_IMPERSONATION_LEVEL Level
,
307 KPROCESSOR_MODE PreviousMode
,
308 PACCESS_TOKEN
* NewToken
)
311 OBJECT_ATTRIBUTES ObjectAttributes
;
313 InitializeObjectAttributes(&ObjectAttributes
,
318 Status
= SepDuplicateToken(Token
,
334 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
335 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
336 IN BOOLEAN RemoteClient
,
337 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
339 TOKEN_TYPE TokenType
;
341 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
344 PACCESS_TOKEN NewToken
;
346 Token
= PsReferenceEffectiveToken(Thread
,
349 &ImpersonationLevel
);
350 if (TokenType
!= TokenImpersonation
)
352 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
356 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
360 ObDereferenceObject(Token
);
362 return(STATUS_UNSUCCESSFUL
);
364 if (ImpersonationLevel
== SecurityAnonymous
||
365 ImpersonationLevel
== SecurityIdentification
||
366 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
370 ObDereferenceObject(Token
);
372 return(STATUS_UNSUCCESSFUL
);
375 Qos
->EffectiveOnly
!= 0)
377 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
381 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
385 if (Qos
->ContextTrackingMode
== 0)
387 ClientContext
->DirectlyAccessClientToken
= FALSE
;
388 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
391 // ObDeleteCapturedInsertInfo(NewToken);
393 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
395 ObDereferenceObject(Token
);
404 ClientContext
->DirectlyAccessClientToken
= TRUE
;
405 if (RemoteClient
!= FALSE
)
407 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
411 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
412 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
413 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
414 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
415 ClientContext
->ServerIsRemote
= RemoteClient
;
416 ClientContext
->ClientToken
= NewToken
;
418 return(STATUS_SUCCESS
);
426 SeCreateClientSecurityFromSubjectContext(
427 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
428 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
429 IN BOOLEAN ServerIsRemote
,
430 OUT PSECURITY_CLIENT_CONTEXT ClientContext
434 return STATUS_NOT_IMPLEMENTED
;
443 IN PACCESS_TOKEN ExistingToken
,
445 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
446 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
447 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
448 OUT PACCESS_TOKEN
* FilteredToken
452 return STATUS_NOT_IMPLEMENTED
;
461 IN PPRIVILEGE_SET Privileges
473 SeImpersonateClientEx(
474 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
475 IN PETHREAD ServerThread OPTIONAL
479 return STATUS_NOT_IMPLEMENTED
;
486 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
487 IN PETHREAD ServerThread OPTIONAL
)
491 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
493 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
497 b
= ClientContext
->DirectAccessEffectiveOnly
;
499 if (ServerThread
== NULL
)
501 ServerThread
= PsGetCurrentThread();
503 PsImpersonateClient(ServerThread
,
504 ClientContext
->ClientToken
,
507 ClientContext
->SecurityQos
.ImpersonationLevel
);
512 SepDeleteToken(PVOID ObjectBody
)
514 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
516 if (AccessToken
->UserAndGroups
)
517 ExFreePool(AccessToken
->UserAndGroups
);
519 if (AccessToken
->Privileges
)
520 ExFreePool(AccessToken
->Privileges
);
522 if (AccessToken
->DefaultDacl
)
523 ExFreePool(AccessToken
->DefaultDacl
);
528 SepInitializeTokenImplementation(VOID
)
530 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
532 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
533 SepTokenObjectType
->PeakObjects
= 0;
534 SepTokenObjectType
->PeakHandles
= 0;
535 SepTokenObjectType
->TotalObjects
= 0;
536 SepTokenObjectType
->TotalHandles
= 0;
537 SepTokenObjectType
->PagedPoolCharge
= 0;
538 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(TOKEN
);
539 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
540 SepTokenObjectType
->Dump
= NULL
;
541 SepTokenObjectType
->Open
= NULL
;
542 SepTokenObjectType
->Close
= NULL
;
543 SepTokenObjectType
->Delete
= SepDeleteToken
;
544 SepTokenObjectType
->Parse
= NULL
;
545 SepTokenObjectType
->Security
= NULL
;
546 SepTokenObjectType
->QueryName
= NULL
;
547 SepTokenObjectType
->OkayToClose
= NULL
;
548 SepTokenObjectType
->Create
= NULL
;
549 SepTokenObjectType
->DuplicationNotify
= NULL
;
551 RtlCreateUnicodeString(&SepTokenObjectType
->TypeName
,
553 ObpCreateTypeObject (SepTokenObjectType
);
561 NtQueryInformationToken(IN HANDLE TokenHandle
,
562 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
563 OUT PVOID TokenInformation
,
564 IN ULONG TokenInformationLength
,
565 OUT PULONG ReturnLength
)
567 NTSTATUS Status
, LengthStatus
;
572 PTOKEN_GROUPS PtrTokenGroups
;
573 PTOKEN_DEFAULT_DACL PtrDefaultDacl
;
574 PTOKEN_STATISTICS PtrTokenStatistics
;
576 Status
= ObReferenceObjectByHandle(TokenHandle
,
577 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
582 if (!NT_SUCCESS(Status
))
587 switch (TokenInformationClass
)
590 DPRINT("NtQueryInformationToken(TokenUser)\n");
591 Length
= RtlLengthSidAndAttributes(1, Token
->UserAndGroups
);
592 if (TokenInformationLength
< Length
)
594 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
595 if (NT_SUCCESS(Status
))
596 Status
= STATUS_BUFFER_TOO_SMALL
;
600 Status
= RtlCopySidAndAttributesArray(1,
601 Token
->UserAndGroups
,
602 TokenInformationLength
,
604 (char*)TokenInformation
+ 8,
607 if (NT_SUCCESS(Status
))
609 Length
= TokenInformationLength
- Length
;
610 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
616 DPRINT("NtQueryInformationToken(TokenGroups)\n");
617 Length
= RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]) + sizeof(ULONG
);
618 if (TokenInformationLength
< Length
)
620 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
621 if (NT_SUCCESS(Status
))
622 Status
= STATUS_BUFFER_TOO_SMALL
;
626 EndMem
= (char*)TokenInformation
+ Token
->UserAndGroupCount
* sizeof(SID_AND_ATTRIBUTES
);
627 PtrTokenGroups
= (PTOKEN_GROUPS
)TokenInformation
;
628 PtrTokenGroups
->GroupCount
= Token
->UserAndGroupCount
- 1;
629 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
630 &Token
->UserAndGroups
[1],
631 TokenInformationLength
,
632 PtrTokenGroups
->Groups
,
636 if (NT_SUCCESS(Status
))
638 Length
= TokenInformationLength
- Length
;
639 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
644 case TokenPrivileges
:
645 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
646 Length
= sizeof(ULONG
) + Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
647 if (TokenInformationLength
< Length
)
649 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
650 if (NT_SUCCESS(Status
))
651 Status
= STATUS_BUFFER_TOO_SMALL
;
656 TOKEN_PRIVILEGES
* pPriv
= (TOKEN_PRIVILEGES
*)TokenInformation
;
658 pPriv
->PrivilegeCount
= Token
->PrivilegeCount
;
659 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
661 RtlCopyLuid(&pPriv
->Privileges
[i
].Luid
, &Token
->Privileges
[i
].Luid
);
662 pPriv
->Privileges
[i
].Attributes
= Token
->Privileges
[i
].Attributes
;
664 Status
= STATUS_SUCCESS
;
669 DPRINT("NtQueryInformationToken(TokenOwner)\n");
670 Length
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
) + sizeof(TOKEN_OWNER
);
671 if (TokenInformationLength
< Length
)
673 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
674 if (NT_SUCCESS(Status
))
675 Status
= STATUS_BUFFER_TOO_SMALL
;
679 ((PTOKEN_OWNER
)TokenInformation
)->Owner
=
680 (PSID
)(((PTOKEN_OWNER
)TokenInformation
) + 1);
681 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
682 ((PTOKEN_OWNER
)TokenInformation
)->Owner
,
683 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
684 Status
= STATUS_SUCCESS
;
688 case TokenPrimaryGroup
:
689 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
690 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
691 Length
= RtlLengthSid(Token
->PrimaryGroup
) + sizeof(TOKEN_PRIMARY_GROUP
);
692 if (TokenInformationLength
< Length
)
694 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
695 if (NT_SUCCESS(Status
))
696 Status
= STATUS_BUFFER_TOO_SMALL
;
700 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
=
701 (PSID
)(((PTOKEN_PRIMARY_GROUP
)TokenInformation
) + 1);
702 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
703 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
,
704 Token
->PrimaryGroup
);
705 Status
= STATUS_SUCCESS
;
709 case TokenDefaultDacl
:
710 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
711 PtrDefaultDacl
= (PTOKEN_DEFAULT_DACL
) TokenInformation
;
712 Length
= (Token
->DefaultDacl
? Token
->DefaultDacl
->AclSize
: 0) + sizeof(TOKEN_DEFAULT_DACL
);
713 if (TokenInformationLength
< Length
)
715 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
716 if (NT_SUCCESS(Status
))
717 Status
= STATUS_BUFFER_TOO_SMALL
;
719 else if (!Token
->DefaultDacl
)
721 PtrDefaultDacl
->DefaultDacl
= 0;
722 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
726 PtrDefaultDacl
->DefaultDacl
= (PACL
) (PtrDefaultDacl
+ 1);
727 memmove(PtrDefaultDacl
->DefaultDacl
,
729 Token
->DefaultDacl
->AclSize
);
730 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
735 DPRINT("NtQueryInformationToken(TokenSource)\n");
736 if (TokenInformationLength
< sizeof(TOKEN_SOURCE
))
738 Length
= sizeof(TOKEN_SOURCE
);
739 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
740 if (NT_SUCCESS(Status
))
741 Status
= STATUS_BUFFER_TOO_SMALL
;
745 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenSource
, sizeof(TOKEN_SOURCE
));
750 DPRINT("NtQueryInformationToken(TokenType)\n");
751 if (TokenInformationLength
< sizeof(TOKEN_TYPE
))
753 Length
= sizeof(TOKEN_TYPE
);
754 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
755 if (NT_SUCCESS(Status
))
756 Status
= STATUS_BUFFER_TOO_SMALL
;
760 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenType
, sizeof(TOKEN_TYPE
));
764 case TokenImpersonationLevel
:
765 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
766 if (TokenInformationLength
< sizeof(SECURITY_IMPERSONATION_LEVEL
))
768 Length
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
769 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
770 if (NT_SUCCESS(Status
))
771 Status
= STATUS_BUFFER_TOO_SMALL
;
775 Status
= MmCopyToCaller(TokenInformation
, &Token
->ImpersonationLevel
, sizeof(SECURITY_IMPERSONATION_LEVEL
));
779 case TokenStatistics
:
780 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
781 if (TokenInformationLength
< sizeof(TOKEN_STATISTICS
))
783 Length
= sizeof(TOKEN_STATISTICS
);
784 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
785 if (NT_SUCCESS(Status
))
786 Status
= STATUS_BUFFER_TOO_SMALL
;
790 PtrTokenStatistics
= (PTOKEN_STATISTICS
)TokenInformation
;
791 PtrTokenStatistics
->TokenId
= Token
->TokenId
;
792 PtrTokenStatistics
->AuthenticationId
= Token
->AuthenticationId
;
793 PtrTokenStatistics
->ExpirationTime
= Token
->ExpirationTime
;
794 PtrTokenStatistics
->TokenType
= Token
->TokenType
;
795 PtrTokenStatistics
->ImpersonationLevel
= Token
->ImpersonationLevel
;
796 PtrTokenStatistics
->DynamicCharged
= Token
->DynamicCharged
;
797 PtrTokenStatistics
->DynamicAvailable
= Token
->DynamicAvailable
;
798 PtrTokenStatistics
->GroupCount
= Token
->UserAndGroupCount
- 1;
799 PtrTokenStatistics
->PrivilegeCount
= Token
->PrivilegeCount
;
800 PtrTokenStatistics
->ModifiedId
= Token
->ModifiedId
;
802 Status
= STATUS_SUCCESS
;
807 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
808 if (TokenInformationLength
< sizeof(TOKEN_ORIGIN
))
810 Status
= STATUS_BUFFER_TOO_SMALL
;
814 Status
= MmCopyToCaller(&((PTOKEN_ORIGIN
)TokenInformation
)->OriginatingLogonSession
,
815 &Token
->AuthenticationId
, sizeof(LUID
));
817 Length
= sizeof(TOKEN_ORIGIN
);
818 LengthStatus
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
819 if (NT_SUCCESS(Status
))
821 Status
= LengthStatus
;
825 case TokenGroupsAndPrivileges
:
826 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
827 Status
= STATUS_NOT_IMPLEMENTED
;
830 case TokenRestrictedSids
:
831 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
832 Status
= STATUS_NOT_IMPLEMENTED
;
835 case TokenSandBoxInert
:
836 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
837 Status
= STATUS_NOT_IMPLEMENTED
;
841 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
842 if (TokenInformationLength
< sizeof(ULONG
))
844 Length
= sizeof(ULONG
);
845 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
846 if (NT_SUCCESS(Status
))
847 Status
= STATUS_BUFFER_TOO_SMALL
;
851 Status
= MmCopyToCaller(TokenInformation
, &Token
->SessionId
, sizeof(ULONG
));
856 DPRINT1("NtQueryInformationToken(%d) invalid parameter\n");
857 Status
= STATUS_INVALID_PARAMETER
;
861 ObDereferenceObject(Token
);
871 SeQueryInformationToken(
872 IN PACCESS_TOKEN Token
,
873 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
874 OUT PVOID
*TokenInformation
878 return STATUS_NOT_IMPLEMENTED
;
886 SeQuerySessionIdToken(
887 IN PACCESS_TOKEN Token
,
892 return STATUS_NOT_IMPLEMENTED
;
896 * NtSetTokenInformation: Partly implemented.
898 * TokenOrigin, TokenDefaultDacl, TokenSessionId
902 NtSetInformationToken(IN HANDLE TokenHandle
,
903 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
904 OUT PVOID TokenInformation
,
905 IN ULONG TokenInformationLength
)
909 TOKEN_OWNER TokenOwnerSet
= { 0 };
910 TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet
= { 0 };
911 DWORD NeededAccess
= 0;
913 switch (TokenInformationClass
)
916 case TokenPrimaryGroup
:
917 NeededAccess
= TOKEN_ADJUST_DEFAULT
;
920 case TokenDefaultDacl
:
921 if (TokenInformationLength
< sizeof(TOKEN_DEFAULT_DACL
))
922 return STATUS_BUFFER_TOO_SMALL
;
923 NeededAccess
= TOKEN_ADJUST_DEFAULT
;
927 DPRINT1("NtSetInformationToken: lying about success (stub) - %x\n", TokenInformationClass
);
928 return STATUS_SUCCESS
;
932 Status
= ObReferenceObjectByHandle(TokenHandle
,
938 if (!NT_SUCCESS(Status
))
943 switch (TokenInformationClass
)
946 MmCopyFromCaller( &TokenOwnerSet
, TokenInformation
,
947 min(sizeof(TokenOwnerSet
),TokenInformationLength
) );
948 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
949 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
950 TokenOwnerSet
.Owner
);
951 Status
= STATUS_SUCCESS
;
952 DPRINT("NtSetInformationToken(TokenOwner)\n");
955 case TokenPrimaryGroup
:
956 MmCopyFromCaller( &TokenPrimaryGroupSet
, TokenInformation
,
957 min(sizeof(TokenPrimaryGroupSet
),
958 TokenInformationLength
) );
959 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
961 TokenPrimaryGroupSet
.PrimaryGroup
);
962 Status
= STATUS_SUCCESS
;
963 DPRINT("NtSetInformationToken(TokenPrimaryGroup),"
964 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
967 case TokenDefaultDacl
:
969 TOKEN_DEFAULT_DACL TokenDefaultDacl
= { 0 };
973 Status
= MmCopyFromCaller( &TokenDefaultDacl
, TokenInformation
,
974 sizeof(TOKEN_DEFAULT_DACL
) );
975 if (!NT_SUCCESS(Status
))
977 Status
= STATUS_INVALID_PARAMETER
;
981 Status
= MmCopyFromCaller( &OldAcl
, TokenDefaultDacl
.DefaultDacl
,
983 if (!NT_SUCCESS(Status
))
985 Status
= STATUS_INVALID_PARAMETER
;
989 NewAcl
= ExAllocatePool(NonPagedPool
, sizeof(ACL
));
992 Status
= STATUS_INSUFFICIENT_RESOURCES
;
996 Status
= MmCopyFromCaller( NewAcl
, TokenDefaultDacl
.DefaultDacl
,
998 if (!NT_SUCCESS(Status
))
1000 Status
= STATUS_INVALID_PARAMETER
;
1005 if (Token
->DefaultDacl
)
1007 ExFreePool(Token
->DefaultDacl
);
1010 Token
->DefaultDacl
= NewAcl
;
1012 Status
= STATUS_SUCCESS
;
1017 Status
= STATUS_NOT_IMPLEMENTED
;
1021 ObDereferenceObject(Token
);
1030 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1031 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1032 * is correct either. -Gunnar
1033 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1036 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1037 IN ACCESS_MASK DesiredAccess
,
1038 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
/*is it really optional?*/,
1039 IN BOOLEAN EffectiveOnly
,
1040 IN TOKEN_TYPE TokenType
,
1041 OUT PHANDLE NewTokenHandle
)
1043 KPROCESSOR_MODE PreviousMode
;
1048 PreviousMode
= KeGetPreviousMode();
1049 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1055 if (!NT_SUCCESS(Status
))
1057 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
1061 Status
= SepDuplicateToken(Token
,
1065 ObjectAttributes
->SecurityQualityOfService
?
1066 ((PSECURITY_QUALITY_OF_SERVICE
)(ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
:
1067 0 /*SecurityAnonymous*/,
1071 ObDereferenceObject(Token
);
1073 if (!NT_SUCCESS(Status
))
1075 DPRINT1("Failed to duplicate token (Status %lx)\n", Status
);
1079 Status
= ObInsertObject((PVOID
)NewToken
,
1086 ObDereferenceObject(NewToken
);
1088 if (!NT_SUCCESS(Status
))
1090 DPRINT1("Failed to create token handle (Status %lx)\n");
1094 return STATUS_SUCCESS
;
1098 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1100 BOOLEAN ResetToDefault
,
1101 PSID_AND_ATTRIBUTES Groups
,
1103 KPROCESSOR_MODE PreviousMode
,
1114 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1115 IN BOOLEAN ResetToDefault
,
1116 IN PTOKEN_GROUPS NewState
,
1117 IN ULONG BufferLength
,
1118 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1119 OUT PULONG ReturnLength
)
1123 PACCESS_TOKEN Token
;
1128 Status
= ObReferenceObjectByHandle(TokenHandle
,
1136 SepAdjustGroups(Token
,
1148 return(STATUS_NOT_IMPLEMENTED
);
1155 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1157 KPROCESSOR_MODE PreviousMode
,
1158 ULONG PrivilegeCount
,
1159 PLUID_AND_ATTRIBUTES Privileges
,
1160 PTOKEN_PRIVILEGES
* PreviousState
,
1169 if (Token
->PrivilegeCount
> 0)
1171 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1173 if (PreviousMode
!= KernelMode
)
1175 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1179 if (PreviousState
!= NULL
)
1181 memcpy(&PreviousState
[i
],
1182 &Token
->Privileges
[i
],
1183 sizeof(LUID_AND_ATTRIBUTES
));
1185 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1192 if (PreviousMode
!= KernelMode
)
1194 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1198 if (PrivilegeCount
<= ?)
1211 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1212 IN BOOLEAN DisableAllPrivileges
,
1213 IN PTOKEN_PRIVILEGES NewState
,
1214 IN ULONG BufferLength
,
1215 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1216 OUT PULONG ReturnLength OPTIONAL
)
1218 // PLUID_AND_ATTRIBUTES Privileges;
1219 KPROCESSOR_MODE PreviousMode
;
1220 // ULONG PrivilegeCount;
1234 DPRINT ("NtAdjustPrivilegesToken() called\n");
1236 // PrivilegeCount = NewState->PrivilegeCount;
1237 PreviousMode
= KeGetPreviousMode ();
1238 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1248 Status
= ObReferenceObjectByHandle (TokenHandle
,
1249 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1254 if (!NT_SUCCESS(Status
))
1256 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1257 // SeReleaseLuidAndAttributesArray(Privileges,
1265 SepAdjustPrivileges(Token
,
1277 if (DisableAllPrivileges
== TRUE
)
1279 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1281 if (Token
->Privileges
[i
].Attributes
!= 0)
1283 DPRINT ("Attributes differ\n");
1285 /* Save current privilege */
1286 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1288 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1289 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1293 /* Update current privlege */
1294 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1297 Status
= STATUS_SUCCESS
;
1302 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1304 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1306 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1307 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1309 DPRINT ("Found privilege\n");
1311 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1312 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1314 DPRINT ("Attributes differ\n");
1315 DPRINT ("Current attributes %lx desired attributes %lx\n",
1316 Token
->Privileges
[i
].Attributes
,
1317 NewState
->Privileges
[j
].Attributes
);
1319 /* Save current privilege */
1320 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1322 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1323 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1327 /* Update current privlege */
1328 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1329 Token
->Privileges
[i
].Attributes
|=
1330 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1331 DPRINT ("New attributes %lx\n",
1332 Token
->Privileges
[i
].Attributes
);
1338 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1341 if (ReturnLength
!= NULL
)
1343 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1344 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1347 ObDereferenceObject (Token
);
1349 // SeReleaseLuidAndAttributesArray(Privileges,
1353 DPRINT ("NtAdjustPrivilegesToken() done\n");
1360 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
1366 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1367 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1368 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1369 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1376 * Initialize the token
1378 Status
= ObCreateObject(KernelMode
,
1386 (PVOID
*)&AccessToken
);
1387 if (!NT_SUCCESS(Status
))
1392 Status
= NtAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1393 if (!NT_SUCCESS(Status
))
1395 ObDereferenceObject(AccessToken
);
1399 Status
= NtAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1400 if (!NT_SUCCESS(Status
))
1402 ObDereferenceObject(AccessToken
);
1406 Status
= NtAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1407 if (!NT_SUCCESS(Status
))
1409 ObDereferenceObject(AccessToken
);
1413 AccessToken
->TokenType
= TokenPrimary
;
1414 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1415 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1416 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1417 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1418 AccessToken
->ExpirationTime
.QuadPart
= -1;
1419 AccessToken
->UserAndGroupCount
= 4;
1421 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1422 uSize
+= uLocalSystemLength
;
1423 uSize
+= uWorldLength
;
1424 uSize
+= uAuthUserLength
;
1425 uSize
+= uAdminsLength
;
1427 AccessToken
->UserAndGroups
=
1428 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1430 TAG('T', 'O', 'K', 'u'));
1431 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1434 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1435 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1436 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1437 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1439 AccessToken
->DefaultOwnerIndex
= i
;
1440 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1441 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1442 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1443 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1444 SidArea
= (char*)SidArea
+ uAdminsLength
;
1446 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1447 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1448 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1449 SidArea
= (char*)SidArea
+ uWorldLength
;
1451 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1452 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1453 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1454 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1456 AccessToken
->PrivilegeCount
= 20;
1458 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1459 AccessToken
->Privileges
=
1460 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1462 TAG('T', 'O', 'K', 'p'));
1465 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1466 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1468 AccessToken
->Privileges
[i
].Attributes
= 0;
1469 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1471 AccessToken
->Privileges
[i
].Attributes
= 0;
1472 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1474 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1475 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1477 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1478 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1480 AccessToken
->Privileges
[i
].Attributes
= 0;
1481 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1483 AccessToken
->Privileges
[i
].Attributes
= 0;
1484 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1486 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1487 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1489 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1490 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1492 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1493 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1495 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1496 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1498 AccessToken
->Privileges
[i
].Attributes
= 0;
1499 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1501 AccessToken
->Privileges
[i
].Attributes
= 0;
1502 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1504 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1505 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1507 AccessToken
->Privileges
[i
].Attributes
= 0;
1508 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1510 AccessToken
->Privileges
[i
].Attributes
= 0;
1511 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1513 AccessToken
->Privileges
[i
].Attributes
= 0;
1514 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1516 AccessToken
->Privileges
[i
].Attributes
= 0;
1517 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1519 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1520 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1522 AccessToken
->Privileges
[i
].Attributes
= 0;
1523 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1525 AccessToken
->Privileges
[i
].Attributes
= 0;
1526 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1528 AccessToken
->Privileges
[i
].Attributes
= 0;
1529 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1534 uSize
= sizeof(ACL
);
1535 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1536 uSize
+= sizeof(ACE
) + uAdminsLength
;
1537 uSize
= (uSize
& (~3)) + 8;
1538 AccessToken
->DefaultDacl
=
1539 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1541 TAG('T', 'O', 'K', 'd'));
1542 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1543 if ( NT_SUCCESS(Status
) )
1545 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1548 if ( NT_SUCCESS(Status
) )
1550 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1553 if ( ! NT_SUCCESS(Status
) )
1555 ObDereferenceObject(AccessToken
);
1559 Process
->Token
= AccessToken
;
1560 return(STATUS_SUCCESS
);
1565 NtCreateToken(OUT PHANDLE UnsafeTokenHandle
,
1566 IN ACCESS_MASK DesiredAccess
,
1567 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes
,
1568 IN TOKEN_TYPE TokenType
,
1569 IN PLUID AuthenticationId
,
1570 IN PLARGE_INTEGER ExpirationTime
,
1571 IN PTOKEN_USER TokenUser
,
1572 IN PTOKEN_GROUPS TokenGroups
,
1573 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1574 IN PTOKEN_OWNER TokenOwner
,
1575 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1576 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1577 IN PTOKEN_SOURCE TokenSource
)
1582 POBJECT_ATTRIBUTES ObjectAttributes
;
1589 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
1590 if (!NT_SUCCESS(Status
))
1593 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
1594 if (!NT_SUCCESS(Status
))
1597 Status
= ObCreateObject(ExGetPreviousMode(),
1600 ExGetPreviousMode(),
1605 (PVOID
*)&AccessToken
);
1606 if (!NT_SUCCESS(Status
))
1608 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1612 Status
= ObInsertObject ((PVOID
)AccessToken
,
1618 if (!NT_SUCCESS(Status
))
1620 DPRINT1("ObInsertObject() failed (Status %lx)\n");
1621 ObDereferenceObject (AccessToken
);
1625 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
1626 &TokenSource
->SourceIdentifier
);
1627 memcpy(AccessToken
->TokenSource
.SourceName
,
1628 TokenSource
->SourceName
,
1629 sizeof(TokenSource
->SourceName
));
1631 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
1632 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
1633 AccessToken
->ExpirationTime
= *ExpirationTime
;
1634 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
1636 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
1637 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
1638 AccessToken
->UserAndGroups
= 0;
1639 AccessToken
->Privileges
= 0;
1641 AccessToken
->TokenType
= TokenType
;
1642 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
1643 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
1646 * Normally we would just point these members into the variable information
1647 * area; however, our ObCreateObject() call can't allocate a variable information
1648 * area, so we allocate them seperately and provide a destroy function.
1651 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1652 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
1653 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
1654 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
1656 AccessToken
->UserAndGroups
=
1657 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1659 TAG('T', 'O', 'K', 'u'));
1661 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1663 Status
= RtlCopySidAndAttributesArray(1,
1666 AccessToken
->UserAndGroups
,
1670 if (NT_SUCCESS(Status
))
1672 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
1673 TokenGroups
->Groups
,
1675 &AccessToken
->UserAndGroups
[1],
1681 if (NT_SUCCESS(Status
))
1683 Status
= SepFindPrimaryGroupAndDefaultOwner(
1685 TokenPrimaryGroup
->PrimaryGroup
,
1689 if (NT_SUCCESS(Status
))
1691 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1692 AccessToken
->Privileges
=
1693 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1695 TAG('T', 'O', 'K', 'p'));
1697 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
1699 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
1700 &TokenPrivileges
->Privileges
[i
],
1701 sizeof(LUID_AND_ATTRIBUTES
));
1702 if (!NT_SUCCESS(Status
))
1707 if (NT_SUCCESS(Status
))
1709 AccessToken
->DefaultDacl
=
1710 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1711 TokenDefaultDacl
->DefaultDacl
->AclSize
,
1712 TAG('T', 'O', 'K', 'd'));
1713 memcpy(AccessToken
->DefaultDacl
,
1714 TokenDefaultDacl
->DefaultDacl
,
1715 TokenDefaultDacl
->DefaultDacl
->AclSize
);
1718 ObDereferenceObject(AccessToken
);
1720 if (NT_SUCCESS(Status
))
1722 Status
= MmCopyToCaller(UnsafeTokenHandle
,
1727 if (!NT_SUCCESS(Status
))
1729 ZwClose(TokenHandle
);
1733 return(STATUS_SUCCESS
);
1741 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1744 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
1746 return STATUS_SUCCESS
;
1753 SECURITY_IMPERSONATION_LEVEL
1755 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1757 return ((PTOKEN
)Token
)->ImpersonationLevel
;
1765 SeTokenType(IN PACCESS_TOKEN Token
)
1767 return ((PTOKEN
)Token
)->TokenType
;
1777 IN PACCESS_TOKEN Token
1789 SeTokenIsRestricted(
1790 IN PACCESS_TOKEN Token
1802 SeTokenIsWriteRestricted(
1803 IN PACCESS_TOKEN Token
1816 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
1817 IN ACCESS_MASK DesiredAccess
,
1818 IN BOOLEAN OpenAsSelf
,
1819 IN ULONG HandleAttributes
,
1820 OUT PHANDLE TokenHandle
)
1823 PTOKEN Token
, NewToken
, PrimaryToken
;
1824 BOOLEAN CopyOnOpen
, EffectiveOnly
;
1825 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
1826 SE_IMPERSONATION_STATE ImpersonationState
;
1827 OBJECT_ATTRIBUTES ObjectAttributes
;
1828 SECURITY_DESCRIPTOR SecurityDescriptor
;
1833 * At first open the thread token for information access and verify
1834 * that the token associated with thread is valid.
1837 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
1838 PsThreadType
, UserMode
, (PVOID
*)&Thread
,
1840 if (!NT_SUCCESS(Status
))
1845 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
1846 &ImpersonationLevel
);
1849 ObfDereferenceObject(Thread
);
1850 return STATUS_NO_TOKEN
;
1853 ObDereferenceObject(Thread
);
1855 if (ImpersonationLevel
== SecurityAnonymous
)
1857 ObfDereferenceObject(Token
);
1858 return STATUS_CANT_OPEN_ANONYMOUS
;
1862 * Revert to self if OpenAsSelf is specified.
1867 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1872 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
1873 PsThreadType
, UserMode
,
1874 (PVOID
*)&Thread
, NULL
);
1875 if (!NT_SUCCESS(Status
))
1877 ObfDereferenceObject(Token
);
1880 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1885 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
1886 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
1887 ObfDereferenceObject(PrimaryToken
);
1888 ObfDereferenceObject(Thread
);
1889 if (!NT_SUCCESS(Status
))
1891 ObfDereferenceObject(Token
);
1894 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1899 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
1900 SECURITY_DESCRIPTOR_REVISION
);
1901 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
1904 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
1905 NULL
, &SecurityDescriptor
);
1907 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
1908 TokenImpersonation
, ImpersonationLevel
,
1909 KernelMode
, &NewToken
);
1911 if (!NT_SUCCESS(Status
))
1913 ObfDereferenceObject(Token
);
1916 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1921 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
1924 ObfDereferenceObject(NewToken
);
1928 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
1929 NULL
, DesiredAccess
, SepTokenObjectType
,
1930 ExGetPreviousMode(), TokenHandle
);
1933 ObfDereferenceObject(Token
);
1937 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1947 NtOpenThreadToken(IN HANDLE ThreadHandle
,
1948 IN ACCESS_MASK DesiredAccess
,
1949 IN BOOLEAN OpenAsSelf
,
1950 OUT PHANDLE TokenHandle
)
1952 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,