Sync with trunk r64222.
[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 PSECURITY_DESCRIPTOR
20 NTAPI
21 INIT_FUNCTION
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_CM);
38 Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
39 Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
40 SidLength = RtlLengthRequiredSid(2);
41 Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
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_CM);
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[0]);
90 Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[1]);
91 Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]);
92 Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]);
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_CM);
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_CM);
134 ExFreePoolWithTag(Acl, TAG_CM);
135
136 /* Return the security descriptor */
137 return SecurityDescriptor;
138 }
139
140 NTSTATUS
141 CmpQuerySecurityDescriptor(IN PCM_KEY_BODY KeyBody,
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(KeyBody);
157
158 if (SecurityInformation == 0)
159 {
160 return STATUS_ACCESS_DENIED;
161 }
162
163 SidSize = RtlLengthSid(SeWorldSid);
164 RelSd = SecurityDescriptor;
165 SdSize = sizeof(*RelSd);
166
167 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
168 {
169 Owner = SdSize;
170 SdSize += SidSize;
171 }
172
173 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
174 {
175 Group = SdSize;
176 SdSize += SidSize;
177 }
178
179 if (SecurityInformation & DACL_SECURITY_INFORMATION)
180 {
181 Control |= SE_DACL_PRESENT;
182 Dacl = SdSize;
183 AclSize = sizeof(ACL) + sizeof(ACE) + SidSize;
184 SdSize += AclSize;
185 }
186
187 if (SecurityInformation & SACL_SECURITY_INFORMATION)
188 {
189 Control |= SE_SACL_PRESENT;
190 }
191
192 if (*BufferLength < SdSize)
193 {
194 *BufferLength = SdSize;
195 return STATUS_BUFFER_TOO_SMALL;
196 }
197
198 *BufferLength = SdSize;
199
200 Status = RtlCreateSecurityDescriptorRelative(RelSd,
201 SECURITY_DESCRIPTOR_REVISION);
202 if (!NT_SUCCESS(Status))
203 return Status;
204
205 RelSd->Control |= Control;
206 RelSd->Owner = Owner;
207 RelSd->Group = Group;
208 RelSd->Dacl = Dacl;
209
210 if (Owner)
211 RtlCopyMemory((PUCHAR)RelSd + Owner,
212 SeWorldSid,
213 SidSize);
214
215 if (Group)
216 RtlCopyMemory((PUCHAR)RelSd + Group,
217 SeWorldSid,
218 SidSize);
219
220 if (Dacl)
221 {
222 Status = RtlCreateAcl((PACL)((PUCHAR)RelSd + Dacl),
223 AclSize,
224 ACL_REVISION);
225 if (NT_SUCCESS(Status))
226 {
227 Status = RtlAddAccessAllowedAce((PACL)((PUCHAR)RelSd + Dacl),
228 ACL_REVISION,
229 GENERIC_ALL,
230 SeWorldSid);
231 }
232 }
233
234 ASSERT(Status == STATUS_SUCCESS);
235 return Status;
236 }
237
238 NTSTATUS
239 NTAPI
240 CmpSecurityMethod(IN PVOID ObjectBody,
241 IN SECURITY_OPERATION_CODE OperationCode,
242 IN PSECURITY_INFORMATION SecurityInformation,
243 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
244 IN OUT PULONG BufferLength,
245 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
246 IN POOL_TYPE PoolType,
247 IN PGENERIC_MAPPING GenericMapping)
248 {
249 DBG_UNREFERENCED_PARAMETER(OldSecurityDescriptor);
250 DBG_UNREFERENCED_PARAMETER(GenericMapping);
251
252 switch (OperationCode)
253 {
254 case SetSecurityDescriptor:
255 DPRINT("Set security descriptor\n");
256 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
257 /* HACK */
258 break;
259
260 case QuerySecurityDescriptor:
261 DPRINT("Query security descriptor\n");
262 return CmpQuerySecurityDescriptor(ObjectBody,
263 *SecurityInformation,
264 SecurityDescriptor,
265 BufferLength);
266
267 case DeleteSecurityDescriptor:
268 DPRINT("Delete security descriptor\n");
269 /* HACK */
270 break;
271
272 case AssignSecurityDescriptor:
273 DPRINT("Assign security descriptor\n");
274 /* HACK */
275 break;
276
277 default:
278 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
279 }
280
281 /* HACK */
282 return STATUS_SUCCESS;
283 }