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