Author: tkreuzer
Date: Fri Jan 17 22:11:10 2014
New Revision: 61662
URL:
http://svn.reactos.org/svn/reactos?rev=61662&view=rev
Log:
[NTOSKRNL]
Fix the s*** out of SepCreateToken and NtCreateToken: respect optional arguments, do not
access usermode memory without SEH, instead properly capture them, don't allocate 0
bytes from the pool, better argument verification. The function isn't perfect yet, but
better and more secure.
Modified:
trunk/reactos/ntoskrnl/se/token.c
Modified: trunk/reactos/ntoskrnl/se/token.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=61…
==============================================================================
--- trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] Fri Jan 17 22:11:10 2014
@@ -738,6 +738,7 @@
for (i = 0; i < GroupCount; i++)
uLength += RtlLengthSid(Groups[i].Sid);
+ // FIXME: should use the object itself
AccessToken->UserAndGroups = ExAllocatePoolWithTag(PagedPool,
uLength,
TAG_TOKEN_USERS);
@@ -775,7 +776,9 @@
if (!NT_SUCCESS(Status))
goto done;
+ // FIXME: should use the object itself
uLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+ if (uLength == 0) uLength = sizeof(PVOID);
AccessToken->Privileges = ExAllocatePoolWithTag(PagedPool,
uLength,
TAG_TOKEN_PRIVILAGES);
@@ -812,18 +815,26 @@
/* Update privilege flags */
SepUpdatePrivilegeFlagsToken(AccessToken);
- AccessToken->DefaultDacl = ExAllocatePoolWithTag(PagedPool,
- DefaultDacl->AclSize,
- TAG_TOKEN_ACL);
- if (AccessToken->DefaultDacl == NULL)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto done;
- }
-
- RtlCopyMemory(AccessToken->DefaultDacl,
- DefaultDacl,
- DefaultDacl->AclSize);
+ if (DefaultDacl != NULL)
+ {
+ // FIXME: should use the object itself
+ AccessToken->DefaultDacl = ExAllocatePoolWithTag(PagedPool,
+ DefaultDacl->AclSize,
+ TAG_TOKEN_ACL);
+ if (AccessToken->DefaultDacl == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ RtlCopyMemory(AccessToken->DefaultDacl,
+ DefaultDacl,
+ DefaultDacl->AclSize);
+ }
+ else
+ {
+ AccessToken->DefaultDacl = NULL;
+ }
if (!SystemToken)
{
@@ -2376,24 +2387,37 @@
NTSTATUS
NTAPI
-NtCreateToken(OUT PHANDLE TokenHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN TOKEN_TYPE TokenType,
- IN PLUID AuthenticationId,
- IN PLARGE_INTEGER ExpirationTime,
- IN PTOKEN_USER TokenUser,
- IN PTOKEN_GROUPS TokenGroups,
- IN PTOKEN_PRIVILEGES TokenPrivileges,
- IN PTOKEN_OWNER TokenOwner,
- IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
- IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
- IN PTOKEN_SOURCE TokenSource)
+NtCreateToken(
+ _Out_ PHANDLE TokenHandle,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
+ _In_ TOKEN_TYPE TokenType,
+ _In_ PLUID AuthenticationId,
+ _In_ PLARGE_INTEGER ExpirationTime,
+ _In_ PTOKEN_USER TokenUser,
+ _In_ PTOKEN_GROUPS TokenGroups,
+ _In_ PTOKEN_PRIVILEGES TokenPrivileges,
+ _In_opt_ PTOKEN_OWNER TokenOwner,
+ _In_ PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
+ _In_opt_ PTOKEN_DEFAULT_DACL TokenDefaultDacl,
+ _In_ PTOKEN_SOURCE TokenSource)
{
HANDLE hToken;
KPROCESSOR_MODE PreviousMode;
- ULONG nTokenPrivileges = 0;
+ ULONG PrivilegeCount, GroupCount;
+ PSID OwnerSid, PrimaryGroupSid;
+ PACL DefaultDacl;
LARGE_INTEGER LocalExpirationTime = {{0, 0}};
+ LUID LocalAuthenticationId;
+ TOKEN_SOURCE LocalTokenSource;
+ SECURITY_QUALITY_OF_SERVICE LocalSecurityQos;
+ PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
+ PSID_AND_ATTRIBUTES CapturedUser = NULL;
+ PSID_AND_ATTRIBUTES CapturedGroups = NULL;
+ PSID CapturedOwnerSid = NULL;
+ PSID CapturedPrimaryGroupSid = NULL;
+ PACL CapturedDefaultDacl = NULL;
+ ULONG PrivilegesLength, UserLength, GroupsLength;
NTSTATUS Status;
PAGED_CODE();
@@ -2405,64 +2429,197 @@
_SEH2_TRY
{
ProbeForWriteHandle(TokenHandle);
+
+ if (ObjectAttributes != NULL)
+ {
+ ProbeForRead(ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
+ LocalSecurityQos =
*(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
+ }
+
ProbeForRead(AuthenticationId,
sizeof(LUID),
sizeof(ULONG));
+ LocalAuthenticationId = *AuthenticationId;
+
LocalExpirationTime = ProbeForReadLargeInteger(ExpirationTime);
+
ProbeForRead(TokenUser,
sizeof(TOKEN_USER),
sizeof(ULONG));
+
ProbeForRead(TokenGroups,
sizeof(TOKEN_GROUPS),
sizeof(ULONG));
+ GroupCount = TokenGroups->GroupCount;
+
ProbeForRead(TokenPrivileges,
sizeof(TOKEN_PRIVILEGES),
sizeof(ULONG));
- ProbeForRead(TokenOwner,
- sizeof(TOKEN_OWNER),
- sizeof(ULONG));
+ PrivilegeCount = TokenPrivileges->PrivilegeCount;
+
+ if (TokenOwner != NULL)
+ {
+ ProbeForRead(TokenOwner,
+ sizeof(TOKEN_OWNER),
+ sizeof(ULONG));
+ OwnerSid = TokenOwner->Owner;
+ }
+ else
+ {
+ OwnerSid = NULL;
+ }
+
ProbeForRead(TokenPrimaryGroup,
sizeof(TOKEN_PRIMARY_GROUP),
sizeof(ULONG));
- ProbeForRead(TokenDefaultDacl,
- sizeof(TOKEN_DEFAULT_DACL),
- sizeof(ULONG));
+ PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
+
+ if (TokenDefaultDacl != NULL)
+ {
+ ProbeForRead(TokenDefaultDacl,
+ sizeof(TOKEN_DEFAULT_DACL),
+ sizeof(ULONG));
+ DefaultDacl = TokenDefaultDacl->DefaultDacl;
+ }
+ else
+ {
+ DefaultDacl = NULL;
+ }
+
ProbeForRead(TokenSource,
sizeof(TOKEN_SOURCE),
sizeof(ULONG));
- nTokenPrivileges = TokenPrivileges->PrivilegeCount;
+ LocalTokenSource = *TokenSource;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ return _SEH2_GetExceptionCode();
}
_SEH2_END;
}
else
{
- nTokenPrivileges = TokenPrivileges->PrivilegeCount;
+ if (ObjectAttributes != NULL)
+ LocalSecurityQos =
*(SECURITY_QUALITY_OF_SERVICE*)ObjectAttributes->SecurityQualityOfService;
+ LocalAuthenticationId = *AuthenticationId;
LocalExpirationTime = *ExpirationTime;
- }
-
+ GroupCount = TokenGroups->GroupCount;
+ PrivilegeCount = TokenPrivileges->PrivilegeCount;
+ OwnerSid = TokenOwner ? TokenOwner->Owner : NULL;
+ PrimaryGroupSid = TokenPrimaryGroup->PrimaryGroup;
+ DefaultDacl = TokenDefaultDacl ? TokenDefaultDacl->DefaultDacl : NULL;
+ LocalTokenSource = *TokenSource;
+ }
+
+ /* Check token type */
+ if ((TokenType < TokenPrimary) ||
+ (TokenType > TokenImpersonation))
+ {
+ return STATUS_BAD_TOKEN_TYPE;
+ }
+
+ /* Capture the user SID and attributes */
+ Status = SeCaptureSidAndAttributesArray(&TokenUser->User,
+ 1,
+ PreviousMode,
+ NULL,
+ 0,
+ PagedPool,
+ FALSE,
+ &CapturedUser,
+ &UserLength);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* Capture the groups SID and attributes array */
+ Status = SeCaptureSidAndAttributesArray(&TokenGroups->Groups[0],
+ GroupCount,
+ PreviousMode,
+ NULL,
+ 0,
+ PagedPool,
+ FALSE,
+ &CapturedGroups,
+ &GroupsLength);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* Capture privileges */
+ Status = SeCaptureLuidAndAttributesArray(&TokenPrivileges->Privileges[0],
+ PrivilegeCount,
+ PreviousMode,
+ NULL,
+ 0,
+ PagedPool,
+ FALSE,
+ &CapturedPrivileges,
+ &PrivilegesLength);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* Capture the token owner SID */
+ if (TokenOwner != NULL)
+ {
+ Status = SepCaptureSid(OwnerSid,
+ PreviousMode,
+ PagedPool,
+ FALSE,
+ &CapturedOwnerSid);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+ }
+
+ /* Capture the token primary group SID */
+ Status = SepCaptureSid(PrimaryGroupSid,
+ PreviousMode,
+ PagedPool,
+ FALSE,
+ &CapturedPrimaryGroupSid);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ /* Capture DefaultDacl */
+ if (DefaultDacl != NULL)
+ {
+ Status = SepCaptureAcl(DefaultDacl,
+ PreviousMode,
+ NonPagedPool,
+ FALSE,
+ &CapturedDefaultDacl);
+ }
+
+ /* Call the internal function */
Status = SepCreateToken(&hToken,
PreviousMode,
DesiredAccess,
ObjectAttributes,
TokenType,
-
((PSECURITY_QUALITY_OF_SERVICE)(ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel,
- AuthenticationId,
+ LocalSecurityQos.ImpersonationLevel,
+ &LocalAuthenticationId,
&LocalExpirationTime,
- &TokenUser->User,
- TokenGroups->GroupCount,
- TokenGroups->Groups,
+ CapturedUser,
+ GroupCount,
+ CapturedGroups,
0, // FIXME: Should capture
- nTokenPrivileges,
- TokenPrivileges->Privileges,
- TokenOwner->Owner,
- TokenPrimaryGroup->PrimaryGroup,
- TokenDefaultDacl->DefaultDacl,
- TokenSource,
+ PrivilegeCount,
+ CapturedPrivileges,
+ CapturedOwnerSid,
+ CapturedPrimaryGroupSid,
+ CapturedDefaultDacl,
+ &LocalTokenSource,
FALSE);
if (NT_SUCCESS(Status))
{
@@ -2476,6 +2633,16 @@
}
_SEH2_END;
}
+
+Cleanup:
+
+ /* Release what we captured */
+ SeReleaseSidAndAttributesArray(CapturedUser, PreviousMode, FALSE);
+ SeReleaseSidAndAttributesArray(CapturedGroups, PreviousMode, FALSE);
+ SeReleaseLuidAndAttributesArray(CapturedPrivileges, PreviousMode, FALSE);
+ SepReleaseSid(CapturedOwnerSid, PreviousMode, FALSE);
+ SepReleaseSid(CapturedPrimaryGroupSid, PreviousMode, FALSE);
+ SepReleaseAcl(CapturedDefaultDacl, PreviousMode, FALSE);
return Status;
}