* Sync up to trunk head (r60691).
[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 NTSTATUS NTAPI
619 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
620 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
621 IN OUT PULONG Length,
622 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
623 {
624 PISECURITY_DESCRIPTOR ObjectSd;
625 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
626 PSID Owner = NULL;
627 PSID Group = NULL;
628 PACL Dacl = NULL;
629 PACL Sacl = NULL;
630 ULONG OwnerLength = 0;
631 ULONG GroupLength = 0;
632 ULONG DaclLength = 0;
633 ULONG SaclLength = 0;
634 ULONG Control = 0;
635 ULONG_PTR Current;
636 ULONG SdLength;
637
638 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
639
640 if (*ObjectsSecurityDescriptor == NULL)
641 {
642 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
643 {
644 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
645 return STATUS_BUFFER_TOO_SMALL;
646 }
647
648 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
649 RtlCreateSecurityDescriptorRelative(RelSD,
650 SECURITY_DESCRIPTOR_REVISION);
651 return STATUS_SUCCESS;
652 }
653
654 ObjectSd = *ObjectsSecurityDescriptor;
655
656 /* Calculate the required security descriptor length */
657 Control = SE_SELF_RELATIVE;
658 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
659 (ObjectSd->Owner != NULL))
660 {
661 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
662 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
663 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
664 }
665
666 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
667 (ObjectSd->Group != NULL))
668 {
669 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
670 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
671 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
672 }
673
674 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
675 (ObjectSd->Control & SE_DACL_PRESENT))
676 {
677 if (ObjectSd->Dacl != NULL)
678 {
679 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
680 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
681 }
682
683 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
684 }
685
686 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
687 (ObjectSd->Control & SE_SACL_PRESENT))
688 {
689 if (ObjectSd->Sacl != NULL)
690 {
691 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
692 SaclLength = ROUND_UP(Sacl->AclSize, 4);
693 }
694
695 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
696 }
697
698 SdLength = OwnerLength + GroupLength + DaclLength +
699 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
700 if (*Length < SdLength)
701 {
702 *Length = SdLength;
703 return STATUS_BUFFER_TOO_SMALL;
704 }
705
706 /* Build the new security descrtiptor */
707 RtlCreateSecurityDescriptorRelative(RelSD,
708 SECURITY_DESCRIPTOR_REVISION);
709 RelSD->Control = (USHORT)Control;
710
711 Current = (ULONG_PTR)(RelSD + 1);
712
713 if (OwnerLength != 0)
714 {
715 RtlCopyMemory((PVOID)Current,
716 Owner,
717 OwnerLength);
718 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
719 Current += OwnerLength;
720 }
721
722 if (GroupLength != 0)
723 {
724 RtlCopyMemory((PVOID)Current,
725 Group,
726 GroupLength);
727 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
728 Current += GroupLength;
729 }
730
731 if (DaclLength != 0)
732 {
733 RtlCopyMemory((PVOID)Current,
734 Dacl,
735 DaclLength);
736 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
737 Current += DaclLength;
738 }
739
740 if (SaclLength != 0)
741 {
742 RtlCopyMemory((PVOID)Current,
743 Sacl,
744 SaclLength);
745 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
746 Current += SaclLength;
747 }
748
749 *Length = SdLength;
750
751 return STATUS_SUCCESS;
752 }
753
754 /*
755 * @implemented
756 */
757 NTSTATUS
758 NTAPI
759 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
760 IN KPROCESSOR_MODE CurrentMode,
761 IN BOOLEAN CaptureIfKernelMode)
762 {
763 PAGED_CODE();
764
765 /*
766 * WARNING! You need to call this function with the same value for CurrentMode
767 * and CaptureIfKernelMode that you previously passed to
768 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
769 */
770 if (CapturedSecurityDescriptor != NULL &&
771 (CurrentMode != KernelMode ||
772 (CurrentMode == KernelMode && CaptureIfKernelMode)))
773 {
774 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
775 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
776 }
777
778 return STATUS_SUCCESS;
779 }
780
781 /*
782 * @implemented
783 */
784 NTSTATUS NTAPI
785 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
786 IN PSECURITY_INFORMATION _SecurityInformation,
787 IN PSECURITY_DESCRIPTOR _SecurityDescriptor,
788 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
789 IN POOL_TYPE PoolType,
790 IN PGENERIC_MAPPING GenericMapping)
791 {
792 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd;
793 PISECURITY_DESCRIPTOR_RELATIVE NewSd;
794 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
795 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
796 PSID Owner = 0;
797 PSID Group = 0;
798 PACL Dacl = 0;
799 PACL Sacl = 0;
800 ULONG OwnerLength = 0;
801 ULONG GroupLength = 0;
802 ULONG DaclLength = 0;
803 ULONG SaclLength = 0;
804 ULONG Control = 0;
805 ULONG Current;
806 SECURITY_INFORMATION SecurityInformation;
807
808 ObjectSd = *ObjectsSecurityDescriptor;
809
810 /* The object does not have a security descriptor. */
811 if (!ObjectSd)
812 return STATUS_NO_SECURITY_ON_OBJECT;
813
814 ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
815
816 SecurityInformation = *_SecurityInformation;
817
818 /* Get owner and owner size */
819 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
820 {
821 if (SecurityDescriptor->Owner != NULL)
822 {
823 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
824 Owner = (PSID)((ULONG_PTR)RelSD->Owner +
825 (ULONG_PTR)SecurityDescriptor);
826 else
827 Owner = (PSID)SecurityDescriptor->Owner;
828 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
829 }
830
831 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
832 }
833 else
834 {
835 if (ObjectSd->Owner)
836 {
837 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
838 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
839 }
840
841 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
842 }
843
844 /* Get group and group size */
845 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
846 {
847 if (SecurityDescriptor->Group != NULL)
848 {
849 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
850 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
851 (ULONG_PTR)SecurityDescriptor);
852 else
853 Group = (PSID)SecurityDescriptor->Group;
854 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
855 }
856
857 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
858 }
859 else
860 {
861 if (ObjectSd->Group)
862 {
863 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
864 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
865 }
866
867 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
868 }
869
870 /* Get DACL and DACL size */
871 if (SecurityInformation & DACL_SECURITY_INFORMATION)
872 {
873 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
874 (SecurityDescriptor->Dacl != NULL))
875 {
876 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
877 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
878 (ULONG_PTR)SecurityDescriptor);
879 else
880 Dacl = (PACL)SecurityDescriptor->Dacl;
881
882 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
883 }
884
885 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
886 }
887 else
888 {
889 if ((ObjectSd->Control & SE_DACL_PRESENT) && (ObjectSd->Dacl))
890 {
891 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
892 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
893 }
894
895 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
896 }
897
898 /* Get SACL and SACL size */
899 if (SecurityInformation & SACL_SECURITY_INFORMATION)
900 {
901 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
902 (SecurityDescriptor->Sacl != NULL))
903 {
904 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
905 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
906 (ULONG_PTR)SecurityDescriptor);
907 else
908 Sacl = (PACL)SecurityDescriptor->Sacl;
909 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
910 }
911
912 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
913 }
914 else
915 {
916 if ((ObjectSd->Control & SE_SACL_PRESENT) && (ObjectSd->Sacl))
917 {
918 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
919 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
920 }
921
922 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
923 }
924
925 NewSd = ExAllocatePool(NonPagedPool,
926 sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength +
927 DaclLength + SaclLength);
928 if (NewSd == NULL)
929 {
930 ObDereferenceObject(Object);
931 return STATUS_INSUFFICIENT_RESOURCES;
932 }
933
934 RtlCreateSecurityDescriptor(NewSd,
935 SECURITY_DESCRIPTOR_REVISION1);
936
937 /* We always build a self-relative descriptor */
938 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
939
940 Current = sizeof(SECURITY_DESCRIPTOR);
941
942 if (OwnerLength != 0)
943 {
944 RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
945 NewSd->Owner = Current;
946 Current += OwnerLength;
947 }
948
949 if (GroupLength != 0)
950 {
951 RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
952 NewSd->Group = Current;
953 Current += GroupLength;
954 }
955
956 if (DaclLength != 0)
957 {
958 RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
959 NewSd->Dacl = Current;
960 Current += DaclLength;
961 }
962
963 if (SaclLength != 0)
964 {
965 RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
966 NewSd->Sacl = Current;
967 Current += SaclLength;
968 }
969
970 *ObjectsSecurityDescriptor = NewSd;
971 return STATUS_SUCCESS;
972 }
973
974 /*
975 * @unimplemented
976 */
977 NTSTATUS
978 NTAPI
979 SeSetSecurityDescriptorInfoEx(IN PVOID Object OPTIONAL,
980 IN PSECURITY_INFORMATION SecurityInformation,
981 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
982 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
983 IN ULONG AutoInheritFlags,
984 IN POOL_TYPE PoolType,
985 IN PGENERIC_MAPPING GenericMapping)
986 {
987 PISECURITY_DESCRIPTOR ObjectSd = *ObjectsSecurityDescriptor;
988
989 /* The object does not have a security descriptor. */
990 if (!ObjectSd)
991 return STATUS_NO_SECURITY_ON_OBJECT;
992
993 UNIMPLEMENTED;
994 return STATUS_NOT_IMPLEMENTED;
995 }
996
997
998 /*
999 * @implemented
1000 */
1001 BOOLEAN NTAPI
1002 SeValidSecurityDescriptor(IN ULONG Length,
1003 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
1004 {
1005 ULONG SdLength;
1006 PISID Sid;
1007 PACL Acl;
1008 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
1009
1010 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1011 {
1012 DPRINT1("Invalid Security Descriptor revision\n");
1013 return FALSE;
1014 }
1015
1016 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1017 {
1018 DPRINT1("Invalid Security Descriptor revision\n");
1019 return FALSE;
1020 }
1021
1022 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1023 {
1024 DPRINT1("No self-relative Security Descriptor\n");
1025 return FALSE;
1026 }
1027
1028 SdLength = sizeof(SECURITY_DESCRIPTOR);
1029
1030 /* Check Owner SID */
1031 if (SecurityDescriptor->Owner)
1032 {
1033 DPRINT1("No Owner SID\n");
1034 return FALSE;
1035 }
1036
1037 if (SecurityDescriptor->Owner % sizeof(ULONG))
1038 {
1039 DPRINT1("Invalid Owner SID alignment\n");
1040 return FALSE;
1041 }
1042
1043 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
1044 if (Sid->Revision != SID_REVISION)
1045 {
1046 DPRINT1("Invalid Owner SID revision\n");
1047 return FALSE;
1048 }
1049
1050 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1051 if (Length < SdLength)
1052 {
1053 DPRINT1("Invalid Owner SID size\n");
1054 return FALSE;
1055 }
1056
1057 /* Check Group SID */
1058 if (SecurityDescriptor->Group)
1059 {
1060 if (SecurityDescriptor->Group % sizeof(ULONG))
1061 {
1062 DPRINT1("Invalid Group SID alignment\n");
1063 return FALSE;
1064 }
1065
1066 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
1067 if (Sid->Revision != SID_REVISION)
1068 {
1069 DPRINT1("Invalid Group SID revision\n");
1070 return FALSE;
1071 }
1072
1073 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1074 if (Length < SdLength)
1075 {
1076 DPRINT1("Invalid Group SID size\n");
1077 return FALSE;
1078 }
1079 }
1080
1081 /* Check DACL */
1082 if (SecurityDescriptor->Dacl)
1083 {
1084 if (SecurityDescriptor->Dacl % sizeof(ULONG))
1085 {
1086 DPRINT1("Invalid DACL alignment\n");
1087 return FALSE;
1088 }
1089
1090 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
1091 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1092 (Acl->AclRevision > MAX_ACL_REVISION))
1093 {
1094 DPRINT1("Invalid DACL revision\n");
1095 return FALSE;
1096 }
1097
1098 SdLength += Acl->AclSize;
1099 if (Length < SdLength)
1100 {
1101 DPRINT1("Invalid DACL size\n");
1102 return FALSE;
1103 }
1104 }
1105
1106 /* Check SACL */
1107 if (SecurityDescriptor->Sacl)
1108 {
1109 if (SecurityDescriptor->Sacl % sizeof(ULONG))
1110 {
1111 DPRINT1("Invalid SACL alignment\n");
1112 return FALSE;
1113 }
1114
1115 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
1116 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1117 (Acl->AclRevision > MAX_ACL_REVISION))
1118 {
1119 DPRINT1("Invalid SACL revision\n");
1120 return FALSE;
1121 }
1122
1123 SdLength += Acl->AclSize;
1124 if (Length < SdLength)
1125 {
1126 DPRINT1("Invalid SACL size\n");
1127 return FALSE;
1128 }
1129 }
1130
1131 return TRUE;
1132 }
1133
1134 /*
1135 * @implemented
1136 */
1137 NTSTATUS NTAPI
1138 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
1139 {
1140 PAGED_CODE();
1141
1142 if (*SecurityDescriptor != NULL)
1143 {
1144 ExFreePoolWithTag(*SecurityDescriptor, TAG_SD);
1145 *SecurityDescriptor = NULL;
1146 }
1147
1148 return STATUS_SUCCESS;
1149 }
1150
1151
1152
1153 /*
1154 * @unimplemented
1155 */
1156 NTSTATUS NTAPI
1157 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
1158 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
1159 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
1160 IN GUID *ObjectType OPTIONAL,
1161 IN BOOLEAN IsDirectoryObject,
1162 IN ULONG AutoInheritFlags,
1163 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
1164 IN PGENERIC_MAPPING GenericMapping,
1165 IN POOL_TYPE PoolType)
1166 {
1167 UNIMPLEMENTED;
1168 return STATUS_NOT_IMPLEMENTED;
1169 }
1170
1171 /*
1172 * @implemented
1173 */
1174 NTSTATUS NTAPI
1175 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
1176 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
1177 PSECURITY_DESCRIPTOR *NewDescriptor,
1178 BOOLEAN IsDirectoryObject,
1179 PSECURITY_SUBJECT_CONTEXT SubjectContext,
1180 PGENERIC_MAPPING GenericMapping,
1181 POOL_TYPE PoolType)
1182 {
1183 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1184 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1185 PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
1186 PTOKEN Token;
1187 ULONG OwnerLength = 0;
1188 ULONG GroupLength = 0;
1189 ULONG DaclLength = 0;
1190 ULONG SaclLength = 0;
1191 ULONG Length = 0;
1192 ULONG Control = 0;
1193 ULONG Current;
1194 PSID Owner = NULL;
1195 PSID Group = NULL;
1196 PACL Dacl = NULL;
1197 PACL Sacl = NULL;
1198
1199 PAGED_CODE();
1200
1201 /* Lock subject context */
1202 SeLockSubjectContext(SubjectContext);
1203
1204 if (SubjectContext->ClientToken != NULL)
1205 {
1206 Token = SubjectContext->ClientToken;
1207 }
1208 else
1209 {
1210 Token = SubjectContext->PrimaryToken;
1211 }
1212
1213 /* Inherit the Owner SID */
1214 if (ExplicitDescriptor != NULL)
1215 {
1216 DPRINT("Use explicit owner sid!\n");
1217 Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
1218 }
1219
1220 if (!Owner)
1221 {
1222 if (Token != NULL)
1223 {
1224 DPRINT("Use token owner sid!\n");
1225 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1226 }
1227 else
1228 {
1229 DPRINT("Use default owner sid!\n");
1230 Owner = SeLocalSystemSid;
1231 }
1232
1233 Control |= SE_OWNER_DEFAULTED;
1234 }
1235
1236 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
1237
1238 /* Inherit the Group SID */
1239 if (ExplicitDescriptor != NULL)
1240 {
1241 Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1242 }
1243
1244 if (!Group)
1245 {
1246 if (Token != NULL)
1247 {
1248 DPRINT("Use token group sid!\n");
1249 Group = Token->PrimaryGroup;
1250 }
1251 else
1252 {
1253 DPRINT("Use default group sid!\n");
1254 Group = SeLocalSystemSid;
1255 }
1256
1257 Control |= SE_GROUP_DEFAULTED;
1258 }
1259
1260 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
1261
1262 /* Inherit the DACL */
1263 if (ExplicitDescriptor != NULL &&
1264 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
1265 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
1266 {
1267 DPRINT("Use explicit DACL!\n");
1268 Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1269 Control |= SE_DACL_PRESENT;
1270 }
1271 else if (ParentDescriptor != NULL &&
1272 (ParentDescriptor->Control & SE_DACL_PRESENT))
1273 {
1274 DPRINT("Use parent DACL!\n");
1275 /* FIXME: Inherit */
1276 Dacl = SepGetDaclFromDescriptor(ParentDescriptor);
1277 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1278 }
1279 else if (Token != NULL && Token->DefaultDacl != NULL)
1280 {
1281 DPRINT("Use token default DACL!\n");
1282 /* FIXME: Inherit */
1283 Dacl = Token->DefaultDacl;
1284 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1285 }
1286 else
1287 {
1288 DPRINT("Use NULL DACL!\n");
1289 Dacl = NULL;
1290 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1291 }
1292
1293 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
1294
1295 /* Inherit the SACL */
1296 if (ExplicitDescriptor != NULL &&
1297 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
1298 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
1299 {
1300 DPRINT("Use explicit SACL!\n");
1301 Sacl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1302 Control |= SE_SACL_PRESENT;
1303 }
1304 else if (ParentDescriptor != NULL &&
1305 (ParentDescriptor->Control & SE_SACL_PRESENT))
1306 {
1307 DPRINT("Use parent SACL!\n");
1308 /* FIXME: Inherit */
1309 Sacl = SepGetSaclFromDescriptor(ParentDescriptor);
1310 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
1311 }
1312
1313 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
1314
1315 /* Allocate and initialize the new security descriptor */
1316 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1317 OwnerLength + GroupLength + DaclLength + SaclLength;
1318
1319 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1320 sizeof(SECURITY_DESCRIPTOR),
1321 OwnerLength,
1322 GroupLength,
1323 DaclLength,
1324 SaclLength);
1325
1326 Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1327 if (Descriptor == NULL)
1328 {
1329 DPRINT1("ExAlloctePool() failed\n");
1330 /* FIXME: Unlock subject context */
1331 return STATUS_INSUFFICIENT_RESOURCES;
1332 }
1333
1334 RtlZeroMemory(Descriptor, Length);
1335 RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1336
1337 Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
1338
1339 Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1340
1341 if (SaclLength != 0)
1342 {
1343 RtlCopyMemory((PUCHAR)Descriptor + Current, Sacl, SaclLength);
1344 Descriptor->Sacl = Current;
1345 Current += SaclLength;
1346 }
1347
1348 if (DaclLength != 0)
1349 {
1350 RtlCopyMemory((PUCHAR)Descriptor + Current, Dacl, DaclLength);
1351 Descriptor->Dacl = Current;
1352 Current += DaclLength;
1353 }
1354
1355 if (OwnerLength != 0)
1356 {
1357 RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1358 Descriptor->Owner = Current;
1359 Current += OwnerLength;
1360 DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1361 }
1362 else
1363 {
1364 DPRINT("Owner of %p is zero length\n", Descriptor);
1365 }
1366
1367 if (GroupLength != 0)
1368 {
1369 RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1370 Descriptor->Group = Current;
1371 }
1372
1373 /* Unlock subject context */
1374 SeUnlockSubjectContext(SubjectContext);
1375
1376 *NewDescriptor = Descriptor;
1377
1378 DPRINT("Descrptor %p\n", Descriptor);
1379 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1380
1381 return STATUS_SUCCESS;
1382 }
1383
1384 /* EOF */