- Rename KiSetSystemTime to KeSetSystemTime and enhance prototype for later use.
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PSE_EXPORTS SeExports = NULL;
20 SE_EXPORTS SepExports;
21
22 static ERESOURCE SepSubjectContextLock;
23 extern ULONG ExpInitializationPhase;
24
25
26 /* PROTOTYPES ***************************************************************/
27
28 static BOOLEAN SepInitExports(VOID);
29
30 /* FUNCTIONS ****************************************************************/
31
32 BOOLEAN
33 NTAPI
34 SepInitializationPhase0(VOID)
35 {
36 DPRINT1("FIXME: SeAccessCheck has been HACKED to always grant access!\n");
37 DPRINT1("FIXME: Please fix all the code that doesn't get proper rights!\n");
38
39 SepInitLuid();
40 if (!SepInitSecurityIDs()) return FALSE;
41 if (!SepInitDACLs()) return FALSE;
42 if (!SepInitSDs()) return FALSE;
43 SepInitPrivileges();
44 if (!SepInitExports()) return FALSE;
45
46 /* Initialize the subject context lock */
47 ExInitializeResource(&SepSubjectContextLock);
48
49 /* Initialize token objects */
50 SepInitializeTokenImplementation();
51
52 /* Clear impersonation info for the idle thread */
53 PsGetCurrentThread()->ImpersonationInfo = NULL;
54 PspClearCrossThreadFlag(PsGetCurrentThread(),
55 CT_ACTIVE_IMPERSONATION_INFO_BIT);
56
57 /* Initialize the boot token */
58 ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
59 ObInitializeFastReference(&PsGetCurrentProcess()->Token,
60 SepCreateSystemProcessToken());
61 return TRUE;
62 }
63
64 BOOLEAN
65 NTAPI
66 SepInitializationPhase1(VOID)
67 {
68 NTSTATUS Status;
69 PAGED_CODE();
70
71 /* Insert the system token into the tree */
72 Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
73 ~MAX_FAST_REFS),
74 NULL,
75 0,
76 0,
77 NULL,
78 NULL);
79 ASSERT(NT_SUCCESS(Status));
80
81 /* FIXME: TODO \\ Security directory */
82 return TRUE;
83 }
84
85 BOOLEAN
86 NTAPI
87 SeInit(VOID)
88 {
89 /* Check the initialization phase */
90 switch (ExpInitializationPhase)
91 {
92 case 0:
93
94 /* Do Phase 0 */
95 return SepInitializationPhase0();
96
97 case 1:
98
99 /* Do Phase 1 */
100 return SepInitializationPhase1();
101
102 default:
103
104 /* Don't know any other phase! Bugcheck! */
105 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
106 0,
107 ExpInitializationPhase,
108 0,
109 0);
110 return FALSE;
111 }
112 }
113
114 BOOLEAN
115 NTAPI
116 SeInitSRM(VOID)
117 {
118 OBJECT_ATTRIBUTES ObjectAttributes;
119 UNICODE_STRING Name;
120 HANDLE DirectoryHandle;
121 HANDLE EventHandle;
122 NTSTATUS Status;
123
124 /* Create '\Security' directory */
125 RtlInitUnicodeString(&Name,
126 L"\\Security");
127 InitializeObjectAttributes(&ObjectAttributes,
128 &Name,
129 OBJ_PERMANENT,
130 0,
131 NULL);
132 Status = ZwCreateDirectoryObject(&DirectoryHandle,
133 DIRECTORY_ALL_ACCESS,
134 &ObjectAttributes);
135 if (!NT_SUCCESS(Status))
136 {
137 DPRINT1("Failed to create 'Security' directory!\n");
138 return FALSE;
139 }
140
141 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
142 RtlInitUnicodeString(&Name,
143 L"\\LSA_AUTHENTICATION_INITALIZED");
144 InitializeObjectAttributes(&ObjectAttributes,
145 &Name,
146 OBJ_PERMANENT,
147 DirectoryHandle,
148 SePublicDefaultSd);
149 Status = ZwCreateEvent(&EventHandle,
150 EVENT_ALL_ACCESS,
151 &ObjectAttributes,
152 SynchronizationEvent,
153 FALSE);
154 if (!NT_SUCCESS(Status))
155 {
156 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
157 NtClose(DirectoryHandle);
158 return FALSE;
159 }
160
161 ZwClose(EventHandle);
162 ZwClose(DirectoryHandle);
163
164 /* FIXME: Create SRM port and listener thread */
165
166 return TRUE;
167 }
168
169
170 static BOOLEAN INIT_FUNCTION
171 SepInitExports(VOID)
172 {
173 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
174 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
175 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
176 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
177 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
178 SepExports.SeTcbPrivilege = SeTcbPrivilege;
179 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
180 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
181 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
182 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
183 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
184 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
185 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
186 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
187 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
188 SepExports.SeBackupPrivilege = SeBackupPrivilege;
189 SepExports.SeRestorePrivilege = SeRestorePrivilege;
190 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
191 SepExports.SeDebugPrivilege = SeDebugPrivilege;
192 SepExports.SeAuditPrivilege = SeAuditPrivilege;
193 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
194 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
195 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
196
197 SepExports.SeNullSid = SeNullSid;
198 SepExports.SeWorldSid = SeWorldSid;
199 SepExports.SeLocalSid = SeLocalSid;
200 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
201 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
202 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
203 SepExports.SeDialupSid = SeDialupSid;
204 SepExports.SeNetworkSid = SeNetworkSid;
205 SepExports.SeBatchSid = SeBatchSid;
206 SepExports.SeInteractiveSid = SeInteractiveSid;
207 SepExports.SeLocalSystemSid = SeLocalSystemSid;
208 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
209 SepExports.SeAliasUsersSid = SeAliasUsersSid;
210 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
211 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
212 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
213 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
214 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
215 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
216 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
217 SepExports.SeRestrictedSid = SeRestrictedSid;
218 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
219
220 SepExports.SeUndockPrivilege = SeUndockPrivilege;
221 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
222 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
223
224 SeExports = &SepExports;
225 return TRUE;
226 }
227
228
229 VOID SepReferenceLogonSession(PLUID AuthenticationId)
230 {
231 UNIMPLEMENTED;
232 }
233
234 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
235 {
236 UNIMPLEMENTED;
237 }
238
239 NTSTATUS
240 STDCALL
241 SeDefaultObjectMethod(PVOID Object,
242 SECURITY_OPERATION_CODE OperationType,
243 PSECURITY_INFORMATION _SecurityInformation,
244 PSECURITY_DESCRIPTOR _SecurityDescriptor,
245 PULONG ReturnLength,
246 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
247 POOL_TYPE PoolType,
248 PGENERIC_MAPPING GenericMapping)
249 {
250 PISECURITY_DESCRIPTOR ObjectSd;
251 PISECURITY_DESCRIPTOR NewSd;
252 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
253 POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
254 PSID Owner = 0;
255 PSID Group = 0;
256 PACL Dacl = 0;
257 PACL Sacl = 0;
258 ULONG OwnerLength = 0;
259 ULONG GroupLength = 0;
260 ULONG DaclLength = 0;
261 ULONG SaclLength = 0;
262 ULONG Control = 0;
263 ULONG_PTR Current;
264 NTSTATUS Status;
265 SECURITY_INFORMATION SecurityInformation;
266
267 if (OperationType == SetSecurityDescriptor)
268 {
269 ObjectSd = Header->SecurityDescriptor;
270 SecurityInformation = *_SecurityInformation;
271
272 /* Get owner and owner size */
273 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
274 {
275 if (SecurityDescriptor->Owner != NULL)
276 {
277 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
278 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
279 (ULONG_PTR)SecurityDescriptor);
280 else
281 Owner = (PSID)SecurityDescriptor->Owner;
282 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
283 }
284 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
285 }
286 else
287 {
288 if (ObjectSd->Owner != NULL)
289 {
290 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
291 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
292 }
293 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
294 }
295
296 /* Get group and group size */
297 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
298 {
299 if (SecurityDescriptor->Group != NULL)
300 {
301 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
302 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
303 (ULONG_PTR)SecurityDescriptor);
304 else
305 Group = (PSID)SecurityDescriptor->Group;
306 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
307 }
308 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
309 }
310 else
311 {
312 if (ObjectSd->Group != NULL)
313 {
314 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
315 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
316 }
317 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
318 }
319
320 /* Get DACL and DACL size */
321 if (SecurityInformation & DACL_SECURITY_INFORMATION)
322 {
323 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
324 (SecurityDescriptor->Dacl != NULL))
325 {
326 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
327 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
328 (ULONG_PTR)SecurityDescriptor);
329 else
330 Dacl = (PACL)SecurityDescriptor->Dacl;
331
332 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
333 }
334 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
335 }
336 else
337 {
338 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
339 (ObjectSd->Dacl != NULL))
340 {
341 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
342 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
343 }
344 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
345 }
346
347 /* Get SACL and SACL size */
348 if (SecurityInformation & SACL_SECURITY_INFORMATION)
349 {
350 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
351 (SecurityDescriptor->Sacl != NULL))
352 {
353 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
354 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
355 (ULONG_PTR)SecurityDescriptor);
356 else
357 Sacl = (PACL)SecurityDescriptor->Sacl;
358 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
359 }
360 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
361 }
362 else
363 {
364 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
365 (ObjectSd->Sacl != NULL))
366 {
367 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
368 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
369 }
370 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
371 }
372
373 NewSd = ExAllocatePool(NonPagedPool,
374 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
375 DaclLength + SaclLength);
376 if (NewSd == NULL)
377 {
378 ObDereferenceObject(Object);
379 return STATUS_INSUFFICIENT_RESOURCES;
380 }
381
382 RtlCreateSecurityDescriptor(NewSd,
383 SECURITY_DESCRIPTOR_REVISION1);
384 /* We always build a self-relative descriptor */
385 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
386
387 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
388
389 if (OwnerLength != 0)
390 {
391 RtlCopyMemory((PVOID)Current,
392 Owner,
393 OwnerLength);
394 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
395 Current += OwnerLength;
396 }
397
398 if (GroupLength != 0)
399 {
400 RtlCopyMemory((PVOID)Current,
401 Group,
402 GroupLength);
403 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
404 Current += GroupLength;
405 }
406
407 if (DaclLength != 0)
408 {
409 RtlCopyMemory((PVOID)Current,
410 Dacl,
411 DaclLength);
412 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
413 Current += DaclLength;
414 }
415
416 if (SaclLength != 0)
417 {
418 RtlCopyMemory((PVOID)Current,
419 Sacl,
420 SaclLength);
421 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
422 Current += SaclLength;
423 }
424
425 /* Add the new SD */
426 Status = ObpAddSecurityDescriptor(NewSd,
427 &Header->SecurityDescriptor);
428 if (NT_SUCCESS(Status))
429 {
430 /* Remove the old security descriptor */
431 ObpRemoveSecurityDescriptor(ObjectSd);
432 }
433 else
434 {
435 /* Restore the old security descriptor */
436 Header->SecurityDescriptor = ObjectSd;
437 }
438
439 ExFreePool(NewSd);
440 }
441 else if (OperationType == QuerySecurityDescriptor)
442 {
443 Status = SeQuerySecurityDescriptorInfo(_SecurityInformation,
444 SecurityDescriptor,
445 ReturnLength,
446 &Header->SecurityDescriptor);
447 }
448 else if (OperationType == AssignSecurityDescriptor)
449 {
450 /* Assign the security descriptor to the object header */
451 Status = ObpAddSecurityDescriptor(SecurityDescriptor,
452 &Header->SecurityDescriptor);
453 }
454
455
456 return STATUS_SUCCESS;
457 }
458
459 VOID
460 NTAPI
461 SeCaptureSubjectContextEx(IN PETHREAD Thread,
462 IN PEPROCESS Process,
463 OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
464 {
465 BOOLEAN CopyOnOpen, EffectiveOnly;
466 PAGED_CODE();
467
468 /* Save the unique ID */
469 SubjectContext->ProcessAuditId = Process->UniqueProcessId;
470
471 /* Check if we have a thread */
472 if (!Thread)
473 {
474 /* We don't, so no token */
475 SubjectContext->ClientToken = NULL;
476 }
477 else
478 {
479 /* Get the impersonation token */
480 SubjectContext->ClientToken =
481 PsReferenceImpersonationToken(Thread,
482 &CopyOnOpen,
483 &EffectiveOnly,
484 &SubjectContext->ImpersonationLevel);
485 }
486
487 /* Get the primary token */
488 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process);
489 }
490
491 /*
492 * @implemented
493 */
494 VOID
495 NTAPI
496 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
497 {
498 /* Call the internal API */
499 SeCaptureSubjectContextEx(PsGetCurrentThread(),
500 PsGetCurrentProcess(),
501 SubjectContext);
502 }
503
504
505 /*
506 * @implemented
507 */
508 VOID STDCALL
509 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
510 {
511 PAGED_CODE();
512
513 KeEnterCriticalRegion();
514 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
515 }
516
517
518 /*
519 * @implemented
520 */
521 VOID STDCALL
522 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
523 {
524 PAGED_CODE();
525
526 ExReleaseResourceLite(&SepSubjectContextLock);
527 KeLeaveCriticalRegion();
528 }
529
530
531 /*
532 * @implemented
533 */
534 VOID STDCALL
535 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
536 {
537 PAGED_CODE();
538
539 if (SubjectContext->PrimaryToken != NULL)
540 {
541 ObFastDereferenceObject(&PsGetCurrentProcess()->Token, SubjectContext->PrimaryToken);
542 }
543
544 if (SubjectContext->ClientToken != NULL)
545 {
546 ObDereferenceObject(SubjectContext->ClientToken);
547 }
548 }
549
550
551 /*
552 * @implemented
553 */
554 NTSTATUS STDCALL
555 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
556 {
557 PAGED_CODE();
558
559 if (*SecurityDescriptor != NULL)
560 {
561 ExFreePool(*SecurityDescriptor);
562 *SecurityDescriptor = NULL;
563 }
564
565 return STATUS_SUCCESS;
566 }
567
568
569 /*
570 * @unimplemented
571 */
572 NTSTATUS STDCALL
573 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
574 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
575 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
576 IN GUID *ObjectType OPTIONAL,
577 IN BOOLEAN IsDirectoryObject,
578 IN ULONG AutoInheritFlags,
579 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
580 IN PGENERIC_MAPPING GenericMapping,
581 IN POOL_TYPE PoolType)
582 {
583 UNIMPLEMENTED;
584 return STATUS_NOT_IMPLEMENTED;
585 }
586
587
588 /*
589 * FUNCTION: Creates a security descriptor for a new object.
590 * ARGUMENTS:
591 * ParentDescriptor =
592 * ExplicitDescriptor =
593 * NewDescriptor =
594 * IsDirectoryObject =
595 * SubjectContext =
596 * GeneralMapping =
597 * PoolType =
598 * RETURNS: Status
599 *
600 * @implemented
601 */
602 NTSTATUS STDCALL
603 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
604 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
605 PSECURITY_DESCRIPTOR *NewDescriptor,
606 BOOLEAN IsDirectoryObject,
607 PSECURITY_SUBJECT_CONTEXT SubjectContext,
608 PGENERIC_MAPPING GenericMapping,
609 POOL_TYPE PoolType)
610 {
611 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
612 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
613 PISECURITY_DESCRIPTOR Descriptor;
614 PTOKEN Token;
615 ULONG OwnerLength = 0;
616 ULONG GroupLength = 0;
617 ULONG DaclLength = 0;
618 ULONG SaclLength = 0;
619 ULONG Length = 0;
620 ULONG Control = 0;
621 ULONG_PTR Current;
622 PSID Owner = NULL;
623 PSID Group = NULL;
624 PACL Dacl = NULL;
625 PACL Sacl = NULL;
626
627 PAGED_CODE();
628
629 /* Lock subject context */
630 SeLockSubjectContext(SubjectContext);
631
632 if (SubjectContext->ClientToken != NULL)
633 {
634 Token = SubjectContext->ClientToken;
635 }
636 else
637 {
638 Token = SubjectContext->PrimaryToken;
639 }
640
641
642 /* Inherit the Owner SID */
643 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
644 {
645 DPRINT("Use explicit owner sid!\n");
646 Owner = ExplicitDescriptor->Owner;
647
648 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
649 {
650 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
651
652 }
653 }
654 else
655 {
656 if (Token != NULL)
657 {
658 DPRINT("Use token owner sid!\n");
659 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
660 }
661 else
662 {
663 DPRINT("Use default owner sid!\n");
664 Owner = SeLocalSystemSid;
665 }
666
667 Control |= SE_OWNER_DEFAULTED;
668 }
669
670 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
671
672
673 /* Inherit the Group SID */
674 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
675 {
676 DPRINT("Use explicit group sid!\n");
677 Group = ExplicitDescriptor->Group;
678 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
679 {
680 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
681 }
682 }
683 else
684 {
685 if (Token != NULL)
686 {
687 DPRINT("Use token group sid!\n");
688 Group = Token->PrimaryGroup;
689 }
690 else
691 {
692 DPRINT("Use default group sid!\n");
693 Group = SeLocalSystemSid;
694 }
695
696 Control |= SE_OWNER_DEFAULTED;
697 }
698
699 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
700
701
702 /* Inherit the DACL */
703 if (ExplicitDescriptor != NULL &&
704 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
705 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
706 {
707 DPRINT("Use explicit DACL!\n");
708 Dacl = ExplicitDescriptor->Dacl;
709 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
710 {
711 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
712 }
713
714 Control |= SE_DACL_PRESENT;
715 }
716 else if (ParentDescriptor != NULL &&
717 (ParentDescriptor->Control & SE_DACL_PRESENT))
718 {
719 DPRINT("Use parent DACL!\n");
720 /* FIXME: Inherit */
721 Dacl = ParentDescriptor->Dacl;
722 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
723 {
724 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
725 }
726 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
727 }
728 else if (Token != NULL && Token->DefaultDacl != NULL)
729 {
730 DPRINT("Use token default DACL!\n");
731 /* FIXME: Inherit */
732 Dacl = Token->DefaultDacl;
733 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
734 }
735 else
736 {
737 DPRINT("Use NULL DACL!\n");
738 Dacl = NULL;
739 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
740 }
741
742 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
743
744
745 /* Inherit the SACL */
746 if (ExplicitDescriptor != NULL &&
747 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
748 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
749 {
750 DPRINT("Use explicit SACL!\n");
751 Sacl = ExplicitDescriptor->Sacl;
752 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
753 {
754 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
755 }
756
757 Control |= SE_SACL_PRESENT;
758 }
759 else if (ParentDescriptor != NULL &&
760 (ParentDescriptor->Control & SE_SACL_PRESENT))
761 {
762 DPRINT("Use parent SACL!\n");
763 /* FIXME: Inherit */
764 Sacl = ParentDescriptor->Sacl;
765 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
766 {
767 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
768 }
769 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
770 }
771
772 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
773
774
775 /* Allocate and initialize the new security descriptor */
776 Length = sizeof(SECURITY_DESCRIPTOR) +
777 OwnerLength + GroupLength + DaclLength + SaclLength;
778
779 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
780 sizeof(SECURITY_DESCRIPTOR),
781 OwnerLength,
782 GroupLength,
783 DaclLength,
784 SaclLength);
785
786 Descriptor = ExAllocatePool(PagedPool,
787 Length);
788 if (Descriptor == NULL)
789 {
790 DPRINT1("ExAlloctePool() failed\n");
791 /* FIXME: Unlock subject context */
792 return STATUS_INSUFFICIENT_RESOURCES;
793 }
794
795 RtlZeroMemory( Descriptor, Length );
796 RtlCreateSecurityDescriptor(Descriptor,
797 SECURITY_DESCRIPTOR_REVISION);
798
799 Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
800
801 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
802
803 if (SaclLength != 0)
804 {
805 RtlCopyMemory((PVOID)Current,
806 Sacl,
807 SaclLength);
808 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
809 Current += SaclLength;
810 }
811
812 if (DaclLength != 0)
813 {
814 RtlCopyMemory((PVOID)Current,
815 Dacl,
816 DaclLength);
817 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
818 Current += DaclLength;
819 }
820
821 if (OwnerLength != 0)
822 {
823 RtlCopyMemory((PVOID)Current,
824 Owner,
825 OwnerLength);
826 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
827 Current += OwnerLength;
828 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
829 }
830 else
831 DPRINT("Owner of %x is zero length\n", Descriptor);
832
833 if (GroupLength != 0)
834 {
835 memmove((PVOID)Current,
836 Group,
837 GroupLength);
838 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
839 }
840
841 /* Unlock subject context */
842 SeUnlockSubjectContext(SubjectContext);
843
844 *NewDescriptor = Descriptor;
845
846 DPRINT("Descrptor %x\n", Descriptor);
847 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
848
849 return STATUS_SUCCESS;
850 }
851
852
853 static BOOLEAN
854 SepSidInToken(PACCESS_TOKEN _Token,
855 PSID Sid)
856 {
857 ULONG i;
858 PTOKEN Token = (PTOKEN)_Token;
859
860 PAGED_CODE();
861
862 if (Token->UserAndGroupCount == 0)
863 {
864 return FALSE;
865 }
866
867 for (i=0; i<Token->UserAndGroupCount; i++)
868 {
869 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
870 {
871 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
872 {
873 return TRUE;
874 }
875
876 return FALSE;
877 }
878 }
879
880 return FALSE;
881 }
882
883
884 /*
885 * FUNCTION: Determines whether the requested access rights can be granted
886 * to an object protected by a security descriptor and an object owner
887 * ARGUMENTS:
888 * SecurityDescriptor = Security descriptor protecting the object
889 * SubjectSecurityContext = Subject's captured security context
890 * SubjectContextLocked = Indicates the user's subject context is locked
891 * DesiredAccess = Access rights the caller is trying to acquire
892 * PreviouslyGrantedAccess = Specified the access rights already granted
893 * Privileges = ?
894 * GenericMapping = Generic mapping associated with the object
895 * AccessMode = Access mode used for the check
896 * GrantedAccess (OUT) = On return specifies the access granted
897 * AccessStatus (OUT) = Status indicating why access was denied
898 * RETURNS: If access was granted, returns TRUE
899 *
900 * @implemented
901 */
902 BOOLEAN STDCALL
903 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
904 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
905 IN BOOLEAN SubjectContextLocked,
906 IN ACCESS_MASK DesiredAccess,
907 IN ACCESS_MASK PreviouslyGrantedAccess,
908 OUT PPRIVILEGE_SET* Privileges,
909 IN PGENERIC_MAPPING GenericMapping,
910 IN KPROCESSOR_MODE AccessMode,
911 OUT PACCESS_MASK GrantedAccess,
912 OUT PNTSTATUS AccessStatus)
913 {
914 LUID_AND_ATTRIBUTES Privilege;
915 ACCESS_MASK CurrentAccess;
916 PACCESS_TOKEN Token;
917 ULONG i;
918 PACL Dacl;
919 BOOLEAN Present;
920 BOOLEAN Defaulted;
921 PACE CurrentAce;
922 PSID Sid;
923 NTSTATUS Status;
924
925 PAGED_CODE();
926
927 /* Check if we didn't get an SD */
928 if (!SecurityDescriptor)
929 {
930 /* Automatic failure */
931 *AccessStatus = STATUS_ACCESS_DENIED;
932 return FALSE;
933 }
934
935 CurrentAccess = PreviouslyGrantedAccess;
936
937 if (SubjectContextLocked == FALSE)
938 {
939 SeLockSubjectContext(SubjectSecurityContext);
940 }
941
942 Token = SubjectSecurityContext->ClientToken ?
943 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
944
945 /* Get the DACL */
946 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
947 &Present,
948 &Dacl,
949 &Defaulted);
950 if (!NT_SUCCESS(Status))
951 {
952 if (SubjectContextLocked == FALSE)
953 {
954 SeUnlockSubjectContext(SubjectSecurityContext);
955 }
956
957 *AccessStatus = Status;
958 return FALSE;
959 }
960
961 /* RULE 1: Grant desired access if the object is unprotected */
962 if (Present == TRUE && Dacl == NULL)
963 {
964 if (SubjectContextLocked == FALSE)
965 {
966 SeUnlockSubjectContext(SubjectSecurityContext);
967 }
968
969 *GrantedAccess = DesiredAccess;
970 *AccessStatus = STATUS_SUCCESS;
971 return TRUE;
972 }
973
974 CurrentAccess = PreviouslyGrantedAccess;
975
976 /* RULE 2: Check token for 'take ownership' privilege */
977 Privilege.Luid = SeTakeOwnershipPrivilege;
978 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
979
980 if (SepPrivilegeCheck(Token,
981 &Privilege,
982 1,
983 PRIVILEGE_SET_ALL_NECESSARY,
984 AccessMode))
985 {
986 CurrentAccess |= WRITE_OWNER;
987 if (DesiredAccess == CurrentAccess)
988 {
989 if (SubjectContextLocked == FALSE)
990 {
991 SeUnlockSubjectContext(SubjectSecurityContext);
992 }
993
994 *GrantedAccess = CurrentAccess;
995 *AccessStatus = STATUS_SUCCESS;
996 return TRUE;
997 }
998 }
999
1000 /* RULE 3: Check whether the token is the owner */
1001 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
1002 &Sid,
1003 &Defaulted);
1004 if (!NT_SUCCESS(Status))
1005 {
1006 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
1007 if (SubjectContextLocked == FALSE)
1008 {
1009 SeUnlockSubjectContext(SubjectSecurityContext);
1010 }
1011
1012 *AccessStatus = Status;
1013 return FALSE;
1014 }
1015
1016 if (Sid && SepSidInToken(Token, Sid))
1017 {
1018 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
1019 if (DesiredAccess == CurrentAccess)
1020 {
1021 if (SubjectContextLocked == FALSE)
1022 {
1023 SeUnlockSubjectContext(SubjectSecurityContext);
1024 }
1025
1026 *GrantedAccess = CurrentAccess;
1027 *AccessStatus = STATUS_SUCCESS;
1028 return TRUE;
1029 }
1030 }
1031
1032 /* Fail if DACL is absent */
1033 if (Present == FALSE)
1034 {
1035 if (SubjectContextLocked == FALSE)
1036 {
1037 SeUnlockSubjectContext(SubjectSecurityContext);
1038 }
1039
1040 *GrantedAccess = 0;
1041 *AccessStatus = STATUS_ACCESS_DENIED;
1042 return FALSE;
1043 }
1044
1045 /* RULE 4: Grant rights according to the DACL */
1046 CurrentAce = (PACE)(Dacl + 1);
1047 for (i = 0; i < Dacl->AceCount; i++)
1048 {
1049 Sid = (PSID)(CurrentAce + 1);
1050 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
1051 {
1052 if (SepSidInToken(Token, Sid))
1053 {
1054 if (SubjectContextLocked == FALSE)
1055 {
1056 SeUnlockSubjectContext(SubjectSecurityContext);
1057 }
1058
1059 *GrantedAccess = 0;
1060 *AccessStatus = STATUS_ACCESS_DENIED;
1061 return FALSE;
1062 }
1063 }
1064
1065 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
1066 {
1067 if (SepSidInToken(Token, Sid))
1068 {
1069 CurrentAccess |= CurrentAce->AccessMask;
1070 }
1071 }
1072 else
1073 DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType);
1074 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
1075 }
1076
1077 if (SubjectContextLocked == FALSE)
1078 {
1079 SeUnlockSubjectContext(SubjectSecurityContext);
1080 }
1081
1082 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1083 CurrentAccess, DesiredAccess);
1084
1085 *GrantedAccess = CurrentAccess & DesiredAccess;
1086
1087 if (*GrantedAccess == DesiredAccess)
1088 {
1089 *AccessStatus = STATUS_SUCCESS;
1090 return TRUE;
1091 }
1092 else
1093 {
1094 *AccessStatus = STATUS_SUCCESS;
1095 DPRINT("FIX caller rights (granted 0x%lx, desired 0x%lx)!\n",
1096 *GrantedAccess, DesiredAccess);
1097 return TRUE; /* FIXME: should be FALSE */
1098 }
1099 }
1100
1101
1102 NTSTATUS STDCALL
1103 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1104 IN HANDLE TokenHandle,
1105 IN ACCESS_MASK DesiredAccess,
1106 IN PGENERIC_MAPPING GenericMapping,
1107 OUT PPRIVILEGE_SET PrivilegeSet,
1108 OUT PULONG ReturnLength,
1109 OUT PACCESS_MASK GrantedAccess,
1110 OUT PNTSTATUS AccessStatus)
1111 {
1112 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext = {0};
1113 KPROCESSOR_MODE PreviousMode;
1114 PTOKEN Token;
1115 NTSTATUS Status;
1116
1117 PAGED_CODE();
1118
1119 DPRINT("NtAccessCheck() called\n");
1120
1121 PreviousMode = KeGetPreviousMode();
1122 if (PreviousMode == KernelMode)
1123 {
1124 *GrantedAccess = DesiredAccess;
1125 *AccessStatus = STATUS_SUCCESS;
1126 return STATUS_SUCCESS;
1127 }
1128
1129 Status = ObReferenceObjectByHandle(TokenHandle,
1130 TOKEN_QUERY,
1131 SepTokenObjectType,
1132 PreviousMode,
1133 (PVOID*)&Token,
1134 NULL);
1135 if (!NT_SUCCESS(Status))
1136 {
1137 DPRINT1("Failed to reference token (Status %lx)\n", Status);
1138 return Status;
1139 }
1140
1141 /* Check token type */
1142 if (Token->TokenType != TokenImpersonation)
1143 {
1144 DPRINT1("No impersonation token\n");
1145 ObDereferenceObject(Token);
1146 return STATUS_ACCESS_VIOLATION;
1147 }
1148
1149 /* Check impersonation level */
1150 if (Token->ImpersonationLevel < SecurityAnonymous)
1151 {
1152 DPRINT1("Invalid impersonation level\n");
1153 ObDereferenceObject(Token);
1154 return STATUS_ACCESS_VIOLATION;
1155 }
1156
1157 SubjectSecurityContext.ClientToken = Token;
1158 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
1159
1160 /* Lock subject context */
1161 SeLockSubjectContext(&SubjectSecurityContext);
1162
1163 if (SeAccessCheck(SecurityDescriptor,
1164 &SubjectSecurityContext,
1165 TRUE,
1166 DesiredAccess,
1167 0,
1168 &PrivilegeSet,
1169 GenericMapping,
1170 PreviousMode,
1171 GrantedAccess,
1172 AccessStatus))
1173 {
1174 Status = *AccessStatus;
1175 }
1176 else
1177 {
1178 Status = STATUS_ACCESS_DENIED;
1179 }
1180
1181 /* Unlock subject context */
1182 SeUnlockSubjectContext(&SubjectSecurityContext);
1183
1184 ObDereferenceObject(Token);
1185
1186 DPRINT("NtAccessCheck() done\n");
1187
1188 return Status;
1189 }
1190
1191 NTSTATUS
1192 NTAPI
1193 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1194 IN PSID PrincipalSelfSid,
1195 IN HANDLE ClientToken,
1196 IN ACCESS_MASK DesiredAccess,
1197 IN POBJECT_TYPE_LIST ObjectTypeList,
1198 IN ULONG ObjectTypeLength,
1199 IN PGENERIC_MAPPING GenericMapping,
1200 IN PPRIVILEGE_SET PrivilegeSet,
1201 IN ULONG PrivilegeSetLength,
1202 OUT PACCESS_MASK GrantedAccess,
1203 OUT PNTSTATUS AccessStatus)
1204 {
1205 UNIMPLEMENTED;
1206 return STATUS_NOT_IMPLEMENTED;
1207 }
1208
1209 NTSTATUS
1210 NTAPI
1211 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
1212 IN HANDLE HandleId,
1213 IN PUNICODE_STRING ObjectTypeName,
1214 IN PUNICODE_STRING ObjectName,
1215 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1216 IN PSID PrincipalSelfSid,
1217 IN ACCESS_MASK DesiredAccess,
1218 IN AUDIT_EVENT_TYPE AuditType,
1219 IN ULONG Flags,
1220 IN POBJECT_TYPE_LIST ObjectTypeList,
1221 IN ULONG ObjectTypeLength,
1222 IN PGENERIC_MAPPING GenericMapping,
1223 IN BOOLEAN ObjectCreation,
1224 OUT PACCESS_MASK GrantedAccess,
1225 OUT PNTSTATUS AccessStatus,
1226 OUT PBOOLEAN GenerateOnClose)
1227 {
1228 UNIMPLEMENTED;
1229 return STATUS_NOT_IMPLEMENTED;
1230 }
1231
1232 NTSTATUS
1233 NTAPI
1234 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1235 IN PSID PrincipalSelfSid,
1236 IN HANDLE ClientToken,
1237 IN ACCESS_MASK DesiredAccess,
1238 IN POBJECT_TYPE_LIST ObjectTypeList,
1239 IN ULONG ObjectTypeLength,
1240 IN PGENERIC_MAPPING GenericMapping,
1241 IN PPRIVILEGE_SET PrivilegeSet,
1242 IN ULONG PrivilegeSetLength,
1243 OUT PACCESS_MASK GrantedAccess,
1244 OUT PNTSTATUS AccessStatus)
1245 {
1246 UNIMPLEMENTED;
1247 return STATUS_NOT_IMPLEMENTED;
1248 }
1249
1250 NTSTATUS
1251 NTAPI
1252 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
1253 IN HANDLE HandleId,
1254 IN PUNICODE_STRING ObjectTypeName,
1255 IN PUNICODE_STRING ObjectName,
1256 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1257 IN PSID PrincipalSelfSid,
1258 IN ACCESS_MASK DesiredAccess,
1259 IN AUDIT_EVENT_TYPE AuditType,
1260 IN ULONG Flags,
1261 IN POBJECT_TYPE_LIST ObjectTypeList,
1262 IN ULONG ObjectTypeLength,
1263 IN PGENERIC_MAPPING GenericMapping,
1264 IN BOOLEAN ObjectCreation,
1265 OUT PACCESS_MASK GrantedAccess,
1266 OUT PNTSTATUS AccessStatus,
1267 OUT PBOOLEAN GenerateOnClose)
1268 {
1269 UNIMPLEMENTED;
1270 return STATUS_NOT_IMPLEMENTED;
1271 }
1272
1273 NTSTATUS
1274 NTAPI
1275 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
1276 IN HANDLE HandleId,
1277 IN HANDLE ClientToken,
1278 IN PUNICODE_STRING ObjectTypeName,
1279 IN PUNICODE_STRING ObjectName,
1280 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1281 IN PSID PrincipalSelfSid,
1282 IN ACCESS_MASK DesiredAccess,
1283 IN AUDIT_EVENT_TYPE AuditType,
1284 IN ULONG Flags,
1285 IN POBJECT_TYPE_LIST ObjectTypeList,
1286 IN ULONG ObjectTypeLength,
1287 IN PGENERIC_MAPPING GenericMapping,
1288 IN BOOLEAN ObjectCreation,
1289 OUT PACCESS_MASK GrantedAccess,
1290 OUT PNTSTATUS AccessStatus,
1291 OUT PBOOLEAN GenerateOnClose)
1292 {
1293 UNIMPLEMENTED;
1294 return STATUS_NOT_IMPLEMENTED;
1295 }
1296
1297 VOID STDCALL
1298 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
1299 OUT PACCESS_MASK DesiredAccess)
1300 {
1301 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
1302 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
1303 {
1304 *DesiredAccess |= READ_CONTROL;
1305 }
1306 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1307 {
1308 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
1309 }
1310 }
1311
1312 VOID STDCALL
1313 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
1314 OUT PACCESS_MASK DesiredAccess)
1315 {
1316 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
1317 {
1318 *DesiredAccess |= WRITE_OWNER;
1319 }
1320 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1321 {
1322 *DesiredAccess |= WRITE_DAC;
1323 }
1324 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1325 {
1326 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
1327 }
1328 }
1329
1330 /* EOF */