[CRT] Massively improve performance of rand_s
[reactos.git] / base / system / services / security.c
1 /*
2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/security.c
5 * PURPOSE: Security functions
6 * COPYRIGHT: Eric Kohl
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "services.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 static PSID pNullSid = NULL;
17 static PSID pWorldSid = NULL;
18 static PSID pLocalSystemSid = NULL;
19 static PSID pAuthenticatedUserSid = NULL;
20 static PSID pAliasAdminsSid = NULL;
21
22 static PACL pDefaultDacl = NULL;
23 static PACL pDefaultSacl = NULL;
24 static PACL pPipeDacl = NULL;
25
26 static PSECURITY_DESCRIPTOR pDefaultSD = NULL;
27 PSECURITY_DESCRIPTOR pPipeSD = NULL;
28
29
30 /* FUNCTIONS ****************************************************************/
31
32 static
33 VOID
34 ScmFreeSids(VOID)
35 {
36 if (pNullSid != NULL)
37 RtlFreeHeap(RtlGetProcessHeap(), 0, pNullSid);
38
39 if (pWorldSid != NULL)
40 RtlFreeHeap(RtlGetProcessHeap(), 0, pWorldSid);
41
42 if (pLocalSystemSid != NULL)
43 RtlFreeHeap(RtlGetProcessHeap(), 0, pLocalSystemSid);
44
45 if (pAuthenticatedUserSid != NULL)
46 RtlFreeHeap(RtlGetProcessHeap(), 0, pAuthenticatedUserSid);
47
48 if (pAliasAdminsSid != NULL)
49 RtlFreeHeap(RtlGetProcessHeap(), 0, pAliasAdminsSid);
50 }
51
52
53 static
54 DWORD
55 ScmCreateSids(VOID)
56 {
57 SID_IDENTIFIER_AUTHORITY NullAuthority = {SECURITY_NULL_SID_AUTHORITY};
58 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
59 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
60 PULONG pSubAuthority;
61 ULONG ulLength1 = RtlLengthRequiredSid(1);
62 ULONG ulLength2 = RtlLengthRequiredSid(2);
63
64 /* Create the Null SID */
65 pNullSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
66 if (pNullSid == NULL)
67 {
68 return ERROR_OUTOFMEMORY;
69 }
70
71 RtlInitializeSid(pNullSid, &NullAuthority, 1);
72 pSubAuthority = RtlSubAuthoritySid(pNullSid, 0);
73 *pSubAuthority = SECURITY_NULL_RID;
74
75 /* Create the World SID */
76 pWorldSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
77 if (pWorldSid == NULL)
78 {
79 return ERROR_OUTOFMEMORY;
80 }
81
82 RtlInitializeSid(pWorldSid, &WorldAuthority, 1);
83 pSubAuthority = RtlSubAuthoritySid(pWorldSid, 0);
84 *pSubAuthority = SECURITY_WORLD_RID;
85
86 /* Create the LocalSystem SID */
87 pLocalSystemSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
88 if (pLocalSystemSid == NULL)
89 {
90 return ERROR_OUTOFMEMORY;
91 }
92
93 RtlInitializeSid(pLocalSystemSid, &NtAuthority, 1);
94 pSubAuthority = RtlSubAuthoritySid(pLocalSystemSid, 0);
95 *pSubAuthority = SECURITY_LOCAL_SYSTEM_RID;
96
97 /* Create the AuthenticatedUser SID */
98 pAuthenticatedUserSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength1);
99 if (pAuthenticatedUserSid == NULL)
100 {
101 return ERROR_OUTOFMEMORY;
102 }
103
104 RtlInitializeSid(pAuthenticatedUserSid, &NtAuthority, 1);
105 pSubAuthority = RtlSubAuthoritySid(pAuthenticatedUserSid, 0);
106 *pSubAuthority = SECURITY_AUTHENTICATED_USER_RID;
107
108 /* Create the AliasAdmins SID */
109 pAliasAdminsSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulLength2);
110 if (pAliasAdminsSid == NULL)
111 {
112 return ERROR_OUTOFMEMORY;
113 }
114
115 RtlInitializeSid(pAliasAdminsSid, &NtAuthority, 2);
116 pSubAuthority = RtlSubAuthoritySid(pAliasAdminsSid, 0);
117 *pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
118 pSubAuthority = RtlSubAuthoritySid(pAliasAdminsSid, 1);
119 *pSubAuthority = DOMAIN_ALIAS_RID_ADMINS;
120
121 return ERROR_SUCCESS;
122 }
123
124
125 static
126 DWORD
127 ScmCreateAcls(VOID)
128 {
129 ULONG ulLength;
130
131 /* Create DACL */
132 ulLength = sizeof(ACL) +
133 (sizeof(ACE) + RtlLengthSid(pLocalSystemSid)) +
134 (sizeof(ACE) + RtlLengthSid(pAliasAdminsSid)) +
135 (sizeof(ACE) + RtlLengthSid(pAuthenticatedUserSid));
136
137 pDefaultDacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
138 if (pDefaultDacl == NULL)
139 return ERROR_OUTOFMEMORY;
140
141 RtlCreateAcl(pDefaultDacl, ulLength, ACL_REVISION);
142
143 RtlAddAccessAllowedAce(pDefaultDacl,
144 ACL_REVISION,
145 READ_CONTROL | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE |
146 SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS |
147 SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL,
148 pLocalSystemSid);
149
150 RtlAddAccessAllowedAce(pDefaultDacl,
151 ACL_REVISION,
152 SERVICE_ALL_ACCESS,
153 pAliasAdminsSid);
154
155 RtlAddAccessAllowedAce(pDefaultDacl,
156 ACL_REVISION,
157 READ_CONTROL | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE |
158 SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_USER_DEFINED_CONTROL,
159 pAuthenticatedUserSid);
160
161 /* Create SACL */
162 ulLength = sizeof(ACL) +
163 (sizeof(ACE) + RtlLengthSid(pNullSid));
164
165 pDefaultSacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
166 if (pDefaultSacl == NULL)
167 return ERROR_OUTOFMEMORY;
168
169 RtlCreateAcl(pDefaultSacl, ulLength, ACL_REVISION);
170
171 RtlAddAuditAccessAce(pDefaultSacl,
172 ACL_REVISION,
173 SERVICE_ALL_ACCESS,
174 pNullSid,
175 FALSE,
176 TRUE);
177
178 /* Create the pipe DACL */
179 ulLength = sizeof(ACL) +
180 (sizeof(ACE) + RtlLengthSid(pWorldSid));
181
182 pPipeDacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
183 if (pPipeDacl == NULL)
184 return ERROR_OUTOFMEMORY;
185
186 RtlCreateAcl(pPipeDacl, ulLength, ACL_REVISION);
187
188 RtlAddAccessAllowedAce(pPipeDacl,
189 ACL_REVISION,
190 GENERIC_ALL,
191 pWorldSid);
192
193 return ERROR_SUCCESS;
194 }
195
196
197 static
198 VOID
199 ScmFreeAcls(VOID)
200 {
201 if (pDefaultDacl != NULL)
202 RtlFreeHeap(RtlGetProcessHeap(), 0, pDefaultDacl);
203
204 if (pDefaultSacl != NULL)
205 RtlFreeHeap(RtlGetProcessHeap(), 0, pDefaultSacl);
206
207 if (pPipeDacl != NULL)
208 RtlFreeHeap(RtlGetProcessHeap(), 0, pPipeDacl);
209 }
210
211
212 static
213 DWORD
214 ScmCreateDefaultSD(VOID)
215 {
216 NTSTATUS Status;
217
218 /* Create the absolute security descriptor */
219 pDefaultSD = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SECURITY_DESCRIPTOR));
220 if (pDefaultSD == NULL)
221 return ERROR_OUTOFMEMORY;
222
223 DPRINT("pDefaultSD %p\n", pDefaultSD);
224
225 Status = RtlCreateSecurityDescriptor(pDefaultSD,
226 SECURITY_DESCRIPTOR_REVISION);
227 if (!NT_SUCCESS(Status))
228 return RtlNtStatusToDosError(Status);
229
230 Status = RtlSetOwnerSecurityDescriptor(pDefaultSD,
231 pLocalSystemSid,
232 FALSE);
233 if (!NT_SUCCESS(Status))
234 return RtlNtStatusToDosError(Status);
235
236 Status = RtlSetGroupSecurityDescriptor(pDefaultSD,
237 pLocalSystemSid,
238 FALSE);
239 if (!NT_SUCCESS(Status))
240 return RtlNtStatusToDosError(Status);
241
242 Status = RtlSetDaclSecurityDescriptor(pDefaultSD,
243 TRUE,
244 pDefaultDacl,
245 FALSE);
246 if (!NT_SUCCESS(Status))
247 return RtlNtStatusToDosError(Status);
248
249 Status = RtlSetSaclSecurityDescriptor(pDefaultSD,
250 TRUE,
251 pDefaultSacl,
252 FALSE);
253 if (!NT_SUCCESS(Status))
254 return RtlNtStatusToDosError(Status);
255
256 return ERROR_SUCCESS;
257 }
258
259
260 static
261 VOID
262 ScmFreeDefaultSD(VOID)
263 {
264 if (pDefaultSD != NULL)
265 RtlFreeHeap(RtlGetProcessHeap(), 0, pDefaultSD);
266 }
267
268
269 static
270 DWORD
271 ScmCreatePipeSD(VOID)
272 {
273 NTSTATUS Status;
274
275 /* Create the absolute security descriptor */
276 pPipeSD = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SECURITY_DESCRIPTOR));
277 if (pPipeSD == NULL)
278 return ERROR_OUTOFMEMORY;
279
280 DPRINT("pPipeSD %p\n", pDefaultSD);
281
282 Status = RtlCreateSecurityDescriptor(pPipeSD,
283 SECURITY_DESCRIPTOR_REVISION);
284 if (!NT_SUCCESS(Status))
285 return RtlNtStatusToDosError(Status);
286
287 Status = RtlSetOwnerSecurityDescriptor(pPipeSD,
288 pLocalSystemSid,
289 FALSE);
290 if (!NT_SUCCESS(Status))
291 return RtlNtStatusToDosError(Status);
292
293 Status = RtlSetGroupSecurityDescriptor(pPipeSD,
294 pLocalSystemSid,
295 FALSE);
296 if (!NT_SUCCESS(Status))
297 return RtlNtStatusToDosError(Status);
298
299 Status = RtlSetDaclSecurityDescriptor(pPipeSD,
300 TRUE,
301 pPipeDacl,
302 FALSE);
303 if (!NT_SUCCESS(Status))
304 return RtlNtStatusToDosError(Status);
305
306 return ERROR_SUCCESS;
307 }
308
309
310 static
311 VOID
312 ScmFreePipeSD(VOID)
313 {
314 if (pPipeSD != NULL)
315 RtlFreeHeap(RtlGetProcessHeap(), 0, pPipeSD);
316 }
317
318
319 DWORD
320 ScmCreateDefaultServiceSD(
321 PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
322 {
323 PSECURITY_DESCRIPTOR pRelativeSD = NULL;
324 DWORD dwBufferLength = 0;
325 NTSTATUS Status;
326 DWORD dwError = ERROR_SUCCESS;
327
328 /* Convert the absolute SD to a self-relative SD */
329 Status = RtlAbsoluteToSelfRelativeSD(pDefaultSD,
330 NULL,
331 &dwBufferLength);
332 if (Status != STATUS_BUFFER_TOO_SMALL)
333 {
334 dwError = RtlNtStatusToDosError(Status);
335 goto done;
336 }
337
338 DPRINT("BufferLength %lu\n", dwBufferLength);
339
340 pRelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
341 HEAP_ZERO_MEMORY,
342 dwBufferLength);
343 if (pRelativeSD == NULL)
344 {
345 dwError = ERROR_OUTOFMEMORY;
346 goto done;
347 }
348 DPRINT("pRelativeSD %p\n", pRelativeSD);
349
350 Status = RtlAbsoluteToSelfRelativeSD(pDefaultSD,
351 pRelativeSD,
352 &dwBufferLength);
353 if (!NT_SUCCESS(Status))
354 {
355 dwError = RtlNtStatusToDosError(Status);
356 goto done;
357 }
358
359 *ppSecurityDescriptor = pRelativeSD;
360
361 done:
362 if (dwError != ERROR_SUCCESS)
363 {
364 if (pRelativeSD != NULL)
365 RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD);
366 }
367
368 return dwError;
369 }
370
371
372 DWORD
373 ScmInitializeSecurity(VOID)
374 {
375 DWORD dwError;
376
377 dwError = ScmCreateSids();
378 if (dwError != ERROR_SUCCESS)
379 return dwError;
380
381 dwError = ScmCreateAcls();
382 if (dwError != ERROR_SUCCESS)
383 return dwError;
384
385 dwError = ScmCreateDefaultSD();
386 if (dwError != ERROR_SUCCESS)
387 return dwError;
388
389 dwError = ScmCreatePipeSD();
390 if (dwError != ERROR_SUCCESS)
391 return dwError;
392
393 return ERROR_SUCCESS;
394 }
395
396
397 VOID
398 ScmShutdownSecurity(VOID)
399 {
400 ScmFreePipeSD();
401 ScmFreeDefaultSD();
402 ScmFreeAcls();
403 ScmFreeSids();
404 }
405
406 /* EOF */