Sync to trunk r65566.
[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 = ExAllocatePool(PoolType,
285 sizeof(SECURITY_QUALITY_OF_SERVICE));
286 if (CapturedQos != NULL)
287 {
288 RtlCopyMemory(CapturedQos,
289 &SafeQos,
290 sizeof(SECURITY_QUALITY_OF_SERVICE));
291 *CapturedSecurityQualityOfService = CapturedQos;
292 }
293 else
294 {
295 Status = STATUS_INSUFFICIENT_RESOURCES;
296 }
297 }
298 else
299 {
300 *CapturedSecurityQualityOfService = NULL;
301 }
302 }
303 }
304 else
305 {
306 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
307 {
308 if (CaptureIfKernel)
309 {
310 if (ObjectAttributes->SecurityQualityOfService != NULL)
311 {
312 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
313 sizeof(SECURITY_QUALITY_OF_SERVICE))
314 {
315 CapturedQos = ExAllocatePool(PoolType,
316 sizeof(SECURITY_QUALITY_OF_SERVICE));
317 if (CapturedQos != NULL)
318 {
319 RtlCopyMemory(CapturedQos,
320 ObjectAttributes->SecurityQualityOfService,
321 sizeof(SECURITY_QUALITY_OF_SERVICE));
322 *CapturedSecurityQualityOfService = CapturedQos;
323 *Present = TRUE;
324 }
325 else
326 {
327 Status = STATUS_INSUFFICIENT_RESOURCES;
328 }
329 }
330 else
331 {
332 Status = STATUS_INVALID_PARAMETER;
333 }
334 }
335 else
336 {
337 *CapturedSecurityQualityOfService = NULL;
338 *Present = FALSE;
339 }
340 }
341 else
342 {
343 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
344 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
345 }
346 }
347 else
348 {
349 Status = STATUS_INVALID_PARAMETER;
350 }
351 }
352 }
353 else
354 {
355 *CapturedSecurityQualityOfService = NULL;
356 *Present = FALSE;
357 }
358
359 return Status;
360 }
361
362
363 VOID
364 NTAPI
365 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL,
366 IN KPROCESSOR_MODE AccessMode,
367 IN BOOLEAN CaptureIfKernel)
368 {
369 PAGED_CODE();
370
371 if (CapturedSecurityQualityOfService != NULL &&
372 (AccessMode != KernelMode || CaptureIfKernel))
373 {
374 ExFreePool(CapturedSecurityQualityOfService);
375 }
376 }
377
378 /* PUBLIC FUNCTIONS ***********************************************************/
379
380 static
381 ULONG
382 DetermineSIDSize(
383 PISID Sid,
384 PULONG OutSAC,
385 KPROCESSOR_MODE ProcessorMode)
386 {
387 ULONG Size;
388
389 if (!Sid)
390 {
391 *OutSAC = 0;
392 return 0;
393 }
394
395 if (ProcessorMode != KernelMode)
396 {
397 /* Securely access the buffers! */
398 *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount);
399 Size = RtlLengthRequiredSid(*OutSAC);
400 ProbeForRead(Sid, Size, sizeof(ULONG));
401 }
402 else
403 {
404 *OutSAC = Sid->SubAuthorityCount;
405 Size = RtlLengthRequiredSid(*OutSAC);
406 }
407
408 return Size;
409 }
410
411 static
412 ULONG
413 DetermineACLSize(
414 PACL Acl,
415 KPROCESSOR_MODE ProcessorMode)
416 {
417 ULONG Size;
418
419 if (!Acl) return 0;
420
421 if (ProcessorMode == KernelMode) return Acl->AclSize;
422
423 /* Probe the buffers! */
424 Size = ProbeForReadUshort(&Acl->AclSize);
425 ProbeForRead(Acl, Size, sizeof(ULONG));
426
427 return Size;
428 }
429
430 NTSTATUS
431 NTAPI
432 SeCaptureSecurityDescriptor(
433 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
434 IN KPROCESSOR_MODE CurrentMode,
435 IN POOL_TYPE PoolType,
436 IN BOOLEAN CaptureIfKernel,
437 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
438 {
439 PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor;
440 SECURITY_DESCRIPTOR DescriptorCopy;
441 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor;
442 ULONG OwnerSAC = 0, GroupSAC = 0;
443 ULONG OwnerSize = 0, GroupSize = 0;
444 ULONG SaclSize = 0, DaclSize = 0;
445 ULONG DescriptorSize = 0;
446 ULONG Offset;
447
448 if (!OriginalDescriptor)
449 {
450 /* Nothing to do... */
451 *CapturedSecurityDescriptor = NULL;
452 return STATUS_SUCCESS;
453 }
454
455 /* Quick path */
456 if (CurrentMode == KernelMode && !CaptureIfKernel)
457 {
458 /* Check descriptor version */
459 if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
460 {
461 return STATUS_UNKNOWN_REVISION;
462 }
463
464 *CapturedSecurityDescriptor = _OriginalSecurityDescriptor;
465 return STATUS_SUCCESS;
466 }
467
468 _SEH2_TRY
469 {
470 if (CurrentMode != KernelMode)
471 {
472 ProbeForRead(OriginalDescriptor,
473 sizeof(SECURITY_DESCRIPTOR_RELATIVE),
474 sizeof(ULONG));
475 }
476
477 /* Check the descriptor version */
478 if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
479 {
480 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
481 }
482
483 if (CurrentMode != KernelMode)
484 {
485 /* Get the size of the descriptor */
486 DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ?
487 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR);
488
489 /* Probe the entire security descriptor structure. The SIDs
490 * and ACLs will be probed and copied later though */
491 ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG));
492 }
493
494 /* Now capture all fields and convert to an absolute descriptor */
495 DescriptorCopy.Revision = OriginalDescriptor->Revision;
496 DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1;
497 DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE;
498 DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor);
499 DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor);
500 DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor);
501 DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor);
502 DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
503
504 /* Determine owner and group sizes */
505 OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode);
506 DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG));
507 GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode);
508 DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG));
509
510 /* Determine the size of the ACLs */
511 if (DescriptorCopy.Control & SE_SACL_PRESENT)
512 {
513 /* Get the size and probe if user mode */
514 SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode);
515 DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG));
516 }
517
518 if (DescriptorCopy.Control & SE_DACL_PRESENT)
519 {
520 /* Get the size and probe if user mode */
521 DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode);
522 DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG));
523 }
524 }
525 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
526 {
527 _SEH2_YIELD(return _SEH2_GetExceptionCode());
528 }
529 _SEH2_END
530
531 /*
532 * Allocate enough memory to store a complete copy of a self-relative
533 * security descriptor
534 */
535 NewDescriptor = ExAllocatePoolWithTag(PoolType,
536 DescriptorSize,
537 TAG_SD);
538 if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
539
540 RtlZeroMemory(NewDescriptor, DescriptorSize);
541 NewDescriptor->Revision = DescriptorCopy.Revision;
542 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
543 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
544
545 _SEH2_TRY
546 {
547 /*
548 * Setup the offsets and copy the SIDs and ACLs to the new
549 * self-relative security descriptor. Probing the pointers is not
550 * neccessary anymore as we did that when collecting the sizes!
551 * Make sure to validate the SIDs and ACLs *again* as they could have
552 * been modified in the meanwhile!
553 */
554 Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
555
556 if (DescriptorCopy.Owner)
557 {
558 if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID);
559 NewDescriptor->Owner = Offset;
560 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
561 DescriptorCopy.Owner,
562 OwnerSize);
563 Offset += ROUND_UP(OwnerSize, sizeof(ULONG));
564 }
565
566 if (DescriptorCopy.Group)
567 {
568 if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID);
569 NewDescriptor->Group = Offset;
570 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
571 DescriptorCopy.Group,
572 GroupSize);
573 Offset += ROUND_UP(GroupSize, sizeof(ULONG));
574 }
575
576 if (DescriptorCopy.Sacl)
577 {
578 if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
579 NewDescriptor->Sacl = Offset;
580 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
581 DescriptorCopy.Sacl,
582 SaclSize);
583 Offset += ROUND_UP(SaclSize, sizeof(ULONG));
584 }
585
586 if (DescriptorCopy.Dacl)
587 {
588 if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
589 NewDescriptor->Dacl = Offset;
590 RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
591 DescriptorCopy.Dacl,
592 DaclSize);
593 Offset += ROUND_UP(DaclSize, sizeof(ULONG));
594 }
595
596 /* Make sure the size was correct */
597 ASSERT(Offset == DescriptorSize);
598 }
599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
600 {
601 /* We failed to copy the data to the new descriptor */
602 ExFreePoolWithTag(NewDescriptor, TAG_SD);
603 _SEH2_YIELD(return _SEH2_GetExceptionCode());
604 }
605 _SEH2_END;
606
607 /*
608 * We're finally done!
609 * Copy the pointer to the captured descriptor to to the caller.
610 */
611 *CapturedSecurityDescriptor = NewDescriptor;
612 return STATUS_SUCCESS;
613 }
614
615 /*
616 * @implemented
617 */
618 _IRQL_requires_max_(PASSIVE_LEVEL)
619 NTSTATUS
620 NTAPI
621 SeQuerySecurityDescriptorInfo(
622 _In_ PSECURITY_INFORMATION SecurityInformation,
623 _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor,
624 _Inout_ PULONG Length,
625 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
626 {
627 PISECURITY_DESCRIPTOR ObjectSd;
628 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
629 PSID Owner = NULL;
630 PSID Group = NULL;
631 PACL Dacl = NULL;
632 PACL Sacl = NULL;
633 ULONG OwnerLength = 0;
634 ULONG GroupLength = 0;
635 ULONG DaclLength = 0;
636 ULONG SaclLength = 0;
637 SECURITY_DESCRIPTOR_CONTROL Control = 0;
638 ULONG_PTR Current;
639 ULONG SdLength;
640
641 PAGED_CODE();
642
643 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
644
645 if (*ObjectsSecurityDescriptor == NULL)
646 {
647 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
648 {
649 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
650 return STATUS_BUFFER_TOO_SMALL;
651 }
652
653 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
654 RtlCreateSecurityDescriptorRelative(RelSD,
655 SECURITY_DESCRIPTOR_REVISION);
656 return STATUS_SUCCESS;
657 }
658
659 ObjectSd = *ObjectsSecurityDescriptor;
660
661 /* Calculate the required security descriptor length */
662 Control = SE_SELF_RELATIVE;
663 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
664 (ObjectSd->Owner != NULL))
665 {
666 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
667 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
668 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
669 }
670
671 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
672 (ObjectSd->Group != NULL))
673 {
674 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
675 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
676 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
677 }
678
679 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
680 (ObjectSd->Control & SE_DACL_PRESENT))
681 {
682 if (ObjectSd->Dacl != NULL)
683 {
684 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
685 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
686 }
687
688 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
689 }
690
691 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
692 (ObjectSd->Control & SE_SACL_PRESENT))
693 {
694 if (ObjectSd->Sacl != NULL)
695 {
696 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
697 SaclLength = ROUND_UP(Sacl->AclSize, 4);
698 }
699
700 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
701 }
702
703 SdLength = OwnerLength + GroupLength + DaclLength +
704 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
705 if (*Length < SdLength)
706 {
707 *Length = SdLength;
708 return STATUS_BUFFER_TOO_SMALL;
709 }
710
711 /* Build the new security descrtiptor */
712 RtlCreateSecurityDescriptorRelative(RelSD,
713 SECURITY_DESCRIPTOR_REVISION);
714 RelSD->Control = Control;
715
716 Current = (ULONG_PTR)(RelSD + 1);
717
718 if (OwnerLength != 0)
719 {
720 RtlCopyMemory((PVOID)Current,
721 Owner,
722 OwnerLength);
723 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
724 Current += OwnerLength;
725 }
726
727 if (GroupLength != 0)
728 {
729 RtlCopyMemory((PVOID)Current,
730 Group,
731 GroupLength);
732 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
733 Current += GroupLength;
734 }
735
736 if (DaclLength != 0)
737 {
738 RtlCopyMemory((PVOID)Current,
739 Dacl,
740 DaclLength);
741 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
742 Current += DaclLength;
743 }
744
745 if (SaclLength != 0)
746 {
747 RtlCopyMemory((PVOID)Current,
748 Sacl,
749 SaclLength);
750 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
751 Current += SaclLength;
752 }
753
754 *Length = SdLength;
755
756 return STATUS_SUCCESS;
757 }
758
759 /*
760 * @implemented
761 */
762 NTSTATUS
763 NTAPI
764 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
765 IN KPROCESSOR_MODE CurrentMode,
766 IN BOOLEAN CaptureIfKernelMode)
767 {
768 PAGED_CODE();
769
770 /*
771 * WARNING! You need to call this function with the same value for CurrentMode
772 * and CaptureIfKernelMode that you previously passed to
773 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
774 */
775 if (CapturedSecurityDescriptor != NULL &&
776 (CurrentMode != KernelMode ||
777 (CurrentMode == KernelMode && CaptureIfKernelMode)))
778 {
779 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
780 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
781 }
782
783 return STATUS_SUCCESS;
784 }
785
786 /*
787 * @implemented
788 */
789 _IRQL_requires_max_(PASSIVE_LEVEL)
790 NTSTATUS
791 NTAPI
792 SeSetSecurityDescriptorInfo(
793 _In_opt_ PVOID Object,
794 _In_ PSECURITY_INFORMATION SecurityInformation,
795 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
796 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
797 _In_ POOL_TYPE PoolType,
798 _In_ PGENERIC_MAPPING GenericMapping)
799 {
800 PAGED_CODE();
801
802 return SeSetSecurityDescriptorInfoEx(Object,
803 SecurityInformation,
804 SecurityDescriptor,
805 ObjectsSecurityDescriptor,
806 0,
807 PoolType,
808 GenericMapping);
809 }
810
811 /*
812 * @implemented
813 */
814 _IRQL_requires_max_(PASSIVE_LEVEL)
815 NTSTATUS
816 NTAPI
817 SeSetSecurityDescriptorInfoEx(
818 _In_opt_ PVOID Object,
819 _In_ PSECURITY_INFORMATION _SecurityInformation,
820 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor,
821 _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
822 _In_ ULONG AutoInheritFlags,
823 _In_ POOL_TYPE PoolType,
824 _In_ PGENERIC_MAPPING GenericMapping)
825 {
826 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd;
827 PISECURITY_DESCRIPTOR_RELATIVE NewSd;
828 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
829 PSID Owner;
830 PSID Group;
831 PACL Dacl;
832 PACL Sacl;
833 ULONG OwnerLength;
834 ULONG GroupLength;
835 ULONG DaclLength;
836 ULONG SaclLength;
837 SECURITY_DESCRIPTOR_CONTROL Control = 0;
838 ULONG Current;
839 SECURITY_INFORMATION SecurityInformation;
840
841 PAGED_CODE();
842
843 ObjectSd = *ObjectsSecurityDescriptor;
844
845 /* The object does not have a security descriptor. */
846 if (!ObjectSd)
847 return STATUS_NO_SECURITY_ON_OBJECT;
848
849 ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
850
851 SecurityInformation = *_SecurityInformation;
852
853 /* Get owner and owner size */
854 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
855 {
856 Owner = SepGetOwnerFromDescriptor(SecurityDescriptor);
857 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
858 }
859 else
860 {
861 Owner = SepGetOwnerFromDescriptor(ObjectSd);
862 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
863 }
864 OwnerLength = Owner ? RtlLengthSid(Owner) : 0;
865 NT_ASSERT(OwnerLength % sizeof(ULONG) == 0);
866
867 /* Get group and group size */
868 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
869 {
870 Group = SepGetGroupFromDescriptor(SecurityDescriptor);
871 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
872 }
873 else
874 {
875 Group = SepGetGroupFromDescriptor(ObjectSd);
876 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
877 }
878 GroupLength = Group ? RtlLengthSid(Group) : 0;
879 NT_ASSERT(GroupLength % sizeof(ULONG) == 0);
880
881 /* Get DACL and DACL size */
882 if (SecurityInformation & DACL_SECURITY_INFORMATION)
883 {
884 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
885 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
886 }
887 else
888 {
889 Dacl = SepGetDaclFromDescriptor(ObjectSd);
890 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
891 }
892 DaclLength = Dacl ? ROUND_UP((ULONG)Dacl->AclSize, 4) : 0;
893
894 /* Get SACL and SACL size */
895 if (SecurityInformation & SACL_SECURITY_INFORMATION)
896 {
897 Sacl = SepGetSaclFromDescriptor(SecurityDescriptor);
898 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
899 }
900 else
901 {
902 Sacl = SepGetSaclFromDescriptor(ObjectSd);
903 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
904 }
905 SaclLength = Sacl ? ROUND_UP((ULONG)Sacl->AclSize, 4) : 0;
906
907 NewSd = ExAllocatePool(NonPagedPool,
908 sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength +
909 DaclLength + SaclLength);
910 if (NewSd == NULL)
911 {
912 return STATUS_INSUFFICIENT_RESOURCES;
913 }
914
915 RtlCreateSecurityDescriptor(NewSd,
916 SECURITY_DESCRIPTOR_REVISION1);
917
918 /* We always build a self-relative descriptor */
919 NewSd->Control = Control | SE_SELF_RELATIVE;
920
921 Current = sizeof(SECURITY_DESCRIPTOR);
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 DPRINT("Use token owner sid!\n");
1188 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1189 }
1190 OwnerLength = RtlLengthSid(Owner);
1191 NT_ASSERT(OwnerLength % sizeof(ULONG) == 0);
1192
1193 /* Inherit the Group SID */
1194 if (ExplicitDescriptor != NULL)
1195 {
1196 Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1197 }
1198 if (!Group)
1199 {
1200 DPRINT("Use token group sid!\n");
1201 Group = Token->PrimaryGroup;
1202 }
1203 if (!Group)
1204 {
1205 SeUnlockSubjectContext(SubjectContext);
1206 return STATUS_INVALID_PRIMARY_GROUP;
1207 }
1208 GroupLength = RtlLengthSid(Group);
1209 NT_ASSERT(GroupLength % sizeof(ULONG) == 0);
1210
1211 /* Inherit the DACL */
1212 DaclLength = 0;
1213 ExplicitAcl = NULL;
1214 ExplicitPresent = FALSE;
1215 ExplicitDefaulted = FALSE;
1216 if (ExplicitDescriptor != NULL &&
1217 (ExplicitDescriptor->Control & SE_DACL_PRESENT))
1218 {
1219 ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1220 ExplicitPresent = TRUE;
1221 if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED)
1222 ExplicitDefaulted = TRUE;
1223 }
1224 ParentAcl = NULL;
1225 if (ParentDescriptor != NULL &&
1226 (ParentDescriptor->Control & SE_DACL_PRESENT))
1227 {
1228 ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
1229 }
1230 Dacl = SepSelectAcl(ExplicitAcl,
1231 ExplicitPresent,
1232 ExplicitDefaulted,
1233 ParentAcl,
1234 Token->DefaultDacl,
1235 &DaclLength,
1236 Owner,
1237 Group,
1238 &DaclPresent,
1239 &DaclIsInherited,
1240 IsDirectoryObject,
1241 GenericMapping);
1242 if (DaclPresent)
1243 Control |= SE_DACL_PRESENT;
1244 NT_ASSERT(DaclLength % sizeof(ULONG) == 0);
1245
1246 /* Inherit the SACL */
1247 SaclLength = 0;
1248 ExplicitAcl = NULL;
1249 ExplicitPresent = FALSE;
1250 ExplicitDefaulted = FALSE;
1251 if (ExplicitDescriptor != NULL &&
1252 (ExplicitDescriptor->Control & SE_SACL_PRESENT))
1253 {
1254 ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1255 ExplicitPresent = TRUE;
1256 if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
1257 ExplicitDefaulted = TRUE;
1258 }
1259 ParentAcl = NULL;
1260 if (ParentDescriptor != NULL &&
1261 (ParentDescriptor->Control & SE_SACL_PRESENT))
1262 {
1263 ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
1264 }
1265 Sacl = SepSelectAcl(ExplicitAcl,
1266 ExplicitPresent,
1267 ExplicitDefaulted,
1268 ParentAcl,
1269 NULL,
1270 &SaclLength,
1271 Owner,
1272 Group,
1273 &SaclPresent,
1274 &SaclIsInherited,
1275 IsDirectoryObject,
1276 GenericMapping);
1277 if (SaclPresent)
1278 Control |= SE_SACL_PRESENT;
1279 NT_ASSERT(SaclLength % sizeof(ULONG) == 0);
1280
1281 /* Allocate and initialize the new security descriptor */
1282 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1283 OwnerLength + GroupLength + DaclLength + SaclLength;
1284
1285 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1286 sizeof(SECURITY_DESCRIPTOR),
1287 OwnerLength,
1288 GroupLength,
1289 DaclLength,
1290 SaclLength);
1291
1292 Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1293 if (Descriptor == NULL)
1294 {
1295 DPRINT1("ExAlloctePool() failed\n");
1296 SeUnlockSubjectContext(SubjectContext);
1297 return STATUS_INSUFFICIENT_RESOURCES;
1298 }
1299
1300 RtlZeroMemory(Descriptor, Length);
1301 RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1302
1303 Descriptor->Control = Control | SE_SELF_RELATIVE;
1304
1305 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1306
1307 if (SaclLength != 0)
1308 {
1309 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1310 &SaclLength,
1311 Sacl,
1312 Owner,
1313 Group,
1314 SaclIsInherited,
1315 IsDirectoryObject,
1316 GenericMapping);
1317 NT_ASSERT(Status == STATUS_SUCCESS);
1318 Descriptor->Sacl = Current;
1319 Current += SaclLength;
1320 }
1321
1322 if (DaclLength != 0)
1323 {
1324 Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1325 &DaclLength,
1326 Dacl,
1327 Owner,
1328 Group,
1329 DaclIsInherited,
1330 IsDirectoryObject,
1331 GenericMapping);
1332 NT_ASSERT(Status == STATUS_SUCCESS);
1333 Descriptor->Dacl = Current;
1334 Current += DaclLength;
1335 }
1336
1337 if (OwnerLength != 0)
1338 {
1339 RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1340 Descriptor->Owner = Current;
1341 Current += OwnerLength;
1342 DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1343 }
1344 else
1345 {
1346 DPRINT("Owner of %p is zero length\n", Descriptor);
1347 }
1348
1349 if (GroupLength != 0)
1350 {
1351 RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1352 Descriptor->Group = Current;
1353 }
1354
1355 /* Unlock subject context */
1356 SeUnlockSubjectContext(SubjectContext);
1357
1358 *NewDescriptor = Descriptor;
1359
1360 DPRINT("Descriptor %p\n", Descriptor);
1361 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1362
1363 return STATUS_SUCCESS;
1364 }
1365
1366 /*
1367 * @implemented
1368 */
1369 _IRQL_requires_max_(PASSIVE_LEVEL)
1370 NTSTATUS
1371 NTAPI
1372 SeAssignSecurity(
1373 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor,
1374 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor,
1375 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1376 _In_ BOOLEAN IsDirectoryObject,
1377 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1378 _In_ PGENERIC_MAPPING GenericMapping,
1379 _In_ POOL_TYPE PoolType)
1380 {
1381 PAGED_CODE();
1382
1383 return SeAssignSecurityEx(ParentDescriptor,
1384 ExplicitDescriptor,
1385 NewDescriptor,
1386 NULL,
1387 IsDirectoryObject,
1388 0,
1389 SubjectContext,
1390 GenericMapping,
1391 PoolType);
1392 }
1393
1394 /* EOF */