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 NtImpersonateAnonymousToken API
5  * COPYRIGHT:       Copyright 2021 George Bișoc <george.bisoc@reactos.org>
6  */
7 
8 #include "precomp.h"
9 #include <winreg.h>
10 
11 #define TOKEN_WITH_EVERYONE_GROUP    1
12 #define TOKEN_WITHOUT_EVERYONE_GROUP 0
13 
14 static
15 HANDLE
16 GetThreadFromCurrentProcess(_In_ DWORD DesiredAccess)
17 {
18     HANDLE Thread;
19 
20     Thread = OpenThread(DesiredAccess, FALSE, GetCurrentThreadId());
21     if (!Thread)
22     {
23         skip("OpenThread() has failed to open the current process' thread (error code: %lu)\n", GetLastError());
24         return NULL;
25     }
26 
27     return Thread;
28 }
29 
30 static
31 VOID
32 ImpersonateTokenWithEveryoneOrWithout(_In_ DWORD Value)
33 {
34     LONG Result;
35     HKEY Key;
36 
37     Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
38                            L"SYSTEM\\CurrentControlSet\\Control\\Lsa",
39                            0,
40                            KEY_SET_VALUE,
41                            &Key);
42     if (Result != ERROR_SUCCESS)
43     {
44         skip("RegOpenKeyExW() has failed to open the key (error code: %li)\n", Result);
45         return;
46     }
47 
48     Result = RegSetValueExW(Key,
49                             L"EveryoneIncludesAnonymous",
50                             0,
51                             REG_DWORD,
52                             (PBYTE)&Value,
53                             sizeof(Value));
54     if (Result != ERROR_SUCCESS)
55     {
56         skip("RegSetValueExW() has failed to set the value (error code: %li)\n", Result);
57         RegCloseKey(Key);
58         return;
59     }
60 
61     RegCloseKey(Key);
62 }
63 
64 START_TEST(NtImpersonateAnonymousToken)
65 {
66     NTSTATUS Status;
67     BOOL Success;
68     HANDLE ThreadHandle;
69 
70     ThreadHandle = GetThreadFromCurrentProcess(THREAD_IMPERSONATE);
71 
72     /* We give an invalid thread handle */
73     Status = NtImpersonateAnonymousToken(NULL);
74     ok_hex(Status, STATUS_INVALID_HANDLE);
75 
76     /* We want to impersonate the token including Everyone Group SID */
77     ImpersonateTokenWithEveryoneOrWithout(TOKEN_WITH_EVERYONE_GROUP);
78 
79     /* Impersonate the anonymous logon token */
80     Status = NtImpersonateAnonymousToken(ThreadHandle);
81     ok_hex(Status, STATUS_SUCCESS);
82 
83     /* Now revert to the previous security properties */
84     Success = RevertToSelf();
85     ok(Success == TRUE, "We should have terminated the impersonation but we couldn't (error code: %lu)\n", GetLastError());
86 
87     /* Return to default setting -- token without Everyone Group SID */
88     ImpersonateTokenWithEveryoneOrWithout(TOKEN_WITHOUT_EVERYONE_GROUP);
89 
90     /* Impersonate the anonymous logon token again */
91     Status = NtImpersonateAnonymousToken(ThreadHandle);
92     ok_hex(Status, STATUS_SUCCESS);
93 
94     /* Now revert to the previous security properties */
95     Success = RevertToSelf();
96     ok(Success == TRUE, "We should have terminated the impersonation but we couldn't (error code: %lu)\n", GetLastError());
97 
98     /*
99      * Invalidate the handle and open a new one. This time
100      * with the wrong access right mask, the function will
101      * outright fail on impersonating the token.
102      */
103     CloseHandle(ThreadHandle);
104     ThreadHandle = GetThreadFromCurrentProcess(SYNCHRONIZE);
105 
106     /* The thread handle has incorrect right access */
107     Status = NtImpersonateAnonymousToken(ThreadHandle);
108     ok_hex(Status, STATUS_ACCESS_DENIED);
109 
110     /* We're done with the tests */
111     CloseHandle(ThreadHandle);
112 }
113