| Platform SDK: Active Directory, ADSI, and Directory Services |
The following code is a program that reads the defaultSecurityDescriptor for a specified object class:
#include <stdio.h>
#include <wchar.h>
#include <objbase.h>
#include <activeds.h>
#include <ACCCTRL.h>
//For security descriptor control flags
#include <winnt.h>
#define _WIN32_WINNT 0x0500
#include <Sddl.h>
HRESULT ReadDefaultSecurityDescriptor( IADs *pObject );
int SDParseControlMasks( long lCtrl );
int SDParseAccessMask( long lCtrl );
int main(int argc, char *argv[])
{
LPOLESTR szPath = new OLECHAR[MAX_PATH];
LPOLESTR pszBuffer = new WCHAR[MAX_PATH];
HRESULT hr = S_OK;
IADs *pObject = NULL;
VARIANT var;
wprintf(L"This program displays the default security descriptor of an object class\n");
wprintf(L"Specify the object class:");
_getws(pszBuffer);
if (!pszBuffer)
return TRUE;
wcscpy(szPath, L"LDAP://cn=");
wcscat(szPath, pszBuffer);
wcscat(szPath, L",");
// Intialize COM.
CoInitialize(NULL);
// Get rootDSE and the schema container's DN.
// Bind to current user's domain using current user's security context.
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
IID_IADs,
(void**)&pObject);
if (SUCCEEDED(hr))
{
hr = pObject->Get(L"schemaNamingContext",&var);
if (SUCCEEDED(hr))
{
wcscat(szPath,var.bstrVal);
VariantClear(&var);
if (pObject)
{
pObject->Release();
pObject = NULL;
}
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
IID_IADs,
(void**)&pObject);
if (SUCCEEDED(hr))
{
wprintf(L"***********Read the default SD for the %s class***********\n", pszBuffer);
hr = ReadDefaultSecurityDescriptor(
pObject
);
}
}
}
if (FAILED(hr))
wprintf(L"Failed with the following HRESULT: %x\n",hr);
if (pObject)
pObject->Release();
// Uninitialize COM
CoUninitialize();
return TRUE;
}
HRESULT ReadDefaultSecurityDescriptor( IADs *pObject )
{
HRESULT hr = E_FAIL;
PSECURITY_DESCRIPTOR pSDCNV = NULL;
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
PACL pDacl = NULL;
LPVOID pAce = NULL;
BYTE bAceType, bAceFlags;
PSID pSID = NULL;
DWORD dAccessMask;
OLECHAR szTrusteeName[MAX_PATH];
DWORD cbName = 0L;
OLECHAR szTrusteeDomainName[MAX_PATH];
DWORD cbReferencedDomainName = 0L;
SID_NAME_USE TrusteeType;
PACCESS_ALLOWED_ACE paace = NULL;
PACCESS_ALLOWED_OBJECT_ACE poace = NULL;
DWORD dFlags = 0L;
VARIANT var;
LPOLESTR szGUID = new WCHAR [39];
hr = pObject->Get(L"defaultSecurityDescriptor",&var);
if (SUCCEEDED(hr))
{
//Type should be VT_BSTR.
if (var.vt==VT_BSTR)
{
wprintf(L"Default SD: %s\n", var.bstrVal);
if (ConvertStringSecurityDescriptorToSecurityDescriptor(var.bstrVal,
SDDL_REVISION_1,
&pSDCNV,
NULL
))
{
//Read the security descriptor.
//Get the DACL
if (GetSecurityDescriptorDacl(
pSDCNV, // address of security descriptor
&bDaclPresent, // address of flag for presence of disc. ACL
&pDacl, // address of pointer to ACL
&bDaclDefaulted // address of flag for default disc. ACL
))
{
printf("Ace count: %d\n",pDacl->AceCount);
for (WORD i = 0; i < pDacl->AceCount; i++ )
{
//Get the ACE
if (GetAce( pDacl, // pointer to access-control list
i, // index of ACE to retrieve
&pAce // pointer to pointer to ACE
))
{
wprintf(L"**** ACE %d of %d ****\n", i+1, pDacl->AceCount);
bAceType = ((ACE_HEADER *)pAce)->AceType;
bAceFlags = ((ACE_HEADER *)pAce)->AceFlags;
switch (bAceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
printf("ACE Type: ACCESS_ALLOWED_ACE_TYPE\n");
dAccessMask = ((ACCESS_ALLOWED_ACE *)pAce)->Mask;
paace = (PACCESS_ALLOWED_ACE)pAce;
pSID = (PSID)&(paace->SidStart);
break;
case ACCESS_DENIED_ACE_TYPE:
printf("ACE Type: ACCESS_DENIED_ACE_TYPE\n");
dAccessMask = ((ACCESS_DENIED_ACE *)pAce)->Mask;
paace = (PACCESS_ALLOWED_ACE)pAce;
pSID = (PSID)&(paace->SidStart);
break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
printf("ACE Type: ACCESS_ALLOWED_OBJECT_ACE_TYPE\n");
dAccessMask = ((ACCESS_ALLOWED_OBJECT_ACE *)pAce)->Mask;
poace = (PACCESS_ALLOWED_OBJECT_ACE)pAce;
//Check Flags to see
//if object type and/or inherited object type is set.
dFlags = poace->Flags;
if (dFlags & ACE_OBJECT_TYPE_PRESENT)
{
//Convert GUID to string.
::StringFromGUID2(poace->ObjectType, szGUID, 39);
//Print the GUID
wprintf(L"ObjectType GUID: %s\n",szGUID);
}
//Print the inherited object type
//If both GUIDs are present, go to the member.
if ( (dFlags & ACE_OBJECT_TYPE_PRESENT)
&& (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
)
{
//Convert GUID to string.
::StringFromGUID2(poace->InheritedObjectType, szGUID, 39);
//Print the GUID
wprintf(L"Inherited ObjectType GUID: %s\n",szGUID);
}
//If only the inherited object type is present,
//we need to go to the ObjectType member.
if ( (!(dFlags & ACE_OBJECT_TYPE_PRESENT))
&& (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
)
{
//Convert GUID to string.
::StringFromGUID2(poace->ObjectType, szGUID, 39);
//Print the GUID
wprintf(L"Inherited ObjectType GUID: %s\n",szGUID);
}
//Get the SID from the ACE.
if ( (dFlags & ACE_OBJECT_TYPE_PRESENT)
&& (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
)
{
pSID = (PSID)&(poace->SidStart);
}
else if (dFlags & ACE_OBJECT_TYPE_PRESENT)
{
pSID = (PSID)&(poace->InheritedObjectType);
}
else if (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
{
pSID = (PSID)&(poace->InheritedObjectType);
}
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
printf("ACCESS_DENIED_OBJECT_ACE_TYPE\n");
dAccessMask = ((ACCESS_DENIED_OBJECT_ACE *)pAce)->Mask;
poace = (PACCESS_ALLOWED_OBJECT_ACE)pAce;
//Check Flags to see
//if object type and/or inherited object type is set.
dFlags = poace->Flags;
if (dFlags & ACE_OBJECT_TYPE_PRESENT)
{
//Convert GUID to string.
::StringFromGUID2(poace->ObjectType, szGUID, 39);
//Print the GUID
wprintf(L"ObjectType GUID: %s\n",szGUID);
}
//Print the inherited object type
//If both GUIDs are present, go to the member.
if ( (dFlags & ACE_OBJECT_TYPE_PRESENT)
&& (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
)
{
//Convert GUID to string.
::StringFromGUID2(poace->InheritedObjectType, szGUID, 39);
//Print the GUID
wprintf(L"Inherited ObjectType GUID: %s\n",szGUID);
}
//If only the inherited object type is present,
//we need to go to the ObjectType member.
if ( (!(dFlags & ACE_OBJECT_TYPE_PRESENT))
&& (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
)
{
//Convert GUID to string.
::StringFromGUID2(poace->ObjectType, szGUID, 39);
//Print the GUID
wprintf(L"Inherited ObjectType GUID: %s\n",szGUID);
}
//Get the SID from the ACE.
if ( (dFlags & ACE_OBJECT_TYPE_PRESENT)
&& (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
)
{
pSID = (PSID)&(poace->SidStart);
}
else if (dFlags & ACE_OBJECT_TYPE_PRESENT)
{
pSID = (PSID)&(poace->InheritedObjectType);
}
else if (dFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
{
pSID = (PSID)&(poace->InheritedObjectType);
}
break;
default:
printf("Unknown ACE TYPE\n");
break;
}
cbName = sizeof(szTrusteeName);
cbReferencedDomainName = sizeof(szTrusteeDomainName);
ZeroMemory(szTrusteeName, cbName);
ZeroMemory(szTrusteeDomainName, cbReferencedDomainName);
//Look up the trustee name and domain.
if (LookupAccountSid(
NULL, // address of string for system name
pSID, // address of security identifier
szTrusteeName, // address of string for account name
&cbName, // address of size account string
szTrusteeDomainName,
// address of string for referenced domain
&cbReferencedDomainName,
// address of size domain string
&TrusteeType // address of structure for SID type
))
{
if (wcslen(szTrusteeDomainName)==0)
wprintf(L"Trustee: %s\n",szTrusteeName);
else
wprintf(L"Trustee: %s\\%s\n", szTrusteeDomainName,szTrusteeName);
}
else
{
if (GetLastError() == ERROR_NONE_MAPPED)
{
printf("Last Error: ERROR_NONE_MAPPED\n");
}
else
{
printf("Last Error: %d\n",GetLastError());
}
}
printf("AccessMask: \n");
SDParseAccessMask(dAccessMask);
printf("Inheritance flags: %d\n",bAceFlags);
}
}
}
}
if (pSDCNV)
LocalFree(pSDCNV);
}
}
VariantClear(&var);
return hr;
}
//Function to print Control flags.
int SDParseControlMasks(
long lCtrl
)
{
int iReturn = TRUE;
if (lCtrl & SE_OWNER_DEFAULTED)
printf(" SE_OWNER_DEFAULTED\n");
if (lCtrl & SE_GROUP_DEFAULTED)
printf(" SE_GROUP_DEFAULTED\n");
if (lCtrl & SE_DACL_PRESENT)
printf(" SE_DACL_PRESENT\n");
if (lCtrl & SE_DACL_DEFAULTED)
printf(" SE_DACL_DEFAULTED\n");
if (lCtrl & SE_SACL_PRESENT)
printf(" SE_SACL_PRESENT\n");
if (lCtrl & SE_SACL_DEFAULTED)
printf(" SE_SACL_DEFAULTED\n");
if (lCtrl & SE_DACL_AUTO_INHERIT_REQ)
printf(" SE_DACL_AUTO_INHERIT_REQ\n");
if (lCtrl & SE_SACL_AUTO_INHERIT_REQ)
printf(" SE_SACL_AUTO_INHERIT_REQ\n");
if (lCtrl & SE_DACL_AUTO_INHERITED)
printf(" SE_DACL_AUTO_INHERITED\n");
if (lCtrl & SE_SACL_AUTO_INHERITED)
printf(" SE_SACL_AUTO_INHERITED\n");
if (lCtrl & SE_DACL_PROTECTED)
printf(" SE_DACL_PROTECTED\n");
if (lCtrl & SE_SACL_PROTECTED)
printf(" SE_SACL_PROTECTED\n");
if (lCtrl & SE_SELF_RELATIVE)
printf(" SE_OWNER_DEFAULTED\n");
return iReturn;
}
//Function to print AccessMask flags.
int SDParseAccessMask(
long lCtrl
)
{
int iReturn = TRUE;
if (lCtrl & ADS_RIGHT_DELETE)
printf(" ADS_RIGHT_DELETE\n");
if (lCtrl & ADS_RIGHT_READ_CONTROL)
printf(" ADS_RIGHT_READ_CONTROL\n");
if (lCtrl & ADS_RIGHT_WRITE_DAC)
printf(" ADS_RIGHT_WRITE_DAC\n");
if (lCtrl & ADS_RIGHT_WRITE_OWNER)
printf(" ADS_RIGHT_WRITE_OWNER\n");
if (lCtrl & ADS_RIGHT_GENERIC_READ)
printf(" ADS_RIGHT_GENERIC_READ\n");
if (lCtrl & ADS_RIGHT_GENERIC_WRITE)
printf(" ADS_RIGHT_GENERIC_WRITE\n");
if (lCtrl & ADS_RIGHT_GENERIC_EXECUTE)
printf(" ADS_RIGHT_GENERIC_EXECUTE\n");
if (lCtrl & ADS_RIGHT_GENERIC_ALL)
printf(" ADS_RIGHT_GENERIC_ALL\n");
if (lCtrl & ADS_RIGHT_DS_CREATE_CHILD)
printf(" ADS_RIGHT_DS_CREATE_CHILD\n");
if (lCtrl & ADS_RIGHT_DS_DELETE_CHILD)
printf(" ADS_RIGHT_DS_DELETE_CHILD\n");
if (lCtrl & ADS_RIGHT_ACTRL_DS_LIST)
printf(" ADS_RIGHT_ACTRL_DS_LIST\n");
if (lCtrl & ADS_RIGHT_DS_SELF)
printf(" ADS_RIGHT_DS_SELF\n");
if (lCtrl & ADS_RIGHT_DS_READ_PROP)
printf(" ADS_RIGHT_DS_READ_PROP\n");
if (lCtrl & ADS_RIGHT_DS_WRITE_PROP)
printf(" ADS_RIGHT_DS_WRITE_PROP\n");
if (lCtrl & ADS_RIGHT_DS_DELETE_TREE)
printf(" ADS_RIGHT_DS_DELETE_TREE\n");
if (lCtrl & ADS_RIGHT_DS_LIST_OBJECT)
printf(" ADS_RIGHT_DS_LIST_OBJECT\n");
if (lCtrl & ADS_RIGHT_DS_CONTROL_ACCESS)
printf(" ADS_RIGHT_DS_CONTROL_ACCESS\n");
return iReturn;
}