[VCDROM] Implement the virtual CD-ROM class driver.
[reactos.git] / ntoskrnl / config / cmse.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmse.c
5 * PURPOSE: Configuration Manager - Security Subsystem Interface
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14
15 /* GLOBALS *******************************************************************/
16
17 /* FUNCTIONS *****************************************************************/
18
19 //INIT_FUNCTION
20 PSECURITY_DESCRIPTOR
21 NTAPI
22 CmpHiveRootSecurityDescriptor(VOID)
23 {
24 NTSTATUS Status;
25 PSECURITY_DESCRIPTOR SecurityDescriptor;
26 PACL Acl, AclCopy;
27 PSID Sid[4];
28 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
29 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
30 ULONG AceLength, AclLength, SidLength;
31 PACE_HEADER AceHeader;
32 ULONG i;
33 PAGED_CODE();
34
35 /* Phase 1: Allocate SIDs */
36 SidLength = RtlLengthRequiredSid(1);
37 Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CMSD);
38 Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CMSD);
39 Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CMSD);
40 SidLength = RtlLengthRequiredSid(2);
41 Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CMSD);
42
43 /* Make sure all SIDs were allocated */
44 if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3]))
45 {
46 /* Bugcheck */
47 KeBugCheckEx(REGISTRY_ERROR, 11, 1, 0, 0);
48 }
49
50 /* Phase 2: Initialize all SIDs */
51 Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1);
52 Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1);
53 Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1);
54 Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2);
55 if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 2, 0, 0);
56
57 /* Phase 2: Setup SID Sub Authorities */
58 *RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID;
59 *RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID;
60 *RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID;
61 *RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID;
62 *RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS;
63
64 /* Make sure all SIDs are valid */
65 ASSERT(RtlValidSid(Sid[0]));
66 ASSERT(RtlValidSid(Sid[1]));
67 ASSERT(RtlValidSid(Sid[2]));
68 ASSERT(RtlValidSid(Sid[3]));
69
70 /* Phase 3: Calculate ACL Length */
71 AclLength = sizeof(ACL);
72 for (i = 0; i < 4; i++)
73 {
74 /* This is what MSDN says to do */
75 AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
76 AceLength += SeLengthSid(Sid[i]);
77 AclLength += AceLength;
78 }
79
80 /* Phase 3: Allocate the ACL */
81 Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CMSD);
82 if (!Acl) KeBugCheckEx(REGISTRY_ERROR, 11, 3, 0, 0);
83
84 /* Phase 4: Create the ACL */
85 Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
86 if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 4, Status, 0);
87
88 /* Phase 5: Build the ACL */
89 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[2]);
90 Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[3]);
91 Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[0]);
92 Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[1]);
93 if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 5, Status, 0);
94
95 /* Phase 5: Make the ACEs inheritable */
96 Status = RtlGetAce(Acl, 0, (PVOID*)&AceHeader);
97 ASSERT(NT_SUCCESS(Status));
98 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
99 Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader);
100 ASSERT(NT_SUCCESS(Status));
101 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
102 Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader);
103 ASSERT(NT_SUCCESS(Status));
104 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
105 Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader);
106 ASSERT(NT_SUCCESS(Status));
107 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
108
109 /* Phase 6: Allocate the security descriptor and make space for the ACL */
110 SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
111 sizeof(SECURITY_DESCRIPTOR) +
112 AclLength,
113 TAG_CMSD);
114 if (!SecurityDescriptor) KeBugCheckEx(REGISTRY_ERROR, 11, 6, 0, 0);
115
116 /* Phase 6: Make a copy of the ACL */
117 AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1);
118 RtlCopyMemory(AclCopy, Acl, AclLength);
119
120 /* Phase 7: Create the security descriptor */
121 Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
122 SECURITY_DESCRIPTOR_REVISION);
123 if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 7, Status, 0);
124
125 /* Phase 8: Set the ACL as a DACL */
126 Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
127 TRUE,
128 AclCopy,
129 FALSE);
130 if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 8, Status, 0);
131
132 /* Free the SIDs and original ACL */
133 for (i = 0; i < 4; i++) ExFreePoolWithTag(Sid[i], TAG_CMSD);
134 ExFreePoolWithTag(Acl, TAG_CMSD);
135
136 /* Return the security descriptor */
137 return SecurityDescriptor;
138 }
139
140 NTSTATUS
141 CmpQuerySecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb,
142 IN SECURITY_INFORMATION SecurityInformation,
143 OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
144 IN OUT PULONG BufferLength)
145 {
146 PISECURITY_DESCRIPTOR_RELATIVE RelSd;
147 ULONG SidSize;
148 ULONG AclSize;
149 ULONG SdSize;
150 NTSTATUS Status;
151 SECURITY_DESCRIPTOR_CONTROL Control = 0;
152 ULONG Owner = 0;
153 ULONG Group = 0;
154 ULONG Dacl = 0;
155
156 DBG_UNREFERENCED_PARAMETER(Kcb);
157
158 DPRINT("CmpQuerySecurityDescriptor()\n");
159
160 if (SecurityInformation == 0)
161 {
162 return STATUS_ACCESS_DENIED;
163 }
164
165 SidSize = RtlLengthSid(SeWorldSid);
166 RelSd = SecurityDescriptor;
167 SdSize = sizeof(*RelSd);
168
169 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
170 {
171 Owner = SdSize;
172 SdSize += SidSize;
173 }
174
175 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
176 {
177 Group = SdSize;
178 SdSize += SidSize;
179 }
180
181 if (SecurityInformation & DACL_SECURITY_INFORMATION)
182 {
183 Control |= SE_DACL_PRESENT;
184 Dacl = SdSize;
185 AclSize = sizeof(ACL) + sizeof(ACE) + SidSize;
186 SdSize += AclSize;
187 }
188
189 if (SecurityInformation & SACL_SECURITY_INFORMATION)
190 {
191 Control |= SE_SACL_PRESENT;
192 }
193
194 if (*BufferLength < SdSize)
195 {
196 *BufferLength = SdSize;
197 return STATUS_BUFFER_TOO_SMALL;
198 }
199
200 *BufferLength = SdSize;
201
202 Status = RtlCreateSecurityDescriptorRelative(RelSd,
203 SECURITY_DESCRIPTOR_REVISION);
204 if (!NT_SUCCESS(Status))
205 return Status;
206
207 RelSd->Control |= Control;
208 RelSd->Owner = Owner;
209 RelSd->Group = Group;
210 RelSd->Dacl = Dacl;
211
212 if (Owner)
213 RtlCopyMemory((PUCHAR)RelSd + Owner,
214 SeWorldSid,
215 SidSize);
216
217 if (Group)
218 RtlCopyMemory((PUCHAR)RelSd + Group,
219 SeWorldSid,
220 SidSize);
221
222 if (Dacl)
223 {
224 Status = RtlCreateAcl((PACL)((PUCHAR)RelSd + Dacl),
225 AclSize,
226 ACL_REVISION);
227 if (NT_SUCCESS(Status))
228 {
229 Status = RtlAddAccessAllowedAce((PACL)((PUCHAR)RelSd + Dacl),
230 ACL_REVISION,
231 GENERIC_ALL,
232 SeWorldSid);
233 }
234 }
235
236 ASSERT(Status == STATUS_SUCCESS);
237 return Status;
238 }
239
240 NTSTATUS
241 CmpSetSecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb,
242 IN PSECURITY_INFORMATION SecurityInformation,
243 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
244 IN POOL_TYPE PoolType,
245 IN PGENERIC_MAPPING GenericMapping)
246 {
247 DPRINT("CmpSetSecurityDescriptor()\n");
248 return STATUS_SUCCESS;
249 }
250
251 NTSTATUS
252 CmpAssignSecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb,
253 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
254 {
255 DPRINT("CmpAssignSecurityDescriptor(%p %p)\n",
256 Kcb, SecurityDescriptor);
257 return STATUS_SUCCESS;
258 }
259
260 NTSTATUS
261 NTAPI
262 CmpSecurityMethod(IN PVOID ObjectBody,
263 IN SECURITY_OPERATION_CODE OperationCode,
264 IN PSECURITY_INFORMATION SecurityInformation,
265 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
266 IN OUT PULONG BufferLength,
267 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
268 IN POOL_TYPE PoolType,
269 IN PGENERIC_MAPPING GenericMapping)
270 {
271 PCM_KEY_CONTROL_BLOCK Kcb;
272 NTSTATUS Status = STATUS_SUCCESS;
273
274 DBG_UNREFERENCED_PARAMETER(OldSecurityDescriptor);
275 DBG_UNREFERENCED_PARAMETER(GenericMapping);
276
277 Kcb = ((PCM_KEY_BODY)ObjectBody)->KeyControlBlock;
278
279 /* Acquire the hive lock */
280 CmpLockRegistry();
281
282 /* Acquire the KCB lock */
283 if (OperationCode == QuerySecurityDescriptor)
284 {
285 CmpAcquireKcbLockShared(Kcb);
286 }
287 else
288 {
289 CmpAcquireKcbLockExclusive(Kcb);
290 }
291
292 /* Don't touch deleted keys */
293 if (Kcb->Delete)
294 {
295 /* Release the KCB lock */
296 CmpReleaseKcbLock(Kcb);
297
298 /* Release the hive lock */
299 CmpUnlockRegistry();
300 return STATUS_KEY_DELETED;
301 }
302
303 switch (OperationCode)
304 {
305 case SetSecurityDescriptor:
306 DPRINT("Set security descriptor\n");
307 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
308 Status = CmpSetSecurityDescriptor(Kcb,
309 SecurityInformation,
310 SecurityDescriptor,
311 PoolType,
312 GenericMapping);
313 break;
314
315 case QuerySecurityDescriptor:
316 DPRINT("Query security descriptor\n");
317 Status = CmpQuerySecurityDescriptor(Kcb,
318 *SecurityInformation,
319 SecurityDescriptor,
320 BufferLength);
321 break;
322
323 case DeleteSecurityDescriptor:
324 DPRINT("Delete security descriptor\n");
325 /* HACK */
326 break;
327
328 case AssignSecurityDescriptor:
329 DPRINT("Assign security descriptor\n");
330 Status = CmpAssignSecurityDescriptor(Kcb,
331 SecurityDescriptor);
332 break;
333
334 default:
335 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
336 }
337
338 /* Release the KCB lock */
339 CmpReleaseKcbLock(Kcb);
340
341 /* Release the hive lock */
342 CmpUnlockRegistry();
343
344 return Status;
345 }