1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         See COPYING in the top level directory
4  * PURPOSE:         Test for RtlRemovePrivileges
5  * PROGRAMMER:      Ratin Gao <ratin@knsoft.org>
6  */
7 
8 #include "precomp.h"
9 
10 START_TEST(RtlRemovePrivileges)
11 {
12 #if (NTDDI_VERSION >= NTDDI_VISTA)
13     NTSTATUS Status;
14     HANDLE TokenHandle, TestTokenHandle;
15     ULONG ReturnLength;
16     UCHAR Buffer
17         [sizeof(TOKEN_PRIVILEGES) +
18          sizeof(LUID_AND_ATTRIBUTES) * (SE_MAX_WELL_KNOWN_PRIVILEGE - SE_MIN_WELL_KNOWN_PRIVILEGE)];
19     PTOKEN_PRIVILEGES Privileges;
20     ULONG PrivilegesToKeep[2];
21 
22     /* Duplicate current process token to run this test */
23     Status = NtOpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &TokenHandle);
24     if (!NT_SUCCESS(Status))
25     {
26         ok(0, "Failed to open current process token with TOKEN_DUPLICATE access (Status code %lx)!\n", Status);
27         return;
28     }
29 
30     Status = NtDuplicateToken(TokenHandle, TOKEN_ALL_ACCESS, NULL, FALSE, TokenPrimary, &TestTokenHandle);
31     NtClose(TokenHandle);
32     if (!NT_SUCCESS(Status))
33     {
34         ok(0, "Failed to duplicate current process token (Status code %lx)!\n", Status);
35         return;
36     }
37 
38     /* Retrieve token privileges, we need at least 3 privileges to run following tests */
39     Status = NtQueryInformationToken(TestTokenHandle, TokenPrivileges, Buffer, sizeof(Buffer), &ReturnLength);
40     if (!NT_SUCCESS(Status))
41     {
42         NtClose(TestTokenHandle);
43         ok(0, "Failed to retrieve token privileges (Status code %lx)!\n", Status);
44         return;
45     }
46     Privileges = (PTOKEN_PRIVILEGES)Buffer;
47     if (Privileges->PrivilegeCount < 3)
48     {
49         NtClose(TestTokenHandle);
50         ok(0, "No enough privileges to run the test (Number of privilege: %lu)!\n", Privileges->PrivilegeCount);
51         return;
52     }
53 
54     /* Remove all privileges except 2nd and 3rd privileges, this should succeed */
55     PrivilegesToKeep[0] = Privileges->Privileges[1].Luid.LowPart;
56     PrivilegesToKeep[1] = Privileges->Privileges[2].Luid.LowPart;
57     Status = RtlRemovePrivileges(TestTokenHandle, PrivilegesToKeep, ARRAYSIZE(PrivilegesToKeep));
58 
59     /* Do not use NT_SUCCESS, RtlRemovePrivileges may returns STATUS_NOT_ALL_ASSIGNED */
60     if (Status != STATUS_SUCCESS)
61     {
62         NtClose(TestTokenHandle);
63         ok_ntstatus(Status, STATUS_SUCCESS);
64         return;
65     }
66 
67     /* Now, only two privileges we kept should be present */
68     Status = NtQueryInformationToken(TestTokenHandle, TokenPrivileges, Buffer, sizeof(Buffer), &ReturnLength);
69     if (!NT_SUCCESS(Status))
70     {
71         NtClose(TestTokenHandle);
72         ok(0, "Failed to retrieve token privileges (Status code %lx)!\n", Status);
73         return;
74     }
75     ok(Privileges->PrivilegeCount == ARRAYSIZE(PrivilegesToKeep),
76        "Number of privileges after RtlRemovePrivileges is %lu, expected %u\n", Privileges->PrivilegeCount,
77        ARRAYSIZE(PrivilegesToKeep));
78     ok(PrivilegesToKeep[0] + PrivilegesToKeep[1] ==
79            Privileges->Privileges[0].Luid.LowPart + Privileges->Privileges[1].Luid.LowPart,
80        "Incorrect privileges kept by RtlRemovePrivileges: %lu and %lu, expected %lu and %lu",
81        Privileges->Privileges[0].Luid.LowPart, Privileges->Privileges[1].Luid.LowPart, PrivilegesToKeep[0],
82        PrivilegesToKeep[1]);
83 
84     /* Remove all privileges, this should succeed */
85     Status = RtlRemovePrivileges(TestTokenHandle, NULL, 0);
86 
87     /* Do not use NT_SUCCESS, RtlRemovePrivileges may returns STATUS_NOT_ALL_ASSIGNED */
88     if (Status != STATUS_SUCCESS)
89     {
90         NtClose(TestTokenHandle);
91         ok_ntstatus(Status, STATUS_SUCCESS);
92         return;
93     }
94 
95     /* Now, no privilege should be present */
96     Status = NtQueryInformationToken(TestTokenHandle, TokenPrivileges, Buffer, sizeof(Buffer), &ReturnLength);
97     if (!NT_SUCCESS(Status))
98     {
99         NtClose(TestTokenHandle);
100         ok(0, "Failed to retrieve token privileges (Status code %lx)!\n", Status);
101         return;
102     }
103     ok(Privileges->PrivilegeCount == 0, "There are %lu privileges still exist after RtlRemovePrivileges\n",
104        Privileges->PrivilegeCount);
105 
106     NtClose(TestTokenHandle);
107     return;
108 #else
109     skip("RtlRemovePrivileges available on NT6.0+ (NTDDI_VERSION >= NTDDI_VISTA)");
110 #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
111 }
112