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 *****************************************************************/
38 VOID SepFreeProxyData(PVOID ProxyData)
43 NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src)
48 NTSTATUS SeExchangePrimaryToken(PEPROCESS Process,
49 PACCESS_TOKEN NewToken,
50 PACCESS_TOKEN* OldTokenP)
52 PACCESS_TOKEN OldToken;
54 if (NewToken->TokenType != TokenPrimary)
56 return(STATUS_UNSUCCESSFUL);
58 if (NewToken->TokenInUse != 0)
60 return(STATUS_UNSUCCESSFUL);
62 OldToken = Process->Token;
63 Process->Token = NewToken;
64 NewToken->TokenInUse = 1;
65 ObReferenceObjectByPointer(NewToken,
69 OldToken->TokenInUse = 0;
70 *OldTokenP = OldToken;
71 return(STATUS_SUCCESS);
75 RtlLengthSidAndAttributes(ULONG Count,
76 PSID_AND_ATTRIBUTES Src)
81 uLength = Count * sizeof(SID_AND_ATTRIBUTES);
82 for (i = 0; i < Count; i++)
83 uLength += RtlLengthSid(Src[i].Sid);
90 SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token,
96 Token->PrimaryGroup = 0;
100 Token->DefaultOwnerIndex = Token->UserAndGroupCount;
103 /* Validate and set the primary group and user pointers */
104 for (i = 0; i < Token->UserAndGroupCount; i++)
107 RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner))
109 Token->DefaultOwnerIndex = i;
112 if (RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup))
114 Token->PrimaryGroup = Token->UserAndGroups[i].Sid;
118 if (Token->DefaultOwnerIndex == Token->UserAndGroupCount)
120 return(STATUS_INVALID_OWNER);
123 if (Token->PrimaryGroup == 0)
125 return(STATUS_INVALID_PRIMARY_GROUP);
128 return(STATUS_SUCCESS);
133 SepDuplicateToken(PACCESS_TOKEN Token,
134 POBJECT_ATTRIBUTES ObjectAttributes,
135 TOKEN_TYPE TokenType,
136 SECURITY_IMPERSONATION_LEVEL Level,
137 SECURITY_IMPERSONATION_LEVEL ExistingLevel,
138 KPROCESSOR_MODE PreviousMode,
139 PACCESS_TOKEN* NewAccessToken)
147 PACCESS_TOKEN AccessToken;
149 Status = ObCreateObject(0,
153 (PVOID*)&AccessToken);
154 if (!NT_SUCCESS(Status))
156 DPRINT1("ObCreateObject() failed (Status %lx)\n");
160 Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
161 if (!NT_SUCCESS(Status))
163 ObDereferenceObject(AccessToken);
167 Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
168 if (!NT_SUCCESS(Status))
170 ObDereferenceObject(AccessToken);
174 AccessToken->TokenInUse = 0;
175 AccessToken->TokenType = TokenType;
176 AccessToken->ImpersonationLevel = Level;
177 AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID;
179 AccessToken->TokenSource.SourceIdentifier.QuadPart = Token->TokenSource.SourceIdentifier.QuadPart;
180 memcpy(AccessToken->TokenSource.SourceName, Token->TokenSource.SourceName, sizeof(Token->TokenSource.SourceName));
181 AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
182 AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
183 AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
185 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
186 for (i = 0; i < Token->UserAndGroupCount; i++)
187 uLength += RtlLengthSid(Token->UserAndGroups[i].Sid);
189 AccessToken->UserAndGroups =
190 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
192 TAG('T', 'O', 'K', 'u'));
194 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
196 Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount,
197 Token->UserAndGroups,
199 AccessToken->UserAndGroups,
203 if (NT_SUCCESS(Status))
205 Status = SepFindPrimaryGroupAndDefaultOwner(
211 if (NT_SUCCESS(Status))
213 AccessToken->PrivilegeCount = Token->PrivilegeCount;
215 uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
216 AccessToken->Privileges =
217 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
219 TAG('T', 'O', 'K', 'p'));
221 for (i = 0; i < AccessToken->PrivilegeCount; i++)
223 RtlCopyLuid(&AccessToken->Privileges[i].Luid,
224 &Token->Privileges[i].Luid);
225 AccessToken->Privileges[i].Attributes =
226 Token->Privileges[i].Attributes;
229 if ( Token->DefaultDacl )
231 AccessToken->DefaultDacl =
232 (PACL) ExAllocatePoolWithTag(NonPagedPool,
233 Token->DefaultDacl->AclSize,
234 TAG('T', 'O', 'K', 'd'));
235 memcpy(AccessToken->DefaultDacl,
237 Token->DefaultDacl->AclSize);
241 AccessToken->DefaultDacl = 0;
245 if ( NT_SUCCESS(Status) )
247 *NewAccessToken = AccessToken;
248 return(STATUS_SUCCESS);
251 ObDereferenceObject(AccessToken);
257 SepInitializeNewProcess(struct _EPROCESS* NewProcess,
258 struct _EPROCESS* ParentProcess)
261 PACCESS_TOKEN pNewToken;
262 PACCESS_TOKEN pParentToken;
264 OBJECT_ATTRIBUTES ObjectAttributes;
266 pParentToken = (PACCESS_TOKEN) ParentProcess->Token;
268 InitializeObjectAttributes(&ObjectAttributes,
274 Status = SepDuplicateToken(pParentToken,
277 pParentToken->ImpersonationLevel,
278 pParentToken->ImpersonationLevel,
281 if ( ! NT_SUCCESS(Status) )
284 NewProcess->Token = pNewToken;
285 return(STATUS_SUCCESS);
289 NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
290 SECURITY_IMPERSONATION_LEVEL Level,
291 KPROCESSOR_MODE PreviousMode,
292 PACCESS_TOKEN* NewToken)
295 OBJECT_ATTRIBUTES ObjectAttributes;
297 InitializeObjectAttributes(&ObjectAttributes,
302 Status = SepDuplicateToken(Token,
305 SecurityIdentification,
314 SeCreateClientSecurity(IN struct _ETHREAD *Thread,
315 IN PSECURITY_QUALITY_OF_SERVICE Qos,
316 IN BOOLEAN RemoteClient,
317 OUT PSECURITY_CLIENT_CONTEXT ClientContext)
319 TOKEN_TYPE TokenType;
321 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
324 PACCESS_TOKEN NewToken;
326 Token = PsReferenceEffectiveToken(Thread,
329 &ImpersonationLevel);
332 ClientContext->DirectAccessEffectiveOnly = Qos->EffectiveOnly;
336 if (Qos->ImpersonationLevel > ImpersonationLevel)
340 ObDereferenceObject(Token);
342 return(STATUS_UNSUCCESSFUL);
344 if (ImpersonationLevel == 0 ||
345 ImpersonationLevel == 1 ||
346 (RemoteClient != FALSE && ImpersonationLevel != 3))
350 ObDereferenceObject(Token);
352 return(STATUS_UNSUCCESSFUL);
355 Qos->EffectiveOnly != 0)
357 ClientContext->DirectAccessEffectiveOnly = TRUE;
361 ClientContext->DirectAccessEffectiveOnly = FALSE;
365 if (Qos->ContextTrackingMode == 0)
367 ClientContext->DirectlyAccessClientToken = FALSE;
368 g = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken);
371 // ObDeleteCapturedInsertInfo(NewToken);
373 if (TokenType == TokenPrimary || Token != NULL)
375 ObDereferenceObject(Token);
384 ClientContext->DirectlyAccessClientToken = TRUE;
385 if (RemoteClient != FALSE)
387 // SeGetTokenControlInformation(Token, &ClientContext->Unknown11);
391 ClientContext->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
392 ClientContext->SecurityQos.ImpersonationLevel = Qos->ImpersonationLevel;
393 ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode;
394 ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly;
395 ClientContext->ServerIsRemote = RemoteClient;
396 ClientContext->Token = NewToken;
398 return(STATUS_SUCCESS);
403 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
404 IN PETHREAD ServerThread OPTIONAL)
408 if (ClientContext->DirectlyAccessClientToken == FALSE)
410 b = ClientContext->SecurityQos.EffectiveOnly;
414 b = ClientContext->DirectAccessEffectiveOnly;
416 if (ServerThread == NULL)
418 ServerThread = PsGetCurrentThread();
420 PsImpersonateClient(ServerThread,
421 ClientContext->Token,
424 ClientContext->SecurityQos.ImpersonationLevel);
427 #endif /* LIBCAPTIVE */
430 SepDeleteToken(PVOID ObjectBody)
432 PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody;
434 if (AccessToken->UserAndGroups)
435 ExFreePool(AccessToken->UserAndGroups);
437 if (AccessToken->Privileges)
438 ExFreePool(AccessToken->Privileges);
440 if (AccessToken->DefaultDacl)
441 ExFreePool(AccessToken->DefaultDacl);
446 SepInitializeTokenImplementation(VOID)
448 SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
450 SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T');
451 SepTokenObjectType->MaxObjects = ULONG_MAX;
452 SepTokenObjectType->MaxHandles = ULONG_MAX;
453 SepTokenObjectType->TotalObjects = 0;
454 SepTokenObjectType->TotalHandles = 0;
455 SepTokenObjectType->PagedPoolCharge = 0;
456 SepTokenObjectType->NonpagedPoolCharge = sizeof(ACCESS_TOKEN);
457 SepTokenObjectType->Mapping = &SepTokenMapping;
458 SepTokenObjectType->Dump = NULL;
459 SepTokenObjectType->Open = NULL;
460 SepTokenObjectType->Close = NULL;
461 SepTokenObjectType->Delete = SepDeleteToken;
462 SepTokenObjectType->Parse = NULL;
463 SepTokenObjectType->Security = NULL;
464 SepTokenObjectType->QueryName = NULL;
465 SepTokenObjectType->OkayToClose = NULL;
466 SepTokenObjectType->Create = NULL;
467 SepTokenObjectType->DuplicationNotify = NULL;
469 RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
470 REACTOS_UCS2(L"Token"));
476 NtQueryInformationToken(IN HANDLE TokenHandle,
477 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
478 OUT PVOID TokenInformation,
479 IN ULONG TokenInformationLength,
480 OUT PULONG ReturnLength)
486 PTOKEN_GROUPS PtrTokenGroups;
487 PTOKEN_DEFAULT_DACL PtrDefaultDacl;
488 PTOKEN_STATISTICS PtrTokenStatistics;
491 Status = ObReferenceObjectByHandle(TokenHandle,
492 (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
497 if (!NT_SUCCESS(Status))
502 switch (TokenInformationClass)
505 DPRINT("NtQueryInformationToken(TokenUser)\n");
506 uLength = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
507 if (TokenInformationLength < uLength)
509 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
510 if (NT_SUCCESS(Status))
511 Status = STATUS_BUFFER_TOO_SMALL;
515 Status = RtlCopySidAndAttributesArray(1,
516 Token->UserAndGroups,
517 TokenInformationLength,
519 TokenInformation + 8,
522 if (NT_SUCCESS(Status))
524 uLength = TokenInformationLength - uLength;
525 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
531 DPRINT("NtQueryInformationToken(TokenGroups)\n");
532 uLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(DWORD);
533 if (TokenInformationLength < uLength)
535 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
536 if (NT_SUCCESS(Status))
537 Status = STATUS_BUFFER_TOO_SMALL;
541 EndMem = TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES);
542 PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation;
543 PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1;
544 Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
545 &Token->UserAndGroups[1],
546 TokenInformationLength,
547 PtrTokenGroups->Groups,
551 if (NT_SUCCESS(Status))
553 uLength = TokenInformationLength - uLength;
554 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
559 case TokenPrivileges:
560 DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
561 uLength = sizeof(DWORD) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
562 if (TokenInformationLength < uLength)
564 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
565 if (NT_SUCCESS(Status))
566 Status = STATUS_BUFFER_TOO_SMALL;
571 TOKEN_PRIVILEGES* pPriv = (TOKEN_PRIVILEGES*)TokenInformation;
573 pPriv->PrivilegeCount = Token->PrivilegeCount;
574 for (i = 0; i < Token->PrivilegeCount; i++)
576 RtlCopyLuid(&pPriv->Privileges[i].Luid, &Token->Privileges[i].Luid);
577 pPriv->Privileges[i].Attributes = Token->Privileges[i].Attributes;
579 Status = STATUS_SUCCESS;
584 DPRINT("NtQueryInformationToken(TokenOwner)\n");
585 uLength = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
586 if (TokenInformationLength < uLength)
588 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
589 if (NT_SUCCESS(Status))
590 Status = STATUS_BUFFER_TOO_SMALL;
594 ((PTOKEN_OWNER)TokenInformation)->Owner =
595 (PSID)(((PTOKEN_OWNER)TokenInformation) + 1);
596 RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
597 ((PTOKEN_OWNER)TokenInformation)->Owner,
598 Token->UserAndGroups[Token->DefaultOwnerIndex].Sid);
599 Status = STATUS_SUCCESS;
603 case TokenPrimaryGroup:
604 DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
605 "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
606 uLength = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
607 if (TokenInformationLength < uLength)
609 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
610 if (NT_SUCCESS(Status))
611 Status = STATUS_BUFFER_TOO_SMALL;
615 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup =
616 (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1);
617 RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
618 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup,
619 Token->PrimaryGroup);
620 Status = STATUS_SUCCESS;
624 case TokenDefaultDacl:
625 DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
626 PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation;
627 uLength = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
628 if (TokenInformationLength < uLength)
630 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
631 if (NT_SUCCESS(Status))
632 Status = STATUS_BUFFER_TOO_SMALL;
634 else if (!Token->DefaultDacl)
636 PtrDefaultDacl->DefaultDacl = 0;
637 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
641 PtrDefaultDacl->DefaultDacl = (PACL) (PtrDefaultDacl + 1);
642 memmove(PtrDefaultDacl->DefaultDacl,
644 Token->DefaultDacl->AclSize);
645 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
650 DPRINT("NtQueryInformationToken(TokenSource)\n");
651 if (TokenInformationLength < sizeof(TOKEN_SOURCE))
653 uLength = sizeof(TOKEN_SOURCE);
654 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
655 if (NT_SUCCESS(Status))
656 Status = STATUS_BUFFER_TOO_SMALL;
660 Status = MmCopyToCaller(TokenInformation, &Token->TokenSource, sizeof(TOKEN_SOURCE));
665 DPRINT("NtQueryInformationToken(TokenType)\n");
666 if (TokenInformationLength < sizeof(TOKEN_TYPE))
668 uLength = sizeof(TOKEN_TYPE);
669 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
670 if (NT_SUCCESS(Status))
671 Status = STATUS_BUFFER_TOO_SMALL;
675 Status = MmCopyToCaller(TokenInformation, &Token->TokenType, sizeof(TOKEN_TYPE));
679 case TokenImpersonationLevel:
680 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
681 if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL))
683 uLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
684 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
685 if (NT_SUCCESS(Status))
686 Status = STATUS_BUFFER_TOO_SMALL;
690 Status = MmCopyToCaller(TokenInformation, &Token->ImpersonationLevel, sizeof(SECURITY_IMPERSONATION_LEVEL));
694 case TokenStatistics:
695 DPRINT("NtQueryInformationToken(TokenStatistics)\n");
696 if (TokenInformationLength < sizeof(TOKEN_STATISTICS))
698 uLength = sizeof(TOKEN_STATISTICS);
699 Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
700 if (NT_SUCCESS(Status))
701 Status = STATUS_BUFFER_TOO_SMALL;
705 PtrTokenStatistics = (PTOKEN_STATISTICS)TokenInformation;
706 PtrTokenStatistics->TokenId = Token->TokenId;
707 PtrTokenStatistics->AuthenticationId = Token->AuthenticationId;
708 PtrTokenStatistics->ExpirationTime = Token->ExpirationTime;
709 PtrTokenStatistics->TokenType = Token->TokenType;
710 PtrTokenStatistics->ImpersonationLevel = Token->ImpersonationLevel;
711 PtrTokenStatistics->DynamicCharged = Token->DynamicCharged;
712 PtrTokenStatistics->DynamicAvailable = Token->DynamicAvailable;
713 PtrTokenStatistics->GroupCount = Token->UserAndGroupCount - 1;
714 PtrTokenStatistics->PrivilegeCount = Token->PrivilegeCount;
715 PtrTokenStatistics->ModifiedId = Token->ModifiedId;
717 Status = STATUS_SUCCESS;
722 ObDereferenceObject(Token);
729 NtSetInformationToken(IN HANDLE TokenHandle,
730 IN TOKEN_INFORMATION_CLASS TokenInformationClass,
731 OUT PVOID TokenInformation,
732 IN ULONG TokenInformationLength)
739 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
740 IN ACCESS_MASK DesiredAccess,
741 IN POBJECT_ATTRIBUTES ObjectAttributes,
742 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
743 IN TOKEN_TYPE TokenType,
744 OUT PHANDLE NewTokenHandle)
748 PACCESS_TOKEN NewToken;
750 ULONG ExistingImpersonationLevel;
752 Status = ObReferenceObjectByHandle(ExistingTokenHandle,
759 ExistingImpersonationLevel = Token->ImpersonationLevel;
760 SepDuplicateToken(Token,
764 ExistingImpersonationLevel,
772 VOID SepAdjustGroups(PACCESS_TOKEN Token,
774 BOOLEAN ResetToDefault,
775 PSID_AND_ATTRIBUTES Groups,
777 KPROCESSOR_MODE PreviousMode,
788 NtAdjustGroupsToken(IN HANDLE TokenHandle,
789 IN BOOLEAN ResetToDefault,
790 IN PTOKEN_GROUPS NewState,
791 IN ULONG BufferLength,
792 OUT PTOKEN_GROUPS PreviousState OPTIONAL,
793 OUT PULONG ReturnLength)
802 Status = ObReferenceObjectByHandle(TokenHandle,
810 SepAdjustGroups(Token,
827 NTSTATUS SepAdjustPrivileges(PACCESS_TOKEN Token, // 0x8
829 KPROCESSOR_MODE PreviousMode, // 0x10
830 ULONG PrivilegeCount, // 0x14
831 PLUID_AND_ATTRIBUTES Privileges, // 0x18
832 PTOKEN_PRIVILEGES* PreviousState, // 0x1C
840 if (Token->PrivilegeCount > 0)
842 for (i=0; i<Token->PrivilegeCount; i++)
844 if (PreviousMode != 0)
846 if (!(Token->Privileges[i]->Attributes &
847 SE_PRIVILEGE_ENABLED))
851 if (PreviousState != NULL)
853 memcpy(&PreviousState[i],
854 &Token->Privileges[i],
855 sizeof(LUID_AND_ATTRIBUTES));
857 Token->Privileges[i].Attributes =
858 Token->Privileges[i].Attributes &
859 (~SE_PRIVILEGE_ENABLED);
865 if (PreviousMode != 0)
867 Token->TokenFlags = Token->TokenFlags & (~1);
871 if (PrivilegeCount <= ?)
882 NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
883 IN BOOLEAN DisableAllPrivileges,
884 IN PTOKEN_PRIVILEGES NewState,
885 IN ULONG BufferLength,
886 OUT PTOKEN_PRIVILEGES PreviousState,
887 OUT PULONG ReturnLength)
890 ULONG PrivilegeCount;
892 PSID_AND_ATTRIBUTES Privileges;
897 PrivilegeCount = NewState->PrivilegeCount;
899 SeCaptureLuidAndAttributesArray(NewState->Privileges,
908 SepAdjustPrivileges(Token,
922 #endif /* LIBCAPTIVE */
925 SepCreateSystemProcessToken(struct _EPROCESS* Process)
931 ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
932 ULONG uWorldLength = RtlLengthSid(SeWorldSid);
933 ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid);
934 ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid);
936 PACCESS_TOKEN AccessToken;
941 * Initialize the token
943 Status = ObCreateObject(NULL,
947 (PVOID*)&AccessToken);
949 Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId);
950 if (!NT_SUCCESS(Status))
952 ObDereferenceObject(AccessToken);
956 Status = NtAllocateLocallyUniqueId(&AccessToken->ModifiedId);
957 if (!NT_SUCCESS(Status))
959 ObDereferenceObject(AccessToken);
963 AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID;
965 AccessToken->TokenType = TokenPrimary;
966 AccessToken->ImpersonationLevel = SecurityDelegation;
967 AccessToken->TokenSource.SourceIdentifier.QuadPart = 0;
968 memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
969 AccessToken->ExpirationTime.QuadPart = -1;
970 AccessToken->UserAndGroupCount = 4;
972 uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
973 uSize += uLocalSystemLength;
974 uSize += uWorldLength;
975 uSize += uAuthUserLength;
976 uSize += uAdminsLength;
978 AccessToken->UserAndGroups =
979 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
981 TAG('T', 'O', 'K', 'u'));
982 SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
985 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
986 AccessToken->UserAndGroups[i++].Attributes = 0;
987 RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
988 SidArea += uLocalSystemLength;
990 AccessToken->DefaultOwnerIndex = i;
991 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
992 AccessToken->PrimaryGroup = (PSID) SidArea;
993 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
994 Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
995 SidArea += uAdminsLength;
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(uWorldLength, SidArea, SeWorldSid);
1000 SidArea += uWorldLength;
1002 AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
1003 AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
1004 RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
1005 SidArea += uAuthUserLength;
1007 AccessToken->PrivilegeCount = 20;
1009 uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1010 AccessToken->Privileges =
1011 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1013 TAG('T', 'O', 'K', 'p'));
1016 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1017 AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
1019 AccessToken->Privileges[i].Attributes = 0;
1020 AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
1022 AccessToken->Privileges[i].Attributes = 0;
1023 AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
1025 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1026 AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
1028 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1029 AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
1031 AccessToken->Privileges[i].Attributes = 0;
1032 AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
1034 AccessToken->Privileges[i].Attributes = 0;
1035 AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
1037 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1038 AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
1040 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1041 AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
1043 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1044 AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
1046 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1047 AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
1049 AccessToken->Privileges[i].Attributes = 0;
1050 AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
1052 AccessToken->Privileges[i].Attributes = 0;
1053 AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
1055 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1056 AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
1058 AccessToken->Privileges[i].Attributes = 0;
1059 AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
1061 AccessToken->Privileges[i].Attributes = 0;
1062 AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
1064 AccessToken->Privileges[i].Attributes = 0;
1065 AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
1067 AccessToken->Privileges[i].Attributes = 0;
1068 AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
1070 AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
1071 AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
1073 AccessToken->Privileges[i].Attributes = 0;
1074 AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
1076 AccessToken->Privileges[i].Attributes = 0;
1077 AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
1079 AccessToken->Privileges[i].Attributes = 0;
1080 AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
1085 uSize = sizeof(ACL);
1086 uSize += sizeof(ACE) + uLocalSystemLength;
1087 uSize += sizeof(ACE) + uAdminsLength;
1088 uSize = (uSize & (~3)) + 8;
1089 AccessToken->DefaultDacl =
1090 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1092 TAG('T', 'O', 'K', 'd'));
1093 Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
1094 if ( NT_SUCCESS(Status) )
1096 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
1099 if ( NT_SUCCESS(Status) )
1101 Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
1104 if ( ! NT_SUCCESS(Status) )
1106 ObDereferenceObject(AccessToken);
1110 Process->Token = AccessToken;
1111 return(STATUS_SUCCESS);
1117 NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
1118 IN ACCESS_MASK DesiredAccess,
1119 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
1120 IN TOKEN_TYPE TokenType,
1121 IN PLUID AuthenticationId,
1122 IN PLARGE_INTEGER ExpirationTime,
1123 IN PTOKEN_USER TokenUser,
1124 IN PTOKEN_GROUPS TokenGroups,
1125 IN PTOKEN_PRIVILEGES TokenPrivileges,
1126 IN PTOKEN_OWNER TokenOwner,
1127 IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
1128 IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
1129 IN PTOKEN_SOURCE TokenSource)
1132 PACCESS_TOKEN AccessToken;
1134 OBJECT_ATTRIBUTES SafeObjectAttributes;
1135 POBJECT_ATTRIBUTES ObjectAttributes;
1142 Status = MmCopyFromCaller(&SafeObjectAttributes,
1143 UnsafeObjectAttributes,
1144 sizeof(OBJECT_ATTRIBUTES));
1145 if (!NT_SUCCESS(Status))
1148 ObjectAttributes = &SafeObjectAttributes;
1150 Status = ZwAllocateLocallyUniqueId(&TokenId);
1151 if (!NT_SUCCESS(Status))
1154 Status = ZwAllocateLocallyUniqueId(&ModifiedId);
1155 if (!NT_SUCCESS(Status))
1158 Status = ObCreateObject(&TokenHandle,
1162 (PVOID*)&AccessToken);
1163 if (!NT_SUCCESS(Status))
1165 DPRINT1("ObCreateObject() failed (Status %lx)\n");
1169 RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
1170 &TokenSource->SourceIdentifier);
1171 memcpy(AccessToken->TokenSource.SourceName,
1172 TokenSource->SourceName,
1173 sizeof(TokenSource->SourceName));
1175 RtlCopyLuid(&AccessToken->TokenId, &TokenId);
1176 RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
1177 AccessToken->ExpirationTime = *ExpirationTime;
1178 RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
1180 AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
1181 AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount;
1182 AccessToken->UserAndGroups = 0;
1183 AccessToken->Privileges = 0;
1185 AccessToken->TokenType = TokenType;
1186 AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel;
1189 * Normally we would just point these members into the variable information
1190 * area; however, our ObCreateObject() call can't allocate a variable information
1191 * area, so we allocate them seperately and provide a destroy function.
1194 uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
1195 uLength += RtlLengthSid(TokenUser->User.Sid);
1196 for (i = 0; i < TokenGroups->GroupCount; i++)
1197 uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
1199 AccessToken->UserAndGroups =
1200 (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1202 TAG('T', 'O', 'K', 'u'));
1204 EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
1206 Status = RtlCopySidAndAttributesArray(1,
1209 AccessToken->UserAndGroups,
1213 if (NT_SUCCESS(Status))
1215 Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
1216 TokenGroups->Groups,
1218 &AccessToken->UserAndGroups[1],
1224 if (NT_SUCCESS(Status))
1226 Status = SepFindPrimaryGroupAndDefaultOwner(
1228 TokenPrimaryGroup->PrimaryGroup,
1232 if (NT_SUCCESS(Status))
1234 uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
1235 AccessToken->Privileges =
1236 (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool,
1238 TAG('T', 'O', 'K', 'p'));
1240 for (i = 0; i < TokenPrivileges->PrivilegeCount; i++)
1242 Status = MmCopyFromCaller(&AccessToken->Privileges[i],
1243 &TokenPrivileges->Privileges[i],
1244 sizeof(LUID_AND_ATTRIBUTES));
1245 if (!NT_SUCCESS(Status))
1250 if (NT_SUCCESS(Status))
1252 AccessToken->DefaultDacl =
1253 (PACL) ExAllocatePoolWithTag(NonPagedPool,
1254 TokenDefaultDacl->DefaultDacl->AclSize,
1255 TAG('T', 'O', 'K', 'd'));
1256 memcpy(AccessToken->DefaultDacl,
1257 TokenDefaultDacl->DefaultDacl,
1258 TokenDefaultDacl->DefaultDacl->AclSize);
1261 ObDereferenceObject(AccessToken);
1263 if (NT_SUCCESS(Status))
1265 Status = MmCopyToCaller(UnsafeTokenHandle,
1270 if (!NT_SUCCESS(Status))
1272 ZwClose(TokenHandle);
1276 return(STATUS_SUCCESS);
1280 SECURITY_IMPERSONATION_LEVEL STDCALL
1281 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
1283 return(Token->ImpersonationLevel);
1288 SeTokenType(IN PACCESS_TOKEN Token)
1290 return(Token->TokenType);
1293 #endif /* LIBCAPTIVE */