[NTOS:SE]
[reactos.git] / reactos / 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 ULONG 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 = (USHORT)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 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
830 PSID Owner = 0;
831 PSID Group = 0;
832 PACL Dacl = 0;
833 PACL Sacl = 0;
834 ULONG OwnerLength = 0;
835 ULONG GroupLength = 0;
836 ULONG DaclLength = 0;
837 ULONG SaclLength = 0;
838 ULONG Control = 0;
839 ULONG Current;
840 SECURITY_INFORMATION SecurityInformation;
841
842 PAGED_CODE();
843
844 ObjectSd = *ObjectsSecurityDescriptor;
845
846 /* The object does not have a security descriptor. */
847 if (!ObjectSd)
848 return STATUS_NO_SECURITY_ON_OBJECT;
849
850 ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
851
852 SecurityInformation = *_SecurityInformation;
853
854 /* Get owner and owner size */
855 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
856 {
857 if (SecurityDescriptor->Owner != NULL)
858 {
859 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
860 Owner = (PSID)((ULONG_PTR)RelSD->Owner +
861 (ULONG_PTR)SecurityDescriptor);
862 else
863 Owner = (PSID)SecurityDescriptor->Owner;
864 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
865 }
866
867 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
868 }
869 else
870 {
871 if (ObjectSd->Owner)
872 {
873 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
874 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
875 }
876
877 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
878 }
879
880 /* Get group and group size */
881 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
882 {
883 if (SecurityDescriptor->Group != NULL)
884 {
885 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
886 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
887 (ULONG_PTR)SecurityDescriptor);
888 else
889 Group = (PSID)SecurityDescriptor->Group;
890 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
891 }
892
893 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
894 }
895 else
896 {
897 if (ObjectSd->Group)
898 {
899 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
900 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
901 }
902
903 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
904 }
905
906 /* Get DACL and DACL size */
907 if (SecurityInformation & DACL_SECURITY_INFORMATION)
908 {
909 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
910 (SecurityDescriptor->Dacl != NULL))
911 {
912 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
913 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
914 (ULONG_PTR)SecurityDescriptor);
915 else
916 Dacl = (PACL)SecurityDescriptor->Dacl;
917
918 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
919 }
920
921 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
922 }
923 else
924 {
925 if ((ObjectSd->Control & SE_DACL_PRESENT) && (ObjectSd->Dacl))
926 {
927 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
928 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
929 }
930
931 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
932 }
933
934 /* Get SACL and SACL size */
935 if (SecurityInformation & SACL_SECURITY_INFORMATION)
936 {
937 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
938 (SecurityDescriptor->Sacl != NULL))
939 {
940 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
941 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
942 (ULONG_PTR)SecurityDescriptor);
943 else
944 Sacl = (PACL)SecurityDescriptor->Sacl;
945 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
946 }
947
948 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
949 }
950 else
951 {
952 if ((ObjectSd->Control & SE_SACL_PRESENT) && (ObjectSd->Sacl))
953 {
954 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
955 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
956 }
957
958 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
959 }
960
961 NewSd = ExAllocatePool(NonPagedPool,
962 sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength +
963 DaclLength + SaclLength);
964 if (NewSd == NULL)
965 {
966 ObDereferenceObject(Object);
967 return STATUS_INSUFFICIENT_RESOURCES;
968 }
969
970 RtlCreateSecurityDescriptor(NewSd,
971 SECURITY_DESCRIPTOR_REVISION1);
972
973 /* We always build a self-relative descriptor */
974 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
975
976 Current = sizeof(SECURITY_DESCRIPTOR);
977
978 if (OwnerLength != 0)
979 {
980 RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
981 NewSd->Owner = Current;
982 Current += OwnerLength;
983 }
984
985 if (GroupLength != 0)
986 {
987 RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
988 NewSd->Group = Current;
989 Current += GroupLength;
990 }
991
992 if (DaclLength != 0)
993 {
994 RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
995 NewSd->Dacl = Current;
996 Current += DaclLength;
997 }
998
999 if (SaclLength != 0)
1000 {
1001 RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
1002 NewSd->Sacl = Current;
1003 Current += SaclLength;
1004 }
1005
1006 *ObjectsSecurityDescriptor = NewSd;
1007 return STATUS_SUCCESS;
1008 }
1009
1010
1011 /*
1012 * @implemented
1013 */
1014 BOOLEAN NTAPI
1015 SeValidSecurityDescriptor(IN ULONG Length,
1016 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
1017 {
1018 ULONG SdLength;
1019 PISID Sid;
1020 PACL Acl;
1021 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
1022
1023 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1024 {
1025 DPRINT1("Invalid Security Descriptor revision\n");
1026 return FALSE;
1027 }
1028
1029 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1030 {
1031 DPRINT1("Invalid Security Descriptor revision\n");
1032 return FALSE;
1033 }
1034
1035 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1036 {
1037 DPRINT1("No self-relative Security Descriptor\n");
1038 return FALSE;
1039 }
1040
1041 SdLength = sizeof(SECURITY_DESCRIPTOR);
1042
1043 /* Check Owner SID */
1044 if (SecurityDescriptor->Owner)
1045 {
1046 DPRINT1("No Owner SID\n");
1047 return FALSE;
1048 }
1049
1050 if (SecurityDescriptor->Owner % sizeof(ULONG))
1051 {
1052 DPRINT1("Invalid Owner SID alignment\n");
1053 return FALSE;
1054 }
1055
1056 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
1057 if (Sid->Revision != SID_REVISION)
1058 {
1059 DPRINT1("Invalid Owner SID revision\n");
1060 return FALSE;
1061 }
1062
1063 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1064 if (Length < SdLength)
1065 {
1066 DPRINT1("Invalid Owner SID size\n");
1067 return FALSE;
1068 }
1069
1070 /* Check Group SID */
1071 if (SecurityDescriptor->Group)
1072 {
1073 if (SecurityDescriptor->Group % sizeof(ULONG))
1074 {
1075 DPRINT1("Invalid Group SID alignment\n");
1076 return FALSE;
1077 }
1078
1079 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
1080 if (Sid->Revision != SID_REVISION)
1081 {
1082 DPRINT1("Invalid Group SID revision\n");
1083 return FALSE;
1084 }
1085
1086 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1087 if (Length < SdLength)
1088 {
1089 DPRINT1("Invalid Group SID size\n");
1090 return FALSE;
1091 }
1092 }
1093
1094 /* Check DACL */
1095 if (SecurityDescriptor->Dacl)
1096 {
1097 if (SecurityDescriptor->Dacl % sizeof(ULONG))
1098 {
1099 DPRINT1("Invalid DACL alignment\n");
1100 return FALSE;
1101 }
1102
1103 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
1104 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1105 (Acl->AclRevision > MAX_ACL_REVISION))
1106 {
1107 DPRINT1("Invalid DACL revision\n");
1108 return FALSE;
1109 }
1110
1111 SdLength += Acl->AclSize;
1112 if (Length < SdLength)
1113 {
1114 DPRINT1("Invalid DACL size\n");
1115 return FALSE;
1116 }
1117 }
1118
1119 /* Check SACL */
1120 if (SecurityDescriptor->Sacl)
1121 {
1122 if (SecurityDescriptor->Sacl % sizeof(ULONG))
1123 {
1124 DPRINT1("Invalid SACL alignment\n");
1125 return FALSE;
1126 }
1127
1128 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
1129 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1130 (Acl->AclRevision > MAX_ACL_REVISION))
1131 {
1132 DPRINT1("Invalid SACL revision\n");
1133 return FALSE;
1134 }
1135
1136 SdLength += Acl->AclSize;
1137 if (Length < SdLength)
1138 {
1139 DPRINT1("Invalid SACL size\n");
1140 return FALSE;
1141 }
1142 }
1143
1144 return TRUE;
1145 }
1146
1147 /*
1148 * @implemented
1149 */
1150 _IRQL_requires_max_(PASSIVE_LEVEL)
1151 NTSTATUS
1152 NTAPI
1153 SeDeassignSecurity(
1154 _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor)
1155 {
1156 PAGED_CODE();
1157
1158 if (*SecurityDescriptor != NULL)
1159 {
1160 ExFreePoolWithTag(*SecurityDescriptor, TAG_SD);
1161 *SecurityDescriptor = NULL;
1162 }
1163
1164 return STATUS_SUCCESS;
1165 }
1166
1167
1168 /*
1169 * @implemented
1170 */
1171 _IRQL_requires_max_(PASSIVE_LEVEL)
1172 NTSTATUS
1173 NTAPI
1174 SeAssignSecurityEx(
1175 _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor,
1176 _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor,
1177 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1178 _In_opt_ GUID *ObjectType,
1179 _In_ BOOLEAN IsDirectoryObject,
1180 _In_ ULONG AutoInheritFlags,
1181 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1182 _In_ PGENERIC_MAPPING GenericMapping,
1183 _In_ POOL_TYPE PoolType)
1184 {
1185 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1186 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1187 PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
1188 PTOKEN Token;
1189 ULONG OwnerLength;
1190 ULONG GroupLength;
1191 ULONG DaclLength;
1192 ULONG SaclLength;
1193 ULONG Length;
1194 SECURITY_DESCRIPTOR_CONTROL Control = 0;
1195 ULONG Current;
1196 PSID Owner = NULL;
1197 PSID Group = NULL;
1198 PACL Dacl = NULL;
1199 PACL Sacl = NULL;
1200
1201 DBG_UNREFERENCED_PARAMETER(ObjectType);
1202 DBG_UNREFERENCED_PARAMETER(AutoInheritFlags);
1203 DBG_UNREFERENCED_PARAMETER(GenericMapping);
1204 UNREFERENCED_PARAMETER(PoolType);
1205
1206 PAGED_CODE();
1207
1208 *NewDescriptor = NULL;
1209
1210 if (!ARGUMENT_PRESENT(SubjectContext))
1211 {
1212 return STATUS_NO_TOKEN;
1213 }
1214
1215 /* Lock subject context */
1216 SeLockSubjectContext(SubjectContext);
1217
1218 if (SubjectContext->ClientToken != NULL)
1219 {
1220 Token = SubjectContext->ClientToken;
1221 }
1222 else
1223 {
1224 Token = SubjectContext->PrimaryToken;
1225 }
1226
1227 /* Inherit the Owner SID */
1228 if (ExplicitDescriptor != NULL)
1229 {
1230 DPRINT("Use explicit owner sid!\n");
1231 Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
1232 }
1233 if (!Owner)
1234 {
1235 DPRINT("Use token owner sid!\n");
1236 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1237 }
1238
1239 OwnerLength = RtlLengthSid(Owner);
1240 NT_ASSERT(OwnerLength % sizeof(ULONG) == 0);
1241
1242 /* Inherit the Group SID */
1243 if (ExplicitDescriptor != NULL)
1244 {
1245 Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1246 }
1247 if (!Group)
1248 {
1249 DPRINT("Use token group sid!\n");
1250 Group = Token->PrimaryGroup;
1251 }
1252 if (!Group)
1253 {
1254 SeUnlockSubjectContext(SubjectContext);
1255 return STATUS_INVALID_PRIMARY_GROUP;
1256 }
1257
1258 GroupLength = RtlLengthSid(Group);
1259 NT_ASSERT(GroupLength % sizeof(ULONG) == 0);
1260
1261 /* Inherit the DACL */
1262 if (ExplicitDescriptor != NULL &&
1263 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
1264 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
1265 {
1266 DPRINT("Use explicit DACL!\n");
1267 Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1268 Control |= SE_DACL_PRESENT;
1269 }
1270 else if (ParentDescriptor != NULL &&
1271 (ParentDescriptor->Control & SE_DACL_PRESENT))
1272 {
1273 DPRINT("Use parent DACL!\n");
1274 /* FIXME: Inherit */
1275 Dacl = SepGetDaclFromDescriptor(ParentDescriptor);
1276 Control |= SE_DACL_PRESENT;
1277 }
1278 else if (Token->DefaultDacl)
1279 {
1280 DPRINT("Use token default DACL!\n");
1281 Dacl = Token->DefaultDacl;
1282 Control |= SE_DACL_PRESENT;
1283 }
1284
1285 DaclLength = (Dacl != NULL) ? Dacl->AclSize : 0;
1286 NT_ASSERT(DaclLength % sizeof(ULONG) == 0);
1287
1288 /* Inherit the SACL */
1289 if (ExplicitDescriptor != NULL &&
1290 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
1291 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
1292 {
1293 DPRINT("Use explicit SACL!\n");
1294 Sacl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1295 Control |= SE_SACL_PRESENT;
1296 }
1297 else if (ParentDescriptor != NULL &&
1298 (ParentDescriptor->Control & SE_SACL_PRESENT))
1299 {
1300 DPRINT("Use parent SACL!\n");
1301 /* FIXME: Inherit */
1302 Sacl = SepGetSaclFromDescriptor(ParentDescriptor);
1303 Control |= SE_SACL_PRESENT;
1304 }
1305
1306 SaclLength = (Sacl != NULL) ? Sacl->AclSize : 0;
1307 NT_ASSERT(SaclLength % sizeof(ULONG) == 0);
1308
1309 /* Allocate and initialize the new security descriptor */
1310 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1311 OwnerLength + GroupLength + DaclLength + SaclLength;
1312
1313 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1314 sizeof(SECURITY_DESCRIPTOR),
1315 OwnerLength,
1316 GroupLength,
1317 DaclLength,
1318 SaclLength);
1319
1320 Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1321 if (Descriptor == NULL)
1322 {
1323 DPRINT1("ExAlloctePool() failed\n");
1324 SeUnlockSubjectContext(SubjectContext);
1325 return STATUS_INSUFFICIENT_RESOURCES;
1326 }
1327
1328 RtlZeroMemory(Descriptor, Length);
1329 RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1330
1331 Descriptor->Control = Control | SE_SELF_RELATIVE;
1332
1333 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1334
1335 if (SaclLength != 0)
1336 {
1337 RtlCopyMemory((PUCHAR)Descriptor + Current, Sacl, SaclLength);
1338 Descriptor->Sacl = Current;
1339 Current += SaclLength;
1340 }
1341
1342 if (DaclLength != 0)
1343 {
1344 RtlCopyMemory((PUCHAR)Descriptor + Current, Dacl, DaclLength);
1345 Descriptor->Dacl = Current;
1346 Current += DaclLength;
1347 }
1348
1349 if (OwnerLength != 0)
1350 {
1351 RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1352 Descriptor->Owner = Current;
1353 Current += OwnerLength;
1354 DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1355 }
1356 else
1357 {
1358 DPRINT("Owner of %p is zero length\n", Descriptor);
1359 }
1360
1361 if (GroupLength != 0)
1362 {
1363 RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1364 Descriptor->Group = Current;
1365 }
1366
1367 /* Unlock subject context */
1368 SeUnlockSubjectContext(SubjectContext);
1369
1370 *NewDescriptor = Descriptor;
1371
1372 DPRINT("Descriptor %p\n", Descriptor);
1373 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1374
1375 return STATUS_SUCCESS;
1376 }
1377
1378 /*
1379 * @implemented
1380 */
1381 _IRQL_requires_max_(PASSIVE_LEVEL)
1382 NTSTATUS
1383 NTAPI
1384 SeAssignSecurity(
1385 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor,
1386 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor,
1387 _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1388 _In_ BOOLEAN IsDirectoryObject,
1389 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1390 _In_ PGENERIC_MAPPING GenericMapping,
1391 _In_ POOL_TYPE PoolType)
1392 {
1393 PAGED_CODE();
1394
1395 return SeAssignSecurityEx(ParentDescriptor,
1396 ExplicitDescriptor,
1397 NewDescriptor,
1398 NULL,
1399 IsDirectoryObject,
1400 0,
1401 SubjectContext,
1402 GenericMapping,
1403 PoolType);
1404 }
1405
1406 /* EOF */