Standardize comment headers. Patch by Trevor McCort
[reactos.git] / reactos / ntoskrnl / se / sd.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/sd.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: David Welch <welch@cwcom.net>
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #include <internal/debug.h>
15
16 /* GLOBALS ******************************************************************/
17
18 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
19 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
20 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
21 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
22 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
23 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
24
25 /* FUNCTIONS ***************************************************************/
26
27 BOOLEAN INIT_FUNCTION
28 SepInitSDs(VOID)
29 {
30 /* Create PublicDefaultSd */
31 SePublicDefaultSd = ExAllocatePool(NonPagedPool,
32 sizeof(SECURITY_DESCRIPTOR));
33 if (SePublicDefaultSd == NULL)
34 return FALSE;
35
36 RtlCreateSecurityDescriptor(SePublicDefaultSd,
37 SECURITY_DESCRIPTOR_REVISION);
38 RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
39 TRUE,
40 SePublicDefaultDacl,
41 FALSE);
42
43 /* Create PublicDefaultUnrestrictedSd */
44 SePublicDefaultUnrestrictedSd = ExAllocatePool(NonPagedPool,
45 sizeof(SECURITY_DESCRIPTOR));
46 if (SePublicDefaultUnrestrictedSd == NULL)
47 return FALSE;
48
49 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
50 SECURITY_DESCRIPTOR_REVISION);
51 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
52 TRUE,
53 SePublicDefaultUnrestrictedDacl,
54 FALSE);
55
56 /* Create PublicOpenSd */
57 SePublicOpenSd = ExAllocatePool(NonPagedPool,
58 sizeof(SECURITY_DESCRIPTOR));
59 if (SePublicOpenSd == NULL)
60 return FALSE;
61
62 RtlCreateSecurityDescriptor(SePublicOpenSd,
63 SECURITY_DESCRIPTOR_REVISION);
64 RtlSetDaclSecurityDescriptor(SePublicOpenSd,
65 TRUE,
66 SePublicOpenDacl,
67 FALSE);
68
69 /* Create PublicOpenUnrestrictedSd */
70 SePublicOpenUnrestrictedSd = ExAllocatePool(NonPagedPool,
71 sizeof(SECURITY_DESCRIPTOR));
72 if (SePublicOpenUnrestrictedSd == NULL)
73 return FALSE;
74
75 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
76 SECURITY_DESCRIPTOR_REVISION);
77 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
78 TRUE,
79 SePublicOpenUnrestrictedDacl,
80 FALSE);
81
82 /* Create SystemDefaultSd */
83 SeSystemDefaultSd = ExAllocatePool(NonPagedPool,
84 sizeof(SECURITY_DESCRIPTOR));
85 if (SeSystemDefaultSd == NULL)
86 return FALSE;
87
88 RtlCreateSecurityDescriptor(SeSystemDefaultSd,
89 SECURITY_DESCRIPTOR_REVISION);
90 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
91 TRUE,
92 SeSystemDefaultDacl,
93 FALSE);
94
95 /* Create UnrestrictedSd */
96 SeUnrestrictedSd = ExAllocatePool(NonPagedPool,
97 sizeof(SECURITY_DESCRIPTOR));
98 if (SeUnrestrictedSd == NULL)
99 return FALSE;
100
101 RtlCreateSecurityDescriptor(SeUnrestrictedSd,
102 SECURITY_DESCRIPTOR_REVISION);
103 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
104 TRUE,
105 SeUnrestrictedDacl,
106 FALSE);
107
108 return TRUE;
109 }
110
111 /*
112 * @implemented
113 */
114 NTSTATUS
115 STDCALL
116 SeCaptureSecurityDescriptor(
117 IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
118 IN KPROCESSOR_MODE CurrentMode,
119 IN POOL_TYPE PoolType,
120 IN BOOLEAN CaptureIfKernel,
121 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor
122 )
123 {
124 SECURITY_DESCRIPTOR DescriptorCopy;
125 PSECURITY_DESCRIPTOR NewDescriptor;
126 ULONG OwnerSAC = 0, GroupSAC = 0;
127 ULONG OwnerSize = 0, GroupSize = 0;
128 ULONG SaclSize = 0, DaclSize = 0;
129 ULONG DescriptorSize = sizeof(SECURITY_DESCRIPTOR);
130 NTSTATUS Status = STATUS_SUCCESS;
131
132 if(OriginalSecurityDescriptor != NULL)
133 {
134 if(CurrentMode != KernelMode)
135 {
136 _SEH_TRY
137 {
138 ProbeForRead(OriginalSecurityDescriptor,
139 sizeof(SECURITY_DESCRIPTOR),
140 sizeof(ULONG));
141
142 /* make a copy on the stack */
143 DescriptorCopy = *OriginalSecurityDescriptor;
144 }
145 _SEH_HANDLE
146 {
147 Status = _SEH_GetExceptionCode();
148 }
149 _SEH_END;
150
151 if(!NT_SUCCESS(Status))
152 {
153 return Status;
154 }
155 }
156 else if(!CaptureIfKernel)
157 {
158 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
159 {
160 return STATUS_UNKNOWN_REVISION;
161 }
162
163 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
164 return STATUS_SUCCESS;
165 }
166 else
167 {
168 /* make a copy on the stack */
169 DescriptorCopy = *OriginalSecurityDescriptor;
170 }
171
172 if(DescriptorCopy.Revision != SECURITY_DESCRIPTOR_REVISION1)
173 {
174 return STATUS_UNKNOWN_REVISION;
175 }
176
177 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
178 {
179 /* in case we're dealing with a self-relative descriptor, do a basic convert
180 to an absolute descriptor. We do this so we can simply access the data
181 using the pointers without calculating them again. */
182 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
183 if(DescriptorCopy.Owner != NULL)
184 {
185 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
186 }
187 if(DescriptorCopy.Group != NULL)
188 {
189 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
190 }
191 if(DescriptorCopy.Dacl != NULL)
192 {
193 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
194 }
195 if(DescriptorCopy.Sacl != NULL)
196 {
197 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
198 }
199 }
200
201 /* determine the size of the SIDs */
202 #define DetermineSIDSize(SidType) \
203 do { \
204 if(DescriptorCopy.SidType != NULL) \
205 { \
206 SID *SidType = (SID*)DescriptorCopy.SidType; \
207 \
208 if(CurrentMode != KernelMode) \
209 { \
210 /* securely access the buffers! */ \
211 _SEH_TRY \
212 { \
213 ProbeForRead(&SidType->SubAuthorityCount, \
214 sizeof(SidType->SubAuthorityCount), \
215 1); \
216 SidType##SAC = SidType->SubAuthorityCount; \
217 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
218 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
219 ProbeForRead(SidType, \
220 SidType##Size, \
221 sizeof(ULONG)); \
222 if(!RtlValidSid(SidType)) \
223 { \
224 Status = STATUS_INVALID_SID; \
225 } \
226 } \
227 _SEH_HANDLE \
228 { \
229 Status = _SEH_GetExceptionCode(); \
230 } \
231 _SEH_END; \
232 \
233 if(!NT_SUCCESS(Status)) \
234 { \
235 return Status; \
236 } \
237 } \
238 else \
239 { \
240 SidType##SAC = SidType->SubAuthorityCount; \
241 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
242 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
243 } \
244 } \
245 } while(0)
246
247 DetermineSIDSize(Owner);
248 DetermineSIDSize(Group);
249
250 /* determine the size of the ACLs */
251 #define DetermineACLSize(AclType, AclFlag) \
252 do { \
253 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
254 DescriptorCopy.AclType != NULL) \
255 { \
256 PACL AclType = (PACL)DescriptorCopy.AclType; \
257 \
258 if(CurrentMode != KernelMode) \
259 { \
260 /* securely access the buffers! */ \
261 _SEH_TRY \
262 { \
263 ProbeForRead(&AclType->AclSize, \
264 sizeof(AclType->AclSize), \
265 1); \
266 AclType##Size = AclType->AclSize; \
267 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
268 ProbeForRead(AclType, \
269 AclType##Size, \
270 sizeof(ULONG)); \
271 if(!RtlValidAcl(AclType)) \
272 { \
273 Status = STATUS_INVALID_ACL; \
274 } \
275 } \
276 _SEH_HANDLE \
277 { \
278 Status = _SEH_GetExceptionCode(); \
279 } \
280 _SEH_END; \
281 \
282 if(!NT_SUCCESS(Status)) \
283 { \
284 return Status; \
285 } \
286 } \
287 else \
288 { \
289 AclType##Size = AclType->AclSize; \
290 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
291 } \
292 } \
293 else \
294 { \
295 DescriptorCopy.AclType = NULL; \
296 } \
297 } while(0)
298
299 DetermineACLSize(Sacl, SACL);
300 DetermineACLSize(Dacl, DACL);
301
302 /* allocate enough memory to store a complete copy of a self-relative
303 security descriptor */
304 NewDescriptor = ExAllocatePool(PoolType,
305 DescriptorSize);
306 if(NewDescriptor != NULL)
307 {
308 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
309
310 NewDescriptor->Revision = DescriptorCopy.Revision;
311 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
312 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
313
314 _SEH_TRY
315 {
316 /* setup the offsets and copy the SIDs and ACLs to the new
317 self-relative security descriptor. Probing the pointers is not
318 neccessary anymore as we did that when collecting the sizes! */
319 #define CopySIDOrACL(Type) \
320 do { \
321 if(DescriptorCopy.Type != NULL) \
322 { \
323 NewDescriptor->Type = (PVOID)Offset; \
324 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
325 (ULONG_PTR)NewDescriptor->Type), \
326 DescriptorCopy.Type, \
327 Type##Size); \
328 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
329 } \
330 } while(0)
331
332 CopySIDOrACL(Owner);
333 CopySIDOrACL(Group);
334 CopySIDOrACL(Sacl);
335 CopySIDOrACL(Dacl);
336 }
337 _SEH_HANDLE
338 {
339 Status = _SEH_GetExceptionCode();
340 }
341 _SEH_END;
342
343 if(NT_SUCCESS(Status))
344 {
345 /* we're finally done! copy the pointer to the captured descriptor to
346 to the caller */
347 *CapturedSecurityDescriptor = NewDescriptor;
348 return STATUS_SUCCESS;
349 }
350 else
351 {
352 /* we failed to copy the data to the new descriptor */
353 ExFreePool(NewDescriptor);
354 }
355 }
356 else
357 {
358 Status = STATUS_INSUFFICIENT_RESOURCES;
359 }
360 }
361 else
362 {
363 /* nothing to do... */
364 *CapturedSecurityDescriptor = NULL;
365 }
366
367 return Status;
368 }
369
370 /*
371 * @implemented
372 */
373 NTSTATUS STDCALL
374 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
375 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
376 IN OUT PULONG Length,
377 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
378 {
379 PSECURITY_DESCRIPTOR ObjectSd;
380 PSID Owner = 0;
381 PSID Group = 0;
382 PACL Dacl = 0;
383 PACL Sacl = 0;
384 ULONG OwnerLength = 0;
385 ULONG GroupLength = 0;
386 ULONG DaclLength = 0;
387 ULONG SaclLength = 0;
388 ULONG Control = 0;
389 ULONG_PTR Current;
390 ULONG SdLength;
391
392 if (*ObjectsSecurityDescriptor == NULL)
393 {
394 if (*Length < sizeof(SECURITY_DESCRIPTOR))
395 {
396 *Length = sizeof(SECURITY_DESCRIPTOR);
397 return STATUS_BUFFER_TOO_SMALL;
398 }
399
400 *Length = sizeof(SECURITY_DESCRIPTOR);
401 RtlCreateSecurityDescriptor(SecurityDescriptor,
402 SECURITY_DESCRIPTOR_REVISION);
403 SecurityDescriptor->Control |= SE_SELF_RELATIVE;
404 return STATUS_SUCCESS;
405 }
406
407 ObjectSd = *ObjectsSecurityDescriptor;
408
409 /* Calculate the required security descriptor length */
410 Control = SE_SELF_RELATIVE;
411 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
412 (ObjectSd->Owner != NULL))
413 {
414 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
415 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
416 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
417 }
418
419 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
420 (ObjectSd->Group != NULL))
421 {
422 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
423 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
424 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
425 }
426
427 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
428 (ObjectSd->Control & SE_DACL_PRESENT))
429 {
430 if (ObjectSd->Dacl != NULL)
431 {
432 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
433 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
434 }
435 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
436 }
437
438 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
439 (ObjectSd->Control & SE_SACL_PRESENT))
440 {
441 if (ObjectSd->Sacl != NULL)
442 {
443 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
444 SaclLength = ROUND_UP(Sacl->AclSize, 4);
445 }
446 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
447 }
448
449 SdLength = OwnerLength + GroupLength + DaclLength +
450 SaclLength + sizeof(SECURITY_DESCRIPTOR);
451 if (*Length < sizeof(SECURITY_DESCRIPTOR))
452 {
453 *Length = SdLength;
454 return STATUS_BUFFER_TOO_SMALL;
455 }
456
457 /* Build the new security descrtiptor */
458 RtlCreateSecurityDescriptor(SecurityDescriptor,
459 SECURITY_DESCRIPTOR_REVISION);
460 SecurityDescriptor->Control = Control;
461
462 Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
463
464 if (OwnerLength != 0)
465 {
466 RtlCopyMemory((PVOID)Current,
467 Owner,
468 OwnerLength);
469 SecurityDescriptor->Owner = (PSID)(Current - (ULONG_PTR)SecurityDescriptor);
470 Current += OwnerLength;
471 }
472
473 if (GroupLength != 0)
474 {
475 RtlCopyMemory((PVOID)Current,
476 Group,
477 GroupLength);
478 SecurityDescriptor->Group = (PSID)(Current - (ULONG_PTR)SecurityDescriptor);
479 Current += GroupLength;
480 }
481
482 if (DaclLength != 0)
483 {
484 RtlCopyMemory((PVOID)Current,
485 Dacl,
486 DaclLength);
487 SecurityDescriptor->Dacl = (PACL)(Current - (ULONG_PTR)SecurityDescriptor);
488 Current += DaclLength;
489 }
490
491 if (SaclLength != 0)
492 {
493 RtlCopyMemory((PVOID)Current,
494 Sacl,
495 SaclLength);
496 SecurityDescriptor->Sacl = (PACL)(Current - (ULONG_PTR)SecurityDescriptor);
497 Current += SaclLength;
498 }
499
500 *Length = SdLength;
501
502 return STATUS_SUCCESS;
503 }
504
505 /*
506 * @implemented
507 */
508 NTSTATUS
509 STDCALL
510 SeReleaseSecurityDescriptor(
511 IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
512 IN KPROCESSOR_MODE CurrentMode,
513 IN BOOLEAN CaptureIfKernelMode
514 )
515 {
516 /* WARNING! You need to call this function with the same value for CurrentMode
517 and CaptureIfKernelMode that you previously passed to
518 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
519 if(CapturedSecurityDescriptor != NULL &&
520 (CurrentMode == UserMode ||
521 (CurrentMode == KernelMode && CaptureIfKernelMode)))
522 {
523 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
524 ExFreePool(CapturedSecurityDescriptor);
525 }
526
527 return STATUS_SUCCESS;
528 }
529
530 /*
531 * @unimplemented
532 */
533 NTSTATUS STDCALL
534 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
535 IN PSECURITY_INFORMATION SecurityInformation,
536 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
537 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
538 IN POOL_TYPE PoolType,
539 IN PGENERIC_MAPPING GenericMapping)
540 {
541 UNIMPLEMENTED;
542 return STATUS_NOT_IMPLEMENTED;
543 }
544
545 /*
546 * @unimplemented
547 */
548 NTSTATUS
549 STDCALL
550 SeSetSecurityDescriptorInfoEx(
551 IN PVOID Object OPTIONAL,
552 IN PSECURITY_INFORMATION SecurityInformation,
553 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
554 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
555 IN ULONG AutoInheritFlags,
556 IN POOL_TYPE PoolType,
557 IN PGENERIC_MAPPING GenericMapping
558 )
559 {
560 UNIMPLEMENTED;
561 return STATUS_NOT_IMPLEMENTED;
562 }
563
564
565 /*
566 * @implemented
567 */
568 BOOLEAN STDCALL
569 SeValidSecurityDescriptor(IN ULONG Length,
570 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
571 {
572 ULONG SdLength;
573 PISID Sid;
574 PACL Acl;
575
576 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
577 {
578 DPRINT1("Invalid Security Descriptor revision\n");
579 return FALSE;
580 }
581
582 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
583 {
584 DPRINT1("Invalid Security Descriptor revision\n");
585 return FALSE;
586 }
587
588 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
589 {
590 DPRINT1("No self-relative Security Descriptor\n");
591 return FALSE;
592 }
593
594 SdLength = sizeof(SECURITY_DESCRIPTOR);
595
596 /* Check Owner SID */
597 if (SecurityDescriptor->Owner == NULL)
598 {
599 DPRINT1("No Owner SID\n");
600 return FALSE;
601 }
602
603 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
604 {
605 DPRINT1("Invalid Owner SID alignment\n");
606 return FALSE;
607 }
608
609 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
610 if (Sid->Revision != SID_REVISION)
611 {
612 DPRINT1("Invalid Owner SID revision\n");
613 return FALSE;
614 }
615
616 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
617 if (Length < SdLength)
618 {
619 DPRINT1("Invalid Owner SID size\n");
620 return FALSE;
621 }
622
623 /* Check Group SID */
624 if (SecurityDescriptor->Group != NULL)
625 {
626 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
627 {
628 DPRINT1("Invalid Group SID alignment\n");
629 return FALSE;
630 }
631
632 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
633 if (Sid->Revision != SID_REVISION)
634 {
635 DPRINT1("Invalid Group SID revision\n");
636 return FALSE;
637 }
638
639 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
640 if (Length < SdLength)
641 {
642 DPRINT1("Invalid Group SID size\n");
643 return FALSE;
644 }
645 }
646
647 /* Check DACL */
648 if (SecurityDescriptor->Dacl != NULL)
649 {
650 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
651 {
652 DPRINT1("Invalid DACL alignment\n");
653 return FALSE;
654 }
655
656 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
657 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
658 (Acl->AclRevision > MAX_ACL_REVISION))
659 {
660 DPRINT1("Invalid DACL revision\n");
661 return FALSE;
662 }
663
664 SdLength += Acl->AclSize;
665 if (Length < SdLength)
666 {
667 DPRINT1("Invalid DACL size\n");
668 return FALSE;
669 }
670 }
671
672 /* Check SACL */
673 if (SecurityDescriptor->Sacl != NULL)
674 {
675 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
676 {
677 DPRINT1("Invalid SACL alignment\n");
678 return FALSE;
679 }
680
681 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
682 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
683 (Acl->AclRevision > MAX_ACL_REVISION))
684 {
685 DPRINT1("Invalid SACL revision\n");
686 return FALSE;
687 }
688
689 SdLength += Acl->AclSize;
690 if (Length < SdLength)
691 {
692 DPRINT1("Invalid SACL size\n");
693 return FALSE;
694 }
695 }
696
697 return TRUE;
698 }
699
700 /* EOF */