[NTOSKRNL] Don't leak DACL
[reactos.git] / ntoskrnl / se / semgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/semgr.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: No programmer listed.
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 PSE_EXPORTS SeExports = NULL;
19 SE_EXPORTS SepExports;
20 ULONG SidInTokenCalls = 0;
21
22 extern ULONG ExpInitializationPhase;
23 extern ERESOURCE SepSubjectContextLock;
24
25 /* PRIVATE FUNCTIONS **********************************************************/
26
27 static BOOLEAN
28 INIT_FUNCTION
29 SepInitExports(VOID)
30 {
31 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
32 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
33 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
34 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
35 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
36 SepExports.SeTcbPrivilege = SeTcbPrivilege;
37 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
38 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
39 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
40 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
41 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
42 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
43 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
44 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
45 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
46 SepExports.SeBackupPrivilege = SeBackupPrivilege;
47 SepExports.SeRestorePrivilege = SeRestorePrivilege;
48 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
49 SepExports.SeDebugPrivilege = SeDebugPrivilege;
50 SepExports.SeAuditPrivilege = SeAuditPrivilege;
51 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
52 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
53 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
54
55 SepExports.SeNullSid = SeNullSid;
56 SepExports.SeWorldSid = SeWorldSid;
57 SepExports.SeLocalSid = SeLocalSid;
58 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
59 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
60 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
61 SepExports.SeDialupSid = SeDialupSid;
62 SepExports.SeNetworkSid = SeNetworkSid;
63 SepExports.SeBatchSid = SeBatchSid;
64 SepExports.SeInteractiveSid = SeInteractiveSid;
65 SepExports.SeLocalSystemSid = SeLocalSystemSid;
66 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
67 SepExports.SeAliasUsersSid = SeAliasUsersSid;
68 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
69 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
70 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
71 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
72 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
73 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
74 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
75 SepExports.SeRestrictedSid = SeRestrictedSid;
76 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
77 SepExports.SeLocalServiceSid = SeLocalServiceSid;
78 SepExports.SeNetworkServiceSid = SeNetworkServiceSid;
79
80 SepExports.SeUndockPrivilege = SeUndockPrivilege;
81 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
82 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
83 SepExports.SeManageVolumePrivilege = SeManageVolumePrivilege;
84 SepExports.SeImpersonatePrivilege = SeImpersonatePrivilege;
85 SepExports.SeCreateGlobalPrivilege = SeCreateGlobalPrivilege;
86
87 SeExports = &SepExports;
88 return TRUE;
89 }
90
91
92 BOOLEAN
93 NTAPI
94 INIT_FUNCTION
95 SepInitializationPhase0(VOID)
96 {
97 PAGED_CODE();
98
99 ExpInitLuid();
100 if (!SepInitSecurityIDs()) return FALSE;
101 if (!SepInitDACLs()) return FALSE;
102 if (!SepInitSDs()) return FALSE;
103 SepInitPrivileges();
104 if (!SepInitExports()) return FALSE;
105
106 /* Initialize the subject context lock */
107 ExInitializeResource(&SepSubjectContextLock);
108
109 /* Initialize token objects */
110 SepInitializeTokenImplementation();
111
112 /* Initialize logon sessions */
113 if (!SeRmInitPhase0()) return FALSE;
114
115 /* Clear impersonation info for the idle thread */
116 PsGetCurrentThread()->ImpersonationInfo = NULL;
117 PspClearCrossThreadFlag(PsGetCurrentThread(),
118 CT_ACTIVE_IMPERSONATION_INFO_BIT);
119
120 /* Initialize the boot token */
121 ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
122 ObInitializeFastReference(&PsGetCurrentProcess()->Token,
123 SepCreateSystemProcessToken());
124 return TRUE;
125 }
126
127 BOOLEAN
128 NTAPI
129 INIT_FUNCTION
130 SepInitializationPhase1(VOID)
131 {
132 OBJECT_ATTRIBUTES ObjectAttributes;
133 UNICODE_STRING Name;
134 HANDLE SecurityHandle;
135 HANDLE EventHandle;
136 NTSTATUS Status;
137 SECURITY_DESCRIPTOR SecurityDescriptor;
138 PACL Dacl;
139 ULONG DaclLength;
140
141 PAGED_CODE();
142
143 /* Insert the system token into the tree */
144 Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
145 ~MAX_FAST_REFS),
146 NULL,
147 0,
148 0,
149 NULL,
150 NULL);
151 ASSERT(NT_SUCCESS(Status));
152
153 /* Create a security descriptor for the directory */
154 RtlCreateSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
155
156 /* Setup the ACL */
157 DaclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
158 RtlLengthSid(SeLocalSystemSid) +
159 RtlLengthSid(SeAliasAdminsSid) +
160 RtlLengthSid(SeWorldSid);
161 Dacl = ExAllocatePoolWithTag(NonPagedPool, DaclLength, TAG_SE);
162 if (Dacl == NULL)
163 {
164 return FALSE;
165 }
166
167 Status = RtlCreateAcl(Dacl, DaclLength, ACL_REVISION);
168 ASSERT(NT_SUCCESS(Status));
169
170 /* Grant full access to SYSTEM */
171 Status = RtlAddAccessAllowedAce(Dacl,
172 ACL_REVISION,
173 DIRECTORY_ALL_ACCESS,
174 SeLocalSystemSid);
175 ASSERT(NT_SUCCESS(Status));
176
177 /* Allow admins to traverse and query */
178 Status = RtlAddAccessAllowedAce(Dacl,
179 ACL_REVISION,
180 READ_CONTROL | DIRECTORY_TRAVERSE | DIRECTORY_QUERY,
181 SeAliasAdminsSid);
182 ASSERT(NT_SUCCESS(Status));
183
184 /* Allow anyone to traverse */
185 Status = RtlAddAccessAllowedAce(Dacl,
186 ACL_REVISION,
187 DIRECTORY_TRAVERSE,
188 SeWorldSid);
189 ASSERT(NT_SUCCESS(Status));
190
191 /* And link ACL and SD */
192 Status = RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl, FALSE);
193 ASSERT(NT_SUCCESS(Status));
194
195 /* Create '\Security' directory */
196 RtlInitUnicodeString(&Name, L"\\Security");
197 InitializeObjectAttributes(&ObjectAttributes,
198 &Name,
199 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
200 0,
201 &SecurityDescriptor);
202
203 Status = ZwCreateDirectoryObject(&SecurityHandle,
204 DIRECTORY_ALL_ACCESS,
205 &ObjectAttributes);
206 ASSERT(NT_SUCCESS(Status));
207
208 /* Free the DACL */
209 ExFreePoolWithTag(Dacl, TAG_SE);
210
211 /* Create 'LSA_AUTHENTICATION_INITIALIZED' event */
212 RtlInitUnicodeString(&Name, L"LSA_AUTHENTICATION_INITIALIZED");
213 InitializeObjectAttributes(&ObjectAttributes,
214 &Name,
215 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
216 SecurityHandle,
217 SePublicDefaultSd);
218
219 Status = ZwCreateEvent(&EventHandle,
220 GENERIC_WRITE,
221 &ObjectAttributes,
222 NotificationEvent,
223 FALSE);
224 ASSERT(NT_SUCCESS(Status));
225
226 Status = ZwClose(EventHandle);
227 ASSERT(NT_SUCCESS(Status));
228
229 Status = ZwClose(SecurityHandle);
230 ASSERT(NT_SUCCESS(Status));
231
232 return TRUE;
233 }
234
235 BOOLEAN
236 NTAPI
237 INIT_FUNCTION
238 SeInitSystem(VOID)
239 {
240 /* Check the initialization phase */
241 switch (ExpInitializationPhase)
242 {
243 case 0:
244
245 /* Do Phase 0 */
246 return SepInitializationPhase0();
247
248 case 1:
249
250 /* Do Phase 1 */
251 return SepInitializationPhase1();
252
253 default:
254
255 /* Don't know any other phase! Bugcheck! */
256 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
257 0,
258 ExpInitializationPhase,
259 0,
260 0);
261 return FALSE;
262 }
263 }
264
265 NTSTATUS
266 NTAPI
267 SeDefaultObjectMethod(IN PVOID Object,
268 IN SECURITY_OPERATION_CODE OperationType,
269 IN PSECURITY_INFORMATION SecurityInformation,
270 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
271 IN OUT PULONG ReturnLength OPTIONAL,
272 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
273 IN POOL_TYPE PoolType,
274 IN PGENERIC_MAPPING GenericMapping)
275 {
276 PAGED_CODE();
277
278 /* Select the operation type */
279 switch (OperationType)
280 {
281 /* Setting a new descriptor */
282 case SetSecurityDescriptor:
283
284 /* Sanity check */
285 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
286
287 /* Set the information */
288 return ObSetSecurityDescriptorInfo(Object,
289 SecurityInformation,
290 SecurityDescriptor,
291 OldSecurityDescriptor,
292 PoolType,
293 GenericMapping);
294
295 case QuerySecurityDescriptor:
296
297 /* Query the information */
298 return ObQuerySecurityDescriptorInfo(Object,
299 SecurityInformation,
300 SecurityDescriptor,
301 ReturnLength,
302 OldSecurityDescriptor);
303
304 case DeleteSecurityDescriptor:
305
306 /* De-assign it */
307 return ObDeassignSecurity(OldSecurityDescriptor);
308
309 case AssignSecurityDescriptor:
310
311 /* Assign it */
312 ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
313 return STATUS_SUCCESS;
314
315 default:
316
317 /* Bug check */
318 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
319 }
320
321 /* Should never reach here */
322 ASSERT(FALSE);
323 return STATUS_SUCCESS;
324 }
325
326 VOID
327 NTAPI
328 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
329 OUT PACCESS_MASK DesiredAccess)
330 {
331 *DesiredAccess = 0;
332
333 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
334 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
335 {
336 *DesiredAccess |= READ_CONTROL;
337 }
338
339 if (SecurityInformation & SACL_SECURITY_INFORMATION)
340 {
341 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
342 }
343 }
344
345 VOID
346 NTAPI
347 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
348 OUT PACCESS_MASK DesiredAccess)
349 {
350 *DesiredAccess = 0;
351
352 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
353 {
354 *DesiredAccess |= WRITE_OWNER;
355 }
356
357 if (SecurityInformation & DACL_SECURITY_INFORMATION)
358 {
359 *DesiredAccess |= WRITE_DAC;
360 }
361
362 if (SecurityInformation & SACL_SECURITY_INFORMATION)
363 {
364 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
365 }
366 }
367
368 NTSTATUS
369 NTAPI
370 SeReportSecurityEvent(
371 _In_ ULONG Flags,
372 _In_ PUNICODE_STRING SourceName,
373 _In_opt_ PSID UserSid,
374 _In_ PSE_ADT_PARAMETER_ARRAY AuditParameters)
375 {
376 SECURITY_SUBJECT_CONTEXT SubjectContext;
377 PTOKEN EffectiveToken;
378 PISID Sid;
379 NTSTATUS Status;
380
381 /* Validate parameters */
382 if ((Flags != 0) ||
383 (SourceName == NULL) ||
384 (SourceName->Buffer == NULL) ||
385 (SourceName->Length == 0) ||
386 (AuditParameters == NULL) ||
387 (AuditParameters->ParameterCount > SE_MAX_AUDIT_PARAMETERS - 4))
388 {
389 return STATUS_INVALID_PARAMETER;
390 }
391
392 /* Validate the source name */
393 Status = RtlValidateUnicodeString(0, SourceName);
394 if (!NT_SUCCESS(Status))
395 {
396 return Status;
397 }
398
399 /* Check if we have a user SID */
400 if (UserSid != NULL)
401 {
402 /* Validate it */
403 if (!RtlValidSid(UserSid))
404 {
405 return STATUS_INVALID_PARAMETER;
406 }
407
408 /* Use the user SID */
409 Sid = UserSid;
410 }
411 else
412 {
413 /* No user SID, capture the security subject context */
414 SeCaptureSubjectContext(&SubjectContext);
415
416 /* Extract the effective token */
417 EffectiveToken = SubjectContext.ClientToken ?
418 SubjectContext.ClientToken : SubjectContext.PrimaryToken;
419
420 /* Use the user-and-groups SID */
421 Sid = EffectiveToken->UserAndGroups->Sid;
422 }
423
424 UNIMPLEMENTED;
425
426 /* Check if we captured the subject context */
427 if (Sid != UserSid)
428 {
429 /* Release it */
430 SeReleaseSubjectContext(&SubjectContext);
431 }
432
433 /* Return success */
434 return STATUS_SUCCESS;
435 }
436
437 _Const_
438 NTSTATUS
439 NTAPI
440 SeSetAuditParameter(
441 _Inout_ PSE_ADT_PARAMETER_ARRAY AuditParameters,
442 _In_ SE_ADT_PARAMETER_TYPE Type,
443 _In_range_(<, SE_MAX_AUDIT_PARAMETERS) ULONG Index,
444 _In_reads_(_Inexpressible_("depends on SE_ADT_PARAMETER_TYPE")) PVOID Data)
445 {
446 UNIMPLEMENTED;
447 return STATUS_SUCCESS;
448 }
449
450 /* EOF */