ReactOS  0.4.15-dev-3453-gff89651
NtDuplicateToken.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS API tests
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Tests for the NtDuplicateToken API
5  * COPYRIGHT: Copyright 2021 George BiČ™oc <george.bisoc@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 static
11 HANDLE
13 {
14  BOOL Success;
15  HANDLE Token;
16 
19  &Token);
20  if (!Success)
21  {
22  skip("OpenProcessToken() has failed to get the process' token (error code: %lu)!\n", GetLastError());
23  return NULL;
24  }
25 
26  return Token;
27 }
28 
29 static
30 VOID
33  _In_ LPCWSTR PrivilegeName)
34 {
35  TOKEN_PRIVILEGES TokenPriv;
36  LUID PrivLuid;
37  BOOL Success;
38 
39  Success = LookupPrivilegeValueW(NULL, PrivilegeName, &PrivLuid);
40  if (!Success)
41  {
42  skip("LookupPrivilegeValueW() has failed to locate the privilege value (error code: %lu)!\n", GetLastError());
43  return;
44  }
45 
46  TokenPriv.PrivilegeCount = 1;
47  TokenPriv.Privileges[0].Luid = PrivLuid;
48  TokenPriv.Privileges[0].Attributes = 0;
49 
51  FALSE,
52  &TokenPriv,
53  0,
54  NULL,
55  NULL);
56  if (!Success)
57  {
58  skip("AdjustTokenPrivileges() has failed to adjust privileges of token (error code: %lu)!\n", GetLastError());
59  return;
60  }
61 }
62 
63 static
64 VOID
66 {
68  ULONG Size;
70  HANDLE DuplicatedTokenHandle;
72  PTOKEN_STATISTICS TokenStats;
73 
74  /* Initialize the object attributes for token duplication */
76  NULL,
77  0,
78  NULL,
79  NULL);
80 
81  /* Get the token from process and begin the tests */
83 
84  /* We give a bogus invalid handle */
86  0,
87  NULL,
88  TRUE,
90  NULL);
92 
93  /*
94  * Disable a privilege, the impersonation privilege for example.
95  * Why we're doing this is because such privilege is enabled
96  * by default and we'd want to know what the kernel does
97  * at the moment of removing disabled privileges during making
98  * the token effective, with this potential privilege being
99  * disabled by ourselves.
100  */
101  DisablePrivilege(TokenHandle, L"SeImpersonatePrivilege");
102 
103  /* Query the total size of the token statistics structure */
106  {
107  skip("Failed to query the total size for token statistics structure! (Status -> 0x%lx)\n", Status);
108  return;
109  }
110 
111  /* Total size queried, time to allocate our buffer based on that size */
112  TokenStats = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
113  if (TokenStats == NULL)
114  {
115  skip("Failed to allocate our token statistics buffer!\n");
116  return;
117  }
118 
119  /* Time to query our token statistics, prior duplicating the token as effective */
121  if (!NT_SUCCESS(Status))
122  {
123  skip("Failed to query the token statistics! (Status -> 0x%lx)\n", Status);
124  return;
125  }
126 
127  trace("Number of privileges of regular token -- %lu\n", TokenStats->PrivilegeCount);
128  trace("Number of groups of regular token -- %lu\n", TokenStats->GroupCount);
129 
130  /* Duplicate the token as effective only */
132  0,
134  TRUE,
135  TokenPrimary,
136  &DuplicatedTokenHandle);
138 
139  /*
140  * Query the token statistics again, but now this time of
141  * the duplicated effective token. On this moment this token
142  * should have the disabled privileges (including the one we
143  * disabled ourselves) removed as well as the disabled groups
144  * that the duplicated token includes, whatever that is.
145  */
146  Status = NtQueryInformationToken(DuplicatedTokenHandle, TokenStatistics, TokenStats, Size, &Size);
147  if (!NT_SUCCESS(Status))
148  {
149  skip("Failed to query the token statistics! (Status -> 0x%lx)\n", Status);
150  return;
151  }
152 
153  trace("Number of privileges of effective only token -- %lu\n", TokenStats->PrivilegeCount);
154  trace("Number of groups of effective only token -- %lu\n", TokenStats->GroupCount);
155 
156  /*
157  * We finished our tests, free the memory
158  * block and close the handles now.
159  */
160  RtlFreeHeap(RtlGetProcessHeap(), 0, TokenStats);
162  CloseHandle(DuplicatedTokenHandle);
163 }
164 
166 {
168 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define CloseHandle
Definition: compat.h:598
BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpPrivilegeName, PLUID lpLuid)
Definition: misc.c:782
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define TRUE
Definition: types.h:120
$ULONG GroupCount
Definition: setypes.h:1071
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE Token
$ULONG PrivilegeCount
Definition: setypes.h:1001
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define ok_hex(expression, result)
Definition: atltest.h:94
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
START_TEST(NtDuplicateToken)
static VOID DisablePrivilege(_In_ HANDLE Token, _In_ LPCWSTR PrivilegeName)
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
Queries a specific type of information in regard of an access token based upon the information class....
Definition: token.c:3692
#define _In_
Definition: ms_sal.h:308
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
static HANDLE OpenTokenFromProcess(VOID)
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
Status
Definition: gdiplustypes.h:24
#define TOKEN_ADJUST_GROUPS
Definition: setypes.h:909
#define trace
Definition: atltest.h:70
#define TOKEN_QUERY
Definition: setypes.h:906
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TOKEN_DUPLICATE
Definition: setypes.h:904
#define TOKEN_READ
Definition: setypes.h:929
#define GetCurrentProcess()
Definition: compat.h:618
BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
Definition: security.c:376
static VOID DuplicateTokenAsEffective(VOID)
$ULONG PrivilegeCount
Definition: setypes.h:1072
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define NULL
Definition: types.h:112
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:296
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]
Definition: setypes.h:1002
#define skip(...)
Definition: atltest.h:64
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken(_In_ HANDLE ExistingTokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE NewTokenHandle)
Duplicates a token.
Definition: token.c:4853
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:908