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