//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1999-2002. // // 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 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 (CComBSTR (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 (CComBSTR (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER); if ( SUCCEEDED (hr) ) { hr = spPathname->Set (CComBSTR (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 spDirObj; hr = ADsOpenObjectHelper (bstrFullPath, IID_IDirectoryObject, 0, (void**)&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 ( 0 == cAttrs ) { // remove SACL_SECURITY_INFORMATION hr = SetSecurityInfoMask (spDirObj, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION); hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs); } if ( SUCCEEDED (hr) && 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).c_str ()); 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"ADsOpenObjectHelper (%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; ASSERT (pSecurityDescriptor); if ( !pSecurityDescriptor ) return E_POINTER; PACL pDacl = 0; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; _TRACE (0, L"Calling GetSecurityDescriptorDacl ()\n"); if ( GetSecurityDescriptorDacl (pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) ) { _TRACE (0, L"Call to GetSecurityDescriptorDacl () succeeded.\n"); 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 (pAllowedAce); break; case ACCESS_DENIED_ACE_TYPE: pAceSAMName->m_pDeniedAce = reinterpret_cast (pAllowedAce); break; case ACCESS_DENIED_OBJECT_ACE_TYPE: pAceSAMName->m_pDeniedObjectAce = reinterpret_cast (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 { DWORD dwErr = GetLastError (); _TRACE (0, L"Call to GetSecurityDescriptorDacl () failed: 0x%x\n", dwErr); hr = HRESULT_FROM_WIN32 (dwErr); } _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; ASSERT (pSecurityDescriptor); if ( !pSecurityDescriptor ) return E_POINTER; PACL pSacl = 0; BOOL bSaclPresent = FALSE; BOOL bSaclDefaulted = FALSE; _TRACE (0, L"Calling GetSecurityDescriptorSacl ()\n"); if ( GetSecurityDescriptorSacl (pSecurityDescriptor, &bSaclPresent, &pSacl, &bSaclDefaulted) ) { _TRACE (0, L"Call to GetSecurityDescriptorSacl () succeeded.\n"); 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 (pAllowedAce); break; case SYSTEM_AUDIT_ACE_TYPE: pAceSAMName->m_pSystemAuditAce = reinterpret_cast (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 { DWORD dwErr = GetLastError (); _TRACE (0, L"GetSecurityDescriptorSacl () failed: 0x%x\n", dwErr); hr = HRESULT_FROM_WIN32 (dwErr); } _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::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 spPathname; // // Constructing the directory paths // hr = CoCreateInstance( CLSID_Pathname, NULL, CLSCTX_ALL, IID_IADsPathname, (void**)&spPathname); if ( SUCCEEDED (hr) ) { ASSERT (!!spPathname); hr = spPathname->Set (CComBSTR (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER); if ( SUCCEEDED (hr) ) { hr = spPathname->Set (CComBSTR (_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 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::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& 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::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 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::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 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(CComBSTR (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER); if ( SUCCEEDED (hr) ) { // // Open the root DSE object // hr = spPathname->AddLeafElement(CComBSTR (ACLDIAG_ROOTDSE)); if ( SUCCEEDED (hr) ) { BSTR bstrFullPath = 0; hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath); if ( SUCCEEDED (hr) ) { CComPtr spRootDSEObject; VARIANT varNamingContext; hr = ADsOpenObjectHelper(bstrFullPath,IID_IADs, 0,(void**)&spRootDSEObject); if ( SUCCEEDED (hr) ) { ASSERT (!!spRootDSEObject); // // Get the configuration naming context from the root DSE // hr = spRootDSEObject->Get(CComBSTR (ACLDIAG_CONFIG_NAMING_CONTEXT), &varNamingContext); if ( SUCCEEDED (hr) ) { if ( V_VT (&varNamingContext) == VT_BSTR ) { hr = spPathname->Set(V_BSTR(&varNamingContext), ADS_SETTYPE_DN); if ( SUCCEEDED (hr) ) { hr = spPathname->AddLeafElement (CComBSTR (L"CN=Extended-Rights")); if ( SUCCEEDED (hr) ) { BSTR bstrFullPath1 = 0; hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath1); if ( SUCCEEDED (hr) ) { CComPtr spExtRightsContObj; hr = ADsOpenObjectHelper (bstrFullPath1, IID_IDirectoryObject, 0, (void**)&spExtRightsContObj); if ( SUCCEEDED (hr) ) { CComPtr 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 (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"ADsOpenObjectHelper (%s): 0x%x\n", bstrFullPath1, 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 hr = E_FAIL; } else { _TRACE (0, L"IADs->Get (%s): 0x%x\n", ACLDIAG_CONFIG_NAMING_CONTEXT, hr); } } else { _TRACE (0, L"ADsOpenObjectHelper (%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; }