1 /* $Id: token.c,v 1.30 2003/12/14 17:44:02 hbirr 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 #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 TOKEN_TYPE TokenType
,
137 SECURITY_IMPERSONATION_LEVEL Level
,
138 SECURITY_IMPERSONATION_LEVEL ExistingLevel
,
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 AccessToken
->AuthenticationId
.LowPart
= SYSTEM_LUID
;
183 AccessToken
->AuthenticationId
.HighPart
= 0;
185 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
186 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
187 memcpy(AccessToken
->TokenSource
.SourceName
,
188 Token
->TokenSource
.SourceName
,
189 sizeof(Token
->TokenSource
.SourceName
));
190 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
191 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
192 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
194 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
195 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
196 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
198 AccessToken
->UserAndGroups
=
199 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
201 TAG('T', 'O', 'K', 'u'));
203 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
205 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
206 Token
->UserAndGroups
,
208 AccessToken
->UserAndGroups
,
212 if (NT_SUCCESS(Status
))
214 Status
= SepFindPrimaryGroupAndDefaultOwner(
220 if (NT_SUCCESS(Status
))
222 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
224 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
225 AccessToken
->Privileges
=
226 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
228 TAG('T', 'O', 'K', 'p'));
230 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
232 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
233 &Token
->Privileges
[i
].Luid
);
234 AccessToken
->Privileges
[i
].Attributes
=
235 Token
->Privileges
[i
].Attributes
;
238 if ( Token
->DefaultDacl
)
240 AccessToken
->DefaultDacl
=
241 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
242 Token
->DefaultDacl
->AclSize
,
243 TAG('T', 'O', 'K', 'd'));
244 memcpy(AccessToken
->DefaultDacl
,
246 Token
->DefaultDacl
->AclSize
);
250 AccessToken
->DefaultDacl
= 0;
254 if ( NT_SUCCESS(Status
) )
256 *NewAccessToken
= AccessToken
;
257 return(STATUS_SUCCESS
);
260 ObDereferenceObject(AccessToken
);
266 SepInitializeNewProcess(struct _EPROCESS
* NewProcess
,
267 struct _EPROCESS
* ParentProcess
)
270 PACCESS_TOKEN pNewToken
;
271 PACCESS_TOKEN pParentToken
;
273 OBJECT_ATTRIBUTES ObjectAttributes
;
275 pParentToken
= (PACCESS_TOKEN
) ParentProcess
->Token
;
277 InitializeObjectAttributes(&ObjectAttributes
,
283 Status
= SepDuplicateToken(pParentToken
,
286 pParentToken
->ImpersonationLevel
,
287 pParentToken
->ImpersonationLevel
,
290 if ( ! NT_SUCCESS(Status
) )
293 NewProcess
->Token
= pNewToken
;
294 return(STATUS_SUCCESS
);
298 NTSTATUS
SeCopyClientToken(PACCESS_TOKEN Token
,
299 SECURITY_IMPERSONATION_LEVEL Level
,
300 KPROCESSOR_MODE PreviousMode
,
301 PACCESS_TOKEN
* NewToken
)
304 OBJECT_ATTRIBUTES ObjectAttributes
;
306 InitializeObjectAttributes(&ObjectAttributes
,
311 Status
= SepDuplicateToken(Token
,
314 SecurityIdentification
,
326 SeCreateClientSecurity(IN
struct _ETHREAD
*Thread
,
327 IN PSECURITY_QUALITY_OF_SERVICE Qos
,
328 IN BOOLEAN RemoteClient
,
329 OUT PSECURITY_CLIENT_CONTEXT ClientContext
)
331 TOKEN_TYPE TokenType
;
333 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
336 PACCESS_TOKEN NewToken
;
338 Token
= PsReferenceEffectiveToken(Thread
,
341 &ImpersonationLevel
);
344 ClientContext
->DirectAccessEffectiveOnly
= Qos
->EffectiveOnly
;
348 if (Qos
->ImpersonationLevel
> ImpersonationLevel
)
352 ObDereferenceObject(Token
);
354 return(STATUS_UNSUCCESSFUL
);
356 if (ImpersonationLevel
== 0 ||
357 ImpersonationLevel
== 1 ||
358 (RemoteClient
!= FALSE
&& ImpersonationLevel
!= 3))
362 ObDereferenceObject(Token
);
364 return(STATUS_UNSUCCESSFUL
);
367 Qos
->EffectiveOnly
!= 0)
369 ClientContext
->DirectAccessEffectiveOnly
= TRUE
;
373 ClientContext
->DirectAccessEffectiveOnly
= FALSE
;
377 if (Qos
->ContextTrackingMode
== 0)
379 ClientContext
->DirectlyAccessClientToken
= FALSE
;
380 g
= SeCopyClientToken(Token
, ImpersonationLevel
, 0, &NewToken
);
383 // ObDeleteCapturedInsertInfo(NewToken);
385 if (TokenType
== TokenPrimary
|| Token
!= NULL
)
387 ObDereferenceObject(Token
);
396 ClientContext
->DirectlyAccessClientToken
= TRUE
;
397 if (RemoteClient
!= FALSE
)
399 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
403 ClientContext
->SecurityQos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
404 ClientContext
->SecurityQos
.ImpersonationLevel
= Qos
->ImpersonationLevel
;
405 ClientContext
->SecurityQos
.ContextTrackingMode
= Qos
->ContextTrackingMode
;
406 ClientContext
->SecurityQos
.EffectiveOnly
= Qos
->EffectiveOnly
;
407 ClientContext
->ServerIsRemote
= RemoteClient
;
408 ClientContext
->Token
= NewToken
;
410 return(STATUS_SUCCESS
);
418 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext
,
419 IN PETHREAD ServerThread OPTIONAL
)
423 if (ClientContext
->DirectlyAccessClientToken
== FALSE
)
425 b
= ClientContext
->SecurityQos
.EffectiveOnly
;
429 b
= ClientContext
->DirectAccessEffectiveOnly
;
431 if (ServerThread
== NULL
)
433 ServerThread
= PsGetCurrentThread();
435 PsImpersonateClient(ServerThread
,
436 ClientContext
->Token
,
439 ClientContext
->SecurityQos
.ImpersonationLevel
);
444 SepDeleteToken(PVOID ObjectBody
)
446 PACCESS_TOKEN AccessToken
= (PACCESS_TOKEN
)ObjectBody
;
448 if (AccessToken
->UserAndGroups
)
449 ExFreePool(AccessToken
->UserAndGroups
);
451 if (AccessToken
->Privileges
)
452 ExFreePool(AccessToken
->Privileges
);
454 if (AccessToken
->DefaultDacl
)
455 ExFreePool(AccessToken
->DefaultDacl
);
460 SepInitializeTokenImplementation(VOID
)
462 SepTokenObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
464 SepTokenObjectType
->Tag
= TAG('T', 'O', 'K', 'T');
465 SepTokenObjectType
->MaxObjects
= ULONG_MAX
;
466 SepTokenObjectType
->MaxHandles
= ULONG_MAX
;
467 SepTokenObjectType
->TotalObjects
= 0;
468 SepTokenObjectType
->TotalHandles
= 0;
469 SepTokenObjectType
->PagedPoolCharge
= 0;
470 SepTokenObjectType
->NonpagedPoolCharge
= sizeof(ACCESS_TOKEN
);
471 SepTokenObjectType
->Mapping
= &SepTokenMapping
;
472 SepTokenObjectType
->Dump
= NULL
;
473 SepTokenObjectType
->Open
= NULL
;
474 SepTokenObjectType
->Close
= NULL
;
475 SepTokenObjectType
->Delete
= SepDeleteToken
;
476 SepTokenObjectType
->Parse
= NULL
;
477 SepTokenObjectType
->Security
= NULL
;
478 SepTokenObjectType
->QueryName
= NULL
;
479 SepTokenObjectType
->OkayToClose
= NULL
;
480 SepTokenObjectType
->Create
= NULL
;
481 SepTokenObjectType
->DuplicationNotify
= NULL
;
483 RtlCreateUnicodeString(&SepTokenObjectType
->TypeName
,
485 ObpCreateTypeObject (SepTokenObjectType
);
493 NtQueryInformationToken(IN HANDLE TokenHandle
,
494 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
495 OUT PVOID TokenInformation
,
496 IN ULONG TokenInformationLength
,
497 OUT PULONG ReturnLength
)
503 PTOKEN_GROUPS PtrTokenGroups
;
504 PTOKEN_DEFAULT_DACL PtrDefaultDacl
;
505 PTOKEN_STATISTICS PtrTokenStatistics
;
508 Status
= ObReferenceObjectByHandle(TokenHandle
,
509 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
514 if (!NT_SUCCESS(Status
))
519 switch (TokenInformationClass
)
522 DPRINT("NtQueryInformationToken(TokenUser)\n");
523 uLength
= RtlLengthSidAndAttributes(1, Token
->UserAndGroups
);
524 if (TokenInformationLength
< uLength
)
526 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
527 if (NT_SUCCESS(Status
))
528 Status
= STATUS_BUFFER_TOO_SMALL
;
532 Status
= RtlCopySidAndAttributesArray(1,
533 Token
->UserAndGroups
,
534 TokenInformationLength
,
536 TokenInformation
+ 8,
539 if (NT_SUCCESS(Status
))
541 uLength
= TokenInformationLength
- uLength
;
542 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
548 DPRINT("NtQueryInformationToken(TokenGroups)\n");
549 uLength
= RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]) + sizeof(DWORD
);
550 if (TokenInformationLength
< uLength
)
552 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
553 if (NT_SUCCESS(Status
))
554 Status
= STATUS_BUFFER_TOO_SMALL
;
558 EndMem
= TokenInformation
+ Token
->UserAndGroupCount
* sizeof(SID_AND_ATTRIBUTES
);
559 PtrTokenGroups
= (PTOKEN_GROUPS
)TokenInformation
;
560 PtrTokenGroups
->GroupCount
= Token
->UserAndGroupCount
- 1;
561 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
562 &Token
->UserAndGroups
[1],
563 TokenInformationLength
,
564 PtrTokenGroups
->Groups
,
568 if (NT_SUCCESS(Status
))
570 uLength
= TokenInformationLength
- uLength
;
571 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
576 case TokenPrivileges
:
577 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
578 uLength
= sizeof(DWORD
) + Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
579 if (TokenInformationLength
< uLength
)
581 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
582 if (NT_SUCCESS(Status
))
583 Status
= STATUS_BUFFER_TOO_SMALL
;
588 TOKEN_PRIVILEGES
* pPriv
= (TOKEN_PRIVILEGES
*)TokenInformation
;
590 pPriv
->PrivilegeCount
= Token
->PrivilegeCount
;
591 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
593 RtlCopyLuid(&pPriv
->Privileges
[i
].Luid
, &Token
->Privileges
[i
].Luid
);
594 pPriv
->Privileges
[i
].Attributes
= Token
->Privileges
[i
].Attributes
;
596 Status
= STATUS_SUCCESS
;
601 DPRINT("NtQueryInformationToken(TokenOwner)\n");
602 uLength
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
) + sizeof(TOKEN_OWNER
);
603 if (TokenInformationLength
< uLength
)
605 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
606 if (NT_SUCCESS(Status
))
607 Status
= STATUS_BUFFER_TOO_SMALL
;
611 ((PTOKEN_OWNER
)TokenInformation
)->Owner
=
612 (PSID
)(((PTOKEN_OWNER
)TokenInformation
) + 1);
613 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_OWNER
),
614 ((PTOKEN_OWNER
)TokenInformation
)->Owner
,
615 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
616 Status
= STATUS_SUCCESS
;
620 case TokenPrimaryGroup
:
621 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
622 "Token->PrimaryGroup = 0x%08x\n", Token
->PrimaryGroup
);
623 uLength
= RtlLengthSid(Token
->PrimaryGroup
) + sizeof(TOKEN_PRIMARY_GROUP
);
624 if (TokenInformationLength
< uLength
)
626 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
627 if (NT_SUCCESS(Status
))
628 Status
= STATUS_BUFFER_TOO_SMALL
;
632 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
=
633 (PSID
)(((PTOKEN_PRIMARY_GROUP
)TokenInformation
) + 1);
634 RtlCopySid(TokenInformationLength
- sizeof(TOKEN_PRIMARY_GROUP
),
635 ((PTOKEN_PRIMARY_GROUP
)TokenInformation
)->PrimaryGroup
,
636 Token
->PrimaryGroup
);
637 Status
= STATUS_SUCCESS
;
641 case TokenDefaultDacl
:
642 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
643 PtrDefaultDacl
= (PTOKEN_DEFAULT_DACL
) TokenInformation
;
644 uLength
= (Token
->DefaultDacl
? Token
->DefaultDacl
->AclSize
: 0) + sizeof(TOKEN_DEFAULT_DACL
);
645 if (TokenInformationLength
< uLength
)
647 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
648 if (NT_SUCCESS(Status
))
649 Status
= STATUS_BUFFER_TOO_SMALL
;
651 else if (!Token
->DefaultDacl
)
653 PtrDefaultDacl
->DefaultDacl
= 0;
654 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
658 PtrDefaultDacl
->DefaultDacl
= (PACL
) (PtrDefaultDacl
+ 1);
659 memmove(PtrDefaultDacl
->DefaultDacl
,
661 Token
->DefaultDacl
->AclSize
);
662 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
667 DPRINT("NtQueryInformationToken(TokenSource)\n");
668 if (TokenInformationLength
< sizeof(TOKEN_SOURCE
))
670 uLength
= sizeof(TOKEN_SOURCE
);
671 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
672 if (NT_SUCCESS(Status
))
673 Status
= STATUS_BUFFER_TOO_SMALL
;
677 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenSource
, sizeof(TOKEN_SOURCE
));
682 DPRINT("NtQueryInformationToken(TokenType)\n");
683 if (TokenInformationLength
< sizeof(TOKEN_TYPE
))
685 uLength
= sizeof(TOKEN_TYPE
);
686 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
687 if (NT_SUCCESS(Status
))
688 Status
= STATUS_BUFFER_TOO_SMALL
;
692 Status
= MmCopyToCaller(TokenInformation
, &Token
->TokenType
, sizeof(TOKEN_TYPE
));
696 case TokenImpersonationLevel
:
697 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
698 if (TokenInformationLength
< sizeof(SECURITY_IMPERSONATION_LEVEL
))
700 uLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
701 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
702 if (NT_SUCCESS(Status
))
703 Status
= STATUS_BUFFER_TOO_SMALL
;
707 Status
= MmCopyToCaller(TokenInformation
, &Token
->ImpersonationLevel
, sizeof(SECURITY_IMPERSONATION_LEVEL
));
711 case TokenStatistics
:
712 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
713 if (TokenInformationLength
< sizeof(TOKEN_STATISTICS
))
715 uLength
= sizeof(TOKEN_STATISTICS
);
716 Status
= MmCopyToCaller(ReturnLength
, &uLength
, sizeof(ULONG
));
717 if (NT_SUCCESS(Status
))
718 Status
= STATUS_BUFFER_TOO_SMALL
;
722 PtrTokenStatistics
= (PTOKEN_STATISTICS
)TokenInformation
;
723 PtrTokenStatistics
->TokenId
= Token
->TokenId
;
724 PtrTokenStatistics
->AuthenticationId
= Token
->AuthenticationId
;
725 PtrTokenStatistics
->ExpirationTime
= Token
->ExpirationTime
;
726 PtrTokenStatistics
->TokenType
= Token
->TokenType
;
727 PtrTokenStatistics
->ImpersonationLevel
= Token
->ImpersonationLevel
;
728 PtrTokenStatistics
->DynamicCharged
= Token
->DynamicCharged
;
729 PtrTokenStatistics
->DynamicAvailable
= Token
->DynamicAvailable
;
730 PtrTokenStatistics
->GroupCount
= Token
->UserAndGroupCount
- 1;
731 PtrTokenStatistics
->PrivilegeCount
= Token
->PrivilegeCount
;
732 PtrTokenStatistics
->ModifiedId
= Token
->ModifiedId
;
734 Status
= STATUS_SUCCESS
;
739 ObDereferenceObject(Token
);
746 NtSetInformationToken(IN HANDLE TokenHandle
,
747 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
748 OUT PVOID TokenInformation
,
749 IN ULONG TokenInformationLength
)
752 return(STATUS_NOT_IMPLEMENTED
);
760 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
761 IN ACCESS_MASK DesiredAccess
,
762 IN POBJECT_ATTRIBUTES ObjectAttributes
,
763 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
764 IN TOKEN_TYPE TokenType
,
765 OUT PHANDLE NewTokenHandle
)
769 PACCESS_TOKEN NewToken
;
771 ULONG ExistingImpersonationLevel
;
773 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
780 ExistingImpersonationLevel
= Token
->ImpersonationLevel
;
781 SepDuplicateToken(Token
,
785 ExistingImpersonationLevel
,
790 return(STATUS_NOT_IMPLEMENTED
);
794 VOID
SepAdjustGroups(PACCESS_TOKEN Token
,
796 BOOLEAN ResetToDefault
,
797 PSID_AND_ATTRIBUTES Groups
,
799 KPROCESSOR_MODE PreviousMode
,
810 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
811 IN BOOLEAN ResetToDefault
,
812 IN PTOKEN_GROUPS NewState
,
813 IN ULONG BufferLength
,
814 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
815 OUT PULONG ReturnLength
)
824 Status
= ObReferenceObjectByHandle(TokenHandle
,
832 SepAdjustGroups(Token
,
844 return(STATUS_NOT_IMPLEMENTED
);
851 SepAdjustPrivileges(PACCESS_TOKEN Token
,
853 KPROCESSOR_MODE PreviousMode
,
854 ULONG PrivilegeCount
,
855 PLUID_AND_ATTRIBUTES Privileges
,
856 PTOKEN_PRIVILEGES
* PreviousState
,
865 if (Token
->PrivilegeCount
> 0)
867 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
869 if (PreviousMode
!= KernelMode
)
871 if (Token
->Privileges
[i
]->Attributes
& SE_PRIVILEGE_ENABLED
== 0)
875 if (PreviousState
!= NULL
)
877 memcpy(&PreviousState
[i
],
878 &Token
->Privileges
[i
],
879 sizeof(LUID_AND_ATTRIBUTES
));
881 Token
->Privileges
[i
].Attributes
&= (~SE_PRIVILEGE_ENABLED
);
888 if (PreviousMode
!= KernelMode
)
890 Token
->TokenFlags
= Token
->TokenFlags
& (~1);
894 if (PrivilegeCount
<= ?)
907 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
908 IN BOOLEAN DisableAllPrivileges
,
909 IN PTOKEN_PRIVILEGES NewState
,
910 IN ULONG BufferLength
,
911 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
912 OUT PULONG ReturnLength OPTIONAL
)
914 // PLUID_AND_ATTRIBUTES Privileges;
915 KPROCESSOR_MODE PreviousMode
;
916 // ULONG PrivilegeCount;
929 DPRINT ("NtAdjustPrivilegesToken() called\n");
931 // PrivilegeCount = NewState->PrivilegeCount;
932 PreviousMode
= KeGetPreviousMode ();
933 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
943 Status
= ObReferenceObjectByHandle (TokenHandle
,
944 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
949 if (!NT_SUCCESS(Status
))
951 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
952 // SeReleaseLuidAndAttributesArray(Privileges,
960 SepAdjustPrivileges(Token
,
972 if (DisableAllPrivileges
== TRUE
)
974 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
976 if (Token
->Privileges
[i
].Attributes
!= 0)
978 DPRINT ("Attributes differ\n");
980 /* Save current privilege */
981 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
983 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
984 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
988 /* Update current privlege */
989 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
995 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
997 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
999 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1000 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1002 DPRINT ("Found privilege\n");
1004 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1005 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1007 DPRINT ("Attributes differ\n");
1008 DPRINT ("Current attributes %lx desired attributes %lx\n",
1009 Token
->Privileges
[i
].Attributes
,
1010 NewState
->Privileges
[j
].Attributes
);
1012 /* Save current privilege */
1013 if (PreviousState
!= NULL
&& k
< PreviousState
->PrivilegeCount
)
1015 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1016 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1020 /* Update current privlege */
1021 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1022 Token
->Privileges
[i
].Attributes
|=
1023 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1024 DPRINT ("New attributes %lx\n",
1025 Token
->Privileges
[i
].Attributes
);
1032 if (ReturnLength
!= NULL
)
1034 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1035 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1038 ObDereferenceObject (Token
);
1040 // SeReleaseLuidAndAttributesArray(Privileges,
1044 DPRINT ("NtAdjustPrivilegesToken() done\n");
1046 if (k
< NewState
->PrivilegeCount
)
1048 return STATUS_NOT_ALL_ASSIGNED
;
1051 return STATUS_SUCCESS
;
1056 SepCreateSystemProcessToken(struct _EPROCESS
* Process
)
1062 ULONG uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
1063 ULONG uWorldLength
= RtlLengthSid(SeWorldSid
);
1064 ULONG uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
1065 ULONG uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
1067 PACCESS_TOKEN AccessToken
;
1072 * Initialize the token
1074 Status
= ObCreateObject(KernelMode
,
1079 sizeof(ACCESS_TOKEN
),
1082 (PVOID
*)&AccessToken
);
1083 if (!NT_SUCCESS(Status
))
1088 Status
= NtAllocateLocallyUniqueId(&AccessToken
->TokenId
);
1089 if (!NT_SUCCESS(Status
))
1091 ObDereferenceObject(AccessToken
);
1095 Status
= NtAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
1096 if (!NT_SUCCESS(Status
))
1098 ObDereferenceObject(AccessToken
);
1102 AccessToken
->AuthenticationId
.LowPart
= SYSTEM_LUID
;
1103 AccessToken
->AuthenticationId
.HighPart
= 0;
1105 AccessToken
->TokenType
= TokenPrimary
;
1106 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
1107 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
1108 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
1109 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
1110 AccessToken
->ExpirationTime
.QuadPart
= -1;
1111 AccessToken
->UserAndGroupCount
= 4;
1113 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1114 uSize
+= uLocalSystemLength
;
1115 uSize
+= uWorldLength
;
1116 uSize
+= uAuthUserLength
;
1117 uSize
+= uAdminsLength
;
1119 AccessToken
->UserAndGroups
=
1120 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1122 TAG('T', 'O', 'K', 'u'));
1123 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1126 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1127 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
1128 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
1129 SidArea
+= uLocalSystemLength
;
1131 AccessToken
->DefaultOwnerIndex
= i
;
1132 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1133 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
1134 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
1135 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
1136 SidArea
+= uAdminsLength
;
1138 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1139 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1140 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
1141 SidArea
+= uWorldLength
;
1143 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
1144 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
1145 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
1146 SidArea
+= uAuthUserLength
;
1148 AccessToken
->PrivilegeCount
= 20;
1150 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1151 AccessToken
->Privileges
=
1152 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1154 TAG('T', 'O', 'K', 'p'));
1157 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1158 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
1160 AccessToken
->Privileges
[i
].Attributes
= 0;
1161 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
1163 AccessToken
->Privileges
[i
].Attributes
= 0;
1164 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
1166 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1167 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
1169 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1170 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
1172 AccessToken
->Privileges
[i
].Attributes
= 0;
1173 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
1175 AccessToken
->Privileges
[i
].Attributes
= 0;
1176 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
1178 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1179 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
1181 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1182 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
1184 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1185 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
1187 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1188 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
1190 AccessToken
->Privileges
[i
].Attributes
= 0;
1191 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
1193 AccessToken
->Privileges
[i
].Attributes
= 0;
1194 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
1196 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1197 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
1199 AccessToken
->Privileges
[i
].Attributes
= 0;
1200 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
1202 AccessToken
->Privileges
[i
].Attributes
= 0;
1203 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
1205 AccessToken
->Privileges
[i
].Attributes
= 0;
1206 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
1208 AccessToken
->Privileges
[i
].Attributes
= 0;
1209 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
1211 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
1212 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
1214 AccessToken
->Privileges
[i
].Attributes
= 0;
1215 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
1217 AccessToken
->Privileges
[i
].Attributes
= 0;
1218 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
1220 AccessToken
->Privileges
[i
].Attributes
= 0;
1221 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
1226 uSize
= sizeof(ACL
);
1227 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
1228 uSize
+= sizeof(ACE
) + uAdminsLength
;
1229 uSize
= (uSize
& (~3)) + 8;
1230 AccessToken
->DefaultDacl
=
1231 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1233 TAG('T', 'O', 'K', 'd'));
1234 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
1235 if ( NT_SUCCESS(Status
) )
1237 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
1240 if ( NT_SUCCESS(Status
) )
1242 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
1245 if ( ! NT_SUCCESS(Status
) )
1247 ObDereferenceObject(AccessToken
);
1251 Process
->Token
= AccessToken
;
1252 return(STATUS_SUCCESS
);
1257 NtCreateToken(OUT PHANDLE UnsafeTokenHandle
,
1258 IN ACCESS_MASK DesiredAccess
,
1259 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes
,
1260 IN TOKEN_TYPE TokenType
,
1261 IN PLUID AuthenticationId
,
1262 IN PLARGE_INTEGER ExpirationTime
,
1263 IN PTOKEN_USER TokenUser
,
1264 IN PTOKEN_GROUPS TokenGroups
,
1265 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1266 IN PTOKEN_OWNER TokenOwner
,
1267 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1268 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1269 IN PTOKEN_SOURCE TokenSource
)
1272 PACCESS_TOKEN AccessToken
;
1274 OBJECT_ATTRIBUTES SafeObjectAttributes
;
1275 POBJECT_ATTRIBUTES ObjectAttributes
;
1282 Status
= MmCopyFromCaller(&SafeObjectAttributes
,
1283 UnsafeObjectAttributes
,
1284 sizeof(OBJECT_ATTRIBUTES
));
1285 if (!NT_SUCCESS(Status
))
1288 ObjectAttributes
= &SafeObjectAttributes
;
1290 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
1291 if (!NT_SUCCESS(Status
))
1294 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
1295 if (!NT_SUCCESS(Status
))
1298 Status
= ObCreateObject(ExGetPreviousMode(),
1301 ExGetPreviousMode(),
1303 sizeof(ACCESS_TOKEN
),
1306 (PVOID
*)&AccessToken
);
1307 if (!NT_SUCCESS(Status
))
1309 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1313 Status
= ObInsertObject ((PVOID
)AccessToken
,
1319 if (!NT_SUCCESS(Status
))
1321 DPRINT1("ObInsertObject() failed (Status %lx)\n");
1322 ObDereferenceObject (AccessToken
);
1326 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
1327 &TokenSource
->SourceIdentifier
);
1328 memcpy(AccessToken
->TokenSource
.SourceName
,
1329 TokenSource
->SourceName
,
1330 sizeof(TokenSource
->SourceName
));
1332 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
1333 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
1334 AccessToken
->ExpirationTime
= *ExpirationTime
;
1335 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
1337 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
1338 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
1339 AccessToken
->UserAndGroups
= 0;
1340 AccessToken
->Privileges
= 0;
1342 AccessToken
->TokenType
= TokenType
;
1343 AccessToken
->ImpersonationLevel
= ObjectAttributes
->SecurityQualityOfService
->ImpersonationLevel
;
1346 * Normally we would just point these members into the variable information
1347 * area; however, our ObCreateObject() call can't allocate a variable information
1348 * area, so we allocate them seperately and provide a destroy function.
1351 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
1352 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
1353 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
1354 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
1356 AccessToken
->UserAndGroups
=
1357 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1359 TAG('T', 'O', 'K', 'u'));
1361 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
1363 Status
= RtlCopySidAndAttributesArray(1,
1366 AccessToken
->UserAndGroups
,
1370 if (NT_SUCCESS(Status
))
1372 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
1373 TokenGroups
->Groups
,
1375 &AccessToken
->UserAndGroups
[1],
1381 if (NT_SUCCESS(Status
))
1383 Status
= SepFindPrimaryGroupAndDefaultOwner(
1385 TokenPrimaryGroup
->PrimaryGroup
,
1389 if (NT_SUCCESS(Status
))
1391 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
1392 AccessToken
->Privileges
=
1393 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(NonPagedPool
,
1395 TAG('T', 'O', 'K', 'p'));
1397 for (i
= 0; i
< TokenPrivileges
->PrivilegeCount
; i
++)
1399 Status
= MmCopyFromCaller(&AccessToken
->Privileges
[i
],
1400 &TokenPrivileges
->Privileges
[i
],
1401 sizeof(LUID_AND_ATTRIBUTES
));
1402 if (!NT_SUCCESS(Status
))
1407 if (NT_SUCCESS(Status
))
1409 AccessToken
->DefaultDacl
=
1410 (PACL
) ExAllocatePoolWithTag(NonPagedPool
,
1411 TokenDefaultDacl
->DefaultDacl
->AclSize
,
1412 TAG('T', 'O', 'K', 'd'));
1413 memcpy(AccessToken
->DefaultDacl
,
1414 TokenDefaultDacl
->DefaultDacl
,
1415 TokenDefaultDacl
->DefaultDacl
->AclSize
);
1418 ObDereferenceObject(AccessToken
);
1420 if (NT_SUCCESS(Status
))
1422 Status
= MmCopyToCaller(UnsafeTokenHandle
,
1427 if (!NT_SUCCESS(Status
))
1429 ZwClose(TokenHandle
);
1433 return(STATUS_SUCCESS
);
1440 SECURITY_IMPERSONATION_LEVEL STDCALL
1441 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
1443 return(Token
->ImpersonationLevel
);
1451 SeTokenType(IN PACCESS_TOKEN Token
)
1453 return(Token
->TokenType
);