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