From c74cbfaf67d2a82a704fb207218600904a72af6a Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Wed, 10 May 2006 09:32:23 +0000 Subject: [PATCH] bug 1467 : patch from w3seek, ACLs: Implement audit functions svn path=/trunk/; revision=21875 --- reactos/dll/ntdll/def/ntdll.def | 3 + reactos/dll/win32/advapi32/advapi32.h | 1 + reactos/dll/win32/advapi32/sec/ac.c | 590 +++++++++++++++++++++----- reactos/dll/win32/advapi32/sec/sec.c | 8 +- reactos/dll/win32/ntmarta/ntmarta.c | 158 ++++++- reactos/include/ndk/rtlfuncs.h | 57 ++- reactos/include/winnt.h | 2 +- reactos/lib/rtl/acl.c | 216 +++++++++- 8 files changed, 907 insertions(+), 128 deletions(-) diff --git a/reactos/dll/ntdll/def/ntdll.def b/reactos/dll/ntdll/def/ntdll.def index ef3b141a8bb..feca2d36311 100644 --- a/reactos/dll/ntdll/def/ntdll.def +++ b/reactos/dll/ntdll/def/ntdll.def @@ -292,14 +292,17 @@ RtlAcquireResourceExclusive@8 RtlAcquireResourceShared@8 RtlAddAccessAllowedAce@16 RtlAddAccessAllowedAceEx@20 +RtlAddAccessAllowedObjectAce@28 RtlAddAccessDeniedAce@16 RtlAddAccessDeniedAceEx@20 +RtlAddAccessDeniedObjectAce@28 RtlAddAce@20 ;RtlAddActionToRXact RtlAddAtomToAtomTable@12 ;RtlAddAttributeActionToRXact RtlAddAuditAccessAce@24 RtlAddAuditAccessAceEx@28 +RtlAddAuditAccessObjectAce@36 ;RtlAddCompoundAce RtlAddRange@36 RtlAddVectoredExceptionHandler@8 diff --git a/reactos/dll/win32/advapi32/advapi32.h b/reactos/dll/win32/advapi32/advapi32.h index a89d320a5eb..901e524a1ee 100644 --- a/reactos/dll/win32/advapi32/advapi32.h +++ b/reactos/dll/win32/advapi32/advapi32.h @@ -17,6 +17,7 @@ #define WIN32_NO_STATUS #include #include +#include #include #define NTOS_MODE_USER #include diff --git a/reactos/dll/win32/advapi32/sec/ac.c b/reactos/dll/win32/advapi32/sec/ac.c index f49a02906bb..0bee9e52f25 100644 --- a/reactos/dll/win32/advapi32/sec/ac.c +++ b/reactos/dll/win32/advapi32/sec/ac.c @@ -166,7 +166,7 @@ AddAccessAllowedAceEx(PACL pAcl, /* - * @unimplemented + * @implemented */ BOOL STDCALL @@ -179,8 +179,22 @@ AddAccessAllowedObjectAce( GUID* InheritedObjectTypeGuid, PSID pSid) { - DPRINT1("%s() not implemented!\n", __FUNCTION__); - return ERROR_CALL_NOT_IMPLEMENTED; + NTSTATUS Status; + + Status = RtlAddAccessAllowedObjectAce(pAcl, + dwAceRevision, + AceFlags, + AccessMask, + ObjectTypeGuid, + InheritedObjectTypeGuid, + pSid); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; } @@ -240,7 +254,7 @@ AddAccessDeniedAceEx(PACL pAcl, /* - * @unimplemented + * @implemented */ BOOL STDCALL @@ -253,8 +267,22 @@ AddAccessDeniedObjectAce( GUID* InheritedObjectTypeGuid, PSID pSid) { - DPRINT1("%s() not implemented!\n", __FUNCTION__); - return ERROR_CALL_NOT_IMPLEMENTED; + NTSTATUS Status; + + Status = RtlAddAccessDeniedObjectAce(pAcl, + dwAceRevision, + AceFlags, + AccessMask, + ObjectTypeGuid, + InheritedObjectTypeGuid, + pSid); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; } @@ -352,7 +380,7 @@ AddAuditAccessAceEx(PACL pAcl, /* - * @unimplemented + * @implemented */ BOOL STDCALL @@ -367,8 +395,24 @@ AddAuditAccessObjectAce( BOOL bAuditSuccess, BOOL bAuditFailure) { - DPRINT1("%s() not implemented!\n", __FUNCTION__); - return ERROR_CALL_NOT_IMPLEMENTED; + NTSTATUS Status; + + Status = RtlAddAuditAccessObjectAce(pAcl, + dwAceRevision, + AceFlags, + AccessMask, + ObjectTypeGuid, + InheritedObjectTypeGuid, + pSid, + bAuditSuccess, + bAuditFailure); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; } @@ -554,6 +598,385 @@ SetEntriesInAclW( } +static DWORD +InternalTrusteeAToW(IN PTRUSTEE_A pTrusteeA, + OUT PTRUSTEE_W *pTrusteeW) +{ + TRUSTEE_FORM TrusteeForm; + INT BufferSize = 0; + PSTR lpStr; + DWORD ErrorCode = ERROR_SUCCESS; + + ASSERT(sizeof(TRUSTEE_W) == sizeof(TRUSTEE_A)); + + TrusteeForm = GetTrusteeForm(pTrusteeA); + switch (TrusteeForm) + { + case TRUSTEE_IS_NAME: + { + lpStr = GetTrusteeName(pTrusteeA); + if (lpStr != NULL) + BufferSize = strlen(lpStr) + 1; + + *pTrusteeW = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(TRUSTEE_W) + (BufferSize * sizeof(WCHAR))); + if (*pTrusteeW != NULL) + { + RtlCopyMemory(*pTrusteeW, + pTrusteeA, + FIELD_OFFSET(TRUSTEE_A, + ptstrName)); + + if (lpStr != NULL) + { + (*pTrusteeW)->ptstrName = (PWSTR)((*pTrusteeW) + 1); + + /* convert the trustee's name */ + if (MultiByteToWideChar(CP_ACP, + 0, + lpStr, + -1, + (*pTrusteeW)->ptstrName, + BufferSize) == 0) + { + goto ConvertErr; + } + } + else + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + *pTrusteeW); + goto NothingToConvert; + } + } + else + ErrorCode = ERROR_NOT_ENOUGH_MEMORY; + break; + } + + case TRUSTEE_IS_OBJECTS_AND_NAME: + { + POBJECTS_AND_NAME_A oanA = (POBJECTS_AND_NAME_A)GetTrusteeNameA(pTrusteeA); + POBJECTS_AND_NAME_W oan; + PWSTR StrBuf; + + /* calculate the size needed */ + if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && + oanA->InheritedObjectTypeName != NULL) + { + BufferSize = strlen(oanA->InheritedObjectTypeName) + 1; + } + if (oanA->ptstrName != NULL) + { + BufferSize += strlen(oanA->ptstrName) + 1; + } + + *pTrusteeW = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(TRUSTEE_W) + sizeof(OBJECTS_AND_NAME_W) + + (BufferSize * sizeof(WCHAR))); + + if (*pTrusteeW != NULL) + { + oan = (POBJECTS_AND_NAME_W)((*pTrusteeW) + 1); + StrBuf = (PWSTR)(oan + 1); + + /* copy over the parts of the TRUSTEE structure that don't need + to be touched */ + RtlCopyMemory(*pTrusteeW, + pTrusteeA, + FIELD_OFFSET(TRUSTEE_A, + ptstrName)); + + (*pTrusteeW)->ptstrName = (LPWSTR)oan; + + /* convert the OBJECTS_AND_NAME_A structure */ + oan->ObjectsPresent = oanA->ObjectsPresent; + oan->ObjectType = oanA->ObjectType; + + if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && + oanA->InheritedObjectTypeName != NULL) + { + /* convert inherited object type name */ + BufferSize = strlen(oanA->InheritedObjectTypeName) + 1; + + if (MultiByteToWideChar(CP_ACP, + 0, + oanA->InheritedObjectTypeName, + -1, + StrBuf, + BufferSize) == 0) + { + goto ConvertErr; + } + oan->InheritedObjectTypeName = StrBuf; + + StrBuf += BufferSize; + } + else + oan->InheritedObjectTypeName = NULL; + + if (oanA->ptstrName != NULL) + { + /* convert the trustee name */ + BufferSize = strlen(oanA->ptstrName) + 1; + + if (MultiByteToWideChar(CP_ACP, + 0, + oanA->ptstrName, + -1, + StrBuf, + BufferSize) == 0) + { +ConvertErr: + ErrorCode = GetLastError(); + + /* cleanup */ + RtlFreeHeap(RtlGetProcessHeap(), + 0, + *pTrusteeW); + + return ErrorCode; + } + oan->ptstrName = StrBuf; + } + else + oan->ptstrName = NULL; + } + else + ErrorCode = ERROR_NOT_ENOUGH_MEMORY; + break; + } + + default: + { +NothingToConvert: + /* no need to convert anything to unicode */ + *pTrusteeW = (PTRUSTEE_W)pTrusteeA; + break; + } + } + + return ErrorCode; +} + + +static __inline VOID +InternalFreeConvertedTrustee(IN PTRUSTEE_W pTrusteeW, + IN PTRUSTEE_A pTrusteeA) +{ + if ((PVOID)pTrusteeW != (PVOID)pTrusteeA) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + pTrusteeW); + } +} + + +static DWORD +InternalExplicitAccessAToW(IN ULONG cCountOfExplicitEntries, + IN PEXPLICIT_ACCESS_A pListOfExplicitEntriesA, + OUT PEXPLICIT_ACCESS_W *pListOfExplicitEntriesW) +{ + TRUSTEE_FORM TrusteeForm; + SIZE_T Size; + ULONG i; + ULONG ObjectsAndNameCount = 0; + PEXPLICIT_ACCESS_W peaw = NULL; + DWORD ErrorCode = ERROR_SUCCESS; + LPSTR lpStr; + + /* NOTE: This code assumes that the size of the TRUSTEE_A and TRUSTEE_W structure matches! */ + ASSERT(sizeof(TRUSTEE_A) == sizeof(TRUSTEE_W)); + + if (cCountOfExplicitEntries != 0) + { + /* calculate the size needed */ + Size = cCountOfExplicitEntries * sizeof(EXPLICIT_ACCESS_W); + for (i = 0; i != cCountOfExplicitEntries; i++) + { + TrusteeForm = GetTrusteeForm(&pListOfExplicitEntriesA[i].Trustee); + + switch (TrusteeForm) + { + case TRUSTEE_IS_NAME: + { + lpStr = GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); + if (lpStr != NULL) + Size += (strlen(lpStr) + 1) * sizeof(WCHAR); + break; + } + + case TRUSTEE_IS_OBJECTS_AND_NAME: + { + POBJECTS_AND_NAME_A oan = (POBJECTS_AND_NAME_A)GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); + + if ((oan->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && + oan->InheritedObjectTypeName != NULL) + { + Size += (strlen(oan->InheritedObjectTypeName) + 1) * sizeof(WCHAR); + } + + if (oan->ptstrName != NULL) + Size += (strlen(oan->ptstrName) + 1) * sizeof(WCHAR); + + ObjectsAndNameCount++; + break; + } + + default: + break; + } + } + + /* allocate the array */ + peaw = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + Size); + if (peaw != NULL) + { + INT BufferSize; + POBJECTS_AND_NAME_W oan = (POBJECTS_AND_NAME_W)(peaw + cCountOfExplicitEntries); + LPWSTR StrBuf = (LPWSTR)(oan + ObjectsAndNameCount); + + /* convert the array to unicode */ + for (i = 0; i != cCountOfExplicitEntries; i++) + { + peaw[i].grfAccessPermissions = pListOfExplicitEntriesA[i].grfAccessPermissions; + peaw[i].grfAccessMode = pListOfExplicitEntriesA[i].grfAccessMode; + peaw[i].grfInheritance = pListOfExplicitEntriesA[i].grfInheritance; + + /* convert or copy the TRUSTEE structure */ + TrusteeForm = GetTrusteeForm(&pListOfExplicitEntriesA[i].Trustee); + switch (TrusteeForm) + { + case TRUSTEE_IS_NAME: + { + lpStr = GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); + if (lpStr != NULL) + { + /* convert the trustee name */ + BufferSize = strlen(lpStr) + 1; + + if (MultiByteToWideChar(CP_ACP, + 0, + lpStr, + -1, + StrBuf, + BufferSize) == 0) + { + goto ConvertErr; + } + peaw[i].Trustee.ptstrName = StrBuf; + + StrBuf += BufferSize; + } + else + goto RawTrusteeCopy; + + break; + } + + case TRUSTEE_IS_OBJECTS_AND_NAME: + { + POBJECTS_AND_NAME_A oanA = (POBJECTS_AND_NAME_A)GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee); + + /* copy over the parts of the TRUSTEE structure that don't need + to be touched */ + RtlCopyMemory(&peaw[i].Trustee, + &pListOfExplicitEntriesA[i].Trustee, + FIELD_OFFSET(TRUSTEE_A, + ptstrName)); + + peaw[i].Trustee.ptstrName = (LPWSTR)oan; + + /* convert the OBJECTS_AND_NAME_A structure */ + oan->ObjectsPresent = oanA->ObjectsPresent; + oan->ObjectType = oanA->ObjectType; + + if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) && + oanA->InheritedObjectTypeName != NULL) + { + /* convert inherited object type name */ + BufferSize = strlen(oanA->InheritedObjectTypeName) + 1; + + if (MultiByteToWideChar(CP_ACP, + 0, + oanA->InheritedObjectTypeName, + -1, + StrBuf, + BufferSize) == 0) + { + goto ConvertErr; + } + oan->InheritedObjectTypeName = StrBuf; + + StrBuf += BufferSize; + } + else + oan->InheritedObjectTypeName = NULL; + + if (oanA->ptstrName != NULL) + { + /* convert the trustee name */ + BufferSize = strlen(oanA->ptstrName) + 1; + + if (MultiByteToWideChar(CP_ACP, + 0, + oanA->ptstrName, + -1, + StrBuf, + BufferSize) == 0) + { +ConvertErr: + ErrorCode = GetLastError(); + + /* cleanup */ + RtlFreeHeap(RtlGetProcessHeap(), + 0, + peaw); + + return ErrorCode; + } + oan->ptstrName = StrBuf; + + StrBuf += BufferSize; + } + else + oan->ptstrName = NULL; + + /* move on to the next OBJECTS_AND_NAME_A structure */ + oan++; + break; + } + + default: + { +RawTrusteeCopy: + /* just copy over the TRUSTEE structure, they don't contain any + ansi/unicode specific data */ + RtlCopyMemory(&peaw[i].Trustee, + &pListOfExplicitEntriesA[i].Trustee, + sizeof(TRUSTEE_A)); + break; + } + } + } + + ASSERT(ErrorCode == ERROR_SUCCESS); + *pListOfExplicitEntriesW = peaw; + } + else + ErrorCode = ERROR_NOT_ENOUGH_MEMORY; + } + + return ErrorCode; +} + + /* * @implemented */ @@ -565,102 +988,24 @@ SetEntriesInAclA( PACL OldAcl, PACL* NewAcl) { - PEXPLICIT_ACCESS_W ListOfExplicitEntriesW; - ULONG i; + PEXPLICIT_ACCESS_W ListOfExplicitEntriesW = NULL; DWORD ErrorCode; - if (cCountOfExplicitEntries != 0) + ErrorCode = InternalExplicitAccessAToW(cCountOfExplicitEntries, + pListOfExplicitEntries, + &ListOfExplicitEntriesW); + + if (ErrorCode == ERROR_SUCCESS) { - ListOfExplicitEntriesW = HeapAlloc(GetProcessHeap(), - 0, - cCountOfExplicitEntries * sizeof(EXPLICIT_ACCESS_W)); - if (ListOfExplicitEntriesW != NULL) - { - /* directly copy the array, this works as the size of the EXPLICIT_ACCESS_A - structure matches the size of the EXPLICIT_ACCESS_W version */ - ASSERT(sizeof(EXPLICIT_ACCESS_A) == sizeof(EXPLICIT_ACCESS_W)); - - RtlCopyMemory(ListOfExplicitEntriesW, - pListOfExplicitEntries, - cCountOfExplicitEntries * sizeof(EXPLICIT_ACCESS_W)); - - /* convert the trustee names if required */ - for (i = 0; i != cCountOfExplicitEntries; i++) - { - if (pListOfExplicitEntries[i].Trustee.TrusteeForm == TRUSTEE_IS_NAME) - { - UINT BufCount = strlen(pListOfExplicitEntries[i].Trustee.ptstrName) + 1; - ListOfExplicitEntriesW[i].Trustee.ptstrName = - (LPWSTR)HeapAlloc(GetProcessHeap(), - 0, - BufCount * sizeof(WCHAR)); - - if (ListOfExplicitEntriesW[i].Trustee.ptstrName == NULL || - MultiByteToWideChar(CP_ACP, - 0, - pListOfExplicitEntries[i].Trustee.ptstrName, - -1, - ListOfExplicitEntriesW[i].Trustee.ptstrName, - BufCount) == 0) - { - /* failed to allocate enough momory for the strings or failed to - convert the ansi string to unicode, then fail and free all - allocated memory */ - - ErrorCode = GetLastError(); - - do - { - if (ListOfExplicitEntriesW[i].Trustee.TrusteeForm == TRUSTEE_IS_NAME && - ListOfExplicitEntriesW[i].Trustee.ptstrName != NULL) - { - HeapFree(GetProcessHeap(), - 0, - ListOfExplicitEntriesW[i].Trustee.ptstrName); - } - } while (i-- != 0); - - /* free the allocated array */ - HeapFree(GetProcessHeap(), - 0, - ListOfExplicitEntriesW); - - return ErrorCode; - } - } - } - } - else - { - return GetLastError(); - } - } - else - ListOfExplicitEntriesW = NULL; - - ErrorCode = SetEntriesInAclW(cCountOfExplicitEntries, - ListOfExplicitEntriesW, - OldAcl, - NewAcl); - - /* free the strings */ - if (ListOfExplicitEntriesW != NULL) - { - /* free the converted strings */ - for (i = 0; i != cCountOfExplicitEntries; i++) - { - if (ListOfExplicitEntriesW[i].Trustee.TrusteeForm == TRUSTEE_IS_NAME) - { - HeapFree(GetProcessHeap(), - 0, - ListOfExplicitEntriesW[i].Trustee.ptstrName); - } - } + ErrorCode = SetEntriesInAclW(cCountOfExplicitEntries, + ListOfExplicitEntriesW, + OldAcl, + NewAcl); /* free the allocated array */ - HeapFree(GetProcessHeap(), - 0, - ListOfExplicitEntriesW); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ListOfExplicitEntriesW); } return ErrorCode; @@ -708,7 +1053,7 @@ GetEffectiveRightsFromAclW(IN PACL pacl, /* - * @unimplemented + * @implemented */ DWORD STDCALL @@ -716,8 +1061,24 @@ GetEffectiveRightsFromAclA(IN PACL pacl, IN PTRUSTEE_A pTrustee, OUT PACCESS_MASK pAccessRights) { - DPRINT1("%s() not implemented!\n", __FUNCTION__); - return ERROR_CALL_NOT_IMPLEMENTED; + PTRUSTEE_W pTrusteeW = NULL; + DWORD ErrorCode; + + ErrorCode = InternalTrusteeAToW(pTrustee, + &pTrusteeW); + if (ErrorCode == ERROR_SUCCESS) + { + ErrorCode = GetEffectiveRightsFromAclW(pacl, + pTrusteeW, + pAccessRights); + + InternalFreeConvertedTrustee(pTrusteeW, + pTrustee); + } + else + ErrorCode = ERROR_NOT_ENOUGH_MEMORY; + + return ErrorCode; } @@ -737,7 +1098,7 @@ GetAuditedPermissionsFromAclW(IN PACL pacl, /* - * @unimplemented + * @implemented */ DWORD STDCALL @@ -746,8 +1107,25 @@ GetAuditedPermissionsFromAclA(IN PACL pacl, OUT PACCESS_MASK pSuccessfulAuditedRights, OUT PACCESS_MASK pFailedAuditRights) { - DPRINT1("%s() not implemented!\n", __FUNCTION__); - return ERROR_CALL_NOT_IMPLEMENTED; + PTRUSTEE_W pTrusteeW = NULL; + DWORD ErrorCode; + + ErrorCode = InternalTrusteeAToW(pTrustee, + &pTrusteeW); + if (ErrorCode == ERROR_SUCCESS) + { + ErrorCode = GetAuditedPermissionsFromAclW(pacl, + pTrusteeW, + pSuccessfulAuditedRights, + pFailedAuditRights); + + InternalFreeConvertedTrustee(pTrusteeW, + pTrustee); + } + else + ErrorCode = ERROR_NOT_ENOUGH_MEMORY; + + return ErrorCode; } /* EOF */ diff --git a/reactos/dll/win32/advapi32/sec/sec.c b/reactos/dll/win32/advapi32/sec/sec.c index 20d664e7e83..df8b067f695 100644 --- a/reactos/dll/win32/advapi32/sec/sec.c +++ b/reactos/dll/win32/advapi32/sec/sec.c @@ -490,9 +490,9 @@ STDCALL BuildSecurityDescriptorW(IN PTRUSTEE_W pOwner OPTIONAL, IN PTRUSTEE_W pGroup OPTIONAL, IN ULONG cCountOfAccessEntries, - IN PEXPLICIT_ACCESS pListOfAccessEntries OPTIONAL, + IN PEXPLICIT_ACCESS_W pListOfAccessEntries OPTIONAL, IN ULONG cCountOfAuditEntries, - IN PEXPLICIT_ACCESS pListOfAuditEntries OPTIONAL, + IN PEXPLICIT_ACCESS_W pListOfAuditEntries OPTIONAL, IN PSECURITY_DESCRIPTOR pOldSD OPTIONAL, OUT PULONG pSizeNewSD, OUT PSECURITY_DESCRIPTOR* pNewSD) @@ -510,9 +510,9 @@ STDCALL BuildSecurityDescriptorA(IN PTRUSTEE_A pOwner OPTIONAL, IN PTRUSTEE_A pGroup OPTIONAL, IN ULONG cCountOfAccessEntries, - IN PEXPLICIT_ACCESS pListOfAccessEntries OPTIONAL, + IN PEXPLICIT_ACCESS_A pListOfAccessEntries OPTIONAL, IN ULONG cCountOfAuditEntries, - IN PEXPLICIT_ACCESS pListOfAuditEntries OPTIONAL, + IN PEXPLICIT_ACCESS_A pListOfAuditEntries OPTIONAL, IN PSECURITY_DESCRIPTOR pOldSD OPTIONAL, OUT PULONG pSizeNewSD, OUT PSECURITY_DESCRIPTOR* pNewSD) diff --git a/reactos/dll/win32/ntmarta/ntmarta.c b/reactos/dll/win32/ntmarta/ntmarta.c index 51082818036..8295da31598 100644 --- a/reactos/dll/win32/ntmarta/ntmarta.c +++ b/reactos/dll/win32/ntmarta/ntmarta.c @@ -157,6 +157,136 @@ AccpGetAceAccessMask(IN PACE_HEADER AceHeader) return *((PACCESS_MASK)(AceHeader + 1)); } +static BOOL +AccpIsObjectAce(IN PACE_HEADER AceHeader) +{ + BOOL Ret; + + switch (AceHeader->AceType) + { + case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: + case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: + case ACCESS_ALLOWED_OBJECT_ACE_TYPE: + case ACCESS_DENIED_OBJECT_ACE_TYPE: + case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: + case SYSTEM_AUDIT_OBJECT_ACE_TYPE: + Ret = TRUE; + break; + + default: + Ret = FALSE; + break; + } + + return Ret; +} + +static GUID* +AccpGetObjectAceObjectType(IN PACE_HEADER AceHeader) +{ + GUID *ObjectType = NULL; + + switch (AceHeader->AceType) + { + case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: + case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: + { + PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->ObjectType; + break; + } + case ACCESS_ALLOWED_OBJECT_ACE_TYPE: + case ACCESS_DENIED_OBJECT_ACE_TYPE: + { + PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->ObjectType; + break; + } + + case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: + { + PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->ObjectType; + break; + } + case SYSTEM_AUDIT_OBJECT_ACE_TYPE: + { + PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->ObjectType; + break; + } + } + + return ObjectType; +} + +static GUID* +AccpGetObjectAceInheritedObjectType(IN PACE_HEADER AceHeader) +{ + GUID *ObjectType = NULL; + + switch (AceHeader->AceType) + { + case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: + case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: + { + PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) + { + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->InheritedObjectType; + else + ObjectType = &Ace->ObjectType; + } + break; + } + case ACCESS_ALLOWED_OBJECT_ACE_TYPE: + case ACCESS_DENIED_OBJECT_ACE_TYPE: + { + PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) + { + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->InheritedObjectType; + else + ObjectType = &Ace->ObjectType; + } + break; + } + + case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: + { + PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) + { + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->InheritedObjectType; + else + ObjectType = &Ace->ObjectType; + } + break; + } + case SYSTEM_AUDIT_OBJECT_ACE_TYPE: + { + PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader; + if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) + { + if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT) + ObjectType = &Ace->InheritedObjectType; + else + ObjectType = &Ace->ObjectType; + } + break; + } + } + + return ObjectType; +} + /********************************************************************** * AccRewriteGetHandleRights EXPORTED @@ -925,6 +1055,8 @@ AccRewriteGetExplicitEntriesFromAcl(PACL pacl, { PACE_HEADER AceHeader; PSID Sid, SidTarget; + ULONG ObjectAceCount = 0; + POBJECTS_AND_SID ObjSid; SIZE_T Size; PEXPLICIT_ACCESS_W peaw; DWORD LastErr, SidLen; @@ -947,10 +1079,15 @@ AccRewriteGetExplicitEntriesFromAcl(PACL pacl, { Sid = AccpGetAceSid(AceHeader); Size += GetLengthSid(Sid); - /* FIXME - take size of opaque data in account? */ + + if (AccpIsObjectAce(AceHeader)) + ObjectAceCount++; + AceIndex++; } + Size += ObjectAceCount * sizeof(OBJECTS_AND_SID); + ASSERT(pacl->AceCount == AceIndex); /* allocate the array */ @@ -959,7 +1096,8 @@ AccRewriteGetExplicitEntriesFromAcl(PACL pacl, if (peaw != NULL) { AceIndex = 0; - SidTarget = (PSID)(peaw + pacl->AceCount); + ObjSid = (POBJECTS_AND_SID)(peaw + pacl->AceCount); + SidTarget = (PSID)(ObjSid + ObjectAceCount); /* initialize the array */ while (GetAce(pacl, @@ -977,8 +1115,20 @@ AccRewriteGetExplicitEntriesFromAcl(PACL pacl, SidTarget, Sid)) { - BuildTrusteeWithSid(&peaw[AceIndex].Trustee, - SidTarget); + if (AccpIsObjectAce(AceHeader)) + { + BuildTrusteeWithObjectsAndSid(&peaw[AceIndex].Trustee, + ObjSid++, + AccpGetObjectAceObjectType(AceHeader), + AccpGetObjectAceInheritedObjectType(AceHeader), + SidTarget); + } + else + { + BuildTrusteeWithSid(&peaw[AceIndex].Trustee, + SidTarget); + } + SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen); } else diff --git a/reactos/include/ndk/rtlfuncs.h b/reactos/include/ndk/rtlfuncs.h index 97729ffc8d3..98cf6ae2f68 100644 --- a/reactos/include/ndk/rtlfuncs.h +++ b/reactos/include/ndk/rtlfuncs.h @@ -455,6 +455,19 @@ RtlAddAccessAllowedAceEx( IN PSID pSid ); +NTSYSAPI +NTSTATUS +NTAPI +RtlAddAccessAllowedObjectAce( + IN OUT PACL pAcl, + IN ULONG dwAceRevision, + IN ULONG AceFlags, + IN ULONG AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID pSid +); + NTSYSAPI NTSTATUS NTAPI @@ -479,14 +492,14 @@ RtlAddAccessDeniedAceEx( NTSYSAPI NTSTATUS NTAPI -RtlAddAuditAccessAceEx( - IN OUT PACL Acl, - IN ULONG Revision, - IN ULONG Flags, - IN ACCESS_MASK AccessMask, - IN PSID Sid, - IN BOOLEAN Success, - IN BOOLEAN Failure +RtlAddAccessDeniedObjectAce( + IN OUT PACL pAcl, + IN ULONG dwAceRevision, + IN ULONG AceFlags, + IN ULONG AccessMask, + IN GUID *ObjectTypeGuid OPTIONAL, + IN GUID *InheritedObjectTypeGuid OPTIONAL, + IN PSID pSid ); NTSYSAPI @@ -512,6 +525,34 @@ RtlAddAuditAccessAce( BOOLEAN Failure ); +NTSYSAPI +NTSTATUS +NTAPI +RtlAddAuditAccessAceEx( + IN OUT PACL Acl, + IN ULONG Revision, + IN ULONG Flags, + IN ACCESS_MASK AccessMask, + IN PSID Sid, + IN BOOLEAN Success, + IN BOOLEAN Failure +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlAddAuditAccessObjectAce( + 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, + IN BOOLEAN Success, + IN BOOLEAN Failure +); + NTSYSAPI NTSTATUS NTAPI diff --git a/reactos/include/winnt.h b/reactos/include/winnt.h index 236fe1f2c4b..cd8f01bd8b1 100644 --- a/reactos/include/winnt.h +++ b/reactos/include/winnt.h @@ -225,7 +225,7 @@ typedef DWORD FLONG; #define NO_PROPAGATE_INHERIT_ACE 4 #define INHERIT_ONLY_ACE 8 #define INHERITED_ACE 10 -#define VALID_INHERIT_FLAGS 16 +#define VALID_INHERIT_FLAGS 0x1F #define SUCCESSFUL_ACCESS_ACE_FLAG 64 #define FAILED_ACCESS_ACE_FLAG 128 #define DELETE 0x00010000L diff --git a/reactos/lib/rtl/acl.c b/reactos/lib/rtl/acl.c index c975e9af1f8..e3d68fd841f 100644 --- a/reactos/lib/rtl/acl.c +++ b/reactos/lib/rtl/acl.c @@ -103,14 +103,40 @@ RtlpAddKnownAce (PACL Acl, ULONG Revision, ULONG Flags, ACCESS_MASK AccessMask, + GUID *ObjectTypeGuid OPTIONAL, + GUID *InheritedObjectTypeGuid OPTIONAL, PSID Sid, ULONG Type) { PACE Ace; - ULONG InvalidFlags; + 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); @@ -126,11 +152,17 @@ RtlpAddKnownAce (PACL Acl, } /* Validate the flags */ - if (Type == SYSTEM_AUDIT_ACE_TYPE) + 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) { @@ -145,16 +177,69 @@ RtlpAddKnownAce (PACL Acl, { return(STATUS_ALLOTTED_SPACE_EXCEEDED); } - if ((ULONG_PTR)Ace + RtlLengthSid(Sid) + sizeof(ACE) > + + /* 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 = Flags; Ace->Header.AceType = Type; - Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE); + Ace->Header.AceSize = (WORD)AceSize; Ace->AccessMask = AccessMask; - RtlCopySid(RtlLengthSid(Sid), (PSID)(Ace + 1), Sid); + + 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 = Revision; return(STATUS_SUCCESS); @@ -176,6 +261,8 @@ RtlAddAccessAllowedAce (IN OUT PACL Acl, Revision, 0, AccessMask, + NULL, + NULL, Sid, ACCESS_ALLOWED_ACE_TYPE); } @@ -197,11 +284,46 @@ RtlAddAccessAllowedAceEx (IN OUT PACL 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) +{ + ULONG 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 */ @@ -217,6 +339,8 @@ RtlAddAccessDeniedAce (PACL Acl, Revision, 0, AccessMask, + NULL, + NULL, Sid, ACCESS_DENIED_ACE_TYPE); } @@ -238,11 +362,46 @@ RtlAddAccessDeniedAceEx (IN OUT PACL 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) +{ + ULONG 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, @@ -363,6 +522,8 @@ RtlAddAuditAccessAce(PACL Acl, Revision, Flags, AccessMask, + NULL, + NULL, Sid, SYSTEM_AUDIT_ACE_TYPE); } @@ -394,11 +555,56 @@ RtlAddAuditAccessAceEx(PACL 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) +{ + ULONG 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); +} + + static VOID RtlpDeleteData(PVOID Ace, ULONG AceSize,