Platform SDK: Active Directory, ADSI, and Directory Services

Example Code for Reading defaultSecurityDescriptor

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;
 
}