1 /* $Id: token.c,v 1.17 2002/06/17 22:52:32 joeg Exp $
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 #include <ddk/ntddk.h>
16 #include <internal/ps.h>
17 #include <internal/se.h>
18 #include <internal/safe.h>
21 #include <internal/debug.h>
23 /* GLOBALS *******************************************************************/
25 POBJECT_TYPE SepTokenObjectType
= NULL
;
27 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
32 #define SYSTEM_LUID 0x3E7;
34 /* FUNCTIONS *****************************************************************/
36 VOID
SepFreeProxyData(PVOID ProxyData
)
41 NTSTATUS
SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
46 NTSTATUS
SeExchangePrimaryToken(PEPROCESS Process
,
47 PACCESS_TOKEN NewToken
,
48 PACCESS_TOKEN
* OldTokenP
)
50 PACCESS_TOKEN OldToken
;
52 if (NewToken
->TokenType
!= TokenPrimary
)
54 return(STATUS_UNSUCCESSFUL
);
56 if (NewToken
->TokenInUse
!= 0)
58 return(STATUS_UNSUCCESSFUL
);
60 OldToken
= Process
->Token
;
61 Process
->Token
= NewToken
;
62 NewToken
->TokenInUse
= 1;
63 ObReferenceObjectByPointer(NewToken
,
67 OldToken
->TokenInUse
= 0;
68 *OldTokenP
= OldToken
;
69 return(STATUS_SUCCESS
);
74 RtlCopySidAndAttributesArray(ULONG Count
, // ebp + 8
75 PSID_AND_ATTRIBUTES Src
, // ebp + C
76 ULONG SidAreaSize
, // ebp + 10
77 PSID_AND_ATTRIBUTES Dest
, // ebp + 14
78 PVOID SidArea
, // ebp + 18
79 PVOID
* RemainingSidArea
, // ebp + 1C
80 PULONG RemainingSidAreaSize
) // ebp + 20
82 ULONG Length
; // ebp - 4
87 for (i
=0; i
<Count
; i
++)
89 if (RtlLengthSid(Src
[i
].Sid
) > Length
)
91 return(STATUS_BUFFER_TOO_SMALL
);
93 Length
= Length
- RtlLengthSid(Src
[i
].Sid
);
94 Dest
[i
].Sid
= SidArea
;
95 Dest
[i
].Attributes
= Src
[i
].Attributes
;
96 RtlCopySid(RtlLengthSid(Src
[i
].Sid
), SidArea
, Src
[i
].Sid
);
97 SidArea
= SidArea
+ RtlLengthSid(Src
[i
].Sid
);
99 *RemainingSidArea
= SidArea
;
100 *RemainingSidAreaSize
= Length
;
101 return(STATUS_SUCCESS
);
106 RtlLengthSidAndAttributes(ULONG Count
,
107 PSID_AND_ATTRIBUTES Src
)
112 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
113 for (i
= 0; i
< Count
; i
++)
114 uLength
+= RtlLengthSid(Src
[i
].Sid
);
121 SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token
,
127 Token
->PrimaryGroup
= 0;
131 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
134 /* Validate and set the primary group and user pointers */
135 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
138 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
140 Token
->DefaultOwnerIndex
= i
;
143 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
145 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
149 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
151 return(STATUS_INVALID_OWNER
);
154 if (Token
->PrimaryGroup
== 0)
156 return(STATUS_INVALID_PRIMARY_GROUP
);
159 return(STATUS_SUCCESS
);
164 SepDuplicateToken(PACCESS_TOKEN Token
,
165 POBJECT_ATTRIBUTES ObjectAttributes
,
166 TOKEN_TYPE TokenType
,
167 SECURITY_IMPERSONATION_LEVEL Level
,
168 SECURITY_IMPERSONATION_LEVEL ExistingLevel
,
169 KPROCESSOR_MODE PreviousMode
,
170 PACCESS_TOKEN
* NewAccessToken
)
178 PACCESS_TOKEN AccessToken
;
180 Status
= ObCreateObject(0,
184 (PVOID
*)&AccessToken
);
185 if (!NT_SUCCESS(Status
))
187 DPRINT1("ObCreateObject() failed (Status %lx)\n");
191 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
192 if (!NT_SUCCESS(Status
))
194 ObDereferenceObject(AccessToken
);
198 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
199 if (!NT_SUCCESS(Status
))
201 ObDereferenceObject(AccessToken
);
205 AccessToken
->TokenInUse
= 0;
206 AccessToken
->TokenType
= TokenType
;
207 AccessToken
->ImpersonationLevel
= Level
;
208 AccessToken
->AuthenticationId
.QuadPart
= SYSTEM_LUID
;
210 AccessToken
->TokenSource
.SourceIdentifier
.QuadPart
= Token
->TokenSource
.SourceIdentifier
.QuadPart
;
211 memcpy(AccessToken
->TokenSource
.SourceName
, Token
->TokenSource
.SourceName
, sizeof(Token
->TokenSource
.SourceName
));
212 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
213 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
214 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
216 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
217 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
218 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
220 AccessToken
->UserAndGroups
=
221 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
223 TAG('T', 'O', 'K', 'u'));
225 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
227 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
228 Token
->UserAndGroups
,
230 AccessToken
->UserAndGroups
,
234 if (NT_SUCCESS(Status
))
236 Status
= SepFindPrimaryGroupAndDefaultOwner(
242 if (NT_SUCCESS(Status
))
244 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
246 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
247 AccessToken
->Privileges
=
248 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
250 TAG('T', 'O', 'K', 'p'));
252 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
254 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
255 &Token
->Privileges
[i
].Luid
);
256 AccessToken
->Privileges
[i
].Attributes
=
257 Token
->Privileges
[i
].Attributes
;
260 if ( Token
->DefaultDacl
)
262 AccessToken
->DefaultDacl
=
263 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
264 Token
->DefaultDacl
->AclSize
,
265 TAG('T', 'O', 'K', 'd'));
266 memcpy(AccessToken
->DefaultDacl
,
268 Token
->DefaultDacl
->AclSize
);
272 AccessToken
->DefaultDacl
= 0;
276 if ( NT_SUCCESS(Status
) )
278 *NewAccessToken
= AccessToken
;
279 return(STATUS_SUCCESS
);
282 ObDereferenceObject(AccessToken
);
288 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
289 struct _EPROCESS
* ParentProcess
)
292 PACCESS_TOKEN pNewToken
;
293 PACCESS_TOKEN pParentToken
;
295 OBJECT_ATTRIBUTES ObjectAttributes
;
297 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
299 InitializeObjectAttributes(&ObjectAttributes
,
305 Status
= SepDuplicateToken(pParentToken
,
308 pParentToken
->ImpersonationLevel
,
309 pParentToken
->ImpersonationLevel
,
312 if ( ! NT_SUCCESS(Status
) )
315 NewProcess
->Token
= pNewToken
;
316 return(STATUS_SUCCESS
);
320 NTSTATUS
SeCopyClientToken(PACCESS_TOKEN Token
,
321 SECURITY_IMPERSONATION_LEVEL Level
,
322 KPROCESSOR_MODE PreviousMode
,
323 PACCESS_TOKEN
* NewToken
)
326 OBJECT_ATTRIBUTES ObjectAttributes
;
328 InitializeObjectAttributes(&ObjectAttributes
,
333 Status
= SepDuplicateToken(Token
,
336 SecurityIdentification
,
345 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
346 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
347 IN BOOLEAN RemoteClient
,
348 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
350 TOKEN_TYPE TokenType
;
352 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
355 PACCESS_TOKEN NewToken
;
357 Token
= PsReferenceEffectiveToken(Thread
,
360 &ImpersonationLevel
);
363 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
367 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
371 ObDereferenceObject(Token
);
373 return(STATUS_UNSUCCESSFUL
);
375 if (ImpersonationLevel
== 0 ||
376 ImpersonationLevel
== 1 ||
377 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= 3))
381 ObDereferenceObject(Token
);
383 return(STATUS_UNSUCCESSFUL
);
386 Qos
->EffectiveOnly
!= 0)
388 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
392 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
396 if (Qos
->ContextTrackingMode
== 0)
398 ClientContext
->DirectlyAccessClientToken
= FALSE
;
399 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
402 // ObDeleteCapturedInsertInfo(NewToken);
404 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
406 ObDereferenceObject(Token
);
415 ClientContext
->DirectlyAccessClientToken
= TRUE
;
416 if (RemoteClient
!= FALSE
)
418 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
422 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
423 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
424 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
425 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
426 ClientContext
->ServerIsRemote
= RemoteClient
;
427 ClientContext
->Token
= NewToken
;
429 return(STATUS_SUCCESS
);
434 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
435 IN PETHREAD ServerThread OPTIONAL
)
439 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
441 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
445 b
= ClientContext
->DirectAccessEffectiveOnly
;
447 if (ServerThread
== NULL
)
449 ServerThread
= PsGetCurrentThread();
451 PsImpersonateClient(ServerThread
,
452 ClientContext
->Token
,
455 ClientContext
->SecurityQos
.ImpersonationLevel
);
460 SepDeleteToken(PVOID ObjectBody
)
462 PACCESS_TOKEN AccessToken
= (PACCESS_TOKEN
)ObjectBody
;
464 if (AccessToken
->UserAndGroups
)
465 ExFreePool(AccessToken
->UserAndGroups
);
467 if (AccessToken
->Privileges
)
468 ExFreePool(AccessToken
->Privileges
);
470 if (AccessToken
->DefaultDacl
)
471 ExFreePool(AccessToken
->DefaultDacl
);
476 SepInitializeTokenImplementation(VOID
)
478 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
480 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
481 SepTokenObjectType
->MaxObjects
= ULONG_MAX
;
482 SepTokenObjectType
->MaxHandles
= ULONG_MAX
;
483 SepTokenObjectType
->TotalObjects
= 0;
484 SepTokenObjectType
->TotalHandles
= 0;
485 SepTokenObjectType
->PagedPoolCharge
= 0;
486 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(ACCESS_TOKEN
);
487 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
488 SepTokenObjectType
->Dump
= NULL
;
489 SepTokenObjectType
->Open
= NULL
;
490 SepTokenObjectType
->Close
= NULL
;
491 SepTokenObjectType
->Delete
= SepDeleteToken
;
492 SepTokenObjectType
->Parse
= NULL
;
493 SepTokenObjectType
->Security
= NULL
;
494 SepTokenObjectType
->QueryName
= NULL
;
495 SepTokenObjectType
->OkayToClose
= NULL
;
496 SepTokenObjectType
->Create
= NULL
;
497 SepTokenObjectType
->DuplicationNotify
= NULL
;
499 RtlCreateUnicodeString(&SepTokenObjectType
->TypeName
,
505 NtQueryInformationToken(IN HANDLE TokenHandle
,
506 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
507 OUT PVOID TokenInformation
,
508 IN ULONG TokenInformationLength
,
509 OUT PULONG ReturnLength
)
515 PTOKEN_GROUPS PtrTokenGroups
;
516 PTOKEN_DEFAULT_DACL PtrDefaultDacl
;
517 PTOKEN_STATISTICS PtrTokenStatistics
;
520 Status
= ObReferenceObjectByHandle(TokenHandle
,
521 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
526 if (!NT_SUCCESS(Status
))
531 switch (TokenInformationClass
)
534 DPRINT("NtQueryInformationToken(TokenUser)\n");
535 uLength
= RtlLengthSidAndAttributes(1, Token
->UserAndGroups
);
536 if (TokenInformationLength
< uLength
)
538 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
539 if (NT_SUCCESS(Status
))
540 Status
= STATUS_BUFFER_TOO_SMALL
;
544 Status
= RtlCopySidAndAttributesArray(1,
545 Token
->UserAndGroups
,
546 TokenInformationLength
,
548 TokenInformation
+ 8,
551 if (NT_SUCCESS(Status
))
553 uLength
= TokenInformationLength
- uLength
;
554 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
560 DPRINT("NtQueryInformationToken(TokenGroups)\n");
561 uLength
= RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]) + sizeof(DWORD
);
562 if (TokenInformationLength
< uLength
)
564 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
565 if (NT_SUCCESS(Status
))
566 Status
= STATUS_BUFFER_TOO_SMALL
;
570 EndMem
= TokenInformation
+ Token
->UserAndGroupCount
* sizeof(SID_AND_ATTRIBUTES
);
571 PtrTokenGroups
= (PTOKEN_GROUPS
)TokenInformation
;
572 PtrTokenGroups
->GroupCount
= Token
->UserAndGroupCount
- 1;
573 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
574 &Token
->UserAndGroups
[1],
575 TokenInformationLength
,
576 PtrTokenGroups
->Groups
,
580 if (NT_SUCCESS(Status
))
582 uLength
= TokenInformationLength
- uLength
;
583 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
588 case TokenPrivileges
:
589 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
590 uLength
= sizeof(DWORD
) + Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
591 if (TokenInformationLength
< uLength
)
593 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
594 if (NT_SUCCESS(Status
))
595 Status
= STATUS_BUFFER_TOO_SMALL
;
600 TOKEN_PRIVILEGES
* pPriv
= (TOKEN_PRIVILEGES
*)TokenInformation
;
602 pPriv
->PrivilegeCount
= Token
->PrivilegeCount
;
603 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
605 RtlCopyLuid(&pPriv
->Privileges
[i
].Luid
, &Token
->Privileges
[i
].Luid
);
606 pPriv
->Privileges
[i
].Attributes
= Token
->Privileges
[i
].Attributes
;
608 Status
= STATUS_SUCCESS
;
613 DPRINT("NtQueryInformationToken(TokenOwner)\n");
614 uLength
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
) + sizeof(TOKEN_OWNER
);
615 if (TokenInformationLength
< uLength
)
617 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
618 if (NT_SUCCESS(Status
))
619 Status
= STATUS_BUFFER_TOO_SMALL
;
623 ((PTOKEN_OWNER
)TokenInformation
)->Owner
=
624 (PSID
)(((PTOKEN_OWNER
)TokenInformation
) + 1);
625 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
626 ((PTOKEN_OWNER
)TokenInformation
)->Owner
,
627 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
628 Status
= STATUS_SUCCESS
;
632 case TokenPrimaryGroup
:
633 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
634 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
635 uLength
= RtlLengthSid(Token
->PrimaryGroup
) + sizeof(TOKEN_PRIMARY_GROUP
);
636 if (TokenInformationLength
< uLength
)
638 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
639 if (NT_SUCCESS(Status
))
640 Status
= STATUS_BUFFER_TOO_SMALL
;
644 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
=
645 (PSID
)(((PTOKEN_PRIMARY_GROUP
)TokenInformation
) + 1);
646 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
647 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
,
648 Token
->PrimaryGroup
);
649 Status
= STATUS_SUCCESS
;
653 case TokenDefaultDacl
:
654 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
655 PtrDefaultDacl
= (PTOKEN_DEFAULT_DACL
) TokenInformation
;
656 uLength
= (Token
->DefaultDacl
? Token
->DefaultDacl
->AclSize
: 0) + sizeof(TOKEN_DEFAULT_DACL
);
657 if (TokenInformationLength
< uLength
)
659 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
660 if (NT_SUCCESS(Status
))
661 Status
= STATUS_BUFFER_TOO_SMALL
;
663 else if (!Token
->DefaultDacl
)
665 PtrDefaultDacl
->DefaultDacl
= 0;
666 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
670 PtrDefaultDacl
->DefaultDacl
= (PACL
) (PtrDefaultDacl
+ 1);
671 memmove(PtrDefaultDacl
->DefaultDacl
,
673 Token
->DefaultDacl
->AclSize
);
674 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
679 DPRINT("NtQueryInformationToken(TokenSource)\n");
680 if (TokenInformationLength
< sizeof(TOKEN_SOURCE
))
682 uLength
= sizeof(TOKEN_SOURCE
);
683 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
684 if (NT_SUCCESS(Status
))
685 Status
= STATUS_BUFFER_TOO_SMALL
;
689 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenSource
, sizeof(TOKEN_SOURCE
));
694 DPRINT("NtQueryInformationToken(TokenType)\n");
695 if (TokenInformationLength
< sizeof(TOKEN_TYPE
))
697 uLength
= sizeof(TOKEN_TYPE
);
698 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
699 if (NT_SUCCESS(Status
))
700 Status
= STATUS_BUFFER_TOO_SMALL
;
704 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenType
, sizeof(TOKEN_TYPE
));
708 case TokenImpersonationLevel
:
709 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
710 if (TokenInformationLength
< sizeof(SECURITY_IMPERSONATION_LEVEL
))
712 uLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
713 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
714 if (NT_SUCCESS(Status
))
715 Status
= STATUS_BUFFER_TOO_SMALL
;
719 Status
= MmCopyToCaller(TokenInformation
, &Token
->ImpersonationLevel
, sizeof(SECURITY_IMPERSONATION_LEVEL
));
723 case TokenStatistics
:
724 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
725 if (TokenInformationLength
< sizeof(TOKEN_STATISTICS
))
727 uLength
= sizeof(TOKEN_STATISTICS
);
728 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
729 if (NT_SUCCESS(Status
))
730 Status
= STATUS_BUFFER_TOO_SMALL
;
734 PtrTokenStatistics
= (PTOKEN_STATISTICS
)TokenInformation
;
735 PtrTokenStatistics
->TokenId
= Token
->TokenId
;
736 PtrTokenStatistics
->AuthenticationId
= Token
->AuthenticationId
;
737 PtrTokenStatistics
->ExpirationTime
= Token
->ExpirationTime
;
738 PtrTokenStatistics
->TokenType
= Token
->TokenType
;
739 PtrTokenStatistics
->ImpersonationLevel
= Token
->ImpersonationLevel
;
740 PtrTokenStatistics
->DynamicCharged
= Token
->DynamicCharged
;
741 PtrTokenStatistics
->DynamicAvailable
= Token
->DynamicAvailable
;
742 PtrTokenStatistics
->GroupCount
= Token
->UserAndGroupCount
- 1;
743 PtrTokenStatistics
->PrivilegeCount
= Token
->PrivilegeCount
;
744 PtrTokenStatistics
->ModifiedId
= Token
->ModifiedId
;
746 Status
= STATUS_SUCCESS
;
751 ObDereferenceObject(Token
);
758 NtSetInformationToken(IN HANDLE TokenHandle
,
759 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
760 OUT PVOID TokenInformation
,
761 IN ULONG TokenInformationLength
)
768 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
769 IN ACCESS_MASK DesiredAccess
,
770 IN POBJECT_ATTRIBUTES ObjectAttributes
,
771 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
772 IN TOKEN_TYPE TokenType
,
773 OUT PHANDLE NewTokenHandle
)
777 PACCESS_TOKEN NewToken
;
779 ULONG ExistingImpersonationLevel
;
781 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
788 ExistingImpersonationLevel
= Token
->ImpersonationLevel
;
789 SepDuplicateToken(Token
,
793 ExistingImpersonationLevel
,
801 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
803 BOOLEAN ResetToDefault
,
804 PSID_AND_ATTRIBUTES Groups
,
806 KPROCESSOR_MODE PreviousMode
,
817 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
818 IN BOOLEAN ResetToDefault
,
819 IN PTOKEN_GROUPS NewState
,
820 IN ULONG BufferLength
,
821 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
822 OUT PULONG ReturnLength
)
831 Status
= ObReferenceObjectByHandle(TokenHandle
,
839 SepAdjustGroups(Token
,
856 NTSTATUS
SepAdjustPrivileges(PACCESS_TOKEN Token
, // 0x8
858 KPROCESSOR_MODE PreviousMode
, // 0x10
859 ULONG PrivilegeCount
, // 0x14
860 PLUID_AND_ATTRIBUTES Privileges
, // 0x18
861 PTOKEN_PRIVILEGES
* PreviousState
, // 0x1C
869 if (Token
->PrivilegeCount
> 0)
871 for (i
=0; i
<Token
->PrivilegeCount
; i
++)
873 if (PreviousMode
!= 0)
875 if (!(Token
->Privileges
[i
]->Attributes
&
876 SE_PRIVILEGE_ENABLED
))
880 if (PreviousState
!= NULL
)
882 memcpy(&PreviousState
[i
],
883 &Token
->Privileges
[i
],
884 sizeof(LUID_AND_ATTRIBUTES
));
886 Token
->Privileges
[i
].Attributes
=
887 Token
->Privileges
[i
].Attributes
&
888 (~SE_PRIVILEGE_ENABLED
);
894 if (PreviousMode
!= 0)
896 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
900 if (PrivilegeCount
<= ?)
911 NtAdjustPrivilegesToken(IN HANDLE TokenHandle
,
912 IN BOOLEAN DisableAllPrivileges
,
913 IN PTOKEN_PRIVILEGES NewState
,
914 IN ULONG BufferLength
,
915 OUT PTOKEN_PRIVILEGES PreviousState
,
916 OUT PULONG ReturnLength
)
919 ULONG PrivilegeCount
;
921 PSID_AND_ATTRIBUTES Privileges
;
926 PrivilegeCount
= NewState
->PrivilegeCount
;
928 SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
937 SepAdjustPrivileges(Token
,
953 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
959 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
960 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
961 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
962 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
964 PACCESS_TOKEN AccessToken
;
969 * Initialize the token
971 Status
= ObCreateObject(NULL
,
975 (PVOID
*)&AccessToken
);
977 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
978 if (!NT_SUCCESS(Status
))
980 ObDereferenceObject(AccessToken
);
984 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
985 if (!NT_SUCCESS(Status
))
987 ObDereferenceObject(AccessToken
);
991 AccessToken
->AuthenticationId
.QuadPart
= SYSTEM_LUID
;
993 AccessToken
->TokenType
= TokenPrimary
;
994 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
995 AccessToken
->TokenSource
.SourceIdentifier
.QuadPart
= 0;
996 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
997 AccessToken
->ExpirationTime
.QuadPart
= -1;
998 AccessToken
->UserAndGroupCount
= 4;
1000 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1001 uSize
+= uLocalSystemLength
;
1002 uSize
+= uWorldLength
;
1003 uSize
+= uAuthUserLength
;
1004 uSize
+= uAdminsLength
;
1006 AccessToken
->UserAndGroups
=
1007 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1009 TAG('T', 'O', 'K', 'u'));
1010 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1013 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1014 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1015 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1016 SidArea
+= uLocalSystemLength
;
1018 AccessToken
->DefaultOwnerIndex
= i
;
1019 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1020 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1021 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1022 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1023 SidArea
+= uAdminsLength
;
1025 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1026 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1027 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1028 SidArea
+= uWorldLength
;
1030 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1031 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1032 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1033 SidArea
+= uAuthUserLength
;
1035 AccessToken
->PrivilegeCount
= 20;
1037 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1038 AccessToken
->Privileges
=
1039 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1041 TAG('T', 'O', 'K', 'p'));
1044 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1045 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1047 AccessToken
->Privileges
[i
].Attributes
= 0;
1048 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1050 AccessToken
->Privileges
[i
].Attributes
= 0;
1051 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1053 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1054 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1056 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1057 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1059 AccessToken
->Privileges
[i
].Attributes
= 0;
1060 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1062 AccessToken
->Privileges
[i
].Attributes
= 0;
1063 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1065 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1066 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1068 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1069 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1071 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1072 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1074 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1075 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1077 AccessToken
->Privileges
[i
].Attributes
= 0;
1078 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1080 AccessToken
->Privileges
[i
].Attributes
= 0;
1081 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1083 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1084 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1086 AccessToken
->Privileges
[i
].Attributes
= 0;
1087 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1089 AccessToken
->Privileges
[i
].Attributes
= 0;
1090 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1092 AccessToken
->Privileges
[i
].Attributes
= 0;
1093 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1095 AccessToken
->Privileges
[i
].Attributes
= 0;
1096 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1098 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1099 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1101 AccessToken
->Privileges
[i
].Attributes
= 0;
1102 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1104 AccessToken
->Privileges
[i
].Attributes
= 0;
1105 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1107 AccessToken
->Privileges
[i
].Attributes
= 0;
1108 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1113 uSize
= sizeof(ACL
);
1114 uSize
+= sizeof(ACE_HEADER
) + uLocalSystemLength
;
1115 uSize
+= sizeof(ACE_HEADER
) + uAdminsLength
;
1116 uSize
= (uSize
& (~3)) + 8;
1117 AccessToken
->DefaultDacl
=
1118 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1120 TAG('T', 'O', 'K', 'd'));
1121 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1122 if ( NT_SUCCESS(Status
) )
1124 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1127 if ( NT_SUCCESS(Status
) )
1129 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1132 if ( ! NT_SUCCESS(Status
) )
1134 ObDereferenceObject(AccessToken
);
1138 Process
->Token
= AccessToken
;
1139 return(STATUS_SUCCESS
);
1143 NtCreateToken(OUT PHANDLE UnsafeTokenHandle
,
1144 IN ACCESS_MASK DesiredAccess
,
1145 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes
,
1146 IN TOKEN_TYPE TokenType
,
1147 IN PLUID AuthenticationId
,
1148 IN PLARGE_INTEGER ExpirationTime
,
1149 IN PTOKEN_USER TokenUser
,
1150 IN PTOKEN_GROUPS TokenGroups
,
1151 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1152 IN PTOKEN_OWNER TokenOwner
,
1153 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1154 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1155 IN PTOKEN_SOURCE TokenSource
)
1158 PACCESS_TOKEN AccessToken
;
1160 OBJECT_ATTRIBUTES SafeObjectAttributes
;
1161 POBJECT_ATTRIBUTES ObjectAttributes
;
1168 Status
= MmCopyFromCaller(&SafeObjectAttributes
,
1169 UnsafeObjectAttributes
,
1170 sizeof(OBJECT_ATTRIBUTES
));
1171 if (!NT_SUCCESS(Status
))
1174 ObjectAttributes
= &SafeObjectAttributes
;
1176 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
1177 if (!NT_SUCCESS(Status
))
1180 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
1181 if (!NT_SUCCESS(Status
))
1184 Status
= ObCreateObject(&TokenHandle
,
1188 (PVOID
*)&AccessToken
);
1189 if (!NT_SUCCESS(Status
))
1191 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1195 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
1196 &TokenSource
->SourceIdentifier
);
1197 memcpy(AccessToken
->TokenSource
.SourceName
,
1198 TokenSource
->SourceName
,
1199 sizeof(TokenSource
->SourceName
));
1201 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
1202 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
1203 AccessToken
->ExpirationTime
= *ExpirationTime
;
1204 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
1206 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
1207 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
1208 AccessToken
->UserAndGroups
= 0;
1209 AccessToken
->Privileges
= 0;
1211 AccessToken
->TokenType
= TokenType
;
1212 AccessToken
->ImpersonationLevel
= ObjectAttributes
->SecurityQualityOfService
->ImpersonationLevel
;
1215 * Normally we would just point these members into the variable information
1216 * area; however, our ObCreateObject() call can't allocate a variable information
1217 * area, so we allocate them seperately and provide a destroy function.
1220 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1221 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
1222 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
1223 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
1225 AccessToken
->UserAndGroups
=
1226 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1228 TAG('T', 'O', 'K', 'u'));
1230 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1232 Status
= RtlCopySidAndAttributesArray(1,
1235 AccessToken
->UserAndGroups
,
1239 if (NT_SUCCESS(Status
))
1241 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
1242 TokenGroups
->Groups
,
1244 &AccessToken
->UserAndGroups
[1],
1250 if (NT_SUCCESS(Status
))
1252 Status
= SepFindPrimaryGroupAndDefaultOwner(
1254 TokenPrimaryGroup
->PrimaryGroup
,
1258 if (NT_SUCCESS(Status
))
1260 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1261 AccessToken
->Privileges
=
1262 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1264 TAG('T', 'O', 'K', 'p'));
1266 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
1268 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
1269 &TokenPrivileges
->Privileges
[i
],
1270 sizeof(LUID_AND_ATTRIBUTES
));
1271 if (!NT_SUCCESS(Status
))
1276 if (NT_SUCCESS(Status
))
1278 AccessToken
->DefaultDacl
=
1279 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1280 TokenDefaultDacl
->DefaultDacl
->AclSize
,
1281 TAG('T', 'O', 'K', 'd'));
1282 memcpy(AccessToken
->DefaultDacl
,
1283 TokenDefaultDacl
->DefaultDacl
,
1284 TokenDefaultDacl
->DefaultDacl
->AclSize
);
1287 ObDereferenceObject(AccessToken
);
1289 if (NT_SUCCESS(Status
))
1291 Status
= MmCopyToCaller(UnsafeTokenHandle
,
1296 if (!NT_SUCCESS(Status
))
1298 ZwClose(TokenHandle
);
1302 return(STATUS_SUCCESS
);
1306 SECURITY_IMPERSONATION_LEVEL STDCALL
1307 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1309 return(Token
->ImpersonationLevel
);
1314 SeTokenType(IN PACCESS_TOKEN Token
)
1316 return(Token
->TokenType
);