[NTOSKRNL] Place INIT_FUNCTION before the return type (#2823)
[reactos.git] / ntoskrnl / se / sd.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/sd.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitSDs)
18 #endif
19
20 /* GLOBALS ********************************************************************/
21
22 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
23 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
24 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
25 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
26 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
27 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
28
29 /* PRIVATE FUNCTIONS **********************************************************/
30
31 INIT_FUNCTION
32 BOOLEAN
33 NTAPI
34 SepInitSDs(VOID)
35 {
36 /* Create PublicDefaultSd */
37 SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool,
38 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
39 if (SePublicDefaultSd == NULL)
40 return FALSE;
41
42 RtlCreateSecurityDescriptor(SePublicDefaultSd,
43 SECURITY_DESCRIPTOR_REVISION);
44 RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
45 TRUE,
46 SePublicDefaultDacl,
47 FALSE);
48
49 /* Create PublicDefaultUnrestrictedSd */
50 SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
51 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
52 if (SePublicDefaultUnrestrictedSd == NULL)
53 return FALSE;
54
55 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
56 SECURITY_DESCRIPTOR_REVISION);
57 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
58 TRUE,
59 SePublicDefaultUnrestrictedDacl,
60 FALSE);
61
62 /* Create PublicOpenSd */
63 SePublicOpenSd = ExAllocatePoolWithTag(PagedPool,
64 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
65 if (SePublicOpenSd == NULL)
66 return FALSE;
67
68 RtlCreateSecurityDescriptor(SePublicOpenSd,
69 SECURITY_DESCRIPTOR_REVISION);
70 RtlSetDaclSecurityDescriptor(SePublicOpenSd,
71 TRUE,
72 SePublicOpenDacl,
73 FALSE);
74
75 /* Create PublicOpenUnrestrictedSd */
76 SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
77 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
78 if (SePublicOpenUnrestrictedSd == NULL)
79 return FALSE;
80
81 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
82 SECURITY_DESCRIPTOR_REVISION);
83 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
84 TRUE,
85 SePublicOpenUnrestrictedDacl,
86 FALSE);
87
88 /* Create SystemDefaultSd */
89 SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool,
90 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
91 if (SeSystemDefaultSd == NULL)
92 return FALSE;
93
94 RtlCreateSecurityDescriptor(SeSystemDefaultSd,
95 SECURITY_DESCRIPTOR_REVISION);
96 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
97 TRUE,
98 SeSystemDefaultDacl,
99 FALSE);
100
101 /* Create UnrestrictedSd */
102 SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
103 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
104 if (SeUnrestrictedSd == NULL)
105 return FALSE;
106
107 RtlCreateSecurityDescriptor(SeUnrestrictedSd,
108 SECURITY_DESCRIPTOR_REVISION);
109 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
110 TRUE,
111 SeUnrestrictedDacl,
112 FALSE);
113
114 return TRUE;
115 }
116
117 NTSTATUS
118 NTAPI
119 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
120 PISECURITY_DESCRIPTOR SecurityDescriptor,
121 PULONG BufferLength)
122 {
123 ULONG Current;
124 ULONG SidSize;
125 ULONG SdSize;
126 NTSTATUS Status;
127 PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
128
129 DPRINT("SeSetWorldSecurityDescriptor() called\n");
130
131 if (SecurityInformation == 0)
132 {
133 return STATUS_ACCESS_DENIED;
134 }
135
136 /* calculate the minimum size of the buffer */
137 SidSize = RtlLengthSid(SeWorldSid);
138 SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
139 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
140 SdSize += SidSize;
141 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
142 SdSize += SidSize;
143 if (SecurityInformation & DACL_SECURITY_INFORMATION)
144 {
145 SdSize += sizeof(ACL) + sizeof(ACE) + SidSize;
146 }
147
148 if (*BufferLength < SdSize)
149 {
150 *BufferLength = SdSize;
151 return STATUS_BUFFER_TOO_SMALL;
152 }
153
154 *BufferLength = SdSize;
155
156 Status = RtlCreateSecurityDescriptorRelative(SdRel,
157 SECURITY_DESCRIPTOR_REVISION);
158 if (!NT_SUCCESS(Status))
159 {
160 return Status;
161 }
162
163 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
164
165 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
166 {
167 RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
168 SdRel->Owner = Current;
169 Current += SidSize;
170 }
171
172 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
173 {
174 RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
175 SdRel->Group = Current;
176 Current += SidSize;
177 }
178
179 if (SecurityInformation & DACL_SECURITY_INFORMATION)
180 {
181 PACL Dacl = (PACL)((PUCHAR)SdRel + Current);
182 SdRel->Control |= SE_DACL_PRESENT;
183
184 Status = RtlCreateAcl(Dacl,
185 sizeof(ACL) + sizeof(ACE) + SidSize,
186 ACL_REVISION);
187 if (!NT_SUCCESS(Status))
188 return Status;
189
190 Status = RtlAddAccessAllowedAce(Dacl,
191 ACL_REVISION,
192 GENERIC_ALL,
193 SeWorldSid);
194 if (!NT_SUCCESS(Status))
195 return Status;
196
197 SdRel->Dacl = Current;
198 }
199
200 if (SecurityInformation & SACL_SECURITY_INFORMATION)
201 {
202 /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */
203 }
204
205 return STATUS_SUCCESS;
206 }
207
208
209 NTSTATUS
210 NTAPI
211 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
212 IN KPROCESSOR_MODE AccessMode,
213 IN POOL_TYPE PoolType,
214 IN BOOLEAN CaptureIfKernel,
215 OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService,
216 OUT PBOOLEAN Present)
217 {
218 PSECURITY_QUALITY_OF_SERVICE CapturedQos;
219 NTSTATUS Status = STATUS_SUCCESS;
220
221 PAGED_CODE();
222
223 ASSERT(CapturedSecurityQualityOfService);
224 ASSERT(Present);
225
226 if (ObjectAttributes != NULL)
227 {
228 if (AccessMode != KernelMode)
229 {
230 SECURITY_QUALITY_OF_SERVICE SafeQos;
231
232 _SEH2_TRY
233 {
234 ProbeForRead(ObjectAttributes,
235 sizeof(OBJECT_ATTRIBUTES),
236 sizeof(ULONG));
237 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
238 {
239 if (ObjectAttributes->SecurityQualityOfService != NULL)
240 {
241 ProbeForRead(ObjectAttributes->SecurityQualityOfService,
242 sizeof(SECURITY_QUALITY_OF_SERVICE),
243 sizeof(ULONG));
244
245 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
246 sizeof(SECURITY_QUALITY_OF_SERVICE))
247 {
248 /*
249 * Don't allocate memory here because ExAllocate should bugcheck
250 * the system if it's buggy, SEH would catch that! So make a local
251 * copy of the qos structure.
252 */
253 RtlCopyMemory(&SafeQos,
254 ObjectAttributes->SecurityQualityOfService,
255 sizeof(SECURITY_QUALITY_OF_SERVICE));
256 *Present = TRUE;
257 }
258 else
259 {
260 Status = STATUS_INVALID_PARAMETER;
261 }
262 }
263 else
264 {
265 *CapturedSecurityQualityOfService = NULL;
266 *Present = FALSE;
267 }
268 }
269 else
270 {
271 Status = STATUS_INVALID_PARAMETER;
272 }
273 }
274 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
275 {
276 Status = _SEH2_GetExceptionCode();
277 }
278 _SEH2_END;
279
280 if (NT_SUCCESS(Status))
281 {
282 if (*Present)
283 {
284 CapturedQos = ExAllocatePoolWithTag(PoolType,
285 sizeof(SECURITY_QUALITY_OF_SERVICE),
286 TAG_QOS);
287 if (CapturedQos != NULL)
288 {
289 RtlCopyMemory(CapturedQos,
290 &SafeQos,
291 sizeof(SECURITY_QUALITY_OF_SERVICE));
292 *CapturedSecurityQualityOfService = CapturedQos;
293 }
294 else
295 {
296 Status = STATUS_INSUFFICIENT_RESOURCES;
297 }
298 }
299 else
300 {
301 *CapturedSecurityQualityOfService = NULL;
302 }
303 }
304 }
305 else
306 {
307 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
308 {
309 if (CaptureIfKernel)
310 {
311 if (ObjectAttributes->SecurityQualityOfService != NULL)
312 {
313 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
314 sizeof(SECURITY_QUALITY_OF_SERVICE))
315 {
316 CapturedQos = ExAllocatePoolWithTag(PoolType,
317 sizeof(SECURITY_QUALITY_OF_SERVICE),
318 TAG_QOS);
319 if (CapturedQos != NULL)
320 {
321 RtlCopyMemory(CapturedQos,
322 ObjectAttributes->SecurityQualityOfService,
323 sizeof(SECURITY_QUALITY_OF_SERVICE));
324 *CapturedSecurityQualityOfService = CapturedQos;
325 *Present = TRUE;
326 }
327 else
328 {
329 Status = STATUS_INSUFFICIENT_RESOURCES;
330 }
331 }
332 else
333 {
334 Status = STATUS_INVALID_PARAMETER;
335 }
336 }
337 else
338 {
339 *CapturedSecurityQualityOfService = NULL;
340 *Present = FALSE;
341 }
342 }
343 else
344 {
345 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
346 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
347 }
348 }
349 else
350 {
351 Status = STATUS_INVALID_PARAMETER;
352 }
353 }
354 }
355 else
356 {
357 *CapturedSecurityQualityOfService = NULL;
358 *Present = FALSE;
359 }
360
361 return Status;
362 }
363
364
365 VOID
366 NTAPI
367 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL,
368 IN KPROCESSOR_MODE AccessMode,
369 IN BOOLEAN CaptureIfKernel)
370 {
371 PAGED_CODE();
372
373 if (CapturedSecurityQualityOfService != NULL &&
374 (AccessMode != KernelMode || CaptureIfKernel))
375 {
376 ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS);
377 }
378 }
379
380 /* PUBLIC FUNCTIONS ***********************************************************/
381
382 static
383 ULONG
384 DetermineSIDSize(
385 PISID Sid,
386 PULONG OutSAC,
387 KPROCESSOR_MODE ProcessorMode)
388 {
389 ULONG Size;
390
391 if (!Sid)
392 {
393 *OutSAC = 0;
394 return 0;
395 }
396
397 if (ProcessorMode != KernelMode)
398 {
399 /* Securely access the buffers! */
400 *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount);
401 Size = RtlLengthRequiredSid(*OutSAC);
402 ProbeForRead(Sid, Size, sizeof(ULONG));
403 }
404 else
405 {
406 *OutSAC = Sid->SubAuthorityCount;
407 Size = RtlLengthRequiredSid(*OutSAC);
408 }
409
410 return Size;
411 }
412
413 static
414 ULONG
415 DetermineACLSize(
416 PACL Acl,
417 KPROCESSOR_MODE ProcessorMode)
418 {
419 ULONG Size;
420
421 if (!Acl) return 0;
422
423 if (ProcessorMode == KernelMode) return Acl->AclSize;
424
425 /* Probe the buffers! */
426 Size = ProbeForReadUshort(&Acl->AclSize);
427 ProbeForRead(Acl, Size, sizeof(ULONG));
428
429 return Size;
430 }
431
432 NTSTATUS
433 NTAPI
434 SeCaptureSecurityDescriptor(
435 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
436 IN KPROCESSOR_MODE CurrentMode,
437 IN POOL_TYPE PoolType,
438 IN BOOLEAN CaptureIfKernel,
439 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
440 {
441 PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor;
442 SECURITY_DESCRIPTOR DescriptorCopy;
443 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor;
444 ULONG OwnerSAC = 0, GroupSAC = 0;
445 ULONG OwnerSize = 0, GroupSize = 0;
446 ULONG SaclSize = 0, DaclSize = 0;
447 ULONG DescriptorSize = 0;
448 ULONG Offset;
449
450 if (!OriginalDescriptor)
451 {
452 /* Nothing to do... */
453 *CapturedSecurityDescriptor = NULL;
454 return STATUS_SUCCESS;
455 }
456
457 /* Quick path */
458 if (CurrentMode == KernelMode && !CaptureIfKernel)
459 {
460 /* Check descriptor version */
461 if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
462 {
463 return STATUS_UNKNOWN_REVISION;
464 }
465
466 *CapturedSecurityDescriptor = _OriginalSecurityDescriptor;
467 return STATUS_SUCCESS;
468 }
469
470 _SEH2_TRY
471 {
472 if (CurrentMode != KernelMode)
473 {
474 ProbeForRead(OriginalDescriptor,
475 sizeof(SECURITY_DESCRIPTOR_RELATIVE),
476 sizeof(ULONG));
477 }
478
479 /* Check the descriptor version */
480 if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
481 {
482 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
483 }
484
485 if (CurrentMode != KernelMode)
486 {
487 /* Get the size of the descriptor */
488 DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ?
489 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR);
490
491 /* Probe the entire security descriptor structure. The SIDs
492 * and ACLs will be probed and copied later though */
493 ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG));
494 }
495
496 /* Now capture all fields and convert to an absolute descriptor */
497 DescriptorCopy.Revision = OriginalDescriptor->Revision;
498 DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1;
499 DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE;
500 DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor);
501 DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor);
502 DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor);
503 DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor);
504 DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
505
506 /* Determine owner and group sizes */
507 OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode);
508 DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG));
509 GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode);
510 DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG));
511
512 /* Determine the size of the ACLs */
513 if (DescriptorCopy.Control & SE_SACL_PRESENT)
514 {
515 /* Get the size and probe if user mode */
516 SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode);
517 DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG));
518 }
519
520 if (DescriptorCopy.Control & SE_DACL_PRESENT)
521 {
522 /* Get the size and probe if user mode */
523 DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode);
524 DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG));
525 }
526 }
527 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
528 {
529 _SEH2_YIELD(return _SEH2_GetExceptionCode());
530 }
531 _SEH2_END;
532
533 /*
534 * Allocate enough memory to store a complete copy of a self-relative
535 * security descriptor
536 */
537 NewDescriptor = ExAllocatePoolWithTag(PoolType,
538 DescriptorSize,
539 TAG_SD);
540 if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
541
542 RtlZeroMemory(NewDescriptor, DescriptorSize);
543 NewDescriptor->Revision = DescriptorCopy.Revision;
544 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
545 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
546
547 _SEH2_TRY
548 {
549 /*
550 * Setup the offsets and copy the SIDs and ACLs to the new
551 * self-relative security descriptor. Probing the pointers is not
552 * neccessary anymore as we did that when collecting the sizes!
553 * Make sure to validate the SIDs and ACLs *again* as they could have
554 * been modified in the meanwhile!
555 */
556 Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
557
558 if (DescriptorCopy.Owner)
559 {
560 if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID);
561 NewDescriptor->Owner = Offset;
562 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
563 DescriptorCopy.Owner,
564 OwnerSize);
565 Offset += ROUND_UP(OwnerSize, sizeof(ULONG));
566 }
567
568 if (DescriptorCopy.Group)
569 {
570 if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID);
571 NewDescriptor->Group = Offset;
572 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
573 DescriptorCopy.Group,
574 GroupSize);
575 Offset += ROUND_UP(GroupSize, sizeof(ULONG));
576 }
577
578 if (DescriptorCopy.Sacl)
579 {
580 if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
581 NewDescriptor->Sacl = Offset;
582 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
583 DescriptorCopy.Sacl,
584 SaclSize);
585 Offset += ROUND_UP(SaclSize, sizeof(ULONG));
586 }
587
588 if (DescriptorCopy.Dacl)
589 {
590 if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
591 NewDescriptor->Dacl = Offset;
592 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
593 DescriptorCopy.Dacl,
594 DaclSize);
595 Offset += ROUND_UP(DaclSize, sizeof(ULONG));
596 }
597
598 /* Make sure the size was correct */
599 ASSERT(Offset == DescriptorSize);
600 }
601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
602 {
603 /* We failed to copy the data to the new descriptor */
604 ExFreePoolWithTag(NewDescriptor, TAG_SD);
605 _SEH2_YIELD(return _SEH2_GetExceptionCode());
606 }
607 _SEH2_END;
608
609 /*
610 * We're finally done!
611 * Copy the pointer to the captured descriptor to to the caller.
612 */
613 *CapturedSecurityDescriptor = NewDescriptor;
614 return STATUS_SUCCESS;
615 }
616
617 /*
618 * @implemented
619 */
620 _IRQL_requires_max_(PASSIVE_LEVEL)
621 NTSTATUS
622 NTAPI
623 SeQuerySecurityDescriptorInfo(
624 _In_ PSECURITY_INFORMATION SecurityInformation,
625 _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor,
626 _Inout_ PULONG Length,
627 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
628 {
629 PISECURITY_DESCRIPTOR ObjectSd;
630 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
631 PSID Owner = NULL;
632 PSID Group = NULL;
633 PACL Dacl = NULL;
634 PACL Sacl = NULL;
635 ULONG OwnerLength = 0;
636 ULONG GroupLength = 0;
637 ULONG DaclLength = 0;
638 ULONG SaclLength = 0;
639 SECURITY_DESCRIPTOR_CONTROL Control = 0;
640 ULONG_PTR Current;
641 ULONG SdLength;
642
643 PAGED_CODE();
644
645 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
646
647 if (*ObjectsSecurityDescriptor == NULL)
648 {
649 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
650 {
651 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
652 return STATUS_BUFFER_TOO_SMALL;
653 }
654
655 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
656 RtlCreateSecurityDescriptorRelative(RelSD,
657 SECURITY_DESCRIPTOR_REVISION);
658 return STATUS_SUCCESS;
659 }
660
661 ObjectSd = *ObjectsSecurityDescriptor;
662
663 /* Calculate the required security descriptor length */
664 Control = SE_SELF_RELATIVE;
665 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
666 (ObjectSd->Owner != NULL))
667 {
668 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
669 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
670 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
671 }
672
673 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
674 (ObjectSd->Group != NULL))
675 {
676 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
677 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
678 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
679 }
680
681 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
682 (ObjectSd->Control & SE_DACL_PRESENT))
683 {
684 if (ObjectSd->Dacl != NULL)
685 {
686 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
687 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
688 }
689
690 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
691 }
692
693 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
694 (ObjectSd->Control & SE_SACL_PRESENT))
695 {
696 if (ObjectSd->Sacl != NULL)
697 {
698 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
699 SaclLength = ROUND_UP(Sacl->AclSize, 4);
700 }
701
702 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
703 }
704
705 SdLength = OwnerLength + GroupLength + DaclLength +
706 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
707 if (*Length < SdLength)
708 {
709 *Length = SdLength;
710 return STATUS_BUFFER_TOO_SMALL;
711 }
712
713 /* Build the new security descrtiptor */
714 RtlCreateSecurityDescriptorRelative(RelSD,
715 SECURITY_DESCRIPTOR_REVISION);
716 RelSD->Control = Control;
717
718 Current = (ULONG_PTR)(RelSD + 1);
719
720 if (OwnerLength != 0)
721 {
722 RtlCopyMemory((PVOID)Current,
723 Owner,
724 OwnerLength);
725 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
726 Current += OwnerLength;
727 }
728
729 if (GroupLength != 0)
730 {
731 RtlCopyMemory((PVOID)Current,
732 Group,
733 GroupLength);
734 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
735 Current += GroupLength;
736 }
737
738 if (DaclLength != 0)
739 {
740 RtlCopyMemory((PVOID)Current,
741 Dacl,
742 DaclLength);
743 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
744 Current += DaclLength;
745 }
746
747 if (SaclLength != 0)
748 {
749 RtlCopyMemory((PVOID)Current,
750 Sacl,
751 SaclLength);
752 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
753 Current += SaclLength;
754 }
755
756 *Length = SdLength;
757
758 return STATUS_SUCCESS;
759 }
760
761 /*
762 * @implemented
763 */
764 NTSTATUS
765 NTAPI
766 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
767 IN KPROCESSOR_MODE CurrentMode,
768 IN BOOLEAN CaptureIfKernelMode)
769 {
770 PAGED_CODE();
771
772 /*
773 * WARNING! You need to call this function with the same value for CurrentMode
774 * and CaptureIfKernelMode that you previously passed to
775 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
776 */
777 if (CapturedSecurityDescriptor != NULL &&
778 (CurrentMode != KernelMode ||
779 (CurrentMode == KernelMode && CaptureIfKernelMode)))
780 {
781 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
782 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
783 }
784
785 return STATUS_SUCCESS;
786 }
787
788 /*
789 * @implemented
790 */
791 _IRQL_requires_max_(PASSIVE_LEVEL)
792 NTSTATUS
793 NTAPI
794 SeSetSecurityDescriptorInfo(
795 _In_opt_ PVOID Object,
796 _In_ PSECURITY_INFORMATION SecurityInformation,
797 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
798 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
799 _In_ POOL_TYPE PoolType,
800 _In_ PGENERIC_MAPPING GenericMapping)
801 {
802 PAGED_CODE();
803
804 return SeSetSecurityDescriptorInfoEx(Object,
805 SecurityInformation,
806 SecurityDescriptor,
807 ObjectsSecurityDescriptor,
808 0,
809 PoolType,
810 GenericMapping);
811 }
812
813 /*
814 * @implemented
815 */
816 _IRQL_requires_max_(PASSIVE_LEVEL)
817 NTSTATUS
818 NTAPI
819 SeSetSecurityDescriptorInfoEx(
820 _In_opt_ PVOID Object,
821 _In_ PSECURITY_INFORMATION _SecurityInformation,
822 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor,
823 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
824 _In_ ULONG AutoInheritFlags,
825 _In_ POOL_TYPE PoolType,
826 _In_ PGENERIC_MAPPING GenericMapping)
827 {
828 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd;
829 PISECURITY_DESCRIPTOR_RELATIVE NewSd;
830 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
831 PSID Owner;
832 PSID Group;
833 PACL Dacl;
834 PACL Sacl;
835 ULONG OwnerLength;
836 ULONG GroupLength;
837 ULONG DaclLength;
838 ULONG SaclLength;
839 SECURITY_DESCRIPTOR_CONTROL Control = 0;
840 ULONG Current;
841 SECURITY_INFORMATION SecurityInformation;
842
843 PAGED_CODE();
844
845 ObjectSd = *ObjectsSecurityDescriptor;
846
847 /* The object does not have a security descriptor. */
848 if (!ObjectSd)
849 return STATUS_NO_SECURITY_ON_OBJECT;
850
851 ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
852
853 SecurityInformation = *_SecurityInformation;
854
855 /* Get owner and owner size */
856 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
857 {
858 Owner = SepGetOwnerFromDescriptor(SecurityDescriptor);
859 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
860 }
861 else
862 {
863 Owner = SepGetOwnerFromDescriptor(ObjectSd);
864 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
865 }
866 OwnerLength = Owner ? RtlLengthSid(Owner) : 0;
867 ASSERT(OwnerLength % sizeof(ULONG) == 0);
868
869 /* Get group and group size */
870 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
871 {
872 Group = SepGetGroupFromDescriptor(SecurityDescriptor);
873 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
874 }
875 else
876 {
877 Group = SepGetGroupFromDescriptor(ObjectSd);
878 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
879 }
880 GroupLength = Group ? RtlLengthSid(Group) : 0;
881 ASSERT(GroupLength % sizeof(ULONG) == 0);
882
883 /* Get DACL and DACL size */
884 if (SecurityInformation & DACL_SECURITY_INFORMATION)
885 {
886 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
887 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
888 }
889 else
890 {
891 Dacl = SepGetDaclFromDescriptor(ObjectSd);
892 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
893 }
894 DaclLength = Dacl ? ROUND_UP((ULONG)Dacl->AclSize, 4) : 0;
895
896 /* Get SACL and SACL size */
897 if (SecurityInformation & SACL_SECURITY_INFORMATION)
898 {
899 Sacl = SepGetSaclFromDescriptor(SecurityDescriptor);
900 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
901 }
902 else
903 {
904 Sacl = SepGetSaclFromDescriptor(ObjectSd);
905 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
906 }
907 SaclLength = Sacl ? ROUND_UP((ULONG)Sacl->AclSize, 4) : 0;
908
909 NewSd = ExAllocatePoolWithTag(NonPagedPool,
910 sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
911 OwnerLength + GroupLength +
912 DaclLength + SaclLength,
913 TAG_SD);
914 if (NewSd == NULL)
915 {
916 return STATUS_INSUFFICIENT_RESOURCES;
917 }
918
919 RtlCreateSecurityDescriptorRelative(NewSd, SECURITY_DESCRIPTOR_REVISION1);
920
921 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
922
923 if (OwnerLength != 0)
924 {
925 RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
926 NewSd->Owner = Current;
927 Current += OwnerLength;
928 }
929
930 if (GroupLength != 0)
931 {
932 RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
933 NewSd->Group = Current;
934 Current += GroupLength;
935 }
936
937 if (DaclLength != 0)
938 {
939 RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
940 NewSd->Dacl = Current;
941 Current += DaclLength;
942 }
943
944 if (SaclLength != 0)
945 {
946 RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
947 NewSd->Sacl = Current;
948 Current += SaclLength;
949 }
950
951 *ObjectsSecurityDescriptor = NewSd;
952 return STATUS_SUCCESS;
953 }
954
955
956 /*
957 * @implemented
958 */
959 BOOLEAN NTAPI
960 SeValidSecurityDescriptor(IN ULONG Length,
961 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
962 {
963 ULONG SdLength;
964 PISID Sid;
965 PACL Acl;
966 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
967
968 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
969 {
970 DPRINT1("Invalid Security Descriptor revision\n");
971 return FALSE;
972 }
973
974 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
975 {
976 DPRINT1("Invalid Security Descriptor revision\n");
977 return FALSE;
978 }
979
980 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
981 {
982 DPRINT1("No self-relative Security Descriptor\n");
983 return FALSE;
984 }
985
986 SdLength = sizeof(SECURITY_DESCRIPTOR);
987
988 /* Check Owner SID */
989 if (!SecurityDescriptor->Owner)
990 {
991 DPRINT1("No Owner SID\n");
992 return FALSE;
993 }
994
995 if (SecurityDescriptor->Owner % sizeof(ULONG))
996 {
997 DPRINT1("Invalid Owner SID alignment\n");
998 return FALSE;
999 }
1000
1001 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
1002 if (Sid->Revision != SID_REVISION)
1003 {
1004 DPRINT1("Invalid Owner SID revision\n");
1005 return FALSE;
1006 }
1007
1008 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1009 if (Length < SdLength)
1010 {
1011 DPRINT1("Invalid Owner SID size\n");
1012 return FALSE;
1013 }
1014
1015 /* Check Group SID */
1016 if (SecurityDescriptor->Group)
1017 {
1018 if (SecurityDescriptor->Group % sizeof(ULONG))
1019 {
1020 DPRINT1("Invalid Group SID alignment\n");
1021 return FALSE;
1022 }
1023
1024 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
1025 if (Sid->Revision != SID_REVISION)
1026 {
1027 DPRINT1("Invalid Group SID revision\n");
1028 return FALSE;
1029 }
1030
1031 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1032 if (Length < SdLength)
1033 {
1034 DPRINT1("Invalid Group SID size\n");
1035 return FALSE;
1036 }
1037 }
1038
1039 /* Check DACL */
1040 if (SecurityDescriptor->Dacl)
1041 {
1042 if (SecurityDescriptor->Dacl % sizeof(ULONG))
1043 {
1044 DPRINT1("Invalid DACL alignment\n");
1045 return FALSE;
1046 }
1047
1048 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
1049 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1050 (Acl->AclRevision > MAX_ACL_REVISION))
1051 {
1052 DPRINT1("Invalid DACL revision\n");
1053 return FALSE;
1054 }
1055
1056 SdLength += Acl->AclSize;
1057 if (Length < SdLength)
1058 {
1059 DPRINT1("Invalid DACL size\n");
1060 return FALSE;
1061 }
1062 }
1063
1064 /* Check SACL */
1065 if (SecurityDescriptor->Sacl)
1066 {
1067 if (SecurityDescriptor->Sacl % sizeof(ULONG))
1068 {
1069 DPRINT1("Invalid SACL alignment\n");
1070 return FALSE;
1071 }
1072
1073 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
1074 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1075 (Acl->AclRevision > MAX_ACL_REVISION))
1076 {
1077 DPRINT1("Invalid SACL revision\n");
1078 return FALSE;
1079 }
1080
1081 SdLength += Acl->AclSize;
1082 if (Length < SdLength)
1083 {
1084 DPRINT1("Invalid SACL size\n");
1085 return FALSE;
1086 }
1087 }
1088
1089 return TRUE;
1090 }
1091
1092 /*
1093 * @implemented
1094 */
1095 _IRQL_requires_max_(PASSIVE_LEVEL)
1096 NTSTATUS
1097 NTAPI
1098 SeDeassignSecurity(
1099 _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor)
1100 {
1101 PAGED_CODE();
1102
1103 if (*SecurityDescriptor != NULL)
1104 {
1105 ExFreePoolWithTag(*SecurityDescriptor, TAG_SD);
1106 *SecurityDescriptor = NULL;
1107 }
1108
1109 return STATUS_SUCCESS;
1110 }
1111
1112 /*
1113 * @implemented
1114 */
1115 _IRQL_requires_max_(PASSIVE_LEVEL)
1116 NTSTATUS
1117 NTAPI
1118 SeAssignSecurityEx(
1119 _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor,
1120 _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor,
1121 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1122 _In_opt_ GUID *ObjectType,
1123 _In_ BOOLEAN IsDirectoryObject,
1124 _In_ ULONG AutoInheritFlags,
1125 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1126 _In_ PGENERIC_MAPPING GenericMapping,
1127 _In_ POOL_TYPE PoolType)
1128 {
1129 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1130 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1131 PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
1132 PTOKEN Token;
1133 ULONG OwnerLength;
1134 ULONG GroupLength;
1135 ULONG DaclLength;
1136 ULONG SaclLength;
1137 ULONG Length;
1138 SECURITY_DESCRIPTOR_CONTROL Control = 0;
1139 ULONG Current;
1140 PSID Owner = NULL;
1141 PSID Group = NULL;
1142 PACL ExplicitAcl;
1143 BOOLEAN ExplicitPresent;
1144 BOOLEAN ExplicitDefaulted;
1145 PACL ParentAcl;
1146 PACL Dacl = NULL;
1147 PACL Sacl = NULL;
1148 BOOLEAN DaclIsInherited;
1149 BOOLEAN SaclIsInherited;
1150 BOOLEAN DaclPresent;
1151 BOOLEAN SaclPresent;
1152 NTSTATUS Status;
1153
1154 DBG_UNREFERENCED_PARAMETER(ObjectType);
1155 DBG_UNREFERENCED_PARAMETER(AutoInheritFlags);
1156 UNREFERENCED_PARAMETER(PoolType);
1157
1158 PAGED_CODE();
1159
1160 *NewDescriptor = NULL;
1161
1162 if (!ARGUMENT_PRESENT(SubjectContext))
1163 {
1164 return STATUS_NO_TOKEN;
1165 }
1166
1167 /* Lock subject context */
1168 SeLockSubjectContext(SubjectContext);
1169
1170 if (SubjectContext->ClientToken != NULL)
1171 {
1172 Token = SubjectContext->ClientToken;
1173 }
1174 else
1175 {
1176 Token = SubjectContext->PrimaryToken;
1177 }
1178
1179 /* Inherit the Owner SID */
1180 if (ExplicitDescriptor != NULL)
1181 {
1182 DPRINT("Use explicit owner sid!\n");
1183 Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
1184 }
1185 if (!Owner)
1186 {
1187 if (AutoInheritFlags & 0x20 /* FIXME: SEF_DEFAULT_OWNER_FROM_PARENT */)
1188 {
1189 DPRINT("Use parent owner sid!\n");
1190 if (!ARGUMENT_PRESENT(ParentDescriptor))
1191 {
1192 SeUnlockSubjectContext(SubjectContext);
1193 return STATUS_INVALID_OWNER;
1194 }
1195
1196 Owner = SepGetOwnerFromDescriptor(ParentDescriptor);
1197 if (!Owner)
1198 {
1199 SeUnlockSubjectContext(SubjectContext);
1200 return STATUS_INVALID_OWNER;
1201 }
1202 }
1203 else
1204 {
1205 DPRINT("Use token owner sid!\n");
1206 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1207 }
1208 }
1209 OwnerLength = RtlLengthSid(Owner);
1210 ASSERT(OwnerLength % sizeof(ULONG) == 0);
1211
1212 /* Inherit the Group SID */
1213 if (ExplicitDescriptor != NULL)
1214 {
1215 Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1216 }
1217 if (!Group)
1218 {
1219 if (AutoInheritFlags & 0x40 /* FIXME: SEF_DEFAULT_GROUP_FROM_PARENT */)
1220 {
1221 DPRINT("Use parent group sid!\n");
1222 if (!ARGUMENT_PRESENT(ParentDescriptor))
1223 {
1224 SeUnlockSubjectContext(SubjectContext);
1225 return STATUS_INVALID_PRIMARY_GROUP;
1226 }
1227
1228 Group = SepGetGroupFromDescriptor(ParentDescriptor);
1229 if (!Group)
1230 {
1231 SeUnlockSubjectContext(SubjectContext);
1232 return STATUS_INVALID_PRIMARY_GROUP;
1233 }
1234 }
1235 else
1236 {
1237 DPRINT("Use token group sid!\n");
1238 Group = Token->PrimaryGroup;
1239 }
1240 }
1241 if (!Group)
1242 {
1243 SeUnlockSubjectContext(SubjectContext);
1244 return STATUS_INVALID_PRIMARY_GROUP;
1245 }
1246 GroupLength = RtlLengthSid(Group);
1247 ASSERT(GroupLength % sizeof(ULONG) == 0);
1248
1249 /* Inherit the DACL */
1250 DaclLength = 0;
1251 ExplicitAcl = NULL;
1252 ExplicitPresent = FALSE;
1253 ExplicitDefaulted = FALSE;
1254 if (ExplicitDescriptor != NULL &&
1255 (ExplicitDescriptor->Control & SE_DACL_PRESENT))
1256 {
1257 ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1258 ExplicitPresent = TRUE;
1259 if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED)
1260 ExplicitDefaulted = TRUE;
1261 }
1262 ParentAcl = NULL;
1263 if (ParentDescriptor != NULL &&
1264 (ParentDescriptor->Control & SE_DACL_PRESENT))
1265 {
1266 ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
1267 }
1268 Dacl = SepSelectAcl(ExplicitAcl,
1269 ExplicitPresent,
1270 ExplicitDefaulted,
1271 ParentAcl,
1272 Token->DefaultDacl,
1273 &DaclLength,
1274 Owner,
1275 Group,
1276 &DaclPresent,
1277 &DaclIsInherited,
1278 IsDirectoryObject,
1279 GenericMapping);
1280 if (DaclPresent)
1281 Control |= SE_DACL_PRESENT;
1282 ASSERT(DaclLength % sizeof(ULONG) == 0);
1283
1284 /* Inherit the SACL */
1285 SaclLength = 0;
1286 ExplicitAcl = NULL;
1287 ExplicitPresent = FALSE;
1288 ExplicitDefaulted = FALSE;
1289 if (ExplicitDescriptor != NULL &&
1290 (ExplicitDescriptor->Control & SE_SACL_PRESENT))
1291 {
1292 ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1293 ExplicitPresent = TRUE;
1294 if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
1295 ExplicitDefaulted = TRUE;
1296 }
1297 ParentAcl = NULL;
1298 if (ParentDescriptor != NULL &&
1299 (ParentDescriptor->Control & SE_SACL_PRESENT))
1300 {
1301 ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
1302 }
1303 Sacl = SepSelectAcl(ExplicitAcl,
1304 ExplicitPresent,
1305 ExplicitDefaulted,
1306 ParentAcl,
1307 NULL,
1308 &SaclLength,
1309 Owner,
1310 Group,
1311 &SaclPresent,
1312 &SaclIsInherited,
1313 IsDirectoryObject,
1314 GenericMapping);
1315 if (SaclPresent)
1316 Control |= SE_SACL_PRESENT;
1317 ASSERT(SaclLength % sizeof(ULONG) == 0);
1318
1319 /* Allocate and initialize the new security descriptor */
1320 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1321 OwnerLength + GroupLength + DaclLength + SaclLength;
1322
1323 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1324 sizeof(SECURITY_DESCRIPTOR),
1325 OwnerLength,
1326 GroupLength,
1327 DaclLength,
1328 SaclLength);
1329
1330 Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1331 if (Descriptor == NULL)
1332 {
1333 DPRINT1("ExAlloctePool() failed\n");
1334 SeUnlockSubjectContext(SubjectContext);
1335 return STATUS_INSUFFICIENT_RESOURCES;
1336 }
1337
1338 RtlZeroMemory(Descriptor, Length);
1339 RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1340
1341 Descriptor->Control = Control | SE_SELF_RELATIVE;
1342
1343 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1344
1345 if (SaclLength != 0)
1346 {
1347 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1348 &SaclLength,
1349 Sacl,
1350 Owner,
1351 Group,
1352 SaclIsInherited,
1353 IsDirectoryObject,
1354 GenericMapping);
1355 ASSERT(Status == STATUS_SUCCESS);
1356 Descriptor->Sacl = Current;
1357 Current += SaclLength;
1358 }
1359
1360 if (DaclLength != 0)
1361 {
1362 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1363 &DaclLength,
1364 Dacl,
1365 Owner,
1366 Group,
1367 DaclIsInherited,
1368 IsDirectoryObject,
1369 GenericMapping);
1370 ASSERT(Status == STATUS_SUCCESS);
1371 Descriptor->Dacl = Current;
1372 Current += DaclLength;
1373 }
1374
1375 if (OwnerLength != 0)
1376 {
1377 RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1378 Descriptor->Owner = Current;
1379 Current += OwnerLength;
1380 DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1381 }
1382 else
1383 {
1384 DPRINT("Owner of %p is zero length\n", Descriptor);
1385 }
1386
1387 if (GroupLength != 0)
1388 {
1389 RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1390 Descriptor->Group = Current;
1391 }
1392
1393 /* Unlock subject context */
1394 SeUnlockSubjectContext(SubjectContext);
1395
1396 *NewDescriptor = Descriptor;
1397
1398 DPRINT("Descriptor %p\n", Descriptor);
1399 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1400
1401 return STATUS_SUCCESS;
1402 }
1403
1404 /*
1405 * @implemented
1406 */
1407 _IRQL_requires_max_(PASSIVE_LEVEL)
1408 NTSTATUS
1409 NTAPI
1410 SeAssignSecurity(
1411 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor,
1412 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor,
1413 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1414 _In_ BOOLEAN IsDirectoryObject,
1415 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1416 _In_ PGENERIC_MAPPING GenericMapping,
1417 _In_ POOL_TYPE PoolType)
1418 {
1419 PAGED_CODE();
1420
1421 return SeAssignSecurityEx(ParentDescriptor,
1422 ExplicitDescriptor,
1423 NewDescriptor,
1424 NULL,
1425 IsDirectoryObject,
1426 0,
1427 SubjectContext,
1428 GenericMapping,
1429 PoolType);
1430 }
1431
1432 /*
1433 * @implemented
1434 */
1435 _IRQL_requires_max_(PASSIVE_LEVEL)
1436 NTSTATUS
1437 NTAPI
1438 SeComputeQuotaInformationSize(
1439 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1440 _Out_ PULONG QuotaInfoSize)
1441 {
1442 PSID Group;
1443 PACL Dacl;
1444
1445 PAGED_CODE();
1446
1447 *QuotaInfoSize = 0;
1448
1449 /* Validate security descriptor revision */
1450 if (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION1)
1451 {
1452 return STATUS_UNKNOWN_REVISION;
1453 }
1454
1455 /* Get group and DACL, if any */
1456 Group = SepGetGroupFromDescriptor(SecurityDescriptor);
1457 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
1458
1459 /* Return SID length if any */
1460 if (Group != NULL)
1461 {
1462 *QuotaInfoSize = ALIGN_UP_BY(RtlLengthSid(Group), sizeof(ULONG));
1463 }
1464
1465 /* Return DACL if any */
1466 if (Dacl != NULL)
1467 {
1468 *QuotaInfoSize += ALIGN_UP_BY(Dacl->AclSize, sizeof(ULONG));
1469 }
1470
1471 return STATUS_SUCCESS;
1472 }
1473
1474 /* EOF */