1 /* $Id: token.c,v 1.21 2002/09/08 10:23:43 chorns 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
);
73 RtlLengthSidAndAttributes(ULONG Count
,
74 PSID_AND_ATTRIBUTES Src
)
79 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
80 for (i
= 0; i
< Count
; i
++)
81 uLength
+= RtlLengthSid(Src
[i
].Sid
);
88 SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token
,
94 Token
->PrimaryGroup
= 0;
98 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
101 /* Validate and set the primary group and user pointers */
102 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
105 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
107 Token
->DefaultOwnerIndex
= i
;
110 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
112 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
116 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
118 return(STATUS_INVALID_OWNER
);
121 if (Token
->PrimaryGroup
== 0)
123 return(STATUS_INVALID_PRIMARY_GROUP
);
126 return(STATUS_SUCCESS
);
131 SepDuplicateToken(PACCESS_TOKEN Token
,
132 POBJECT_ATTRIBUTES ObjectAttributes
,
133 TOKEN_TYPE TokenType
,
134 SECURITY_IMPERSONATION_LEVEL Level
,
135 SECURITY_IMPERSONATION_LEVEL ExistingLevel
,
136 KPROCESSOR_MODE PreviousMode
,
137 PACCESS_TOKEN
* NewAccessToken
)
145 PACCESS_TOKEN AccessToken
;
147 Status
= ObCreateObject(0,
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 AccessToken
->AuthenticationId
.QuadPart
= SYSTEM_LUID
;
177 AccessToken
->TokenSource
.SourceIdentifier
.QuadPart
= Token
->TokenSource
.SourceIdentifier
.QuadPart
;
178 memcpy(AccessToken
->TokenSource
.SourceName
, Token
->TokenSource
.SourceName
, sizeof(Token
->TokenSource
.SourceName
));
179 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
180 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
181 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
183 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
184 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
185 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
187 AccessToken
->UserAndGroups
=
188 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
190 TAG('T', 'O', 'K', 'u'));
192 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
194 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
195 Token
->UserAndGroups
,
197 AccessToken
->UserAndGroups
,
201 if (NT_SUCCESS(Status
))
203 Status
= SepFindPrimaryGroupAndDefaultOwner(
209 if (NT_SUCCESS(Status
))
211 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
213 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
214 AccessToken
->Privileges
=
215 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
217 TAG('T', 'O', 'K', 'p'));
219 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
221 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
222 &Token
->Privileges
[i
].Luid
);
223 AccessToken
->Privileges
[i
].Attributes
=
224 Token
->Privileges
[i
].Attributes
;
227 if ( Token
->DefaultDacl
)
229 AccessToken
->DefaultDacl
=
230 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
231 Token
->DefaultDacl
->AclSize
,
232 TAG('T', 'O', 'K', 'd'));
233 memcpy(AccessToken
->DefaultDacl
,
235 Token
->DefaultDacl
->AclSize
);
239 AccessToken
->DefaultDacl
= 0;
243 if ( NT_SUCCESS(Status
) )
245 *NewAccessToken
= AccessToken
;
246 return(STATUS_SUCCESS
);
249 ObDereferenceObject(AccessToken
);
255 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
256 struct _EPROCESS
* ParentProcess
)
259 PACCESS_TOKEN pNewToken
;
260 PACCESS_TOKEN pParentToken
;
262 OBJECT_ATTRIBUTES ObjectAttributes
;
264 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
266 InitializeObjectAttributes(&ObjectAttributes
,
272 Status
= SepDuplicateToken(pParentToken
,
275 pParentToken
->ImpersonationLevel
,
276 pParentToken
->ImpersonationLevel
,
279 if ( ! NT_SUCCESS(Status
) )
282 NewProcess
->Token
= pNewToken
;
283 return(STATUS_SUCCESS
);
287 NTSTATUS
SeCopyClientToken(PACCESS_TOKEN Token
,
288 SECURITY_IMPERSONATION_LEVEL Level
,
289 KPROCESSOR_MODE PreviousMode
,
290 PACCESS_TOKEN
* NewToken
)
293 OBJECT_ATTRIBUTES ObjectAttributes
;
295 InitializeObjectAttributes(&ObjectAttributes
,
300 Status
= SepDuplicateToken(Token
,
303 SecurityIdentification
,
312 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
313 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
314 IN BOOLEAN RemoteClient
,
315 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
317 TOKEN_TYPE TokenType
;
319 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
322 PACCESS_TOKEN NewToken
;
324 Token
= PsReferenceEffectiveToken(Thread
,
327 &ImpersonationLevel
);
330 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
334 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
338 ObDereferenceObject(Token
);
340 return(STATUS_UNSUCCESSFUL
);
342 if (ImpersonationLevel
== 0 ||
343 ImpersonationLevel
== 1 ||
344 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= 3))
348 ObDereferenceObject(Token
);
350 return(STATUS_UNSUCCESSFUL
);
353 Qos
->EffectiveOnly
!= 0)
355 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
359 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
363 if (Qos
->ContextTrackingMode
== 0)
365 ClientContext
->DirectlyAccessClientToken
= FALSE
;
366 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
369 // ObDeleteCapturedInsertInfo(NewToken);
371 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
373 ObDereferenceObject(Token
);
382 ClientContext
->DirectlyAccessClientToken
= TRUE
;
383 if (RemoteClient
!= FALSE
)
385 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
389 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
390 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
391 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
392 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
393 ClientContext
->ServerIsRemote
= RemoteClient
;
394 ClientContext
->Token
= NewToken
;
396 return(STATUS_SUCCESS
);
401 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
402 IN PETHREAD ServerThread OPTIONAL
)
406 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
408 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
412 b
= ClientContext
->DirectAccessEffectiveOnly
;
414 if (ServerThread
== NULL
)
416 ServerThread
= PsGetCurrentThread();
418 PsImpersonateClient(ServerThread
,
419 ClientContext
->Token
,
422 ClientContext
->SecurityQos
.ImpersonationLevel
);
427 SepDeleteToken(PVOID ObjectBody
)
429 PACCESS_TOKEN AccessToken
= (PACCESS_TOKEN
)ObjectBody
;
431 if (AccessToken
->UserAndGroups
)
432 ExFreePool(AccessToken
->UserAndGroups
);
434 if (AccessToken
->Privileges
)
435 ExFreePool(AccessToken
->Privileges
);
437 if (AccessToken
->DefaultDacl
)
438 ExFreePool(AccessToken
->DefaultDacl
);
443 SepInitializeTokenImplementation(VOID
)
445 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
447 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
448 SepTokenObjectType
->MaxObjects
= ULONG_MAX
;
449 SepTokenObjectType
->MaxHandles
= ULONG_MAX
;
450 SepTokenObjectType
->TotalObjects
= 0;
451 SepTokenObjectType
->TotalHandles
= 0;
452 SepTokenObjectType
->PagedPoolCharge
= 0;
453 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(ACCESS_TOKEN
);
454 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
455 SepTokenObjectType
->Dump
= NULL
;
456 SepTokenObjectType
->Open
= NULL
;
457 SepTokenObjectType
->Close
= NULL
;
458 SepTokenObjectType
->Delete
= SepDeleteToken
;
459 SepTokenObjectType
->Parse
= NULL
;
460 SepTokenObjectType
->Security
= NULL
;
461 SepTokenObjectType
->QueryName
= NULL
;
462 SepTokenObjectType
->OkayToClose
= NULL
;
463 SepTokenObjectType
->Create
= NULL
;
464 SepTokenObjectType
->DuplicationNotify
= NULL
;
466 RtlCreateUnicodeString(&SepTokenObjectType
->TypeName
,
472 NtQueryInformationToken(IN HANDLE TokenHandle
,
473 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
474 OUT PVOID TokenInformation
,
475 IN ULONG TokenInformationLength
,
476 OUT PULONG ReturnLength
)
482 PTOKEN_GROUPS PtrTokenGroups
;
483 PTOKEN_DEFAULT_DACL PtrDefaultDacl
;
484 PTOKEN_STATISTICS PtrTokenStatistics
;
487 Status
= ObReferenceObjectByHandle(TokenHandle
,
488 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
493 if (!NT_SUCCESS(Status
))
498 switch (TokenInformationClass
)
501 DPRINT("NtQueryInformationToken(TokenUser)\n");
502 uLength
= RtlLengthSidAndAttributes(1, Token
->UserAndGroups
);
503 if (TokenInformationLength
< uLength
)
505 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
506 if (NT_SUCCESS(Status
))
507 Status
= STATUS_BUFFER_TOO_SMALL
;
511 Status
= RtlCopySidAndAttributesArray(1,
512 Token
->UserAndGroups
,
513 TokenInformationLength
,
515 TokenInformation
+ 8,
518 if (NT_SUCCESS(Status
))
520 uLength
= TokenInformationLength
- uLength
;
521 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
527 DPRINT("NtQueryInformationToken(TokenGroups)\n");
528 uLength
= RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]) + sizeof(DWORD
);
529 if (TokenInformationLength
< uLength
)
531 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
532 if (NT_SUCCESS(Status
))
533 Status
= STATUS_BUFFER_TOO_SMALL
;
537 EndMem
= TokenInformation
+ Token
->UserAndGroupCount
* sizeof(SID_AND_ATTRIBUTES
);
538 PtrTokenGroups
= (PTOKEN_GROUPS
)TokenInformation
;
539 PtrTokenGroups
->GroupCount
= Token
->UserAndGroupCount
- 1;
540 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
541 &Token
->UserAndGroups
[1],
542 TokenInformationLength
,
543 PtrTokenGroups
->Groups
,
547 if (NT_SUCCESS(Status
))
549 uLength
= TokenInformationLength
- uLength
;
550 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
555 case TokenPrivileges
:
556 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
557 uLength
= sizeof(DWORD
) + Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
558 if (TokenInformationLength
< uLength
)
560 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
561 if (NT_SUCCESS(Status
))
562 Status
= STATUS_BUFFER_TOO_SMALL
;
567 TOKEN_PRIVILEGES
* pPriv
= (TOKEN_PRIVILEGES
*)TokenInformation
;
569 pPriv
->PrivilegeCount
= Token
->PrivilegeCount
;
570 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
572 RtlCopyLuid(&pPriv
->Privileges
[i
].Luid
, &Token
->Privileges
[i
].Luid
);
573 pPriv
->Privileges
[i
].Attributes
= Token
->Privileges
[i
].Attributes
;
575 Status
= STATUS_SUCCESS
;
580 DPRINT("NtQueryInformationToken(TokenOwner)\n");
581 uLength
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
) + sizeof(TOKEN_OWNER
);
582 if (TokenInformationLength
< uLength
)
584 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
585 if (NT_SUCCESS(Status
))
586 Status
= STATUS_BUFFER_TOO_SMALL
;
590 ((PTOKEN_OWNER
)TokenInformation
)->Owner
=
591 (PSID
)(((PTOKEN_OWNER
)TokenInformation
) + 1);
592 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
593 ((PTOKEN_OWNER
)TokenInformation
)->Owner
,
594 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
595 Status
= STATUS_SUCCESS
;
599 case TokenPrimaryGroup
:
600 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
601 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
602 uLength
= RtlLengthSid(Token
->PrimaryGroup
) + sizeof(TOKEN_PRIMARY_GROUP
);
603 if (TokenInformationLength
< uLength
)
605 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
606 if (NT_SUCCESS(Status
))
607 Status
= STATUS_BUFFER_TOO_SMALL
;
611 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
=
612 (PSID
)(((PTOKEN_PRIMARY_GROUP
)TokenInformation
) + 1);
613 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
614 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
,
615 Token
->PrimaryGroup
);
616 Status
= STATUS_SUCCESS
;
620 case TokenDefaultDacl
:
621 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
622 PtrDefaultDacl
= (PTOKEN_DEFAULT_DACL
) TokenInformation
;
623 uLength
= (Token
->DefaultDacl
? Token
->DefaultDacl
->AclSize
: 0) + sizeof(TOKEN_DEFAULT_DACL
);
624 if (TokenInformationLength
< uLength
)
626 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
627 if (NT_SUCCESS(Status
))
628 Status
= STATUS_BUFFER_TOO_SMALL
;
630 else if (!Token
->DefaultDacl
)
632 PtrDefaultDacl
->DefaultDacl
= 0;
633 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
637 PtrDefaultDacl
->DefaultDacl
= (PACL
) (PtrDefaultDacl
+ 1);
638 memmove(PtrDefaultDacl
->DefaultDacl
,
640 Token
->DefaultDacl
->AclSize
);
641 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
646 DPRINT("NtQueryInformationToken(TokenSource)\n");
647 if (TokenInformationLength
< sizeof(TOKEN_SOURCE
))
649 uLength
= sizeof(TOKEN_SOURCE
);
650 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
651 if (NT_SUCCESS(Status
))
652 Status
= STATUS_BUFFER_TOO_SMALL
;
656 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenSource
, sizeof(TOKEN_SOURCE
));
661 DPRINT("NtQueryInformationToken(TokenType)\n");
662 if (TokenInformationLength
< sizeof(TOKEN_TYPE
))
664 uLength
= sizeof(TOKEN_TYPE
);
665 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
666 if (NT_SUCCESS(Status
))
667 Status
= STATUS_BUFFER_TOO_SMALL
;
671 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenType
, sizeof(TOKEN_TYPE
));
675 case TokenImpersonationLevel
:
676 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
677 if (TokenInformationLength
< sizeof(SECURITY_IMPERSONATION_LEVEL
))
679 uLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
680 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
681 if (NT_SUCCESS(Status
))
682 Status
= STATUS_BUFFER_TOO_SMALL
;
686 Status
= MmCopyToCaller(TokenInformation
, &Token
->ImpersonationLevel
, sizeof(SECURITY_IMPERSONATION_LEVEL
));
690 case TokenStatistics
:
691 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
692 if (TokenInformationLength
< sizeof(TOKEN_STATISTICS
))
694 uLength
= sizeof(TOKEN_STATISTICS
);
695 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
696 if (NT_SUCCESS(Status
))
697 Status
= STATUS_BUFFER_TOO_SMALL
;
701 PtrTokenStatistics
= (PTOKEN_STATISTICS
)TokenInformation
;
702 PtrTokenStatistics
->TokenId
= Token
->TokenId
;
703 PtrTokenStatistics
->AuthenticationId
= Token
->AuthenticationId
;
704 PtrTokenStatistics
->ExpirationTime
= Token
->ExpirationTime
;
705 PtrTokenStatistics
->TokenType
= Token
->TokenType
;
706 PtrTokenStatistics
->ImpersonationLevel
= Token
->ImpersonationLevel
;
707 PtrTokenStatistics
->DynamicCharged
= Token
->DynamicCharged
;
708 PtrTokenStatistics
->DynamicAvailable
= Token
->DynamicAvailable
;
709 PtrTokenStatistics
->GroupCount
= Token
->UserAndGroupCount
- 1;
710 PtrTokenStatistics
->PrivilegeCount
= Token
->PrivilegeCount
;
711 PtrTokenStatistics
->ModifiedId
= Token
->ModifiedId
;
713 Status
= STATUS_SUCCESS
;
718 ObDereferenceObject(Token
);
725 NtSetInformationToken(IN HANDLE TokenHandle
,
726 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
727 OUT PVOID TokenInformation
,
728 IN ULONG TokenInformationLength
)
735 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
736 IN ACCESS_MASK DesiredAccess
,
737 IN POBJECT_ATTRIBUTES ObjectAttributes
,
738 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
739 IN TOKEN_TYPE TokenType
,
740 OUT PHANDLE NewTokenHandle
)
744 PACCESS_TOKEN NewToken
;
746 ULONG ExistingImpersonationLevel
;
748 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
755 ExistingImpersonationLevel
= Token
->ImpersonationLevel
;
756 SepDuplicateToken(Token
,
760 ExistingImpersonationLevel
,
768 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
770 BOOLEAN ResetToDefault
,
771 PSID_AND_ATTRIBUTES Groups
,
773 KPROCESSOR_MODE PreviousMode
,
784 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
785 IN BOOLEAN ResetToDefault
,
786 IN PTOKEN_GROUPS NewState
,
787 IN ULONG BufferLength
,
788 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
789 OUT PULONG ReturnLength
)
798 Status
= ObReferenceObjectByHandle(TokenHandle
,
806 SepAdjustGroups(Token
,
823 NTSTATUS
SepAdjustPrivileges(PACCESS_TOKEN Token
, // 0x8
825 KPROCESSOR_MODE PreviousMode
, // 0x10
826 ULONG PrivilegeCount
, // 0x14
827 PLUID_AND_ATTRIBUTES Privileges
, // 0x18
828 PTOKEN_PRIVILEGES
* PreviousState
, // 0x1C
836 if (Token
->PrivilegeCount
> 0)
838 for (i
=0; i
<Token
->PrivilegeCount
; i
++)
840 if (PreviousMode
!= 0)
842 if (!(Token
->Privileges
[i
]->Attributes
&
843 SE_PRIVILEGE_ENABLED
))
847 if (PreviousState
!= NULL
)
849 memcpy(&PreviousState
[i
],
850 &Token
->Privileges
[i
],
851 sizeof(LUID_AND_ATTRIBUTES
));
853 Token
->Privileges
[i
].Attributes
=
854 Token
->Privileges
[i
].Attributes
&
855 (~SE_PRIVILEGE_ENABLED
);
861 if (PreviousMode
!= 0)
863 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
867 if (PrivilegeCount
<= ?)
878 NtAdjustPrivilegesToken(IN HANDLE TokenHandle
,
879 IN BOOLEAN DisableAllPrivileges
,
880 IN PTOKEN_PRIVILEGES NewState
,
881 IN ULONG BufferLength
,
882 OUT PTOKEN_PRIVILEGES PreviousState
,
883 OUT PULONG ReturnLength
)
886 ULONG PrivilegeCount
;
888 PSID_AND_ATTRIBUTES Privileges
;
893 PrivilegeCount
= NewState
->PrivilegeCount
;
895 SeCaptureLuidAndAttributesArray(NewState
->Privileges
,
904 SepAdjustPrivileges(Token
,
920 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
926 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
927 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
928 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
929 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
931 PACCESS_TOKEN AccessToken
;
936 * Initialize the token
938 Status
= ObCreateObject(NULL
,
942 (PVOID
*)&AccessToken
);
944 Status
= NtAllocateLocallyUniqueId(&AccessToken
->TokenId
);
945 if (!NT_SUCCESS(Status
))
947 ObDereferenceObject(AccessToken
);
951 Status
= NtAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
952 if (!NT_SUCCESS(Status
))
954 ObDereferenceObject(AccessToken
);
958 AccessToken
->AuthenticationId
.QuadPart
= SYSTEM_LUID
;
960 AccessToken
->TokenType
= TokenPrimary
;
961 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
962 AccessToken
->TokenSource
.SourceIdentifier
.QuadPart
= 0;
963 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
964 AccessToken
->ExpirationTime
.QuadPart
= -1;
965 AccessToken
->UserAndGroupCount
= 4;
967 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
968 uSize
+= uLocalSystemLength
;
969 uSize
+= uWorldLength
;
970 uSize
+= uAuthUserLength
;
971 uSize
+= uAdminsLength
;
973 AccessToken
->UserAndGroups
=
974 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
976 TAG('T', 'O', 'K', 'u'));
977 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
980 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
981 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
982 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
983 SidArea
+= uLocalSystemLength
;
985 AccessToken
->DefaultOwnerIndex
= i
;
986 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
987 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
988 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
989 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
990 SidArea
+= uAdminsLength
;
992 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
993 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
994 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
995 SidArea
+= uWorldLength
;
997 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
998 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
999 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1000 SidArea
+= uAuthUserLength
;
1002 AccessToken
->PrivilegeCount
= 20;
1004 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1005 AccessToken
->Privileges
=
1006 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1008 TAG('T', 'O', 'K', 'p'));
1011 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1012 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1014 AccessToken
->Privileges
[i
].Attributes
= 0;
1015 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1017 AccessToken
->Privileges
[i
].Attributes
= 0;
1018 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1020 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1021 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1023 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1024 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1026 AccessToken
->Privileges
[i
].Attributes
= 0;
1027 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1029 AccessToken
->Privileges
[i
].Attributes
= 0;
1030 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1032 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1033 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1035 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1036 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1038 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1039 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1041 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1042 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1044 AccessToken
->Privileges
[i
].Attributes
= 0;
1045 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1047 AccessToken
->Privileges
[i
].Attributes
= 0;
1048 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1050 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1051 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1053 AccessToken
->Privileges
[i
].Attributes
= 0;
1054 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1056 AccessToken
->Privileges
[i
].Attributes
= 0;
1057 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1059 AccessToken
->Privileges
[i
].Attributes
= 0;
1060 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1062 AccessToken
->Privileges
[i
].Attributes
= 0;
1063 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1065 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1066 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1068 AccessToken
->Privileges
[i
].Attributes
= 0;
1069 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1071 AccessToken
->Privileges
[i
].Attributes
= 0;
1072 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1074 AccessToken
->Privileges
[i
].Attributes
= 0;
1075 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1080 uSize
= sizeof(ACL
);
1081 uSize
+= sizeof(ACE_HEADER
) + uLocalSystemLength
;
1082 uSize
+= sizeof(ACE_HEADER
) + uAdminsLength
;
1083 uSize
= (uSize
& (~3)) + 8;
1084 AccessToken
->DefaultDacl
=
1085 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1087 TAG('T', 'O', 'K', 'd'));
1088 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1089 if ( NT_SUCCESS(Status
) )
1091 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1094 if ( NT_SUCCESS(Status
) )
1096 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1099 if ( ! NT_SUCCESS(Status
) )
1101 ObDereferenceObject(AccessToken
);
1105 Process
->Token
= AccessToken
;
1106 return(STATUS_SUCCESS
);
1110 NtCreateToken(OUT PHANDLE UnsafeTokenHandle
,
1111 IN ACCESS_MASK DesiredAccess
,
1112 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes
,
1113 IN TOKEN_TYPE TokenType
,
1114 IN PLUID AuthenticationId
,
1115 IN PLARGE_INTEGER ExpirationTime
,
1116 IN PTOKEN_USER TokenUser
,
1117 IN PTOKEN_GROUPS TokenGroups
,
1118 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1119 IN PTOKEN_OWNER TokenOwner
,
1120 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1121 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1122 IN PTOKEN_SOURCE TokenSource
)
1125 PACCESS_TOKEN AccessToken
;
1127 OBJECT_ATTRIBUTES SafeObjectAttributes
;
1128 POBJECT_ATTRIBUTES ObjectAttributes
;
1135 Status
= MmCopyFromCaller(&SafeObjectAttributes
,
1136 UnsafeObjectAttributes
,
1137 sizeof(OBJECT_ATTRIBUTES
));
1138 if (!NT_SUCCESS(Status
))
1141 ObjectAttributes
= &SafeObjectAttributes
;
1143 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
1144 if (!NT_SUCCESS(Status
))
1147 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
1148 if (!NT_SUCCESS(Status
))
1151 Status
= ObCreateObject(&TokenHandle
,
1155 (PVOID
*)&AccessToken
);
1156 if (!NT_SUCCESS(Status
))
1158 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1162 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
1163 &TokenSource
->SourceIdentifier
);
1164 memcpy(AccessToken
->TokenSource
.SourceName
,
1165 TokenSource
->SourceName
,
1166 sizeof(TokenSource
->SourceName
));
1168 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
1169 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
1170 AccessToken
->ExpirationTime
= *ExpirationTime
;
1171 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
1173 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
1174 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
1175 AccessToken
->UserAndGroups
= 0;
1176 AccessToken
->Privileges
= 0;
1178 AccessToken
->TokenType
= TokenType
;
1179 AccessToken
->ImpersonationLevel
= ObjectAttributes
->SecurityQualityOfService
->ImpersonationLevel
;
1182 * Normally we would just point these members into the variable information
1183 * area; however, our ObCreateObject() call can't allocate a variable information
1184 * area, so we allocate them seperately and provide a destroy function.
1187 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1188 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
1189 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
1190 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
1192 AccessToken
->UserAndGroups
=
1193 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1195 TAG('T', 'O', 'K', 'u'));
1197 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1199 Status
= RtlCopySidAndAttributesArray(1,
1202 AccessToken
->UserAndGroups
,
1206 if (NT_SUCCESS(Status
))
1208 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
1209 TokenGroups
->Groups
,
1211 &AccessToken
->UserAndGroups
[1],
1217 if (NT_SUCCESS(Status
))
1219 Status
= SepFindPrimaryGroupAndDefaultOwner(
1221 TokenPrimaryGroup
->PrimaryGroup
,
1225 if (NT_SUCCESS(Status
))
1227 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1228 AccessToken
->Privileges
=
1229 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1231 TAG('T', 'O', 'K', 'p'));
1233 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
1235 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
1236 &TokenPrivileges
->Privileges
[i
],
1237 sizeof(LUID_AND_ATTRIBUTES
));
1238 if (!NT_SUCCESS(Status
))
1243 if (NT_SUCCESS(Status
))
1245 AccessToken
->DefaultDacl
=
1246 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1247 TokenDefaultDacl
->DefaultDacl
->AclSize
,
1248 TAG('T', 'O', 'K', 'd'));
1249 memcpy(AccessToken
->DefaultDacl
,
1250 TokenDefaultDacl
->DefaultDacl
,
1251 TokenDefaultDacl
->DefaultDacl
->AclSize
);
1254 ObDereferenceObject(AccessToken
);
1256 if (NT_SUCCESS(Status
))
1258 Status
= MmCopyToCaller(UnsafeTokenHandle
,
1263 if (!NT_SUCCESS(Status
))
1265 ZwClose(TokenHandle
);
1269 return(STATUS_SUCCESS
);
1273 SECURITY_IMPERSONATION_LEVEL STDCALL
1274 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1276 return(Token
->ImpersonationLevel
);
1281 SeTokenType(IN PACCESS_TOKEN Token
)
1283 return(Token
->TokenType
);