mirror of
https://github.com/ladislav-zezula/FileTest
synced 2026-06-08 15:24:12 +00:00
251 lines
9.8 KiB
C++
251 lines
9.8 KiB
C++
/*****************************************************************************/
|
|
/* TAceHelper.cpp Copyright (c) Ladislav Zezula 2016 */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Description : */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Date Ver Who Comment */
|
|
/* -------- ---- --- ------- */
|
|
/* 26.03.16 1.00 Lad The first version of TAceHelper.cpp */
|
|
/*****************************************************************************/
|
|
|
|
#include "FileTest.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local variables
|
|
|
|
static DWORD AceLayouts[] =
|
|
{
|
|
ACE_LAYOUT_SIMPLE, // ACCESS_ALLOWED_ACE = {Header-Mask-SidStart}
|
|
ACE_LAYOUT_SIMPLE, // ACCESS_DENIED_ACE = {Header-Mask-SidStart}
|
|
ACE_LAYOUT_SIMPLE, // SYSTEM_AUDIT_ACE = {Header-Mask-SidStart}
|
|
ACE_LAYOUT_SIMPLE, // SYSTEM_ALARM_ACE = {Header-Mask-SidStart}
|
|
|
|
ACE_LAYOUT_UNKNOWN, // ACCESS_ALLOWED_COMPOUND_ACE = Unknown layout
|
|
|
|
ACE_LAYOUT_OBJECT, // ACCESS_ALLOWED_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart}
|
|
ACE_LAYOUT_OBJECT, // ACCESS_DENIED_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart}
|
|
ACE_LAYOUT_OBJECT, // SYSTEM_AUDIT_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart}
|
|
ACE_LAYOUT_OBJECT, // SYSTEM_ALARM_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart}
|
|
|
|
ACE_LAYOUT_SIMPLE2, // ACCESS_ALLOWED_CALLBACK_ACE = {Header-Mask-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_SIMPLE2, // ACCESS_DENIED_CALLBACK_ACE = {Header-Mask-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_OBJECT2, // ACCESS_ALLOWED_CALLBACK_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_OBJECT2, // ACCESS_DENIED_CALLBACK_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_SIMPLE2, // SYSTEM_AUDIT_CALLBACK_ACE = {Header-Mask-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_SIMPLE2, // SYSTEM_ALARM_CALLBACK_ACE = {Header-Mask-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_OBJECT2, // SYSTEM_AUDIT_CALLBACK_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart-OpaqueResMgrData}
|
|
ACE_LAYOUT_OBJECT2, // SYSTEM_ALARM_CALLBACK_OBJECT_ACE = {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart-OpaqueResMgrData}
|
|
|
|
ACE_LAYOUT_MANDATORY // SYSTEM_MANDATORY_LABEL_ACE = {Header-MandatoryMask-MandatorySidStart}
|
|
};
|
|
|
|
static GUID NullGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor and destructor
|
|
|
|
ACE_HELPER::ACE_HELPER()
|
|
{
|
|
memset(this, 0, sizeof(ACE_HELPER));
|
|
}
|
|
|
|
ACE_HELPER::~ACE_HELPER()
|
|
{
|
|
SetAllocatedSid(NULL);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Public functions
|
|
|
|
// In Page09Security.cpp
|
|
void Sid_Free(PSID pSid);
|
|
|
|
bool ACE_HELPER::SetAceType(DWORD dwAceType)
|
|
{
|
|
// Verify ACE type and set the ACE layout
|
|
if(dwAceType > SYSTEM_MANDATORY_LABEL_ACE_TYPE || AceLayouts[dwAceType] == ACE_LAYOUT_UNKNOWN)
|
|
return false;
|
|
|
|
// Remember the ACE layour and ACE type
|
|
AceLayout = AceLayouts[dwAceType];
|
|
AceType = (BYTE)dwAceType;
|
|
return true;
|
|
}
|
|
|
|
bool ACE_HELPER::SetAce(PACE_HEADER pAceHeader)
|
|
{
|
|
LPBYTE PtrAceData;
|
|
bool bResult;
|
|
|
|
// Verify ACE type and set the ACE layout
|
|
bResult = SetAceType(pAceHeader->AceType);
|
|
if(bResult)
|
|
{
|
|
// Fill-in the header (always included)
|
|
AceFlags = pAceHeader->AceFlags;
|
|
AceSize = pAceHeader->AceSize;
|
|
|
|
// Now get ready for variable ACE layouts
|
|
PtrAceData = (LPBYTE)(pAceHeader + 1);
|
|
|
|
// Is there the ACE::Mask?
|
|
if(AceLayout & (ACE_FIELD_ACCESS_MASK | ACE_FIELD_ADS_ACCESS_MASK | ACE_FIELD_MANDATORY_MASK))
|
|
{
|
|
Mask = *(PDWORD)PtrAceData;
|
|
PtrAceData += sizeof(DWORD);
|
|
}
|
|
|
|
// Is there the ACE::Flags
|
|
if(AceLayout & ACE_FIELD_FLAGS)
|
|
{
|
|
// Copy the ACE::Flags
|
|
Flags = *(PDWORD)PtrAceData;
|
|
PtrAceData += sizeof(DWORD);
|
|
|
|
// ACE::ObjectType is only present if ACE_OBJECT_TYPE_PRESENT is in the flags
|
|
if(Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
{
|
|
memcpy(&ObjectType, PtrAceData, sizeof(GUID));
|
|
PtrAceData += sizeof(GUID);
|
|
}
|
|
|
|
// Is there the ACE::InheritedObjectType?
|
|
if(Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
{
|
|
memcpy(&InheritedObjectType, PtrAceData, sizeof(GUID));
|
|
PtrAceData += sizeof(GUID);
|
|
}
|
|
}
|
|
|
|
// Get the pointer to SID
|
|
if(AceLayout & (ACE_FIELD_ACCESS_SID | ACE_FIELD_MANDATORY_SID))
|
|
{
|
|
Sid = (PSID)PtrAceData;
|
|
AceLayout &= ~ACE_FIELD_NEED_FREE_SID;
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
// pSid could be NULL if we want just to free the existing SID
|
|
void ACE_HELPER::SetAllocatedSid(PSID pSid)
|
|
{
|
|
// Free the old SID
|
|
if((Sid != NULL) && (AceLayout & ACE_FIELD_NEED_FREE_SID))
|
|
Sid_Free(Sid);
|
|
Sid = NULL;
|
|
|
|
// Store the new one
|
|
AceLayout = (pSid != NULL) ? (AceLayout | ACE_FIELD_NEED_FREE_SID) : (AceLayout & ~ACE_FIELD_NEED_FREE_SID);
|
|
Sid = pSid;
|
|
}
|
|
|
|
// Adds itself as an ACE to the ACL
|
|
bool ACE_HELPER::AddToAcl(PACL pAcl)
|
|
{
|
|
PACE_HEADER pAceHeader;
|
|
LPBYTE PtrAclData = (LPBYTE)(pAcl + 1);
|
|
LPBYTE PtrAclEnd = (LPBYTE)pAcl + pAcl->AclSize;
|
|
|
|
// Don't try to push in an unsupported ACE
|
|
if(AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE || AceType > SYSTEM_MANDATORY_LABEL_ACE_TYPE)
|
|
return false;
|
|
|
|
// Find the space after all present ACEs.
|
|
for(BYTE i = 0; i < pAcl->AceCount; i++)
|
|
{
|
|
if(!GetAce(pAcl, i, (LPVOID *)&pAceHeader))
|
|
return false;
|
|
PtrAclData += pAceHeader->AceSize;
|
|
}
|
|
|
|
// Now we have the pointer to the ACE. Insert it there
|
|
pAceHeader = (PACE_HEADER)PtrAclData;
|
|
if((PtrAclEnd - PtrAclData) < sizeof(ACE_HEADER))
|
|
return false;
|
|
|
|
// Fill-in the header
|
|
pAceHeader->AceType = (BYTE)AceType;
|
|
pAceHeader->AceFlags = (BYTE)AceFlags;
|
|
pAceHeader->AceSize = sizeof(ACE_HEADER);
|
|
PtrAclData = (LPBYTE)(pAceHeader + 1);
|
|
|
|
// Fill-in the mask
|
|
PtrAclData = PutAceValue(PtrAclData, PtrAclEnd, &Mask, (ACE_FIELD_ACCESS_MASK | ACE_FIELD_ADS_ACCESS_MASK | ACE_FIELD_MANDATORY_MASK), sizeof(ACCESS_MASK));
|
|
if(PtrAclData == NULL)
|
|
return false;
|
|
|
|
// Fill-in the ACE::flags
|
|
if(AceLayout & ACE_FIELD_FLAGS)
|
|
{
|
|
// If we have the object, get the ACE_OBJECT_TYPE_PRESENT flag there
|
|
if(!(ObjectType == NullGuid))
|
|
Flags |= ACE_OBJECT_TYPE_PRESENT;
|
|
if(!(InheritedObjectType == NullGuid))
|
|
Flags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
|
|
|
|
PtrAclData = PutAceValue(PtrAclData, PtrAclEnd, &Flags, ACE_FIELD_FLAGS, sizeof(DWORD));
|
|
if(PtrAclData == NULL)
|
|
return false;
|
|
}
|
|
|
|
// Fill-in the object type, only if the ACE_OBJECT_TYPE_PRESENT is present in the ACE::Flags
|
|
if(Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
{
|
|
PtrAclData = PutAceValue(PtrAclData, PtrAclEnd, &ObjectType, ACE_FIELD_OBJECT_TYPE, sizeof(GUID));
|
|
if(PtrAclData == NULL)
|
|
return false;
|
|
}
|
|
|
|
// Fill-in the inherited object type, only if the ACE_INHERITED_OBJECT_TYPE_PRESENT is present in the ACE::Flags
|
|
if(Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
{
|
|
// Fill-in the inherited object type
|
|
PtrAclData = PutAceValue(PtrAclData, PtrAclEnd, &InheritedObjectType, ACE_FIELD_OBJECT_TYPE2, sizeof(GUID));
|
|
if(PtrAclData == NULL)
|
|
return false;
|
|
}
|
|
|
|
// Fill-in the SID
|
|
PtrAclData = PutAceValue(PtrAclData, PtrAclEnd, Sid, (ACE_FIELD_ACCESS_SID | ACE_FIELD_MANDATORY_SID), GetLengthSid(Sid));
|
|
if(PtrAclData == NULL)
|
|
return false;
|
|
|
|
// TODO: Fill-in the extra data
|
|
|
|
// The ACL must have ACL_REVISION_DS if it contains any object ACEs
|
|
// https://technet.microsoft.com/cs-cz/aa379293
|
|
if(ACCESS_ALLOWED_OBJECT_ACE_TYPE <= AceType && AceType <= SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE)
|
|
pAcl->AclRevision = ACL_REVISION_DS;
|
|
|
|
// Get the size of the ACE
|
|
pAceHeader->AceSize = (WORD)(PtrAclData - (LPBYTE)pAceHeader);
|
|
pAcl->AceCount = pAcl->AceCount + 1;
|
|
return true;
|
|
}
|
|
|
|
void ACE_HELPER::Reset()
|
|
{
|
|
memset(&AceType, 0, FIELD_OFFSET(ACE_HELPER, Sid) - FIELD_OFFSET(ACE_HELPER, AceType));
|
|
SetAllocatedSid(NULL);
|
|
}
|
|
|
|
LPBYTE ACE_HELPER::PutAceValue(LPBYTE PtrAclData, LPBYTE PtrAclEnd, PVOID PtrValue, DWORD dwLayoutMask, DWORD ValueSize)
|
|
{
|
|
// Only if the value is present
|
|
if(AceLayout & dwLayoutMask)
|
|
{
|
|
// Is there enough space in the ACL?
|
|
if((DWORD)(PtrAclEnd - PtrAclData) < ValueSize)
|
|
return NULL;
|
|
|
|
// Copy the value
|
|
memcpy(PtrAclData, PtrValue, ValueSize);
|
|
PtrAclData += ValueSize;
|
|
}
|
|
|
|
// Return the new pointer
|
|
return PtrAclData;
|
|
}
|