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