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 *****************************************************************/
15 #define NTOS_MODE_KERNEL
17 #include <internal/ob.h>
18 #include <internal/ps.h>
19 #include <internal/se.h>
20 #include <internal/safe.h>
23 #include <internal/debug.h>
25 /* GLOBALS *******************************************************************/
27 POBJECT_TYPE SepTokenObjectType
= NULL
;
29 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
34 //#define SYSTEM_LUID 0x3E7;
36 /* FUNCTIONS *****************************************************************/
38 VOID
SepFreeProxyData(PVOID ProxyData
)
43 NTSTATUS
SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
46 return(STATUS_NOT_IMPLEMENTED
);
49 NTSTATUS
SeExchangePrimaryToken(PEPROCESS Process
,
50 PACCESS_TOKEN NewToken
,
51 PACCESS_TOKEN
* OldTokenP
)
53 PACCESS_TOKEN OldToken
;
55 if (NewToken
->TokenType
!= TokenPrimary
)
57 return(STATUS_UNSUCCESSFUL
);
59 if (NewToken
->TokenInUse
!= 0)
61 return(STATUS_UNSUCCESSFUL
);
63 OldToken
= Process
->Token
;
64 Process
->Token
= NewToken
;
65 NewToken
->TokenInUse
= 1;
66 ObReferenceObjectByPointer(NewToken
,
70 OldToken
->TokenInUse
= 0;
71 *OldTokenP
= OldToken
;
72 return(STATUS_SUCCESS
);
76 RtlLengthSidAndAttributes(ULONG Count
,
77 PSID_AND_ATTRIBUTES Src
)
82 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
83 for (i
= 0; i
< Count
; i
++)
84 uLength
+= RtlLengthSid(Src
[i
].Sid
);
91 SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token
,
97 Token
->PrimaryGroup
= 0;
101 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
104 /* Validate and set the primary group and user pointers */
105 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
108 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
110 Token
->DefaultOwnerIndex
= i
;
113 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
115 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
119 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
121 return(STATUS_INVALID_OWNER
);
124 if (Token
->PrimaryGroup
== 0)
126 return(STATUS_INVALID_PRIMARY_GROUP
);
129 return(STATUS_SUCCESS
);
134 SepDuplicateToken(PACCESS_TOKEN Token
,
135 POBJECT_ATTRIBUTES ObjectAttributes
,
136 BOOLEAN EffectiveOnly
,
137 TOKEN_TYPE TokenType
,
138 SECURITY_IMPERSONATION_LEVEL Level
,
139 KPROCESSOR_MODE PreviousMode
,
140 PACCESS_TOKEN
* NewAccessToken
)
148 PACCESS_TOKEN AccessToken
;
150 Status
= ObCreateObject(PreviousMode
,
155 sizeof(ACCESS_TOKEN
),
158 (PVOID
*)&AccessToken
);
159 if (!NT_SUCCESS(Status
))
161 DPRINT1("ObCreateObject() failed (Status %lx)\n");
165 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
166 if (!NT_SUCCESS(Status
))
168 ObDereferenceObject(AccessToken
);
172 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
173 if (!NT_SUCCESS(Status
))
175 ObDereferenceObject(AccessToken
);
179 AccessToken
->TokenInUse
= 0;
180 AccessToken
->TokenType
= TokenType
;
181 AccessToken
->ImpersonationLevel
= Level
;
182 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
184 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
185 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
186 memcpy(AccessToken
->TokenSource
.SourceName
,
187 Token
->TokenSource
.SourceName
,
188 sizeof(Token
->TokenSource
.SourceName
));
189 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
190 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
191 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
193 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
194 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
195 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
197 AccessToken
->UserAndGroups
=
198 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
200 TAG('T', 'O', 'K', 'u'));
202 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
204 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
205 Token
->UserAndGroups
,
207 AccessToken
->UserAndGroups
,
211 if (NT_SUCCESS(Status
))
213 Status
= SepFindPrimaryGroupAndDefaultOwner(
219 if (NT_SUCCESS(Status
))
221 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
223 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
224 AccessToken
->Privileges
=
225 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
227 TAG('T', 'O', 'K', 'p'));
229 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
231 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
232 &Token
->Privileges
[i
].Luid
);
233 AccessToken
->Privileges
[i
].Attributes
=
234 Token
->Privileges
[i
].Attributes
;
237 if ( Token
->DefaultDacl
)
239 AccessToken
->DefaultDacl
=
240 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
241 Token
->DefaultDacl
->AclSize
,
242 TAG('T', 'O', 'K', 'd'));
243 memcpy(AccessToken
->DefaultDacl
,
245 Token
->DefaultDacl
->AclSize
);
249 AccessToken
->DefaultDacl
= 0;
253 if ( NT_SUCCESS(Status
) )
255 *NewAccessToken
= AccessToken
;
256 return(STATUS_SUCCESS
);
259 ObDereferenceObject(AccessToken
);
265 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
266 struct _EPROCESS
* ParentProcess
)
269 PACCESS_TOKEN pNewToken
;
270 PACCESS_TOKEN pParentToken
;
272 OBJECT_ATTRIBUTES ObjectAttributes
;
274 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
276 InitializeObjectAttributes(&ObjectAttributes
,
282 Status
= SepDuplicateToken(pParentToken
,
286 pParentToken
->ImpersonationLevel
,
289 if ( ! NT_SUCCESS(Status
) )
292 NewProcess
->Token
= pNewToken
;
293 return(STATUS_SUCCESS
);
302 PACCESS_STATE AccessState
,
303 PPRIVILEGE_SET Privileges
307 return STATUS_NOT_IMPLEMENTED
;
312 SeCopyClientToken(PACCESS_TOKEN Token
,
313 SECURITY_IMPERSONATION_LEVEL Level
,
314 KPROCESSOR_MODE PreviousMode
,
315 PACCESS_TOKEN
* NewToken
)
318 OBJECT_ATTRIBUTES ObjectAttributes
;
320 InitializeObjectAttributes(&ObjectAttributes
,
325 Status
= SepDuplicateToken(Token
,
340 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
341 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
342 IN BOOLEAN RemoteClient
,
343 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
345 TOKEN_TYPE TokenType
;
347 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
350 PACCESS_TOKEN NewToken
;
352 Token
= PsReferenceEffectiveToken(Thread
,
355 &ImpersonationLevel
);
356 if (TokenType
!= TokenImpersonation
)
358 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
362 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
366 ObDereferenceObject(Token
);
368 return(STATUS_UNSUCCESSFUL
);
370 if (ImpersonationLevel
== SecurityAnonymous
||
371 ImpersonationLevel
== SecurityIdentification
||
372 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= SecurityDelegation
))
376 ObDereferenceObject(Token
);
378 return(STATUS_UNSUCCESSFUL
);
381 Qos
->EffectiveOnly
!= 0)
383 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
387 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
391 if (Qos
->ContextTrackingMode
== 0)
393 ClientContext
->DirectlyAccessClientToken
= FALSE
;
394 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
397 // ObDeleteCapturedInsertInfo(NewToken);
399 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
401 ObDereferenceObject(Token
);
410 ClientContext
->DirectlyAccessClientToken
= TRUE
;
411 if (RemoteClient
!= FALSE
)
413 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
417 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
418 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
419 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
420 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
421 ClientContext
->ServerIsRemote
= RemoteClient
;
422 ClientContext
->Token
= NewToken
;
424 return(STATUS_SUCCESS
);
432 SeCreateClientSecurityFromSubjectContext(
433 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
434 IN PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos
,
435 IN BOOLEAN ServerIsRemote
,
436 OUT PSECURITY_CLIENT_CONTEXT ClientContext
440 return STATUS_NOT_IMPLEMENTED
;
449 IN PACCESS_TOKEN ExistingToken
,
451 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
452 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
453 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
454 OUT PACCESS_TOKEN
* FilteredToken
458 return STATUS_NOT_IMPLEMENTED
;
467 IN PPRIVILEGE_SET Privileges
479 SeImpersonateClientEx(
480 IN PSECURITY_CLIENT_CONTEXT ClientContext
,
481 IN PETHREAD ServerThread OPTIONAL
485 return STATUS_NOT_IMPLEMENTED
;
492 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
493 IN PETHREAD ServerThread OPTIONAL
)
497 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
499 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
503 b
= ClientContext
->DirectAccessEffectiveOnly
;
505 if (ServerThread
== NULL
)
507 ServerThread
= PsGetCurrentThread();
509 PsImpersonateClient(ServerThread
,
510 ClientContext
->Token
,
513 ClientContext
->SecurityQos
.ImpersonationLevel
);
518 SepDeleteToken(PVOID ObjectBody
)
520 PACCESS_TOKEN AccessToken
= (PACCESS_TOKEN
)ObjectBody
;
522 if (AccessToken
->UserAndGroups
)
523 ExFreePool(AccessToken
->UserAndGroups
);
525 if (AccessToken
->Privileges
)
526 ExFreePool(AccessToken
->Privileges
);
528 if (AccessToken
->DefaultDacl
)
529 ExFreePool(AccessToken
->DefaultDacl
);
534 SepInitializeTokenImplementation(VOID
)
536 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
538 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
539 SepTokenObjectType
->MaxObjects
= ULONG_MAX
;
540 SepTokenObjectType
->MaxHandles
= ULONG_MAX
;
541 SepTokenObjectType
->TotalObjects
= 0;
542 SepTokenObjectType
->TotalHandles
= 0;
543 SepTokenObjectType
->PagedPoolCharge
= 0;
544 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(ACCESS_TOKEN
);
545 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
546 SepTokenObjectType
->Dump
= NULL
;
547 SepTokenObjectType
->Open
= NULL
;
548 SepTokenObjectType
->Close
= NULL
;
549 SepTokenObjectType
->Delete
= SepDeleteToken
;
550 SepTokenObjectType
->Parse
= NULL
;
551 SepTokenObjectType
->Security
= NULL
;
552 SepTokenObjectType
->QueryName
= NULL
;
553 SepTokenObjectType
->OkayToClose
= NULL
;
554 SepTokenObjectType
->Create
= NULL
;
555 SepTokenObjectType
->DuplicationNotify
= NULL
;
557 RtlCreateUnicodeString(&SepTokenObjectType
->TypeName
,
559 ObpCreateTypeObject (SepTokenObjectType
);
567 NtQueryInformationToken(IN HANDLE TokenHandle
,
568 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
569 OUT PVOID TokenInformation
,
570 IN ULONG TokenInformationLength
,
571 OUT PULONG ReturnLength
)
573 NTSTATUS Status
, LengthStatus
;
578 PTOKEN_GROUPS PtrTokenGroups
;
579 PTOKEN_DEFAULT_DACL PtrDefaultDacl
;
580 PTOKEN_STATISTICS PtrTokenStatistics
;
582 Status
= ObReferenceObjectByHandle(TokenHandle
,
583 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
588 if (!NT_SUCCESS(Status
))
593 switch (TokenInformationClass
)
596 DPRINT("NtQueryInformationToken(TokenUser)\n");
597 Length
= RtlLengthSidAndAttributes(1, Token
->UserAndGroups
);
598 if (TokenInformationLength
< Length
)
600 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
601 if (NT_SUCCESS(Status
))
602 Status
= STATUS_BUFFER_TOO_SMALL
;
606 Status
= RtlCopySidAndAttributesArray(1,
607 Token
->UserAndGroups
,
608 TokenInformationLength
,
610 (char*)TokenInformation
+ 8,
613 if (NT_SUCCESS(Status
))
615 Length
= TokenInformationLength
- Length
;
616 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
622 DPRINT("NtQueryInformationToken(TokenGroups)\n");
623 Length
= RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]) + sizeof(ULONG
);
624 if (TokenInformationLength
< Length
)
626 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
627 if (NT_SUCCESS(Status
))
628 Status
= STATUS_BUFFER_TOO_SMALL
;
632 EndMem
= (char*)TokenInformation
+ Token
->UserAndGroupCount
* sizeof(SID_AND_ATTRIBUTES
);
633 PtrTokenGroups
= (PTOKEN_GROUPS
)TokenInformation
;
634 PtrTokenGroups
->GroupCount
= Token
->UserAndGroupCount
- 1;
635 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
636 &Token
->UserAndGroups
[1],
637 TokenInformationLength
,
638 PtrTokenGroups
->Groups
,
642 if (NT_SUCCESS(Status
))
644 Length
= TokenInformationLength
- Length
;
645 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
650 case TokenPrivileges
:
651 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
652 Length
= sizeof(ULONG
) + Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
653 if (TokenInformationLength
< Length
)
655 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
656 if (NT_SUCCESS(Status
))
657 Status
= STATUS_BUFFER_TOO_SMALL
;
662 TOKEN_PRIVILEGES
* pPriv
= (TOKEN_PRIVILEGES
*)TokenInformation
;
664 pPriv
->PrivilegeCount
= Token
->PrivilegeCount
;
665 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
667 RtlCopyLuid(&pPriv
->Privileges
[i
].Luid
, &Token
->Privileges
[i
].Luid
);
668 pPriv
->Privileges
[i
].Attributes
= Token
->Privileges
[i
].Attributes
;
670 Status
= STATUS_SUCCESS
;
675 DPRINT("NtQueryInformationToken(TokenOwner)\n");
676 Length
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
) + sizeof(TOKEN_OWNER
);
677 if (TokenInformationLength
< Length
)
679 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
680 if (NT_SUCCESS(Status
))
681 Status
= STATUS_BUFFER_TOO_SMALL
;
685 ((PTOKEN_OWNER
)TokenInformation
)->Owner
=
686 (PSID
)(((PTOKEN_OWNER
)TokenInformation
) + 1);
687 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
688 ((PTOKEN_OWNER
)TokenInformation
)->Owner
,
689 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
690 Status
= STATUS_SUCCESS
;
694 case TokenPrimaryGroup
:
695 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
696 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
697 Length
= RtlLengthSid(Token
->PrimaryGroup
) + sizeof(TOKEN_PRIMARY_GROUP
);
698 if (TokenInformationLength
< Length
)
700 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
701 if (NT_SUCCESS(Status
))
702 Status
= STATUS_BUFFER_TOO_SMALL
;
706 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
=
707 (PSID
)(((PTOKEN_PRIMARY_GROUP
)TokenInformation
) + 1);
708 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
709 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
,
710 Token
->PrimaryGroup
);
711 Status
= STATUS_SUCCESS
;
715 case TokenDefaultDacl
:
716 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
717 PtrDefaultDacl
= (PTOKEN_DEFAULT_DACL
) TokenInformation
;
718 Length
= (Token
->DefaultDacl
? Token
->DefaultDacl
->AclSize
: 0) + sizeof(TOKEN_DEFAULT_DACL
);
719 if (TokenInformationLength
< Length
)
721 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
722 if (NT_SUCCESS(Status
))
723 Status
= STATUS_BUFFER_TOO_SMALL
;
725 else if (!Token
->DefaultDacl
)
727 PtrDefaultDacl
->DefaultDacl
= 0;
728 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
732 PtrDefaultDacl
->DefaultDacl
= (PACL
) (PtrDefaultDacl
+ 1);
733 memmove(PtrDefaultDacl
->DefaultDacl
,
735 Token
->DefaultDacl
->AclSize
);
736 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
741 DPRINT("NtQueryInformationToken(TokenSource)\n");
742 if (TokenInformationLength
< sizeof(TOKEN_SOURCE
))
744 Length
= sizeof(TOKEN_SOURCE
);
745 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
746 if (NT_SUCCESS(Status
))
747 Status
= STATUS_BUFFER_TOO_SMALL
;
751 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenSource
, sizeof(TOKEN_SOURCE
));
756 DPRINT("NtQueryInformationToken(TokenType)\n");
757 if (TokenInformationLength
< sizeof(TOKEN_TYPE
))
759 Length
= sizeof(TOKEN_TYPE
);
760 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
761 if (NT_SUCCESS(Status
))
762 Status
= STATUS_BUFFER_TOO_SMALL
;
766 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenType
, sizeof(TOKEN_TYPE
));
770 case TokenImpersonationLevel
:
771 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
772 if (TokenInformationLength
< sizeof(SECURITY_IMPERSONATION_LEVEL
))
774 Length
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
775 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
776 if (NT_SUCCESS(Status
))
777 Status
= STATUS_BUFFER_TOO_SMALL
;
781 Status
= MmCopyToCaller(TokenInformation
, &Token
->ImpersonationLevel
, sizeof(SECURITY_IMPERSONATION_LEVEL
));
785 case TokenStatistics
:
786 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
787 if (TokenInformationLength
< sizeof(TOKEN_STATISTICS
))
789 Length
= sizeof(TOKEN_STATISTICS
);
790 Status
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
791 if (NT_SUCCESS(Status
))
792 Status
= STATUS_BUFFER_TOO_SMALL
;
796 PtrTokenStatistics
= (PTOKEN_STATISTICS
)TokenInformation
;
797 PtrTokenStatistics
->TokenId
= Token
->TokenId
;
798 PtrTokenStatistics
->AuthenticationId
= Token
->AuthenticationId
;
799 PtrTokenStatistics
->ExpirationTime
= Token
->ExpirationTime
;
800 PtrTokenStatistics
->TokenType
= Token
->TokenType
;
801 PtrTokenStatistics
->ImpersonationLevel
= Token
->ImpersonationLevel
;
802 PtrTokenStatistics
->DynamicCharged
= Token
->DynamicCharged
;
803 PtrTokenStatistics
->DynamicAvailable
= Token
->DynamicAvailable
;
804 PtrTokenStatistics
->GroupCount
= Token
->UserAndGroupCount
- 1;
805 PtrTokenStatistics
->PrivilegeCount
= Token
->PrivilegeCount
;
806 PtrTokenStatistics
->ModifiedId
= Token
->ModifiedId
;
808 Status
= STATUS_SUCCESS
;
813 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
814 if (TokenInformationLength
< sizeof(TOKEN_ORIGIN
))
816 Status
= STATUS_BUFFER_TOO_SMALL
;
820 Status
= MmCopyToCaller(&((PTOKEN_ORIGIN
)TokenInformation
)->OriginatingLogonSession
,
821 &Token
->AuthenticationId
, sizeof(LUID
));
823 Length
= sizeof(TOKEN_ORIGIN
);
824 LengthStatus
= MmCopyToCaller(ReturnLength
, &Length
, sizeof(ULONG
));
825 if (NT_SUCCESS(Status
))
827 Status
= LengthStatus
;
831 case TokenGroupsAndPrivileges
:
832 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
833 Status
= STATUS_NOT_IMPLEMENTED
;
836 case TokenRestrictedSids
:
837 DPRINT1("NtQueryInformationToken(TokenRestrictedSids) not implemented\n");
838 Status
= STATUS_NOT_IMPLEMENTED
;
841 case TokenSandBoxInert
:
842 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
843 Status
= STATUS_NOT_IMPLEMENTED
;
847 DPRINT1("NtQueryInformationToken(TokenSessionId) not implemented\n");
848 Status
= STATUS_NOT_IMPLEMENTED
;
852 DPRINT1("NtQueryInformationToken(%d) invalid parameter\n");
853 Status
= STATUS_INVALID_PARAMETER
;
857 ObDereferenceObject(Token
);
867 SeQueryInformationToken(
868 IN PACCESS_TOKEN Token
,
869 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
870 OUT PVOID
*TokenInformation
874 return STATUS_NOT_IMPLEMENTED
;
882 SeQuerySessionIdToken(
883 IN PACCESS_TOKEN Token
,
888 return STATUS_NOT_IMPLEMENTED
;
892 * NtSetTokenInformation: Partly implemented.
894 * TokenOrigin, TokenDefaultDacl, TokenSessionId
898 NtSetInformationToken(IN HANDLE TokenHandle
,
899 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
900 OUT PVOID TokenInformation
,
901 IN ULONG TokenInformationLength
)
905 TOKEN_OWNER TokenOwnerSet
= { 0 };
906 TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet
= { 0 };
907 DWORD NeededAccess
= 0;
909 switch (TokenInformationClass
)
912 case TokenPrimaryGroup
:
913 NeededAccess
= TOKEN_ADJUST_DEFAULT
;
916 case TokenDefaultDacl
:
917 if (TokenInformationLength
< sizeof(TOKEN_DEFAULT_DACL
))
918 return STATUS_BUFFER_TOO_SMALL
;
919 NeededAccess
= TOKEN_ADJUST_DEFAULT
;
923 DPRINT1("NtSetInformationToken: lying about success (stub) - %x\n", TokenInformationClass
);
924 return STATUS_SUCCESS
;
928 Status
= ObReferenceObjectByHandle(TokenHandle
,
934 if (!NT_SUCCESS(Status
))
939 switch (TokenInformationClass
)
942 MmCopyFromCaller( &TokenOwnerSet
, TokenInformation
,
943 min(sizeof(TokenOwnerSet
),TokenInformationLength
) );
944 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
945 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
946 TokenOwnerSet
.Owner
);
947 Status
= STATUS_SUCCESS
;
948 DPRINT("NtSetInformationToken(TokenOwner)\n");
951 case TokenPrimaryGroup
:
952 MmCopyFromCaller( &TokenPrimaryGroupSet
, TokenInformation
,
953 min(sizeof(TokenPrimaryGroupSet
),
954 TokenInformationLength
) );
955 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
957 TokenPrimaryGroupSet
.PrimaryGroup
);
958 Status
= STATUS_SUCCESS
;
959 DPRINT("NtSetInformationToken(TokenPrimaryGroup),"
960 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
963 case TokenDefaultDacl
:
965 TOKEN_DEFAULT_DACL TokenDefaultDacl
= { 0 };
969 Status
= MmCopyFromCaller( &TokenDefaultDacl
, TokenInformation
,
970 sizeof(TOKEN_DEFAULT_DACL
) );
971 if (!NT_SUCCESS(Status
))
973 Status
= STATUS_INVALID_PARAMETER
;
977 Status
= MmCopyFromCaller( &OldAcl
, TokenDefaultDacl
.DefaultDacl
,
979 if (!NT_SUCCESS(Status
))
981 Status
= STATUS_INVALID_PARAMETER
;
985 NewAcl
= ExAllocatePool(NonPagedPool
, sizeof(ACL
));
988 Status
= STATUS_INSUFFICIENT_RESOURCES
;
992 Status
= MmCopyFromCaller( NewAcl
, TokenDefaultDacl
.DefaultDacl
,
994 if (!NT_SUCCESS(Status
))
996 Status
= STATUS_INVALID_PARAMETER
;
1001 if (Token
->DefaultDacl
)
1003 ExFreePool(Token
->DefaultDacl
);
1006 Token
->DefaultDacl
= NewAcl
;
1008 Status
= STATUS_SUCCESS
;
1013 Status
= STATUS_NOT_IMPLEMENTED
;
1017 ObDereferenceObject(Token
);
1026 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1027 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1028 * is correct either. -Gunnar
1031 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1032 IN ACCESS_MASK DesiredAccess
,
1033 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
/*is it really optional?*/,
1034 IN BOOLEAN EffectiveOnly
,
1035 IN TOKEN_TYPE TokenType
,
1036 OUT PHANDLE NewTokenHandle
)
1038 KPROCESSOR_MODE PreviousMode
;
1039 PACCESS_TOKEN Token
;
1040 PACCESS_TOKEN NewToken
;
1043 PreviousMode
= KeGetPreviousMode();
1044 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1050 if (!NT_SUCCESS(Status
))
1052 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
1056 Status
= SepDuplicateToken(Token
,
1060 ObjectAttributes
->SecurityQualityOfService
?
1061 ObjectAttributes
->SecurityQualityOfService
->ImpersonationLevel
:
1062 0 /*SecurityAnonymous*/,
1066 ObDereferenceObject(Token
);
1068 if (!NT_SUCCESS(Status
))
1070 DPRINT1("Failed to duplicate token (Status %lx)\n", Status
);
1074 Status
= ObInsertObject((PVOID
)NewToken
,
1081 ObDereferenceObject(NewToken
);
1083 if (!NT_SUCCESS(Status
))
1085 DPRINT1("Failed to create token handle (Status %lx)\n");
1089 return STATUS_SUCCESS
;
1093 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
1095 BOOLEAN ResetToDefault
,
1096 PSID_AND_ATTRIBUTES Groups
,
1098 KPROCESSOR_MODE PreviousMode
,
1109 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1110 IN BOOLEAN ResetToDefault
,
1111 IN PTOKEN_GROUPS NewState
,
1112 IN ULONG BufferLength
,
1113 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1114 OUT PULONG ReturnLength
)
1118 PACCESS_TOKEN Token
;
1123 Status
= ObReferenceObjectByHandle(TokenHandle
,
1131 SepAdjustGroups(Token
,
1143 return(STATUS_NOT_IMPLEMENTED
);
1150 SepAdjustPrivileges(PACCESS_TOKEN Token
,
1152 KPROCESSOR_MODE PreviousMode
,
1153 ULONG PrivilegeCount
,
1154 PLUID_AND_ATTRIBUTES Privileges
,
1155 PTOKEN_PRIVILEGES
* PreviousState
,
1164 if (Token
->PrivilegeCount
> 0)
1166 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1168 if (PreviousMode
!= KernelMode
)
1170 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
1174 if (PreviousState
!= NULL
)
1176 memcpy(&PreviousState
[i
],
1177 &Token
->Privileges
[i
],
1178 sizeof(LUID_AND_ATTRIBUTES
));
1180 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
1187 if (PreviousMode
!= KernelMode
)
1189 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
1193 if (PrivilegeCount
<= ?)
1206 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1207 IN BOOLEAN DisableAllPrivileges
,
1208 IN PTOKEN_PRIVILEGES NewState
,
1209 IN ULONG BufferLength
,
1210 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1211 OUT PULONG ReturnLength OPTIONAL
)
1213 // PLUID_AND_ATTRIBUTES Privileges;
1214 KPROCESSOR_MODE PreviousMode
;
1215 // ULONG PrivilegeCount;
1216 PACCESS_TOKEN Token
;
1229 DPRINT ("NtAdjustPrivilegesToken() called\n");
1231 // PrivilegeCount = NewState->PrivilegeCount;
1232 PreviousMode
= KeGetPreviousMode ();
1233 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1243 Status
= ObReferenceObjectByHandle (TokenHandle
,
1244 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1249 if (!NT_SUCCESS(Status
))
1251 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1252 // SeReleaseLuidAndAttributesArray(Privileges,
1260 SepAdjustPrivileges(Token
,
1272 if (DisableAllPrivileges
== TRUE
)
1274 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1276 if (Token
->Privileges
[i
].Attributes
!= 0)
1278 DPRINT ("Attributes differ\n");
1280 /* Save current privilege */
1281 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1283 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1284 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1288 /* Update current privlege */
1289 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1292 Status
= STATUS_SUCCESS
;
1297 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1299 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1301 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1302 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1304 DPRINT ("Found privilege\n");
1306 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1307 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1309 DPRINT ("Attributes differ\n");
1310 DPRINT ("Current attributes %lx desired attributes %lx\n",
1311 Token
->Privileges
[i
].Attributes
,
1312 NewState
->Privileges
[j
].Attributes
);
1314 /* Save current privilege */
1315 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1317 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1318 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1322 /* Update current privlege */
1323 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1324 Token
->Privileges
[i
].Attributes
|=
1325 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1326 DPRINT ("New attributes %lx\n",
1327 Token
->Privileges
[i
].Attributes
);
1333 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1336 if (ReturnLength
!= NULL
)
1338 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1339 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1342 ObDereferenceObject (Token
);
1344 // SeReleaseLuidAndAttributesArray(Privileges,
1348 DPRINT ("NtAdjustPrivilegesToken() done\n");
1355 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
1361 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1362 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1363 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1364 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1366 PACCESS_TOKEN AccessToken
;
1371 * Initialize the token
1373 Status
= ObCreateObject(KernelMode
,
1378 sizeof(ACCESS_TOKEN
),
1381 (PVOID
*)&AccessToken
);
1382 if (!NT_SUCCESS(Status
))
1387 Status
= NtAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1388 if (!NT_SUCCESS(Status
))
1390 ObDereferenceObject(AccessToken
);
1394 Status
= NtAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1395 if (!NT_SUCCESS(Status
))
1397 ObDereferenceObject(AccessToken
);
1401 Status
= NtAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
1402 if (!NT_SUCCESS(Status
))
1404 ObDereferenceObject(AccessToken
);
1408 AccessToken
->TokenType
= TokenPrimary
;
1409 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1410 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1411 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1412 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1413 AccessToken
->ExpirationTime
.QuadPart
= -1;
1414 AccessToken
->UserAndGroupCount
= 4;
1416 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1417 uSize
+= uLocalSystemLength
;
1418 uSize
+= uWorldLength
;
1419 uSize
+= uAuthUserLength
;
1420 uSize
+= uAdminsLength
;
1422 AccessToken
->UserAndGroups
=
1423 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1425 TAG('T', 'O', 'K', 'u'));
1426 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1429 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1430 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1431 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1432 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
1434 AccessToken
->DefaultOwnerIndex
= i
;
1435 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1436 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1437 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1438 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1439 SidArea
= (char*)SidArea
+ uAdminsLength
;
1441 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1442 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1443 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1444 SidArea
= (char*)SidArea
+ uWorldLength
;
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(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1449 SidArea
= (char*)SidArea
+ uAuthUserLength
;
1451 AccessToken
->PrivilegeCount
= 20;
1453 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1454 AccessToken
->Privileges
=
1455 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1457 TAG('T', 'O', 'K', 'p'));
1460 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1461 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1463 AccessToken
->Privileges
[i
].Attributes
= 0;
1464 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1466 AccessToken
->Privileges
[i
].Attributes
= 0;
1467 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1469 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1470 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1472 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1473 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1475 AccessToken
->Privileges
[i
].Attributes
= 0;
1476 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1478 AccessToken
->Privileges
[i
].Attributes
= 0;
1479 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1481 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1482 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1484 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1485 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1487 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1488 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1490 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1491 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1493 AccessToken
->Privileges
[i
].Attributes
= 0;
1494 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1496 AccessToken
->Privileges
[i
].Attributes
= 0;
1497 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1499 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1500 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1502 AccessToken
->Privileges
[i
].Attributes
= 0;
1503 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1505 AccessToken
->Privileges
[i
].Attributes
= 0;
1506 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1508 AccessToken
->Privileges
[i
].Attributes
= 0;
1509 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1511 AccessToken
->Privileges
[i
].Attributes
= 0;
1512 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1514 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1515 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1517 AccessToken
->Privileges
[i
].Attributes
= 0;
1518 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1520 AccessToken
->Privileges
[i
].Attributes
= 0;
1521 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1523 AccessToken
->Privileges
[i
].Attributes
= 0;
1524 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1529 uSize
= sizeof(ACL
);
1530 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1531 uSize
+= sizeof(ACE
) + uAdminsLength
;
1532 uSize
= (uSize
& (~3)) + 8;
1533 AccessToken
->DefaultDacl
=
1534 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1536 TAG('T', 'O', 'K', 'd'));
1537 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1538 if ( NT_SUCCESS(Status
) )
1540 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1543 if ( NT_SUCCESS(Status
) )
1545 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1548 if ( ! NT_SUCCESS(Status
) )
1550 ObDereferenceObject(AccessToken
);
1554 Process
->Token
= AccessToken
;
1555 return(STATUS_SUCCESS
);
1560 NtCreateToken(OUT PHANDLE UnsafeTokenHandle
,
1561 IN ACCESS_MASK DesiredAccess
,
1562 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes
,
1563 IN TOKEN_TYPE TokenType
,
1564 IN PLUID AuthenticationId
,
1565 IN PLARGE_INTEGER ExpirationTime
,
1566 IN PTOKEN_USER TokenUser
,
1567 IN PTOKEN_GROUPS TokenGroups
,
1568 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1569 IN PTOKEN_OWNER TokenOwner
,
1570 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1571 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1572 IN PTOKEN_SOURCE TokenSource
)
1575 PACCESS_TOKEN AccessToken
;
1577 OBJECT_ATTRIBUTES SafeObjectAttributes
;
1578 POBJECT_ATTRIBUTES ObjectAttributes
;
1585 Status
= MmCopyFromCaller(&SafeObjectAttributes
,
1586 UnsafeObjectAttributes
,
1587 sizeof(OBJECT_ATTRIBUTES
));
1588 if (!NT_SUCCESS(Status
))
1591 ObjectAttributes
= &SafeObjectAttributes
;
1593 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
1594 if (!NT_SUCCESS(Status
))
1597 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
1598 if (!NT_SUCCESS(Status
))
1601 Status
= ObCreateObject(ExGetPreviousMode(),
1604 ExGetPreviousMode(),
1606 sizeof(ACCESS_TOKEN
),
1609 (PVOID
*)&AccessToken
);
1610 if (!NT_SUCCESS(Status
))
1612 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1616 Status
= ObInsertObject ((PVOID
)AccessToken
,
1622 if (!NT_SUCCESS(Status
))
1624 DPRINT1("ObInsertObject() failed (Status %lx)\n");
1625 ObDereferenceObject (AccessToken
);
1629 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
1630 &TokenSource
->SourceIdentifier
);
1631 memcpy(AccessToken
->TokenSource
.SourceName
,
1632 TokenSource
->SourceName
,
1633 sizeof(TokenSource
->SourceName
));
1635 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
1636 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
1637 AccessToken
->ExpirationTime
= *ExpirationTime
;
1638 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
1640 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
1641 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
1642 AccessToken
->UserAndGroups
= 0;
1643 AccessToken
->Privileges
= 0;
1645 AccessToken
->TokenType
= TokenType
;
1646 AccessToken
->ImpersonationLevel
= ObjectAttributes
->SecurityQualityOfService
->ImpersonationLevel
;
1649 * Normally we would just point these members into the variable information
1650 * area; however, our ObCreateObject() call can't allocate a variable information
1651 * area, so we allocate them seperately and provide a destroy function.
1654 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1655 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
1656 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
1657 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
1659 AccessToken
->UserAndGroups
=
1660 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1662 TAG('T', 'O', 'K', 'u'));
1664 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1666 Status
= RtlCopySidAndAttributesArray(1,
1669 AccessToken
->UserAndGroups
,
1673 if (NT_SUCCESS(Status
))
1675 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
1676 TokenGroups
->Groups
,
1678 &AccessToken
->UserAndGroups
[1],
1684 if (NT_SUCCESS(Status
))
1686 Status
= SepFindPrimaryGroupAndDefaultOwner(
1688 TokenPrimaryGroup
->PrimaryGroup
,
1692 if (NT_SUCCESS(Status
))
1694 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1695 AccessToken
->Privileges
=
1696 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1698 TAG('T', 'O', 'K', 'p'));
1700 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
1702 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
1703 &TokenPrivileges
->Privileges
[i
],
1704 sizeof(LUID_AND_ATTRIBUTES
));
1705 if (!NT_SUCCESS(Status
))
1710 if (NT_SUCCESS(Status
))
1712 AccessToken
->DefaultDacl
=
1713 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1714 TokenDefaultDacl
->DefaultDacl
->AclSize
,
1715 TAG('T', 'O', 'K', 'd'));
1716 memcpy(AccessToken
->DefaultDacl
,
1717 TokenDefaultDacl
->DefaultDacl
,
1718 TokenDefaultDacl
->DefaultDacl
->AclSize
);
1721 ObDereferenceObject(AccessToken
);
1723 if (NT_SUCCESS(Status
))
1725 Status
= MmCopyToCaller(UnsafeTokenHandle
,
1730 if (!NT_SUCCESS(Status
))
1732 ZwClose(TokenHandle
);
1736 return(STATUS_SUCCESS
);
1744 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
1747 LogonId
->LowPart
= Token
->AuthenticationId
.LowPart
;
1748 LogonId
->HighPart
= Token
->AuthenticationId
.HighPart
;
1750 return STATUS_SUCCESS
;
1757 SECURITY_IMPERSONATION_LEVEL STDCALL
1758 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1760 return Token
->ImpersonationLevel
;
1768 SeTokenType(IN PACCESS_TOKEN Token
)
1770 return Token
->TokenType
;
1780 IN PACCESS_TOKEN Token
1792 SeTokenIsRestricted(
1793 IN PACCESS_TOKEN Token
1805 SeTokenIsWriteRestricted(
1806 IN PACCESS_TOKEN Token
1819 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
1820 IN ACCESS_MASK DesiredAccess
,
1821 IN BOOLEAN OpenAsSelf
,
1822 IN ULONG HandleAttributes
,
1823 OUT PHANDLE TokenHandle
)
1826 PACCESS_TOKEN Token
, NewToken
, PrimaryToken
;
1827 BOOLEAN CopyOnOpen
, EffectiveOnly
;
1828 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
1829 SE_IMPERSONATION_STATE ImpersonationState
;
1830 OBJECT_ATTRIBUTES ObjectAttributes
;
1831 SECURITY_DESCRIPTOR SecurityDescriptor
;
1836 * At first open the thread token for information access and verify
1837 * that the token associated with thread is valid.
1840 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
1841 PsThreadType
, UserMode
, (PVOID
*)&Thread
,
1843 if (!NT_SUCCESS(Status
))
1848 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
1849 &ImpersonationLevel
);
1852 ObfDereferenceObject(Thread
);
1853 return STATUS_NO_TOKEN
;
1856 ObDereferenceObject(Thread
);
1858 if (ImpersonationLevel
== SecurityAnonymous
)
1860 ObfDereferenceObject(Token
);
1861 return STATUS_CANT_OPEN_ANONYMOUS
;
1865 * Revert to self if OpenAsSelf is specified.
1870 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1875 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
1876 PsThreadType
, UserMode
,
1877 (PVOID
*)&Thread
, NULL
);
1878 if (!NT_SUCCESS(Status
))
1880 ObfDereferenceObject(Token
);
1883 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1888 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
1889 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
1890 ObfDereferenceObject(PrimaryToken
);
1891 ObfDereferenceObject(Thread
);
1892 if (!NT_SUCCESS(Status
))
1894 ObfDereferenceObject(Token
);
1897 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1902 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
1903 SECURITY_DESCRIPTOR_REVISION
);
1904 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
1907 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
1908 NULL
, &SecurityDescriptor
);
1910 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
1911 TokenImpersonation
, ImpersonationLevel
,
1912 KernelMode
, &NewToken
);
1914 if (!NT_SUCCESS(Status
))
1916 ObfDereferenceObject(Token
);
1919 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1924 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
1927 ObfDereferenceObject(NewToken
);
1931 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
1932 NULL
, DesiredAccess
, SepTokenObjectType
,
1933 ExGetPreviousMode(), TokenHandle
);
1936 ObfDereferenceObject(Token
);
1940 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
1950 NtOpenThreadToken(IN HANDLE ThreadHandle
,
1951 IN ACCESS_MASK DesiredAccess
,
1952 IN BOOLEAN OpenAsSelf
,
1953 OUT PHANDLE TokenHandle
)
1955 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,