WEBINAR:
On-Demand
Application Security Testing: An Integral Part of DevOps
The ACLInfo Sample
The sample program that accompanies this article is a console application that accepts a file or directory path as its command line argument and then retrieves and displays the ACL information for that file. This will only work correctly if the file or folder resides on an NTFS-formatted partition and you have Read access permissions to ACL information.
Listing 1 shows the interface definition of the ACLInfo class as it appears in the
ACLInfo.h header file. You should construct an ACLInfo object supplying the path to the file or folder. Then call the
Query method that loads the corresponding ACEs and places them into the linked list (
m_sAceList) of the
ace_list* type (the definition of
ace_list appears in
Listing 1 as well). Finally, call the
Output method to display the ACL. The
Main.cpp file (
Listing 2) is the sample usage of the ACLInfo class.
The Query Method
The
Query method (
Listing 3) calls the
GetFileSecurityW function twice. In the first call it obtains the size required to store the security descriptor. Then you allocate the required memory and call the function again, this time supplying the pointer to the
BYTE* buffer that will hold the security descriptor. Note that I pass
DACL_SECURITY_INFORMATION as the second argument. This way, I inform the API that I want Discretionary Access Control List information. The second argument may be any valid combination of different flags that specify the type of security information you are querying. Read the MSDN documentation for
GetFileSecurity to learn more about its arguments.
The next fragment retrieves DACL from the security descriptor:
// Getting DACL from Security Descriptor
PACL pacl;
BOOL bDaclPresent, bDaclDefaulted;
bSuccess =GetSecurityDescriptorDacl(
(SECURITY_DESCRIPTOR*)pSecDescriptorBuf,
&bDaclPresent, &pacl, &bDaclDefaulted);
// Check if we successfully retrieved DACL
if (!bSuccess)
{
DWORD dwError = GetLastError();
cout << "Failed to retrieve DACL from security descriptor (";
cout << dwError << ")\n";
return E_FAIL;
}
This code checks that DACL is actually present in the security descriptor. If there is no DACL present then
GetSecurityDescriptorDacl sets
bDaclPresent to False.
// Check if DACL present in security descriptor
if (!bDaclPresent)
{
cout << "DACL was not found.\n";
return E_FAIL;
}
After verifying that DACL was successfully retrieved you can iterate through its ACEs and fill in the linked list from ACLInfo. The following loop does just this:
for (USHORT i = 0; i < pacl->AceCount; i++)
{
LPVOID pAce;
bSuccess = GetAce(pacl, i, &pAce);
if (!bSuccess)
{
DWORD dwError = GetLastError();
cout << "Failed to get ace "
<< i << " (" << dwError << ")\n";
continue;
}
HRESULT hr = AddAceToList((ACE_HEADER*)pAce);
if (FAILED(hr))
{
cout << "Failed to add ace "
<< i << "to list.\n";
continue;
}
}