{RTL]
[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 = SECURITY_DESCRIPTOR_REVISION1;
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 = SECURITY_DESCRIPTOR_REVISION1;
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;
254
255 PAGED_CODE_RTL();
256
257 if (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Control & SE_SELF_RELATIVE)
258 Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
259 else
260 Length = sizeof(SECURITY_DESCRIPTOR);
261
262 RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)SecurityDescriptor,
263 &Owner,
264 &Group,
265 &Sacl,
266 &Dacl);
267
268 if (Owner != NULL)
269 {
270 Length += ROUND_UP(RtlLengthSid(Owner), 4);
271 }
272
273 if (Group != NULL)
274 {
275 Length += ROUND_UP(RtlLengthSid(Group), 4);
276 }
277
278 if (Dacl != NULL)
279 {
280 Length += ROUND_UP(Dacl->AclSize, 4);
281 }
282
283 if (Sacl != NULL)
284 {
285 Length += ROUND_UP(Sacl->AclSize, 4);
286 }
287
288 return Length;
289 }
290
291
292 /*
293 * @implemented
294 */
295 NTSTATUS NTAPI
296 RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
297 OUT PBOOLEAN DaclPresent,
298 OUT PACL* Dacl,
299 OUT PBOOLEAN DaclDefaulted)
300 {
301 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
302
303 PAGED_CODE_RTL();
304
305 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
306 {
307 return STATUS_UNKNOWN_REVISION;
308 }
309
310 if (!(pSD->Control & SE_DACL_PRESENT))
311 {
312 *DaclPresent = FALSE;
313 return STATUS_SUCCESS;
314 }
315 *DaclPresent = TRUE;
316
317 RtlpQuerySecurityDescriptorPointers(pSD,
318 NULL,
319 NULL,
320 NULL,
321 Dacl);
322
323 *DaclDefaulted = ((pSD->Control & SE_DACL_DEFAULTED) ? TRUE : FALSE);
324
325 return STATUS_SUCCESS;
326 }
327
328
329 /*
330 * @implemented
331 */
332 NTSTATUS NTAPI
333 RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
334 IN BOOLEAN DaclPresent,
335 IN PACL Dacl,
336 IN BOOLEAN DaclDefaulted)
337 {
338 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
339
340 PAGED_CODE_RTL();
341
342 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
343 {
344 return STATUS_UNKNOWN_REVISION;
345 }
346
347 if (pSD->Control & SE_SELF_RELATIVE)
348 {
349 return STATUS_BAD_DESCRIPTOR_FORMAT;
350 }
351
352 if (!DaclPresent)
353 {
354 pSD->Control = pSD->Control & ~(SE_DACL_PRESENT);
355 return STATUS_SUCCESS;
356 }
357
358 pSD->Dacl = Dacl;
359 pSD->Control |= SE_DACL_PRESENT;
360 pSD->Control &= ~(SE_DACL_DEFAULTED);
361
362 if (DaclDefaulted)
363 {
364 pSD->Control |= SE_DACL_DEFAULTED;
365 }
366
367 return STATUS_SUCCESS;
368 }
369
370
371 /*
372 * @implemented
373 */
374 BOOLEAN NTAPI
375 RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
376 {
377 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
378 PSID Owner, Group;
379 PACL Sacl, Dacl;
380
381 PAGED_CODE_RTL();
382
383 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
384 {
385 return FALSE;
386 }
387
388 RtlpQuerySecurityDescriptorPointers(pSD,
389 &Owner,
390 &Group,
391 &Sacl,
392 &Dacl);
393
394 if ((Owner != NULL && !RtlValidSid(Owner)) ||
395 (Group != NULL && !RtlValidSid(Group)) ||
396 (Sacl != NULL && !RtlValidAcl(Sacl)) ||
397 (Dacl != NULL && !RtlValidAcl(Dacl)))
398 {
399 return FALSE;
400 }
401
402 return TRUE;
403 }
404
405
406 /*
407 * @implemented
408 */
409 NTSTATUS NTAPI
410 RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
411 IN PSID Owner,
412 IN BOOLEAN OwnerDefaulted)
413 {
414 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
415
416 PAGED_CODE_RTL();
417
418 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
419 {
420 return STATUS_UNKNOWN_REVISION;
421 }
422
423 if (pSD->Control & SE_SELF_RELATIVE)
424 {
425 return STATUS_BAD_DESCRIPTOR_FORMAT;
426 }
427
428 pSD->Owner = Owner;
429 pSD->Control &= ~(SE_OWNER_DEFAULTED);
430
431 if (OwnerDefaulted)
432 {
433 pSD->Control |= SE_OWNER_DEFAULTED;
434 }
435
436 return STATUS_SUCCESS;
437 }
438
439
440 /*
441 * @implemented
442 */
443 NTSTATUS NTAPI
444 RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
445 OUT PSID* Owner,
446 OUT PBOOLEAN OwnerDefaulted)
447 {
448 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
449
450 PAGED_CODE_RTL();
451
452 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
453 {
454 return STATUS_UNKNOWN_REVISION;
455 }
456
457 RtlpQuerySecurityDescriptorPointers(pSD,
458 Owner,
459 NULL,
460 NULL,
461 NULL);
462
463 *OwnerDefaulted = ((pSD->Control & SE_OWNER_DEFAULTED) ? TRUE : FALSE);
464
465 return STATUS_SUCCESS;
466 }
467
468
469 /*
470 * @implemented
471 */
472 NTSTATUS NTAPI
473 RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
474 IN PSID Group,
475 IN BOOLEAN GroupDefaulted)
476 {
477 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
478
479 PAGED_CODE_RTL();
480
481 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
482 {
483 return STATUS_UNKNOWN_REVISION;
484 }
485
486 if (pSD->Control & SE_SELF_RELATIVE)
487 {
488 return STATUS_BAD_DESCRIPTOR_FORMAT;
489 }
490
491 pSD->Group = Group;
492 pSD->Control &= ~(SE_GROUP_DEFAULTED);
493 if (GroupDefaulted)
494 {
495 pSD->Control |= SE_GROUP_DEFAULTED;
496 }
497
498 return STATUS_SUCCESS;
499 }
500
501
502 /*
503 * @implemented
504 */
505 NTSTATUS NTAPI
506 RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
507 OUT PSID* Group,
508 OUT PBOOLEAN GroupDefaulted)
509 {
510 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
511
512 PAGED_CODE_RTL();
513
514 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
515 {
516 return STATUS_UNKNOWN_REVISION;
517 }
518
519 RtlpQuerySecurityDescriptorPointers(pSD,
520 NULL,
521 Group,
522 NULL,
523 NULL);
524
525 *GroupDefaulted = ((pSD->Control & SE_GROUP_DEFAULTED) ? TRUE : FALSE);
526
527 return STATUS_SUCCESS;
528 }
529
530
531 /*
532 * @implemented
533 */
534 NTSTATUS NTAPI
535 RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSD,
536 OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
537 IN OUT PULONG BufferLength)
538 {
539 PSID Owner;
540 PSID Group;
541 PACL Sacl;
542 PACL Dacl;
543 ULONG OwnerLength;
544 ULONG GroupLength;
545 ULONG SaclLength;
546 ULONG DaclLength;
547 ULONG TotalLength;
548 ULONG_PTR Current;
549 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
550 PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
551
552 PAGED_CODE_RTL();
553
554 RtlpQuerySecurityDescriptor(pAbsSD,
555 &Owner,
556 &OwnerLength,
557 &Group,
558 &GroupLength,
559 &Dacl,
560 &DaclLength,
561 &Sacl,
562 &SaclLength);
563
564 TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength + SaclLength + DaclLength;
565 if (*BufferLength < TotalLength)
566 {
567 *BufferLength = TotalLength;
568 return STATUS_BUFFER_TOO_SMALL;
569 }
570
571 RtlZeroMemory(pRelSD,
572 TotalLength);
573
574 pRelSD->Revision = pAbsSD->Revision;
575 pRelSD->Sbz1 = pAbsSD->Sbz1;
576 pRelSD->Control = pAbsSD->Control | SE_SELF_RELATIVE;
577
578 Current = (ULONG_PTR)(pRelSD + 1);
579
580 if (SaclLength != 0)
581 {
582 RtlCopyMemory((PVOID)Current,
583 Sacl,
584 SaclLength);
585 pRelSD->Sacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
586 Current += SaclLength;
587 }
588
589 if (DaclLength != 0)
590 {
591 RtlCopyMemory((PVOID)Current,
592 Dacl,
593 DaclLength);
594 pRelSD->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
595 Current += DaclLength;
596 }
597
598 if (OwnerLength != 0)
599 {
600 RtlCopyMemory((PVOID)Current,
601 Owner,
602 OwnerLength);
603 pRelSD->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
604 Current += OwnerLength;
605 }
606
607 if (GroupLength != 0)
608 {
609 RtlCopyMemory((PVOID)Current,
610 Group,
611 GroupLength);
612 pRelSD->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
613 }
614
615 return STATUS_SUCCESS;
616 }
617
618
619 /*
620 * @implemented
621 */
622 NTSTATUS NTAPI
623 RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
624 IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
625 IN PULONG BufferLength)
626 {
627 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
628
629 PAGED_CODE_RTL();
630
631 if (pAbsSD->Control & SE_SELF_RELATIVE)
632 {
633 return STATUS_BAD_DESCRIPTOR_FORMAT;
634 }
635
636 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
637 SelfRelativeSecurityDescriptor,
638 BufferLength);
639 }
640
641
642 /*
643 * @implemented
644 */
645 NTSTATUS NTAPI
646 RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
647 OUT PSECURITY_DESCRIPTOR_CONTROL Control,
648 OUT PULONG Revision)
649 {
650 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
651
652 PAGED_CODE_RTL();
653
654 *Revision = pSD->Revision;
655
656 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
657 {
658 return STATUS_UNKNOWN_REVISION;
659 }
660
661 *Control = pSD->Control;
662
663 return STATUS_SUCCESS;
664 }
665
666
667 /*
668 * @implemented
669 */
670 NTSTATUS NTAPI
671 RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
672 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
673 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
674 {
675 SECURITY_DESCRIPTOR_CONTROL const immutable
676 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
677 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
678 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
679 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
680 ;
681
682 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
683
684 PAGED_CODE_RTL();
685
686 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
687 {
688 return STATUS_UNKNOWN_REVISION;
689 }
690
691 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
692 return STATUS_INVALID_PARAMETER;
693
694 /* Zero the 'bits of interest' */
695 pSD->Control &= ~ControlBitsOfInterest;
696
697 /* Set the 'bits to set' */
698 pSD->Control |= (ControlBitsToSet & ControlBitsOfInterest);
699
700 return STATUS_SUCCESS;
701 }
702
703
704 /*
705 * @implemented
706 */
707 NTSTATUS NTAPI
708 RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
709 OUT PBOOLEAN SaclPresent,
710 OUT PACL *Sacl,
711 OUT PBOOLEAN SaclDefaulted)
712 {
713 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
714
715 PAGED_CODE_RTL();
716
717 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
718 {
719 return STATUS_UNKNOWN_REVISION;
720 }
721
722 if (!(pSD->Control & SE_SACL_PRESENT))
723 {
724 *SaclPresent = FALSE;
725 return STATUS_SUCCESS;
726 }
727 *SaclPresent = TRUE;
728
729 RtlpQuerySecurityDescriptorPointers(pSD,
730 NULL,
731 NULL,
732 Sacl,
733 NULL);
734
735 *SaclDefaulted = ((pSD->Control & SE_SACL_DEFAULTED) ? TRUE : FALSE);
736
737 return STATUS_SUCCESS;
738 }
739
740
741 /*
742 * @implemented
743 */
744 NTSTATUS NTAPI
745 RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
746 IN BOOLEAN SaclPresent,
747 IN PACL Sacl,
748 IN BOOLEAN SaclDefaulted)
749 {
750 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
751
752 PAGED_CODE_RTL();
753
754 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
755 {
756 return STATUS_UNKNOWN_REVISION;
757 }
758
759 if (pSD->Control & SE_SELF_RELATIVE)
760 {
761 return STATUS_BAD_DESCRIPTOR_FORMAT;
762 }
763
764 if (!SaclPresent)
765 {
766 pSD->Control &= ~(SE_SACL_PRESENT);
767 return STATUS_SUCCESS;
768 }
769
770 pSD->Sacl = Sacl;
771 pSD->Control |= SE_SACL_PRESENT;
772 pSD->Control &= ~(SE_SACL_DEFAULTED);
773
774 if (SaclDefaulted)
775 {
776 pSD->Control |= SE_SACL_DEFAULTED;
777 }
778
779 return STATUS_SUCCESS;
780 }
781
782
783 /*
784 * @implemented
785 */
786 NTSTATUS NTAPI
787 RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD,
788 OUT PSECURITY_DESCRIPTOR AbsoluteSD,
789 IN PULONG AbsoluteSDSize,
790 IN PACL Dacl,
791 IN PULONG DaclSize,
792 IN PACL Sacl,
793 IN PULONG SaclSize,
794 IN PSID Owner,
795 IN PULONG OwnerSize,
796 IN PSID PrimaryGroup,
797 IN PULONG PrimaryGroupSize)
798 {
799 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
800 PISECURITY_DESCRIPTOR pRelSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
801 ULONG OwnerLength;
802 ULONG GroupLength;
803 ULONG DaclLength;
804 ULONG SaclLength;
805 PSID pOwner;
806 PSID pGroup;
807 PACL pDacl;
808 PACL pSacl;
809
810 PAGED_CODE_RTL();
811
812 if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
813 {
814 return STATUS_UNKNOWN_REVISION;
815 }
816
817 if (!(pRelSD->Control & SE_SELF_RELATIVE))
818 {
819 return STATUS_BAD_DESCRIPTOR_FORMAT;
820 }
821
822 RtlpQuerySecurityDescriptor (pRelSD,
823 &pOwner,
824 &OwnerLength,
825 &pGroup,
826 &GroupLength,
827 &pDacl,
828 &DaclLength,
829 &pSacl,
830 &SaclLength);
831
832 if (OwnerLength > *OwnerSize ||
833 GroupLength > *PrimaryGroupSize ||
834 DaclLength > *DaclSize ||
835 SaclLength > *SaclSize)
836 {
837 *OwnerSize = OwnerLength;
838 *PrimaryGroupSize = GroupLength;
839 *DaclSize = DaclLength;
840 *SaclSize = SaclLength;
841 return STATUS_BUFFER_TOO_SMALL;
842 }
843
844 RtlCopyMemory (Owner, pOwner, OwnerLength);
845 RtlCopyMemory (PrimaryGroup, pGroup, GroupLength);
846 RtlCopyMemory (Dacl, pDacl, DaclLength);
847 RtlCopyMemory (Sacl, pSacl, SaclLength);
848
849 pAbsSD->Revision = pRelSD->Revision;
850 pAbsSD->Sbz1 = pRelSD->Sbz1;
851 pAbsSD->Control = pRelSD->Control & ~SE_SELF_RELATIVE;
852 pAbsSD->Owner = Owner;
853 pAbsSD->Group = PrimaryGroup;
854 pAbsSD->Dacl = Dacl;
855 pAbsSD->Sacl = Sacl;
856
857 *OwnerSize = OwnerLength;
858 *PrimaryGroupSize = GroupLength;
859 *DaclSize = DaclLength;
860 *SaclSize = SaclLength;
861
862 return STATUS_SUCCESS;
863 }
864
865
866 /*
867 * @implemented
868 */
869 NTSTATUS NTAPI
870 RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
871 OUT PULONG BufferSize)
872 {
873 PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
874 PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
875 #ifdef _WIN64
876 PVOID DataStart, DataEnd;
877 ULONG DataSize;
878 LONG MoveDelta;
879 ULONG OwnerLength;
880 ULONG GroupLength;
881 ULONG DaclLength;
882 ULONG SaclLength;
883 #endif
884 PSID pOwner;
885 PSID pGroup;
886 PACL pDacl;
887 PACL pSacl;
888
889 PAGED_CODE_RTL();
890
891 if (SelfRelativeSD == NULL)
892 {
893 return STATUS_INVALID_PARAMETER_1;
894 }
895 if (BufferSize == NULL)
896 {
897 return STATUS_INVALID_PARAMETER_2;
898 }
899
900 if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
901 {
902 return STATUS_UNKNOWN_REVISION;
903 }
904 if (!(pRelSD->Control & SE_SELF_RELATIVE))
905 {
906 return STATUS_BAD_DESCRIPTOR_FORMAT;
907 }
908
909 #ifdef _WIN64
910
911 RtlpQuerySecurityDescriptor((PISECURITY_DESCRIPTOR)pRelSD,
912 &pOwner,
913 &OwnerLength,
914 &pGroup,
915 &GroupLength,
916 &pDacl,
917 &DaclLength,
918 &pSacl,
919 &SaclLength);
920
921 /* calculate the start and end of the data area, we simply just move the
922 data by the difference between the size of the relative and absolute
923 security descriptor structure */
924 DataStart = pOwner;
925 DataEnd = (PVOID)((ULONG_PTR)pOwner + OwnerLength);
926 if (pGroup != NULL)
927 {
928 if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || DataStart == NULL)
929 DataStart = pGroup;
930 if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
931 DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength);
932 }
933 if (pDacl != NULL)
934 {
935 if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || DataStart == NULL)
936 DataStart = pDacl;
937 if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
938 DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength);
939 }
940 if (pSacl != NULL)
941 {
942 if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || DataStart == NULL)
943 DataStart = pSacl;
944 if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
945 DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength);
946 }
947
948 ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart);
949
950 DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart);
951
952 if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize)
953 {
954 *BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize;
955 return STATUS_BUFFER_TOO_SMALL;
956 }
957
958 if (DataSize != 0)
959 {
960 /* if DataSize != 0 ther must be at least one SID or ACL in the security
961 descriptor! Also the data area must be located somewhere after the
962 end of the SECURITY_DESCRIPTOR_RELATIVE structure */
963 ASSERT(DataStart != NULL);
964 ASSERT((ULONG_PTR)DataStart >= (ULONG_PTR)(pRelSD + 1));
965
966 /* it's time to move the data */
967 RtlMoveMemory((PVOID)(pAbsSD + 1),
968 DataStart,
969 DataSize);
970
971 MoveDelta = (LONG)((LONG_PTR)(pAbsSD + 1) - (LONG_PTR)DataStart);
972
973 /* adjust the pointers if neccessary */
974 if (pOwner != NULL)
975 pAbsSD->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta);
976 else
977 pAbsSD->Owner = NULL;
978
979 if (pGroup != NULL)
980 pAbsSD->Group = (PSID)((LONG_PTR)pGroup + MoveDelta);
981 else
982 pAbsSD->Group = NULL;
983
984 if (pSacl != NULL)
985 pAbsSD->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta);
986 else
987 pAbsSD->Sacl = NULL;
988
989 if (pDacl != NULL)
990 pAbsSD->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta);
991 else
992 pAbsSD->Dacl = NULL;
993 }
994 else
995 {
996 /* all pointers must be NULL! */
997 ASSERT(pOwner == NULL);
998 ASSERT(pGroup == NULL);
999 ASSERT(pSacl == NULL);
1000 ASSERT(pDacl == NULL);
1001
1002 pAbsSD->Owner = NULL;
1003 pAbsSD->Group = NULL;
1004 pAbsSD->Sacl = NULL;
1005 pAbsSD->Dacl = NULL;
1006 }
1007
1008 /* clear the self-relative flag */
1009 pAbsSD->Control &= ~SE_SELF_RELATIVE;
1010
1011 #else
1012
1013 RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)pRelSD,
1014 &pOwner,
1015 &pGroup,
1016 &pSacl,
1017 &pDacl);
1018
1019 /* clear the self-relative flag and simply convert the offsets to pointers */
1020 pAbsSD->Control &= ~SE_SELF_RELATIVE;
1021 pAbsSD->Owner = pOwner;
1022 pAbsSD->Group = pGroup;
1023 pAbsSD->Sacl = pSacl;
1024 pAbsSD->Dacl = pDacl;
1025
1026 #endif
1027
1028 return STATUS_SUCCESS;
1029 }
1030
1031
1032 /*
1033 * @implemented
1034 */
1035 BOOLEAN NTAPI
1036 RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
1037 IN ULONG SecurityDescriptorLength,
1038 IN SECURITY_INFORMATION RequiredInformation)
1039 {
1040 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptorInput;
1041
1042 PAGED_CODE_RTL();
1043
1044 if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE) ||
1045 pSD->Revision != SECURITY_DESCRIPTOR_REVISION1 ||
1046 !(pSD->Control & SE_SELF_RELATIVE))
1047 {
1048 return FALSE;
1049 }
1050
1051 if (pSD->Owner != 0)
1052 {
1053 PSID Owner = (PSID)((ULONG_PTR)pSD->Owner + (ULONG_PTR)pSD);
1054 if (!RtlValidSid(Owner))
1055 {
1056 return FALSE;
1057 }
1058 }
1059 else if (RequiredInformation & OWNER_SECURITY_INFORMATION)
1060 {
1061 return FALSE;
1062 }
1063
1064 if (pSD->Group != 0)
1065 {
1066 PSID Group = (PSID)((ULONG_PTR)pSD->Group + (ULONG_PTR)pSD);
1067 if (!RtlValidSid(Group))
1068 {
1069 return FALSE;
1070 }
1071 }
1072 else if (RequiredInformation & GROUP_SECURITY_INFORMATION)
1073 {
1074 return FALSE;
1075 }
1076
1077 if (pSD->Control & SE_DACL_PRESENT)
1078 {
1079 if (pSD->Dacl != 0 &&
1080 !RtlValidAcl((PACL)((ULONG_PTR)pSD->Dacl + (ULONG_PTR)pSD)))
1081 {
1082 return FALSE;
1083 }
1084 }
1085 else if (RequiredInformation & DACL_SECURITY_INFORMATION)
1086 {
1087 return FALSE;
1088 }
1089
1090 if (pSD->Control & SE_SACL_PRESENT)
1091 {
1092 if (pSD->Sacl != 0 &&
1093 !RtlValidAcl((PACL)((ULONG_PTR)pSD->Sacl + (ULONG_PTR)pSD)))
1094 {
1095 return FALSE;
1096 }
1097 }
1098 else if (RequiredInformation & SACL_SECURITY_INFORMATION)
1099 {
1100 return FALSE;
1101 }
1102
1103 return TRUE;
1104 }
1105
1106
1107 /*
1108 * @implemented
1109 */
1110 BOOLEAN NTAPI
1111 RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1112 OUT PUCHAR RMControl)
1113 {
1114 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1115
1116 PAGED_CODE_RTL();
1117
1118 if (!(pSD->Control & SE_RM_CONTROL_VALID))
1119 {
1120 *RMControl = 0;
1121 return FALSE;
1122 }
1123
1124 *RMControl = pSD->Sbz1;
1125
1126 return TRUE;
1127 }
1128
1129
1130 /*
1131 * @implemented
1132 */
1133 VOID NTAPI
1134 RtlSetSecurityDescriptorRMControl(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
1135 IN PUCHAR RMControl)
1136 {
1137 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1138
1139 PAGED_CODE_RTL();
1140
1141 if (RMControl == NULL)
1142 {
1143 pSD->Control &= ~SE_RM_CONTROL_VALID;
1144 pSD->Sbz1 = 0;
1145 }
1146 else
1147 {
1148 pSD->Control |= SE_RM_CONTROL_VALID;
1149 pSD->Sbz1 = *RMControl;
1150 }
1151 }
1152
1153
1154 /*
1155 * @implemented
1156 */
1157 NTSTATUS NTAPI
1158 RtlSetAttributesSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
1159 IN SECURITY_DESCRIPTOR_CONTROL Control,
1160 OUT PULONG Revision)
1161 {
1162 PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1163
1164 PAGED_CODE_RTL();
1165
1166 *Revision = pSD->Revision;
1167
1168 if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
1169 return STATUS_UNKNOWN_REVISION;
1170
1171 Control &=
1172 ~(SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED | SE_DACL_PRESENT |
1173 SE_DACL_DEFAULTED | SE_SACL_PRESENT | SE_SACL_DEFAULTED |
1174 SE_RM_CONTROL_VALID | SE_SELF_RELATIVE);
1175
1176 return RtlSetControlSecurityDescriptor(SecurityDescriptor,
1177 Control,
1178 Control);
1179 }
1180
1181 /* EOF */