2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/token.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
10 /* INCLUDES *******************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitializeTokenImplementation)
20 /* GLOBALS ********************************************************************/
22 POBJECT_TYPE SepTokenObjectType
= NULL
;
23 ERESOURCE SepTokenLock
;
25 TOKEN_SOURCE SeSystemTokenSource
= {"*SYSTEM*", {0}};
26 LUID SeSystemAuthenticationId
= SYSTEM_LUID
;
28 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
33 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
35 /* Class 0 not used, blame M$! */
36 ICI_SQ_SAME( 0, 0, 0),
39 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
41 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
43 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
45 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
46 /* TokenPrimaryGroup */
47 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
48 /* TokenDefaultDacl */
49 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
51 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
53 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
54 /* TokenImpersonationLevel */
55 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
57 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
58 /* TokenRestrictedSids */
59 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
61 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
62 /* TokenGroupsAndPrivileges */
63 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
64 /* TokenSessionReference */
65 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
66 /* TokenSandBoxInert */
67 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
68 /* TokenAuditPolicy */
69 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
71 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
74 /* FUNCTIONS *****************************************************************/
77 SepCompareTokens(IN PTOKEN FirstToken
,
78 IN PTOKEN SecondToken
,
81 BOOLEAN Restricted
, IsEqual
= FALSE
;
83 ASSERT(FirstToken
!= SecondToken
);
85 /* FIXME: Check if every SID that is present in either token is also present in the other one */
87 Restricted
= SeTokenIsRestricted(FirstToken
);
88 if (Restricted
== SeTokenIsRestricted(SecondToken
))
92 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
95 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
99 return STATUS_SUCCESS
;
104 SepFreeProxyData(PVOID ProxyData
)
111 SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
114 return(STATUS_NOT_IMPLEMENTED
);
119 SeExchangePrimaryToken(PEPROCESS Process
,
120 PACCESS_TOKEN NewTokenP
,
121 PACCESS_TOKEN
* OldTokenP
)
124 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
128 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
129 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
131 /* Mark new token in use */
132 NewToken
->TokenInUse
= 1;
134 /* Reference the New Token */
135 ObReferenceObject(NewToken
);
137 /* Replace the old with the new */
138 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
140 /* Mark the Old Token as free */
141 OldToken
->TokenInUse
= 0;
143 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
144 return STATUS_SUCCESS
;
149 SeDeassignPrimaryToken(PEPROCESS Process
)
153 /* Remove the Token */
154 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
156 /* Mark the Old Token as free */
157 OldToken
->TokenInUse
= 0;
161 RtlLengthSidAndAttributes(ULONG Count
,
162 PSID_AND_ATTRIBUTES Src
)
169 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
170 for (i
= 0; i
< Count
; i
++)
171 uLength
+= RtlLengthSid(Src
[i
].Sid
);
179 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
185 Token
->PrimaryGroup
= 0;
189 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
192 /* Validate and set the primary group and user pointers */
193 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
196 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
198 Token
->DefaultOwnerIndex
= i
;
201 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
203 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
207 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
209 return(STATUS_INVALID_OWNER
);
212 if (Token
->PrimaryGroup
== 0)
214 return(STATUS_INVALID_PRIMARY_GROUP
);
217 return(STATUS_SUCCESS
);
223 SepDuplicateToken(PTOKEN Token
,
224 POBJECT_ATTRIBUTES ObjectAttributes
,
225 BOOLEAN EffectiveOnly
,
226 TOKEN_TYPE TokenType
,
227 SECURITY_IMPERSONATION_LEVEL Level
,
228 KPROCESSOR_MODE PreviousMode
,
229 PTOKEN
* NewAccessToken
)
239 Status
= ObCreateObject(PreviousMode
,
247 (PVOID
*)&AccessToken
);
248 if (!NT_SUCCESS(Status
))
250 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status
);
254 /* Zero out the buffer */
255 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
257 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
258 if (!NT_SUCCESS(Status
))
260 ObDereferenceObject(AccessToken
);
264 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
265 if (!NT_SUCCESS(Status
))
267 ObDereferenceObject(AccessToken
);
271 AccessToken
->TokenLock
= &SepTokenLock
;
273 AccessToken
->TokenType
= TokenType
;
274 AccessToken
->ImpersonationLevel
= Level
;
275 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
277 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
278 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
279 memcpy(AccessToken
->TokenSource
.SourceName
,
280 Token
->TokenSource
.SourceName
,
281 sizeof(Token
->TokenSource
.SourceName
));
282 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
283 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
284 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
286 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
287 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
288 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
290 AccessToken
->UserAndGroups
=
291 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
295 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
297 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
298 Token
->UserAndGroups
,
300 AccessToken
->UserAndGroups
,
304 if (NT_SUCCESS(Status
))
306 Status
= SepFindPrimaryGroupAndDefaultOwner(
312 if (NT_SUCCESS(Status
))
314 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
316 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
317 AccessToken
->Privileges
=
318 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
322 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
324 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
325 &Token
->Privileges
[i
].Luid
);
326 AccessToken
->Privileges
[i
].Attributes
=
327 Token
->Privileges
[i
].Attributes
;
330 if ( Token
->DefaultDacl
)
332 AccessToken
->DefaultDacl
=
333 (PACL
) ExAllocatePoolWithTag(PagedPool
,
334 Token
->DefaultDacl
->AclSize
,
336 memcpy(AccessToken
->DefaultDacl
,
338 Token
->DefaultDacl
->AclSize
);
342 if ( NT_SUCCESS(Status
) )
344 *NewAccessToken
= AccessToken
;
345 return(STATUS_SUCCESS
);
353 SeSubProcessToken(IN PTOKEN ParentToken
,
359 OBJECT_ATTRIBUTES ObjectAttributes
;
362 /* Initialize the attributes and duplicate it */
363 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
364 Status
= SepDuplicateToken(ParentToken
,
368 ParentToken
->ImpersonationLevel
,
371 if (NT_SUCCESS(Status
))
374 Status
= ObInsertObject(NewToken
,
380 if (NT_SUCCESS(Status
))
382 /* Set the session ID */
383 NewToken
->SessionId
= SessionId
;
384 NewToken
->TokenInUse
= InUse
;
386 /* Return the token */
397 SeIsTokenChild(IN PTOKEN Token
,
398 OUT PBOOLEAN IsChild
)
401 LUID ProcessLuid
, CallerLuid
;
406 /* Reference the process token */
407 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
410 ProcessLuid
= ProcessToken
->TokenId
;
412 /* Dereference the token */
413 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
416 CallerLuid
= Token
->TokenId
;
418 /* Compare the LUIDs */
419 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
422 return STATUS_SUCCESS
;
427 SeCopyClientToken(IN PACCESS_TOKEN Token
,
428 IN SECURITY_IMPERSONATION_LEVEL Level
,
429 IN KPROCESSOR_MODE PreviousMode
,
430 OUT PACCESS_TOKEN
* NewToken
)
433 OBJECT_ATTRIBUTES ObjectAttributes
;
437 InitializeObjectAttributes(&ObjectAttributes
,
442 Status
= SepDuplicateToken(Token
,
454 SepDeleteToken(PVOID ObjectBody
)
456 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
458 if (AccessToken
->UserAndGroups
)
459 ExFreePool(AccessToken
->UserAndGroups
);
461 if (AccessToken
->Privileges
)
462 ExFreePool(AccessToken
->Privileges
);
464 if (AccessToken
->DefaultDacl
)
465 ExFreePool(AccessToken
->DefaultDacl
);
472 SepInitializeTokenImplementation(VOID
)
475 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
477 ExInitializeResource(&SepTokenLock
);
479 DPRINT("Creating Token Object Type\n");
481 /* Initialize the Token type */
482 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
483 RtlInitUnicodeString(&Name
, L
"Token");
484 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
485 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
486 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
487 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
488 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
489 ObjectTypeInitializer
.PoolType
= PagedPool
;
490 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
491 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
492 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
493 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SepTokenObjectType
);
498 SeAssignPrimaryToken(IN PEPROCESS Process
,
504 ASSERT(Token
->TokenType
== TokenPrimary
);
505 ASSERT(!Token
->TokenInUse
);
507 /* Clean any previous token */
508 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
510 /* Set the new token */
511 ObReferenceObject(Token
);
512 Token
->TokenInUse
= TRUE
;
513 ObInitializeFastReference(&Process
->Token
, Token
);
519 SepCreateToken(OUT PHANDLE TokenHandle
,
520 IN KPROCESSOR_MODE PreviousMode
,
521 IN ACCESS_MASK DesiredAccess
,
522 IN POBJECT_ATTRIBUTES ObjectAttributes
,
523 IN TOKEN_TYPE TokenType
,
524 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
525 IN PLUID AuthenticationId
,
526 IN PLARGE_INTEGER ExpirationTime
,
527 IN PSID_AND_ATTRIBUTES User
,
529 IN PSID_AND_ATTRIBUTES Groups
,
530 IN ULONG GroupLength
,
531 IN ULONG PrivilegeCount
,
532 IN PLUID_AND_ATTRIBUTES Privileges
,
534 IN PSID PrimaryGroup
,
536 IN PTOKEN_SOURCE TokenSource
,
537 IN BOOLEAN SystemToken
)
546 ULONG TokenFlags
= 0;
548 /* Loop all groups */
549 for (i
= 0; i
< GroupCount
; i
++)
551 /* Check for mandatory groups */
552 if (Groups
[i
].Attributes
& SE_GROUP_MANDATORY
)
554 /* Force them to be enabled */
555 Groups
[i
].Attributes
|= (SE_GROUP_ENABLED
| SE_GROUP_ENABLED_BY_DEFAULT
);
558 /* Check of the group is an admin group */
559 if (RtlEqualSid(SeAliasAdminsSid
, Groups
[i
].Sid
))
561 /* Remember this so we can optimize queries later */
562 TokenFlags
|= TOKEN_HAS_ADMIN_GROUP
;
566 /* Loop all privileges */
567 for (i
= 0; i
< PrivilegeCount
; i
++)
569 /* For optimization, check for change notify and impersonate rights */
570 if (((RtlEqualLuid(&Privileges
[i
].Luid
, &SeChangeNotifyPrivilege
)) &&
571 (Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)))
573 /* Remember token has traverse */
574 TokenFlags
|= TOKEN_HAS_TRAVERSE_PRIVILEGE
;
578 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
579 if (!NT_SUCCESS(Status
))
582 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
583 if (!NT_SUCCESS(Status
))
586 Status
= ObCreateObject(PreviousMode
,
594 (PVOID
*)&AccessToken
);
595 if (!NT_SUCCESS(Status
))
597 DPRINT1("ObCreateObject() failed (Status %lx)\n");
601 /* Zero out the buffer */
602 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
604 AccessToken
->TokenLock
= &SepTokenLock
;
606 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
607 &TokenSource
->SourceIdentifier
);
608 memcpy(AccessToken
->TokenSource
.SourceName
,
609 TokenSource
->SourceName
,
610 sizeof(TokenSource
->SourceName
));
612 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
613 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
614 AccessToken
->ExpirationTime
= *ExpirationTime
;
615 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
617 AccessToken
->UserAndGroupCount
= GroupCount
+ 1;
618 AccessToken
->PrivilegeCount
= PrivilegeCount
;
620 AccessToken
->TokenFlags
= TokenFlags
;
621 AccessToken
->TokenType
= TokenType
;
622 AccessToken
->ImpersonationLevel
= ImpersonationLevel
;
625 * Normally we would just point these members into the variable information
626 * area; however, our ObCreateObject() call can't allocate a variable information
627 * area, so we allocate them seperately and provide a destroy function.
630 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
631 uLength
+= RtlLengthSid(User
);
632 for (i
= 0; i
< GroupCount
; i
++)
633 uLength
+= RtlLengthSid(Groups
[i
].Sid
);
635 AccessToken
->UserAndGroups
=
636 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
640 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
642 Status
= RtlCopySidAndAttributesArray(1,
645 AccessToken
->UserAndGroups
,
649 if (NT_SUCCESS(Status
))
651 Status
= RtlCopySidAndAttributesArray(GroupCount
,
654 &AccessToken
->UserAndGroups
[1],
660 if (NT_SUCCESS(Status
))
662 Status
= SepFindPrimaryGroupAndDefaultOwner(
668 if (NT_SUCCESS(Status
))
670 uLength
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
671 AccessToken
->Privileges
=
672 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
676 if (PreviousMode
!= KernelMode
)
680 RtlCopyMemory(AccessToken
->Privileges
,
682 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
684 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
686 Status
= _SEH2_GetExceptionCode();
692 RtlCopyMemory(AccessToken
->Privileges
,
694 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
698 if (NT_SUCCESS(Status
))
700 AccessToken
->DefaultDacl
=
701 (PACL
) ExAllocatePoolWithTag(PagedPool
,
702 DefaultDacl
->AclSize
,
704 memcpy(AccessToken
->DefaultDacl
,
706 DefaultDacl
->AclSize
);
712 Status
= ObInsertObject ((PVOID
)AccessToken
,
718 if (!NT_SUCCESS(Status
))
720 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
725 /* Return pointer instead of handle */
726 *TokenHandle
= (HANDLE
)AccessToken
;
734 SepCreateSystemProcessToken(VOID
)
736 LUID_AND_ATTRIBUTES Privileges
[25];
737 ULONG GroupAttributes
, OwnerAttributes
;
738 SID_AND_ATTRIBUTES Groups
[32];
739 LARGE_INTEGER Expiration
;
740 SID_AND_ATTRIBUTES UserSid
;
743 OBJECT_ATTRIBUTES ObjectAttributes
;
749 /* Don't ever expire */
750 Expiration
.QuadPart
= -1;
752 /* All groups mandatory and enabled */
753 GroupAttributes
= SE_GROUP_ENABLED
| SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
;
754 OwnerAttributes
= SE_GROUP_ENABLED
| SE_GROUP_OWNER
| SE_GROUP_ENABLED_BY_DEFAULT
;
757 UserSid
.Sid
= SeLocalSystemSid
;
758 UserSid
.Attributes
= 0;
760 /* Primary group is local system */
761 PrimaryGroup
= SeLocalSystemSid
;
763 /* Owner is admins */
764 Owner
= SeAliasAdminsSid
;
766 /* Groups are admins, world, and authenticated users */
767 Groups
[0].Sid
= SeAliasAdminsSid
;
768 Groups
[0].Attributes
= OwnerAttributes
;
769 Groups
[1].Sid
= SeWorldSid
;
770 Groups
[1].Attributes
= GroupAttributes
;
771 Groups
[2].Sid
= SeAuthenticatedUserSid
;
772 Groups
[2].Attributes
= OwnerAttributes
;
773 GroupLength
= sizeof(SID_AND_ATTRIBUTES
) +
774 SeLengthSid(Groups
[0].Sid
) +
775 SeLengthSid(Groups
[1].Sid
) +
776 SeLengthSid(Groups
[2].Sid
);
777 ASSERT(GroupLength
<= sizeof(Groups
));
779 /* Setup the privileges */
781 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
| SE_PRIVILEGE_ENABLED
;
782 Privileges
[i
++].Luid
= SeTcbPrivilege
;
784 Privileges
[i
].Attributes
= 0;
785 Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
787 Privileges
[i
].Attributes
= 0;
788 Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
790 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
791 Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
793 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
794 Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
796 Privileges
[i
].Attributes
= 0;
797 Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
799 Privileges
[i
].Attributes
= 0;
800 Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
802 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
803 Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
805 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
806 Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
808 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
809 Privileges
[i
++].Luid
= SeDebugPrivilege
;
811 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
812 Privileges
[i
++].Luid
= SeAuditPrivilege
;
814 Privileges
[i
].Attributes
= 0;
815 Privileges
[i
++].Luid
= SeSecurityPrivilege
;
817 Privileges
[i
].Attributes
= 0;
818 Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
820 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
821 Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
823 Privileges
[i
].Attributes
= 0;
824 Privileges
[i
++].Luid
= SeBackupPrivilege
;
826 Privileges
[i
].Attributes
= 0;
827 Privileges
[i
++].Luid
= SeRestorePrivilege
;
829 Privileges
[i
].Attributes
= 0;
830 Privileges
[i
++].Luid
= SeShutdownPrivilege
;
832 Privileges
[i
].Attributes
= 0;
833 Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
835 Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
836 Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
838 Privileges
[i
].Attributes
= 0;
839 Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
842 /* Setup the object attributes */
843 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
844 ASSERT(SeSystemDefaultDacl
!= NULL
);
846 /* Create the token */
847 Status
= SepCreateToken((PHANDLE
)&Token
,
853 &SeSystemAuthenticationId
,
864 &SeSystemTokenSource
,
866 ASSERT(Status
== STATUS_SUCCESS
);
868 /* Return the token */
872 /* PUBLIC FUNCTIONS ***********************************************************/
879 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
881 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
882 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
883 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
884 OUT PACCESS_TOKEN
* FilteredToken
)
887 return STATUS_NOT_IMPLEMENTED
;
895 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
896 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
897 OUT PVOID
*TokenInformation
)
900 return STATUS_NOT_IMPLEMENTED
;
908 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
909 IN PULONG pSessionId
)
911 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
912 return STATUS_SUCCESS
;
919 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
924 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
926 return STATUS_SUCCESS
;
933 SECURITY_IMPERSONATION_LEVEL
935 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
939 return ((PTOKEN
)Token
)->ImpersonationLevel
;
947 SeTokenType(IN PACCESS_TOKEN Token
)
951 return ((PTOKEN
)Token
)->TokenType
;
960 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
963 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
971 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
974 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
982 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
985 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
988 /* SYSTEM CALLS ***************************************************************/
994 NtQueryInformationToken(IN HANDLE TokenHandle
,
995 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
996 OUT PVOID TokenInformation
,
997 IN ULONG TokenInformationLength
,
998 OUT PULONG ReturnLength
)
1006 ULONG RequiredLength
;
1007 KPROCESSOR_MODE PreviousMode
;
1008 NTSTATUS Status
= STATUS_SUCCESS
;
1012 PreviousMode
= ExGetPreviousMode();
1014 /* Check buffers and class validity */
1015 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
1016 SeTokenInformationClass
,
1017 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1019 TokenInformationLength
,
1024 if(!NT_SUCCESS(Status
))
1026 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
1030 Status
= ObReferenceObjectByHandle(TokenHandle
,
1031 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
1036 if (NT_SUCCESS(Status
))
1038 switch (TokenInformationClass
)
1042 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
1044 DPRINT("NtQueryInformationToken(TokenUser)\n");
1045 RequiredLength
= sizeof(TOKEN_USER
) +
1046 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
1050 if(TokenInformationLength
>= RequiredLength
)
1052 Status
= RtlCopySidAndAttributesArray(1,
1053 &Token
->UserAndGroups
[0],
1054 RequiredLength
- sizeof(TOKEN_USER
),
1062 Status
= STATUS_BUFFER_TOO_SMALL
;
1065 if(ReturnLength
!= NULL
)
1067 *ReturnLength
= RequiredLength
;
1070 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1072 Status
= _SEH2_GetExceptionCode();
1081 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1083 DPRINT("NtQueryInformationToken(TokenGroups)\n");
1084 RequiredLength
= sizeof(tg
->GroupCount
) +
1085 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
1089 if(TokenInformationLength
>= RequiredLength
)
1091 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1092 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
1093 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1094 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
1096 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
1097 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
1098 &Token
->UserAndGroups
[1],
1107 Status
= STATUS_BUFFER_TOO_SMALL
;
1110 if(ReturnLength
!= NULL
)
1112 *ReturnLength
= RequiredLength
;
1115 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1117 Status
= _SEH2_GetExceptionCode();
1124 case TokenPrivileges
:
1126 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
1128 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
1129 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
1130 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
1134 if(TokenInformationLength
>= RequiredLength
)
1136 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
1137 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
1139 &tp
->Privileges
[0]);
1143 Status
= STATUS_BUFFER_TOO_SMALL
;
1146 if(ReturnLength
!= NULL
)
1148 *ReturnLength
= RequiredLength
;
1151 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1153 Status
= _SEH2_GetExceptionCode();
1163 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1165 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1166 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1167 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1171 if(TokenInformationLength
>= RequiredLength
)
1173 to
->Owner
= (PSID
)(to
+ 1);
1174 Status
= RtlCopySid(SidLen
,
1176 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1180 Status
= STATUS_BUFFER_TOO_SMALL
;
1183 if(ReturnLength
!= NULL
)
1185 *ReturnLength
= RequiredLength
;
1188 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1190 Status
= _SEH2_GetExceptionCode();
1197 case TokenPrimaryGroup
:
1200 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1202 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1203 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1204 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1208 if(TokenInformationLength
>= RequiredLength
)
1210 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1211 Status
= RtlCopySid(SidLen
,
1213 Token
->PrimaryGroup
);
1217 Status
= STATUS_BUFFER_TOO_SMALL
;
1220 if(ReturnLength
!= NULL
)
1222 *ReturnLength
= RequiredLength
;
1225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1227 Status
= _SEH2_GetExceptionCode();
1234 case TokenDefaultDacl
:
1236 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1238 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1239 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1241 if(Token
->DefaultDacl
!= NULL
)
1243 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1248 if(TokenInformationLength
>= RequiredLength
)
1250 if(Token
->DefaultDacl
!= NULL
)
1252 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1253 RtlCopyMemory(tdd
->DefaultDacl
,
1255 Token
->DefaultDacl
->AclSize
);
1259 tdd
->DefaultDacl
= NULL
;
1264 Status
= STATUS_BUFFER_TOO_SMALL
;
1267 if(ReturnLength
!= NULL
)
1269 *ReturnLength
= RequiredLength
;
1272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1274 Status
= _SEH2_GetExceptionCode();
1283 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1285 DPRINT("NtQueryInformationToken(TokenSource)\n");
1286 RequiredLength
= sizeof(TOKEN_SOURCE
);
1290 if(TokenInformationLength
>= RequiredLength
)
1292 *ts
= Token
->TokenSource
;
1296 Status
= STATUS_BUFFER_TOO_SMALL
;
1299 if(ReturnLength
!= NULL
)
1301 *ReturnLength
= RequiredLength
;
1304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1306 Status
= _SEH2_GetExceptionCode();
1315 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1317 DPRINT("NtQueryInformationToken(TokenType)\n");
1318 RequiredLength
= sizeof(TOKEN_TYPE
);
1322 if(TokenInformationLength
>= RequiredLength
)
1324 *tt
= Token
->TokenType
;
1328 Status
= STATUS_BUFFER_TOO_SMALL
;
1331 if(ReturnLength
!= NULL
)
1333 *ReturnLength
= RequiredLength
;
1336 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1338 Status
= _SEH2_GetExceptionCode();
1345 case TokenImpersonationLevel
:
1347 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1349 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1351 /* Fail if the token is not an impersonation token */
1352 if (Token
->TokenType
!= TokenImpersonation
)
1354 Status
= STATUS_INVALID_INFO_CLASS
;
1358 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1362 if(TokenInformationLength
>= RequiredLength
)
1364 *sil
= Token
->ImpersonationLevel
;
1368 Status
= STATUS_BUFFER_TOO_SMALL
;
1371 if(ReturnLength
!= NULL
)
1373 *ReturnLength
= RequiredLength
;
1376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1378 Status
= _SEH2_GetExceptionCode();
1385 case TokenStatistics
:
1387 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1389 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1390 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1394 if(TokenInformationLength
>= RequiredLength
)
1396 ts
->TokenId
= Token
->TokenId
;
1397 ts
->AuthenticationId
= Token
->AuthenticationId
;
1398 ts
->ExpirationTime
= Token
->ExpirationTime
;
1399 ts
->TokenType
= Token
->TokenType
;
1400 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1401 ts
->DynamicCharged
= Token
->DynamicCharged
;
1402 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1403 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1404 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1405 ts
->ModifiedId
= Token
->ModifiedId
;
1409 Status
= STATUS_BUFFER_TOO_SMALL
;
1412 if(ReturnLength
!= NULL
)
1414 *ReturnLength
= RequiredLength
;
1417 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1419 Status
= _SEH2_GetExceptionCode();
1428 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1430 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1431 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1435 if(TokenInformationLength
>= RequiredLength
)
1437 RtlCopyLuid(&to
->OriginatingLogonSession
,
1438 &Token
->AuthenticationId
);
1442 Status
= STATUS_BUFFER_TOO_SMALL
;
1445 if(ReturnLength
!= NULL
)
1447 *ReturnLength
= RequiredLength
;
1450 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1452 Status
= _SEH2_GetExceptionCode();
1459 case TokenGroupsAndPrivileges
:
1460 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1461 Status
= STATUS_NOT_IMPLEMENTED
;
1464 case TokenRestrictedSids
:
1466 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1468 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1469 RequiredLength
= sizeof(tg
->GroupCount
) +
1470 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1474 if(TokenInformationLength
>= RequiredLength
)
1476 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1477 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1478 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1479 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1481 tg
->GroupCount
= Token
->RestrictedSidCount
;
1482 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1483 Token
->RestrictedSids
,
1492 Status
= STATUS_BUFFER_TOO_SMALL
;
1495 if(ReturnLength
!= NULL
)
1497 *ReturnLength
= RequiredLength
;
1500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1502 Status
= _SEH2_GetExceptionCode();
1509 case TokenSandBoxInert
:
1510 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1511 Status
= STATUS_NOT_IMPLEMENTED
;
1514 case TokenSessionId
:
1516 ULONG SessionId
= 0;
1518 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1520 Status
= SeQuerySessionIdToken(Token
,
1523 if(NT_SUCCESS(Status
))
1527 /* buffer size was already verified, no need to check here again */
1528 *(PULONG
)TokenInformation
= SessionId
;
1530 if(ReturnLength
!= NULL
)
1532 *ReturnLength
= sizeof(ULONG
);
1535 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1537 Status
= _SEH2_GetExceptionCode();
1546 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1547 Status
= STATUS_INVALID_INFO_CLASS
;
1551 ObDereferenceObject(Token
);
1559 * NtSetTokenInformation: Partly implemented.
1561 * TokenOrigin, TokenDefaultDacl
1565 NtSetInformationToken(IN HANDLE TokenHandle
,
1566 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1567 OUT PVOID TokenInformation
,
1568 IN ULONG TokenInformationLength
)
1571 KPROCESSOR_MODE PreviousMode
;
1572 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1577 PreviousMode
= ExGetPreviousMode();
1579 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1580 SeTokenInformationClass
,
1581 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1583 TokenInformationLength
,
1586 if(!NT_SUCCESS(Status
))
1588 /* Invalid buffers */
1589 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1593 if(TokenInformationClass
== TokenSessionId
)
1595 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1598 Status
= ObReferenceObjectByHandle(TokenHandle
,
1604 if (NT_SUCCESS(Status
))
1606 switch (TokenInformationClass
)
1610 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1612 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1613 PSID InputSid
= NULL
, CapturedSid
;
1617 InputSid
= to
->Owner
;
1619 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1621 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1625 Status
= SepCaptureSid(InputSid
,
1630 if(NT_SUCCESS(Status
))
1632 RtlCopySid(RtlLengthSid(CapturedSid
),
1633 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1635 SepReleaseSid(CapturedSid
,
1642 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1647 case TokenPrimaryGroup
:
1649 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1651 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1652 PSID InputSid
= NULL
, CapturedSid
;
1656 InputSid
= tpg
->PrimaryGroup
;
1658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1660 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1664 Status
= SepCaptureSid(InputSid
,
1669 if(NT_SUCCESS(Status
))
1671 RtlCopySid(RtlLengthSid(CapturedSid
),
1672 Token
->PrimaryGroup
,
1674 SepReleaseSid(CapturedSid
,
1681 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1686 case TokenDefaultDacl
:
1688 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1690 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1691 PACL InputAcl
= NULL
;
1695 InputAcl
= tdd
->DefaultDacl
;
1697 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1699 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1703 if(InputAcl
!= NULL
)
1707 /* capture and copy the dacl */
1708 Status
= SepCaptureAcl(InputAcl
,
1713 if(NT_SUCCESS(Status
))
1715 /* free the previous dacl if present */
1716 if(Token
->DefaultDacl
!= NULL
)
1718 ExFreePool(Token
->DefaultDacl
);
1721 /* set the new dacl */
1722 Token
->DefaultDacl
= CapturedAcl
;
1727 /* clear and free the default dacl if present */
1728 if(Token
->DefaultDacl
!= NULL
)
1730 ExFreePool(Token
->DefaultDacl
);
1731 Token
->DefaultDacl
= NULL
;
1737 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1742 case TokenSessionId
:
1744 ULONG SessionId
= 0;
1748 /* buffer size was already verified, no need to check here again */
1749 SessionId
= *(PULONG
)TokenInformation
;
1751 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1753 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1757 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1760 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1764 Token
->SessionId
= SessionId
;
1770 Status
= STATUS_NOT_IMPLEMENTED
;
1775 ObDereferenceObject(Token
);
1785 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1786 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1787 * is correct either. -Gunnar
1788 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1791 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1792 IN ACCESS_MASK DesiredAccess
,
1793 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1794 IN BOOLEAN EffectiveOnly
,
1795 IN TOKEN_TYPE TokenType
,
1796 OUT PHANDLE NewTokenHandle
)
1798 KPROCESSOR_MODE PreviousMode
;
1802 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1808 PreviousMode
= KeGetPreviousMode();
1810 if (PreviousMode
!= KernelMode
)
1814 ProbeForWriteHandle(NewTokenHandle
);
1816 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1818 /* Return the exception code */
1819 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1824 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1828 &CapturedSecurityQualityOfService
,
1830 if(!NT_SUCCESS(Status
))
1832 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1836 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1842 if (NT_SUCCESS(Status
))
1844 Status
= SepDuplicateToken(Token
,
1848 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1852 ObDereferenceObject(Token
);
1854 if (NT_SUCCESS(Status
))
1856 Status
= ObInsertObject((PVOID
)NewToken
,
1863 if (NT_SUCCESS(Status
))
1867 *NewTokenHandle
= hToken
;
1869 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1871 Status
= _SEH2_GetExceptionCode();
1878 /* free the captured structure */
1879 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1887 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1888 IN BOOLEAN ResetToDefault
,
1889 IN PTOKEN_GROUPS NewState
,
1890 IN ULONG BufferLength
,
1891 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1892 OUT PULONG ReturnLength
)
1895 return(STATUS_NOT_IMPLEMENTED
);
1902 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1903 IN BOOLEAN DisableAllPrivileges
,
1904 IN PTOKEN_PRIVILEGES NewState
,
1905 IN ULONG BufferLength
,
1906 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1907 OUT PULONG ReturnLength OPTIONAL
)
1909 // PLUID_AND_ATTRIBUTES Privileges;
1910 KPROCESSOR_MODE PreviousMode
;
1911 ULONG PrivilegeCount
;
1927 DPRINT ("NtAdjustPrivilegesToken() called\n");
1929 // PrivilegeCount = NewState->PrivilegeCount;
1930 PreviousMode
= KeGetPreviousMode ();
1931 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1941 Status
= ObReferenceObjectByHandle (TokenHandle
,
1942 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1947 if (!NT_SUCCESS(Status
))
1949 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1950 // SeReleaseLuidAndAttributesArray(Privileges,
1958 SepAdjustPrivileges(Token
,
1969 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1970 sizeof(LUID_AND_ATTRIBUTES
);
1972 if (PreviousState
!= NULL
)
1973 PreviousState
->PrivilegeCount
= 0;
1976 if (DisableAllPrivileges
== TRUE
)
1978 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1980 if (Token
->Privileges
[i
].Attributes
!= 0)
1982 DPRINT ("Attributes differ\n");
1984 /* Save current privilege */
1985 if (PreviousState
!= NULL
)
1987 if (k
< PrivilegeCount
)
1989 PreviousState
->PrivilegeCount
++;
1990 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1991 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1995 /* FIXME: Should revert all the changes, calculate how
1996 * much space would be needed, set ResultLength
1997 * accordingly and fail.
2003 /* Update current privlege */
2004 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2007 Status
= STATUS_SUCCESS
;
2012 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
2014 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
2016 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
2017 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
2019 DPRINT ("Found privilege\n");
2021 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
2022 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
2024 DPRINT ("Attributes differ\n");
2025 DPRINT ("Current attributes %lx desired attributes %lx\n",
2026 Token
->Privileges
[i
].Attributes
,
2027 NewState
->Privileges
[j
].Attributes
);
2029 /* Save current privilege */
2030 if (PreviousState
!= NULL
)
2032 if (k
< PrivilegeCount
)
2034 PreviousState
->PrivilegeCount
++;
2035 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
2036 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
2040 /* FIXME: Should revert all the changes, calculate how
2041 * much space would be needed, set ResultLength
2042 * accordingly and fail.
2048 /* Update current privlege */
2049 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
2050 Token
->Privileges
[i
].Attributes
|=
2051 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
2052 DPRINT ("New attributes %lx\n",
2053 Token
->Privileges
[i
].Attributes
);
2059 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
2062 if (ReturnLength
!= NULL
)
2064 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
2065 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
2068 ObDereferenceObject (Token
);
2070 // SeReleaseLuidAndAttributesArray(Privileges,
2074 DPRINT ("NtAdjustPrivilegesToken() done\n");
2081 NtCreateToken(OUT PHANDLE TokenHandle
,
2082 IN ACCESS_MASK DesiredAccess
,
2083 IN POBJECT_ATTRIBUTES ObjectAttributes
,
2084 IN TOKEN_TYPE TokenType
,
2085 IN PLUID AuthenticationId
,
2086 IN PLARGE_INTEGER ExpirationTime
,
2087 IN PTOKEN_USER TokenUser
,
2088 IN PTOKEN_GROUPS TokenGroups
,
2089 IN PTOKEN_PRIVILEGES TokenPrivileges
,
2090 IN PTOKEN_OWNER TokenOwner
,
2091 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
2092 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
2093 IN PTOKEN_SOURCE TokenSource
)
2096 KPROCESSOR_MODE PreviousMode
;
2097 ULONG nTokenPrivileges
= 0;
2098 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
2103 PreviousMode
= ExGetPreviousMode();
2105 if(PreviousMode
!= KernelMode
)
2109 ProbeForWriteHandle(TokenHandle
);
2110 ProbeForRead(AuthenticationId
,
2113 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
2114 ProbeForRead(TokenUser
,
2117 ProbeForRead(TokenGroups
,
2118 sizeof(TOKEN_GROUPS
),
2120 ProbeForRead(TokenPrivileges
,
2121 sizeof(TOKEN_PRIVILEGES
),
2123 ProbeForRead(TokenOwner
,
2124 sizeof(TOKEN_OWNER
),
2126 ProbeForRead(TokenPrimaryGroup
,
2127 sizeof(TOKEN_PRIMARY_GROUP
),
2129 ProbeForRead(TokenDefaultDacl
,
2130 sizeof(TOKEN_DEFAULT_DACL
),
2132 ProbeForRead(TokenSource
,
2133 sizeof(TOKEN_SOURCE
),
2135 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2137 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2139 /* Return the exception code */
2140 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2146 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2147 LocalExpirationTime
= *ExpirationTime
;
2150 Status
= SepCreateToken(&hToken
,
2155 ((PSECURITY_QUALITY_OF_SERVICE
)(ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
,
2157 &LocalExpirationTime
,
2159 TokenGroups
->GroupCount
,
2160 TokenGroups
->Groups
,
2161 0, // FIXME: Should capture
2163 TokenPrivileges
->Privileges
,
2165 TokenPrimaryGroup
->PrimaryGroup
,
2166 TokenDefaultDacl
->DefaultDacl
,
2169 if (NT_SUCCESS(Status
))
2173 *TokenHandle
= hToken
;
2175 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2177 Status
= _SEH2_GetExceptionCode();
2190 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2191 IN ACCESS_MASK DesiredAccess
,
2192 IN BOOLEAN OpenAsSelf
,
2193 IN ULONG HandleAttributes
,
2194 OUT PHANDLE TokenHandle
)
2196 PETHREAD Thread
, NewThread
;
2198 PTOKEN Token
, NewToken
= NULL
, PrimaryToken
;
2199 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2200 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2201 SE_IMPERSONATION_STATE ImpersonationState
;
2202 OBJECT_ATTRIBUTES ObjectAttributes
;
2203 SECURITY_DESCRIPTOR SecurityDescriptor
;
2205 KPROCESSOR_MODE PreviousMode
;
2210 PreviousMode
= ExGetPreviousMode();
2212 if (PreviousMode
!= KernelMode
)
2216 ProbeForWriteHandle(TokenHandle
);
2218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2220 /* Return the exception code */
2221 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2227 * At first open the thread token for information access and verify
2228 * that the token associated with thread is valid.
2231 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2232 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2234 if (!NT_SUCCESS(Status
))
2239 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2240 &ImpersonationLevel
);
2243 ObDereferenceObject(Thread
);
2244 return STATUS_NO_TOKEN
;
2247 if (ImpersonationLevel
== SecurityAnonymous
)
2249 PsDereferenceImpersonationToken(Token
);
2250 ObDereferenceObject(Thread
);
2251 return STATUS_CANT_OPEN_ANONYMOUS
;
2255 * Revert to self if OpenAsSelf is specified.
2260 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2265 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2266 PsThreadType
, KernelMode
,
2267 (PVOID
*)&NewThread
, NULL
);
2268 if (NT_SUCCESS(Status
))
2270 PrimaryToken
= PsReferencePrimaryToken(NewThread
->ThreadsProcess
);
2272 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2274 ObFastDereferenceObject(&NewThread
->ThreadsProcess
->Token
, PrimaryToken
);
2276 if (NT_SUCCESS(Status
))
2280 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2281 SECURITY_DESCRIPTOR_REVISION
);
2282 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2286 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2287 NULL
, Dacl
? &SecurityDescriptor
: NULL
);
2290 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2291 TokenImpersonation
, ImpersonationLevel
,
2292 KernelMode
, &NewToken
);
2293 if (NT_SUCCESS(Status
))
2295 ObReferenceObject(NewToken
);
2296 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2304 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2305 NULL
, DesiredAccess
, SepTokenObjectType
,
2306 PreviousMode
, &hToken
);
2309 if (Dacl
) ExFreePool(Dacl
);
2313 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2316 ObDereferenceObject(Token
);
2318 if (NT_SUCCESS(Status
) && CopyOnOpen
)
2320 PsImpersonateClient(Thread
, NewToken
, FALSE
, EffectiveOnly
, ImpersonationLevel
);
2323 if (NewToken
) ObDereferenceObject(NewToken
);
2325 if (CopyOnOpen
&& NewThread
) ObDereferenceObject(NewThread
);
2327 if(NT_SUCCESS(Status
))
2331 *TokenHandle
= hToken
;
2333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2335 Status
= _SEH2_GetExceptionCode();
2347 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2348 IN ACCESS_MASK DesiredAccess
,
2349 IN BOOLEAN OpenAsSelf
,
2350 OUT PHANDLE TokenHandle
)
2352 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2363 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2364 IN HANDLE SecondTokenHandle
,
2367 KPROCESSOR_MODE PreviousMode
;
2368 PTOKEN FirstToken
, SecondToken
;
2374 PreviousMode
= ExGetPreviousMode();
2376 if (PreviousMode
!= KernelMode
)
2380 ProbeForWriteBoolean(Equal
);
2382 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2384 /* Return the exception code */
2385 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2390 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2394 (PVOID
*)&FirstToken
,
2396 if (!NT_SUCCESS(Status
))
2399 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2403 (PVOID
*)&SecondToken
,
2405 if (!NT_SUCCESS(Status
))
2407 ObDereferenceObject(FirstToken
);
2411 if (FirstToken
!= SecondToken
)
2413 Status
= SepCompareTokens(FirstToken
,
2420 ObDereferenceObject(FirstToken
);
2421 ObDereferenceObject(SecondToken
);
2423 if (NT_SUCCESS(Status
))
2429 _SEH2_EXCEPT(ExSystemExceptionFilter())
2431 Status
= _SEH2_GetExceptionCode();
2441 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2443 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2444 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2445 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2446 OUT PHANDLE NewTokenHandle
)
2449 return STATUS_NOT_IMPLEMENTED
;
2457 NtImpersonateAnonymousToken(IN HANDLE Thread
)
2460 return STATUS_NOT_IMPLEMENTED
;