1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite object security test
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 #include "../ntos_se/se.h"
10 
11 #define CheckDirectorySecurityWithOwnerAndGroup(name, Owner, Group, AceCount, ...) CheckDirectorySecurity_(name, Owner, Group, AceCount, __FILE__, __LINE__, ##__VA_ARGS__)
12 #define CheckDirectorySecurity(name, AceCount, ...) CheckDirectorySecurity_(name, SeExports->SeAliasAdminsSid, SeExports->SeLocalSystemSid, AceCount, __FILE__, __LINE__, ##__VA_ARGS__)
13 #define CheckDirectorySecurity_(name, Owner, Group, AceCount, file, line, ...) CheckDirectorySecurity__(name, Owner, Group, AceCount, file ":" KMT_STRINGIZE(line), ##__VA_ARGS__)
14 static
15 VOID
16 CheckDirectorySecurity__(
17     _In_ PCWSTR DirectoryName,
18     _In_ PSID ExpectedOwner,
19     _In_ PSID ExpectedGroup,
20     _In_ ULONG AceCount,
21     _In_ PCSTR FileAndLine,
22     ...)
23 {
24     NTSTATUS Status;
25     UNICODE_STRING DirectoryNameString;
26     OBJECT_ATTRIBUTES ObjectAttributes;
27     HANDLE DirectoryHandle;
28     PSECURITY_DESCRIPTOR SecurityDescriptor;
29     ULONG SecurityDescriptorSize;
30     PSID Owner;
31     PSID Group;
32     PACL Dacl;
33     PACL Sacl;
34     BOOLEAN Present;
35     BOOLEAN Defaulted;
36     va_list Arguments;
37 
38     RtlInitUnicodeString(&DirectoryNameString, DirectoryName);
39     InitializeObjectAttributes(&ObjectAttributes,
40                                &DirectoryNameString,
41                                OBJ_KERNEL_HANDLE,
42                                NULL,
43                                NULL);
44     Status = ZwOpenDirectoryObject(&DirectoryHandle,
45                                    READ_CONTROL | ACCESS_SYSTEM_SECURITY,
46                                    &ObjectAttributes);
47     ok_eq_hex(Status, STATUS_SUCCESS);
48     if (skip(NT_SUCCESS(Status), "No directory (%ls)\n", DirectoryName))
49     {
50         return;
51     }
52 
53     Status = ZwQuerySecurityObject(DirectoryHandle,
54                                    OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
55                                    NULL,
56                                    0,
57                                    &SecurityDescriptorSize);
58     ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
59     if (skip(Status == STATUS_BUFFER_TOO_SMALL, "No security size (%ls)\n", DirectoryName))
60     {
61         ObCloseHandle(DirectoryHandle, KernelMode);
62         return;
63     }
64 
65     SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
66                                                SecurityDescriptorSize,
67                                                'dSmK');
68     ok(SecurityDescriptor != NULL, "Failed to allocate %lu bytes\n", SecurityDescriptorSize);
69     if (skip(SecurityDescriptor != NULL, "No memory for descriptor (%ls)\n", DirectoryName))
70     {
71         ObCloseHandle(DirectoryHandle, KernelMode);
72         return;
73     }
74 
75     Status = ZwQuerySecurityObject(DirectoryHandle,
76                                    OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
77                                    SecurityDescriptor,
78                                    SecurityDescriptorSize,
79                                    &SecurityDescriptorSize);
80     ok_eq_hex(Status, STATUS_SUCCESS);
81     if (NT_SUCCESS(Status))
82     {
83         Owner = NULL;
84         Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
85                                                &Owner,
86                                                &Defaulted);
87         if (ExpectedOwner)
88             CheckSid__(Owner, NO_SIZE, ExpectedOwner, FileAndLine);
89         ok(Defaulted == FALSE, "Owner defaulted for %ls\n", DirectoryName);
90 
91         Group = NULL;
92         Status = RtlGetGroupSecurityDescriptor(SecurityDescriptor,
93                                                &Group,
94                                                &Defaulted);
95         if (ExpectedGroup)
96             CheckSid__(Group, NO_SIZE, ExpectedGroup, FileAndLine);
97         ok(Defaulted == FALSE, "Group defaulted for %ls\n", DirectoryName);
98 
99         Dacl = NULL;
100         Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
101                                               &Present,
102                                               &Dacl,
103                                               &Defaulted);
104         ok_eq_hex(Status, STATUS_SUCCESS);
105         ok(Present == TRUE, "DACL not present for %ls\n", DirectoryName);
106         ok(Defaulted == FALSE, "DACL defaulted for %ls\n", DirectoryName);
107         va_start(Arguments, FileAndLine);
108         VCheckAcl__(Dacl, AceCount, FileAndLine, Arguments);
109         va_end(Arguments);
110 
111         Sacl = NULL;
112         Status = RtlGetSaclSecurityDescriptor(SecurityDescriptor,
113                                               &Present,
114                                               &Sacl,
115                                               &Defaulted);
116         ok_eq_hex(Status, STATUS_SUCCESS);
117         ok(Present == FALSE, "SACL present for %ls\n", DirectoryName);
118         ok(Defaulted == FALSE, "SACL defaulted for %ls\n", DirectoryName);
119         ok(Sacl == NULL, "Sacl is %p for %ls\n", Sacl, DirectoryName);
120     }
121     ExFreePoolWithTag(SecurityDescriptor, 'dSmK');
122     ObCloseHandle(DirectoryHandle, KernelMode);
123 }
124 
125 START_TEST(ObSecurity)
126 {
127     NTSTATUS Status;
128     /* Assume yes, that's the default on W2K3 */
129     ULONG LUIDMappingsEnabled = 1, ReturnLength;
130 
131 #define DIRECTORY_GENERIC_READ      STANDARD_RIGHTS_READ | DIRECTORY_TRAVERSE | DIRECTORY_QUERY
132 #define DIRECTORY_GENERIC_WRITE     STANDARD_RIGHTS_WRITE | DIRECTORY_CREATE_SUBDIRECTORY | DIRECTORY_CREATE_OBJECT
133 
134     /* Check if LUID device maps are enabled */
135     Status = ZwQueryInformationProcess(NtCurrentProcess(),
136                                        ProcessLUIDDeviceMapsEnabled,
137                                        &LUIDMappingsEnabled,
138                                        sizeof(LUIDMappingsEnabled),
139                                        &ReturnLength);
140     ok(NT_SUCCESS(Status), "NtQueryInformationProcess failed: 0x%x\n", Status);
141 
142     trace("LUID mappings are enabled: %d\n", LUIDMappingsEnabled);
143     if (LUIDMappingsEnabled != 0)
144     {
145         CheckDirectorySecurityWithOwnerAndGroup(L"\\??", SeExports->SeAliasAdminsSid, NULL, // Group is "Domain Users"
146                                4, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE |
147                                                            OBJECT_INHERIT_ACE,      SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
148                                   ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE |
149                                                            OBJECT_INHERIT_ACE,      SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS,
150                                   ACCESS_ALLOWED_ACE_TYPE, 0,                       SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS,
151                                   ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
152                                                            CONTAINER_INHERIT_ACE |
153                                                            OBJECT_INHERIT_ACE,      SeExports->SeCreatorOwnerSid,GENERIC_ALL);
154     }
155     else
156     {
157         CheckDirectorySecurityWithOwnerAndGroup(L"\\??", SeExports->SeAliasAdminsSid, NULL, // Group is "Domain Users"
158                                6, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid, READ_CONTROL | DIRECTORY_TRAVERSE | DIRECTORY_QUERY,
159                                   ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
160                                   ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
161                                                            CONTAINER_INHERIT_ACE |
162                                                            OBJECT_INHERIT_ACE,      SeExports->SeWorldSid, GENERIC_EXECUTE,
163                                   ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
164                                                            CONTAINER_INHERIT_ACE |
165                                                            OBJECT_INHERIT_ACE,      SeExports->SeAliasAdminsSid,GENERIC_ALL,
166                                   ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
167                                                            CONTAINER_INHERIT_ACE |
168                                                            OBJECT_INHERIT_ACE,      SeExports->SeLocalSystemSid,GENERIC_ALL,
169                                   ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
170                                                            CONTAINER_INHERIT_ACE |
171                                                            OBJECT_INHERIT_ACE,      SeExports->SeCreatorOwnerSid,GENERIC_ALL);
172     }
173 
174     CheckDirectorySecurity(L"\\",
175                            4, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid,       DIRECTORY_GENERIC_READ,
176                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
177                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS,
178                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeRestrictedSid,  DIRECTORY_GENERIC_READ);
179 
180     CheckDirectorySecurity(L"\\ArcName",
181                            4, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid,       DIRECTORY_GENERIC_READ,
182                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
183                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS,
184                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeRestrictedSid,  DIRECTORY_GENERIC_READ);
185 
186     CheckDirectorySecurity(L"\\BaseNamedObjects",
187                            3, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid,       DIRECTORY_GENERIC_WRITE | DIRECTORY_GENERIC_READ,
188                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
189                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeRestrictedSid,  DIRECTORY_TRAVERSE);
190 
191     CheckDirectorySecurity(L"\\Callback",
192                            3, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid,       DIRECTORY_GENERIC_READ,
193                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
194                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS);
195 
196     CheckDirectorySecurity(L"\\Device",
197                            4, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid,       DIRECTORY_GENERIC_READ,
198                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
199                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS,
200                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeRestrictedSid,  DIRECTORY_GENERIC_READ);
201 
202     CheckDirectorySecurity(L"\\Driver",
203                            2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
204                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_GENERIC_READ);
205 
206     CheckDirectorySecurity(L"\\GLOBAL??",
207                            6, ACCESS_ALLOWED_ACE_TYPE, 0,                       SeExports->SeWorldSid,       DIRECTORY_GENERIC_READ,
208                               ACCESS_ALLOWED_ACE_TYPE, 0,                       SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
209                               ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
210                                                        CONTAINER_INHERIT_ACE |
211                                                        OBJECT_INHERIT_ACE,      SeExports->SeWorldSid,       GENERIC_EXECUTE,
212                               ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
213                                                        CONTAINER_INHERIT_ACE |
214                                                        OBJECT_INHERIT_ACE,      SeExports->SeAliasAdminsSid, GENERIC_ALL,
215                               ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
216                                                        CONTAINER_INHERIT_ACE |
217                                                        OBJECT_INHERIT_ACE,      SeExports->SeLocalSystemSid, GENERIC_ALL,
218                               ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE |
219                                                        CONTAINER_INHERIT_ACE |
220                                                        OBJECT_INHERIT_ACE,      SeExports->SeCreatorOwnerSid,GENERIC_ALL);
221 
222     CheckDirectorySecurity(L"\\KernelObjects",
223                            3, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid,       DIRECTORY_GENERIC_READ,
224                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS,
225                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS);
226 
227     CheckDirectorySecurity(L"\\ObjectTypes",
228                            2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS,
229                               ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_GENERIC_READ);
230 }
231