mirror of
https://github.com/reactos/reactos.git
synced 2024-09-12 05:43:24 +00:00
248 lines
7 KiB
C
248 lines
7 KiB
C
![]() |
/*
|
||
|
* PROJECT: ReactOS API tests
|
||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||
|
* PURPOSE: Tests for the NtSetInformationToken API
|
||
|
* COPYRIGHT: Copyright 2022 George Bișoc <george.bisoc@reactos.org>
|
||
|
*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
static
|
||
|
HANDLE
|
||
|
OpenCurrentToken(VOID)
|
||
|
{
|
||
|
BOOL Success;
|
||
|
HANDLE Token;
|
||
|
|
||
|
Success = OpenProcessToken(GetCurrentProcess(),
|
||
|
TOKEN_READ | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID,
|
||
|
&Token);
|
||
|
if (!Success)
|
||
|
{
|
||
|
ok(0, "OpenProcessToken() has failed to get the process' token (error code: %lu)!\n", GetLastError());
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return Token;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
PTOKEN_DEFAULT_DACL
|
||
|
QueryOriginalDefaultDacl(
|
||
|
_In_ HANDLE Token,
|
||
|
_Out_ PULONG DaclLength)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
PTOKEN_DEFAULT_DACL Dacl;
|
||
|
ULONG BufferLength;
|
||
|
|
||
|
*DaclLength = 0;
|
||
|
|
||
|
Status = NtQueryInformationToken(Token,
|
||
|
TokenDefaultDacl,
|
||
|
NULL,
|
||
|
0,
|
||
|
&BufferLength);
|
||
|
if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
|
||
|
{
|
||
|
ok(0, "Failed to query buffer length, STATUS_BUFFER_TOO_SMALL has to be expected (Status code %lx)!\n", Status);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Dacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||
|
if (!Dacl)
|
||
|
{
|
||
|
ok(0, "Failed to allocate from heap for token default DACL (required buffer length %lu)!\n", BufferLength);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Status = NtQueryInformationToken(Token,
|
||
|
TokenDefaultDacl,
|
||
|
Dacl,
|
||
|
BufferLength,
|
||
|
&BufferLength);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
ok(0, "Failed to query default DACL (Status code %lx)!\n", Status);
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
*DaclLength = BufferLength;
|
||
|
return Dacl;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
PACL
|
||
|
CreateNewDefaultDacl(
|
||
|
_Out_ PULONG DaclLength)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
PACL Dacl;
|
||
|
ULONG Length;
|
||
|
PSID LocalSystemSid;
|
||
|
static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
||
|
|
||
|
*DaclLength = 0;
|
||
|
|
||
|
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
||
|
1,
|
||
|
SECURITY_LOCAL_SYSTEM_RID,
|
||
|
0, 0, 0, 0, 0, 0, 0,
|
||
|
&LocalSystemSid);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
ok(0, "Failed to allocate Local System SID (Status code %lx)!\n", Status);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Length = sizeof(ACL) +
|
||
|
sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(LocalSystemSid);
|
||
|
|
||
|
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
|
||
|
HEAP_ZERO_MEMORY,
|
||
|
Length);
|
||
|
if (!Dacl)
|
||
|
{
|
||
|
ok(0, "Failed to allocate from heap for DACL!\n");
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Status = RtlCreateAcl(Dacl,
|
||
|
Length,
|
||
|
ACL_REVISION);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
ok(0, "Failed to create ACL (Status code %lx)!\n", Status);
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Status = RtlAddAccessAllowedAce(Dacl,
|
||
|
ACL_REVISION,
|
||
|
GENERIC_ALL,
|
||
|
LocalSystemSid);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
ok(0, "Failed to add access allowed ACE (Status code %lx)!\n", Status);
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
*DaclLength = Length;
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||
|
return Dacl;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
VOID
|
||
|
SetTokenDefaultDaclTests(
|
||
|
_In_ HANDLE Token)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
PACL NewDacl;
|
||
|
TOKEN_DEFAULT_DACL NewDefaultDacl;
|
||
|
PTOKEN_DEFAULT_DACL DefaultDacl;
|
||
|
ULONG OriginalDaclLength, NewDaclLength;
|
||
|
|
||
|
/*
|
||
|
* Query the original DACL of the token first,
|
||
|
* we don't want to leave the token tampered
|
||
|
* later on.
|
||
|
*/
|
||
|
DefaultDacl = QueryOriginalDefaultDacl(Token, &OriginalDaclLength);
|
||
|
if (!DefaultDacl)
|
||
|
{
|
||
|
ok(0, "Failed to query token's default DACL!\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Allocate new DACL */
|
||
|
NewDacl = CreateNewDefaultDacl(&NewDaclLength);
|
||
|
if (!DefaultDacl)
|
||
|
{
|
||
|
ok(0, "Failed to allocate buffer for new DACL!\n");
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DefaultDacl);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
NewDefaultDacl.DefaultDacl = NewDacl;
|
||
|
|
||
|
/*
|
||
|
* Set a new DACL for the token.
|
||
|
*/
|
||
|
Status = NtSetInformationToken(Token,
|
||
|
TokenDefaultDacl,
|
||
|
&NewDefaultDacl,
|
||
|
NewDaclLength);
|
||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||
|
|
||
|
/* Now set the original DACL */
|
||
|
Status = NtSetInformationToken(Token,
|
||
|
TokenDefaultDacl,
|
||
|
DefaultDacl,
|
||
|
OriginalDaclLength);
|
||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||
|
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DefaultDacl);
|
||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NewDacl);
|
||
|
}
|
||
|
|
||
|
static
|
||
|
VOID
|
||
|
SetTokenSessionIdTests(
|
||
|
_In_ HANDLE Token)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
ULONG SessionId = 1;
|
||
|
|
||
|
/*
|
||
|
* We're not allowed to set a session ID
|
||
|
* because we don't have the TCB privilege.
|
||
|
*/
|
||
|
Status = NtSetInformationToken(Token,
|
||
|
TokenSessionId,
|
||
|
&SessionId,
|
||
|
sizeof(ULONG));
|
||
|
ok_ntstatus(Status, STATUS_PRIVILEGE_NOT_HELD);
|
||
|
}
|
||
|
|
||
|
START_TEST(NtSetInformationToken)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
ULONG DummyReturnLength = 0;
|
||
|
HANDLE Token;
|
||
|
|
||
|
/* Everything else is NULL */
|
||
|
Status = NtSetInformationToken(NULL,
|
||
|
TokenOwner,
|
||
|
NULL,
|
||
|
0);
|
||
|
ok_ntstatus(Status, STATUS_INVALID_HANDLE);
|
||
|
|
||
|
/* We don't give a token */
|
||
|
Status = NtSetInformationToken(NULL,
|
||
|
TokenOwner,
|
||
|
NULL,
|
||
|
DummyReturnLength);
|
||
|
ok_ntstatus(Status, STATUS_INVALID_HANDLE);
|
||
|
|
||
|
Token = OpenCurrentToken();
|
||
|
|
||
|
/* We give a bogus token class */
|
||
|
Status = NtSetInformationToken(Token,
|
||
|
0xa0a,
|
||
|
NULL,
|
||
|
DummyReturnLength);
|
||
|
ok_ntstatus(Status, STATUS_INVALID_INFO_CLASS);
|
||
|
|
||
|
/* Now perform tests for each class */
|
||
|
SetTokenDefaultDaclTests(Token);
|
||
|
SetTokenSessionIdTests(Token);
|
||
|
|
||
|
CloseHandle(Token);
|
||
|
}
|