1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * PURPOSE: Security manager
5 * PROGRAMER: David Welch <welch@cwcom.net>
8 /* INCLUDES *****************************************************************/
15 /* FUNCTIONS ***************************************************************/
18 RtlFirstFreeAce(PACL Acl
,
27 Current
= (PACE
)(Acl
+ 1);
30 if (Acl
->AceCount
== 0)
37 AclEnd
= (ULONG_PTR
)Acl
+ Acl
->AclSize
;
40 if ((ULONG_PTR
)Current
>= AclEnd
)
44 if (Current
->Header
.AceType
== ACCESS_ALLOWED_COMPOUND_ACE_TYPE
&&
45 Acl
->AclRevision
< ACL_REVISION3
)
49 Current
= (PACE
)((ULONG_PTR
)Current
+ Current
->Header
.AceSize
);
51 while (++i
< Acl
->AceCount
);
53 if ((ULONG_PTR
)Current
< AclEnd
)
74 if (Acl
->AclRevision
< MIN_ACL_REVISION
||
75 Acl
->AclRevision
> MAX_ACL_REVISION
||
76 AceIndex
>= Acl
->AceCount
)
78 return(STATUS_INVALID_PARAMETER
);
81 *Ace
= (PVOID
)((PACE
)(Acl
+ 1));
83 for (i
= 0; i
< AceIndex
; i
++)
85 if ((ULONG_PTR
)*Ace
>= (ULONG_PTR
)Acl
+ Acl
->AclSize
)
87 return(STATUS_INVALID_PARAMETER
);
89 *Ace
= (PVOID
)((PACE
)((ULONG_PTR
)(*Ace
) + ((PACE
)(*Ace
))->Header
.AceSize
));
92 if ((ULONG_PTR
)*Ace
>= (ULONG_PTR
)Acl
+ Acl
->AclSize
)
94 return(STATUS_INVALID_PARAMETER
);
97 return(STATUS_SUCCESS
);
102 RtlpAddKnownAce (PACL Acl
,
105 ACCESS_MASK AccessMask
,
106 GUID
*ObjectTypeGuid OPTIONAL
,
107 GUID
*InheritedObjectTypeGuid OPTIONAL
,
113 ULONG AceSize
, InvalidFlags
;
114 ULONG AceObjectFlags
= 0;
119 /* check if RtlpAddKnownAce was called incorrectly */
120 if (ObjectTypeGuid
!= NULL
|| InheritedObjectTypeGuid
!= NULL
)
122 ASSERT(Type
== ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
||
123 Type
== ACCESS_ALLOWED_OBJECT_ACE_TYPE
||
124 Type
== ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
||
125 Type
== ACCESS_DENIED_OBJECT_ACE_TYPE
||
126 Type
== SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
||
127 Type
== SYSTEM_AUDIT_OBJECT_ACE_TYPE
);
131 ASSERT(Type
!= ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
&&
132 Type
!= ACCESS_ALLOWED_OBJECT_ACE_TYPE
&&
133 Type
!= ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
&&
134 Type
!= ACCESS_DENIED_OBJECT_ACE_TYPE
&&
135 Type
!= SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
&&
136 Type
!= SYSTEM_AUDIT_OBJECT_ACE_TYPE
);
140 if (!RtlValidSid(Sid
))
142 return(STATUS_INVALID_SID
);
145 if (Type
== SYSTEM_MANDATORY_LABEL_ACE_TYPE
)
147 static const SID_IDENTIFIER_AUTHORITY MandatoryLabelAuthority
= {SECURITY_MANDATORY_LABEL_AUTHORITY
};
149 /* The SID's identifier authority must be SECURITY_MANDATORY_LABEL_AUTHORITY! */
150 if (RtlCompareMemory(&((PISID
)Sid
)->IdentifierAuthority
,
151 &MandatoryLabelAuthority
,
152 sizeof(MandatoryLabelAuthority
)) != sizeof(MandatoryLabelAuthority
))
154 return STATUS_INVALID_PARAMETER
;
158 if (Acl
->AclRevision
> MAX_ACL_REVISION
||
159 Revision
> MAX_ACL_REVISION
)
161 return(STATUS_UNKNOWN_REVISION
);
163 if (Revision
< Acl
->AclRevision
)
165 Revision
= Acl
->AclRevision
;
168 /* Validate the flags */
169 if (Type
== SYSTEM_AUDIT_ACE_TYPE
||
170 Type
== SYSTEM_AUDIT_OBJECT_ACE_TYPE
||
171 Type
== SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE
)
173 InvalidFlags
= Flags
& ~(VALID_INHERIT_FLAGS
|
174 SUCCESSFUL_ACCESS_ACE_FLAG
| FAILED_ACCESS_ACE_FLAG
);
178 InvalidFlags
= Flags
& ~VALID_INHERIT_FLAGS
;
181 if (InvalidFlags
!= 0)
183 return(STATUS_INVALID_PARAMETER
);
186 if (!RtlFirstFreeAce(Acl
, &Ace
))
188 return(STATUS_INVALID_ACL
);
192 return(STATUS_ALLOTTED_SPACE_EXCEEDED
);
195 /* Calculate the size of the ACE */
196 AceSize
= RtlLengthSid(Sid
) + sizeof(ACE
);
197 if (ObjectTypeGuid
!= NULL
)
199 AceObjectFlags
|= ACE_OBJECT_TYPE_PRESENT
;
200 AceSize
+= sizeof(GUID
);
202 if (InheritedObjectTypeGuid
!= NULL
)
204 AceObjectFlags
|= ACE_INHERITED_OBJECT_TYPE_PRESENT
;
205 AceSize
+= sizeof(GUID
);
208 if (AceObjectFlags
!= 0)
210 /* Don't forget the ACE object flags
211 (corresponds to the Flags field in the *_OBJECT_ACE structures) */
212 AceSize
+= sizeof(ULONG
);
215 if ((ULONG_PTR
)Ace
+ AceSize
>
216 (ULONG_PTR
)Acl
+ Acl
->AclSize
)
218 return(STATUS_ALLOTTED_SPACE_EXCEEDED
);
221 /* initialize the header and common fields */
222 Ace
->Header
.AceFlags
= Flags
;
223 Ace
->Header
.AceType
= Type
;
224 Ace
->Header
.AceSize
= (WORD
)AceSize
;
225 Ace
->AccessMask
= AccessMask
;
227 if (AceObjectFlags
!= 0)
229 /* Write the ACE flags to the ACE
230 (corresponds to the Flags field in the *_OBJECT_ACE structures) */
231 *(PULONG
)(Ace
+ 1) = AceObjectFlags
;
232 SidStart
= (PSID
)((ULONG_PTR
)(Ace
+ 1) + sizeof(ULONG
));
235 SidStart
= (PSID
)(Ace
+ 1);
238 if (ObjectTypeGuid
!= NULL
)
240 RtlCopyMemory(SidStart
,
243 SidStart
= (PSID
)((ULONG_PTR
)SidStart
+ sizeof(GUID
));
245 if (InheritedObjectTypeGuid
!= NULL
)
247 RtlCopyMemory(SidStart
,
248 InheritedObjectTypeGuid
,
250 SidStart
= (PSID
)((ULONG_PTR
)SidStart
+ sizeof(GUID
));
254 RtlCopySid(RtlLengthSid(Sid
),
258 Acl
->AclRevision
= Revision
;
259 return(STATUS_SUCCESS
);
267 RtlAddAccessAllowedAce (IN OUT PACL Acl
,
269 IN ACCESS_MASK AccessMask
,
274 return RtlpAddKnownAce (Acl
,
281 ACCESS_ALLOWED_ACE_TYPE
);
289 RtlAddAccessAllowedAceEx (IN OUT PACL Acl
,
292 IN ACCESS_MASK AccessMask
,
297 return RtlpAddKnownAce (Acl
,
304 ACCESS_ALLOWED_ACE_TYPE
);
312 RtlAddAccessAllowedObjectAce (IN OUT PACL Acl
,
315 IN ACCESS_MASK AccessMask
,
316 IN GUID
*ObjectTypeGuid OPTIONAL
,
317 IN GUID
*InheritedObjectTypeGuid OPTIONAL
,
324 /* make sure we call RtlpAddKnownAce correctly */
325 if (ObjectTypeGuid
!= NULL
|| InheritedObjectTypeGuid
!= NULL
)
326 Type
= ACCESS_ALLOWED_OBJECT_ACE_TYPE
;
328 Type
= ACCESS_ALLOWED_ACE_TYPE
;
330 return RtlpAddKnownAce (Acl
,
335 InheritedObjectTypeGuid
,
345 RtlAddAccessDeniedAce (PACL Acl
,
347 ACCESS_MASK AccessMask
,
352 return RtlpAddKnownAce (Acl
,
359 ACCESS_DENIED_ACE_TYPE
);
367 RtlAddAccessDeniedAceEx (IN OUT PACL Acl
,
370 IN ACCESS_MASK AccessMask
,
375 return RtlpAddKnownAce (Acl
,
382 ACCESS_DENIED_ACE_TYPE
);
390 RtlAddAccessDeniedObjectAce (IN OUT PACL Acl
,
393 IN ACCESS_MASK AccessMask
,
394 IN GUID
*ObjectTypeGuid OPTIONAL
,
395 IN GUID
*InheritedObjectTypeGuid OPTIONAL
,
402 /* make sure we call RtlpAddKnownAce correctly */
403 if (ObjectTypeGuid
!= NULL
|| InheritedObjectTypeGuid
!= NULL
)
404 Type
= ACCESS_DENIED_OBJECT_ACE_TYPE
;
406 Type
= ACCESS_DENIED_ACE_TYPE
;
408 return RtlpAddKnownAce (Acl
,
413 InheritedObjectTypeGuid
,
420 RtlpAddData(PVOID AceList
,
427 RtlCopyMemory((PVOID
)((ULONG_PTR
)Ace
+ AceListLength
),
432 if (AceListLength
!= 0)
458 if (Acl
->AclRevision
< MIN_ACL_REVISION
||
459 Acl
->AclRevision
> MAX_ACL_REVISION
||
460 !RtlFirstFreeAce(Acl
, &Ace
))
462 return(STATUS_INVALID_PARAMETER
);
465 if (Acl
->AclRevision
<= AclRevision
)
467 AclRevision
= Acl
->AclRevision
;
470 if (((ULONG_PTR
)AceList
+ AceListLength
) <= (ULONG_PTR
)AceList
)
472 return(STATUS_INVALID_PARAMETER
);
475 for (Current
= AceList
, NewAceCount
= 0;
476 (ULONG_PTR
)Current
< ((ULONG_PTR
)AceList
+ AceListLength
);
477 Current
= (PACE
)((ULONG_PTR
)Current
+ Current
->Header
.AceSize
),
480 if (((PACE
)AceList
)->Header
.AceType
== ACCESS_ALLOWED_COMPOUND_ACE_TYPE
&&
481 AclRevision
< ACL_REVISION3
)
483 return(STATUS_INVALID_PARAMETER
);
488 ((ULONG_PTR
)Ace
+ AceListLength
) > ((ULONG_PTR
)Acl
+ Acl
->AclSize
))
490 return(STATUS_BUFFER_TOO_SMALL
);
493 Current
= (PACE
)(Acl
+ 1);
494 for (Index
= 0; Index
< StartingIndex
&& Index
< Acl
->AceCount
; Index
++)
496 Current
= (PACE
)((ULONG_PTR
)Current
+ Current
->Header
.AceSize
);
502 (ULONG
)((ULONG_PTR
)Ace
- (ULONG_PTR
)Current
));
503 Acl
->AceCount
= Acl
->AceCount
+ NewAceCount
;
504 Acl
->AclRevision
= AclRevision
;
506 return(STATUS_SUCCESS
);
514 RtlAddAuditAccessAce(PACL Acl
,
516 ACCESS_MASK AccessMask
,
527 Flags
|= SUCCESSFUL_ACCESS_ACE_FLAG
;
532 Flags
|= FAILED_ACCESS_ACE_FLAG
;
535 return RtlpAddKnownAce (Acl
,
542 SYSTEM_AUDIT_ACE_TYPE
);
550 RtlAddAuditAccessAceEx(PACL Acl
,
553 ACCESS_MASK AccessMask
,
560 Flags
|= SUCCESSFUL_ACCESS_ACE_FLAG
;
565 Flags
|= FAILED_ACCESS_ACE_FLAG
;
568 return RtlpAddKnownAce (Acl
,
575 SYSTEM_AUDIT_ACE_TYPE
);
583 RtlAddAuditAccessObjectAce(PACL Acl
,
586 ACCESS_MASK AccessMask
,
587 IN GUID
*ObjectTypeGuid OPTIONAL
,
588 IN GUID
*InheritedObjectTypeGuid OPTIONAL
,
597 Flags
|= SUCCESSFUL_ACCESS_ACE_FLAG
;
602 Flags
|= FAILED_ACCESS_ACE_FLAG
;
605 /* make sure we call RtlpAddKnownAce correctly */
606 if (ObjectTypeGuid
!= NULL
|| InheritedObjectTypeGuid
!= NULL
)
607 Type
= SYSTEM_AUDIT_OBJECT_ACE_TYPE
;
609 Type
= SYSTEM_AUDIT_ACE_TYPE
;
611 return RtlpAddKnownAce (Acl
,
616 InheritedObjectTypeGuid
,
626 RtlAddMandatoryAce(IN OUT PACL Acl
,
629 IN ULONG MandatoryFlags
,
633 if (MandatoryFlags
& ~SYSTEM_MANDATORY_LABEL_VALID_MASK
)
634 return STATUS_INVALID_PARAMETER
;
636 if (AceType
!= SYSTEM_MANDATORY_LABEL_ACE_TYPE
)
637 return STATUS_INVALID_PARAMETER
;
639 return RtlpAddKnownAce (Acl
,
642 (ACCESS_MASK
)MandatoryFlags
,
651 RtlpDeleteData(PVOID Ace
,
655 if (AceSize
< Offset
)
658 (PVOID
)((ULONG_PTR
)Ace
+ AceSize
),
662 if (Offset
- AceSize
< Offset
)
664 RtlZeroMemory((PVOID
)((ULONG_PTR
)Ace
+ Offset
- AceSize
),
674 RtlDeleteAce(PACL Acl
,
682 if (Acl
->AclRevision
< MIN_ACL_REVISION
||
683 Acl
->AclRevision
> MAX_ACL_REVISION
||
684 Acl
->AceCount
<= AceIndex
||
685 !RtlFirstFreeAce(Acl
, &Ace
))
687 return(STATUS_INVALID_PARAMETER
);
690 Current
= (PACE
)(Acl
+ 1);
694 Current
= (PACE
)((ULONG_PTR
)Current
+ Current
->Header
.AceSize
);
697 RtlpDeleteData(Current
,
698 Current
->Header
.AceSize
,
699 (ULONG
)((ULONG_PTR
)Ace
- (ULONG_PTR
)Current
));
702 return(STATUS_SUCCESS
);
710 RtlCreateAcl(PACL Acl
,
716 if (AclSize
< sizeof(ACL
))
718 return(STATUS_BUFFER_TOO_SMALL
);
721 if (AclRevision
< MIN_ACL_REVISION
||
722 AclRevision
> MAX_ACL_REVISION
||
725 return(STATUS_INVALID_PARAMETER
);
728 AclSize
= ROUND_UP(AclSize
, 4);
729 Acl
->AclSize
= AclSize
;
730 Acl
->AclRevision
= AclRevision
;
735 return(STATUS_SUCCESS
);
743 RtlQueryInformationAcl(PACL Acl
,
745 ULONG InformationLength
,
746 ACL_INFORMATION_CLASS InformationClass
)
752 if (Acl
->AclRevision
< MIN_ACL_REVISION
||
753 Acl
->AclRevision
> MAX_ACL_REVISION
)
755 return(STATUS_INVALID_PARAMETER
);
758 switch (InformationClass
)
760 case AclRevisionInformation
:
762 PACL_REVISION_INFORMATION Info
= (PACL_REVISION_INFORMATION
)Information
;
764 if (InformationLength
< sizeof(ACL_REVISION_INFORMATION
))
766 return(STATUS_BUFFER_TOO_SMALL
);
768 Info
->AclRevision
= Acl
->AclRevision
;
772 case AclSizeInformation
:
774 PACL_SIZE_INFORMATION Info
= (PACL_SIZE_INFORMATION
)Information
;
776 if (InformationLength
< sizeof(ACL_SIZE_INFORMATION
))
778 return(STATUS_BUFFER_TOO_SMALL
);
781 if (!RtlFirstFreeAce(Acl
, &Ace
))
783 return(STATUS_INVALID_PARAMETER
);
786 Info
->AceCount
= Acl
->AceCount
;
789 Info
->AclBytesInUse
= (DWORD
)((ULONG_PTR
)Ace
- (ULONG_PTR
)Acl
);
790 Info
->AclBytesFree
= Acl
->AclSize
- Info
->AclBytesInUse
;
794 Info
->AclBytesInUse
= Acl
->AclSize
;
795 Info
->AclBytesFree
= 0;
801 return(STATUS_INVALID_INFO_CLASS
);
804 return(STATUS_SUCCESS
);
812 RtlSetInformationAcl(PACL Acl
,
814 ULONG InformationLength
,
815 ACL_INFORMATION_CLASS InformationClass
)
819 if (Acl
->AclRevision
< MIN_ACL_REVISION
||
820 Acl
->AclRevision
> MAX_ACL_REVISION
)
822 return(STATUS_INVALID_PARAMETER
);
825 switch (InformationClass
)
827 case AclRevisionInformation
:
829 PACL_REVISION_INFORMATION Info
= (PACL_REVISION_INFORMATION
)Information
;
831 if (InformationLength
< sizeof(ACL_REVISION_INFORMATION
))
833 return(STATUS_BUFFER_TOO_SMALL
);
836 if (Acl
->AclRevision
>= Info
->AclRevision
)
838 return(STATUS_INVALID_PARAMETER
);
841 Acl
->AclRevision
= Info
->AclRevision
;
846 return(STATUS_INVALID_INFO_CLASS
);
849 return(STATUS_SUCCESS
);
857 RtlValidAcl (PACL Acl
)
864 Size
= ROUND_UP(Acl
->AclSize
, 4);
866 if (Acl
->AclRevision
< MIN_ACL_REVISION
||
867 Acl
->AclRevision
> MAX_ACL_REVISION
)
872 if (Size
!= Acl
->AclSize
)
877 return(RtlFirstFreeAce(Acl
, &Ace
));