3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Security manager
6 * FILE: kernel/se/token.c
7 * PROGRAMER: David Welch <welch@cwcom.net>
9 * 26/07/98: Added stubs for security functions
12 /* INCLUDES *****************************************************************/
15 #define NTOS_MODE_KERNEL
17 #include <internal/ps.h>
18 #include <internal/se.h>
19 #include <internal/safe.h>
22 #include <internal/debug.h>
24 /* GLOBALS *******************************************************************/
26 POBJECT_TYPE SepTokenObjectType = NULL;
28 static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ,
33 #define SYSTEM_LUID 0x3E7;
35 /* FUNCTIONS *****************************************************************/
37 VOID SepFreeProxyData(PVOID ProxyData)
42 NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src)
47 NTSTATUS SeExchangePrimaryToken(PEPROCESS Process,
48 PACCESS_TOKEN NewToken,
49 PACCESS_TOKEN* OldTokenP)
51 PACCESS_TOKEN OldToken;
53 if (NewToken->TokenType != TokenPrimary)
55 return(STATUS_UNSUCCESSFUL);
57 if (NewToken->TokenInUse != 0)
59 return(STATUS_UNSUCCESSFUL);
61 OldToken = Process->Token;
62 Process->Token = NewToken;
63 NewToken->TokenInUse = 1;
64 ObReferenceObjectByPointer(NewToken,
68 OldToken->TokenInUse = 0;
69 *OldTokenP = OldToken;
70 return(STATUS_SUCCESS);
74 RtlLengthSidAndAttributes(ULONG Count,
75 PSID_AND_ATTRIBUTES Src)
80 uLength = Count * sizeof(SID_AND_ATTRIBUTES);
81 for (i = 0; i < Count; i++)
82 uLength += RtlLengthSid(Src[i].Sid);
89 SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token,
95 Token->PrimaryGroup = 0;
99 Token->DefaultOwnerIndex = Token->UserAndGroupCount;
102 /* Validate and set the primary group and user pointers */
103 for (i = 0; i < Token->UserAndGroupCount; i++)
106 RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner))
108 Token->DefaultOwnerIndex = i;
111 if (RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
113 Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
117 if (Token->DefaultOwnerIndex == Token->UserAndGroupCount)
119 return(STATUS_INVALID_OWNER);
122 if (Token->PrimaryGroup == 0)
124 return(STATUS_INVALID_PRIMARY_GROUP);
127 return(STATUS_SUCCESS);
132 SepDuplicateToken(PACCESS_TOKEN Token,
133 POBJECT_ATTRIBUTES ObjectAttributes,
134 TOKEN_TYPE TokenType,
135 SECURITY_IMPERSONATION_LEVEL Level,
136 SECURITY_IMPERSONATION_LEVEL ExistingLevel,
137 KPROCESSOR_MODE PreviousMode,
138 PACCESS_TOKEN* NewAccessToken)
146 PACCESS_TOKEN AccessToken;
148 Status = ObRosCreateObject(0,
152 (PVOID*)&AccessToken);
153 if (!NT_SUCCESS(Status))
155 DPRINT1("ObRosCreateObject() failed (Status %lx)\n");
159 Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
160 if (!NT_SUCCESS(Status))
162 ObDereferenceObject(AccessToken);
166 Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
167 if (!NT_SUCCESS(Status))
169 ObDereferenceObject(AccessToken);
173 AccessToken->TokenInUse = 0;
174 AccessToken->TokenType = TokenType;
175 AccessToken->ImpersonationLevel = Level;
176 AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
177 AccessToken->AuthenticationId.HighPart = 0;
179 AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
180 AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
181 memcpy(AccessToken->TokenSource.SourceName,
182 Token->TokenSource.SourceName,
183 sizeof(Token->TokenSource.SourceName));
184 AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
185 AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
186 AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
188 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
189 for (i = 0; i < Token->UserAndGroupCount; i++)
190 uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
192 AccessToken->UserAndGroups =
193 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
195 TAG('T', 'O', 'K', 'u'));
197 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
199 Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
200 Token->UserAndGroups,
202 AccessToken->UserAndGroups,
206 if (NT_SUCCESS(Status))
208 Status = SepFindPrimaryGroupAndDefaultOwner(
214 if (NT_SUCCESS(Status))
216 AccessToken->PrivilegeCount = Token->PrivilegeCount;
218 uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
219 AccessToken->Privileges =
220 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
222 TAG('T', 'O', 'K', 'p'));
224 for (i = 0; i < AccessToken->PrivilegeCount; i++)
226 RtlCopyLuid(&AccessToken->Privileges[i].Luid,
227 &Token->Privileges[i].Luid);
228 AccessToken->Privileges[i].Attributes =
229 Token->Privileges[i].Attributes;
232 if ( Token->DefaultDacl )
234 AccessToken->DefaultDacl =
235 (PACL) ExAllocatePoolWithTag(NonPagedPool,
236 Token->DefaultDacl->AclSize,
237 TAG('T', 'O', 'K', 'd'));
238 memcpy(AccessToken->DefaultDacl,
240 Token->DefaultDacl->AclSize);
244 AccessToken->DefaultDacl = 0;
248 if ( NT_SUCCESS(Status) )
250 *NewAccessToken = AccessToken;
251 return(STATUS_SUCCESS);
254 ObDereferenceObject(AccessToken);
260 SepInitializeNewProcess(struct _EPROCESS* NewProcess,
261 struct _EPROCESS* ParentProcess)
264 PACCESS_TOKEN pNewToken;
265 PACCESS_TOKEN pParentToken;
267 OBJECT_ATTRIBUTES ObjectAttributes;
269 pParentToken = (PACCESS_TOKEN) ParentProcess->Token;
271 InitializeObjectAttributes(&ObjectAttributes,
277 Status = SepDuplicateToken(pParentToken,
280 pParentToken->ImpersonationLevel,
281 pParentToken->ImpersonationLevel,
284 if ( ! NT_SUCCESS(Status) )
287 NewProcess->Token = pNewToken;
288 return(STATUS_SUCCESS);
292 NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
293 SECURITY_IMPERSONATION_LEVEL Level,
294 KPROCESSOR_MODE PreviousMode,
295 PACCESS_TOKEN* NewToken)
298 OBJECT_ATTRIBUTES ObjectAttributes;
300 InitializeObjectAttributes(&ObjectAttributes,
305 Status = SepDuplicateToken(Token,
308 SecurityIdentification,
320 SeCreateClientSecurity(IN struct _ETHREAD *Thread,
321 IN PSECURITY_QUALITY_OF_SERVICE Qos,
322 IN BOOLEAN RemoteClient,
323 OUT PSECURITY_CLIENT_CONTEXT ClientContext)
325 TOKEN_TYPE TokenType;
327 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
330 PACCESS_TOKEN NewToken;
332 Token = PsReferenceEffectiveToken(Thread,
335 &ImpersonationLevel);
338 ClientContext->DirectAccessEffectiveOnly = Qos->EffectiveOnly;
342 if (Qos->ImpersonationLevel > ImpersonationLevel)
346 ObDereferenceObject(Token);
348 return(STATUS_UNSUCCESSFUL);
350 if (ImpersonationLevel == 0 ||
351 ImpersonationLevel == 1 ||
352 (RemoteClient != FALSE && ImpersonationLevel != 3))
356 ObDereferenceObject(Token);
358 return(STATUS_UNSUCCESSFUL);
361 Qos->EffectiveOnly != 0)
363 ClientContext->DirectAccessEffectiveOnly = TRUE;
367 ClientContext->DirectAccessEffectiveOnly = FALSE;
371 if (Qos->ContextTrackingMode == 0)
373 ClientContext->DirectlyAccessClientToken = FALSE;
374 g = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken);
377 // ObDeleteCapturedInsertInfo(NewToken);
379 if (TokenType == TokenPrimary || Token != NULL)
381 ObDereferenceObject(Token);
390 ClientContext->DirectlyAccessClientToken = TRUE;
391 if (RemoteClient != FALSE)
393 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
397 ClientContext->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
398 ClientContext->SecurityQos.ImpersonationLevel = Qos->ImpersonationLevel;
399 ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode;
400 ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly;
401 ClientContext->ServerIsRemote = RemoteClient;
402 ClientContext->Token = NewToken;
404 return(STATUS_SUCCESS);
412 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
413 IN PETHREAD ServerThread OPTIONAL)
417 if (ClientContext->DirectlyAccessClientToken == FALSE)
419 b = ClientContext->SecurityQos.EffectiveOnly;
423 b = ClientContext->DirectAccessEffectiveOnly;
425 if (ServerThread == NULL)
427 ServerThread = PsGetCurrentThread();
429 PsImpersonateClient(ServerThread,
430 ClientContext->Token,
433 ClientContext->SecurityQos.ImpersonationLevel);
438 SepDeleteToken(PVOID ObjectBody)
440 PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody;
442 if (AccessToken->UserAndGroups)
443 ExFreePool(AccessToken->UserAndGroups);
445 if (AccessToken->Privileges)
446 ExFreePool(AccessToken->Privileges);
448 if (AccessToken->DefaultDacl)
449 ExFreePool(AccessToken->DefaultDacl);
454 SepInitializeTokenImplementation(VOID)
456 SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
458 SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T');
459 SepTokenObjectType->MaxObjects = ULONG_MAX;
460 SepTokenObjectType->MaxHandles = ULONG_MAX;
461 SepTokenObjectType->TotalObjects = 0;
462 SepTokenObjectType->TotalHandles = 0;
463 SepTokenObjectType->PagedPoolCharge = 0;
464 SepTokenObjectType->NonpagedPoolCharge = sizeof(ACCESS_TOKEN);
465 SepTokenObjectType->Mapping = &SepTokenMapping;
466 SepTokenObjectType->Dump = NULL;
467 SepTokenObjectType->Open = NULL;
468 SepTokenObjectType->Close = NULL;
469 SepTokenObjectType->Delete = SepDeleteToken;
470 SepTokenObjectType->Parse = NULL;
471 SepTokenObjectType->Security = NULL;
472 SepTokenObjectType->QueryName = NULL;
473 SepTokenObjectType->OkayToClose = NULL;
474 SepTokenObjectType->Create = NULL;
475 SepTokenObjectType->DuplicationNotify = NULL;
477 RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
486 NtQueryInformationToken(IN HANDLE TokenHandle,
487 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
488 OUT PVOID TokenInformation,
489 IN ULONG TokenInformationLength,
490 OUT PULONG ReturnLength)
496 PTOKEN_GROUPS PtrTokenGroups;
497 PTOKEN_DEFAULT_DACL PtrDefaultDacl;
498 PTOKEN_STATISTICS PtrTokenStatistics;
501 Status = ObReferenceObjectByHandle(TokenHandle,
502 (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
507 if (!NT_SUCCESS(Status))
512 switch (TokenInformationClass)
515 DPRINT("NtQueryInformationToken(TokenUser)\n");
516 uLength = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
517 if (TokenInformationLength < uLength)
519 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
520 if (NT_SUCCESS(Status))
521 Status = STATUS_BUFFER_TOO_SMALL;
525 Status = RtlCopySidAndAttributesArray(1,
526 Token->UserAndGroups,
527 TokenInformationLength,
529 TokenInformation + 8,
532 if (NT_SUCCESS(Status))
534 uLength = TokenInformationLength - uLength;
535 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
541 DPRINT("NtQueryInformationToken(TokenGroups)\n");
542 uLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(DWORD);
543 if (TokenInformationLength < uLength)
545 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
546 if (NT_SUCCESS(Status))
547 Status = STATUS_BUFFER_TOO_SMALL;
551 EndMem = TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES);
552 PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation;
553 PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1;
554 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
555 &Token->UserAndGroups[1],
556 TokenInformationLength,
557 PtrTokenGroups->Groups,
561 if (NT_SUCCESS(Status))
563 uLength = TokenInformationLength - uLength;
564 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
569 case TokenPrivileges:
570 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
571 uLength = sizeof(DWORD) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
572 if (TokenInformationLength < uLength)
574 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
575 if (NT_SUCCESS(Status))
576 Status = STATUS_BUFFER_TOO_SMALL;
581 TOKEN_PRIVILEGES* pPriv = (TOKEN_PRIVILEGES*)TokenInformation;
583 pPriv->PrivilegeCount = Token->PrivilegeCount;
584 for (i = 0; i < Token->PrivilegeCount; i++)
586 RtlCopyLuid(&pPriv->Privileges[i].Luid, &Token->Privileges[i].Luid);
587 pPriv->Privileges[i].Attributes = Token->Privileges[i].Attributes;
589 Status = STATUS_SUCCESS;
594 DPRINT("NtQueryInformationToken(TokenOwner)\n");
595 uLength = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
596 if (TokenInformationLength < uLength)
598 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
599 if (NT_SUCCESS(Status))
600 Status = STATUS_BUFFER_TOO_SMALL;
604 ((PTOKEN_OWNER)TokenInformation)->Owner =
605 (PSID)(((PTOKEN_OWNER)TokenInformation) + 1);
606 RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
607 ((PTOKEN_OWNER)TokenInformation)->Owner,
608 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
609 Status = STATUS_SUCCESS;
613 case TokenPrimaryGroup:
614 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
615 "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
616 uLength = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
617 if (TokenInformationLength < uLength)
619 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
620 if (NT_SUCCESS(Status))
621 Status = STATUS_BUFFER_TOO_SMALL;
625 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup =
626 (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1);
627 RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
628 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup,
629 Token->PrimaryGroup);
630 Status = STATUS_SUCCESS;
634 case TokenDefaultDacl:
635 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
636 PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation;
637 uLength = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
638 if (TokenInformationLength < uLength)
640 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
641 if (NT_SUCCESS(Status))
642 Status = STATUS_BUFFER_TOO_SMALL;
644 else if (!Token->DefaultDacl)
646 PtrDefaultDacl->DefaultDacl = 0;
647 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
651 PtrDefaultDacl->DefaultDacl = (PACL) (PtrDefaultDacl + 1);
652 memmove(PtrDefaultDacl->DefaultDacl,
654 Token->DefaultDacl->AclSize);
655 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
660 DPRINT("NtQueryInformationToken(TokenSource)\n");
661 if (TokenInformationLength < sizeof(TOKEN_SOURCE))
663 uLength = sizeof(TOKEN_SOURCE);
664 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
665 if (NT_SUCCESS(Status))
666 Status = STATUS_BUFFER_TOO_SMALL;
670 Status = MmCopyToCaller(TokenInformation, &Token->TokenSource, sizeof(TOKEN_SOURCE));
675 DPRINT("NtQueryInformationToken(TokenType)\n");
676 if (TokenInformationLength < sizeof(TOKEN_TYPE))
678 uLength = sizeof(TOKEN_TYPE);
679 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
680 if (NT_SUCCESS(Status))
681 Status = STATUS_BUFFER_TOO_SMALL;
685 Status = MmCopyToCaller(TokenInformation, &Token->TokenType, sizeof(TOKEN_TYPE));
689 case TokenImpersonationLevel:
690 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
691 if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL))
693 uLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
694 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
695 if (NT_SUCCESS(Status))
696 Status = STATUS_BUFFER_TOO_SMALL;
700 Status = MmCopyToCaller(TokenInformation, &Token->ImpersonationLevel, sizeof(SECURITY_IMPERSONATION_LEVEL));
704 case TokenStatistics:
705 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
706 if (TokenInformationLength < sizeof(TOKEN_STATISTICS))
708 uLength = sizeof(TOKEN_STATISTICS);
709 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
710 if (NT_SUCCESS(Status))
711 Status = STATUS_BUFFER_TOO_SMALL;
715 PtrTokenStatistics = (PTOKEN_STATISTICS)TokenInformation;
716 PtrTokenStatistics->TokenId = Token->TokenId;
717 PtrTokenStatistics->AuthenticationId = Token->AuthenticationId;
718 PtrTokenStatistics->ExpirationTime = Token->ExpirationTime;
719 PtrTokenStatistics->TokenType = Token->TokenType;
720 PtrTokenStatistics->ImpersonationLevel = Token->ImpersonationLevel;
721 PtrTokenStatistics->DynamicCharged = Token->DynamicCharged;
722 PtrTokenStatistics->DynamicAvailable = Token->DynamicAvailable;
723 PtrTokenStatistics->GroupCount = Token->UserAndGroupCount - 1;
724 PtrTokenStatistics->PrivilegeCount = Token->PrivilegeCount;
725 PtrTokenStatistics->ModifiedId = Token->ModifiedId;
727 Status = STATUS_SUCCESS;
732 ObDereferenceObject(Token);
739 NtSetInformationToken(IN HANDLE TokenHandle,
740 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
741 OUT PVOID TokenInformation,
742 IN ULONG TokenInformationLength)
752 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
753 IN ACCESS_MASK DesiredAccess,
754 IN POBJECT_ATTRIBUTES ObjectAttributes,
755 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
756 IN TOKEN_TYPE TokenType,
757 OUT PHANDLE NewTokenHandle)
761 PACCESS_TOKEN NewToken;
763 ULONG ExistingImpersonationLevel;
765 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
772 ExistingImpersonationLevel = Token->ImpersonationLevel;
773 SepDuplicateToken(Token,
777 ExistingImpersonationLevel,
785 VOID SepAdjustGroups(PACCESS_TOKEN Token,
787 BOOLEAN ResetToDefault,
788 PSID_AND_ATTRIBUTES Groups,
790 KPROCESSOR_MODE PreviousMode,
801 NtAdjustGroupsToken(IN HANDLE TokenHandle,
802 IN BOOLEAN ResetToDefault,
803 IN PTOKEN_GROUPS NewState,
804 IN ULONG BufferLength,
805 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
806 OUT PULONG ReturnLength)
815 Status = ObReferenceObjectByHandle(TokenHandle,
823 SepAdjustGroups(Token,
841 SepAdjustPrivileges(PACCESS_TOKEN Token,
843 KPROCESSOR_MODE PreviousMode,
844 ULONG PrivilegeCount,
845 PLUID_AND_ATTRIBUTES Privileges,
846 PTOKEN_PRIVILEGES* PreviousState,
855 if (Token->PrivilegeCount > 0)
857 for (i = 0; i < Token->PrivilegeCount; i++)
859 if (PreviousMode != KernelMode)
861 if (Token->Privileges[i]->Attributes & SE_PRIVILEGE_ENABLED == 0)
865 if (PreviousState != NULL)
867 memcpy(&PreviousState[i],
868 &Token->Privileges[i],
869 sizeof(LUID_AND_ATTRIBUTES));
871 Token->Privileges[i].Attributes &= (~SE_PRIVILEGE_ENABLED);
878 if (PreviousMode != KernelMode)
880 Token->TokenFlags = Token->TokenFlags & (~1);
884 if (PrivilegeCount <= ?)
897 NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
898 IN BOOLEAN DisableAllPrivileges,
899 IN PTOKEN_PRIVILEGES NewState,
900 IN ULONG BufferLength,
901 OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
902 OUT PULONG ReturnLength OPTIONAL)
904 // PLUID_AND_ATTRIBUTES Privileges;
905 KPROCESSOR_MODE PreviousMode;
906 // ULONG PrivilegeCount;
919 DPRINT ("NtAdjustPrivilegesToken() called\n");
921 // PrivilegeCount = NewState->PrivilegeCount;
922 PreviousMode = KeGetPreviousMode ();
923 // SeCaptureLuidAndAttributesArray(NewState->Privileges,
933 Status = ObReferenceObjectByHandle (TokenHandle,
934 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
939 if (!NT_SUCCESS(Status))
941 DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
942 // SeReleaseLuidAndAttributesArray(Privileges,
950 SepAdjustPrivileges(Token,
962 if (DisableAllPrivileges == TRUE)
964 for (i = 0; i < Token->PrivilegeCount; i++)
966 if (Token->Privileges[i].Attributes != 0)
968 DPRINT ("Attributes differ\n");
970 /* Save current privilege */
971 if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
973 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
974 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
978 /* Update current privlege */
979 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
985 for (i = 0; i < Token->PrivilegeCount; i++)
987 for (j = 0; j < NewState->PrivilegeCount; j++)
989 if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
990 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
992 DPRINT ("Found privilege\n");
994 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
995 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
997 DPRINT ("Attributes differ\n");
998 DPRINT ("Current attributes %lx desired attributes %lx\n",
999 Token->Privileges[i].Attributes,
1000 NewState->Privileges[j].Attributes);
1002 /* Save current privilege */
1003 if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
1005 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
1006 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
1010 /* Update current privlege */
1011 Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
1012 Token->Privileges[i].Attributes |=
1013 (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
1014 DPRINT ("New attributes %lx\n",
1015 Token->Privileges[i].Attributes);
1022 if (ReturnLength != NULL)
1024 *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
1025 (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
1028 ObDereferenceObject (Token);
1030 // SeReleaseLuidAndAttributesArray(Privileges,
1034 DPRINT ("NtAdjustPrivilegesToken() done\n");
1036 if (k < NewState->PrivilegeCount)
1038 return STATUS_NOT_ALL_ASSIGNED;
1041 return STATUS_SUCCESS;
1046 SepCreateSystemProcessToken(struct _EPROCESS* Process)
1052 ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
1053 ULONG uWorldLength = RtlLengthSid(SeWorldSid);
1054 ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
1055 ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
1057 PACCESS_TOKEN AccessToken;
1062 * Initialize the token
1064 Status = ObRosCreateObject(NULL,
1068 (PVOID*)&AccessToken);
1070 Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId);
1071 if (!NT_SUCCESS(Status))
1073 ObDereferenceObject(AccessToken);
1077 Status = NtAllocateLocallyUniqueId(&AccessToken->ModifiedId);
1078 if (!NT_SUCCESS(Status))
1080 ObDereferenceObject(AccessToken);
1084 AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
1085 AccessToken->AuthenticationId.HighPart = 0;
1087 AccessToken->TokenType = TokenPrimary;
1088 AccessToken->ImpersonationLevel = SecurityDelegation;
1089 AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
1090 AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
1091 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
1092 AccessToken->ExpirationTime.QuadPart = -1;
1093 AccessToken->UserAndGroupCount = 4;
1095 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1096 uSize += uLocalSystemLength;
1097 uSize += uWorldLength;
1098 uSize += uAuthUserLength;
1099 uSize += uAdminsLength;
1101 AccessToken->UserAndGroups =
1102 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1104 TAG('T', 'O', 'K', 'u'));
1105 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1108 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1109 AccessToken->UserAndGroups[i++].Attributes = 0;
1110 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
1111 SidArea += uLocalSystemLength;
1113 AccessToken->DefaultOwnerIndex = i;
1114 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1115 AccessToken->PrimaryGroup = (PSID) SidArea;
1116 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
1117 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
1118 SidArea += uAdminsLength;
1120 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1121 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1122 RtlCopySid(uWorldLength, SidArea, SeWorldSid);
1123 SidArea += uWorldLength;
1125 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1126 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1127 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
1128 SidArea += uAuthUserLength;
1130 AccessToken->PrivilegeCount = 20;
1132 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1133 AccessToken->Privileges =
1134 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1136 TAG('T', 'O', 'K', 'p'));
1139 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1140 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
1142 AccessToken->Privileges[i].Attributes = 0;
1143 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
1145 AccessToken->Privileges[i].Attributes = 0;
1146 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
1148 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1149 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
1151 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1152 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
1154 AccessToken->Privileges[i].Attributes = 0;
1155 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
1157 AccessToken->Privileges[i].Attributes = 0;
1158 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
1160 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1161 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
1163 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1164 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
1166 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1167 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
1169 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1170 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
1172 AccessToken->Privileges[i].Attributes = 0;
1173 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
1175 AccessToken->Privileges[i].Attributes = 0;
1176 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
1178 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1179 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
1181 AccessToken->Privileges[i].Attributes = 0;
1182 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
1184 AccessToken->Privileges[i].Attributes = 0;
1185 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
1187 AccessToken->Privileges[i].Attributes = 0;
1188 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
1190 AccessToken->Privileges[i].Attributes = 0;
1191 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
1193 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1194 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
1196 AccessToken->Privileges[i].Attributes = 0;
1197 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
1199 AccessToken->Privileges[i].Attributes = 0;
1200 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
1202 AccessToken->Privileges[i].Attributes = 0;
1203 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
1208 uSize = sizeof(ACL);
1209 uSize += sizeof(ACE) + uLocalSystemLength;
1210 uSize += sizeof(ACE) + uAdminsLength;
1211 uSize = (uSize & (~3)) + 8;
1212 AccessToken->DefaultDacl =
1213 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1215 TAG('T', 'O', 'K', 'd'));
1216 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
1217 if ( NT_SUCCESS(Status) )
1219 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
1222 if ( NT_SUCCESS(Status) )
1224 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
1227 if ( ! NT_SUCCESS(Status) )
1229 ObDereferenceObject(AccessToken);
1233 Process->Token = AccessToken;
1234 return(STATUS_SUCCESS);
1239 NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
1240 IN ACCESS_MASK DesiredAccess,
1241 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
1242 IN TOKEN_TYPE TokenType,
1243 IN PLUID AuthenticationId,
1244 IN PLARGE_INTEGER ExpirationTime,
1245 IN PTOKEN_USER TokenUser,
1246 IN PTOKEN_GROUPS TokenGroups,
1247 IN PTOKEN_PRIVILEGES TokenPrivileges,
1248 IN PTOKEN_OWNER TokenOwner,
1249 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1250 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1251 IN PTOKEN_SOURCE TokenSource)
1254 PACCESS_TOKEN AccessToken;
1256 OBJECT_ATTRIBUTES SafeObjectAttributes;
1257 POBJECT_ATTRIBUTES ObjectAttributes;
1264 Status = MmCopyFromCaller(&SafeObjectAttributes,
1265 UnsafeObjectAttributes,
1266 sizeof(OBJECT_ATTRIBUTES));
1267 if (!NT_SUCCESS(Status))
1270 ObjectAttributes = &SafeObjectAttributes;
1272 Status = ZwAllocateLocallyUniqueId(&TokenId);
1273 if (!NT_SUCCESS(Status))
1276 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
1277 if (!NT_SUCCESS(Status))
1280 Status = ObRosCreateObject(&TokenHandle,
1284 (PVOID*)&AccessToken);
1285 if (!NT_SUCCESS(Status))
1287 DPRINT1("ObRosCreateObject() failed (Status %lx)\n");
1291 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1292 &TokenSource->SourceIdentifier);
1293 memcpy(AccessToken->TokenSource.SourceName,
1294 TokenSource->SourceName,
1295 sizeof(TokenSource->SourceName));
1297 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1298 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1299 AccessToken->ExpirationTime = *ExpirationTime;
1300 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1302 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
1303 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
1304 AccessToken->UserAndGroups = 0;
1305 AccessToken->Privileges = 0;
1307 AccessToken->TokenType = TokenType;
1308 AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel;
1311 * Normally we would just point these members into the variable information
1312 * area; however, our ObRosCreateObject() call can't allocate a variable information
1313 * area, so we allocate them seperately and provide a destroy function.
1316 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1317 uLength += RtlLengthSid(TokenUser->User.Sid);
1318 for (i = 0; i < TokenGroups->GroupCount; i++)
1319 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
1321 AccessToken->UserAndGroups =
1322 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1324 TAG('T', 'O', 'K', 'u'));
1326 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1328 Status = RtlCopySidAndAttributesArray(1,
1331 AccessToken->UserAndGroups,
1335 if (NT_SUCCESS(Status))
1337 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
1338 TokenGroups->Groups,
1340 &AccessToken->UserAndGroups[1],
1346 if (NT_SUCCESS(Status))
1348 Status = SepFindPrimaryGroupAndDefaultOwner(
1350 TokenPrimaryGroup->PrimaryGroup,
1354 if (NT_SUCCESS(Status))
1356 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1357 AccessToken->Privileges =
1358 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1360 TAG('T', 'O', 'K', 'p'));
1362 for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
1364 Status = MmCopyFromCaller(&AccessToken->Privileges[i],
1365 &TokenPrivileges->Privileges[i],
1366 sizeof(LUID_AND_ATTRIBUTES));
1367 if (!NT_SUCCESS(Status))
1372 if (NT_SUCCESS(Status))
1374 AccessToken->DefaultDacl =
1375 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1376 TokenDefaultDacl->DefaultDacl->AclSize,
1377 TAG('T', 'O', 'K', 'd'));
1378 memcpy(AccessToken->DefaultDacl,
1379 TokenDefaultDacl->DefaultDacl,
1380 TokenDefaultDacl->DefaultDacl->AclSize);
1383 ObDereferenceObject(AccessToken);
1385 if (NT_SUCCESS(Status))
1387 Status = MmCopyToCaller(UnsafeTokenHandle,
1392 if (!NT_SUCCESS(Status))
1394 ZwClose(TokenHandle);
1398 return(STATUS_SUCCESS);
1405 SECURITY_IMPERSONATION_LEVEL STDCALL
1406 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
1408 return(Token->ImpersonationLevel);
1416 SeTokenType(IN PACCESS_TOKEN Token)
1418 return(Token->TokenType);