Author: ion Date: Wed Sep 19 02:32:58 2012 New Revision: 57331
URL: http://svn.reactos.org/svn/reactos?rev=57331&view=rev Log: [RTL]: Cleanup all the ACL functions. Mostly refactoring, commenting and styling, but there are a few important changes. First, RtlValidateAcl actually does the whole ACL validation algorithm. Second, mandatory label ACEs are not supported, because we shouldn't lie about Vista features in ntdll/kernel code.
Modified: trunk/reactos/dll/ntdll/def/ntdll.spec trunk/reactos/dll/win32/advapi32/advapi32.spec trunk/reactos/dll/win32/advapi32/sec/ac.c trunk/reactos/dll/win32/lsasrv/lsasrv.c trunk/reactos/lib/rtl/acl.c
Modified: trunk/reactos/dll/ntdll/def/ntdll.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.spec?re... ============================================================================== --- trunk/reactos/dll/ntdll/def/ntdll.spec [iso-8859-1] (original) +++ trunk/reactos/dll/ntdll/def/ntdll.spec [iso-8859-1] Wed Sep 19 02:32:58 2012 @@ -435,7 +435,7 @@ ;@ stdcall RtlAddCompoundAce ;@ stdcall RtlAddRange ; 5.0 and 5.1 only @ stdcall -arch=x86_64 RtlAddFunctionTable(ptr long long) -@ stdcall RtlAddMandatoryAce(ptr long long long long ptr) +;@ stdcall RtlAddMandatoryAce(ptr long long long long ptr) @ stdcall RtlAddRefActivationContext(ptr) ;@ stdcall RtlAddRefMemoryStream @ stdcall RtlAddVectoredContinueHandler(long ptr)
Modified: trunk/reactos/dll/win32/advapi32/advapi32.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/advapi32... ============================================================================== --- trunk/reactos/dll/win32/advapi32/advapi32.spec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/advapi32/advapi32.spec [iso-8859-1] Wed Sep 19 02:32:58 2012 @@ -24,7 +24,7 @@ @ stdcall AddAuditAccessAce(ptr long long ptr long long) @ stdcall AddAuditAccessAceEx(ptr long long long ptr long long) @ stdcall AddAuditAccessObjectAce(ptr long long long ptr ptr ptr long long) -@ stdcall AddMandatoryAce(ptr long long long ptr) +;@ stdcall AddMandatoryAce(ptr long long long ptr) @ stdcall AddUsersToEncryptedFile(wstr ptr) @ stdcall AdjustTokenGroups(long long ptr long ptr ptr) @ stdcall AdjustTokenPrivileges(long long ptr long ptr ptr)
Modified: trunk/reactos/dll/win32/advapi32/sec/ac.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/sec/ac.c... ============================================================================== --- trunk/reactos/dll/win32/advapi32/sec/ac.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/advapi32/sec/ac.c [iso-8859-1] Wed Sep 19 02:32:58 2012 @@ -393,36 +393,6 @@
return TRUE; } - - -/* - * @implemented - */ -BOOL -WINAPI -AddMandatoryAce(IN OUT PACL pAcl, - IN DWORD dwAceRevision, - IN DWORD AceFlags, - IN DWORD MandatoryPolicy, - IN PSID pLabelSid) -{ - NTSTATUS Status; - - Status = RtlAddMandatoryAce(pAcl, - dwAceRevision, - AceFlags, - MandatoryPolicy, - SYSTEM_MANDATORY_LABEL_ACE_TYPE, - pLabelSid); - if (!NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return FALSE; - } - - return TRUE; -} -
/* * @implemented
Modified: trunk/reactos/dll/win32/lsasrv/lsasrv.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/lsasrv/lsasrv.c?r... ============================================================================== --- trunk/reactos/dll/win32/lsasrv/lsasrv.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/lsasrv/lsasrv.c [iso-8859-1] Wed Sep 19 02:32:58 2012 @@ -32,7 +32,7 @@ /* Start the RPC server */ LsarStartRpcServer();
- TRACE("Creating notification event!\n"); + DbgPrint("Creating notification event!\n"); /* Notify the service manager */ hEvent = CreateEventW(NULL, TRUE, @@ -41,7 +41,7 @@ if (hEvent == NULL) { dwError = GetLastError(); - TRACE("Failed to create the notication event (Error %lu)\n", dwError); + DbgPrint("Failed to create the notication event (Error %lu)\n", dwError);
if (dwError == ERROR_ALREADY_EXISTS) { @@ -50,13 +50,13 @@ L"LSA_RPC_SERVER_ACTIVE"); if (hEvent == NULL) { - ERR("Could not open the notification event (Error %lu)\n", GetLastError()); + DbgPrint("Could not open the notification event (Error %lu)\n", GetLastError()); return STATUS_UNSUCCESSFUL; } } }
- TRACE("Set notification event!\n"); + DbgPrint("Set notification event!\n"); SetEvent(hEvent);
/* NOTE: Do not close the event handle!!!! */
Modified: trunk/reactos/lib/rtl/acl.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/acl.c?rev=57331&... ============================================================================== --- trunk/reactos/lib/rtl/acl.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/acl.c [iso-8859-1] Wed Sep 19 02:32:58 2012 @@ -8,885 +8,958 @@ /* INCLUDES *****************************************************************/
#include <rtl.h> - +#include <../../ntoskrnl/include/internal/se.h> #define NDEBUG #include <debug.h>
-/* FUNCTIONS ***************************************************************/ +/* PRIVATE FUNCTIONS **********************************************************/
BOOLEAN NTAPI -RtlFirstFreeAce( - PACL Acl, - PACE* Ace) +RtlFirstFreeAce(IN PACL Acl, + OUT PACE* FirstFreeAce) { PACE Current; ULONG_PTR AclEnd; ULONG i; PAGED_CODE_RTL();
+ /* Assume failure */ + *FirstFreeAce = NULL; + + /* Get the start and end pointers */ Current = (PACE)(Acl + 1); - *Ace = NULL; - - if (Acl->AceCount == 0) - { - *Ace = Current; - return TRUE; - } - - i = 0; AclEnd = (ULONG_PTR)Acl + Acl->AclSize; - do - { - if ((ULONG_PTR)Current >= AclEnd) - { - return FALSE; - } - if (Current->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE && - Acl->AclRevision < ACL_REVISION3) - { - return FALSE; - } + + /* Loop all the ACEs */ + for (i = 0; i < Acl->AceCount; i++) + { + /* If any is beyond the DACL, bail out, otherwise keep going */ + if ((ULONG_PTR)Current >= AclEnd) return FALSE; Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize); } - while (++i < Acl->AceCount); - - if ((ULONG_PTR)Current < AclEnd) - { - *Ace = Current; - } - + + /* If the last spot is empty and still valid, return it */ + if ((ULONG_PTR)Current < AclEnd) *FirstFreeAce = Current; return TRUE; }
- -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlGetAce( - PACL Acl, - ULONG AceIndex, - PVOID *Ace) +VOID +NTAPI +RtlpAddData(IN PVOID AceList, + IN ULONG AceListLength, + IN PVOID Ace, + IN ULONG Offset) +{ + /* Shift the buffer down */ + if (Offset > 0) + { + RtlCopyMemory((PVOID)((ULONG_PTR)Ace + AceListLength), + Ace, + Offset); + } + + /* Copy the new data in */ + if (AceListLength) RtlCopyMemory(Ace, AceList, AceListLength); +} + +VOID +NTAPI +RtlpDeleteData(IN PVOID Ace, + IN ULONG AceSize, + IN ULONG Offset) +{ + /* Move the data up */ + if (AceSize < Offset) + { + RtlMoveMemory(Ace, + (PVOID)((ULONG_PTR)Ace + AceSize), + Offset - AceSize); + } + + /* Zero the rest */ + if ((Offset - AceSize) < Offset) + { + RtlZeroMemory((PVOID)((ULONG_PTR)Ace + Offset - AceSize), AceSize); + } +} + +NTSTATUS +NTAPI +RtlpAddKnownAce(IN PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN PSID Sid, + IN UCHAR Type) +{ + PKNOWN_ACE Ace; + ULONG AceSize, InvalidFlags; + PAGED_CODE_RTL(); + + /* Check the validity of the SID */ + if (!RtlValidSid(Sid)) return STATUS_INVALID_SID; + + /* Check the validity of the revision */ + if ((Acl->AclRevision > ACL_REVISION4) || (Revision > ACL_REVISION4)) + { + return STATUS_REVISION_MISMATCH; + } + + /* Pick the smallest of the revisions */ + if (Revision < Acl->AclRevision) Revision = Acl->AclRevision; + + /* Validate the flags */ + if (Type == SYSTEM_AUDIT_ACE_TYPE) + { + InvalidFlags = Flags & ~(VALID_INHERIT_FLAGS | + SUCCESSFUL_ACCESS_ACE_FLAG | + FAILED_ACCESS_ACE_FLAG); + } + else + { + InvalidFlags = Flags & ~VALID_INHERIT_FLAGS; + } + + /* If flags are invalid, bail out */ + if (InvalidFlags != 0) return STATUS_INVALID_PARAMETER; + + /* If ACL is invalid, bail out */ + if (!RtlValidAcl(Acl)) return STATUS_INVALID_ACL; + + /* If there's no free ACE, bail out */ + if (!RtlFirstFreeAce(Acl, (PACE*)&Ace)) return STATUS_INVALID_ACL; + + /* Calculate the size of the ACE and bail out if it's too small */ + AceSize = RtlLengthSid(Sid) + sizeof(ACE); + if (!(Ace) || ((ULONG_PTR)Ace + AceSize > (ULONG_PTR)Acl + Acl->AclSize)) + { + return STATUS_ALLOTTED_SPACE_EXCEEDED; + } + + /* Initialize the header and common fields */ + Ace->Header.AceFlags = (BYTE)Flags; + Ace->Header.AceType = Type; + Ace->Header.AceSize = (WORD)AceSize; + Ace->Mask = AccessMask; + + /* Copy the SID */ + RtlCopySid(RtlLengthSid(Sid), &Ace->SidStart, Sid); + + /* Fill out the ACL header and return */ + Acl->AceCount++; + Acl->AclRevision = (BYTE)Revision; + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +RtlpAddKnownObjectAce(IN PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid, + IN UCHAR Type) +{ + PKNOWN_OBJECT_ACE Ace; + ULONG_PTR SidStart; + ULONG AceSize, InvalidFlags, AceObjectFlags = 0; + PAGED_CODE_RTL(); + + /* Check the validity of the SID */ + if (!RtlValidSid(Sid)) return STATUS_INVALID_SID; + + /* Check the validity of the revision */ + if ((Acl->AclRevision > ACL_REVISION4) || (Revision > ACL_REVISION4)) + { + return STATUS_REVISION_MISMATCH; + } + + /* Pick the smallest of the revisions */ + if (Revision < Acl->AclRevision) Revision = Acl->AclRevision; + + /* Validate the flags */ + if ((Type == SYSTEM_AUDIT_OBJECT_ACE_TYPE) || + (Type == SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE)) + { + InvalidFlags = Flags & ~(VALID_INHERIT_FLAGS | + SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG); + } + else + { + InvalidFlags = Flags & ~VALID_INHERIT_FLAGS; + } + + /* If flags are invalid, bail out */ + if (InvalidFlags != 0) return STATUS_INVALID_PARAMETER; + + /* If ACL is invalid, bail out */ + if (!RtlValidAcl(Acl)) return STATUS_INVALID_ACL; + + /* If there's no free ACE, bail out */ + if (!RtlFirstFreeAce(Acl, (PACE*)&Ace)) return STATUS_INVALID_ACL; + + /* Calculate the size of the ACE */ + AceSize = RtlLengthSid(Sid) + sizeof(ACE) + sizeof(ULONG); + + /* Add-in the size of the GUIDs if any and update flags as needed */ + if (ObjectTypeGuid) + { + AceObjectFlags |= ACE_OBJECT_TYPE_PRESENT; + AceSize += sizeof(GUID); + } + if (InheritedObjectTypeGuid) + { + AceObjectFlags |= ACE_INHERITED_OBJECT_TYPE_PRESENT; + AceSize += sizeof(GUID); + } + + /* Bail out if there's not enough space in the ACL */ + if (!(Ace) || ((ULONG_PTR)Ace + AceSize > (ULONG_PTR)Acl + Acl->AclSize)) + { + return STATUS_ALLOTTED_SPACE_EXCEEDED; + } + + /* Initialize the header and common fields */ + Ace->Header.AceFlags = (BYTE)Flags; + Ace->Header.AceType = Type; + Ace->Header.AceSize = (WORD)AceSize; + Ace->Mask = AccessMask; + Ace->Flags = AceObjectFlags; + + /* Copy the GUIDs */ + SidStart = (ULONG_PTR)&Ace->SidStart; + if (ObjectTypeGuid ) + { + RtlCopyMemory((PVOID)SidStart, ObjectTypeGuid, sizeof(GUID)); + SidStart += sizeof(GUID); + } + if (InheritedObjectTypeGuid) + { + RtlCopyMemory((PVOID)SidStart, InheritedObjectTypeGuid, sizeof(GUID)); + SidStart += sizeof(GUID); + } + + /* Copy the SID */ + RtlCopySid(RtlLengthSid(Sid), (PSID)SidStart, Sid); + + /* Fill out the ACL header and return */ + Acl->AceCount++; + Acl->AclRevision = (BYTE)Revision; + return STATUS_SUCCESS; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAccessAllowedAce(IN OUT PACL Acl, + IN ULONG Revision, + IN ACCESS_MASK AccessMask, + IN PSID Sid) +{ + PAGED_CODE_RTL(); + + /* Call the worker function */ + return RtlpAddKnownAce(Acl, + Revision, + 0, + AccessMask, + Sid, + ACCESS_ALLOWED_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAccessAllowedAceEx(IN OUT PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN PSID Sid) +{ + PAGED_CODE_RTL(); + + /* Call the worker function */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + ACCESS_ALLOWED_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAccessAllowedObjectAce(IN OUT PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid) +{ + PAGED_CODE_RTL(); + + /* Is there no object data? */ + if (!(ObjectTypeGuid) && !(InheritedObjectTypeGuid)) + { + /* Use the usual routine */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + ACCESS_ALLOWED_ACE_TYPE); + } + + /* Use the object routine */ + return RtlpAddKnownObjectAce(Acl, + Revision, + Flags, + AccessMask, + ObjectTypeGuid, + InheritedObjectTypeGuid, + Sid, + ACCESS_ALLOWED_OBJECT_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAccessDeniedAce(IN PACL Acl, + IN ULONG Revision, + IN ACCESS_MASK AccessMask, + IN PSID Sid) +{ + PAGED_CODE_RTL(); + + /* Call the worker function */ + return RtlpAddKnownAce(Acl, + Revision, + 0, + AccessMask, + Sid, + ACCESS_DENIED_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAccessDeniedAceEx(IN OUT PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN PSID Sid) +{ + PAGED_CODE_RTL(); + + /* Call the worker function */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + ACCESS_DENIED_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAccessDeniedObjectAce(IN OUT PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid) +{ + PAGED_CODE_RTL(); + + /* Is there no object data? */ + if (!(ObjectTypeGuid) && !(InheritedObjectTypeGuid)) + { + /* Use the usual routine */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + ACCESS_DENIED_ACE_TYPE); + } + + /* There's object data, use the object routine */ + return RtlpAddKnownObjectAce(Acl, + Revision, + Flags, + AccessMask, + ObjectTypeGuid, + InheritedObjectTypeGuid, + Sid, + ACCESS_DENIED_OBJECT_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAuditAccessAce(IN PACL Acl, + IN ULONG Revision, + IN ACCESS_MASK AccessMask, + IN PSID Sid, + IN BOOLEAN Success, + IN BOOLEAN Failure) +{ + ULONG Flags = 0; + PAGED_CODE_RTL(); + + /* Add flags */ + if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; + if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG; + + /* Call the worker routine */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + SYSTEM_AUDIT_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAuditAccessAceEx(IN PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN PSID Sid, + IN BOOLEAN Success, + IN BOOLEAN Failure) +{ + PAGED_CODE_RTL(); + + /* Add flags */ + if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; + if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG; + + /* Call the worker routine */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + SYSTEM_AUDIT_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAuditAccessObjectAce(IN PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID Sid, + IN BOOLEAN Success, + IN BOOLEAN Failure) +{ + /* Add flags */ + if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; + if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG; + + /* Is there no object data? */ + if (!(ObjectTypeGuid) && !(InheritedObjectTypeGuid)) + { + /* Call the normal routine */ + return RtlpAddKnownAce(Acl, + Revision, + Flags, + AccessMask, + Sid, + SYSTEM_AUDIT_ACE_TYPE); + } + + /* There's object data, use the object routine */ + return RtlpAddKnownObjectAce(Acl, + Revision, + Flags, + AccessMask, + ObjectTypeGuid, + InheritedObjectTypeGuid, + Sid, + SYSTEM_AUDIT_OBJECT_ACE_TYPE); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlGetAce(IN PACL Acl, + IN ULONG AceIndex, + OUT PVOID *Ace) { ULONG i; PAGED_CODE_RTL();
- if (Acl->AclRevision < MIN_ACL_REVISION || - Acl->AclRevision > MAX_ACL_REVISION || - AceIndex >= Acl->AceCount) + /* Bail out if the revision or the index are invalid */ + if ((Acl->AclRevision < MIN_ACL_REVISION) || + (Acl->AclRevision > MAX_ACL_REVISION) || + (AceIndex >= Acl->AceCount)) { return STATUS_INVALID_PARAMETER; }
+ /* Loop through the ACEs */ *Ace = (PVOID)((PACE)(Acl + 1)); - for (i = 0; i < AceIndex; i++) { + /* Bail out if an invalid ACE is ever found */ if ((ULONG_PTR)*Ace >= (ULONG_PTR)Acl + Acl->AclSize) { return STATUS_INVALID_PARAMETER; } + + /* Keep going */ *Ace = (PVOID)((PACE)((ULONG_PTR)(*Ace) + ((PACE)(*Ace))->Header.AceSize)); }
+ /* Check if the last ACE is still valid */ if ((ULONG_PTR)*Ace >= (ULONG_PTR)Acl + Acl->AclSize) { return STATUS_INVALID_PARAMETER; }
+ /* All good, return */ return STATUS_SUCCESS; }
- -static -NTSTATUS -RtlpAddKnownAce( - PACL Acl, - ULONG Revision, - ULONG Flags, - ACCESS_MASK AccessMask, - GUID *ObjectTypeGuid OPTIONAL, - GUID *InheritedObjectTypeGuid OPTIONAL, - PSID Sid, - UCHAR Type) -{ - PACE Ace; - PSID SidStart; - ULONG AceSize, InvalidFlags; - ULONG AceObjectFlags = 0; - PAGED_CODE_RTL(); - -#if DBG - /* check if RtlpAddKnownAce was called incorrectly */ - if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL) - { - ASSERT(Type == ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE || - Type == ACCESS_ALLOWED_OBJECT_ACE_TYPE || - Type == ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE || - Type == ACCESS_DENIED_OBJECT_ACE_TYPE || - Type == SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE || - Type == SYSTEM_AUDIT_OBJECT_ACE_TYPE); - } - else - { - ASSERT(Type != ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE && - Type != ACCESS_ALLOWED_OBJECT_ACE_TYPE && - Type != ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE && - Type != ACCESS_DENIED_OBJECT_ACE_TYPE && - Type != SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE && - Type != SYSTEM_AUDIT_OBJECT_ACE_TYPE); - } -#endif - - if (!RtlValidSid(Sid)) - { - return STATUS_INVALID_SID; - } - - if (Type == SYSTEM_MANDATORY_LABEL_ACE_TYPE) - { - static const SID_IDENTIFIER_AUTHORITY MandatoryLabelAuthority = {SECURITY_MANDATORY_LABEL_AUTHORITY}; - - /* The SID's identifier authority must be SECURITY_MANDATORY_LABEL_AUTHORITY! */ - if (RtlCompareMemory(&((PISID)Sid)->IdentifierAuthority, - &MandatoryLabelAuthority, - sizeof(MandatoryLabelAuthority)) != sizeof(MandatoryLabelAuthority)) +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlAddAce(IN PACL Acl, + IN ULONG AclRevision, + IN ULONG StartingIndex, + IN PVOID AceList, + IN ULONG AceListLength) +{ + PACE Ace, FreeAce; + USHORT NewAceCount; + ULONG Index; + PAGED_CODE_RTL(); + + /* Bail out if the ACL is invalid */ + if (!RtlValidAcl(Acl)) return STATUS_INVALID_PARAMETER; + + /* Bail out if there's no space */ + if (!RtlFirstFreeAce(Acl, &FreeAce)) return STATUS_INVALID_PARAMETER; + + /* Always use the smaller revision */ + if (Acl->AclRevision <= AclRevision) AclRevision = Acl->AclRevision; + + /* Loop over all the ACEs, keeping track of new ACEs as we go along */ + for (Ace = AceList, NewAceCount = 0; + Ace < (PACE)((ULONG_PTR)AceList + AceListLength); + NewAceCount++) + { + /* Make sure that the revision of this ACE is valid in this list */ + if (Ace->Header.AceType <= ACCESS_MAX_MS_V3_ACE_TYPE) { - return STATUS_INVALID_PARAMETER; + if (AclRevision < ACL_REVISION3) return STATUS_INVALID_PARAMETER; } - } - - if (Acl->AclRevision > MAX_ACL_REVISION || - Revision > MAX_ACL_REVISION) - { - return STATUS_UNKNOWN_REVISION; - } - - if (Revision < Acl->AclRevision) - { - Revision = Acl->AclRevision; - } - - /* Validate the flags */ - if (Type == SYSTEM_AUDIT_ACE_TYPE || - Type == SYSTEM_AUDIT_OBJECT_ACE_TYPE || - Type == SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE) - { - InvalidFlags = Flags & ~(VALID_INHERIT_FLAGS | - SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG); - } - else - { - InvalidFlags = Flags & ~VALID_INHERIT_FLAGS; - } - - if (InvalidFlags != 0) + else if (Ace->Header.AceType <= ACCESS_MAX_MS_V4_ACE_TYPE) + { + if (AclRevision < ACL_REVISION4) return STATUS_INVALID_PARAMETER; + } + + /* Move to the next ACE */ + Ace = (PACE)((ULONG_PTR)Ace + Ace->Header.AceSize); + } + + /* Bail out if there's no more space for us */ + if ((ULONG_PTR)Ace > ((ULONG_PTR)AceList + AceListLength)) { return STATUS_INVALID_PARAMETER; }
- if (!RtlFirstFreeAce(Acl, &Ace)) - { - return STATUS_INVALID_ACL; - } - if (Ace == NULL) - { - return STATUS_ALLOTTED_SPACE_EXCEEDED; - } - - /* Calculate the size of the ACE */ - AceSize = RtlLengthSid(Sid) + sizeof(ACE); - if (ObjectTypeGuid != NULL) - { - AceObjectFlags |= ACE_OBJECT_TYPE_PRESENT; - AceSize += sizeof(GUID); - } - if (InheritedObjectTypeGuid != NULL) - { - AceObjectFlags |= ACE_INHERITED_OBJECT_TYPE_PRESENT; - AceSize += sizeof(GUID); - } - - if (AceObjectFlags != 0) - { - /* Don't forget the ACE object flags - (corresponds to the Flags field in the *_OBJECT_ACE structures) */ - AceSize += sizeof(ULONG); - } - - if ((ULONG_PTR)Ace + AceSize > - (ULONG_PTR)Acl + Acl->AclSize) - { - return STATUS_ALLOTTED_SPACE_EXCEEDED; - } - - /* initialize the header and common fields */ - Ace->Header.AceFlags = (BYTE)Flags; - Ace->Header.AceType = Type; - Ace->Header.AceSize = (WORD)AceSize; - Ace->AccessMask = AccessMask; - - if (AceObjectFlags != 0) - { - /* Write the ACE flags to the ACE - (corresponds to the Flags field in the *_OBJECT_ACE structures) */ - *(PULONG)(Ace + 1) = AceObjectFlags; - SidStart = (PSID)((ULONG_PTR)(Ace + 1) + sizeof(ULONG)); - } - else - SidStart = (PSID)(Ace + 1); - - /* copy the GUIDs */ - if (ObjectTypeGuid != NULL) - { - RtlCopyMemory(SidStart, ObjectTypeGuid, sizeof(GUID)); - SidStart = (PSID)((ULONG_PTR)SidStart + sizeof(GUID)); - } - if (InheritedObjectTypeGuid != NULL) - { - RtlCopyMemory(SidStart, InheritedObjectTypeGuid, sizeof(GUID)); - SidStart = (PSID)((ULONG_PTR)SidStart + sizeof(GUID)); - } - - /* copy the SID */ - RtlCopySid(RtlLengthSid(Sid), SidStart, Sid); - Acl->AceCount++; - Acl->AclRevision = (BYTE)Revision; - - return STATUS_SUCCESS; -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAccessAllowedAce( - IN OUT PACL Acl, - IN ULONG Revision, - IN ACCESS_MASK AccessMask, - IN PSID Sid) -{ - PAGED_CODE_RTL(); - - return RtlpAddKnownAce(Acl, - Revision, - 0, - AccessMask, - NULL, - NULL, - Sid, - ACCESS_ALLOWED_ACE_TYPE); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAccessAllowedAceEx( - IN OUT PACL Acl, - IN ULONG Revision, - IN ULONG Flags, - IN ACCESS_MASK AccessMask, - IN PSID Sid) -{ - PAGED_CODE_RTL(); - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - NULL, - NULL, - Sid, - ACCESS_ALLOWED_ACE_TYPE); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAccessAllowedObjectAce( - IN OUT PACL Acl, - IN ULONG Revision, - IN ULONG Flags, - IN ACCESS_MASK AccessMask, - IN GUID *ObjectTypeGuid OPTIONAL, - IN GUID *InheritedObjectTypeGuid OPTIONAL, - IN PSID Sid) -{ - UCHAR Type; - PAGED_CODE_RTL(); - - /* make sure we call RtlpAddKnownAce correctly */ - if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL) - Type = ACCESS_ALLOWED_OBJECT_ACE_TYPE; - else - Type = ACCESS_ALLOWED_ACE_TYPE; - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - ObjectTypeGuid, - InheritedObjectTypeGuid, - Sid, - Type); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAccessDeniedAce( - PACL Acl, - ULONG Revision, - ACCESS_MASK AccessMask, - PSID Sid) -{ - PAGED_CODE_RTL(); - - return RtlpAddKnownAce(Acl, - Revision, - 0, - AccessMask, - NULL, - NULL, - Sid, - ACCESS_DENIED_ACE_TYPE); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAccessDeniedAceEx( - IN OUT PACL Acl, - IN ULONG Revision, - IN ULONG Flags, - IN ACCESS_MASK AccessMask, - IN PSID Sid) -{ - PAGED_CODE_RTL(); - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - NULL, - NULL, - Sid, - ACCESS_DENIED_ACE_TYPE); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAccessDeniedObjectAce( - IN OUT PACL Acl, - IN ULONG Revision, - IN ULONG Flags, - IN ACCESS_MASK AccessMask, - IN GUID *ObjectTypeGuid OPTIONAL, - IN GUID *InheritedObjectTypeGuid OPTIONAL, - IN PSID Sid) -{ - UCHAR Type; - PAGED_CODE_RTL(); - - /* make sure we call RtlpAddKnownAce correctly */ - if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL) - Type = ACCESS_DENIED_OBJECT_ACE_TYPE; - else - Type = ACCESS_DENIED_ACE_TYPE; - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - ObjectTypeGuid, - InheritedObjectTypeGuid, - Sid, - Type); -} - - -static -VOID -RtlpAddData( - PVOID AceList, - ULONG AceListLength, - PVOID Ace, - ULONG Offset) -{ - if (Offset > 0) - { - RtlCopyMemory((PVOID)((ULONG_PTR)Ace + AceListLength), - Ace, - Offset); - } - - if (AceListLength != 0) - { - RtlCopyMemory(Ace, AceList, AceListLength); - } -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAce( - PACL Acl, - ULONG AclRevision, - ULONG StartingIndex, - PVOID AceList, - ULONG AceListLength) -{ - PACE Ace; - PACE Current; - WORD NewAceCount; - ULONG Index; - PAGED_CODE_RTL(); - - /* Make sure, the ACL is valid */ - if (Acl->AclRevision < MIN_ACL_REVISION || - Acl->AclRevision > MAX_ACL_REVISION || - !RtlFirstFreeAce(Acl, &Ace)) - { - return STATUS_INVALID_PARAMETER; - } - - /* Check if the ACL revision is smaller than the given one */ - if (Acl->AclRevision <= AclRevision) - { - /* Update the revision to the given one */ - AclRevision = Acl->AclRevision; - } - - if (((ULONG_PTR)AceList + AceListLength) <= (ULONG_PTR)AceList) - { - return STATUS_INVALID_PARAMETER; - } - - for (Current = AceList, NewAceCount = 0; - (ULONG_PTR)Current < ((ULONG_PTR)AceList + AceListLength); - Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize), - ++NewAceCount) - { - if (((PACE)AceList)->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE && - AclRevision < ACL_REVISION3) - { - return STATUS_INVALID_PARAMETER; - } - } - - if (Ace == NULL || - ((ULONG_PTR)Ace + AceListLength) > ((ULONG_PTR)Acl + Acl->AclSize)) + /* Bail out if there's no free ACE spot, or if we would overflow it */ + if (!(FreeAce) || + ((ULONG_PTR)FreeAce + AceListLength > (ULONG_PTR)Acl + Acl->AclSize)) { return STATUS_BUFFER_TOO_SMALL; }
- Current = (PACE)(Acl + 1); - for (Index = 0; Index < StartingIndex && Index < Acl->AceCount; Index++) - { - Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize); - } - + /* Go down the list until we find our index */ + Ace = (PACE)(Acl + 1); + for (Index = 0; (Index < StartingIndex) && (Index < Acl->AceCount); Index++) + { + Ace = (PACE)((ULONG_PTR)Ace + Ace->Header.AceSize); + } + + /* Found where we want to do, add us to the list */ RtlpAddData(AceList, AceListLength, - Current, - (ULONG)((ULONG_PTR)Ace - (ULONG_PTR)Current)); - + Ace, + (ULONG_PTR)FreeAce - (ULONG_PTR)Ace); + + /* Fill out the header and return */ Acl->AceCount = Acl->AceCount + NewAceCount; - Acl->AclRevision = (BYTE)AclRevision; - + Acl->AclRevision = (UCHAR)AclRevision; return STATUS_SUCCESS; }
- -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAuditAccessAce( - PACL Acl, - ULONG Revision, - ACCESS_MASK AccessMask, - PSID Sid, - BOOLEAN Success, - BOOLEAN Failure) -{ - ULONG Flags = 0; - PAGED_CODE_RTL(); - - if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; - if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG; - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - NULL, - NULL, - Sid, - SYSTEM_AUDIT_ACE_TYPE); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAuditAccessAceEx( - PACL Acl, - ULONG Revision, - ULONG Flags, - ACCESS_MASK AccessMask, - PSID Sid, - BOOLEAN Success, - BOOLEAN Failure) -{ - if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; - if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG; - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - NULL, - NULL, - Sid, - SYSTEM_AUDIT_ACE_TYPE); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddAuditAccessObjectAce( - PACL Acl, - ULONG Revision, - ULONG Flags, - ACCESS_MASK AccessMask, - IN GUID *ObjectTypeGuid OPTIONAL, - IN GUID *InheritedObjectTypeGuid OPTIONAL, - PSID Sid, - BOOLEAN Success, - BOOLEAN Failure) -{ - UCHAR Type; - - if (Success) - { - Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; - } - - if (Failure) - { - Flags |= FAILED_ACCESS_ACE_FLAG; - } - - /* make sure we call RtlpAddKnownAce correctly */ - if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL) - Type = SYSTEM_AUDIT_OBJECT_ACE_TYPE; - else - Type = SYSTEM_AUDIT_ACE_TYPE; - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - AccessMask, - ObjectTypeGuid, - InheritedObjectTypeGuid, - Sid, - Type); -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlAddMandatoryAce( - IN OUT PACL Acl, - IN ULONG Revision, - IN ULONG Flags, - IN ULONG MandatoryFlags, - IN UCHAR AceType, - IN PSID LabelSid) -{ - if (MandatoryFlags & ~SYSTEM_MANDATORY_LABEL_VALID_MASK) +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlDeleteAce(IN PACL Acl, + IN ULONG AceIndex) +{ + PACE FreeAce, Ace; + PAGED_CODE_RTL(); + + /* Bail out if the ACL is invalid */ + if (!RtlValidAcl(Acl)) return STATUS_INVALID_PARAMETER; + + /* Bail out if there's no space or if we're full */ + if ((Acl->AceCount <= AceIndex) || !(RtlFirstFreeAce(Acl, &FreeAce))) + { return STATUS_INVALID_PARAMETER; - - if (AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) + } + + /* Enumerate until the indexed ACE is reached */ + Ace = (PACE)(Acl + 1); + while (AceIndex--) Ace = (PACE)((ULONG_PTR)Ace + Ace->Header.AceSize); + + /* Delete this ACE */ + RtlpDeleteData(Ace, + Ace->Header.AceSize, + (ULONG)((ULONG_PTR)FreeAce - (ULONG_PTR)Ace)); + + /* Decrease an ACE and return success */ + Acl->AceCount--; + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlCreateAcl(IN PACL Acl, + IN ULONG AclSize, + IN ULONG AclRevision) +{ + PAGED_CODE_RTL(); + + /* Bail out if too small */ + if (AclSize < sizeof(ACL)) return STATUS_BUFFER_TOO_SMALL; + + /* Bail out if too large or invalid revision */ + if ((AclRevision < MIN_ACL_REVISION) || + (AclRevision > MAX_ACL_REVISION) || + (AclSize > MAXUSHORT)) + { return STATUS_INVALID_PARAMETER; - - return RtlpAddKnownAce(Acl, - Revision, - Flags, - (ACCESS_MASK)MandatoryFlags, - NULL, - NULL, - LabelSid, - AceType); -} - - -static -VOID -RtlpDeleteData( - PVOID Ace, - ULONG AceSize, - ULONG Offset) -{ - if (AceSize < Offset) - { - RtlMoveMemory(Ace, - (PVOID)((ULONG_PTR)Ace + AceSize), - Offset - AceSize); - } - - if (Offset - AceSize < Offset) - { - RtlZeroMemory((PVOID)((ULONG_PTR)Ace + Offset - AceSize), AceSize); - } -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlDeleteAce( - PACL Acl, - ULONG AceIndex) -{ - PACE Ace; - PACE Current; - PAGED_CODE_RTL(); - - if (Acl->AclRevision < MIN_ACL_REVISION || - Acl->AclRevision > MAX_ACL_REVISION || - Acl->AceCount <= AceIndex || - !RtlFirstFreeAce(Acl, &Ace)) - { - return STATUS_INVALID_PARAMETER; - } - - Current = (PACE)(Acl + 1); - - while(AceIndex--) - { - Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize); - } - - RtlpDeleteData(Current, - Current->Header.AceSize, - (ULONG)((ULONG_PTR)Ace - (ULONG_PTR)Current)); - Acl->AceCount--; - - return STATUS_SUCCESS; -} - - -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlCreateAcl( - PACL Acl, - ULONG AclSize, - ULONG AclRevision) -{ - PAGED_CODE_RTL(); - - if (AclSize < sizeof(ACL)) - { - return STATUS_BUFFER_TOO_SMALL; - } - - if (AclRevision < MIN_ACL_REVISION || - AclRevision > MAX_ACL_REVISION || - AclSize > 0xffff) - { - return STATUS_INVALID_PARAMETER; - } - - AclSize = ROUND_UP(AclSize, 4); - Acl->AclSize = (WORD)AclSize; - Acl->AclRevision = (BYTE)AclRevision; + } + + /* Setup the header */ + Acl->AclSize = (USHORT)ROUND_UP(AclSize, 4); + Acl->AclRevision = (UCHAR)AclRevision; Acl->AceCount = 0; Acl->Sbz1 = 0; Acl->Sbz2 = 0; - return STATUS_SUCCESS; }
- -/* - * @implemented - */ -NTSTATUS -NTAPI -RtlQueryInformationAcl( - PACL Acl, - PVOID Information, - ULONG InformationLength, - ACL_INFORMATION_CLASS InformationClass) +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlQueryInformationAcl(IN PACL Acl, + IN PVOID Information, + IN ULONG InformationLength, + IN ACL_INFORMATION_CLASS InformationClass) { PACE Ace; - PAGED_CODE_RTL(); - - if (Acl->AclRevision < MIN_ACL_REVISION || - Acl->AclRevision > MAX_ACL_REVISION) + PACL_REVISION_INFORMATION RevisionInfo; + PACL_SIZE_INFORMATION SizeInfo; + PAGED_CODE_RTL(); + + /* Validate the ACL revision */ + if ((Acl->AclRevision < MIN_ACL_REVISION) || + (Acl->AclRevision > MAX_ACL_REVISION)) { return STATUS_INVALID_PARAMETER; }
+ /* Check what the caller is querying */ switch (InformationClass) { + /* Revision data */ case AclRevisionInformation: + + /* Bail out if the buffer is too small */ + if (InformationLength < sizeof(ACL_REVISION_INFORMATION)) + { + return STATUS_BUFFER_TOO_SMALL; + } + + /* Return the current revision */ + RevisionInfo = (PACL_REVISION_INFORMATION)Information; + RevisionInfo->AclRevision = Acl->AclRevision; + break; + + /* Size data */ + case AclSizeInformation: + + /* Bail out if the buffer is too small */ + if (InformationLength < sizeof(ACL_SIZE_INFORMATION)) + { + return STATUS_BUFFER_TOO_SMALL; + } + + /* Bail out if there's no space in the ACL */ + if (!RtlFirstFreeAce(Acl, &Ace)) return STATUS_INVALID_PARAMETER; + + /* Read the number of ACEs and check if there was a free ACE */ + SizeInfo = (PACL_SIZE_INFORMATION)Information; + SizeInfo->AceCount = Acl->AceCount; + if (Ace) + { + /* Return how much space there is in the ACL */ + SizeInfo->AclBytesInUse = (ULONG_PTR)Ace - (ULONG_PTR)Acl; + SizeInfo->AclBytesFree = Acl->AclSize - SizeInfo->AclBytesInUse; + } + else + { + /* No free ACE, means the whole ACL is full */ + SizeInfo->AclBytesInUse = Acl->AclSize; + SizeInfo->AclBytesFree = 0; + } + break; + + default: + /* Anything else is illegal */ + return STATUS_INVALID_INFO_CLASS; + } + + /* All done */ + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlSetInformationAcl(IN PACL Acl, + IN PVOID Information, + IN ULONG InformationLength, + IN ACL_INFORMATION_CLASS InformationClass) +{ + PACL_REVISION_INFORMATION Info ; + PAGED_CODE_RTL(); + + /* Validate the ACL revision */ + if ((Acl->AclRevision < MIN_ACL_REVISION) || + (Acl->AclRevision > MAX_ACL_REVISION)) + { + return STATUS_INVALID_PARAMETER; + } + + /* What is the caller trying to set? */ + switch (InformationClass) + { + /* This is the only info class */ + case AclRevisionInformation: + + /* Make sure the buffer is large enough */ + if (InformationLength < sizeof(ACL_REVISION_INFORMATION)) + { + return STATUS_BUFFER_TOO_SMALL; + } + + /* Make sure the new revision is within the acceptable bounds*/ + Info = (PACL_REVISION_INFORMATION)Information; + if (Acl->AclRevision >= Info->AclRevision) + { + return STATUS_INVALID_PARAMETER; + } + + /* Set the new revision */ + Acl->AclRevision = (BYTE)Info->AclRevision; + break; + + default: + /* Anything else is invalid */ + return STATUS_INVALID_INFO_CLASS; + } + + /* All good */ + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +RtlValidAcl(IN PACL Acl) +{ + PACE_HEADER Ace; + PISID Sid; + ULONG i; + PAGED_CODE_RTL(); + + _SEH2_TRY + { + /* First, validate the revision */ + if ((Acl->AclRevision < MIN_ACL_REVISION) || + (Acl->AclRevision > MAX_ACL_REVISION)) { - PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information; - - if (InformationLength < sizeof(ACL_REVISION_INFORMATION)) - { - return STATUS_BUFFER_TOO_SMALL; - } - Info->AclRevision = Acl->AclRevision; + DPRINT1("Invalid ACL revision\n"); + return FALSE; } - break; - - case AclSizeInformation: + + /* Next, validate that the ACL is USHORT-aligned */ + if (ROUND_DOWN(Acl->AclSize, sizeof(USHORT)) != Acl->AclSize) { - PACL_SIZE_INFORMATION Info = (PACL_SIZE_INFORMATION)Information; - - if (InformationLength < sizeof(ACL_SIZE_INFORMATION)) - { - return STATUS_BUFFER_TOO_SMALL; - } - - if (!RtlFirstFreeAce(Acl, &Ace)) - { - return STATUS_INVALID_PARAMETER; - } - - Info->AceCount = Acl->AceCount; - if (Ace != NULL) - { - Info->AclBytesInUse = (DWORD)((ULONG_PTR)Ace - (ULONG_PTR)Acl); - Info->AclBytesFree = Acl->AclSize - Info->AclBytesInUse; + DPRINT1("Invalid ACL size\n"); + return FALSE; + } + + /* And that it's big enough */ + if (Acl->AclSize < sizeof(ACL)) + { + DPRINT1("Invalid ACL size\n"); + return FALSE; + } + + /* Loop each ACE */ + Ace = (PACE_HEADER)((ULONG_PTR)Acl + sizeof(ACL)); + for (i = 0; i < Acl->AceCount; i++) + { + /* Validate we have space for this ACE header */ + if (((ULONG_PTR)Ace + sizeof(ACE_HEADER)) >= ((ULONG_PTR)Acl + Acl->AclSize)) + { + DPRINT1("Invalid ACE size\n"); + return FALSE; + } + + /* Validate the length of this ACE */ + if (ROUND_DOWN(Ace->AceSize, sizeof(USHORT)) != Ace->AceSize) + { + DPRINT1("Invalid ACE size: %lx\n", Ace->AceSize); + return FALSE; + } + + /* Validate we have space for the entire ACE */ + if (((ULONG_PTR)Ace + Ace->AceSize) > ((ULONG_PTR)Acl + Acl->AclSize)) + { + DPRINT1("Invalid ACE size %lx %lx\n", Ace->AceSize, Acl->AclSize); + return FALSE; + } + + /* Check what kind of ACE this is */ + if ((Ace->AceType >= ACCESS_MIN_MS_ACE_TYPE) || + (Ace->AceType <= ACCESS_MAX_MS_V2_ACE_TYPE)) + { + /* Validate the length of this ACE */ + if (ROUND_DOWN(Ace->AceSize, sizeof(ULONG)) != Ace->AceSize) + { + DPRINT1("Invalid ACE size\n"); + return FALSE; + } + + /* The ACE size should at least have enough for the header */ + if (Ace->AceSize < sizeof(ACE_HEADER)) + { + DPRINT1("Invalid ACE size: %lx %lx\n", Ace->AceSize, sizeof(ACE_HEADER)); + return FALSE; + } + + /* Check if the SID revision is valid */ + Sid = (PISID)&((PKNOWN_ACE)Ace)->SidStart; + if (Sid->Revision != SID_REVISION) + { + DPRINT1("Invalid SID\n"); + return FALSE; + } + + /* Check if the SID is out of bounds */ + if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) + { + DPRINT1("Invalid SID\n"); + return FALSE; + } + + /* The ACE size should at least have enough for the header and SID */ + if (Ace->AceSize < (sizeof(ACE_HEADER) + RtlLengthSid(Sid))) + { + DPRINT1("Invalid ACE size\n"); + return FALSE; + } + } + else if (Ace->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) + { + DPRINT1("Unsupported ACE in ReactOS, assuming valid\n"); + } + else if ((Ace->AceType >= ACCESS_MIN_MS_ACE_TYPE) || + (Ace->AceType <= ACCESS_MAX_MS_V2_ACE_TYPE)) + { + DPRINT1("Unsupported ACE in ReactOS, assuming valid\n"); } else { - Info->AclBytesInUse = Acl->AclSize; - Info->AclBytesFree = 0; - } + /* Unknown ACE, see if it's as big as a header at least */ + if (Ace->AceSize < sizeof(ACE_HEADER)) + { + DPRINT1("Unknown ACE\n"); + return FALSE; + } + } + + /* Move to the next ace */ + Ace = (PACE_HEADER)((ULONG_PTR)Ace + Ace->AceSize); } - break; - - default: - return STATUS_INVALID_INFO_CLASS; - } - - return STATUS_SUCCESS; -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlSetInformationAcl(PACL Acl, - PVOID Information, - ULONG InformationLength, - ACL_INFORMATION_CLASS InformationClass) -{ - PAGED_CODE_RTL(); - - if (Acl->AclRevision < MIN_ACL_REVISION || - Acl->AclRevision > MAX_ACL_REVISION) - { - return STATUS_INVALID_PARAMETER; - } - - switch (InformationClass) - { - case AclRevisionInformation: - { - PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information; - - if (InformationLength < sizeof(ACL_REVISION_INFORMATION)) - { - return STATUS_BUFFER_TOO_SMALL; - } - - if (Acl->AclRevision >= Info->AclRevision) - { - return STATUS_INVALID_PARAMETER; - } - - Acl->AclRevision = (BYTE)Info->AclRevision; - } - break; - - default: - return STATUS_INVALID_INFO_CLASS; - } - - return STATUS_SUCCESS; -} - - -/* - * @implemented - */ -BOOLEAN -NTAPI -RtlValidAcl(PACL Acl) -{ - PACE Ace; - USHORT Size; - PAGED_CODE_RTL(); - - Size = ROUND_UP(Acl->AclSize, 4); - - if (Acl->AclRevision < MIN_ACL_REVISION || - Acl->AclRevision > MAX_ACL_REVISION) - { + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Something was invalid, fail */ return FALSE; } - - if (Size != Acl->AclSize) - { - return FALSE; - } - - return RtlFirstFreeAce(Acl, &Ace); + _SEH2_END; + + /* The ACL looks ok */ + return TRUE; }
/* EOF */