windows-nt/Source/XPSP1/NT/admin/extens/acldiag/secdesc.cpp
2020-09-26 16:20:57 +08:00

2105 lines
72 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999.
//
// File: SecDesc.cpp
//
// Contents: DoSecurityDescription and support methods
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "ADUtils.h"
#include "SecDesc.h"
///////////////////////////////////////////////////////////////////////////////
//
// Method: DoSecurityDescription ()
//
// Purpose: Main routine for doing security description
//
//
HRESULT DoSecurityDescription ()
{
_TRACE (1, L"Entering DoSecurityDescription\n");
HRESULT hr = S_OK;
wstring str;
// Print header
if ( _Module.DoTabDelimitedOutput () )
{
MyWprintf (_Module.GetObjectDN ().c_str ());
MyWprintf (L"\n");
}
else
{
FormatMessage (str, IDS_SECURITY_DIAGNOSIS_FOR, _Module.GetObjectDN ().c_str ());
MyWprintf (str.c_str ());
if ( !_Module.SkipDescription () )
{
LoadFromResource (str, IDS_DESCRIPTION);
str += L"\n";
MyWprintf (str.c_str ());
}
}
hr = GetSecurityDescriptor (_Module.GetObjectDN (), &_Module.m_pSecurityDescriptor);
if ( SUCCEEDED (hr) )
{
if ( _Module.m_pSecurityDescriptor )
{
hr = DisplayOwner ();
if ( SUCCEEDED (hr) )
{
SECURITY_DESCRIPTOR_CONTROL control;
DWORD dwRevision = 0;
if ( GetSecurityDescriptorControl (
_Module.m_pSecurityDescriptor,
&control,
&dwRevision) )
{
if ( _Module.DoTabDelimitedOutput () )
{
MyWprintf (L"\n");
if ( control & SE_DACL_PROTECTED )
LoadFromResource (str, IDS_PERMISSIONS_PROTECTED);
else
LoadFromResource (str, IDS_PERMISSIONS_NOT_PROTECTED);
MyWprintf (str.c_str ());
if ( control & SE_SACL_PROTECTED )
LoadFromResource (str, IDS_AUDITING_PROTECTED);
else
LoadFromResource (str, IDS_AUDITING_NOT_PROTECTED);
MyWprintf (str.c_str ());
}
else
{
if ( control & SE_DACL_PROTECTED )
{
LoadFromResource (str, IDS_CONFIG_NO_INHERIT);
MyWprintf (str.c_str ());
}
}
}
else
{
_TRACE (0, L"GetSecurityDescriptorControl () failed: 0x%x\n", GetLastError ());
}
hr = EnumerateDacl (_Module.m_pSecurityDescriptor, _Module.m_DACLList, true);
if ( SUCCEEDED (hr) )
{
hr = EnumerateSacl (_Module.m_pSecurityDescriptor, _Module.m_SACLList);
if ( SUCCEEDED (hr) && !_Module.SkipDescription () )
{
hr = PrintEffectivePermissions ();
if ( SUCCEEDED (hr) )
{
hr = PrintInheritedPermissions ();
if ( SUCCEEDED (hr) )
{
hr = PrintAuditingInformation ();
}
}
}
}
}
}
else
{
hr = E_ACCESSDENIED;
wstring str;
FormatMessage (str, IDS_UNABLE_TO_READ_SECURITY_DESCRIPTOR, _Module.GetObjectDN ().c_str ());
MyWprintf (str.c_str ());
}
}
_TRACE (-1, L"Leaving DoSecurityDescription: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: GetSecurityDescriptor ()
//
// Purpose: Get ths security descriptor for the indicated object
//
// Inputs: strObjectDN - the object show security descriptor we wish to
// retrieve
//
// Outputs: ppAttrs - returns the security descriptor raw data - this holds the data
// persistent in memory
//
// ppSecurityDescriptor - returns the security descriptor
//
HRESULT GetSecurityDescriptor (
wstring strObjectDN, // pass by value
PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
{
_TRACE (1, L"Entering GetSecurityDescriptor\n");
HRESULT hr = S_OK;
if ( ppSecurityDescriptor )
{
CComPtr<IADsPathname> spPathname;
//
// Constructing the directory paths
//
hr = CoCreateInstance(
CLSID_Pathname,
NULL,
CLSCTX_ALL,
IID_PPV_ARG (IADsPathname, &spPathname));
if ( SUCCEEDED (hr) )
{
ASSERT (!!spPathname);
LPCWSTR pszLDAP = L"LDAP://";
// If object name is preceded with LDAP, set the whole name at once.
if ( !wcsncmp (strObjectDN.c_str (), pszLDAP, wcslen (pszLDAP)) )
{
hr = spPathname->Set (
const_cast <PWSTR> (strObjectDN.c_str ()),
ADS_SETTYPE_FULL);
if ( FAILED (hr) )
{
_TRACE (0, L"IADsPathname->Set (%s): 0x%x\n",
strObjectDN.c_str (), hr);
}
}
else
{
hr = spPathname->Set (const_cast <PWSTR> (ACLDIAG_LDAP),
ADS_SETTYPE_PROVIDER);
if ( SUCCEEDED (hr) )
{
hr = spPathname->Set (
const_cast <PWSTR> (strObjectDN.c_str ()),
ADS_SETTYPE_DN);
if ( FAILED (hr) )
{
_TRACE (0, L"IADsPathname->Set (%s): 0x%x\n",
strObjectDN.c_str (), hr);
}
}
else
{
_TRACE (0, L"IADsPathname->Set (%s): 0x%x\n", ACLDIAG_LDAP, hr);
}
}
if ( SUCCEEDED (hr) )
{
BSTR bstrFullPath = 0;
hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
if ( SUCCEEDED (hr) )
{
CComPtr<IDirectoryObject> spDirObj;
hr = ADsGetObject (
bstrFullPath,
IID_PPV_ARG (IDirectoryObject, &spDirObj));
if ( SUCCEEDED (hr) )
{
hr = SetSecurityInfoMask (spDirObj,
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION |
SACL_SECURITY_INFORMATION);
//
// Get this object's Security Descriptor.
//
const PWSTR wzSecDescriptor = L"nTSecurityDescriptor";
PADS_ATTR_INFO pAttrs = 0;
DWORD cAttrs = 0;
LPWSTR rgpwzAttrNames[] = {wzSecDescriptor};
hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
if ( SUCCEEDED (hr) )
{
if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
{
if (!(pAttrs->pADsValues->SecurityDescriptor.lpValue) ||
!(pAttrs->pADsValues->SecurityDescriptor.dwLength))
{
_TRACE (0, L"IADS return bogus SD!\n");
hr = E_UNEXPECTED;
}
else if (!IsValidSecurityDescriptor(pAttrs->pADsValues->SecurityDescriptor.lpValue))
{
_TRACE (0, L"IsValidSecurityDescriptor failed!\n");
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)
::LocalAlloc (LMEM_ZEROINIT, pAttrs->pADsValues->SecurityDescriptor.dwLength);
if ( *ppSecurityDescriptor )
{
memcpy (*ppSecurityDescriptor,
pAttrs->pADsValues->SecurityDescriptor.lpValue,
pAttrs->pADsValues->SecurityDescriptor.dwLength);
}
else
hr = E_OUTOFMEMORY;
}
FreeADsMem (pAttrs);
}
else
{
if ( !wcscmp (strObjectDN.c_str (), _Module.GetObjectDN ().c_str ()) )
{
wstring str;
FormatMessage (str, IDS_NO_SECDESC_RETURNED, strObjectDN.c_str ());
MyWprintf (str.c_str ());
}
}
}
else
{
if ( !wcscmp (strObjectDN.c_str (), _Module.GetObjectDN ().c_str ()) )
{
wstring str;
FormatMessage (str, IDS_NO_SECDESC_RETURNED_WITH_CODE,
strObjectDN.c_str (), GetSystemMessage (hr));
MyWprintf (str.c_str ());
}
_TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
}
}
else
{
if ( ERROR_DS_REFERRAL == HRESULT_CODE (hr) )
hr = S_FALSE;
else
{
_TRACE (0, L"ADsGetObject (%s): 0x%x\n", bstrFullPath, hr);
wstring strErr;
FormatMessage (strErr, IDS_INVALID_OBJECT,
_Module.GetObjectDN ().c_str (),
GetSystemMessage (hr).c_str ());
MyWprintf (strErr.c_str ());
}
}
}
else
{
_TRACE (0, L"IADsPathname->Retrieve (): 0x%x\n", hr);
}
}
}
else
{
_TRACE (0, L"CoCreateInstance(CLSID_Pathname): 0x%x\n", hr);
}
}
else
hr = E_POINTER;
_TRACE (-1, L"Leaving GetSecurityDescriptor: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: DisplayOwner ()
//
// Purpose: Display the owner of this object
//
HRESULT DisplayOwner ()
{
_TRACE (1, L"Entering DisplayOwner\n");
HRESULT hr = S_OK;
PSID pSidOwner = 0;
BOOL bOwnerDefaulted = FALSE;
if ( ::GetSecurityDescriptorOwner(
_Module.m_pSecurityDescriptor,
&pSidOwner,
&bOwnerDefaulted) )
{
wstring strPrincipalName;
wstring strFQDN;
SID_NAME_USE sne = SidTypeUnknown;
hr = GetNameFromSid (pSidOwner, strPrincipalName, &strFQDN, sne);
if ( SUCCEEDED (hr) && !_Module.SkipDescription () )
{
wstring str;
if ( _Module.DoTabDelimitedOutput () )
FormatMessage (str, IDS_OWNER_CDO, strPrincipalName.c_str ());
else
FormatMessage (str, IDS_OWNER, strPrincipalName.c_str ());
MyWprintf (str.c_str ());
}
PSID_FQDN* pItem = new PSID_FQDN (pSidOwner, strFQDN, strPrincipalName, sne);
if ( pItem )
_Module.m_PSIDList.push_back (pItem);
else
hr = E_OUTOFMEMORY;
}
else
{
DWORD dwErr = GetLastError ();
_TRACE (0, L"GetSecurityDescriptorOwner () failed: 0x%x\n",
dwErr);
hr = HRESULT_FROM_WIN32 (dwErr);
}
_TRACE (-1, L"Leaving DisplayOwner: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: EnumerateDacl ()
//
// Purpose: Enumerate the DACL and store it in a list
//
// Inputs: pSecurityDescriptor - where to get the DACL
//
// Outputs: DACLList - return the ACEs in this list
//
HRESULT EnumerateDacl (PSECURITY_DESCRIPTOR pSecurityDescriptor, ACE_SAMNAME_LIST& DACLList, bool bListSids)
{
_TRACE (1, L"Entering EnumerateDacl\n");
HRESULT hr = S_OK;
PACL pDacl = 0;
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
if ( GetSecurityDescriptorDacl (pSecurityDescriptor,
&bDaclPresent, &pDacl, &bDaclDefaulted) )
{
if ( bDaclPresent )
{
PACCESS_ALLOWED_ACE pAllowedAce;
PSID_FQDN_LIST::iterator itrPSID = _Module.m_PSIDList.begin ();
ACE_SAMNAME* pAceSAMName = 0;
PSID_FQDN* pPsidFQDN = 0;
SID_NAME_USE sne = SidTypeUnknown;
// copy the ACES
for (int i = 0; i < pDacl->AceCount; i++)
{
if ( GetAce (pDacl, i, (void **)&pAllowedAce) )
{
PSID AceSid = 0;
if ( IsObjectAceType ( pAllowedAce ) )
{
AceSid = RtlObjectAceSid( pAllowedAce );
}
else
{
AceSid = &( ( PKNOWN_ACE )pAllowedAce )->SidStart;
}
ASSERT (IsValidSid (AceSid));
wstring strPrincipalName;
wstring strFQDN;
hr = GetNameFromSid (AceSid, strPrincipalName,
bListSids ? &strFQDN : 0, sne);
if ( SUCCEEDED (hr) )
{
if ( bListSids )
{
bool bFound = false;
for (PSID_FQDN_LIST::iterator itrPSIDFind = _Module.m_PSIDList.begin ();
itrPSIDFind != _Module.m_PSIDList.end ();
itrPSIDFind++)
{
pPsidFQDN = *itrPSIDFind;
if ( pPsidFQDN )
{
if ( !wcscmp (pPsidFQDN->m_strFQDN.c_str (), strFQDN.c_str ()) )
{
bFound = true;
}
}
}
if ( !bFound )
{
pPsidFQDN = new PSID_FQDN (AceSid, strFQDN, strPrincipalName, sne);
if ( pPsidFQDN )
{
_Module.m_PSIDList.push_back (pPsidFQDN);
}
else
{
hr = E_OUTOFMEMORY;
break;
}
}
}
pAceSAMName = new ACE_SAMNAME;
if ( pAceSAMName )
{
pAceSAMName->m_AceType = pAllowedAce->Header.AceType;
switch (pAceSAMName->m_AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
pAceSAMName->m_pAllowedAce = pAllowedAce;
break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
pAceSAMName->m_pAllowedObjectAce =
reinterpret_cast <PACCESS_ALLOWED_OBJECT_ACE> (pAllowedAce);
break;
case ACCESS_DENIED_ACE_TYPE:
pAceSAMName->m_pDeniedAce =
reinterpret_cast <PACCESS_DENIED_ACE> (pAllowedAce);
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
pAceSAMName->m_pDeniedObjectAce =
reinterpret_cast <PACCESS_DENIED_OBJECT_ACE> (pAllowedAce);
break;
default:
break;
}
pAceSAMName->m_SAMAccountName = strPrincipalName;
pAceSAMName->DebugOut ();
DACLList.push_back (pAceSAMName);
}
else
{
hr = E_OUTOFMEMORY;
break;
}
}
}
else
{
_TRACE (0, L"GetAce failed: 0x%x\n", GetLastError ());
break;
}
}
}
}
else
{
_TRACE (0, L"GetSecurityDescriptorDacl () failed: 0x%x\n", GetLastError ());
}
_TRACE (-1, L"Leaving EnumerateDacl: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: EnumerateSacl ()
//
// Purpose: Enumerate the SACL and store it in a list
//
// Inputs: pSecurityDescriptor - where to get the DACL
//
// Outputs: The results are store in the _Module.m_SACLList
//
HRESULT EnumerateSacl (PSECURITY_DESCRIPTOR pSecurityDescriptor, ACE_SAMNAME_LIST& SACLList)
{
_TRACE (1, L"Entering EnumerateSacl\n");
HRESULT hr = S_OK;
PACL pSacl = 0;
BOOL bSaclPresent = FALSE;
BOOL bSaclDefaulted = FALSE;
if ( GetSecurityDescriptorSacl (pSecurityDescriptor,
&bSaclPresent, &pSacl, &bSaclDefaulted) )
{
if ( bSaclPresent && pSacl )
{
PACCESS_ALLOWED_ACE pAllowedAce;
wstring strPrincipalName;
wstring strFQDN;
ACE_SAMNAME* pAceSAMName = 0;
SID_NAME_USE sne = SidTypeUnknown;
// copy the ACES
for (int i = 0; i < pSacl->AceCount; i++)
{
if ( GetAce (pSacl, i, (void **)&pAllowedAce) )
{
PSID AceSid;
if ( IsObjectAceType ( pAllowedAce ) )
{
AceSid = RtlObjectAceSid( pAllowedAce );
}
else
{
AceSid = &( ( PKNOWN_ACE )pAllowedAce )->SidStart;
}
hr = GetNameFromSid (AceSid, strPrincipalName, 0, sne);
if ( SUCCEEDED (hr) )
{
pAceSAMName = new ACE_SAMNAME;
if ( pAceSAMName )
{
pAceSAMName->m_AceType = pAllowedAce->Header.AceType;
switch (pAceSAMName->m_AceType)
{
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
pAceSAMName->m_pSystemAuditObjectAce =
reinterpret_cast <PSYSTEM_AUDIT_OBJECT_ACE> (pAllowedAce);
break;
case SYSTEM_AUDIT_ACE_TYPE:
pAceSAMName->m_pSystemAuditAce =
reinterpret_cast <PSYSTEM_AUDIT_ACE> (pAllowedAce);
break;
default:
break;
}
pAceSAMName->m_SAMAccountName = strPrincipalName;
pAceSAMName->DebugOut ();
SACLList.push_back (pAceSAMName);
}
else
{
hr = E_OUTOFMEMORY;
break;
}
}
}
else
{
_TRACE (0, L"GetAce failed: 0x%x\n", GetLastError ());
break;
}
}
}
}
else
{
_TRACE (0, L"GetSecurityDescriptorSacl () failed: 0x%x\n", GetLastError ());
}
_TRACE (-1, L"Leaving EnumerateSacl: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintEffectivePermissions ()
//
// Purpose: Print the permissions effective on the object
//
HRESULT PrintEffectivePermissions ()
{
HRESULT hr = S_OK;
ACE_SAMNAME_LIST::iterator itr = _Module.m_DACLList.begin ();
wstring str;
ACE_SAMNAME* pAceSAMName = 0;
if ( !_Module.DoTabDelimitedOutput () )
{
LoadFromResource (str, IDS_PERMISSIONS_EFFECTIVE);
MyWprintf (str.c_str ());
}
for (itr = _Module.m_DACLList.begin(); itr != _Module.m_DACLList.end(); itr++)
{
pAceSAMName = *itr;
if ( !(pAceSAMName->m_pAllowedAce->Header.AceFlags & INHERIT_ONLY_ACE) )
{
switch (pAceSAMName->m_AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
hr = EnumeratePermissions (pAceSAMName, P_ALLOW, P_THIS_OBJECT, L"");
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
hr = EnumeratePermissions (pAceSAMName, P_DENY, P_THIS_OBJECT, L"");
break;
default:
break;
}
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: EnumeratePermissions ()
//
// Purpose: Print all the permissions contained on the passed in ACE
//
// Inputs: pAceSAMName - structure containing the ACE whose permissions we wish
// to print
//
// ptype - allow, deny, succes, failure, success and failure
//
HRESULT EnumeratePermissions (ACE_SAMNAME* pAceSAMName, P_TYPE ptype, P_WHO pWho, PCWSTR pwszClassName)
{
HRESULT hr = S_OK;
if ( pAceSAMName )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_CREATE_CHILD,
ptype,
IDS_CREATE_ALL_SUBOBJECTS,
IDS_CREATE_CLASS_OBJECTS,
pWho,
pwszClassName);
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_DELETE_CHILD,
ptype,
IDS_DELETE_ALL_SUBOBJECTS,
IDS_DELETE_CLASS_OBJECTS,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_READ_PROP,
ptype,
IDS_READ_ALL_PROPERTIES,
IDS_READ_PROPERTY_PROPERTY,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_WRITE_PROP,
ptype,
IDS_WRITE_ALL_PROPERTIES,
IDS_WRITE_PROPERTY_PROPERTY,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_LIST,
ptype,
IDS_LIST_CONTENTS, false,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_LIST_OBJECT,
ptype,
IDS_LIST_OBJECT, false,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_CONTROL_ACCESS,
ptype,
IDS_ALL_CONTROL_ACCESSES,
IDS_CONTROL_ACCESS_DISPLAY_NAME,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DELETE,
ptype,
IDS_DELETE_THIS_OBJECT, false,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_READ_CONTROL,
ptype,
IDS_READ_PERMISSIONS, false,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_CHANGE_ACCESS,
ptype,
IDS_MODIFY_PERMISSIONS, false,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_CHANGE_OWNER,
ptype,
IDS_TAKE_CHANGE_OWNERSHIP, false,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_SELF,
ptype,
IDS_MODIFY_MEMBERSHIP, false,
pWho,
pwszClassName);
}
}
else
hr = E_POINTER;
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintPermission ()
//
// Purpose: Print an OBJECT_ACE_TYPE permission
//
// Inputs: pAceSAMName - structure containing the ACE whose permission we wish
// to print
//
// accessMask - the specific permission we're looking to print
//
// bAllow - whether the permission is allowed or denied
//
// strIDAll - string to print if permission applies to all object
// classes
//
// strIDParam - string print if permission applies to a specific
// object class
//
HRESULT PrintPermission (ACE_SAMNAME* pAceSAMName,
ACCESS_MASK accessMask,
P_TYPE ptype,
int strIDAll,
int strIDParam,
P_WHO pWho,
PCWSTR pwszClassName)
{
HRESULT hr = S_OK;
if ( pAceSAMName )
{
wstring str;
wstring strPermission;
if ( pAceSAMName->m_pAllowedAce->Mask & accessMask )
{
bool bIsAudit = false;
switch (pAceSAMName->m_AceType )
{
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
if ( (pAceSAMName->m_pAllowedObjectAce->Flags & ACE_OBJECT_TYPE_PRESENT) &&
!::IsEqualGUID (pAceSAMName->m_pAllowedObjectAce->ObjectType, NULLGUID) )
{
wstring strClass;
if ( ACTRL_DS_CONTROL_ACCESS == accessMask )
{
hr = GetControlDisplayName (
pAceSAMName->m_pAllowedObjectAce->ObjectType, strClass);
}
else
{
_Module.GetClassFromGUID (
pAceSAMName->m_pAllowedObjectAce->ObjectType,
strClass);
}
FormatMessage (strPermission, strIDParam,
strClass.c_str ());
}
else
{
LoadFromResource (strPermission, strIDAll);
}
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
if ( (pAceSAMName->m_pDeniedObjectAce->Flags & ACE_OBJECT_TYPE_PRESENT) &&
!::IsEqualGUID (pAceSAMName->m_pDeniedObjectAce->ObjectType, NULLGUID) )
{
wstring strClass;
if ( ACTRL_DS_CONTROL_ACCESS == accessMask )
{
hr = GetControlDisplayName (
pAceSAMName->m_pDeniedObjectAce->ObjectType, strClass);
}
else
{
_Module.GetClassFromGUID (
pAceSAMName->m_pDeniedObjectAce->ObjectType,
strClass);
}
FormatMessage (strPermission,strIDParam,
strClass.c_str ());
}
else
{
LoadFromResource (strPermission, strIDAll);
}
break;
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
if ( (pAceSAMName->m_pSystemAuditObjectAce->Flags & ACE_OBJECT_TYPE_PRESENT) &&
!::IsEqualGUID (pAceSAMName->m_pSystemAuditObjectAce->ObjectType, NULLGUID) )
{
wstring strClass;
if ( ACTRL_DS_CONTROL_ACCESS == accessMask )
{
hr = GetControlDisplayName (
pAceSAMName->m_pSystemAuditObjectAce->ObjectType, strClass);
}
else
{
_Module.GetClassFromGUID (
pAceSAMName->m_pSystemAuditObjectAce->ObjectType,
strClass);
}
FormatMessage (strPermission,strIDParam,
strClass.c_str ());
}
else
{
LoadFromResource (strPermission, strIDAll);
}
bIsAudit = true;
break;
case SYSTEM_AUDIT_ACE_TYPE:
bIsAudit = true;
// fall through
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
default:
LoadFromResource (strPermission, strIDAll);
break;
}
int strid = 0;
switch (ptype)
{
case P_ALLOW:
if ( _Module.DoTabDelimitedOutput () )
strid = IDS_ALLOW_CDO;
else
strid = IDS_ALLOW;
break;
case P_DENY:
if ( _Module.DoTabDelimitedOutput () )
strid = IDS_DENY_CDO;
else
strid = IDS_DENY;
break;
case P_SUCCESS:
if ( _Module.DoTabDelimitedOutput () )
strid = IDS_SUCCESS_CDO;
else
strid = IDS_SUCCESS;
break;
case P_FAILURE:
if ( _Module.DoTabDelimitedOutput () )
strid = IDS_FAILURE_CDO;
else
strid = IDS_FAILURE;
break;
case P_SUCCESS_AND_FAILURE:
if ( _Module.DoTabDelimitedOutput () )
strid = IDS_SUCCESS_AND_FAILURE_CDO;
else
strid = IDS_SUCCESS_AND_FAILURE;
break;
default:
return E_UNEXPECTED;
}
if ( _Module.DoTabDelimitedOutput () )
{
wstring strObject;
switch ( pWho )
{
case P_THIS_OBJECT:
LoadFromResource (strObject, IDS_THIS_OBJECT);
break;
case P_ALL_OBJECTS:
LoadFromResource (strObject, IDS_ALL_SUBOBJECTS);
break;
case P_CLASS_OBJECT:
FormatMessage (strObject, IDS_CLASS_OBJECT, pwszClassName);
break;
}
FormatMessage (str, strid,
strObject.c_str (),
pAceSAMName->m_SAMAccountName.c_str (),
strPermission.c_str ());
}
else
{
FormatMessage (str, strid,
pAceSAMName->m_SAMAccountName.c_str (),
strPermission.c_str ());
}
MyWprintf (str.c_str ());
if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & INHERITED_ACE &&
(P_ALLOW == ptype || P_DENY == ptype) )
{
hr = PrintInheritedPermissionFromDN (pAceSAMName, accessMask, bIsAudit);
}
if ( _Module.DoTabDelimitedOutput () )
MyWprintf (L"\n");
}
}
else
hr = E_POINTER;
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintPermission ()
//
// Purpose: Print a non-OBJECT_ACE_TYPE permission
//
// Inputs: pAceSAMName - structure containing the ACE whose permission we wish
// to print
//
// accessMask - the specific permission we're looking to print
//
// bAllow - whether the permission is allowed or denied
//
// strID - string to print
//
HRESULT PrintPermission (ACE_SAMNAME* pAceSAMName,
ACCESS_MASK accessMask,
P_TYPE ptype,
int strID,
bool bIsAudit,
P_WHO pWho,
PCWSTR pwszClassName)
{
HRESULT hr = S_OK;
if ( pAceSAMName )
{
wstring str;
wstring strPermission;
if ( pAceSAMName->m_pAllowedAce->Mask & accessMask )
{
LoadFromResource (strPermission, strID);
int id = 0;
switch (ptype)
{
case P_ALLOW:
if ( _Module.DoTabDelimitedOutput () )
id = IDS_ALLOW_CDO;
else
id = IDS_ALLOW;
break;
case P_DENY:
if ( _Module.DoTabDelimitedOutput () )
id = IDS_DENY_CDO;
else
id = IDS_DENY;
break;
case P_SUCCESS:
if ( _Module.DoTabDelimitedOutput () )
id = IDS_SUCCESS_CDO;
else
id = IDS_SUCCESS;
break;
case P_FAILURE:
if ( _Module.DoTabDelimitedOutput () )
id = IDS_FAILURE_CDO;
else
id = IDS_FAILURE;
break;
case P_SUCCESS_AND_FAILURE:
if ( _Module.DoTabDelimitedOutput () )
id = IDS_SUCCESS_AND_FAILURE_CDO;
else
id = IDS_SUCCESS_AND_FAILURE;
break;
default:
return E_UNEXPECTED;
}
if ( _Module.DoTabDelimitedOutput () )
{
wstring strObject;
switch ( pWho )
{
case P_THIS_OBJECT:
LoadFromResource (strObject, IDS_THIS_OBJECT);
break;
case P_ALL_OBJECTS:
LoadFromResource (strObject, IDS_ALL_SUBOBJECTS);
break;
case P_CLASS_OBJECT:
FormatMessage (strObject, IDS_CLASS_OBJECT, pwszClassName);
break;
}
FormatMessage (str, id,
strObject.c_str (),
pAceSAMName->m_SAMAccountName.c_str (),
strPermission.c_str ());
}
else
{
FormatMessage (str, id,
pAceSAMName->m_SAMAccountName.c_str (),
strPermission.c_str ());
}
MyWprintf (str.c_str ());
if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & INHERITED_ACE )
{
hr = PrintInheritedPermissionFromDN (pAceSAMName, accessMask, bIsAudit);
}
if ( _Module.DoTabDelimitedOutput () )
MyWprintf (L"\n");
}
}
else
hr = E_POINTER;
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// GetParentObjectDNWithSameACE ()
//
// This function is called recursively to try to find an ACE that matches the ACE
// contained in pAceSAMName somewhere in the parent container of the object pointed to
// by pPathName. Each iteration strips a leaf element off pPathName, gets its
// security descriptor and searches the Dacl list for the ACE. If a match is
// found, taking into account the INHERITED_ACE flag, we look to see if the
// INHERITED_ACE flag is set. If so, we call GetParentObjectDNWithSameACE () again.
// If not, we get the return the object name at this level.
//
HRESULT GetParentObjectDNWithSameACE (
IN ACE_SAMNAME* pAceSAMName,
IN IADsPathname* pPathName,
IN ACCESS_MASK accessMask,
OUT wstring& strParentDN,
bool bIsAudit)
{
_TRACE (1, L"Entering GetParentObjectDNWithSameACE\n");
HRESULT hr = pPathName->RemoveLeafElement ();
if ( SUCCEEDED (hr) )
{
BSTR bstrFullPath = 0;
hr = pPathName->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
if ( SUCCEEDED (hr) )
{
if ( !wcscmp (bstrFullPath, L"LDAP://") )
return S_FALSE;
PSECURITY_DESCRIPTOR pSecurityDescriptor = 0;
bool bFound = false;
// Check to see if we already have this object's Security Descriptor
list<SAMNAME_SD*>::iterator sdItr = _Module.m_listOfParentSDs.begin ();
SAMNAME_SD* pCurrSAMNameSD = 0;
for (; sdItr != _Module.m_listOfParentSDs.end (); sdItr++)
{
pCurrSAMNameSD = *sdItr;
if ( !pCurrSAMNameSD->m_upn.compare (bstrFullPath) )
{
pSecurityDescriptor = pCurrSAMNameSD->m_pSecurityDescriptor;
bFound = true; // Note - pSecurityDescriptor could be NULL
// this is expected.
break;
}
}
// If we don't already have the SD for this object, get it and cache it.
if ( !bFound )
{
wstring objectDN (bstrFullPath);
hr = GetSecurityDescriptor (objectDN, &pSecurityDescriptor);
if ( SUCCEEDED (hr) )
{
pCurrSAMNameSD = new SAMNAME_SD (bstrFullPath, pSecurityDescriptor);
if ( pCurrSAMNameSD )
{
if ( pSecurityDescriptor )
{
hr = EnumerateDacl (pSecurityDescriptor, pCurrSAMNameSD->m_DACLList, false);
if ( SUCCEEDED (hr) )
hr = EnumerateSacl (pSecurityDescriptor, pCurrSAMNameSD->m_SACLList);
}
_Module.m_listOfParentSDs.push_back (pCurrSAMNameSD);
}
else
hr = E_OUTOFMEMORY;
}
}
if ( SUCCEEDED (hr) && pCurrSAMNameSD )
{
ACE_SAMNAME_LIST* pList = 0;
if ( bIsAudit )
pList = &pCurrSAMNameSD->m_SACLList;
else
pList = &pCurrSAMNameSD->m_DACLList;
ACE_SAMNAME_LIST::iterator itr = pList->begin ();
ACE_SAMNAME* pCurrSAMName = 0;
for (; itr != pList->end(); itr++)
{
pCurrSAMName = *itr;
if ( pCurrSAMName->IsEquivalent (*pAceSAMName,
accessMask) )
{
if ( pCurrSAMName->m_pAllowedAce->Header.AceFlags & INHERITED_ACE )
{
hr = GetParentObjectDNWithSameACE (
pAceSAMName,
pPathName,
accessMask,
strParentDN,
bIsAudit);
}
else
{
BSTR bstrDN = 0;
hr = pPathName->Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
if ( SUCCEEDED (hr) )
{
strParentDN = bstrDN;
}
else
{
_TRACE (0, L"IADsPathname->Retrieve (): 0x%x\n", hr);
}
}
break;
}
}
}
SysFreeString (bstrFullPath);
}
else
{
_TRACE (0, L"IADsPathname->Retrieve (): 0x%x\n", hr);
}
}
if ( SUCCEEDED (hr) && S_FALSE != hr && !strParentDN.length () )
{
hr = GetParentObjectDNWithSameACE (pAceSAMName, pPathName, accessMask,
strParentDN, bIsAudit);
}
_TRACE (-1, L"Leaving GetParentObjectDNWithSameACE: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintInheritedPermissionFromDN ()
//
// Purpose: Print a message indicating that a permission is inherited from
// another object plus that object's DN
//
// Inputs: pAceSAMName - structure containing the ACE whose permission we wish
// to print
//
// accessMask - the specific permission we're looking to print
//
HRESULT PrintInheritedPermissionFromDN (ACE_SAMNAME* pAceSAMName, ACCESS_MASK accessMask, bool bIsAudit)
{
_TRACE (1, L"Entering PrintInheritedPermissionFromDN\n");
HRESULT hr = S_OK;
if ( pAceSAMName )
{
CComPtr<IADsPathname> spPathname;
//
// Constructing the directory paths
//
hr = CoCreateInstance(
CLSID_Pathname,
NULL,
CLSCTX_ALL,
IID_IADsPathname,
(void**)&spPathname);
if ( SUCCEEDED (hr) )
{
ASSERT (!!spPathname);
hr = spPathname->Set((PWSTR)ACLDIAG_LDAP,
ADS_SETTYPE_PROVIDER);
if ( SUCCEEDED (hr) )
{
hr = spPathname->Set (
const_cast <BSTR> (_Module.GetObjectDN ().c_str ()),
ADS_SETTYPE_DN);
if ( SUCCEEDED (hr) )
{
wstring str;
wstring strParentDN;
hr = GetParentObjectDNWithSameACE (pAceSAMName,
spPathname, accessMask, strParentDN, bIsAudit);
if ( SUCCEEDED (hr) )
{
if ( !strParentDN.length () )
{
if ( _Module.DoTabDelimitedOutput () )
{
LoadFromResource (str,
IDS_GENERATED_INHERITED_PERMISSION_CDO);
}
else
{
LoadFromResource (str,
IDS_GENERATED_INHERITED_PERMISSION);
}
}
else
{
if ( _Module.DoTabDelimitedOutput () )
{
FormatMessage (str, IDS_INHERITED_PERMISSION_CDO,
strParentDN.c_str ());
}
else
{
FormatMessage (str, IDS_INHERITED_PERMISSION,
strParentDN.c_str ());
}
}
MyWprintf (str.c_str ());
}
}
}
}
}
else
hr = E_POINTER;
_TRACE (-1, L"Leaving PrintInheritedPermissionFromDN: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintInheritedPermissions ()
//
// Purpose: Print permissions that are inherited by subobjects
//
HRESULT PrintInheritedPermissions ()
{
_TRACE (1, L"Entering PrintInheritedPermissions\n");
HRESULT hr = S_OK;
ACE_SAMNAME_LIST::iterator aceItr = _Module.m_DACLList.begin ();
wstring str;
ACE_SAMNAME* pAceSAMName = 0;
list<GUID*> guidList;
if ( !_Module.DoTabDelimitedOutput () )
{
LoadFromResource (str, IDS_PERMISSIONS_INHERITED_BY_SUBOBJECTS);
MyWprintf (str.c_str ());
LoadFromResource (str, IDS_INHERIT_TO_ALL_SUBOBJECTS);
MyWprintf (str.c_str ());
}
// Second iteration: Each ACE which has CONTAINER_INHERIT is inherited to
// sub-objects.
// Several "subiterations" are done to categorize inherit ACEs to the
// subobject type they apply.
// First subiteration is for ACEs which are not object type or have
// InheritedObjectType = NULL. These apply to "All Subobjects". We'll gather
// the GUIDs of the InheritedObjectType's which are not NULL at this point to
// use in the subsequent iterations.
// Subsequent subiterations are for each unique InheritedObjectType
// present in the DACL.
for (aceItr = _Module.m_DACLList.begin(); aceItr != _Module.m_DACLList.end(); aceItr++)
{
pAceSAMName = *aceItr;
if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & CONTAINER_INHERIT_ACE )
{
switch (pAceSAMName->m_AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
hr = EnumeratePermissions (pAceSAMName, P_ALLOW, P_ALL_OBJECTS, L"");
break;
case ACCESS_DENIED_ACE_TYPE:
hr = EnumeratePermissions (pAceSAMName, P_DENY, P_ALL_OBJECTS, L"");
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
if ( !(pAceSAMName->m_pDeniedObjectAce->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
::IsEqualGUID (pAceSAMName->m_pDeniedObjectAce->ObjectType, NULLGUID) )
{
hr = EnumeratePermissions (pAceSAMName, P_DENY, P_ALL_OBJECTS, L"");
}
else
{
AddToInheritedObjectTypeGUIDList (guidList,
&(pAceSAMName->m_pDeniedObjectAce->ObjectType));
}
break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
if ( !(pAceSAMName->m_pAllowedObjectAce->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
::IsEqualGUID (pAceSAMName->m_pAllowedObjectAce->ObjectType, NULLGUID) )
{
hr = EnumeratePermissions (pAceSAMName, P_ALLOW, P_ALL_OBJECTS, L"");
}
else
{
AddToInheritedObjectTypeGUIDList (guidList,
&(pAceSAMName->m_pAllowedObjectAce->ObjectType));
}
break;
default:
break;
}
}
}
GUID* pGuid = 0;
wstring strClassName;
GUID_TYPE guidType;
for (list<GUID*>::iterator guidItr = guidList.begin ();
guidItr != guidList.end ();
guidItr++)
{
pGuid = *guidItr;
hr = _Module.GetClassFromGUID (*pGuid, strClassName, &guidType);
if ( SUCCEEDED (hr) && GUID_TYPE_CLASS == guidType )
{
if ( !_Module.DoTabDelimitedOutput () )
{
FormatMessage (str, IDS_INHERIT_TO_X_OBJECTS_ONLY, strClassName.c_str ());
MyWprintf (str.c_str ());
}
for (aceItr = _Module.m_DACLList.begin(); aceItr != _Module.m_DACLList.end(); aceItr++)
{
pAceSAMName = *aceItr;
if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & CONTAINER_INHERIT_ACE )
{
switch (pAceSAMName->m_AceType)
{
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
if ( ::IsEqualGUID (pAceSAMName->m_pAllowedObjectAce->ObjectType,
*pGuid) )
{
hr = EnumeratePermissions (pAceSAMName, P_ALLOW,
P_CLASS_OBJECT, strClassName.c_str ());
}
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
if ( ::IsEqualGUID (pAceSAMName->m_pDeniedObjectAce->ObjectType,
*pGuid) )
{
hr = EnumeratePermissions (pAceSAMName, P_DENY,
P_CLASS_OBJECT, strClassName.c_str ());
}
break;
default:
break;
}
}
}
}
}
_TRACE (1, L"Entering PrintInheritedPermissions: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: AddToInheritedObjectTypeGUIDList ()
//
// Purpose: Add a GUID to a list. Ensure that it is unique.
//
// Inputs: guidList - list to which the GUID should be added
//
// pGuid - GUID to add to the list
//
void AddToInheritedObjectTypeGUIDList (list<GUID*>& guidList, GUID* pGuid)
{
// The guidList should only contain unique GUIDs. Verify that the one we
// wish to add is not already in the list.
if ( pGuid )
{
bool bFound = false;
GUID* pCurrGuid = 0;
list<GUID*>::iterator guidItr = guidList.begin();
for (; guidItr != guidList.end(); guidItr++)
{
pCurrGuid = *guidItr;
if ( ::IsEqualGUID (*pCurrGuid, *pGuid) )
{
bFound = true;
break;
}
}
if ( !bFound )
{
guidList.push_back (pGuid);
}
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintAuditingInformation ()
//
// Purpose: Print auditing information from the SACL
//
HRESULT PrintAuditingInformation ()
{
_TRACE (1, L"Entering PrintAuditingInformation\n");
HRESULT hr = S_OK;
wstring str;
MyWprintf (L"\n\n");
SECURITY_DESCRIPTOR_CONTROL control;
DWORD dwRevision = 0;
if ( GetSecurityDescriptorControl (
_Module.m_pSecurityDescriptor,
&control,
&dwRevision) )
{
if ( !_Module.DoTabDelimitedOutput () && (control & SE_SACL_PROTECTED) )
{
wstring str;
LoadFromResource (str, IDS_CONFIG_NO_INHERIT);
MyWprintf (str.c_str ());
}
}
else
{
_TRACE (0, L"GetSecurityDescriptorControl () failed: 0x%x\n", GetLastError ());
}
hr = PrintEffectiveAuditing ();
if ( SUCCEEDED (hr) )
hr = PrintInheritedAuditing ();
_TRACE (-1, L"Leaving PrintAuditingInformation: 0x%x\n", hr);
return hr;
}
HRESULT PrintEffectiveAuditing ()
{
_TRACE (1, L"Entering PrintEffectiveAuditing\n");
HRESULT hr = S_OK;
ACE_SAMNAME_LIST::iterator itr = _Module.m_SACLList.begin ();
wstring str;
ACE_SAMNAME* pAceSAMName = 0;
if ( !_Module.DoTabDelimitedOutput () )
{
LoadFromResource (str, IDS_AUDITING_EFFECTIVE_ON_THIS_OBJECT);
MyWprintf (str.c_str ());
}
for (itr = _Module.m_SACLList.begin(); itr != _Module.m_SACLList.end(); itr++)
{
pAceSAMName = *itr;
if ( !(pAceSAMName->m_pAllowedAce->Header.AceFlags & INHERIT_ONLY_ACE) )
{
switch (pAceSAMName->m_AceType)
{
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
case SYSTEM_AUDIT_ACE_TYPE:
hr = EnumerateAudits (pAceSAMName, P_THIS_OBJECT, L"");
break;
default:
break;
}
}
}
_TRACE (-1, L"Leaving PrintEffectiveAuditing: 0x%x\n", hr);
return hr;
}
HRESULT EnumerateAudits (ACE_SAMNAME* pAceSAMName, P_WHO pWho, PCWSTR pwszClassName)
{
_TRACE (1, L"Entering EnumerateAudits\n");
HRESULT hr = S_OK;
P_TYPE ptype = P_UNASSIGNED;
BYTE byBoth = SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
if ( (pAceSAMName->m_pAllowedAce->Header.AceFlags & byBoth) == byBoth )
{
ptype = P_SUCCESS_AND_FAILURE;
}
else if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG )
ptype = P_SUCCESS;
else if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & FAILED_ACCESS_ACE_FLAG )
ptype = P_FAILURE;
else
return E_UNEXPECTED;
if ( pAceSAMName )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_CREATE_CHILD,
ptype,
IDS_CREATE_ALL_SUBOBJECTS,
IDS_CREATE_CLASS_OBJECTS,
pWho,
pwszClassName);
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_DELETE_CHILD,
ptype,
IDS_DELETE_ALL_SUBOBJECTS,
IDS_DELETE_CLASS_OBJECTS,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_READ_PROP,
ptype,
IDS_READ_ALL_PROPERTIES,
IDS_READ_PROPERTY_PROPERTY,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_WRITE_PROP,
ptype,
IDS_WRITE_ALL_PROPERTIES,
IDS_WRITE_PROPERTY_PROPERTY,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_LIST,
ptype,
IDS_LIST_CONTENTS, true,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_LIST_OBJECT,
ptype,
IDS_LIST_OBJECT, true,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
if ( pAceSAMName->m_pAllowedAce->Mask & ACTRL_DS_CONTROL_ACCESS )
hr = PrintPermission (pAceSAMName,
ACTRL_DS_CONTROL_ACCESS,
ptype,
IDS_ALL_CONTROL_ACCESSES,
IDS_CONTROL_ACCESS_DISPLAY_NAME,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DELETE,
ptype,
IDS_DELETE_THIS_OBJECT, true,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_READ_CONTROL,
ptype,
IDS_READ_PERMISSIONS, true,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_CHANGE_ACCESS,
ptype,
IDS_MODIFY_PERMISSIONS, true,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_CHANGE_OWNER,
ptype,
IDS_TAKE_CHANGE_OWNERSHIP, true,
pWho,
pwszClassName);
}
if ( SUCCEEDED (hr) )
{
hr = PrintPermission (pAceSAMName,
ACTRL_DS_SELF,
ptype,
IDS_MODIFY_MEMBERSHIP, true,
pWho,
pwszClassName);
}
}
else
hr = E_POINTER;
_TRACE (-1, L"Leaving EnumerateAudits: 0x%x\n", hr);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Method: PrintInheritedAuditing ()
//
// Purpose: Print audits that are inherited to subobjects
//
HRESULT PrintInheritedAuditing ()
{
_TRACE (1, L"Entering PrintInheritedAuditing\n");
HRESULT hr = S_OK;
ACE_SAMNAME_LIST::iterator aceItr = _Module.m_SACLList.begin ();
wstring str;
ACE_SAMNAME* pAceSAMName = 0;
list<GUID*> guidList;
if ( !_Module.DoTabDelimitedOutput () )
{
LoadFromResource (str, IDS_AUDITING_INHERITED_TO_SUBOBJECTS);
MyWprintf (str.c_str ());
LoadFromResource (str, IDS_INHERIT_TO_ALL_SUBOBJECTS);
MyWprintf (str.c_str ());
}
// Second iteration: Each ACE which has CONTAINER_INHERIT is inherited to
// sub-objects.
// Several "subiterations" are done to categorize inherit ACEs to the
// subobject type they apply.
// First subiteration is for ACEs which are not object type or have
// InheritedObjectType = NULL. These apply to "All Subobjects". We'll gather
// the GUIDs of the InheritedObjectType's which are not NULL at this point to
// use in the subsequent iterations.
// Subsequent subiterations are for each unique InheritedObjectType
// present in the DACL.
for (aceItr = _Module.m_SACLList.begin(); aceItr != _Module.m_SACLList.end(); aceItr++)
{
pAceSAMName = *aceItr;
if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & CONTAINER_INHERIT_ACE )
{
switch (pAceSAMName->m_AceType)
{
case SYSTEM_AUDIT_ACE_TYPE:
hr = EnumerateAudits (pAceSAMName, P_ALL_OBJECTS, L"");
break;
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
if ( !(pAceSAMName->m_pSystemAuditObjectAce->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
::IsEqualGUID (pAceSAMName->m_pSystemAuditObjectAce->ObjectType, NULLGUID) )
{
hr = EnumerateAudits (pAceSAMName, P_ALL_OBJECTS, L"");
}
else
{
AddToInheritedObjectTypeGUIDList (guidList,
&(pAceSAMName->m_pSystemAuditObjectAce->ObjectType));
}
break;
default:
break;
}
}
}
GUID* pGuid = 0;
wstring strClassName;
for (list<GUID*>::iterator guidItr = guidList.begin ();
guidItr != guidList.end ();
guidItr++)
{
pGuid = *guidItr;
hr = _Module.GetClassFromGUID (*pGuid, strClassName);
if ( SUCCEEDED (hr) )
{
if ( !_Module.DoTabDelimitedOutput () )
{
FormatMessage (str, IDS_INHERIT_TO_X_OBJECTS_ONLY, strClassName.c_str ());
MyWprintf (str.c_str ());
}
for (aceItr = _Module.m_SACLList.begin(); aceItr != _Module.m_SACLList.end(); aceItr++)
{
pAceSAMName = *aceItr;
if ( pAceSAMName->m_pAllowedAce->Header.AceFlags & CONTAINER_INHERIT_ACE )
{
switch (pAceSAMName->m_AceType)
{
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
if ( ::IsEqualGUID (pAceSAMName->m_pSystemAuditObjectAce->ObjectType,
*pGuid) )
{
hr = EnumerateAudits (pAceSAMName, P_CLASS_OBJECT, strClassName.c_str ());
}
break;
case SYSTEM_AUDIT_ACE_TYPE:
default:
break;
}
}
}
}
}
_TRACE (-1, L"Leaving PrintInheritedAuditing: 0x%x\n", hr);
return hr;
}
HRESULT GetControlDisplayName (REFGUID guid, wstring& strDisplayName)
{
HRESULT hr = S_OK;
wstring strGUID;
hr = wstringFromGUID (strGUID, guid);
if ( SUCCEEDED (hr) )
{
// strip braces from GUID
wstring strRightsGUID (strGUID.substr (1, strGUID.length () - 2));
hr = GetControlDisplayName (strRightsGUID, strDisplayName);
}
else
hr = E_INVALIDARG;
return hr;
}
// TODO: Optimize this by searching for all controls and putting them in an
// array like the classes and attributes
HRESULT GetControlDisplayName (const wstring strGuid, wstring& strDisplayName)
{
HRESULT hr = S_OK;
CComPtr<IADsPathname> spPathname;
//
// Constructing the directory paths
//
hr = CoCreateInstance(
CLSID_Pathname,
NULL,
CLSCTX_ALL,
IID_PPV_ARG (IADsPathname, &spPathname));
if ( SUCCEEDED (hr) )
{
ASSERT (!!spPathname);
hr = spPathname->Set(const_cast <PWSTR> (ACLDIAG_LDAP),
ADS_SETTYPE_PROVIDER);
if ( SUCCEEDED (hr) )
{
//
// Open the root DSE object
//
hr = spPathname->AddLeafElement(const_cast <PWSTR> (ACLDIAG_ROOTDSE));
if ( SUCCEEDED (hr) )
{
BSTR bstrFullPath = 0;
hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
if ( SUCCEEDED (hr) )
{
CComPtr<IADs> spRootDSEObject;
VARIANT varNamingContext;
hr = ADsGetObject (
bstrFullPath,
IID_PPV_ARG (IADs, &spRootDSEObject));
if ( SUCCEEDED (hr) )
{
ASSERT (!!spRootDSEObject);
//
// Get the configuration naming context from the root DSE
//
hr = spRootDSEObject->Get(const_cast <PWSTR> (ACLDIAG_CONFIG_NAMING_CONTEXT),
&varNamingContext);
if ( SUCCEEDED (hr) )
{
hr = spPathname->Set(V_BSTR(&varNamingContext),
ADS_SETTYPE_DN);
if ( SUCCEEDED (hr) )
{
hr = spPathname->AddLeafElement (L"CN=Extended-Rights");
if ( SUCCEEDED (hr) )
{
BSTR bstrFullPath = 0;
hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
if ( SUCCEEDED (hr) )
{
CComPtr<IDirectoryObject> spExtRightsContObj;
hr = ADsGetObject (
bstrFullPath,
IID_PPV_ARG (IDirectoryObject, &spExtRightsContObj));
if ( SUCCEEDED (hr) )
{
CComPtr<IDirectorySearch> spDsSearch;
hr = spExtRightsContObj->QueryInterface (IID_PPV_ARG(IDirectorySearch, &spDsSearch));
if ( SUCCEEDED (hr) )
{
ASSERT (!!spDsSearch);
ADS_SEARCHPREF_INFO pSearchPref[2];
DWORD dwNumPref = 2;
pSearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
pSearchPref[0].vValue.dwType = ADSTYPE_INTEGER;
pSearchPref[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
pSearchPref[1].dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
pSearchPref[1].vValue.dwType = ADSTYPE_INTEGER;
pSearchPref[1].vValue.Integer = ADS_CHASE_REFERRALS_NEVER;
hr = spDsSearch->SetSearchPreference(
pSearchPref,
dwNumPref
);
if ( SUCCEEDED (hr) )
{
PWSTR rgszAttrList[] = {L"displayName"};
ADS_SEARCH_HANDLE hSearchHandle = 0;
DWORD dwNumAttributes = 1;
wstring strQuery;
ADS_SEARCH_COLUMN Column;
Column.pszAttrName = 0;
FormatMessage (strQuery,
L"rightsGUID=%1",
strGuid.c_str ());
hr = spDsSearch->ExecuteSearch(
const_cast <LPWSTR>(strQuery.c_str ()),
rgszAttrList,
dwNumAttributes,
&hSearchHandle
);
if ( SUCCEEDED (hr) )
{
hr = spDsSearch->GetFirstRow (hSearchHandle);
if ( SUCCEEDED (hr) )
{
while (hr != S_ADS_NOMORE_ROWS )
{
//
// Getting current row's information
//
hr = spDsSearch->GetColumn(
hSearchHandle,
rgszAttrList[0],
&Column
);
if ( SUCCEEDED (hr) )
{
strDisplayName = Column.pADsValues->CaseIgnoreString;
spDsSearch->FreeColumn (&Column);
Column.pszAttrName = NULL;
break;
}
else if ( hr != E_ADS_COLUMN_NOT_SET )
{
break;
}
else
{
_TRACE (0, L"IDirectorySearch::GetColumn (): 0x%x\n", hr);
}
}
}
else
{
_TRACE (0, L"IDirectorySearch::GetFirstRow (): 0x%x\n", hr);
}
if (Column.pszAttrName)
{
spDsSearch->FreeColumn(&Column);
}
spDsSearch->CloseSearchHandle(hSearchHandle);
}
else
{
_TRACE (0, L"IDirectorySearch::ExecuteSearch (): 0x%x\n", hr);
hr = S_OK;
}
}
else
{
_TRACE (0, L"IDirectorySearch::SetSearchPreference (): 0x%x\n", hr);
}
}
else
{
_TRACE (0, L"IDirectoryObject::QueryInterface (IDirectorySearch): 0x%x\n", hr);
}
}
else
{
_TRACE (0, L"ADsGetObject (%s): 0x%x\n", bstrFullPath, hr);
}
}
else
{
_TRACE (0, L"IADsPathname->Retrieve (): 0x%x\n", hr);
}
}
else
{
_TRACE (0, L"IADsPathname->AddLeafElement (%s): 0x%x\n",
L"CN=Extended-Rights", hr);
}
}
else
{
_TRACE (0, L"IADsPathname->Set (): 0x%x\n", V_BSTR(&varNamingContext), hr);
}
}
else
{
_TRACE (0, L"IADs->Get (%s): 0x%x\n", ACLDIAG_CONFIG_NAMING_CONTEXT, hr);
}
}
else
{
_TRACE (0, L"ADsGetObject (%s): 0x%x\n", bstrFullPath, hr);
}
}
else
{
_TRACE (0, L"IADsPathname->Retrieve (): 0x%x\n", hr);
}
}
else
{
_TRACE (0, L"IADsPathname->AddLeafElement (%s): 0x%x\n", ACLDIAG_ROOTDSE, hr);
}
}
else
{
_TRACE (0, L"IADsPathname->Set (%s): 0x%x\n", ACLDIAG_LDAP, hr);
}
}
else
{
_TRACE (0, L"CoCreateInstance(CLSID_Pathname): 0x%x\n", hr);
}
return hr;
}