mirror of
https://github.com/ladislav-zezula/FileTest
synced 2026-06-08 15:24:12 +00:00
609 lines
22 KiB
C++
609 lines
22 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
|
|
|
|
// SID_IDENTIFIER_AUTHORITY SiaWorld = SECURITY_WORLD_SID_AUTHORITY;
|
|
const BYTE SidEveryone[0x0C] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
// SID_IDENTIFIER_AUTHORITY SiaWorld = SECURITY_NT_AUTHORITY;
|
|
const BYTE SidLocAdmins[0x10] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00};
|
|
|
|
// SID_IDENTIFIER_AUTHORITY SiaWorld = SECURITY_NT_AUTHORITY;
|
|
const BYTE SidLocUsers[0x10] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00};
|
|
|
|
// SID_IDENTIFIER_AUTHORITY SiaLabel = SECURITY_MANDATORY_LABEL_AUTHORITY;
|
|
const BYTE SidLabelMedium[0x0C] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00};
|
|
|
|
// SID_IDENTIFIER_AUTHORITY SiaPolicy = SECURITY_SCOPED_POLICY_ID_AUTHORITY;
|
|
const BYTE SidSystemAce17[0x0C] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
// SID_IDENTIFIER_AUTHORITY SiaTrust = SECURITY_PROCESS_TRUST_AUTHORITY;
|
|
const BYTE SidSystemAce19[0x10] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00};
|
|
|
|
// Dummy condition for various reasons
|
|
// Obtained from "c:\Program Files\WindowsApps\Microsoft.ZuneMusic_11.2310.8.0_neutral_~_8wekyb3d8bbwe"
|
|
static const BYTE DummyAllowedCondition[] =
|
|
{
|
|
0x61, 0x72, 0x74, 0x78, 0xf8, 0x1c, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x3a,
|
|
0x00, 0x2f, 0x00, 0x2f, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x41, 0x00, 0x50, 0x00, 0x50,
|
|
0x00, 0x49, 0x00, 0x44, 0x00, 0x10, 0x42, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00,
|
|
0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x5a, 0x00,
|
|
0x75, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x56, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6f, 0x00,
|
|
0x5f, 0x00, 0x38, 0x00, 0x77, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x79, 0x00, 0x62, 0x00, 0x33, 0x00,
|
|
0x64, 0x00, 0x38, 0x00, 0x62, 0x00, 0x62, 0x00, 0x77, 0x00, 0x65, 0x00, 0x86, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
static const BYTE DummyOtherCondition[] =
|
|
{
|
|
0x61, 0x72, 0x74, 0x78, 0xF8, 0x1C, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x3A,
|
|
0x00, 0x2F, 0x00, 0x2F, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x41, 0x00, 0x50, 0x00, 0x50,
|
|
0x00, 0x49, 0x00, 0x44, 0x00, 0x10, 0x46, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00,
|
|
0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2E, 0x00, 0x42, 0x00,
|
|
0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x57, 0x00, 0x65, 0x00, 0x61, 0x00, 0x74, 0x00, 0x68, 0x00,
|
|
0x65, 0x00, 0x72, 0x00, 0x5F, 0x00, 0x38, 0x00, 0x77, 0x00, 0x65, 0x00, 0x6B, 0x00, 0x79, 0x00,
|
|
0x62, 0x00, 0x33, 0x00, 0x64, 0x00, 0x38, 0x00, 0x62, 0x00, 0x62, 0x00, 0x77, 0x00, 0x65, 0x00,
|
|
0x80, 0xF8, 0x1C, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x3A, 0x00, 0x2F, 0x00,
|
|
0x2F, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x41, 0x00, 0x50, 0x00, 0x50, 0x00, 0x49, 0x00,
|
|
0x44, 0x00, 0x01, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xA1, 0x00,
|
|
0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor and destructor
|
|
|
|
ACE_HELPER::ACE_HELPER(DWORD dwAceType, PSID pSid)
|
|
{
|
|
Init(dwAceType, INVALID_ACCESS_MASK, pSid, NULL);
|
|
}
|
|
|
|
ACE_HELPER::ACE_HELPER(DWORD dwAceType, ACCESS_MASK AccessMask, PSID pSid)
|
|
{
|
|
Init(dwAceType, AccessMask, pSid, NULL);
|
|
}
|
|
|
|
ACE_HELPER::ACE_HELPER(const ACE_CSA_HELPER & CsaHelper, PSID pSid)
|
|
{
|
|
Init(SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE, FILE_READ_DATA, pSid, NULL);
|
|
SetResource(CsaHelper);
|
|
}
|
|
|
|
ACE_HELPER::~ACE_HELPER()
|
|
{
|
|
// Free the SIDs
|
|
for(size_t i = 0; i < _countof(Sid); i++)
|
|
{
|
|
if(Sid[i] != NULL)
|
|
LocalFree(Sid[i]);
|
|
Sid[i] = NULL;
|
|
}
|
|
|
|
// Free the condition
|
|
if(Condition != NULL)
|
|
delete[] Condition;
|
|
Condition = NULL;
|
|
|
|
// Free the security attributes
|
|
if(AttrRel != NULL)
|
|
delete[] AttrRel;
|
|
AttrRel = NULL;
|
|
}
|
|
|
|
void ACE_HELPER::Init(DWORD dwAceType, ACCESS_MASK AccessMask, PSID pSid1, PSID pSid2)
|
|
{
|
|
// Set the object to default values
|
|
memset(this, 0, sizeof(ACE_HELPER));
|
|
Mask = AccessMask;
|
|
|
|
// Set the ACE type
|
|
SetAceType(dwAceType);
|
|
|
|
// Put the main SID. If not provided, choose a default SID
|
|
if(pSid1 == NULL)
|
|
pSid1 = GetDefaultSid(AceType, AceFlags);
|
|
SetSid(pSid1, 0);
|
|
|
|
// Put the secondary SID, if any
|
|
SetSid(pSid2, 1);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Public functions
|
|
|
|
bool ACE_HELPER::SetAceType(DWORD dwAceType)
|
|
{
|
|
// Set the ACE type
|
|
AceType = (BYTE)(dwAceType);
|
|
|
|
// Perform ACE-specific initialization
|
|
switch(dwAceType)
|
|
{
|
|
case ACCESS_ALLOWED_ACE_TYPE: // Simple ACEs:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : GENERIC_ALL;
|
|
AceLayout = ACE_LAYOUT_SIMPLE;
|
|
break;
|
|
|
|
case ACCESS_DENIED_ACE_TYPE: // {Header-Mask-SidStart}
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_EXECUTE;
|
|
AceLayout = ACE_LAYOUT_SIMPLE;
|
|
break;
|
|
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : GENERIC_ALL;
|
|
AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
|
|
AceLayout = ACE_LAYOUT_SIMPLE;
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: // Compound ACEs:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : GENERIC_ALL;
|
|
CompoundAceType |= COMPOUND_ACE_IMPERSONATION;
|
|
AceLayout = ACE_LAYOUT_COMPOUND; // {Header-Mask-CompoundType-Reserved-ServerSid-CliendSid}
|
|
SetSid(SidEveryone, 1);
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: // Object ACEs:
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE: // {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart-Condition}
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : ADS_RIGHT_DS_READ_PROP;
|
|
AceLayout = ACE_LAYOUT_OBJECT;
|
|
break;
|
|
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : ADS_RIGHT_DS_READ_PROP;
|
|
AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
|
|
AceLayout = ACE_LAYOUT_OBJECT;
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: // Conditional ACEs:
|
|
SetCondition(DummyAllowedCondition, sizeof(DummyAllowedCondition));
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : GENERIC_ALL;
|
|
AceLayout = ACE_LAYOUT_CONDITION;
|
|
break;
|
|
|
|
case ACCESS_DENIED_CALLBACK_ACE_TYPE: // {Header-Mask-SidStart-Condition}
|
|
SetCondition(DummyAllowedCondition, sizeof(DummyAllowedCondition));
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_EXECUTE;
|
|
AceLayout = ACE_LAYOUT_CONDITION;
|
|
break;
|
|
|
|
case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
|
|
case SYSTEM_ALARM_CALLBACK_ACE_TYPE:
|
|
SetCondition(DummyOtherCondition, sizeof(DummyOtherCondition));
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_EXECUTE;
|
|
AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
|
|
AceLayout = ACE_LAYOUT_CONDITION;
|
|
break;
|
|
|
|
case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: // Conditional object ACEs:
|
|
SetCondition(DummyAllowedCondition, sizeof(DummyAllowedCondition));
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : GENERIC_ALL;
|
|
AceLayout = ACE_LAYOUT_OBJECT_CONDITION;
|
|
break;
|
|
|
|
case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: // {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart-Condition}
|
|
SetCondition(DummyOtherCondition, sizeof(DummyOtherCondition));
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_EXECUTE;
|
|
AceLayout = ACE_LAYOUT_OBJECT_CONDITION;
|
|
break;
|
|
|
|
case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
|
|
case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
|
|
SetCondition(DummyOtherCondition, sizeof(DummyOtherCondition));
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_EXECUTE;
|
|
AceLayout = ACE_LAYOUT_OBJECT_CONDITION;
|
|
AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
|
|
break;
|
|
|
|
case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
|
|
AceLayout = ACE_LAYOUT_MANDATORY;
|
|
break;
|
|
|
|
case SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
|
|
if(AttrRel == NULL || AttrRelLength == 0)
|
|
SetDummyResource();
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_READ_DATA;
|
|
AceLayout = ACE_LAYOUT_RESOURCE; // Contains the CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 structure
|
|
break;
|
|
|
|
case SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_READ_DATA;
|
|
AceLayout = ACE_LAYOUT_POLICY_ID;
|
|
AceFlags |= INHERIT_ONLY_ACE;
|
|
break;
|
|
|
|
case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_READ_DATA;
|
|
AceLayout = ACE_LAYOUT_TRUST_ID;
|
|
AceFlags |= INHERIT_ONLY_ACE;
|
|
break;
|
|
|
|
case SYSTEM_ACCESS_FILTER_ACE_TYPE:
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : FILE_READ_DATA;
|
|
AceLayout = ACE_LAYOUT_TRUST_ID_CONDITION;
|
|
AceFlags |= TRUST_PROTECTED_FILTER_ACE_FLAG;
|
|
SetCondition(DummyOtherCondition, sizeof(DummyOtherCondition));
|
|
break;
|
|
|
|
default: // Unknown ACE type. Just assume ACE_HEADER and AccessMask
|
|
Mask = (Mask != INVALID_ACCESS_MASK) ? Mask : GENERIC_ALL;
|
|
AceLayout = ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK;
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ACE_HELPER::SetAce(PACE_HEADER pAceHeader)
|
|
{
|
|
PSID pSid;
|
|
bool bResult;
|
|
|
|
// Verify ACE type and set the ACE layout
|
|
if((bResult = SetAceType(pAceHeader->AceType)) != false)
|
|
{
|
|
LPBYTE pbAceEnd = (LPBYTE)(pAceHeader) + pAceHeader->AceSize;
|
|
LPBYTE pbAcePtr = (LPBYTE)(pAceHeader + 1);
|
|
|
|
// Fill-in the header (always included)
|
|
if(AceLayout & ACE_FIELD_HEADER)
|
|
{
|
|
AceFlags = pAceHeader->AceFlags;
|
|
AceSize = pAceHeader->AceSize;
|
|
}
|
|
|
|
// Is there the ACE::Mask?
|
|
if(AceLayout & (ACE_FIELD_ACCESS_MASK | ACE_FIELD_ADS_ACCESS_MASK | ACE_FIELD_MANDATORY_MASK))
|
|
{
|
|
Mask = *(PDWORD)(pbAcePtr);
|
|
pbAcePtr += sizeof(DWORD);
|
|
}
|
|
|
|
// Is there the ACE::Flags
|
|
if(AceLayout & ACE_FIELD_GUID_FLAGS)
|
|
{
|
|
// Copy the ACE::Flags
|
|
Flags = *(PDWORD)(pbAcePtr);
|
|
pbAcePtr += sizeof(DWORD);
|
|
|
|
// ACE::ObjectType is only present if ACE_OBJECT_TYPE_PRESENT is in the flags
|
|
if(Flags & ACE_OBJECT_TYPE_PRESENT)
|
|
{
|
|
memcpy(&ObjectType, pbAcePtr, sizeof(GUID));
|
|
pbAcePtr += sizeof(GUID);
|
|
}
|
|
|
|
// Is there the ACE::InheritedObjectType?
|
|
if(Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
|
|
{
|
|
memcpy(&InheritedObjectType, pbAcePtr, sizeof(GUID));
|
|
pbAcePtr += sizeof(GUID);
|
|
}
|
|
}
|
|
|
|
// Get the compound ACE type
|
|
if(AceLayout & (ACE_FIELD_COMPOUND_TYPE | ACE_FIELD_COMPOUND_RSVD))
|
|
{
|
|
CompoundAceType = *(PUSHORT)(pbAcePtr);
|
|
CompoundReserved = *(PUSHORT)(pbAcePtr + sizeof(USHORT));
|
|
pbAcePtr += sizeof(USHORT) + sizeof(USHORT);
|
|
}
|
|
|
|
// Get the pointer to (server|mandatory) SID
|
|
if(AceLayout & (ACE_FIELD_SID | ACE_FIELD_MANDATORY_SID | ACE_FIELD_MANDATORY_MASK))
|
|
{
|
|
if((pSid = SetSid(pbAcePtr, 0)) != NULL)
|
|
pbAcePtr += GetLengthSid(pSid);
|
|
}
|
|
|
|
// Get the pointer to (server|mandatory) SID
|
|
if(AceLayout & ACE_FIELD_CLIENT_SID)
|
|
{
|
|
if((pSid = SetSid(pbAcePtr, 1)) != NULL)
|
|
pbAcePtr += GetLengthSid(pSid);
|
|
}
|
|
|
|
// Get the CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 and convert it to pointer-based structure
|
|
if((AceLayout & ACE_FIELD_CSA_V1) && (pbAcePtr < pbAceEnd))
|
|
{
|
|
if(SetResource(pbAcePtr, (pbAceEnd - pbAcePtr)))
|
|
pbAcePtr += AttrRelLength;
|
|
}
|
|
|
|
// Get the ACE condition. Example: C:\Program Files\WindowsApps\<any folder>
|
|
if((AceLayout & ACE_FIELD_CONDITION) && (pbAcePtr < pbAceEnd))
|
|
{
|
|
if(SetCondition(pbAcePtr, (pbAceEnd - pbAcePtr)))
|
|
pbAcePtr += ConditionLength;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
// pSid could be NULL if we want just to free the existing SID[nSidIndex]
|
|
PSID ACE_HELPER::SetSid(LPCVOID lpSid, size_t nSidIndex)
|
|
{
|
|
PSID pSid = (PSID)(lpSid);
|
|
ULONG cbSid;
|
|
|
|
// Free the old SID
|
|
if(Sid[nSidIndex] != NULL)
|
|
LocalFree(Sid[nSidIndex]);
|
|
Sid[nSidIndex] = NULL;
|
|
|
|
// Store the new one
|
|
if(pSid != NULL && (cbSid = RtlLengthSid(pSid)) != 0)
|
|
{
|
|
if((Sid[nSidIndex] = (PSID)LocalAlloc(LPTR, cbSid)) != NULL)
|
|
{
|
|
memcpy(Sid[nSidIndex], pSid, cbSid);
|
|
}
|
|
}
|
|
|
|
// Return the new SID
|
|
return Sid[nSidIndex];
|
|
}
|
|
|
|
bool ACE_HELPER::SetResource(LPCVOID lpAttrRel, size_t cbAttrRel)
|
|
{
|
|
LPBYTE pbAttrRel = (LPBYTE)(lpAttrRel);
|
|
|
|
AttrRel = CaptureExtraStructure(pbAttrRel, pbAttrRel + cbAttrRel, &AttrRelLength);
|
|
return (AttrRel && AttrRelLength);
|
|
}
|
|
|
|
bool ACE_HELPER::SetCondition(LPCVOID lpCondition, size_t cbCondition)
|
|
{
|
|
LPBYTE pbCondition = (LPBYTE)(lpCondition);
|
|
|
|
Condition = CaptureExtraStructure(pbCondition, pbCondition + cbCondition, &ConditionLength);
|
|
return (Condition && ConditionLength);
|
|
}
|
|
|
|
bool ACE_HELPER::SetResource(const ACE_CSA_HELPER & CsaHelper)
|
|
{
|
|
PCLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 pAttrRel;
|
|
ULONG cbAttrRel = 0;
|
|
bool bResult = false;
|
|
|
|
// Export the resource object
|
|
if((pAttrRel = CsaHelper.Export(&cbAttrRel)) != NULL)
|
|
{
|
|
bResult = SetResource(pAttrRel, cbAttrRel);
|
|
LocalFree(pAttrRel);
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
bool ACE_HELPER::SetDummyResource()
|
|
{
|
|
ACE_CSA_HELPER CsaHelper(L"RESOURCE_STRINGS", CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING, 4);
|
|
|
|
// Modify the flags
|
|
CsaHelper.Flags = CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
|
|
return SetResource(CsaHelper);
|
|
}
|
|
|
|
PACE_HEADER ACE_HELPER::Export(LPBYTE pbBuffer, size_t cbBuffer)
|
|
{
|
|
PACE_HEADER pAceHeader = (PACE_HEADER)(pbBuffer);
|
|
LPBYTE pbEnd = pbBuffer + cbBuffer;
|
|
LPBYTE pbPtr = pbBuffer;
|
|
|
|
// Fill-in the header
|
|
if(AceLayout & ACE_FIELD_HEADER)
|
|
{
|
|
if((pbPtr + sizeof(ACE_HEADER)) > pbEnd)
|
|
return NULL;
|
|
pAceHeader->AceType = AceType;
|
|
pAceHeader->AceFlags = AceFlags;
|
|
pAceHeader->AceSize = sizeof(ACE_HEADER);
|
|
pbPtr += sizeof(ACE_HEADER);
|
|
}
|
|
|
|
// Fill-in the ACE:Mask
|
|
pbPtr = PutAceValue(pbPtr, pbEnd, &Mask, (ACE_FIELD_ACCESS_MASK | ACE_FIELD_ADS_ACCESS_MASK | ACE_FIELD_MANDATORY_MASK), sizeof(ACCESS_MASK));
|
|
if(pbPtr == NULL)
|
|
return NULL;
|
|
|
|
// Fill-in the ACE::Flags
|
|
pbPtr = PutAceValue(pbPtr, pbEnd, &Flags, ACE_FIELD_GUID_FLAGS, sizeof(Flags));
|
|
if(pbPtr == NULL)
|
|
return NULL;
|
|
|
|
// Fill-in the ACE::CompoundAceType
|
|
pbPtr = PutAceValue(pbPtr, pbEnd, &CompoundAceType, ACE_FIELD_COMPOUND_TYPE, sizeof(CompoundAceType));
|
|
if(pbPtr == NULL)
|
|
return NULL;
|
|
|
|
// Fill-in the ACE::CompoundReserved
|
|
pbPtr = PutAceValue(pbPtr, pbEnd, &CompoundReserved, ACE_FIELD_COMPOUND_RSVD, sizeof(CompoundReserved));
|
|
if(pbPtr == NULL)
|
|
return NULL;
|
|
|
|
// Fill-in the ACE::ObjectType
|
|
if((AceLayout & ACE_FIELD_GUID_FLAGS) && (Flags & ACE_OBJECT_TYPE_PRESENT))
|
|
{
|
|
pbPtr = PutAceValue(pbPtr, pbEnd, &ObjectType, ACE_FIELD_OBJECT_TYPE1, sizeof(ObjectType));
|
|
if(pbPtr == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Fill-in the ACE::InheritedObjectType
|
|
if((AceLayout & ACE_FIELD_GUID_FLAGS) && (Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT))
|
|
{
|
|
pbPtr = PutAceValue(pbPtr, pbEnd, &InheritedObjectType, ACE_FIELD_OBJECT_TYPE2, sizeof(InheritedObjectType));
|
|
if(pbPtr == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Fill-in the (server, mandatory, policy, trust, conditional trust) SID
|
|
if(AceLayout & ACE_FIELD_PRIMARY_SID_MASK)
|
|
{
|
|
if((pbPtr = PutAceValueSid(pbPtr, pbEnd, Sid[0])) == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Fill-in the client SID
|
|
if(AceLayout & ACE_FIELD_CLIENT_SID)
|
|
{
|
|
if((pbPtr = PutAceValueSid(pbPtr, pbEnd, Sid[1])) == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Fill-in the CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
|
|
if(AceLayout & ACE_FIELD_CSA_V1)
|
|
{
|
|
if((pbPtr = PutAceValueBinary(pbPtr, pbEnd, AttrRel, AttrRelLength)) == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Fill-in the CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
|
|
if((AceLayout & ACE_FIELD_CONDITION) && (Condition != NULL))
|
|
{
|
|
if((pbPtr = PutAceValueBinary(pbPtr, pbEnd, Condition, ConditionLength)) == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Fixup the ACE size
|
|
pAceHeader->AceSize = (WORD)(pbPtr - (LPBYTE)pAceHeader);
|
|
return pAceHeader;
|
|
}
|
|
|
|
PACE_HEADER ACE_HELPER::AddToAcl(PACL pAcl)
|
|
{
|
|
PACE_HEADER pAceHeader;
|
|
PACE_HEADER pTemp = NULL;
|
|
LPBYTE pbPtr = (LPBYTE)(pAcl) + sizeof(ACL);
|
|
LPBYTE pbEnd = (LPBYTE)(pAcl) + pAcl->AclSize;
|
|
|
|
// Skip all ACEs
|
|
if(pAcl->AceCount > 0)
|
|
{
|
|
RtlGetAce(pAcl, pAcl->AceCount - 1, (PVOID *)(&pTemp));
|
|
pbPtr = (LPBYTE)(pTemp) + pTemp->AceSize;
|
|
}
|
|
|
|
// Build the ACE
|
|
if((pAceHeader = Export(pbPtr, pbEnd - pbPtr)) != NULL)
|
|
pAcl->AceCount++;
|
|
return pAceHeader;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
LPBYTE ACE_HELPER::PutAceValueSid(LPBYTE PtrAclData, LPBYTE PtrAclEnd, PSID pSourceSid)
|
|
{
|
|
LPBYTE pbResult = NULL;
|
|
ULONG SidLength;
|
|
|
|
// If no SID is given, create one with Everyone
|
|
if(pSourceSid == NULL)
|
|
pSourceSid = GetDefaultSid(AceType, AceFlags);
|
|
|
|
// If we have that SID, add it to the ACE data
|
|
if(pSourceSid != NULL)
|
|
{
|
|
SidLength = RtlLengthSid(pSourceSid);
|
|
|
|
if((PtrAclData + SidLength) <= PtrAclEnd)
|
|
{
|
|
memmove(PtrAclData, pSourceSid, SidLength);
|
|
pbResult = PtrAclData + SidLength;
|
|
}
|
|
}
|
|
return pbResult;
|
|
}
|
|
|
|
LPBYTE ACE_HELPER::PutAceValueBinary(LPBYTE PtrAclData, LPBYTE PtrAclEnd, LPVOID lpData, size_t cbData)
|
|
{
|
|
LPBYTE pbResult = NULL;
|
|
|
|
// If we have that SID, add it to the ACE data
|
|
if(lpData && cbData)
|
|
{
|
|
if((PtrAclData + cbData) <= PtrAclEnd)
|
|
{
|
|
memmove(PtrAclData, lpData, cbData);
|
|
pbResult = PtrAclData + cbData;
|
|
}
|
|
}
|
|
return pbResult;
|
|
}
|
|
|
|
LPBYTE ACE_HELPER::CaptureExtraStructure(LPBYTE pbPtr, LPBYTE pbEnd, size_t * pcbMoveBy)
|
|
{
|
|
LPBYTE pbExtraStructure = NULL;
|
|
size_t cbExtraStructure = 0;
|
|
|
|
// Allocate copy of the values
|
|
if(pbPtr < pbEnd)
|
|
{
|
|
if((pbExtraStructure = new BYTE[pbEnd - pbPtr]) != NULL)
|
|
{
|
|
memmove(pbExtraStructure, pbPtr, pbEnd - pbPtr);
|
|
cbExtraStructure = pbEnd - pbPtr;
|
|
}
|
|
}
|
|
|
|
// Give the values to the caller
|
|
if(pcbMoveBy != NULL)
|
|
pcbMoveBy[0] = cbExtraStructure;
|
|
return pbExtraStructure;
|
|
}
|
|
|
|
PSID ACE_HELPER::GetDefaultSid(DWORD dwAceType, DWORD dwAceFlags)
|
|
{
|
|
switch(dwAceType)
|
|
{
|
|
case SYSTEM_MANDATORY_LABEL_ACE_TYPE: // Mandatory label ACE requires S-1-16-###
|
|
return (PSID)(SidLabelMedium);
|
|
|
|
case SYSTEM_SCOPED_POLICY_ID_ACE_TYPE: // System scoped policy requires S-1-17-###
|
|
return (PSID)(SidSystemAce17);
|
|
|
|
case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE: // System process trust label requires S-1-19-###
|
|
return (PSID)(SidSystemAce19);
|
|
|
|
// When Flags don't contain TRUST_PROTECTED_FILTER_ACE_FLAG (0x40), the SID must be Everyone,
|
|
// which means the system simply filters access according to the callback condition.
|
|
// When Flags contain TRUST_PROTECTED_FILTER_ACE_FLAG, the SID must represent a trust level
|
|
// (S-1-19-x-y). In this case, the system performs access filtration according to the condition
|
|
// only when the caller's trust is lower. In other words, a trust-protected Access Filter ACE
|
|
// works as a Trust Label Callback ACE would.
|
|
case SYSTEM_ACCESS_FILTER_ACE_TYPE:
|
|
if(dwAceFlags & TRUST_PROTECTED_FILTER_ACE_FLAG)
|
|
return (PSID)(SidSystemAce19);
|
|
// Go default into SidEveryone
|
|
|
|
default:
|
|
return (PSID)(SidEveryone);
|
|
}
|
|
}
|