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 static GENERIC_MAPPING SepTokenMapping
= {TOKEN_READ
,
30 static const INFORMATION_CLASS_INFO SeTokenInformationClass
[] = {
32 /* Class 0 not used, blame M$! */
33 ICI_SQ_SAME( 0, 0, 0),
36 ICI_SQ_SAME( sizeof(TOKEN_USER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
38 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
40 ICI_SQ_SAME( sizeof(TOKEN_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
42 ICI_SQ_SAME( sizeof(TOKEN_OWNER
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
43 /* TokenPrimaryGroup */
44 ICI_SQ_SAME( sizeof(TOKEN_PRIMARY_GROUP
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
45 /* TokenDefaultDacl */
46 ICI_SQ_SAME( sizeof(TOKEN_DEFAULT_DACL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
48 ICI_SQ_SAME( sizeof(TOKEN_SOURCE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
50 ICI_SQ_SAME( sizeof(TOKEN_TYPE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
51 /* TokenImpersonationLevel */
52 ICI_SQ_SAME( sizeof(SECURITY_IMPERSONATION_LEVEL
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
54 ICI_SQ_SAME( sizeof(TOKEN_STATISTICS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
| ICIF_SET
| ICIF_SET_SIZE_VARIABLE
),
55 /* TokenRestrictedSids */
56 ICI_SQ_SAME( sizeof(TOKEN_GROUPS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
58 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
),
59 /* TokenGroupsAndPrivileges */
60 ICI_SQ_SAME( sizeof(TOKEN_GROUPS_AND_PRIVILEGES
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
61 /* TokenSessionReference */
62 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
63 /* TokenSandBoxInert */
64 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
65 /* TokenAuditPolicy */
66 ICI_SQ_SAME( /* FIXME */0, sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
68 ICI_SQ_SAME( sizeof(TOKEN_ORIGIN
), sizeof(ULONG
), ICIF_QUERY
| ICIF_QUERY_SIZE_VARIABLE
),
71 /* FUNCTIONS *****************************************************************/
74 SepCompareTokens(IN PTOKEN FirstToken
,
75 IN PTOKEN SecondToken
,
78 BOOLEAN Restricted
, IsEqual
= FALSE
;
80 ASSERT(FirstToken
!= SecondToken
);
82 /* FIXME: Check if every SID that is present in either token is also present in the other one */
84 Restricted
= SeTokenIsRestricted(FirstToken
);
85 if (Restricted
== SeTokenIsRestricted(SecondToken
))
89 /* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
92 /* FIXME: Check if every privilege that is present in either token is also present in the other one */
96 return STATUS_SUCCESS
;
101 SepFreeProxyData(PVOID ProxyData
)
108 SepCopyProxyData(PVOID
* Dest
, PVOID Src
)
111 return(STATUS_NOT_IMPLEMENTED
);
116 SeExchangePrimaryToken(PEPROCESS Process
,
117 PACCESS_TOKEN NewTokenP
,
118 PACCESS_TOKEN
* OldTokenP
)
121 PTOKEN NewToken
= (PTOKEN
)NewTokenP
;
125 if (NewToken
->TokenType
!= TokenPrimary
) return(STATUS_BAD_TOKEN_TYPE
);
126 if (NewToken
->TokenInUse
) return(STATUS_TOKEN_ALREADY_IN_USE
);
128 /* Mark new token in use */
129 NewToken
->TokenInUse
= 1;
131 /* Reference the New Token */
132 ObReferenceObject(NewToken
);
134 /* Replace the old with the new */
135 OldToken
= ObFastReplaceObject(&Process
->Token
, NewToken
);
137 /* Mark the Old Token as free */
138 OldToken
->TokenInUse
= 0;
140 *OldTokenP
= (PACCESS_TOKEN
)OldToken
;
141 return STATUS_SUCCESS
;
146 SeDeassignPrimaryToken(PEPROCESS Process
)
150 /* Remove the Token */
151 OldToken
= ObFastReplaceObject(&Process
->Token
, NULL
);
153 /* Mark the Old Token as free */
154 OldToken
->TokenInUse
= 0;
158 RtlLengthSidAndAttributes(ULONG Count
,
159 PSID_AND_ATTRIBUTES Src
)
166 uLength
= Count
* sizeof(SID_AND_ATTRIBUTES
);
167 for (i
= 0; i
< Count
; i
++)
168 uLength
+= RtlLengthSid(Src
[i
].Sid
);
176 SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token
,
182 Token
->PrimaryGroup
= 0;
186 Token
->DefaultOwnerIndex
= Token
->UserAndGroupCount
;
189 /* Validate and set the primary group and user pointers */
190 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
193 RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, DefaultOwner
))
195 Token
->DefaultOwnerIndex
= i
;
198 if (RtlEqualSid(Token
->UserAndGroups
[i
].Sid
, PrimaryGroup
))
200 Token
->PrimaryGroup
= Token
->UserAndGroups
[i
].Sid
;
204 if (Token
->DefaultOwnerIndex
== Token
->UserAndGroupCount
)
206 return(STATUS_INVALID_OWNER
);
209 if (Token
->PrimaryGroup
== 0)
211 return(STATUS_INVALID_PRIMARY_GROUP
);
214 return(STATUS_SUCCESS
);
220 SepDuplicateToken(PTOKEN Token
,
221 POBJECT_ATTRIBUTES ObjectAttributes
,
222 BOOLEAN EffectiveOnly
,
223 TOKEN_TYPE TokenType
,
224 SECURITY_IMPERSONATION_LEVEL Level
,
225 KPROCESSOR_MODE PreviousMode
,
226 PTOKEN
* NewAccessToken
)
236 Status
= ObCreateObject(PreviousMode
,
244 (PVOID
*)&AccessToken
);
245 if (!NT_SUCCESS(Status
))
247 DPRINT1("ObCreateObject() failed (Status %lx)\n");
251 /* Zero out the buffer */
252 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
254 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
255 if (!NT_SUCCESS(Status
))
257 ObDereferenceObject(AccessToken
);
261 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
262 if (!NT_SUCCESS(Status
))
264 ObDereferenceObject(AccessToken
);
268 AccessToken
->TokenLock
= &SepTokenLock
;
270 AccessToken
->TokenType
= TokenType
;
271 AccessToken
->ImpersonationLevel
= Level
;
272 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
274 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
275 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
276 memcpy(AccessToken
->TokenSource
.SourceName
,
277 Token
->TokenSource
.SourceName
,
278 sizeof(Token
->TokenSource
.SourceName
));
279 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
280 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
281 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
283 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
284 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
285 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
287 AccessToken
->UserAndGroups
=
288 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
290 TAG('T', 'O', 'K', 'u'));
292 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
294 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
295 Token
->UserAndGroups
,
297 AccessToken
->UserAndGroups
,
301 if (NT_SUCCESS(Status
))
303 Status
= SepFindPrimaryGroupAndDefaultOwner(
309 if (NT_SUCCESS(Status
))
311 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
313 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
314 AccessToken
->Privileges
=
315 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
317 TAG('T', 'O', 'K', 'p'));
319 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
321 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
322 &Token
->Privileges
[i
].Luid
);
323 AccessToken
->Privileges
[i
].Attributes
=
324 Token
->Privileges
[i
].Attributes
;
327 if ( Token
->DefaultDacl
)
329 AccessToken
->DefaultDacl
=
330 (PACL
) ExAllocatePoolWithTag(PagedPool
,
331 Token
->DefaultDacl
->AclSize
,
332 TAG('T', 'O', 'K', 'd'));
333 memcpy(AccessToken
->DefaultDacl
,
335 Token
->DefaultDacl
->AclSize
);
339 if ( NT_SUCCESS(Status
) )
341 *NewAccessToken
= AccessToken
;
342 return(STATUS_SUCCESS
);
350 SeSubProcessToken(IN PTOKEN ParentToken
,
356 OBJECT_ATTRIBUTES ObjectAttributes
;
359 /* Initialize the attributes and duplicate it */
360 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
361 Status
= SepDuplicateToken(ParentToken
,
365 ParentToken
->ImpersonationLevel
,
368 if (NT_SUCCESS(Status
))
371 Status
= ObInsertObject(NewToken
,
377 if (NT_SUCCESS(Status
))
379 /* Set the session ID */
380 NewToken
->SessionId
= SessionId
;
381 NewToken
->TokenInUse
= InUse
;
383 /* Return the token */
394 SeIsTokenChild(IN PTOKEN Token
,
395 OUT PBOOLEAN IsChild
)
398 LUID ProcessLuid
, CallerLuid
;
403 /* Reference the process token */
404 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
407 ProcessLuid
= ProcessToken
->TokenId
;
409 /* Dereference the token */
410 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
413 CallerLuid
= Token
->TokenId
;
415 /* Compare the LUIDs */
416 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
419 return STATUS_SUCCESS
;
424 SeCopyClientToken(IN PACCESS_TOKEN Token
,
425 IN SECURITY_IMPERSONATION_LEVEL Level
,
426 IN KPROCESSOR_MODE PreviousMode
,
427 OUT PACCESS_TOKEN
* NewToken
)
430 OBJECT_ATTRIBUTES ObjectAttributes
;
434 InitializeObjectAttributes(&ObjectAttributes
,
439 Status
= SepDuplicateToken(Token
,
451 SepDeleteToken(PVOID ObjectBody
)
453 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
455 if (AccessToken
->UserAndGroups
)
456 ExFreePool(AccessToken
->UserAndGroups
);
458 if (AccessToken
->Privileges
)
459 ExFreePool(AccessToken
->Privileges
);
461 if (AccessToken
->DefaultDacl
)
462 ExFreePool(AccessToken
->DefaultDacl
);
469 SepInitializeTokenImplementation(VOID
)
472 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
474 ExInitializeResource(&SepTokenLock
);
476 DPRINT("Creating Token Object Type\n");
478 /* Initialize the Token type */
479 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
480 RtlInitUnicodeString(&Name
, L
"Token");
481 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
482 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
483 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
484 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
485 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
486 ObjectTypeInitializer
.PoolType
= PagedPool
;
487 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
488 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
489 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
490 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SepTokenObjectType
);
495 SeAssignPrimaryToken(IN PEPROCESS Process
,
501 ASSERT(Token
->TokenType
== TokenPrimary
);
502 ASSERT(!Token
->TokenInUse
);
504 /* Clean any previous token */
505 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
507 /* Set the new token */
508 ObReferenceObject(Token
);
509 Token
->TokenInUse
= TRUE
;
510 ObInitializeFastReference(&Process
->Token
, Token
);
515 SepCreateSystemProcessToken(VOID
)
520 ULONG uLocalSystemLength
;
522 ULONG uAuthUserLength
;
529 uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
530 uWorldLength
= RtlLengthSid(SeWorldSid
);
531 uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
532 uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
535 * Initialize the token
537 Status
= ObCreateObject(KernelMode
,
545 (PVOID
*)&AccessToken
);
546 if (!NT_SUCCESS(Status
))
551 /* Zero out the buffer */
552 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
554 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
555 if (!NT_SUCCESS(Status
))
557 ObDereferenceObject(AccessToken
);
561 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
562 if (!NT_SUCCESS(Status
))
564 ObDereferenceObject(AccessToken
);
568 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
569 if (!NT_SUCCESS(Status
))
571 ObDereferenceObject(AccessToken
);
575 AccessToken
->TokenLock
= &SepTokenLock
;
577 AccessToken
->TokenType
= TokenPrimary
;
578 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
579 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
580 AccessToken
->ExpirationTime
.QuadPart
= -1;
581 AccessToken
->UserAndGroupCount
= 4;
583 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
584 uSize
+= uLocalSystemLength
;
585 uSize
+= uWorldLength
;
586 uSize
+= uAuthUserLength
;
587 uSize
+= uAdminsLength
;
589 AccessToken
->UserAndGroups
=
590 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
592 TAG('T', 'O', 'K', 'u'));
593 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
596 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
597 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
598 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
599 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
601 AccessToken
->DefaultOwnerIndex
= i
;
602 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
603 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
604 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
605 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
606 SidArea
= (char*)SidArea
+ uAdminsLength
;
608 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
609 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
610 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
611 SidArea
= (char*)SidArea
+ uWorldLength
;
613 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
614 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
615 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
616 SidArea
= (char*)SidArea
+ uAuthUserLength
;
618 AccessToken
->PrivilegeCount
= 20;
620 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
621 AccessToken
->Privileges
=
622 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
624 TAG('T', 'O', 'K', 'p'));
627 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
628 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
630 AccessToken
->Privileges
[i
].Attributes
= 0;
631 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
633 AccessToken
->Privileges
[i
].Attributes
= 0;
634 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
636 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
637 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
639 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
640 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
642 AccessToken
->Privileges
[i
].Attributes
= 0;
643 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
645 AccessToken
->Privileges
[i
].Attributes
= 0;
646 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
648 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
649 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
651 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
652 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
654 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
655 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
657 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
658 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
660 AccessToken
->Privileges
[i
].Attributes
= 0;
661 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
663 AccessToken
->Privileges
[i
].Attributes
= 0;
664 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
666 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
667 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
669 AccessToken
->Privileges
[i
].Attributes
= 0;
670 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
672 AccessToken
->Privileges
[i
].Attributes
= 0;
673 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
675 AccessToken
->Privileges
[i
].Attributes
= 0;
676 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
678 AccessToken
->Privileges
[i
].Attributes
= 0;
679 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
681 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
682 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
684 AccessToken
->Privileges
[i
].Attributes
= 0;
685 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
687 AccessToken
->Privileges
[i
].Attributes
= 0;
688 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
690 AccessToken
->Privileges
[i
].Attributes
= 0;
691 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
697 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
698 uSize
+= sizeof(ACE
) + uAdminsLength
;
699 uSize
= (uSize
& (~3)) + 8;
700 AccessToken
->DefaultDacl
=
701 (PACL
) ExAllocatePoolWithTag(PagedPool
,
703 TAG('T', 'O', 'K', 'd'));
704 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
705 if ( NT_SUCCESS(Status
) )
707 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
710 if ( NT_SUCCESS(Status
) )
712 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
715 if ( ! NT_SUCCESS(Status
) )
717 ObDereferenceObject(AccessToken
);
724 /* PUBLIC FUNCTIONS ***********************************************************/
731 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
733 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
734 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
735 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
736 OUT PACCESS_TOKEN
* FilteredToken
)
739 return STATUS_NOT_IMPLEMENTED
;
747 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
748 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
749 OUT PVOID
*TokenInformation
)
752 return STATUS_NOT_IMPLEMENTED
;
760 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
761 IN PULONG pSessionId
)
763 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
764 return STATUS_SUCCESS
;
771 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
776 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
778 return STATUS_SUCCESS
;
785 SECURITY_IMPERSONATION_LEVEL
787 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
791 return ((PTOKEN
)Token
)->ImpersonationLevel
;
799 SeTokenType(IN PACCESS_TOKEN Token
)
803 return ((PTOKEN
)Token
)->TokenType
;
812 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
815 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
823 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
826 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
834 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
837 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
840 /* SYSTEM CALLS ***************************************************************/
846 NtQueryInformationToken(IN HANDLE TokenHandle
,
847 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
848 OUT PVOID TokenInformation
,
849 IN ULONG TokenInformationLength
,
850 OUT PULONG ReturnLength
)
858 ULONG RequiredLength
;
859 KPROCESSOR_MODE PreviousMode
;
860 NTSTATUS Status
= STATUS_SUCCESS
;
864 PreviousMode
= ExGetPreviousMode();
866 /* Check buffers and class validity */
867 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
868 SeTokenInformationClass
,
869 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
871 TokenInformationLength
,
875 if(!NT_SUCCESS(Status
))
877 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
881 Status
= ObReferenceObjectByHandle(TokenHandle
,
882 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
887 if (NT_SUCCESS(Status
))
889 switch (TokenInformationClass
)
893 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
895 DPRINT("NtQueryInformationToken(TokenUser)\n");
896 RequiredLength
= sizeof(TOKEN_USER
) +
897 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
901 if(TokenInformationLength
>= RequiredLength
)
903 Status
= RtlCopySidAndAttributesArray(1,
904 &Token
->UserAndGroups
[0],
905 RequiredLength
- sizeof(TOKEN_USER
),
913 Status
= STATUS_BUFFER_TOO_SMALL
;
916 if(ReturnLength
!= NULL
)
918 *ReturnLength
= RequiredLength
;
921 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
923 Status
= _SEH2_GetExceptionCode();
932 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
934 DPRINT("NtQueryInformationToken(TokenGroups)\n");
935 RequiredLength
= sizeof(tg
->GroupCount
) +
936 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
940 if(TokenInformationLength
>= RequiredLength
)
942 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
943 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
944 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
945 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
947 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
948 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
949 &Token
->UserAndGroups
[1],
958 Status
= STATUS_BUFFER_TOO_SMALL
;
961 if(ReturnLength
!= NULL
)
963 *ReturnLength
= RequiredLength
;
966 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
968 Status
= _SEH2_GetExceptionCode();
975 case TokenPrivileges
:
977 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
979 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
980 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
981 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
985 if(TokenInformationLength
>= RequiredLength
)
987 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
988 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
994 Status
= STATUS_BUFFER_TOO_SMALL
;
997 if(ReturnLength
!= NULL
)
999 *ReturnLength
= RequiredLength
;
1002 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1004 Status
= _SEH2_GetExceptionCode();
1014 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1016 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1017 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1018 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1022 if(TokenInformationLength
>= RequiredLength
)
1024 to
->Owner
= (PSID
)(to
+ 1);
1025 Status
= RtlCopySid(SidLen
,
1027 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1031 Status
= STATUS_BUFFER_TOO_SMALL
;
1034 if(ReturnLength
!= NULL
)
1036 *ReturnLength
= RequiredLength
;
1039 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1041 Status
= _SEH2_GetExceptionCode();
1048 case TokenPrimaryGroup
:
1051 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1053 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1054 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1055 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1059 if(TokenInformationLength
>= RequiredLength
)
1061 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1062 Status
= RtlCopySid(SidLen
,
1064 Token
->PrimaryGroup
);
1068 Status
= STATUS_BUFFER_TOO_SMALL
;
1071 if(ReturnLength
!= NULL
)
1073 *ReturnLength
= RequiredLength
;
1076 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1078 Status
= _SEH2_GetExceptionCode();
1085 case TokenDefaultDacl
:
1087 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1089 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1090 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1092 if(Token
->DefaultDacl
!= NULL
)
1094 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1099 if(TokenInformationLength
>= RequiredLength
)
1101 if(Token
->DefaultDacl
!= NULL
)
1103 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1104 RtlCopyMemory(tdd
->DefaultDacl
,
1106 Token
->DefaultDacl
->AclSize
);
1110 tdd
->DefaultDacl
= NULL
;
1115 Status
= STATUS_BUFFER_TOO_SMALL
;
1118 if(ReturnLength
!= NULL
)
1120 *ReturnLength
= RequiredLength
;
1123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1125 Status
= _SEH2_GetExceptionCode();
1134 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1136 DPRINT("NtQueryInformationToken(TokenSource)\n");
1137 RequiredLength
= sizeof(TOKEN_SOURCE
);
1141 if(TokenInformationLength
>= RequiredLength
)
1143 *ts
= Token
->TokenSource
;
1147 Status
= STATUS_BUFFER_TOO_SMALL
;
1150 if(ReturnLength
!= NULL
)
1152 *ReturnLength
= RequiredLength
;
1155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1157 Status
= _SEH2_GetExceptionCode();
1166 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1168 DPRINT("NtQueryInformationToken(TokenType)\n");
1169 RequiredLength
= sizeof(TOKEN_TYPE
);
1173 if(TokenInformationLength
>= RequiredLength
)
1175 *tt
= Token
->TokenType
;
1179 Status
= STATUS_BUFFER_TOO_SMALL
;
1182 if(ReturnLength
!= NULL
)
1184 *ReturnLength
= RequiredLength
;
1187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1189 Status
= _SEH2_GetExceptionCode();
1196 case TokenImpersonationLevel
:
1198 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1200 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1201 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1205 if(TokenInformationLength
>= RequiredLength
)
1207 *sil
= Token
->ImpersonationLevel
;
1211 Status
= STATUS_BUFFER_TOO_SMALL
;
1214 if(ReturnLength
!= NULL
)
1216 *ReturnLength
= RequiredLength
;
1219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1221 Status
= _SEH2_GetExceptionCode();
1228 case TokenStatistics
:
1230 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1232 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1233 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1237 if(TokenInformationLength
>= RequiredLength
)
1239 ts
->TokenId
= Token
->TokenId
;
1240 ts
->AuthenticationId
= Token
->AuthenticationId
;
1241 ts
->ExpirationTime
= Token
->ExpirationTime
;
1242 ts
->TokenType
= Token
->TokenType
;
1243 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1244 ts
->DynamicCharged
= Token
->DynamicCharged
;
1245 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1246 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1247 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1248 ts
->ModifiedId
= Token
->ModifiedId
;
1252 Status
= STATUS_BUFFER_TOO_SMALL
;
1255 if(ReturnLength
!= NULL
)
1257 *ReturnLength
= RequiredLength
;
1260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1262 Status
= _SEH2_GetExceptionCode();
1271 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1273 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1274 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1278 if(TokenInformationLength
>= RequiredLength
)
1280 RtlCopyLuid(&to
->OriginatingLogonSession
,
1281 &Token
->AuthenticationId
);
1285 Status
= STATUS_BUFFER_TOO_SMALL
;
1288 if(ReturnLength
!= NULL
)
1290 *ReturnLength
= RequiredLength
;
1293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1295 Status
= _SEH2_GetExceptionCode();
1302 case TokenGroupsAndPrivileges
:
1303 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1304 Status
= STATUS_NOT_IMPLEMENTED
;
1307 case TokenRestrictedSids
:
1309 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1311 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1312 RequiredLength
= sizeof(tg
->GroupCount
) +
1313 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1317 if(TokenInformationLength
>= RequiredLength
)
1319 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1320 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1321 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1322 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1324 tg
->GroupCount
= Token
->RestrictedSidCount
;
1325 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1326 Token
->RestrictedSids
,
1335 Status
= STATUS_BUFFER_TOO_SMALL
;
1338 if(ReturnLength
!= NULL
)
1340 *ReturnLength
= RequiredLength
;
1343 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1345 Status
= _SEH2_GetExceptionCode();
1352 case TokenSandBoxInert
:
1353 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1354 Status
= STATUS_NOT_IMPLEMENTED
;
1357 case TokenSessionId
:
1359 ULONG SessionId
= 0;
1361 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1363 Status
= SeQuerySessionIdToken(Token
,
1366 if(NT_SUCCESS(Status
))
1370 /* buffer size was already verified, no need to check here again */
1371 *(PULONG
)TokenInformation
= SessionId
;
1373 if(ReturnLength
!= NULL
)
1375 *ReturnLength
= sizeof(ULONG
);
1378 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1380 Status
= _SEH2_GetExceptionCode();
1389 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1390 Status
= STATUS_INVALID_INFO_CLASS
;
1394 ObDereferenceObject(Token
);
1402 * NtSetTokenInformation: Partly implemented.
1404 * TokenOrigin, TokenDefaultDacl
1408 NtSetInformationToken(IN HANDLE TokenHandle
,
1409 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1410 OUT PVOID TokenInformation
,
1411 IN ULONG TokenInformationLength
)
1414 KPROCESSOR_MODE PreviousMode
;
1415 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1416 NTSTATUS Status
= STATUS_SUCCESS
;
1420 PreviousMode
= ExGetPreviousMode();
1422 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1423 SeTokenInformationClass
,
1424 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1426 TokenInformationLength
,
1429 if(!NT_SUCCESS(Status
))
1431 /* Invalid buffers */
1432 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1436 if(TokenInformationClass
== TokenSessionId
)
1438 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1441 Status
= ObReferenceObjectByHandle(TokenHandle
,
1447 if (NT_SUCCESS(Status
))
1449 switch (TokenInformationClass
)
1453 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1455 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1456 PSID InputSid
= NULL
;
1460 InputSid
= to
->Owner
;
1462 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1464 Status
= _SEH2_GetExceptionCode();
1468 if(NT_SUCCESS(Status
))
1472 Status
= SepCaptureSid(InputSid
,
1477 if(NT_SUCCESS(Status
))
1479 RtlCopySid(RtlLengthSid(CapturedSid
),
1480 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1482 SepReleaseSid(CapturedSid
,
1490 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1495 case TokenPrimaryGroup
:
1497 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1499 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1500 PSID InputSid
= NULL
;
1504 InputSid
= tpg
->PrimaryGroup
;
1506 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1508 Status
= _SEH2_GetExceptionCode();
1512 if(NT_SUCCESS(Status
))
1516 Status
= SepCaptureSid(InputSid
,
1521 if(NT_SUCCESS(Status
))
1523 RtlCopySid(RtlLengthSid(CapturedSid
),
1524 Token
->PrimaryGroup
,
1526 SepReleaseSid(CapturedSid
,
1534 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1539 case TokenDefaultDacl
:
1541 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1543 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1544 PACL InputAcl
= NULL
;
1548 InputAcl
= tdd
->DefaultDacl
;
1550 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1552 Status
= _SEH2_GetExceptionCode();
1556 if(NT_SUCCESS(Status
))
1558 if(InputAcl
!= NULL
)
1562 /* capture and copy the dacl */
1563 Status
= SepCaptureAcl(InputAcl
,
1568 if(NT_SUCCESS(Status
))
1570 /* free the previous dacl if present */
1571 if(Token
->DefaultDacl
!= NULL
)
1573 ExFreePool(Token
->DefaultDacl
);
1576 /* set the new dacl */
1577 Token
->DefaultDacl
= CapturedAcl
;
1582 /* clear and free the default dacl if present */
1583 if(Token
->DefaultDacl
!= NULL
)
1585 ExFreePool(Token
->DefaultDacl
);
1586 Token
->DefaultDacl
= NULL
;
1593 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1598 case TokenSessionId
:
1600 ULONG SessionId
= 0;
1604 /* buffer size was already verified, no need to check here again */
1605 SessionId
= *(PULONG
)TokenInformation
;
1607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1609 Status
= _SEH2_GetExceptionCode();
1613 if(NT_SUCCESS(Status
))
1615 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1618 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1622 Token
->SessionId
= SessionId
;
1629 Status
= STATUS_NOT_IMPLEMENTED
;
1634 ObDereferenceObject(Token
);
1644 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1645 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1646 * is correct either. -Gunnar
1647 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1650 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1651 IN ACCESS_MASK DesiredAccess
,
1652 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1653 IN BOOLEAN EffectiveOnly
,
1654 IN TOKEN_TYPE TokenType
,
1655 OUT PHANDLE NewTokenHandle
)
1657 KPROCESSOR_MODE PreviousMode
;
1661 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1663 NTSTATUS Status
= STATUS_SUCCESS
;
1667 PreviousMode
= KeGetPreviousMode();
1669 if(PreviousMode
!= KernelMode
)
1673 ProbeForWriteHandle(NewTokenHandle
);
1675 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1677 Status
= _SEH2_GetExceptionCode();
1681 if(!NT_SUCCESS(Status
))
1687 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1691 &CapturedSecurityQualityOfService
,
1693 if(!NT_SUCCESS(Status
))
1695 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1699 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1705 if (NT_SUCCESS(Status
))
1707 Status
= SepDuplicateToken(Token
,
1711 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1715 ObDereferenceObject(Token
);
1717 if (NT_SUCCESS(Status
))
1719 Status
= ObInsertObject((PVOID
)NewToken
,
1726 if (NT_SUCCESS(Status
))
1730 *NewTokenHandle
= hToken
;
1732 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1734 Status
= _SEH2_GetExceptionCode();
1741 /* free the captured structure */
1742 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1750 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1751 IN BOOLEAN ResetToDefault
,
1752 IN PTOKEN_GROUPS NewState
,
1753 IN ULONG BufferLength
,
1754 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1755 OUT PULONG ReturnLength
)
1758 return(STATUS_NOT_IMPLEMENTED
);
1765 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1766 IN BOOLEAN DisableAllPrivileges
,
1767 IN PTOKEN_PRIVILEGES NewState
,
1768 IN ULONG BufferLength
,
1769 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1770 OUT PULONG ReturnLength OPTIONAL
)
1772 // PLUID_AND_ATTRIBUTES Privileges;
1773 KPROCESSOR_MODE PreviousMode
;
1774 ULONG PrivilegeCount
;
1790 DPRINT ("NtAdjustPrivilegesToken() called\n");
1792 // PrivilegeCount = NewState->PrivilegeCount;
1793 PreviousMode
= KeGetPreviousMode ();
1794 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1804 Status
= ObReferenceObjectByHandle (TokenHandle
,
1805 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1810 if (!NT_SUCCESS(Status
))
1812 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1813 // SeReleaseLuidAndAttributesArray(Privileges,
1821 SepAdjustPrivileges(Token
,
1832 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1833 sizeof(LUID_AND_ATTRIBUTES
);
1835 if (PreviousState
!= NULL
)
1836 PreviousState
->PrivilegeCount
= 0;
1839 if (DisableAllPrivileges
== TRUE
)
1841 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1843 if (Token
->Privileges
[i
].Attributes
!= 0)
1845 DPRINT ("Attributes differ\n");
1847 /* Save current privilege */
1848 if (PreviousState
!= NULL
)
1850 if (k
< PrivilegeCount
)
1852 PreviousState
->PrivilegeCount
++;
1853 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1854 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1858 /* FIXME: Should revert all the changes, calculate how
1859 * much space would be needed, set ResultLength
1860 * accordingly and fail.
1866 /* Update current privlege */
1867 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1870 Status
= STATUS_SUCCESS
;
1875 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1877 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1879 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1880 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1882 DPRINT ("Found privilege\n");
1884 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1885 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1887 DPRINT ("Attributes differ\n");
1888 DPRINT ("Current attributes %lx desired attributes %lx\n",
1889 Token
->Privileges
[i
].Attributes
,
1890 NewState
->Privileges
[j
].Attributes
);
1892 /* Save current privilege */
1893 if (PreviousState
!= NULL
)
1895 if (k
< PrivilegeCount
)
1897 PreviousState
->PrivilegeCount
++;
1898 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1899 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1903 /* FIXME: Should revert all the changes, calculate how
1904 * much space would be needed, set ResultLength
1905 * accordingly and fail.
1911 /* Update current privlege */
1912 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1913 Token
->Privileges
[i
].Attributes
|=
1914 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1915 DPRINT ("New attributes %lx\n",
1916 Token
->Privileges
[i
].Attributes
);
1922 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1925 if (ReturnLength
!= NULL
)
1927 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1928 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1931 ObDereferenceObject (Token
);
1933 // SeReleaseLuidAndAttributesArray(Privileges,
1937 DPRINT ("NtAdjustPrivilegesToken() done\n");
1943 NtCreateToken(OUT PHANDLE TokenHandle
,
1944 IN ACCESS_MASK DesiredAccess
,
1945 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1946 IN TOKEN_TYPE TokenType
,
1947 IN PLUID AuthenticationId
,
1948 IN PLARGE_INTEGER ExpirationTime
,
1949 IN PTOKEN_USER TokenUser
,
1950 IN PTOKEN_GROUPS TokenGroups
,
1951 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1952 IN PTOKEN_OWNER TokenOwner
,
1953 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1954 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1955 IN PTOKEN_SOURCE TokenSource
)
1964 KPROCESSOR_MODE PreviousMode
;
1965 ULONG nTokenPrivileges
= 0;
1966 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
1967 NTSTATUS Status
= STATUS_SUCCESS
;
1971 PreviousMode
= ExGetPreviousMode();
1973 if(PreviousMode
!= KernelMode
)
1977 ProbeForWriteHandle(TokenHandle
);
1978 ProbeForRead(AuthenticationId
,
1981 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
1982 ProbeForRead(TokenUser
,
1985 ProbeForRead(TokenGroups
,
1986 sizeof(TOKEN_GROUPS
),
1988 ProbeForRead(TokenPrivileges
,
1989 sizeof(TOKEN_PRIVILEGES
),
1991 ProbeForRead(TokenOwner
,
1992 sizeof(TOKEN_OWNER
),
1994 ProbeForRead(TokenPrimaryGroup
,
1995 sizeof(TOKEN_PRIMARY_GROUP
),
1997 ProbeForRead(TokenDefaultDacl
,
1998 sizeof(TOKEN_DEFAULT_DACL
),
2000 ProbeForRead(TokenSource
,
2001 sizeof(TOKEN_SOURCE
),
2003 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2005 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2007 Status
= _SEH2_GetExceptionCode();
2011 if(!NT_SUCCESS(Status
))
2018 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2019 LocalExpirationTime
= *ExpirationTime
;
2022 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2023 if (!NT_SUCCESS(Status
))
2026 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2027 if (!NT_SUCCESS(Status
))
2030 Status
= ObCreateObject(PreviousMode
,
2038 (PVOID
*)&AccessToken
);
2039 if (!NT_SUCCESS(Status
))
2041 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2045 /* Zero out the buffer */
2046 RtlZeroMemory(AccessToken
, sizeof(TOKEN
));
2048 AccessToken
->TokenLock
= &SepTokenLock
;
2050 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2051 &TokenSource
->SourceIdentifier
);
2052 memcpy(AccessToken
->TokenSource
.SourceName
,
2053 TokenSource
->SourceName
,
2054 sizeof(TokenSource
->SourceName
));
2056 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2057 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2058 AccessToken
->ExpirationTime
= *ExpirationTime
;
2059 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2061 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2062 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2064 AccessToken
->TokenType
= TokenType
;
2065 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2066 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2069 * Normally we would just point these members into the variable information
2070 * area; however, our ObCreateObject() call can't allocate a variable information
2071 * area, so we allocate them seperately and provide a destroy function.
2074 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2075 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2076 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2077 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2079 AccessToken
->UserAndGroups
=
2080 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2082 TAG('T', 'O', 'K', 'u'));
2084 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2086 Status
= RtlCopySidAndAttributesArray(1,
2089 AccessToken
->UserAndGroups
,
2093 if (NT_SUCCESS(Status
))
2095 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2096 TokenGroups
->Groups
,
2098 &AccessToken
->UserAndGroups
[1],
2104 if (NT_SUCCESS(Status
))
2106 Status
= SepFindPrimaryGroupAndDefaultOwner(
2108 TokenPrimaryGroup
->PrimaryGroup
,
2112 if (NT_SUCCESS(Status
))
2114 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2115 AccessToken
->Privileges
=
2116 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2118 TAG('T', 'O', 'K', 'p'));
2120 if (PreviousMode
!= KernelMode
)
2124 RtlCopyMemory(AccessToken
->Privileges
,
2125 TokenPrivileges
->Privileges
,
2126 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2128 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2130 Status
= _SEH2_GetExceptionCode();
2136 RtlCopyMemory(AccessToken
->Privileges
,
2137 TokenPrivileges
->Privileges
,
2138 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2142 if (NT_SUCCESS(Status
))
2144 AccessToken
->DefaultDacl
=
2145 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2146 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2147 TAG('T', 'O', 'K', 'd'));
2148 memcpy(AccessToken
->DefaultDacl
,
2149 TokenDefaultDacl
->DefaultDacl
,
2150 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2153 Status
= ObInsertObject ((PVOID
)AccessToken
,
2159 if (!NT_SUCCESS(Status
))
2161 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2164 if (NT_SUCCESS(Status
))
2168 *TokenHandle
= hToken
;
2170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2172 Status
= _SEH2_GetExceptionCode();
2185 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2186 IN ACCESS_MASK DesiredAccess
,
2187 IN BOOLEAN OpenAsSelf
,
2188 IN ULONG HandleAttributes
,
2189 OUT PHANDLE TokenHandle
)
2193 PTOKEN Token
, NewToken
, PrimaryToken
;
2194 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2195 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2196 SE_IMPERSONATION_STATE ImpersonationState
;
2197 OBJECT_ATTRIBUTES ObjectAttributes
;
2198 SECURITY_DESCRIPTOR SecurityDescriptor
;
2200 KPROCESSOR_MODE PreviousMode
;
2201 NTSTATUS Status
= STATUS_SUCCESS
;
2205 PreviousMode
= ExGetPreviousMode();
2207 if(PreviousMode
!= KernelMode
)
2211 ProbeForWriteHandle(TokenHandle
);
2213 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2215 Status
= _SEH2_GetExceptionCode();
2219 if(!NT_SUCCESS(Status
))
2226 * At first open the thread token for information access and verify
2227 * that the token associated with thread is valid.
2230 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_QUERY_INFORMATION
,
2231 PsThreadType
, PreviousMode
, (PVOID
*)&Thread
,
2233 if (!NT_SUCCESS(Status
))
2238 Token
= PsReferenceImpersonationToken(Thread
, &CopyOnOpen
, &EffectiveOnly
,
2239 &ImpersonationLevel
);
2242 ObDereferenceObject(Thread
);
2243 return STATUS_NO_TOKEN
;
2246 ObDereferenceObject(Thread
);
2248 if (ImpersonationLevel
== SecurityAnonymous
)
2250 ObDereferenceObject(Token
);
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
, PreviousMode
,
2267 (PVOID
*)&Thread
, NULL
);
2268 if (!NT_SUCCESS(Status
))
2270 ObDereferenceObject(Token
);
2273 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2278 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2279 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2281 ObDereferenceObject(PrimaryToken
);
2282 ObDereferenceObject(Thread
);
2283 if (!NT_SUCCESS(Status
))
2285 ObDereferenceObject(Token
);
2288 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2293 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2294 SECURITY_DESCRIPTOR_REVISION
);
2295 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2298 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2299 NULL
, &SecurityDescriptor
);
2301 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2302 TokenImpersonation
, ImpersonationLevel
,
2303 KernelMode
, &NewToken
);
2305 if (!NT_SUCCESS(Status
))
2307 ObDereferenceObject(Token
);
2310 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2315 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2321 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2322 NULL
, DesiredAccess
, SepTokenObjectType
,
2323 PreviousMode
, &hToken
);
2326 ObDereferenceObject(Token
);
2330 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2333 if(NT_SUCCESS(Status
))
2337 *TokenHandle
= hToken
;
2339 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2341 Status
= _SEH2_GetExceptionCode();
2353 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2354 IN ACCESS_MASK DesiredAccess
,
2355 IN BOOLEAN OpenAsSelf
,
2356 OUT PHANDLE TokenHandle
)
2358 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2369 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2370 IN HANDLE SecondTokenHandle
,
2373 KPROCESSOR_MODE PreviousMode
;
2374 PTOKEN FirstToken
, SecondToken
;
2376 NTSTATUS Status
= STATUS_SUCCESS
;
2380 PreviousMode
= ExGetPreviousMode();
2382 if (PreviousMode
!= KernelMode
)
2386 ProbeForWriteBoolean(Equal
);
2388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2390 Status
= _SEH2_GetExceptionCode();
2394 if (!NT_SUCCESS(Status
))
2398 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2402 (PVOID
*)&FirstToken
,
2404 if (!NT_SUCCESS(Status
))
2407 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2411 (PVOID
*)&SecondToken
,
2413 if (!NT_SUCCESS(Status
))
2415 ObDereferenceObject(FirstToken
);
2419 if (FirstToken
!= SecondToken
)
2421 Status
= SepCompareTokens(FirstToken
,
2428 ObDereferenceObject(FirstToken
);
2429 ObDereferenceObject(SecondToken
);
2431 if (NT_SUCCESS(Status
))
2437 _SEH2_EXCEPT(ExSystemExceptionFilter())
2439 Status
= _SEH2_GetExceptionCode();
2449 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2451 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2452 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2453 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2454 OUT PHANDLE NewTokenHandle
)
2457 return STATUS_NOT_IMPLEMENTED
;
2465 NtImpersonateAnonymousToken(IN HANDLE Thread
)
2468 return STATUS_NOT_IMPLEMENTED
;