[STORPORT] Fix x64 build
[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 BOOLEAN
32 INIT_FUNCTION
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 RtlCreateSecurityDescriptor(NewSd,
920 SECURITY_DESCRIPTOR_REVISION1);
921
922 /* We always build a self-relative descriptor */
923 NewSd->Control = Control | SE_SELF_RELATIVE;
924
925 Current = sizeof(SECURITY_DESCRIPTOR);
926
927 if (OwnerLength != 0)
928 {
929 RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
930 NewSd->Owner = Current;
931 Current += OwnerLength;
932 }
933
934 if (GroupLength != 0)
935 {
936 RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
937 NewSd->Group = Current;
938 Current += GroupLength;
939 }
940
941 if (DaclLength != 0)
942 {
943 RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
944 NewSd->Dacl = Current;
945 Current += DaclLength;
946 }
947
948 if (SaclLength != 0)
949 {
950 RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
951 NewSd->Sacl = Current;
952 Current += SaclLength;
953 }
954
955 *ObjectsSecurityDescriptor = NewSd;
956 return STATUS_SUCCESS;
957 }
958
959
960 /*
961 * @implemented
962 */
963 BOOLEAN NTAPI
964 SeValidSecurityDescriptor(IN ULONG Length,
965 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
966 {
967 ULONG SdLength;
968 PISID Sid;
969 PACL Acl;
970 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
971
972 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
973 {
974 DPRINT1("Invalid Security Descriptor revision\n");
975 return FALSE;
976 }
977
978 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
979 {
980 DPRINT1("Invalid Security Descriptor revision\n");
981 return FALSE;
982 }
983
984 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
985 {
986 DPRINT1("No self-relative Security Descriptor\n");
987 return FALSE;
988 }
989
990 SdLength = sizeof(SECURITY_DESCRIPTOR);
991
992 /* Check Owner SID */
993 if (!SecurityDescriptor->Owner)
994 {
995 DPRINT1("No Owner SID\n");
996 return FALSE;
997 }
998
999 if (SecurityDescriptor->Owner % sizeof(ULONG))
1000 {
1001 DPRINT1("Invalid Owner SID alignment\n");
1002 return FALSE;
1003 }
1004
1005 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
1006 if (Sid->Revision != SID_REVISION)
1007 {
1008 DPRINT1("Invalid Owner SID revision\n");
1009 return FALSE;
1010 }
1011
1012 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1013 if (Length < SdLength)
1014 {
1015 DPRINT1("Invalid Owner SID size\n");
1016 return FALSE;
1017 }
1018
1019 /* Check Group SID */
1020 if (SecurityDescriptor->Group)
1021 {
1022 if (SecurityDescriptor->Group % sizeof(ULONG))
1023 {
1024 DPRINT1("Invalid Group SID alignment\n");
1025 return FALSE;
1026 }
1027
1028 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
1029 if (Sid->Revision != SID_REVISION)
1030 {
1031 DPRINT1("Invalid Group SID revision\n");
1032 return FALSE;
1033 }
1034
1035 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1036 if (Length < SdLength)
1037 {
1038 DPRINT1("Invalid Group SID size\n");
1039 return FALSE;
1040 }
1041 }
1042
1043 /* Check DACL */
1044 if (SecurityDescriptor->Dacl)
1045 {
1046 if (SecurityDescriptor->Dacl % sizeof(ULONG))
1047 {
1048 DPRINT1("Invalid DACL alignment\n");
1049 return FALSE;
1050 }
1051
1052 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
1053 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1054 (Acl->AclRevision > MAX_ACL_REVISION))
1055 {
1056 DPRINT1("Invalid DACL revision\n");
1057 return FALSE;
1058 }
1059
1060 SdLength += Acl->AclSize;
1061 if (Length < SdLength)
1062 {
1063 DPRINT1("Invalid DACL size\n");
1064 return FALSE;
1065 }
1066 }
1067
1068 /* Check SACL */
1069 if (SecurityDescriptor->Sacl)
1070 {
1071 if (SecurityDescriptor->Sacl % sizeof(ULONG))
1072 {
1073 DPRINT1("Invalid SACL alignment\n");
1074 return FALSE;
1075 }
1076
1077 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
1078 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1079 (Acl->AclRevision > MAX_ACL_REVISION))
1080 {
1081 DPRINT1("Invalid SACL revision\n");
1082 return FALSE;
1083 }
1084
1085 SdLength += Acl->AclSize;
1086 if (Length < SdLength)
1087 {
1088 DPRINT1("Invalid SACL size\n");
1089 return FALSE;
1090 }
1091 }
1092
1093 return TRUE;
1094 }
1095
1096 /*
1097 * @implemented
1098 */
1099 _IRQL_requires_max_(PASSIVE_LEVEL)
1100 NTSTATUS
1101 NTAPI
1102 SeDeassignSecurity(
1103 _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor)
1104 {
1105 PAGED_CODE();
1106
1107 if (*SecurityDescriptor != NULL)
1108 {
1109 ExFreePoolWithTag(*SecurityDescriptor, TAG_SD);
1110 *SecurityDescriptor = NULL;
1111 }
1112
1113 return STATUS_SUCCESS;
1114 }
1115
1116 /*
1117 * @implemented
1118 */
1119 _IRQL_requires_max_(PASSIVE_LEVEL)
1120 NTSTATUS
1121 NTAPI
1122 SeAssignSecurityEx(
1123 _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor,
1124 _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor,
1125 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1126 _In_opt_ GUID *ObjectType,
1127 _In_ BOOLEAN IsDirectoryObject,
1128 _In_ ULONG AutoInheritFlags,
1129 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1130 _In_ PGENERIC_MAPPING GenericMapping,
1131 _In_ POOL_TYPE PoolType)
1132 {
1133 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1134 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1135 PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
1136 PTOKEN Token;
1137 ULONG OwnerLength;
1138 ULONG GroupLength;
1139 ULONG DaclLength;
1140 ULONG SaclLength;
1141 ULONG Length;
1142 SECURITY_DESCRIPTOR_CONTROL Control = 0;
1143 ULONG Current;
1144 PSID Owner = NULL;
1145 PSID Group = NULL;
1146 PACL ExplicitAcl;
1147 BOOLEAN ExplicitPresent;
1148 BOOLEAN ExplicitDefaulted;
1149 PACL ParentAcl;
1150 PACL Dacl = NULL;
1151 PACL Sacl = NULL;
1152 BOOLEAN DaclIsInherited;
1153 BOOLEAN SaclIsInherited;
1154 BOOLEAN DaclPresent;
1155 BOOLEAN SaclPresent;
1156 NTSTATUS Status;
1157
1158 DBG_UNREFERENCED_PARAMETER(ObjectType);
1159 DBG_UNREFERENCED_PARAMETER(AutoInheritFlags);
1160 UNREFERENCED_PARAMETER(PoolType);
1161
1162 PAGED_CODE();
1163
1164 *NewDescriptor = NULL;
1165
1166 if (!ARGUMENT_PRESENT(SubjectContext))
1167 {
1168 return STATUS_NO_TOKEN;
1169 }
1170
1171 /* Lock subject context */
1172 SeLockSubjectContext(SubjectContext);
1173
1174 if (SubjectContext->ClientToken != NULL)
1175 {
1176 Token = SubjectContext->ClientToken;
1177 }
1178 else
1179 {
1180 Token = SubjectContext->PrimaryToken;
1181 }
1182
1183 /* Inherit the Owner SID */
1184 if (ExplicitDescriptor != NULL)
1185 {
1186 DPRINT("Use explicit owner sid!\n");
1187 Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
1188 }
1189 if (!Owner)
1190 {
1191 if (AutoInheritFlags & 0x20 /* FIXME: SEF_DEFAULT_OWNER_FROM_PARENT */)
1192 {
1193 DPRINT("Use parent owner sid!\n");
1194 if (!ARGUMENT_PRESENT(ParentDescriptor))
1195 {
1196 SeUnlockSubjectContext(SubjectContext);
1197 return STATUS_INVALID_OWNER;
1198 }
1199
1200 Owner = SepGetOwnerFromDescriptor(ParentDescriptor);
1201 if (!Owner)
1202 {
1203 SeUnlockSubjectContext(SubjectContext);
1204 return STATUS_INVALID_OWNER;
1205 }
1206 }
1207 else
1208 {
1209 DPRINT("Use token owner sid!\n");
1210 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1211 }
1212 }
1213 OwnerLength = RtlLengthSid(Owner);
1214 ASSERT(OwnerLength % sizeof(ULONG) == 0);
1215
1216 /* Inherit the Group SID */
1217 if (ExplicitDescriptor != NULL)
1218 {
1219 Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1220 }
1221 if (!Group)
1222 {
1223 if (AutoInheritFlags & 0x40 /* FIXME: SEF_DEFAULT_GROUP_FROM_PARENT */)
1224 {
1225 DPRINT("Use parent group sid!\n");
1226 if (!ARGUMENT_PRESENT(ParentDescriptor))
1227 {
1228 SeUnlockSubjectContext(SubjectContext);
1229 return STATUS_INVALID_PRIMARY_GROUP;
1230 }
1231
1232 Group = SepGetGroupFromDescriptor(ParentDescriptor);
1233 if (!Group)
1234 {
1235 SeUnlockSubjectContext(SubjectContext);
1236 return STATUS_INVALID_PRIMARY_GROUP;
1237 }
1238 }
1239 else
1240 {
1241 DPRINT("Use token group sid!\n");
1242 Group = Token->PrimaryGroup;
1243 }
1244 }
1245 if (!Group)
1246 {
1247 SeUnlockSubjectContext(SubjectContext);
1248 return STATUS_INVALID_PRIMARY_GROUP;
1249 }
1250 GroupLength = RtlLengthSid(Group);
1251 ASSERT(GroupLength % sizeof(ULONG) == 0);
1252
1253 /* Inherit the DACL */
1254 DaclLength = 0;
1255 ExplicitAcl = NULL;
1256 ExplicitPresent = FALSE;
1257 ExplicitDefaulted = FALSE;
1258 if (ExplicitDescriptor != NULL &&
1259 (ExplicitDescriptor->Control & SE_DACL_PRESENT))
1260 {
1261 ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1262 ExplicitPresent = TRUE;
1263 if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED)
1264 ExplicitDefaulted = TRUE;
1265 }
1266 ParentAcl = NULL;
1267 if (ParentDescriptor != NULL &&
1268 (ParentDescriptor->Control & SE_DACL_PRESENT))
1269 {
1270 ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
1271 }
1272 Dacl = SepSelectAcl(ExplicitAcl,
1273 ExplicitPresent,
1274 ExplicitDefaulted,
1275 ParentAcl,
1276 Token->DefaultDacl,
1277 &DaclLength,
1278 Owner,
1279 Group,
1280 &DaclPresent,
1281 &DaclIsInherited,
1282 IsDirectoryObject,
1283 GenericMapping);
1284 if (DaclPresent)
1285 Control |= SE_DACL_PRESENT;
1286 ASSERT(DaclLength % sizeof(ULONG) == 0);
1287
1288 /* Inherit the SACL */
1289 SaclLength = 0;
1290 ExplicitAcl = NULL;
1291 ExplicitPresent = FALSE;
1292 ExplicitDefaulted = FALSE;
1293 if (ExplicitDescriptor != NULL &&
1294 (ExplicitDescriptor->Control & SE_SACL_PRESENT))
1295 {
1296 ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1297 ExplicitPresent = TRUE;
1298 if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
1299 ExplicitDefaulted = TRUE;
1300 }
1301 ParentAcl = NULL;
1302 if (ParentDescriptor != NULL &&
1303 (ParentDescriptor->Control & SE_SACL_PRESENT))
1304 {
1305 ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
1306 }
1307 Sacl = SepSelectAcl(ExplicitAcl,
1308 ExplicitPresent,
1309 ExplicitDefaulted,
1310 ParentAcl,
1311 NULL,
1312 &SaclLength,
1313 Owner,
1314 Group,
1315 &SaclPresent,
1316 &SaclIsInherited,
1317 IsDirectoryObject,
1318 GenericMapping);
1319 if (SaclPresent)
1320 Control |= SE_SACL_PRESENT;
1321 ASSERT(SaclLength % sizeof(ULONG) == 0);
1322
1323 /* Allocate and initialize the new security descriptor */
1324 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1325 OwnerLength + GroupLength + DaclLength + SaclLength;
1326
1327 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1328 sizeof(SECURITY_DESCRIPTOR),
1329 OwnerLength,
1330 GroupLength,
1331 DaclLength,
1332 SaclLength);
1333
1334 Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1335 if (Descriptor == NULL)
1336 {
1337 DPRINT1("ExAlloctePool() failed\n");
1338 SeUnlockSubjectContext(SubjectContext);
1339 return STATUS_INSUFFICIENT_RESOURCES;
1340 }
1341
1342 RtlZeroMemory(Descriptor, Length);
1343 RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1344
1345 Descriptor->Control = Control | SE_SELF_RELATIVE;
1346
1347 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1348
1349 if (SaclLength != 0)
1350 {
1351 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1352 &SaclLength,
1353 Sacl,
1354 Owner,
1355 Group,
1356 SaclIsInherited,
1357 IsDirectoryObject,
1358 GenericMapping);
1359 ASSERT(Status == STATUS_SUCCESS);
1360 Descriptor->Sacl = Current;
1361 Current += SaclLength;
1362 }
1363
1364 if (DaclLength != 0)
1365 {
1366 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1367 &DaclLength,
1368 Dacl,
1369 Owner,
1370 Group,
1371 DaclIsInherited,
1372 IsDirectoryObject,
1373 GenericMapping);
1374 ASSERT(Status == STATUS_SUCCESS);
1375 Descriptor->Dacl = Current;
1376 Current += DaclLength;
1377 }
1378
1379 if (OwnerLength != 0)
1380 {
1381 RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1382 Descriptor->Owner = Current;
1383 Current += OwnerLength;
1384 DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1385 }
1386 else
1387 {
1388 DPRINT("Owner of %p is zero length\n", Descriptor);
1389 }
1390
1391 if (GroupLength != 0)
1392 {
1393 RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1394 Descriptor->Group = Current;
1395 }
1396
1397 /* Unlock subject context */
1398 SeUnlockSubjectContext(SubjectContext);
1399
1400 *NewDescriptor = Descriptor;
1401
1402 DPRINT("Descriptor %p\n", Descriptor);
1403 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1404
1405 return STATUS_SUCCESS;
1406 }
1407
1408 /*
1409 * @implemented
1410 */
1411 _IRQL_requires_max_(PASSIVE_LEVEL)
1412 NTSTATUS
1413 NTAPI
1414 SeAssignSecurity(
1415 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor,
1416 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor,
1417 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1418 _In_ BOOLEAN IsDirectoryObject,
1419 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1420 _In_ PGENERIC_MAPPING GenericMapping,
1421 _In_ POOL_TYPE PoolType)
1422 {
1423 PAGED_CODE();
1424
1425 return SeAssignSecurityEx(ParentDescriptor,
1426 ExplicitDescriptor,
1427 NewDescriptor,
1428 NULL,
1429 IsDirectoryObject,
1430 0,
1431 SubjectContext,
1432 GenericMapping,
1433 PoolType);
1434 }
1435
1436 /* EOF */