forked from ladislav-zezula/FileTest
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTAceHelper.cpp
250 lines (206 loc) · 9.75 KB
/
TAceHelper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*****************************************************************************/
/* 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;
}