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 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->TokenId
);
252 if (!NT_SUCCESS(Status
))
254 ObDereferenceObject(AccessToken
);
258 Status
= ZwAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
259 if (!NT_SUCCESS(Status
))
261 ObDereferenceObject(AccessToken
);
265 AccessToken
->TokenLock
= &SepTokenLock
;
267 AccessToken
->TokenInUse
= 0;
268 AccessToken
->TokenType
= TokenType
;
269 AccessToken
->ImpersonationLevel
= Level
;
270 RtlCopyLuid(&AccessToken
->AuthenticationId
, &Token
->AuthenticationId
);
272 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= Token
->TokenSource
.SourceIdentifier
.LowPart
;
273 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= Token
->TokenSource
.SourceIdentifier
.HighPart
;
274 memcpy(AccessToken
->TokenSource
.SourceName
,
275 Token
->TokenSource
.SourceName
,
276 sizeof(Token
->TokenSource
.SourceName
));
277 AccessToken
->ExpirationTime
.QuadPart
= Token
->ExpirationTime
.QuadPart
;
278 AccessToken
->UserAndGroupCount
= Token
->UserAndGroupCount
;
279 AccessToken
->DefaultOwnerIndex
= Token
->DefaultOwnerIndex
;
281 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
282 for (i
= 0; i
< Token
->UserAndGroupCount
; i
++)
283 uLength
+= RtlLengthSid(Token
->UserAndGroups
[i
].Sid
);
285 AccessToken
->UserAndGroups
=
286 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
288 TAG('T', 'O', 'K', 'u'));
290 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
292 Status
= RtlCopySidAndAttributesArray(AccessToken
->UserAndGroupCount
,
293 Token
->UserAndGroups
,
295 AccessToken
->UserAndGroups
,
299 if (NT_SUCCESS(Status
))
301 Status
= SepFindPrimaryGroupAndDefaultOwner(
307 if (NT_SUCCESS(Status
))
309 AccessToken
->PrivilegeCount
= Token
->PrivilegeCount
;
311 uLength
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
312 AccessToken
->Privileges
=
313 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
315 TAG('T', 'O', 'K', 'p'));
317 for (i
= 0; i
< AccessToken
->PrivilegeCount
; i
++)
319 RtlCopyLuid(&AccessToken
->Privileges
[i
].Luid
,
320 &Token
->Privileges
[i
].Luid
);
321 AccessToken
->Privileges
[i
].Attributes
=
322 Token
->Privileges
[i
].Attributes
;
325 if ( Token
->DefaultDacl
)
327 AccessToken
->DefaultDacl
=
328 (PACL
) ExAllocatePoolWithTag(PagedPool
,
329 Token
->DefaultDacl
->AclSize
,
330 TAG('T', 'O', 'K', 'd'));
331 memcpy(AccessToken
->DefaultDacl
,
333 Token
->DefaultDacl
->AclSize
);
337 AccessToken
->DefaultDacl
= 0;
341 if ( NT_SUCCESS(Status
) )
343 *NewAccessToken
= AccessToken
;
344 return(STATUS_SUCCESS
);
352 SeSubProcessToken(IN PTOKEN ParentToken
,
358 OBJECT_ATTRIBUTES ObjectAttributes
;
361 /* Initialize the attributes and duplicate it */
362 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
363 Status
= SepDuplicateToken(ParentToken
,
367 ParentToken
->ImpersonationLevel
,
370 if (NT_SUCCESS(Status
))
373 Status
= ObInsertObject(NewToken
,
379 if (NT_SUCCESS(Status
))
381 /* Set the session ID */
382 NewToken
->SessionId
= SessionId
;
383 NewToken
->TokenInUse
= InUse
;
385 /* Return the token */
396 SeIsTokenChild(IN PTOKEN Token
,
397 OUT PBOOLEAN IsChild
)
400 LUID ProcessLuid
, CallerLuid
;
405 /* Reference the process token */
406 ProcessToken
= PsReferencePrimaryToken(PsGetCurrentProcess());
409 ProcessLuid
= ProcessToken
->TokenId
;
411 /* Dereference the token */
412 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, ProcessToken
);
415 CallerLuid
= Token
->TokenId
;
417 /* Compare the LUIDs */
418 if (RtlEqualLuid(&CallerLuid
, &ProcessLuid
)) *IsChild
= TRUE
;
421 return STATUS_SUCCESS
;
426 SeCopyClientToken(IN PACCESS_TOKEN Token
,
427 IN SECURITY_IMPERSONATION_LEVEL Level
,
428 IN KPROCESSOR_MODE PreviousMode
,
429 OUT PACCESS_TOKEN
* NewToken
)
432 OBJECT_ATTRIBUTES ObjectAttributes
;
436 InitializeObjectAttributes(&ObjectAttributes
,
441 Status
= SepDuplicateToken(Token
,
453 SepDeleteToken(PVOID ObjectBody
)
455 PTOKEN AccessToken
= (PTOKEN
)ObjectBody
;
457 if (AccessToken
->UserAndGroups
)
458 ExFreePool(AccessToken
->UserAndGroups
);
460 if (AccessToken
->Privileges
)
461 ExFreePool(AccessToken
->Privileges
);
463 if (AccessToken
->DefaultDacl
)
464 ExFreePool(AccessToken
->DefaultDacl
);
471 SepInitializeTokenImplementation(VOID
)
474 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
476 ExInitializeResource(&SepTokenLock
);
478 DPRINT("Creating Token Object Type\n");
480 /* Initialize the Token type */
481 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
482 RtlInitUnicodeString(&Name
, L
"Token");
483 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
484 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
485 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
486 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(TOKEN
);
487 ObjectTypeInitializer
.GenericMapping
= SepTokenMapping
;
488 ObjectTypeInitializer
.PoolType
= PagedPool
;
489 ObjectTypeInitializer
.ValidAccessMask
= TOKEN_ALL_ACCESS
;
490 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
491 ObjectTypeInitializer
.DeleteProcedure
= SepDeleteToken
;
492 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &SepTokenObjectType
);
497 SeAssignPrimaryToken(IN PEPROCESS Process
,
503 ASSERT(Token
->TokenType
== TokenPrimary
);
504 ASSERT(!Token
->TokenInUse
);
506 /* Clean any previous token */
507 if (Process
->Token
.Object
) SeDeassignPrimaryToken(Process
);
509 /* Set the new token */
510 ObReferenceObject(Token
);
511 Token
->TokenInUse
= TRUE
;
512 ObInitializeFastReference(&Process
->Token
, Token
);
517 SepCreateSystemProcessToken(VOID
)
522 ULONG uLocalSystemLength
;
524 ULONG uAuthUserLength
;
531 uLocalSystemLength
= RtlLengthSid(SeLocalSystemSid
);
532 uWorldLength
= RtlLengthSid(SeWorldSid
);
533 uAuthUserLength
= RtlLengthSid(SeAuthenticatedUserSid
);
534 uAdminsLength
= RtlLengthSid(SeAliasAdminsSid
);
537 * Initialize the token
539 Status
= ObCreateObject(KernelMode
,
547 (PVOID
*)&AccessToken
);
548 if (!NT_SUCCESS(Status
))
553 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->TokenId
);
554 if (!NT_SUCCESS(Status
))
556 ObDereferenceObject(AccessToken
);
560 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->ModifiedId
);
561 if (!NT_SUCCESS(Status
))
563 ObDereferenceObject(AccessToken
);
567 Status
= ExpAllocateLocallyUniqueId(&AccessToken
->AuthenticationId
);
568 if (!NT_SUCCESS(Status
))
570 ObDereferenceObject(AccessToken
);
574 AccessToken
->TokenLock
= &SepTokenLock
;
576 AccessToken
->TokenType
= TokenPrimary
;
577 AccessToken
->ImpersonationLevel
= SecurityDelegation
;
578 AccessToken
->TokenSource
.SourceIdentifier
.LowPart
= 0;
579 AccessToken
->TokenSource
.SourceIdentifier
.HighPart
= 0;
580 memcpy(AccessToken
->TokenSource
.SourceName
, "SeMgr\0\0\0", 8);
581 AccessToken
->ExpirationTime
.QuadPart
= -1;
582 AccessToken
->UserAndGroupCount
= 4;
584 uSize
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
585 uSize
+= uLocalSystemLength
;
586 uSize
+= uWorldLength
;
587 uSize
+= uAuthUserLength
;
588 uSize
+= uAdminsLength
;
590 AccessToken
->UserAndGroups
=
591 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
593 TAG('T', 'O', 'K', 'u'));
594 SidArea
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
597 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
598 AccessToken
->UserAndGroups
[i
++].Attributes
= 0;
599 RtlCopySid(uLocalSystemLength
, SidArea
, SeLocalSystemSid
);
600 SidArea
= (char*)SidArea
+ uLocalSystemLength
;
602 AccessToken
->DefaultOwnerIndex
= i
;
603 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
604 AccessToken
->PrimaryGroup
= (PSID
) SidArea
;
605 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
;
606 Status
= RtlCopySid(uAdminsLength
, SidArea
, SeAliasAdminsSid
);
607 SidArea
= (char*)SidArea
+ uAdminsLength
;
609 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
610 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
611 RtlCopySid(uWorldLength
, SidArea
, SeWorldSid
);
612 SidArea
= (char*)SidArea
+ uWorldLength
;
614 AccessToken
->UserAndGroups
[i
].Sid
= (PSID
) SidArea
;
615 AccessToken
->UserAndGroups
[i
++].Attributes
= SE_GROUP_ENABLED
|SE_GROUP_ENABLED_BY_DEFAULT
|SE_GROUP_MANDATORY
;
616 RtlCopySid(uAuthUserLength
, SidArea
, SeAuthenticatedUserSid
);
617 SidArea
= (char*)SidArea
+ uAuthUserLength
;
619 AccessToken
->PrivilegeCount
= 20;
621 uSize
= AccessToken
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
622 AccessToken
->Privileges
=
623 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
625 TAG('T', 'O', 'K', 'p'));
628 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
629 AccessToken
->Privileges
[i
++].Luid
= SeTcbPrivilege
;
631 AccessToken
->Privileges
[i
].Attributes
= 0;
632 AccessToken
->Privileges
[i
++].Luid
= SeCreateTokenPrivilege
;
634 AccessToken
->Privileges
[i
].Attributes
= 0;
635 AccessToken
->Privileges
[i
++].Luid
= SeTakeOwnershipPrivilege
;
637 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
638 AccessToken
->Privileges
[i
++].Luid
= SeCreatePagefilePrivilege
;
640 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
641 AccessToken
->Privileges
[i
++].Luid
= SeLockMemoryPrivilege
;
643 AccessToken
->Privileges
[i
].Attributes
= 0;
644 AccessToken
->Privileges
[i
++].Luid
= SeAssignPrimaryTokenPrivilege
;
646 AccessToken
->Privileges
[i
].Attributes
= 0;
647 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseQuotaPrivilege
;
649 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
650 AccessToken
->Privileges
[i
++].Luid
= SeIncreaseBasePriorityPrivilege
;
652 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
653 AccessToken
->Privileges
[i
++].Luid
= SeCreatePermanentPrivilege
;
655 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
656 AccessToken
->Privileges
[i
++].Luid
= SeDebugPrivilege
;
658 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
659 AccessToken
->Privileges
[i
++].Luid
= SeAuditPrivilege
;
661 AccessToken
->Privileges
[i
].Attributes
= 0;
662 AccessToken
->Privileges
[i
++].Luid
= SeSecurityPrivilege
;
664 AccessToken
->Privileges
[i
].Attributes
= 0;
665 AccessToken
->Privileges
[i
++].Luid
= SeSystemEnvironmentPrivilege
;
667 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
668 AccessToken
->Privileges
[i
++].Luid
= SeChangeNotifyPrivilege
;
670 AccessToken
->Privileges
[i
].Attributes
= 0;
671 AccessToken
->Privileges
[i
++].Luid
= SeBackupPrivilege
;
673 AccessToken
->Privileges
[i
].Attributes
= 0;
674 AccessToken
->Privileges
[i
++].Luid
= SeRestorePrivilege
;
676 AccessToken
->Privileges
[i
].Attributes
= 0;
677 AccessToken
->Privileges
[i
++].Luid
= SeShutdownPrivilege
;
679 AccessToken
->Privileges
[i
].Attributes
= 0;
680 AccessToken
->Privileges
[i
++].Luid
= SeLoadDriverPrivilege
;
682 AccessToken
->Privileges
[i
].Attributes
= SE_PRIVILEGE_ENABLED_BY_DEFAULT
|SE_PRIVILEGE_ENABLED
;
683 AccessToken
->Privileges
[i
++].Luid
= SeProfileSingleProcessPrivilege
;
685 AccessToken
->Privileges
[i
].Attributes
= 0;
686 AccessToken
->Privileges
[i
++].Luid
= SeSystemtimePrivilege
;
688 AccessToken
->Privileges
[i
].Attributes
= 0;
689 AccessToken
->Privileges
[i
++].Luid
= SeUndockPrivilege
;
691 AccessToken
->Privileges
[i
].Attributes
= 0;
692 AccessToken
->Privileges
[i
++].Luid
= SeManageVolumePrivilege
;
698 uSize
+= sizeof(ACE
) + uLocalSystemLength
;
699 uSize
+= sizeof(ACE
) + uAdminsLength
;
700 uSize
= (uSize
& (~3)) + 8;
701 AccessToken
->DefaultDacl
=
702 (PACL
) ExAllocatePoolWithTag(PagedPool
,
704 TAG('T', 'O', 'K', 'd'));
705 Status
= RtlCreateAcl(AccessToken
->DefaultDacl
, uSize
, ACL_REVISION
);
706 if ( NT_SUCCESS(Status
) )
708 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_ALL
, SeLocalSystemSid
);
711 if ( NT_SUCCESS(Status
) )
713 Status
= RtlAddAccessAllowedAce(AccessToken
->DefaultDacl
, ACL_REVISION
, GENERIC_READ
|GENERIC_WRITE
|GENERIC_EXECUTE
|READ_CONTROL
, SeAliasAdminsSid
);
716 if ( ! NT_SUCCESS(Status
) )
718 ObDereferenceObject(AccessToken
);
725 /* PUBLIC FUNCTIONS ***********************************************************/
732 SeFilterToken(IN PACCESS_TOKEN ExistingToken
,
734 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
735 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
736 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
737 OUT PACCESS_TOKEN
* FilteredToken
)
740 return STATUS_NOT_IMPLEMENTED
;
748 SeQueryInformationToken(IN PACCESS_TOKEN Token
,
749 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
750 OUT PVOID
*TokenInformation
)
753 return STATUS_NOT_IMPLEMENTED
;
761 SeQuerySessionIdToken(IN PACCESS_TOKEN Token
,
762 IN PULONG pSessionId
)
764 *pSessionId
= ((PTOKEN
)Token
)->SessionId
;
765 return STATUS_SUCCESS
;
772 SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token
,
777 *LogonId
= ((PTOKEN
)Token
)->AuthenticationId
;
779 return STATUS_SUCCESS
;
786 SECURITY_IMPERSONATION_LEVEL
788 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token
)
792 return ((PTOKEN
)Token
)->ImpersonationLevel
;
800 SeTokenType(IN PACCESS_TOKEN Token
)
804 return ((PTOKEN
)Token
)->TokenType
;
813 SeTokenIsAdmin(IN PACCESS_TOKEN Token
)
816 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_WRITE_RESTRICTED
) != 0;
824 SeTokenIsRestricted(IN PACCESS_TOKEN Token
)
827 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_IS_RESTRICTED
) != 0;
835 SeTokenIsWriteRestricted(IN PACCESS_TOKEN Token
)
838 return (((PTOKEN
)Token
)->TokenFlags
& TOKEN_HAS_RESTORE_PRIVILEGE
) != 0;
841 /* SYSTEM CALLS ***************************************************************/
847 NtQueryInformationToken(IN HANDLE TokenHandle
,
848 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
849 OUT PVOID TokenInformation
,
850 IN ULONG TokenInformationLength
,
851 OUT PULONG ReturnLength
)
859 ULONG RequiredLength
;
860 KPROCESSOR_MODE PreviousMode
;
861 NTSTATUS Status
= STATUS_SUCCESS
;
865 PreviousMode
= ExGetPreviousMode();
867 /* Check buffers and class validity */
868 Status
= DefaultQueryInfoBufferCheck(TokenInformationClass
,
869 SeTokenInformationClass
,
870 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
872 TokenInformationLength
,
877 if(!NT_SUCCESS(Status
))
879 DPRINT("NtQueryInformationToken() failed, Status: 0x%x\n", Status
);
883 Status
= ObReferenceObjectByHandle(TokenHandle
,
884 (TokenInformationClass
== TokenSource
) ? TOKEN_QUERY_SOURCE
: TOKEN_QUERY
,
889 if (NT_SUCCESS(Status
))
891 switch (TokenInformationClass
)
895 PTOKEN_USER tu
= (PTOKEN_USER
)TokenInformation
;
897 DPRINT("NtQueryInformationToken(TokenUser)\n");
898 RequiredLength
= sizeof(TOKEN_USER
) +
899 RtlLengthSid(Token
->UserAndGroups
[0].Sid
);
903 if(TokenInformationLength
>= RequiredLength
)
905 Status
= RtlCopySidAndAttributesArray(1,
906 &Token
->UserAndGroups
[0],
907 RequiredLength
- sizeof(TOKEN_USER
),
915 Status
= STATUS_BUFFER_TOO_SMALL
;
918 if(ReturnLength
!= NULL
)
920 *ReturnLength
= RequiredLength
;
923 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
925 Status
= _SEH2_GetExceptionCode();
934 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
936 DPRINT("NtQueryInformationToken(TokenGroups)\n");
937 RequiredLength
= sizeof(tg
->GroupCount
) +
938 RtlLengthSidAndAttributes(Token
->UserAndGroupCount
- 1, &Token
->UserAndGroups
[1]);
942 if(TokenInformationLength
>= RequiredLength
)
944 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
945 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
));
946 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
947 ((Token
->UserAndGroupCount
- 1) * sizeof(SID_AND_ATTRIBUTES
)));
949 tg
->GroupCount
= Token
->UserAndGroupCount
- 1;
950 Status
= RtlCopySidAndAttributesArray(Token
->UserAndGroupCount
- 1,
951 &Token
->UserAndGroups
[1],
960 Status
= STATUS_BUFFER_TOO_SMALL
;
963 if(ReturnLength
!= NULL
)
965 *ReturnLength
= RequiredLength
;
968 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
970 Status
= _SEH2_GetExceptionCode();
977 case TokenPrivileges
:
979 PTOKEN_PRIVILEGES tp
= (PTOKEN_PRIVILEGES
)TokenInformation
;
981 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
982 RequiredLength
= sizeof(tp
->PrivilegeCount
) +
983 (Token
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
987 if(TokenInformationLength
>= RequiredLength
)
989 tp
->PrivilegeCount
= Token
->PrivilegeCount
;
990 RtlCopyLuidAndAttributesArray(Token
->PrivilegeCount
,
996 Status
= STATUS_BUFFER_TOO_SMALL
;
999 if(ReturnLength
!= NULL
)
1001 *ReturnLength
= RequiredLength
;
1004 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1006 Status
= _SEH2_GetExceptionCode();
1016 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1018 DPRINT("NtQueryInformationToken(TokenOwner)\n");
1019 SidLen
= RtlLengthSid(Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1020 RequiredLength
= sizeof(TOKEN_OWNER
) + SidLen
;
1024 if(TokenInformationLength
>= RequiredLength
)
1026 to
->Owner
= (PSID
)(to
+ 1);
1027 Status
= RtlCopySid(SidLen
,
1029 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
);
1033 Status
= STATUS_BUFFER_TOO_SMALL
;
1036 if(ReturnLength
!= NULL
)
1038 *ReturnLength
= RequiredLength
;
1041 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1043 Status
= _SEH2_GetExceptionCode();
1050 case TokenPrimaryGroup
:
1053 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1055 DPRINT("NtQueryInformationToken(TokenPrimaryGroup)\n");
1056 SidLen
= RtlLengthSid(Token
->PrimaryGroup
);
1057 RequiredLength
= sizeof(TOKEN_PRIMARY_GROUP
) + SidLen
;
1061 if(TokenInformationLength
>= RequiredLength
)
1063 tpg
->PrimaryGroup
= (PSID
)(tpg
+ 1);
1064 Status
= RtlCopySid(SidLen
,
1066 Token
->PrimaryGroup
);
1070 Status
= STATUS_BUFFER_TOO_SMALL
;
1073 if(ReturnLength
!= NULL
)
1075 *ReturnLength
= RequiredLength
;
1078 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1080 Status
= _SEH2_GetExceptionCode();
1087 case TokenDefaultDacl
:
1089 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1091 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
1092 RequiredLength
= sizeof(TOKEN_DEFAULT_DACL
);
1094 if(Token
->DefaultDacl
!= NULL
)
1096 RequiredLength
+= Token
->DefaultDacl
->AclSize
;
1101 if(TokenInformationLength
>= RequiredLength
)
1103 if(Token
->DefaultDacl
!= NULL
)
1105 tdd
->DefaultDacl
= (PACL
)(tdd
+ 1);
1106 RtlCopyMemory(tdd
->DefaultDacl
,
1108 Token
->DefaultDacl
->AclSize
);
1112 tdd
->DefaultDacl
= NULL
;
1117 Status
= STATUS_BUFFER_TOO_SMALL
;
1120 if(ReturnLength
!= NULL
)
1122 *ReturnLength
= RequiredLength
;
1125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1127 Status
= _SEH2_GetExceptionCode();
1136 PTOKEN_SOURCE ts
= (PTOKEN_SOURCE
)TokenInformation
;
1138 DPRINT("NtQueryInformationToken(TokenSource)\n");
1139 RequiredLength
= sizeof(TOKEN_SOURCE
);
1143 if(TokenInformationLength
>= RequiredLength
)
1145 *ts
= Token
->TokenSource
;
1149 Status
= STATUS_BUFFER_TOO_SMALL
;
1152 if(ReturnLength
!= NULL
)
1154 *ReturnLength
= RequiredLength
;
1157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1159 Status
= _SEH2_GetExceptionCode();
1168 PTOKEN_TYPE tt
= (PTOKEN_TYPE
)TokenInformation
;
1170 DPRINT("NtQueryInformationToken(TokenType)\n");
1171 RequiredLength
= sizeof(TOKEN_TYPE
);
1175 if(TokenInformationLength
>= RequiredLength
)
1177 *tt
= Token
->TokenType
;
1181 Status
= STATUS_BUFFER_TOO_SMALL
;
1184 if(ReturnLength
!= NULL
)
1186 *ReturnLength
= RequiredLength
;
1189 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1191 Status
= _SEH2_GetExceptionCode();
1198 case TokenImpersonationLevel
:
1200 PSECURITY_IMPERSONATION_LEVEL sil
= (PSECURITY_IMPERSONATION_LEVEL
)TokenInformation
;
1202 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
1203 RequiredLength
= sizeof(SECURITY_IMPERSONATION_LEVEL
);
1207 if(TokenInformationLength
>= RequiredLength
)
1209 *sil
= Token
->ImpersonationLevel
;
1213 Status
= STATUS_BUFFER_TOO_SMALL
;
1216 if(ReturnLength
!= NULL
)
1218 *ReturnLength
= RequiredLength
;
1221 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1223 Status
= _SEH2_GetExceptionCode();
1230 case TokenStatistics
:
1232 PTOKEN_STATISTICS ts
= (PTOKEN_STATISTICS
)TokenInformation
;
1234 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
1235 RequiredLength
= sizeof(TOKEN_STATISTICS
);
1239 if(TokenInformationLength
>= RequiredLength
)
1241 ts
->TokenId
= Token
->TokenId
;
1242 ts
->AuthenticationId
= Token
->AuthenticationId
;
1243 ts
->ExpirationTime
= Token
->ExpirationTime
;
1244 ts
->TokenType
= Token
->TokenType
;
1245 ts
->ImpersonationLevel
= Token
->ImpersonationLevel
;
1246 ts
->DynamicCharged
= Token
->DynamicCharged
;
1247 ts
->DynamicAvailable
= Token
->DynamicAvailable
;
1248 ts
->GroupCount
= Token
->UserAndGroupCount
- 1;
1249 ts
->PrivilegeCount
= Token
->PrivilegeCount
;
1250 ts
->ModifiedId
= Token
->ModifiedId
;
1254 Status
= STATUS_BUFFER_TOO_SMALL
;
1257 if(ReturnLength
!= NULL
)
1259 *ReturnLength
= RequiredLength
;
1262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1264 Status
= _SEH2_GetExceptionCode();
1273 PTOKEN_ORIGIN to
= (PTOKEN_ORIGIN
)TokenInformation
;
1275 DPRINT("NtQueryInformationToken(TokenOrigin)\n");
1276 RequiredLength
= sizeof(TOKEN_ORIGIN
);
1280 if(TokenInformationLength
>= RequiredLength
)
1282 RtlCopyLuid(&to
->OriginatingLogonSession
,
1283 &Token
->AuthenticationId
);
1287 Status
= STATUS_BUFFER_TOO_SMALL
;
1290 if(ReturnLength
!= NULL
)
1292 *ReturnLength
= RequiredLength
;
1295 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1297 Status
= _SEH2_GetExceptionCode();
1304 case TokenGroupsAndPrivileges
:
1305 DPRINT1("NtQueryInformationToken(TokenGroupsAndPrivileges) not implemented\n");
1306 Status
= STATUS_NOT_IMPLEMENTED
;
1309 case TokenRestrictedSids
:
1311 PTOKEN_GROUPS tg
= (PTOKEN_GROUPS
)TokenInformation
;
1313 DPRINT("NtQueryInformationToken(TokenRestrictedSids)\n");
1314 RequiredLength
= sizeof(tg
->GroupCount
) +
1315 RtlLengthSidAndAttributes(Token
->RestrictedSidCount
, Token
->RestrictedSids
);
1319 if(TokenInformationLength
>= RequiredLength
)
1321 ULONG SidLen
= RequiredLength
- sizeof(tg
->GroupCount
) -
1322 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
));
1323 PSID_AND_ATTRIBUTES Sid
= (PSID_AND_ATTRIBUTES
)((ULONG_PTR
)TokenInformation
+ sizeof(tg
->GroupCount
) +
1324 (Token
->RestrictedSidCount
* sizeof(SID_AND_ATTRIBUTES
)));
1326 tg
->GroupCount
= Token
->RestrictedSidCount
;
1327 Status
= RtlCopySidAndAttributesArray(Token
->RestrictedSidCount
,
1328 Token
->RestrictedSids
,
1337 Status
= STATUS_BUFFER_TOO_SMALL
;
1340 if(ReturnLength
!= NULL
)
1342 *ReturnLength
= RequiredLength
;
1345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1347 Status
= _SEH2_GetExceptionCode();
1354 case TokenSandBoxInert
:
1355 DPRINT1("NtQueryInformationToken(TokenSandboxInert) not implemented\n");
1356 Status
= STATUS_NOT_IMPLEMENTED
;
1359 case TokenSessionId
:
1361 ULONG SessionId
= 0;
1363 DPRINT("NtQueryInformationToken(TokenSessionId)\n");
1365 Status
= SeQuerySessionIdToken(Token
,
1368 if(NT_SUCCESS(Status
))
1372 /* buffer size was already verified, no need to check here again */
1373 *(PULONG
)TokenInformation
= SessionId
;
1375 if(ReturnLength
!= NULL
)
1377 *ReturnLength
= sizeof(ULONG
);
1380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1382 Status
= _SEH2_GetExceptionCode();
1391 DPRINT1("NtQueryInformationToken(%d) invalid information class\n", TokenInformationClass
);
1392 Status
= STATUS_INVALID_INFO_CLASS
;
1396 ObDereferenceObject(Token
);
1404 * NtSetTokenInformation: Partly implemented.
1406 * TokenOrigin, TokenDefaultDacl
1410 NtSetInformationToken(IN HANDLE TokenHandle
,
1411 IN TOKEN_INFORMATION_CLASS TokenInformationClass
,
1412 OUT PVOID TokenInformation
,
1413 IN ULONG TokenInformationLength
)
1416 KPROCESSOR_MODE PreviousMode
;
1417 ULONG NeededAccess
= TOKEN_ADJUST_DEFAULT
;
1418 NTSTATUS Status
= STATUS_SUCCESS
;
1422 PreviousMode
= ExGetPreviousMode();
1424 Status
= DefaultSetInfoBufferCheck(TokenInformationClass
,
1425 SeTokenInformationClass
,
1426 sizeof(SeTokenInformationClass
) / sizeof(SeTokenInformationClass
[0]),
1428 TokenInformationLength
,
1431 if(!NT_SUCCESS(Status
))
1433 /* Invalid buffers */
1434 DPRINT("NtSetInformationToken() failed, Status: 0x%x\n", Status
);
1438 if(TokenInformationClass
== TokenSessionId
)
1440 NeededAccess
|= TOKEN_ADJUST_SESSIONID
;
1443 Status
= ObReferenceObjectByHandle(TokenHandle
,
1449 if (NT_SUCCESS(Status
))
1451 switch (TokenInformationClass
)
1455 if(TokenInformationLength
>= sizeof(TOKEN_OWNER
))
1457 PTOKEN_OWNER to
= (PTOKEN_OWNER
)TokenInformation
;
1458 PSID InputSid
= NULL
;
1462 InputSid
= to
->Owner
;
1464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1466 Status
= _SEH2_GetExceptionCode();
1470 if(NT_SUCCESS(Status
))
1474 Status
= SepCaptureSid(InputSid
,
1479 if(NT_SUCCESS(Status
))
1481 RtlCopySid(RtlLengthSid(CapturedSid
),
1482 Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
,
1484 SepReleaseSid(CapturedSid
,
1492 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1497 case TokenPrimaryGroup
:
1499 if(TokenInformationLength
>= sizeof(TOKEN_PRIMARY_GROUP
))
1501 PTOKEN_PRIMARY_GROUP tpg
= (PTOKEN_PRIMARY_GROUP
)TokenInformation
;
1502 PSID InputSid
= NULL
;
1506 InputSid
= tpg
->PrimaryGroup
;
1508 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1510 Status
= _SEH2_GetExceptionCode();
1514 if(NT_SUCCESS(Status
))
1518 Status
= SepCaptureSid(InputSid
,
1523 if(NT_SUCCESS(Status
))
1525 RtlCopySid(RtlLengthSid(CapturedSid
),
1526 Token
->PrimaryGroup
,
1528 SepReleaseSid(CapturedSid
,
1536 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1541 case TokenDefaultDacl
:
1543 if(TokenInformationLength
>= sizeof(TOKEN_DEFAULT_DACL
))
1545 PTOKEN_DEFAULT_DACL tdd
= (PTOKEN_DEFAULT_DACL
)TokenInformation
;
1546 PACL InputAcl
= NULL
;
1550 InputAcl
= tdd
->DefaultDacl
;
1552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1554 Status
= _SEH2_GetExceptionCode();
1558 if(NT_SUCCESS(Status
))
1560 if(InputAcl
!= NULL
)
1564 /* capture and copy the dacl */
1565 Status
= SepCaptureAcl(InputAcl
,
1570 if(NT_SUCCESS(Status
))
1572 /* free the previous dacl if present */
1573 if(Token
->DefaultDacl
!= NULL
)
1575 ExFreePool(Token
->DefaultDacl
);
1578 /* set the new dacl */
1579 Token
->DefaultDacl
= CapturedAcl
;
1584 /* clear and free the default dacl if present */
1585 if(Token
->DefaultDacl
!= NULL
)
1587 ExFreePool(Token
->DefaultDacl
);
1588 Token
->DefaultDacl
= NULL
;
1595 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1600 case TokenSessionId
:
1602 ULONG SessionId
= 0;
1606 /* buffer size was already verified, no need to check here again */
1607 SessionId
= *(PULONG
)TokenInformation
;
1609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1611 Status
= _SEH2_GetExceptionCode();
1615 if(NT_SUCCESS(Status
))
1617 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1620 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1624 Token
->SessionId
= SessionId
;
1631 Status
= STATUS_NOT_IMPLEMENTED
;
1636 ObDereferenceObject(Token
);
1646 * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K
1647 * this is certainly NOT true, thou i can't say for sure that EffectiveOnly
1648 * is correct either. -Gunnar
1649 * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI
1652 NtDuplicateToken(IN HANDLE ExistingTokenHandle
,
1653 IN ACCESS_MASK DesiredAccess
,
1654 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1655 IN BOOLEAN EffectiveOnly
,
1656 IN TOKEN_TYPE TokenType
,
1657 OUT PHANDLE NewTokenHandle
)
1659 KPROCESSOR_MODE PreviousMode
;
1663 PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService
;
1665 NTSTATUS Status
= STATUS_SUCCESS
;
1669 PreviousMode
= KeGetPreviousMode();
1671 if(PreviousMode
!= KernelMode
)
1675 ProbeForWriteHandle(NewTokenHandle
);
1677 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1679 Status
= _SEH2_GetExceptionCode();
1683 if(!NT_SUCCESS(Status
))
1689 Status
= SepCaptureSecurityQualityOfService(ObjectAttributes
,
1693 &CapturedSecurityQualityOfService
,
1695 if(!NT_SUCCESS(Status
))
1697 DPRINT1("NtDuplicateToken() failed to capture QoS! Status: 0x%x\n", Status
);
1701 Status
= ObReferenceObjectByHandle(ExistingTokenHandle
,
1707 if (NT_SUCCESS(Status
))
1709 Status
= SepDuplicateToken(Token
,
1713 (QoSPresent
? CapturedSecurityQualityOfService
->ImpersonationLevel
: SecurityAnonymous
),
1717 ObDereferenceObject(Token
);
1719 if (NT_SUCCESS(Status
))
1721 Status
= ObInsertObject((PVOID
)NewToken
,
1728 if (NT_SUCCESS(Status
))
1732 *NewTokenHandle
= hToken
;
1734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1736 Status
= _SEH2_GetExceptionCode();
1743 /* free the captured structure */
1744 SepReleaseSecurityQualityOfService(CapturedSecurityQualityOfService
,
1752 NtAdjustGroupsToken(IN HANDLE TokenHandle
,
1753 IN BOOLEAN ResetToDefault
,
1754 IN PTOKEN_GROUPS NewState
,
1755 IN ULONG BufferLength
,
1756 OUT PTOKEN_GROUPS PreviousState OPTIONAL
,
1757 OUT PULONG ReturnLength
)
1760 return(STATUS_NOT_IMPLEMENTED
);
1767 NtAdjustPrivilegesToken (IN HANDLE TokenHandle
,
1768 IN BOOLEAN DisableAllPrivileges
,
1769 IN PTOKEN_PRIVILEGES NewState
,
1770 IN ULONG BufferLength
,
1771 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL
,
1772 OUT PULONG ReturnLength OPTIONAL
)
1774 // PLUID_AND_ATTRIBUTES Privileges;
1775 KPROCESSOR_MODE PreviousMode
;
1776 ULONG PrivilegeCount
;
1792 DPRINT ("NtAdjustPrivilegesToken() called\n");
1794 // PrivilegeCount = NewState->PrivilegeCount;
1795 PreviousMode
= KeGetPreviousMode ();
1796 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
1806 Status
= ObReferenceObjectByHandle (TokenHandle
,
1807 TOKEN_ADJUST_PRIVILEGES
| (PreviousState
!= NULL
? TOKEN_QUERY
: 0),
1812 if (!NT_SUCCESS(Status
))
1814 DPRINT1 ("Failed to reference token (Status %lx)\n", Status
);
1815 // SeReleaseLuidAndAttributesArray(Privileges,
1823 SepAdjustPrivileges(Token
,
1834 PrivilegeCount
= (BufferLength
- FIELD_OFFSET(TOKEN_PRIVILEGES
, Privileges
)) /
1835 sizeof(LUID_AND_ATTRIBUTES
);
1837 if (PreviousState
!= NULL
)
1838 PreviousState
->PrivilegeCount
= 0;
1841 if (DisableAllPrivileges
== TRUE
)
1843 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1845 if (Token
->Privileges
[i
].Attributes
!= 0)
1847 DPRINT ("Attributes differ\n");
1849 /* Save current privilege */
1850 if (PreviousState
!= NULL
)
1852 if (k
< PrivilegeCount
)
1854 PreviousState
->PrivilegeCount
++;
1855 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1856 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1860 /* FIXME: Should revert all the changes, calculate how
1861 * much space would be needed, set ResultLength
1862 * accordingly and fail.
1868 /* Update current privlege */
1869 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1872 Status
= STATUS_SUCCESS
;
1877 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
1879 for (j
= 0; j
< NewState
->PrivilegeCount
; j
++)
1881 if (Token
->Privileges
[i
].Luid
.LowPart
== NewState
->Privileges
[j
].Luid
.LowPart
&&
1882 Token
->Privileges
[i
].Luid
.HighPart
== NewState
->Privileges
[j
].Luid
.HighPart
)
1884 DPRINT ("Found privilege\n");
1886 if ((Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
) !=
1887 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
))
1889 DPRINT ("Attributes differ\n");
1890 DPRINT ("Current attributes %lx desired attributes %lx\n",
1891 Token
->Privileges
[i
].Attributes
,
1892 NewState
->Privileges
[j
].Attributes
);
1894 /* Save current privilege */
1895 if (PreviousState
!= NULL
)
1897 if (k
< PrivilegeCount
)
1899 PreviousState
->PrivilegeCount
++;
1900 PreviousState
->Privileges
[k
].Luid
= Token
->Privileges
[i
].Luid
;
1901 PreviousState
->Privileges
[k
].Attributes
= Token
->Privileges
[i
].Attributes
;
1905 /* FIXME: Should revert all the changes, calculate how
1906 * much space would be needed, set ResultLength
1907 * accordingly and fail.
1913 /* Update current privlege */
1914 Token
->Privileges
[i
].Attributes
&= ~SE_PRIVILEGE_ENABLED
;
1915 Token
->Privileges
[i
].Attributes
|=
1916 (NewState
->Privileges
[j
].Attributes
& SE_PRIVILEGE_ENABLED
);
1917 DPRINT ("New attributes %lx\n",
1918 Token
->Privileges
[i
].Attributes
);
1924 Status
= Count
< NewState
->PrivilegeCount
? STATUS_NOT_ALL_ASSIGNED
: STATUS_SUCCESS
;
1927 if (ReturnLength
!= NULL
)
1929 *ReturnLength
= sizeof(TOKEN_PRIVILEGES
) +
1930 (sizeof(LUID_AND_ATTRIBUTES
) * (k
- 1));
1933 ObDereferenceObject (Token
);
1935 // SeReleaseLuidAndAttributesArray(Privileges,
1939 DPRINT ("NtAdjustPrivilegesToken() done\n");
1945 NtCreateToken(OUT PHANDLE TokenHandle
,
1946 IN ACCESS_MASK DesiredAccess
,
1947 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1948 IN TOKEN_TYPE TokenType
,
1949 IN PLUID AuthenticationId
,
1950 IN PLARGE_INTEGER ExpirationTime
,
1951 IN PTOKEN_USER TokenUser
,
1952 IN PTOKEN_GROUPS TokenGroups
,
1953 IN PTOKEN_PRIVILEGES TokenPrivileges
,
1954 IN PTOKEN_OWNER TokenOwner
,
1955 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup
,
1956 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl
,
1957 IN PTOKEN_SOURCE TokenSource
)
1966 KPROCESSOR_MODE PreviousMode
;
1967 ULONG nTokenPrivileges
= 0;
1968 LARGE_INTEGER LocalExpirationTime
= {{0, 0}};
1969 NTSTATUS Status
= STATUS_SUCCESS
;
1973 PreviousMode
= ExGetPreviousMode();
1975 if(PreviousMode
!= KernelMode
)
1979 ProbeForWriteHandle(TokenHandle
);
1980 ProbeForRead(AuthenticationId
,
1983 LocalExpirationTime
= ProbeForReadLargeInteger(ExpirationTime
);
1984 ProbeForRead(TokenUser
,
1987 ProbeForRead(TokenGroups
,
1988 sizeof(TOKEN_GROUPS
),
1990 ProbeForRead(TokenPrivileges
,
1991 sizeof(TOKEN_PRIVILEGES
),
1993 ProbeForRead(TokenOwner
,
1994 sizeof(TOKEN_OWNER
),
1996 ProbeForRead(TokenPrimaryGroup
,
1997 sizeof(TOKEN_PRIMARY_GROUP
),
1999 ProbeForRead(TokenDefaultDacl
,
2000 sizeof(TOKEN_DEFAULT_DACL
),
2002 ProbeForRead(TokenSource
,
2003 sizeof(TOKEN_SOURCE
),
2005 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2007 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2009 Status
= _SEH2_GetExceptionCode();
2013 if(!NT_SUCCESS(Status
))
2020 nTokenPrivileges
= TokenPrivileges
->PrivilegeCount
;
2021 LocalExpirationTime
= *ExpirationTime
;
2024 Status
= ZwAllocateLocallyUniqueId(&TokenId
);
2025 if (!NT_SUCCESS(Status
))
2028 Status
= ZwAllocateLocallyUniqueId(&ModifiedId
);
2029 if (!NT_SUCCESS(Status
))
2032 Status
= ObCreateObject(PreviousMode
,
2040 (PVOID
*)&AccessToken
);
2041 if (!NT_SUCCESS(Status
))
2043 DPRINT1("ObCreateObject() failed (Status %lx)\n");
2047 AccessToken
->TokenLock
= &SepTokenLock
;
2049 RtlCopyLuid(&AccessToken
->TokenSource
.SourceIdentifier
,
2050 &TokenSource
->SourceIdentifier
);
2051 memcpy(AccessToken
->TokenSource
.SourceName
,
2052 TokenSource
->SourceName
,
2053 sizeof(TokenSource
->SourceName
));
2055 RtlCopyLuid(&AccessToken
->TokenId
, &TokenId
);
2056 RtlCopyLuid(&AccessToken
->AuthenticationId
, AuthenticationId
);
2057 AccessToken
->ExpirationTime
= *ExpirationTime
;
2058 RtlCopyLuid(&AccessToken
->ModifiedId
, &ModifiedId
);
2060 AccessToken
->UserAndGroupCount
= TokenGroups
->GroupCount
+ 1;
2061 AccessToken
->PrivilegeCount
= TokenPrivileges
->PrivilegeCount
;
2062 AccessToken
->UserAndGroups
= 0;
2063 AccessToken
->Privileges
= 0;
2065 AccessToken
->TokenType
= TokenType
;
2066 AccessToken
->ImpersonationLevel
= ((PSECURITY_QUALITY_OF_SERVICE
)
2067 (ObjectAttributes
->SecurityQualityOfService
))->ImpersonationLevel
;
2070 * Normally we would just point these members into the variable information
2071 * area; however, our ObCreateObject() call can't allocate a variable information
2072 * area, so we allocate them seperately and provide a destroy function.
2075 uLength
= sizeof(SID_AND_ATTRIBUTES
) * AccessToken
->UserAndGroupCount
;
2076 uLength
+= RtlLengthSid(TokenUser
->User
.Sid
);
2077 for (i
= 0; i
< TokenGroups
->GroupCount
; i
++)
2078 uLength
+= RtlLengthSid(TokenGroups
->Groups
[i
].Sid
);
2080 AccessToken
->UserAndGroups
=
2081 (PSID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2083 TAG('T', 'O', 'K', 'u'));
2085 EndMem
= &AccessToken
->UserAndGroups
[AccessToken
->UserAndGroupCount
];
2087 Status
= RtlCopySidAndAttributesArray(1,
2090 AccessToken
->UserAndGroups
,
2094 if (NT_SUCCESS(Status
))
2096 Status
= RtlCopySidAndAttributesArray(TokenGroups
->GroupCount
,
2097 TokenGroups
->Groups
,
2099 &AccessToken
->UserAndGroups
[1],
2105 if (NT_SUCCESS(Status
))
2107 Status
= SepFindPrimaryGroupAndDefaultOwner(
2109 TokenPrimaryGroup
->PrimaryGroup
,
2113 if (NT_SUCCESS(Status
))
2115 uLength
= TokenPrivileges
->PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
2116 AccessToken
->Privileges
=
2117 (PLUID_AND_ATTRIBUTES
)ExAllocatePoolWithTag(PagedPool
,
2119 TAG('T', 'O', 'K', 'p'));
2121 if (PreviousMode
!= KernelMode
)
2125 RtlCopyMemory(AccessToken
->Privileges
,
2126 TokenPrivileges
->Privileges
,
2127 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2131 Status
= _SEH2_GetExceptionCode();
2137 RtlCopyMemory(AccessToken
->Privileges
,
2138 TokenPrivileges
->Privileges
,
2139 nTokenPrivileges
* sizeof(LUID_AND_ATTRIBUTES
));
2143 if (NT_SUCCESS(Status
))
2145 AccessToken
->DefaultDacl
=
2146 (PACL
) ExAllocatePoolWithTag(PagedPool
,
2147 TokenDefaultDacl
->DefaultDacl
->AclSize
,
2148 TAG('T', 'O', 'K', 'd'));
2149 memcpy(AccessToken
->DefaultDacl
,
2150 TokenDefaultDacl
->DefaultDacl
,
2151 TokenDefaultDacl
->DefaultDacl
->AclSize
);
2154 Status
= ObInsertObject ((PVOID
)AccessToken
,
2160 if (!NT_SUCCESS(Status
))
2162 DPRINT1("ObInsertObject() failed (Status %lx)\n", Status
);
2165 if (NT_SUCCESS(Status
))
2169 *TokenHandle
= hToken
;
2171 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2173 Status
= _SEH2_GetExceptionCode();
2186 NtOpenThreadTokenEx(IN HANDLE ThreadHandle
,
2187 IN ACCESS_MASK DesiredAccess
,
2188 IN BOOLEAN OpenAsSelf
,
2189 IN ULONG HandleAttributes
,
2190 OUT PHANDLE TokenHandle
)
2194 PTOKEN Token
, NewToken
, PrimaryToken
;
2195 BOOLEAN CopyOnOpen
, EffectiveOnly
;
2196 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
2197 SE_IMPERSONATION_STATE ImpersonationState
;
2198 OBJECT_ATTRIBUTES ObjectAttributes
;
2199 SECURITY_DESCRIPTOR SecurityDescriptor
;
2201 KPROCESSOR_MODE PreviousMode
;
2202 NTSTATUS Status
= STATUS_SUCCESS
;
2206 PreviousMode
= ExGetPreviousMode();
2208 if(PreviousMode
!= KernelMode
)
2212 ProbeForWriteHandle(TokenHandle
);
2214 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2216 Status
= _SEH2_GetExceptionCode();
2220 if(!NT_SUCCESS(Status
))
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 ObfDereferenceObject(Thread
);
2244 return STATUS_NO_TOKEN
;
2247 ObDereferenceObject(Thread
);
2249 if (ImpersonationLevel
== SecurityAnonymous
)
2251 ObfDereferenceObject(Token
);
2252 return STATUS_CANT_OPEN_ANONYMOUS
;
2256 * Revert to self if OpenAsSelf is specified.
2261 PsDisableImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2266 Status
= ObReferenceObjectByHandle(ThreadHandle
, THREAD_ALL_ACCESS
,
2267 PsThreadType
, PreviousMode
,
2268 (PVOID
*)&Thread
, NULL
);
2269 if (!NT_SUCCESS(Status
))
2271 ObfDereferenceObject(Token
);
2274 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2279 PrimaryToken
= PsReferencePrimaryToken(Thread
->ThreadsProcess
);
2280 Status
= SepCreateImpersonationTokenDacl(Token
, PrimaryToken
, &Dacl
);
2282 ObfDereferenceObject(PrimaryToken
);
2283 ObfDereferenceObject(Thread
);
2284 if (!NT_SUCCESS(Status
))
2286 ObfDereferenceObject(Token
);
2289 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2294 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
2295 SECURITY_DESCRIPTOR_REVISION
);
2296 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
, TRUE
, Dacl
,
2299 InitializeObjectAttributes(&ObjectAttributes
, NULL
, HandleAttributes
,
2300 NULL
, &SecurityDescriptor
);
2302 Status
= SepDuplicateToken(Token
, &ObjectAttributes
, EffectiveOnly
,
2303 TokenImpersonation
, ImpersonationLevel
,
2304 KernelMode
, &NewToken
);
2306 if (!NT_SUCCESS(Status
))
2308 ObfDereferenceObject(Token
);
2311 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2316 Status
= ObInsertObject(NewToken
, NULL
, DesiredAccess
, 0, NULL
,
2322 Status
= ObOpenObjectByPointer(Token
, HandleAttributes
,
2323 NULL
, DesiredAccess
, SepTokenObjectType
,
2324 PreviousMode
, &hToken
);
2327 ObfDereferenceObject(Token
);
2331 PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState
);
2334 if(NT_SUCCESS(Status
))
2338 *TokenHandle
= hToken
;
2340 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2342 Status
= _SEH2_GetExceptionCode();
2354 NtOpenThreadToken(IN HANDLE ThreadHandle
,
2355 IN ACCESS_MASK DesiredAccess
,
2356 IN BOOLEAN OpenAsSelf
,
2357 OUT PHANDLE TokenHandle
)
2359 return NtOpenThreadTokenEx(ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0,
2370 NtCompareTokens(IN HANDLE FirstTokenHandle
,
2371 IN HANDLE SecondTokenHandle
,
2374 KPROCESSOR_MODE PreviousMode
;
2375 PTOKEN FirstToken
, SecondToken
;
2377 NTSTATUS Status
= STATUS_SUCCESS
;
2381 PreviousMode
= ExGetPreviousMode();
2383 if (PreviousMode
!= KernelMode
)
2387 ProbeForWriteBoolean(Equal
);
2389 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2391 Status
= _SEH2_GetExceptionCode();
2395 if (!NT_SUCCESS(Status
))
2399 Status
= ObReferenceObjectByHandle(FirstTokenHandle
,
2403 (PVOID
*)&FirstToken
,
2405 if (!NT_SUCCESS(Status
))
2408 Status
= ObReferenceObjectByHandle(SecondTokenHandle
,
2412 (PVOID
*)&SecondToken
,
2414 if (!NT_SUCCESS(Status
))
2416 ObDereferenceObject(FirstToken
);
2420 if (FirstToken
!= SecondToken
)
2422 Status
= SepCompareTokens(FirstToken
,
2429 ObDereferenceObject(FirstToken
);
2430 ObDereferenceObject(SecondToken
);
2432 if (NT_SUCCESS(Status
))
2438 _SEH2_EXCEPT(ExSystemExceptionFilter())
2440 Status
= _SEH2_GetExceptionCode();
2450 NtFilterToken(IN HANDLE ExistingTokenHandle
,
2452 IN PTOKEN_GROUPS SidsToDisable OPTIONAL
,
2453 IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL
,
2454 IN PTOKEN_GROUPS RestrictedSids OPTIONAL
,
2455 OUT PHANDLE NewTokenHandle
)
2458 return STATUS_NOT_IMPLEMENTED
;
2466 NtImpersonateAnonymousToken(IN HANDLE Thread
)
2469 return STATUS_NOT_IMPLEMENTED
;