Skip to content

Commit 002c5a0

Browse files
committed
Initial code checkin
1 parent f4197ce commit 002c5a0

File tree

10 files changed

+1188
-0
lines changed

10 files changed

+1188
-0
lines changed

addacl.c

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
#define WIN32_LEAN_AND_MEAN
2+
#include <windows.h>
3+
#include <stdio.h>
4+
#include "addacl.h"
5+
6+
void ShowModuleError(LPSTR pszModError, LPSTR pszError);
7+
8+
typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)(
9+
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
10+
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
11+
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet);
12+
13+
typedef struct {
14+
PSECURITY_DESCRIPTOR pFileSD;
15+
PACL pNewACL;
16+
} TYP_INST;
17+
18+
static void FreeInst(TYP_INST *pInst);
19+
static BOOL ShowError(TYP_INST *pInst, LPSTR pszError);
20+
21+
BOOL AddAccessRights(LPSTR lpszFileName, LPVOID pUserSID,
22+
DWORD dwAccessMask)
23+
{
24+
TYP_INST Inst = {0};
25+
26+
// File SD variables.
27+
DWORD cbFileSD = 0;
28+
29+
// New SD variables.
30+
SECURITY_DESCRIPTOR newSD;
31+
32+
// ACL variables.
33+
PACL pACL = NULL;
34+
BOOL fDaclPresent;
35+
BOOL fDaclDefaulted;
36+
ACL_SIZE_INFORMATION AclInfo;
37+
38+
// New ACL variables.
39+
DWORD cbNewACL = 0;
40+
41+
// Temporary ACE.
42+
LPVOID pTempAce = NULL;
43+
UINT CurrentAceIndex = 0;
44+
45+
UINT newAceIndex = 0;
46+
47+
// Assume function will fail.
48+
BOOL fResult = FALSE;
49+
BOOL fAPISuccess;
50+
51+
SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
52+
53+
// New APIs available only in Windows 2000 and above for setting
54+
// SD control
55+
SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl = NULL;
56+
57+
//
58+
// STEP 2: Get security descriptor (SD) of the file specified.
59+
//
60+
if (fAPISuccess = GetFileSecurity(lpszFileName,
61+
secInfo, Inst.pFileSD, 0, &cbFileSD))
62+
return ShowError (&Inst, "GetFileSecurity() failed.");
63+
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
64+
{
65+
Inst.pFileSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbFileSD);
66+
if (!Inst.pFileSD) return ShowError (&Inst, "Out of memory");
67+
fAPISuccess = GetFileSecurity(lpszFileName,
68+
secInfo, Inst.pFileSD, cbFileSD, &cbFileSD);
69+
}
70+
if (!fAPISuccess) return ShowError (&Inst, "GetFileSecurity() failed.");
71+
72+
//
73+
// STEP 3: Initialize new SD.
74+
//
75+
if (!InitializeSecurityDescriptor(&newSD, SECURITY_DESCRIPTOR_REVISION))
76+
return ShowError (&Inst, "InitializeSecurityDescriptor() failed.");
77+
78+
//
79+
// STEP 4: Get DACL from the old SD.
80+
//
81+
if (!GetSecurityDescriptorDacl(Inst.pFileSD, &fDaclPresent, &pACL,
82+
&fDaclDefaulted)) return ShowError (&Inst, "GetSecurityDescriptorDacl() failed.");
83+
84+
//
85+
// STEP 5: Get size information for DACL.
86+
//
87+
AclInfo.AceCount = 0; // Assume NULL DACL.
88+
AclInfo.AclBytesFree = 0;
89+
AclInfo.AclBytesInUse = sizeof(ACL);
90+
91+
if (pACL == NULL)
92+
fDaclPresent = FALSE;
93+
94+
// If not NULL DACL, gather size information from DACL.
95+
if (fDaclPresent) {
96+
if (!GetAclInformation(pACL, &AclInfo,
97+
sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
98+
return ShowError (&Inst, "GetAclInformation() failed.");
99+
}
100+
101+
//
102+
// STEP 6: Compute size needed for the new ACL.
103+
//
104+
cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
105+
+ GetLengthSid(pUserSID) - sizeof(DWORD);
106+
107+
//
108+
// STEP 7: Allocate memory for new ACL.
109+
//
110+
if (!(Inst.pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL)))
111+
return ShowError (&Inst, "Out of memory.");
112+
113+
//
114+
// STEP 8: Initialize the new ACL.
115+
//
116+
if (!InitializeAcl(Inst.pNewACL, cbNewACL, ACL_REVISION2))
117+
return ShowError (&Inst, "InitializeAcl() failed");
118+
119+
//
120+
// STEP 9 If DACL is present, copy all the ACEs from the old DACL
121+
// to the new DACL.
122+
//
123+
// The following code assumes that the old DACL is
124+
// already in Windows 2000 preferred order. To conform
125+
// to the new Windows 2000 preferred order, first we will
126+
// copy all non-inherited ACEs from the old DACL to the
127+
// new DACL, irrespective of the ACE type.
128+
//
129+
130+
newAceIndex = 0;
131+
132+
if (fDaclPresent && AclInfo.AceCount) {
133+
134+
for (CurrentAceIndex = 0;
135+
CurrentAceIndex < AclInfo.AceCount;
136+
CurrentAceIndex++) {
137+
138+
//
139+
// STEP 10: Get an ACE.
140+
//
141+
if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
142+
return ShowError (&Inst, "GetAce() failed.");
143+
144+
//
145+
// STEP 11: Check if it is a non-inherited ACE.
146+
// If it is an inherited ACE, break from the loop so
147+
// that the new access allowed non-inherited ACE can
148+
// be added in the correct position, immediately after
149+
// all non-inherited ACEs.
150+
//
151+
if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags
152+
& INHERITED_ACE)
153+
break;
154+
155+
//
156+
// STEP 12: Skip adding the ACE, if the SID matches
157+
// with the account specified, as we are going to
158+
// add an access allowed ACE with a different access
159+
// mask.
160+
//
161+
if (EqualSid(pUserSID,
162+
&(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))
163+
continue;
164+
165+
//
166+
// STEP 13: Add the ACE to the new ACL.
167+
//
168+
if (!AddAce(Inst.pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
169+
((PACE_HEADER) pTempAce)->AceSize))
170+
return ShowError (&Inst, "AddAce() failed.");
171+
172+
newAceIndex++;
173+
}
174+
}
175+
176+
//
177+
// STEP 14: Add the access-allowed ACE to the new DACL.
178+
// The new ACE added here will be in the correct position,
179+
// immediately after all existing non-inherited ACEs.
180+
//
181+
if (!AddAccessAllowedAce(Inst.pNewACL, ACL_REVISION2, dwAccessMask,
182+
pUserSID))
183+
return ShowError (&Inst, "AddAccessAllowedAce() failed.");
184+
185+
//
186+
// STEP 15: To conform to the new Windows 2000 preferred order,
187+
// we will now copy the rest of inherited ACEs from the
188+
// old DACL to the new DACL.
189+
//
190+
if (fDaclPresent && AclInfo.AceCount) {
191+
192+
for (;
193+
CurrentAceIndex < AclInfo.AceCount;
194+
CurrentAceIndex++) {
195+
196+
//
197+
// STEP 16: Get an ACE.
198+
//
199+
if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
200+
return ShowError (&Inst, "GetAce() failed.");
201+
202+
//
203+
// STEP 17: Add the ACE to the new ACL.
204+
//
205+
if (!AddAce(Inst.pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
206+
((PACE_HEADER) pTempAce)->AceSize))
207+
return ShowError (&Inst, "AddAce() failed.");
208+
}
209+
}
210+
211+
//
212+
// STEP 18: Set the new DACL to the new SD.
213+
//
214+
if (!SetSecurityDescriptorDacl(&newSD, TRUE, Inst.pNewACL,
215+
FALSE)) return ShowError (&Inst, "SetSecurityDescriptorDacl() failed.");
216+
217+
//
218+
// STEP 19: Copy the old security descriptor control flags
219+
// regarding DACL automatic inheritance for Windows 2000 or
220+
// later where SetSecurityDescriptorControl() API is available
221+
// in advapi32.dll.
222+
//
223+
_SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr)
224+
GetProcAddress(GetModuleHandle("advapi32.dll"),
225+
"SetSecurityDescriptorControl");
226+
if (_SetSecurityDescriptorControl) {
227+
228+
SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0;
229+
SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0;
230+
SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0;
231+
DWORD dwRevision = 0;
232+
233+
if (!GetSecurityDescriptorControl(Inst.pFileSD, &oldControlBits,
234+
&dwRevision)) return ShowError (&Inst, "GetSecurityDescriptorControl() failed.");
235+
236+
if (oldControlBits & SE_DACL_AUTO_INHERITED) {
237+
controlBitsOfInterest =
238+
SE_DACL_AUTO_INHERIT_REQ |
239+
SE_DACL_AUTO_INHERITED;
240+
controlBitsToSet = controlBitsOfInterest;
241+
}
242+
else if (oldControlBits & SE_DACL_PROTECTED) {
243+
controlBitsOfInterest = SE_DACL_PROTECTED;
244+
controlBitsToSet = controlBitsOfInterest;
245+
}
246+
247+
if (controlBitsOfInterest) {
248+
if (!_SetSecurityDescriptorControl(&newSD,
249+
controlBitsOfInterest,
250+
controlBitsToSet))
251+
return ShowError (&Inst, "SetSecurityDescriptorControl() failed.");
252+
}
253+
}
254+
255+
//
256+
// STEP 20: Set the new SD to the File.
257+
//
258+
if (!SetFileSecurity(lpszFileName, secInfo,
259+
&newSD)) return ShowError (&Inst, "SetFileSecurity() failed.");
260+
261+
fResult = TRUE;
262+
FreeInst(&Inst);
263+
264+
return fResult;
265+
}
266+
267+
// =============================================================
268+
// Private
269+
// =============================================================
270+
static void FreeInst(TYP_INST *pInst)
271+
{
272+
if (pInst->pFileSD)
273+
HeapFree(GetProcessHeap(), 0, pInst->pFileSD);
274+
275+
if (pInst->pNewACL)
276+
HeapFree (GetProcessHeap(), 0, pInst->pNewACL);
277+
}
278+
279+
// --------------------------------------------------------------
280+
281+
static BOOL ShowError(TYP_INST *pInst, LPSTR pszError)
282+
{
283+
ShowModuleError("Failed setting up ACL", pszError);
284+
FreeInst(pInst);
285+
return FALSE;
286+
}

addacl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
BOOL AddAccessRights(LPSTR lpszFileName, LPVOID pUserSID, DWORD dwAccessMask);

0 commit comments

Comments
 (0)