[SHELL32]
[reactos.git] / reactos / lib / rtl / sd.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Security descriptor functions
5 * FILE: lib/rtl/sd.c
6 * PROGRAMER: David Welch <welch@cwcom.net>
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <rtl.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS ***************************************************************/
17
18
19 static VOID
20 RtlpQuerySecurityDescriptorPointers(IN PISECURITY_DESCRIPTOR SecurityDescriptor,
21 OUT PSID *Owner OPTIONAL,
22 OUT PSID *Group OPTIONAL,
23 OUT PACL *Sacl OPTIONAL,
24 OUT PACL *Dacl OPTIONAL)
25 {
26 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
27 {
28 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
29 if(Owner != NULL)
30 {
31 *Owner = ((RelSD->Owner != 0) ? (PSID)((ULONG_PTR)RelSD + RelSD->Owner) : NULL);
32 }
33 if(Group != NULL)
34 {
35 *Group = ((RelSD->Group != 0) ? (PSID)((ULONG_PTR)RelSD + RelSD->Group) : NULL);
36 }
37 if(Sacl != NULL)
38 {
39 *Sacl = (((RelSD->Control & SE_SACL_PRESENT) && (RelSD->Sacl != 0)) ?
40 (PSID)((ULONG_PTR)RelSD + RelSD->Sacl) : NULL);
41 }
42 if(Dacl != NULL)
43 {
44 *Dacl = (((RelSD->Control & SE_DACL_PRESENT) && (RelSD->Dacl != 0)) ?
45 (PSID)((ULONG_PTR)RelSD + RelSD->Dacl) : NULL);
46 }
47 }
48 else
49 {
50 if(Owner != NULL)
51 {
52 *Owner = SecurityDescriptor->Owner;
53 }
54 if(Group != NULL)
55 {
56 *Group = SecurityDescriptor->Group;
57 }
58 if(Sacl != NULL)
59 {
60 *Sacl = ((SecurityDescriptor->Control & SE_SACL_PRESENT) ? SecurityDescriptor->Sacl : NULL);
61 }
62 if(Dacl != NULL)
63 {
64 *Dacl = ((SecurityDescriptor->Control & SE_DACL_PRESENT) ? SecurityDescriptor->Dacl : NULL);
65 }
66 }
67 }
68
69 static VOID
70 RtlpQuerySecurityDescriptor(PISECURITY_DESCRIPTOR SecurityDescriptor,
71 PSID* Owner,
72 PULONG OwnerLength,
73 PSID* Group,
74 PULONG GroupLength,
75 PACL* Dacl,
76 PULONG DaclLength,
77 PACL* Sacl,
78 PULONG SaclLength)
79 {
80 RtlpQuerySecurityDescriptorPointers(SecurityDescriptor,
81 Owner,
82 Group,
83 Sacl,
84 Dacl);
85
86 if (Owner != NULL)
87 {
88 *OwnerLength = ((*Owner != NULL) ? ROUND_UP(RtlLengthSid(*Owner), 4) : 0);
89 }
90
91 if (Group != NULL)
92 {
93 *GroupLength = ((*Group != NULL) ? ROUND_UP(RtlLengthSid(*Group), 4) : 0);
94 }
95
96 if (Dacl != NULL)
97 {
98 *DaclLength = ((*Dacl != NULL) ? ROUND_UP((*Dacl)->AclSize, 4) : 0);
99 }
100
101 if (Sacl != NULL)
102 {
103 *SaclLength = ((*Sacl != NULL) ? ROUND_UP((*Sacl)->AclSize, 4) : 0);
104 }
105 }
106
107 /*
108 * @implemented
109 */
110 NTSTATUS NTAPI
111 RtlCreateSecurityDescriptor(OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
112 IN ULONG Revision)
113 {
114 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
115
116 PAGED_CODE_RTL();
117
118 if (Revision != SECURITY_DESCRIPTOR_REVISION1)
119 {
120 return STATUS_UNKNOWN_REVISION;
121 }
122
123 pSD->Revision = Revision;
124 pSD->Sbz1 = 0;
125 pSD->Control = 0;
126 pSD->Owner = NULL;
127 pSD->Group = NULL;
128 pSD->Sacl = NULL;
129 pSD->Dacl = NULL;
130
131 return STATUS_SUCCESS;
132 }
133
134 /*
135 * @implemented
136 */
137 NTSTATUS NTAPI
138 RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor,
139 OUT PSECURITY_DESCRIPTOR pDestinationSecurityDescriptor)
140 {
141 PSID Owner = NULL, Group = NULL;
142 PACL Dacl = NULL, Sacl = NULL;
143 BOOLEAN Defaulted, Present;
144 DWORD OwnerLength, GroupLength;
145 PISECURITY_DESCRIPTOR srcSD = pSourceSecurityDescriptor;
146 PISECURITY_DESCRIPTOR destSD = pDestinationSecurityDescriptor;
147
148 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
149 return STATUS_UNKNOWN_REVISION;
150
151 /* Copy non relative dependent data */
152 destSD->Revision = srcSD->Revision;
153 destSD->Sbz1 = srcSD->Sbz1;
154 destSD->Control = srcSD->Control;
155
156 /* Read relative data */
157 RtlGetOwnerSecurityDescriptor(srcSD, &Owner, &Defaulted);
158 OwnerLength = RtlLengthSid(Owner);
159 RtlGetGroupSecurityDescriptor(srcSD, &Group, &Defaulted);
160 GroupLength = RtlLengthSid(Group);
161 RtlGetDaclSecurityDescriptor(srcSD, &Present, &Dacl, &Defaulted);
162 RtlGetSaclSecurityDescriptor(srcSD, &Present, &Sacl, &Defaulted);
163
164 if (srcSD->Control & SE_SELF_RELATIVE)
165 {
166 destSD->Owner = srcSD->Owner;
167 RtlCopySid(OwnerLength, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
168
169 destSD->Group = srcSD->Group;
170 RtlCopySid(GroupLength, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
171
172 if (srcSD->Control & SE_DACL_PRESENT)
173 {
174 destSD->Dacl = srcSD->Dacl;
175
176 if(srcSD->Dacl != NULL && RtlValidAcl(srcSD->Dacl))
177 {
178 RtlCopyMemory(((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl, Dacl->AclSize);
179 }
180 }
181
182 if (srcSD->Control & SE_SACL_PRESENT)
183 {
184 destSD->Sacl = srcSD->Sacl;
185
186 if(srcSD->Sacl != NULL && RtlValidAcl(srcSD->Sacl))
187 {
188 RtlCopyMemory(((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl, Sacl->AclSize);
189 }
190 }
191 }
192 else
193 {
194 RtlCopySid(OwnerLength, destSD->Owner, Owner);
195 RtlCopySid(GroupLength, destSD->Group, Group);
196
197 if (srcSD->Control & SE_DACL_PRESENT)
198 {
199 destSD->Dacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, Dacl->AclSize);
200
201 if(srcSD->Dacl != NULL && RtlValidAcl(srcSD->Dacl))
202 {
203 RtlCopyMemory(destSD->Dacl, Dacl, Dacl->AclSize);
204 }
205 }
206
207 if (srcSD->Control & SE_SACL_PRESENT)
208 {
209 destSD->Sacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, Sacl->AclSize);
210
211 if(srcSD->Sacl != NULL && RtlValidAcl(srcSD->Sacl))
212 {
213 RtlCopyMemory(destSD->Sacl, Sacl, Sacl->AclSize);
214 }
215 }
216 }
217
218 return STATUS_SUCCESS;
219 }
220
221
222 NTSTATUS NTAPI
223 RtlCreateSecurityDescriptorRelative (OUT PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
224 IN ULONG Revision)
225 {
226 PAGED_CODE_RTL();
227
228 if (Revision != SECURITY_DESCRIPTOR_REVISION1)
229 {
230 return STATUS_UNKNOWN_REVISION;
231 }
232
233 SecurityDescriptor->Revision = Revision;
234 SecurityDescriptor->Sbz1 = 0;
235 SecurityDescriptor->Control = SE_SELF_RELATIVE;
236 SecurityDescriptor->Owner = 0;
237 SecurityDescriptor->Group = 0;
238 SecurityDescriptor->Sacl = 0;
239 SecurityDescriptor->Dacl = 0;
240
241 return STATUS_SUCCESS;
242 }
243
244
245 /*
246 * @implemented
247 */
248 ULONG NTAPI
249 RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
250 {
251 PSID Owner, Group;
252 PACL Sacl, Dacl;
253 ULONG Length = sizeof(SECURITY_DESCRIPTOR);
254
255 PAGED_CODE_RTL();
256
257 RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)SecurityDescriptor,
258 &Owner,
259 &Group,
260 &Sacl,
261 &Dacl);
262
263 if (Owner != NULL)
264 {
265 Length += ROUND_UP(RtlLengthSid(Owner), 4);
266 }
267
268 if (Group != NULL)
269 {
270 Length += ROUND_UP(RtlLengthSid(Group), 4);
271 }
272
273 if (Dacl != NULL)
274 {
275 Length += ROUND_UP(Dacl->AclSize, 4);
276 }
277
278 if (Sacl != NULL)
279 {
280 Length += ROUND_UP(Sacl->AclSize, 4);
281 }
282
283 return Length;
284 }
285
286
287 /*
288 * @implemented
289 */
290 NTSTATUS NTAPI
291 RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
292 OUT PBOOLEAN DaclPresent,
293 OUT PACL* Dacl,
294 OUT PBOOLEAN DaclDefaulted)
295 {
296 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
297
298 PAGED_CODE_RTL();
299
300 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
301 {
302 return STATUS_UNKNOWN_REVISION;
303 }
304
305 if (!(pSD->Control & SE_DACL_PRESENT))
306 {
307 *DaclPresent = FALSE;
308 return STATUS_SUCCESS;
309 }
310 *DaclPresent = TRUE;
311
312 RtlpQuerySecurityDescriptorPointers(pSD,
313 NULL,
314 NULL,
315 NULL,
316 Dacl);
317
318 *DaclDefaulted = ((pSD->Control & SE_DACL_DEFAULTED) ? TRUE : FALSE);
319
320 return STATUS_SUCCESS;
321 }
322
323
324 /*
325 * @implemented
326 */
327 NTSTATUS NTAPI
328 RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
329 IN BOOLEAN DaclPresent,
330 IN PACL Dacl,
331 IN BOOLEAN DaclDefaulted)
332 {
333 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
334
335 PAGED_CODE_RTL();
336
337 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
338 {
339 return STATUS_UNKNOWN_REVISION;
340 }
341
342 if (pSD->Control & SE_SELF_RELATIVE)
343 {
344 return STATUS_BAD_DESCRIPTOR_FORMAT;
345 }
346
347 if (!DaclPresent)
348 {
349 pSD->Control = pSD->Control & ~(SE_DACL_PRESENT);
350 return STATUS_SUCCESS;
351 }
352
353 pSD->Dacl = Dacl;
354 pSD->Control |= SE_DACL_PRESENT;
355 pSD->Control &= ~(SE_DACL_DEFAULTED);
356
357 if (DaclDefaulted)
358 {
359 pSD->Control |= SE_DACL_DEFAULTED;
360 }
361
362 return STATUS_SUCCESS;
363 }
364
365
366 /*
367 * @implemented
368 */
369 BOOLEAN NTAPI
370 RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
371 {
372 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
373 PSID Owner, Group;
374 PACL Sacl, Dacl;
375
376 PAGED_CODE_RTL();
377
378 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
379 {
380 return FALSE;
381 }
382
383 RtlpQuerySecurityDescriptorPointers(pSD,
384 &Owner,
385 &Group,
386 &Sacl,
387 &Dacl);
388
389 if ((Owner != NULL && !RtlValidSid(Owner)) ||
390 (Group != NULL && !RtlValidSid(Group)) ||
391 (Sacl != NULL && !RtlValidAcl(Sacl)) ||
392 (Dacl != NULL && !RtlValidAcl(Dacl)))
393 {
394 return FALSE;
395 }
396
397 return TRUE;
398 }
399
400
401 /*
402 * @implemented
403 */
404 NTSTATUS NTAPI
405 RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
406 IN PSID Owner,
407 IN BOOLEAN OwnerDefaulted)
408 {
409 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
410
411 PAGED_CODE_RTL();
412
413 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
414 {
415 return STATUS_UNKNOWN_REVISION;
416 }
417
418 if (pSD->Control & SE_SELF_RELATIVE)
419 {
420 return STATUS_BAD_DESCRIPTOR_FORMAT;
421 }
422
423 pSD->Owner = Owner;
424 pSD->Control &= ~(SE_OWNER_DEFAULTED);
425
426 if (OwnerDefaulted)
427 {
428 pSD->Control |= SE_OWNER_DEFAULTED;
429 }
430
431 return STATUS_SUCCESS;
432 }
433
434
435 /*
436 * @implemented
437 */
438 NTSTATUS NTAPI
439 RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
440 OUT PSID* Owner,
441 OUT PBOOLEAN OwnerDefaulted)
442 {
443 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
444
445 PAGED_CODE_RTL();
446
447 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
448 {
449 return STATUS_UNKNOWN_REVISION;
450 }
451
452 RtlpQuerySecurityDescriptorPointers(pSD,
453 Owner,
454 NULL,
455 NULL,
456 NULL);
457
458 *OwnerDefaulted = ((pSD->Control & SE_OWNER_DEFAULTED) ? TRUE : FALSE);
459
460 return STATUS_SUCCESS;
461 }
462
463
464 /*
465 * @implemented
466 */
467 NTSTATUS NTAPI
468 RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
469 IN PSID Group,
470 IN BOOLEAN GroupDefaulted)
471 {
472 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
473
474 PAGED_CODE_RTL();
475
476 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
477 {
478 return STATUS_UNKNOWN_REVISION;
479 }
480
481 if (pSD->Control & SE_SELF_RELATIVE)
482 {
483 return STATUS_BAD_DESCRIPTOR_FORMAT;
484 }
485
486 pSD->Group = Group;
487 pSD->Control &= ~(SE_GROUP_DEFAULTED);
488 if (GroupDefaulted)
489 {
490 pSD->Control |= SE_GROUP_DEFAULTED;
491 }
492
493 return STATUS_SUCCESS;
494 }
495
496
497 /*
498 * @implemented
499 */
500 NTSTATUS NTAPI
501 RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
502 OUT PSID* Group,
503 OUT PBOOLEAN GroupDefaulted)
504 {
505 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
506
507 PAGED_CODE_RTL();
508
509 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
510 {
511 return STATUS_UNKNOWN_REVISION;
512 }
513
514 RtlpQuerySecurityDescriptorPointers(pSD,
515 NULL,
516 Group,
517 NULL,
518 NULL);
519
520 *GroupDefaulted = ((pSD->Control & SE_GROUP_DEFAULTED) ? TRUE : FALSE);
521
522 return STATUS_SUCCESS;
523 }
524
525
526 /*
527 * @implemented
528 */
529 NTSTATUS NTAPI
530 RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSD,
531 OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
532 IN OUT PULONG BufferLength)
533 {
534 PSID Owner;
535 PSID Group;
536 PACL Sacl;
537 PACL Dacl;
538 ULONG OwnerLength;
539 ULONG GroupLength;
540 ULONG SaclLength;
541 ULONG DaclLength;
542 ULONG TotalLength;
543 ULONG_PTR Current;
544 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
545 PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
546
547 PAGED_CODE_RTL();
548
549 RtlpQuerySecurityDescriptor(pAbsSD,
550 &Owner,
551 &OwnerLength,
552 &Group,
553 &GroupLength,
554 &Dacl,
555 &DaclLength,
556 &Sacl,
557 &SaclLength);
558
559 TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength + SaclLength + DaclLength;
560 if (*BufferLength < TotalLength)
561 {
562 *BufferLength = TotalLength;
563 return STATUS_BUFFER_TOO_SMALL;
564 }
565
566 RtlZeroMemory(pRelSD,
567 TotalLength);
568
569 pRelSD->Revision = pAbsSD->Revision;
570 pRelSD->Sbz1 = pAbsSD->Sbz1;
571 pRelSD->Control = pAbsSD->Control | SE_SELF_RELATIVE;
572
573 Current = (ULONG_PTR)(pRelSD + 1);
574
575 if (SaclLength != 0)
576 {
577 RtlCopyMemory((PVOID)Current,
578 Sacl,
579 SaclLength);
580 pRelSD->Sacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
581 Current += SaclLength;
582 }
583
584 if (DaclLength != 0)
585 {
586 RtlCopyMemory((PVOID)Current,
587 Dacl,
588 DaclLength);
589 pRelSD->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
590 Current += DaclLength;
591 }
592
593 if (OwnerLength != 0)
594 {
595 RtlCopyMemory((PVOID)Current,
596 Owner,
597 OwnerLength);
598 pRelSD->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
599 Current += OwnerLength;
600 }
601
602 if (GroupLength != 0)
603 {
604 RtlCopyMemory((PVOID)Current,
605 Group,
606 GroupLength);
607 pRelSD->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
608 }
609
610 return STATUS_SUCCESS;
611 }
612
613
614 /*
615 * @implemented
616 */
617 NTSTATUS NTAPI
618 RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
619 IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
620 IN PULONG BufferLength)
621 {
622 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
623
624 PAGED_CODE_RTL();
625
626 if (pAbsSD->Control & SE_SELF_RELATIVE)
627 {
628 return STATUS_BAD_DESCRIPTOR_FORMAT;
629 }
630
631 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
632 SelfRelativeSecurityDescriptor,
633 BufferLength);
634 }
635
636
637 /*
638 * @implemented
639 */
640 NTSTATUS NTAPI
641 RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
642 OUT PSECURITY_DESCRIPTOR_CONTROL Control,
643 OUT PULONG Revision)
644 {
645 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
646
647 PAGED_CODE_RTL();
648
649 *Revision = pSD->Revision;
650
651 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
652 {
653 return STATUS_UNKNOWN_REVISION;
654 }
655
656 *Control = pSD->Control;
657
658 return STATUS_SUCCESS;
659 }
660
661
662 /*
663 * @implemented
664 */
665 NTSTATUS NTAPI
666 RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
667 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
668 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
669 {
670 SECURITY_DESCRIPTOR_CONTROL const immutable
671 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
672 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
673 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
674 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
675 ;
676
677 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
678
679 PAGED_CODE_RTL();
680
681 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
682 {
683 return STATUS_UNKNOWN_REVISION;
684 }
685
686 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
687 return STATUS_INVALID_PARAMETER;
688
689 /* Zero the 'bits of interest' */
690 pSD->Control &= ~ControlBitsOfInterest;
691
692 /* Set the 'bits to set' */
693 pSD->Control |= (ControlBitsToSet & ControlBitsOfInterest);
694
695 return STATUS_SUCCESS;
696 }
697
698
699 /*
700 * @implemented
701 */
702 NTSTATUS NTAPI
703 RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
704 OUT PBOOLEAN SaclPresent,
705 OUT PACL *Sacl,
706 OUT PBOOLEAN SaclDefaulted)
707 {
708 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
709
710 PAGED_CODE_RTL();
711
712 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
713 {
714 return STATUS_UNKNOWN_REVISION;
715 }
716
717 if (!(pSD->Control & SE_SACL_PRESENT))
718 {
719 *SaclPresent = FALSE;
720 return STATUS_SUCCESS;
721 }
722 *SaclPresent = TRUE;
723
724 RtlpQuerySecurityDescriptorPointers(pSD,
725 NULL,
726 NULL,
727 Sacl,
728 NULL);
729
730 *SaclDefaulted = ((pSD->Control & SE_SACL_DEFAULTED) ? TRUE : FALSE);
731
732 return STATUS_SUCCESS;
733 }
734
735
736 /*
737 * @implemented
738 */
739 NTSTATUS NTAPI
740 RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
741 IN BOOLEAN SaclPresent,
742 IN PACL Sacl,
743 IN BOOLEAN SaclDefaulted)
744 {
745 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
746
747 PAGED_CODE_RTL();
748
749 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
750 {
751 return STATUS_UNKNOWN_REVISION;
752 }
753
754 if (pSD->Control & SE_SELF_RELATIVE)
755 {
756 return STATUS_BAD_DESCRIPTOR_FORMAT;
757 }
758
759 if (!SaclPresent)
760 {
761 pSD->Control &= ~(SE_SACL_PRESENT);
762 return STATUS_SUCCESS;
763 }
764
765 pSD->Sacl = Sacl;
766 pSD->Control |= SE_SACL_PRESENT;
767 pSD->Control &= ~(SE_SACL_DEFAULTED);
768
769 if (SaclDefaulted)
770 {
771 pSD->Control |= SE_SACL_DEFAULTED;
772 }
773
774 return STATUS_SUCCESS;
775 }
776
777
778 /*
779 * @implemented
780 */
781 NTSTATUS NTAPI
782 RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD,
783 OUT PSECURITY_DESCRIPTOR AbsoluteSD,
784 IN PULONG AbsoluteSDSize,
785 IN PACL Dacl,
786 IN PULONG DaclSize,
787 IN PACL Sacl,
788 IN PULONG SaclSize,
789 IN PSID Owner,
790 IN PULONG OwnerSize,
791 IN PSID PrimaryGroup,
792 IN PULONG PrimaryGroupSize)
793 {
794 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
795 PISECURITY_DESCRIPTOR pRelSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
796 ULONG OwnerLength;
797 ULONG GroupLength;
798 ULONG DaclLength;
799 ULONG SaclLength;
800 PSID pOwner;
801 PSID pGroup;
802 PACL pDacl;
803 PACL pSacl;
804
805 PAGED_CODE_RTL();
806
807 if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
808 {
809 return STATUS_UNKNOWN_REVISION;
810 }
811
812 if (!(pRelSD->Control & SE_SELF_RELATIVE))
813 {
814 return STATUS_BAD_DESCRIPTOR_FORMAT;
815 }
816
817 RtlpQuerySecurityDescriptor (pRelSD,
818 &pOwner,
819 &OwnerLength,
820 &pGroup,
821 &GroupLength,
822 &pDacl,
823 &DaclLength,
824 &pSacl,
825 &SaclLength);
826
827 if (OwnerLength > *OwnerSize ||
828 GroupLength > *PrimaryGroupSize ||
829 DaclLength > *DaclSize ||
830 SaclLength > *SaclSize)
831 {
832 *OwnerSize = OwnerLength;
833 *PrimaryGroupSize = GroupLength;
834 *DaclSize = DaclLength;
835 *SaclSize = SaclLength;
836 return STATUS_BUFFER_TOO_SMALL;
837 }
838
839 RtlCopyMemory (Owner, pOwner, OwnerLength);
840 RtlCopyMemory (PrimaryGroup, pGroup, GroupLength);
841 RtlCopyMemory (Dacl, pDacl, DaclLength);
842 RtlCopyMemory (Sacl, pSacl, SaclLength);
843
844 pAbsSD->Revision = pRelSD->Revision;
845 pAbsSD->Sbz1 = pRelSD->Sbz1;
846 pAbsSD->Control = pRelSD->Control & ~SE_SELF_RELATIVE;
847 pAbsSD->Owner = Owner;
848 pAbsSD->Group = PrimaryGroup;
849 pAbsSD->Dacl = Dacl;
850 pAbsSD->Sacl = Sacl;
851
852 *OwnerSize = OwnerLength;
853 *PrimaryGroupSize = GroupLength;
854 *DaclSize = DaclLength;
855 *SaclSize = SaclLength;
856
857 return STATUS_SUCCESS;
858 }
859
860
861 /*
862 * @implemented
863 */
864 NTSTATUS NTAPI
865 RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
866 OUT PULONG BufferSize)
867 {
868 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
869 PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
870 #ifdef _WIN64
871 PVOID DataStart, DataEnd;
872 ULONG DataSize;
873 LONG MoveDelta;
874 ULONG OwnerLength;
875 ULONG GroupLength;
876 ULONG DaclLength;
877 ULONG SaclLength;
878 #endif
879 PSID pOwner;
880 PSID pGroup;
881 PACL pDacl;
882 PACL pSacl;
883
884 PAGED_CODE_RTL();
885
886 if (SelfRelativeSD == NULL)
887 {
888 return STATUS_INVALID_PARAMETER_1;
889 }
890 if (BufferSize == NULL)
891 {
892 return STATUS_INVALID_PARAMETER_2;
893 }
894
895 if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
896 {
897 return STATUS_UNKNOWN_REVISION;
898 }
899 if (!(pRelSD->Control & SE_SELF_RELATIVE))
900 {
901 return STATUS_BAD_DESCRIPTOR_FORMAT;
902 }
903
904 #ifdef _WIN64
905
906 RtlpQuerySecurityDescriptor((PISECURITY_DESCRIPTOR)pRelSD,
907 &pOwner,
908 &OwnerLength,
909 &pGroup,
910 &GroupLength,
911 &pDacl,
912 &DaclLength,
913 &pSacl,
914 &SaclLength);
915
916 /* calculate the start and end of the data area, we simply just move the
917 data by the difference between the size of the relative and absolute
918 security descriptor structure */
919 DataStart = pOwner;
920 DataEnd = (PVOID)((ULONG_PTR)pOwner + OwnerLength);
921 if (pGroup != NULL)
922 {
923 if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || DataStart == NULL)
924 DataStart = pGroup;
925 if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
926 DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength);
927 }
928 if (pDacl != NULL)
929 {
930 if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || DataStart == NULL)
931 DataStart = pDacl;
932 if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
933 DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength);
934 }
935 if (pSacl != NULL)
936 {
937 if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || DataStart == NULL)
938 DataStart = pSacl;
939 if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
940 DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength);
941 }
942
943 ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart);
944
945 DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart);
946
947 if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize)
948 {
949 *BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize;
950 return STATUS_BUFFER_TOO_SMALL;
951 }
952
953 if (DataSize != 0)
954 {
955 /* if DataSize != 0 ther must be at least one SID or ACL in the security
956 descriptor! Also the data area must be located somewhere after the
957 end of the SECURITY_DESCRIPTOR_RELATIVE structure */
958 ASSERT(DataStart != NULL);
959 ASSERT((ULONG_PTR)DataStart >= (ULONG_PTR)(pRelSD + 1));
960
961 /* it's time to move the data */
962 RtlMoveMemory((PVOID)(pAbsSD + 1),
963 DataStart,
964 DataSize);
965
966 MoveDelta = (LONG)((LONG_PTR)(pAbsSD + 1) - (LONG_PTR)DataStart);
967
968 /* adjust the pointers if neccessary */
969 if (pOwner != NULL)
970 pAbsSD->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta);
971 else
972 pAbsSD->Owner = NULL;
973
974 if (pGroup != NULL)
975 pAbsSD->Group = (PSID)((LONG_PTR)pGroup + MoveDelta);
976 else
977 pAbsSD->Group = NULL;
978
979 if (pSacl != NULL)
980 pAbsSD->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta);
981 else
982 pAbsSD->Sacl = NULL;
983
984 if (pDacl != NULL)
985 pAbsSD->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta);
986 else
987 pAbsSD->Dacl = NULL;
988 }
989 else
990 {
991 /* all pointers must be NULL! */
992 ASSERT(pOwner == NULL);
993 ASSERT(pGroup == NULL);
994 ASSERT(pSacl == NULL);
995 ASSERT(pDacl == NULL);
996
997 pAbsSD->Owner = NULL;
998 pAbsSD->Group = NULL;
999 pAbsSD->Sacl = NULL;
1000 pAbsSD->Dacl = NULL;
1001 }
1002
1003 /* clear the self-relative flag */
1004 pAbsSD->Control &= ~SE_SELF_RELATIVE;
1005
1006 #else
1007
1008 RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)pRelSD,
1009 &pOwner,
1010 &pGroup,
1011 &pSacl,
1012 &pDacl);
1013
1014 /* clear the self-relative flag and simply convert the offsets to pointers */
1015 pAbsSD->Control &= ~SE_SELF_RELATIVE;
1016 pAbsSD->Owner = pOwner;
1017 pAbsSD->Group = pGroup;
1018 pAbsSD->Sacl = pSacl;
1019 pAbsSD->Dacl = pDacl;
1020
1021 #endif
1022
1023 return STATUS_SUCCESS;
1024 }
1025
1026
1027 /*
1028 * @implemented
1029 */
1030 BOOLEAN NTAPI
1031 RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
1032 IN ULONG SecurityDescriptorLength,
1033 IN SECURITY_INFORMATION RequiredInformation)
1034 {
1035 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptorInput;
1036
1037 PAGED_CODE_RTL();
1038
1039 if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE) ||
1040 pSD->Revision != SECURITY_DESCRIPTOR_REVISION1 ||
1041 !(pSD->Control & SE_SELF_RELATIVE))
1042 {
1043 return FALSE;
1044 }
1045
1046 if (pSD->Owner != 0)
1047 {
1048 PSID Owner = (PSID)((ULONG_PTR)pSD->Owner + (ULONG_PTR)pSD);
1049 if (!RtlValidSid(Owner))
1050 {
1051 return FALSE;
1052 }
1053 }
1054 else if (RequiredInformation & OWNER_SECURITY_INFORMATION)
1055 {
1056 return FALSE;
1057 }
1058
1059 if (pSD->Group != 0)
1060 {
1061 PSID Group = (PSID)((ULONG_PTR)pSD->Group + (ULONG_PTR)pSD);
1062 if (!RtlValidSid(Group))
1063 {
1064 return FALSE;
1065 }
1066 }
1067 else if (RequiredInformation & GROUP_SECURITY_INFORMATION)
1068 {
1069 return FALSE;
1070 }
1071
1072 if (pSD->Control & SE_DACL_PRESENT)
1073 {
1074 if (pSD->Dacl != 0 &&
1075 !RtlValidAcl((PACL)((ULONG_PTR)pSD->Dacl + (ULONG_PTR)pSD)))
1076 {
1077 return FALSE;
1078 }
1079 }
1080 else if (RequiredInformation & DACL_SECURITY_INFORMATION)
1081 {
1082 return FALSE;
1083 }
1084
1085 if (pSD->Control & SE_SACL_PRESENT)
1086 {
1087 if (pSD->Sacl != 0 &&
1088 !RtlValidAcl((PACL)((ULONG_PTR)pSD->Sacl + (ULONG_PTR)pSD)))
1089 {
1090 return FALSE;
1091 }
1092 }
1093 else if (RequiredInformation & SACL_SECURITY_INFORMATION)
1094 {
1095 return FALSE;
1096 }
1097
1098 return TRUE;
1099 }
1100
1101
1102 /*
1103 * @implemented
1104 */
1105 BOOLEAN NTAPI
1106 RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1107 OUT PUCHAR RMControl)
1108 {
1109 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1110
1111 PAGED_CODE_RTL();
1112
1113 if (!(pSD->Control & SE_RM_CONTROL_VALID))
1114 {
1115 *RMControl = 0;
1116 return FALSE;
1117 }
1118
1119 *RMControl = pSD->Sbz1;
1120
1121 return TRUE;
1122 }
1123
1124
1125 /*
1126 * @implemented
1127 */
1128 VOID NTAPI
1129 RtlSetSecurityDescriptorRMControl(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
1130 IN PUCHAR RMControl)
1131 {
1132 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1133
1134 PAGED_CODE_RTL();
1135
1136 if (RMControl == NULL)
1137 {
1138 pSD->Control &= ~SE_RM_CONTROL_VALID;
1139 pSD->Sbz1 = 0;
1140 }
1141 else
1142 {
1143 pSD->Control |= SE_RM_CONTROL_VALID;
1144 pSD->Sbz1 = *RMControl;
1145 }
1146 }
1147
1148
1149 /*
1150 * @implemented
1151 */
1152 NTSTATUS NTAPI
1153 RtlSetAttributesSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
1154 IN SECURITY_DESCRIPTOR_CONTROL Control,
1155 OUT PULONG Revision)
1156 {
1157 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1158
1159 PAGED_CODE_RTL();
1160
1161 *Revision = pSD->Revision;
1162
1163 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
1164 return STATUS_UNKNOWN_REVISION;
1165
1166 Control &=
1167 ~(SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED | SE_DACL_PRESENT |
1168 SE_DACL_DEFAULTED | SE_SACL_PRESENT | SE_SACL_DEFAULTED |
1169 SE_RM_CONTROL_VALID | SE_SELF_RELATIVE);
1170
1171 return RtlSetControlSecurityDescriptor(SecurityDescriptor,
1172 Control,
1173 Control);
1174 }
1175
1176 /* EOF */