WaveHdr prepare/unprepare/submit now gets handled within the context of the
[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 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
671
672 PAGED_CODE_RTL();
673
674 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
675 {
676 return STATUS_UNKNOWN_REVISION;
677 }
678
679 /* Zero the 'bits of interest' */
680 pSD->Control &= ~ControlBitsOfInterest;
681
682 /* Set the 'bits to set' */
683 pSD->Control |= (ControlBitsToSet & ControlBitsOfInterest);
684
685 return STATUS_SUCCESS;
686 }
687
688
689 /*
690 * @implemented
691 */
692 NTSTATUS NTAPI
693 RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
694 OUT PBOOLEAN SaclPresent,
695 OUT PACL *Sacl,
696 OUT PBOOLEAN SaclDefaulted)
697 {
698 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
699
700 PAGED_CODE_RTL();
701
702 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
703 {
704 return STATUS_UNKNOWN_REVISION;
705 }
706
707 if (!(pSD->Control & SE_SACL_PRESENT))
708 {
709 *SaclPresent = FALSE;
710 return STATUS_SUCCESS;
711 }
712 *SaclPresent = TRUE;
713
714 RtlpQuerySecurityDescriptorPointers(pSD,
715 NULL,
716 NULL,
717 Sacl,
718 NULL);
719
720 *SaclDefaulted = ((pSD->Control & SE_SACL_DEFAULTED) ? TRUE : FALSE);
721
722 return STATUS_SUCCESS;
723 }
724
725
726 /*
727 * @implemented
728 */
729 NTSTATUS NTAPI
730 RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
731 IN BOOLEAN SaclPresent,
732 IN PACL Sacl,
733 IN BOOLEAN SaclDefaulted)
734 {
735 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
736
737 PAGED_CODE_RTL();
738
739 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
740 {
741 return STATUS_UNKNOWN_REVISION;
742 }
743
744 if (pSD->Control & SE_SELF_RELATIVE)
745 {
746 return STATUS_BAD_DESCRIPTOR_FORMAT;
747 }
748
749 if (!SaclPresent)
750 {
751 pSD->Control &= ~(SE_SACL_PRESENT);
752 return STATUS_SUCCESS;
753 }
754
755 pSD->Sacl = Sacl;
756 pSD->Control |= SE_SACL_PRESENT;
757 pSD->Control &= ~(SE_SACL_DEFAULTED);
758
759 if (SaclDefaulted)
760 {
761 pSD->Control |= SE_SACL_DEFAULTED;
762 }
763
764 return STATUS_SUCCESS;
765 }
766
767
768 /*
769 * @implemented
770 */
771 NTSTATUS NTAPI
772 RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD,
773 OUT PSECURITY_DESCRIPTOR AbsoluteSD,
774 IN PULONG AbsoluteSDSize,
775 IN PACL Dacl,
776 IN PULONG DaclSize,
777 IN PACL Sacl,
778 IN PULONG SaclSize,
779 IN PSID Owner,
780 IN PULONG OwnerSize,
781 IN PSID PrimaryGroup,
782 IN PULONG PrimaryGroupSize)
783 {
784 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
785 PISECURITY_DESCRIPTOR pRelSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
786 ULONG OwnerLength;
787 ULONG GroupLength;
788 ULONG DaclLength;
789 ULONG SaclLength;
790 PSID pOwner;
791 PSID pGroup;
792 PACL pDacl;
793 PACL pSacl;
794
795 PAGED_CODE_RTL();
796
797 if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
798 {
799 return STATUS_UNKNOWN_REVISION;
800 }
801
802 if (!(pRelSD->Control & SE_SELF_RELATIVE))
803 {
804 return STATUS_BAD_DESCRIPTOR_FORMAT;
805 }
806
807 RtlpQuerySecurityDescriptor (pRelSD,
808 &pOwner,
809 &OwnerLength,
810 &pGroup,
811 &GroupLength,
812 &pDacl,
813 &DaclLength,
814 &pSacl,
815 &SaclLength);
816
817 if (OwnerLength > *OwnerSize ||
818 GroupLength > *PrimaryGroupSize ||
819 DaclLength > *DaclSize ||
820 SaclLength > *SaclSize)
821 {
822 *OwnerSize = OwnerLength;
823 *PrimaryGroupSize = GroupLength;
824 *DaclSize = DaclLength;
825 *SaclSize = SaclLength;
826 return STATUS_BUFFER_TOO_SMALL;
827 }
828
829 RtlCopyMemory (Owner, pOwner, OwnerLength);
830 RtlCopyMemory (PrimaryGroup, pGroup, GroupLength);
831 RtlCopyMemory (Dacl, pDacl, DaclLength);
832 RtlCopyMemory (Sacl, pSacl, SaclLength);
833
834 pAbsSD->Revision = pRelSD->Revision;
835 pAbsSD->Sbz1 = pRelSD->Sbz1;
836 pAbsSD->Control = pRelSD->Control & ~SE_SELF_RELATIVE;
837 pAbsSD->Owner = Owner;
838 pAbsSD->Group = PrimaryGroup;
839 pAbsSD->Dacl = Dacl;
840 pAbsSD->Sacl = Sacl;
841
842 *OwnerSize = OwnerLength;
843 *PrimaryGroupSize = GroupLength;
844 *DaclSize = DaclLength;
845 *SaclSize = SaclLength;
846
847 return STATUS_SUCCESS;
848 }
849
850
851 /*
852 * @implemented
853 */
854 NTSTATUS NTAPI
855 RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
856 OUT PULONG BufferSize)
857 {
858 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
859 PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
860 #ifdef _WIN64
861 PVOID DataStart, DataEnd;
862 ULONG DataSize;
863 LONG MoveDelta;
864 ULONG OwnerLength;
865 ULONG GroupLength;
866 ULONG DaclLength;
867 ULONG SaclLength;
868 #endif
869 PSID pOwner;
870 PSID pGroup;
871 PACL pDacl;
872 PACL pSacl;
873
874 PAGED_CODE_RTL();
875
876 if (SelfRelativeSD == NULL)
877 {
878 return STATUS_INVALID_PARAMETER_1;
879 }
880 if (BufferSize == NULL)
881 {
882 return STATUS_INVALID_PARAMETER_2;
883 }
884
885 if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
886 {
887 return STATUS_UNKNOWN_REVISION;
888 }
889 if (!(pRelSD->Control & SE_SELF_RELATIVE))
890 {
891 return STATUS_BAD_DESCRIPTOR_FORMAT;
892 }
893
894 #ifdef _WIN64
895
896 RtlpQuerySecurityDescriptor((PISECURITY_DESCRIPTOR)pRelSD,
897 &pOwner,
898 &OwnerLength,
899 &pGroup,
900 &GroupLength,
901 &pDacl,
902 &DaclLength,
903 &pSacl,
904 &SaclLength);
905
906 /* calculate the start and end of the data area, we simply just move the
907 data by the difference between the size of the relative and absolute
908 security descriptor structure */
909 DataStart = pOwner;
910 DataEnd = (PVOID)((ULONG_PTR)pOwner + OwnerLength);
911 if (pGroup != NULL)
912 {
913 if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || DataStart == NULL)
914 DataStart = pGroup;
915 if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
916 DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength);
917 }
918 if (pDacl != NULL)
919 {
920 if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || DataStart == NULL)
921 DataStart = pDacl;
922 if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
923 DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength);
924 }
925 if (pSacl != NULL)
926 {
927 if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || DataStart == NULL)
928 DataStart = pSacl;
929 if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
930 DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength);
931 }
932
933 ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart);
934
935 DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart);
936
937 if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize)
938 {
939 *BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize;
940 return STATUS_BUFFER_TOO_SMALL;
941 }
942
943 if (DataSize != 0)
944 {
945 /* if DataSize != 0 ther must be at least one SID or ACL in the security
946 descriptor! Also the data area must be located somewhere after the
947 end of the SECURITY_DESCRIPTOR_RELATIVE structure */
948 ASSERT(DataStart != NULL);
949 ASSERT((ULONG_PTR)DataStart >= (ULONG_PTR)(pRelSD + 1));
950
951 /* it's time to move the data */
952 RtlMoveMemory((PVOID)(pAbsSD + 1),
953 DataStart,
954 DataSize);
955
956 MoveDelta = (LONG)((LONG_PTR)(pAbsSD + 1) - (LONG_PTR)DataStart);
957
958 /* adjust the pointers if neccessary */
959 if (pOwner != NULL)
960 pAbsSD->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta);
961 else
962 pAbsSD->Owner = NULL;
963
964 if (pGroup != NULL)
965 pAbsSD->Group = (PSID)((LONG_PTR)pGroup + MoveDelta);
966 else
967 pAbsSD->Group = NULL;
968
969 if (pSacl != NULL)
970 pAbsSD->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta);
971 else
972 pAbsSD->Sacl = NULL;
973
974 if (pDacl != NULL)
975 pAbsSD->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta);
976 else
977 pAbsSD->Dacl = NULL;
978 }
979 else
980 {
981 /* all pointers must be NULL! */
982 ASSERT(pOwner == NULL);
983 ASSERT(pGroup == NULL);
984 ASSERT(pSacl == NULL);
985 ASSERT(pDacl == NULL);
986
987 pAbsSD->Owner = NULL;
988 pAbsSD->Group = NULL;
989 pAbsSD->Sacl = NULL;
990 pAbsSD->Dacl = NULL;
991 }
992
993 /* clear the self-relative flag */
994 pAbsSD->Control &= ~SE_SELF_RELATIVE;
995
996 #else
997
998 RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)pRelSD,
999 &pOwner,
1000 &pGroup,
1001 &pSacl,
1002 &pDacl);
1003
1004 /* clear the self-relative flag and simply convert the offsets to pointers */
1005 pAbsSD->Control &= ~SE_SELF_RELATIVE;
1006 pAbsSD->Owner = pOwner;
1007 pAbsSD->Group = pGroup;
1008 pAbsSD->Sacl = pSacl;
1009 pAbsSD->Dacl = pDacl;
1010
1011 #endif
1012
1013 return STATUS_SUCCESS;
1014 }
1015
1016
1017 /*
1018 * @implemented
1019 */
1020 BOOLEAN NTAPI
1021 RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
1022 IN ULONG SecurityDescriptorLength,
1023 IN SECURITY_INFORMATION RequiredInformation)
1024 {
1025 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptorInput;
1026
1027 PAGED_CODE_RTL();
1028
1029 if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE) ||
1030 pSD->Revision != SECURITY_DESCRIPTOR_REVISION1 ||
1031 !(pSD->Control & SE_SELF_RELATIVE))
1032 {
1033 return FALSE;
1034 }
1035
1036 if (pSD->Owner != 0)
1037 {
1038 PSID Owner = (PSID)((ULONG_PTR)pSD->Owner + (ULONG_PTR)pSD);
1039 if (!RtlValidSid(Owner))
1040 {
1041 return FALSE;
1042 }
1043 }
1044 else if (RequiredInformation & OWNER_SECURITY_INFORMATION)
1045 {
1046 return FALSE;
1047 }
1048
1049 if (pSD->Group != 0)
1050 {
1051 PSID Group = (PSID)((ULONG_PTR)pSD->Group + (ULONG_PTR)pSD);
1052 if (!RtlValidSid(Group))
1053 {
1054 return FALSE;
1055 }
1056 }
1057 else if (RequiredInformation & GROUP_SECURITY_INFORMATION)
1058 {
1059 return FALSE;
1060 }
1061
1062 if (pSD->Control & SE_DACL_PRESENT)
1063 {
1064 if (pSD->Dacl != 0 &&
1065 !RtlValidAcl((PACL)((ULONG_PTR)pSD->Dacl + (ULONG_PTR)pSD)))
1066 {
1067 return FALSE;
1068 }
1069 }
1070 else if (RequiredInformation & DACL_SECURITY_INFORMATION)
1071 {
1072 return FALSE;
1073 }
1074
1075 if (pSD->Control & SE_SACL_PRESENT)
1076 {
1077 if (pSD->Sacl != 0 &&
1078 !RtlValidAcl((PACL)((ULONG_PTR)pSD->Sacl + (ULONG_PTR)pSD)))
1079 {
1080 return FALSE;
1081 }
1082 }
1083 else if (RequiredInformation & SACL_SECURITY_INFORMATION)
1084 {
1085 return FALSE;
1086 }
1087
1088 return TRUE;
1089 }
1090
1091
1092 /*
1093 * @implemented
1094 */
1095 BOOLEAN NTAPI
1096 RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1097 OUT PUCHAR RMControl)
1098 {
1099 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1100
1101 PAGED_CODE_RTL();
1102
1103 if (!(pSD->Control & SE_RM_CONTROL_VALID))
1104 {
1105 *RMControl = 0;
1106 return FALSE;
1107 }
1108
1109 *RMControl = pSD->Sbz1;
1110
1111 return TRUE;
1112 }
1113
1114
1115 /*
1116 * @implemented
1117 */
1118 VOID NTAPI
1119 RtlSetSecurityDescriptorRMControl(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
1120 IN PUCHAR RMControl)
1121 {
1122 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1123
1124 PAGED_CODE_RTL();
1125
1126 if (RMControl == NULL)
1127 {
1128 pSD->Control &= ~SE_RM_CONTROL_VALID;
1129 pSD->Sbz1 = 0;
1130 }
1131 else
1132 {
1133 pSD->Control |= SE_RM_CONTROL_VALID;
1134 pSD->Sbz1 = *RMControl;
1135 }
1136 }
1137
1138
1139 /*
1140 * @implemented
1141 */
1142 NTSTATUS NTAPI
1143 RtlSetAttributesSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
1144 IN SECURITY_DESCRIPTOR_CONTROL Control,
1145 OUT PULONG Revision)
1146 {
1147 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1148
1149 PAGED_CODE_RTL();
1150
1151 *Revision = pSD->Revision;
1152
1153 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
1154 return STATUS_UNKNOWN_REVISION;
1155
1156 Control &=
1157 ~(SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED | SE_DACL_PRESENT |
1158 SE_DACL_DEFAULTED | SE_SACL_PRESENT | SE_SACL_DEFAULTED |
1159 SE_RM_CONTROL_VALID | SE_SELF_RELATIVE);
1160
1161 return RtlSetControlSecurityDescriptor(SecurityDescriptor,
1162 Control,
1163 Control);
1164 }
1165
1166 /* EOF */