//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1999-2002. // // File: EffRight.cpp // // Contents: Effective Rights Diagnosis and support methods // // //---------------------------------------------------------------------------- #include "stdafx.h" #include "adutils.h" #include "EffRight.h" #include "AccessCk.h" #include "SecDesc.h" // Classes #pragma warning (disable : 4127) class CResultObject { public: CResultObject ( ACCESS_MASK accessBit, const wstring& strResult, GUID_TYPE guidType, USHORT level); ~CResultObject () {} bool operator== (CResultObject& rResultObject) { if ( m_accessBit == rResultObject.m_accessBit ) return true; else return false; } bool operator< (CResultObject& rResultObject) { if ( 0 == m_level ) return true; if ( m_accessBit < rResultObject.m_accessBit ) { return true; } else return false; } const CResultObject& operator= (const CResultObject& obj) { UNREFERENCED_PARAMETER (obj); ASSERT (0); } void PrintResult () { MyWprintf (m_strResult.c_str ()); } ACCESS_MASK GetRight () const { return m_accessBit; } bool IsValid () const { return m_bIsValid; } USHORT GetLevel () const { return m_level; } private: const wstring m_strResult; const ACCESS_MASK m_accessBit; const GUID_TYPE m_guidType; bool m_bIsValid; const USHORT m_level; }; CResultObject::CResultObject ( ACCESS_MASK accessBit, const wstring& strResult, GUID_TYPE guidType, USHORT level) : m_accessBit (accessBit), m_strResult (strResult), m_guidType (guidType), m_bIsValid (true), m_level (level) { // case ACTRL_DS_LIST: // case ACTRL_DELETE: // case ACTRL_CHANGE_ACCESS: // case ACTRL_CHANGE_OWNER: // case ACTRL_DS_LIST_OBJECT: // case ACTRL_DS_SELF: switch (guidType) { case GUID_TYPE_CLASS: ASSERT (0 == m_level); switch (accessBit) { case ACTRL_DS_CREATE_CHILD: case ACTRL_DS_DELETE_CHILD: case ACTRL_DS_READ_PROP: // all case ACTRL_DS_WRITE_PROP: // all case ACTRL_DS_LIST: case ACTRL_DS_LIST_OBJECT: case ACTRL_DS_CONTROL_ACCESS: // all case ACTRL_DS_SELF: break; default: m_bIsValid = false; break; } break; case GUID_TYPE_ATTRIBUTE: ASSERT (0 != m_level); switch (accessBit) { case ACTRL_DS_READ_PROP: case ACTRL_DS_WRITE_PROP: break; case ACTRL_DS_CREATE_CHILD: case ACTRL_DS_DELETE_CHILD: case ACTRL_DS_CONTROL_ACCESS: m_bIsValid = false; break; default: m_bIsValid = false; break; } break; break; case GUID_TYPE_CONTROL: ASSERT (0 != m_level); switch (accessBit) { case ACTRL_DS_CONTROL_ACCESS: case ACTRL_DS_CREATE_CHILD: case ACTRL_DS_DELETE_CHILD: m_bIsValid = false; break; case ACTRL_DS_READ_PROP: case ACTRL_DS_WRITE_PROP: case ACTRL_READ_CONTROL: default: m_bIsValid = false; break; } break; default: ASSERT (FALSE); break; } } typedef CResultObject* PCResultObject; bool compare_resultObject (PCResultObject& obj1, PCResultObject& obj2) { return (*obj1) < (*obj2); } // // Function Prototypes // HRESULT GetFQDN ( PSID_FQDN* pPsidFQDN, wstring& strFQDN); HRESULT GetDownlevelName ( PSID_FQDN* pPsidFQDN, wstring& strDownlevelName); HRESULT ProcessObject ( const wstring& strObjectDN, POBJECT_TYPE_LIST pObjectTypeList, size_t objectTypeListLength, PSID principalSelfSid, const wstring& strDownlevelName); HRESULT GetTokenGroups ( const wstring& strObjectDN, list& psidList); HRESULT EnumerateEffectivePermissions ( const wstring& strObjectDN, const IOBJECT_TYPE_LIST& otl, const P_TYPE ptype, vector& resultList); HRESULT DisplayEffectivePermission ( const wstring& strObjectDN, const IOBJECT_TYPE_LIST& otl, const ACCESS_MASK accessMask, const P_TYPE ptype, const int strIDAll, const int strIDParam, const int strIDCDO, vector& resultList); HRESULT DisplayEffectivePermission ( const wstring& strObjectDN, const IOBJECT_TYPE_LIST& otl, const ACCESS_MASK accessMask, const P_TYPE ptype, const int strID, vector& resultList); void PrintGroupProvenance ( const ACCESS_MASK accessMask, const IOBJECT_TYPE_LIST& otl, const P_TYPE ptype, wstring& strProvenance); void PrintEffectiveRightsHeader ( ACCESS_MASK lastRight, USHORT level); HRESULT EffectiveRightsDiagnosis () { _TRACE (1, L"Entering EffectiveRightsDiagnosis\n"); HRESULT hr = S_OK; wstring str; if ( !_Module.DoTabDelimitedOutput () ) { LoadFromResource (str, IDS_EFFECTIVE_RIGHTS_DIAGNOSIS); MyWprintf (str.c_str ()); } POBJECT_TYPE_LIST pObjectTypeList = 0; size_t objectTypeListLength = 0; hr = _Module.m_adsiObject.BuildObjectTypeList (&pObjectTypeList, objectTypeListLength); if ( SUCCEEDED (hr) && SUCCEEDED (SepInit ()) ) { PSID principalSelfSid = 0; hr = _Module.m_adsiObject.GetPrincipalSelfSid (principalSelfSid); if ( !wcscmp (_Module.GetEffectiveRightsPrincipal ().c_str (), L"*") ) { for (PSID_FQDN_LIST::iterator itr = _Module.m_PSIDList.begin (); itr != _Module.m_PSIDList.end ();// && SUCCEEDED (hr); itr++) { wstring strDownlevelName; wstring strFQDN; hr = GetFQDN (*itr, strFQDN); if ( SUCCEEDED (hr) ) { hr = GetDownlevelName (*itr, strDownlevelName); if ( SUCCEEDED (hr) ) { hr = ProcessObject (strFQDN, pObjectTypeList, objectTypeListLength, principalSelfSid, strDownlevelName); } } } } else { hr = ProcessObject (_Module.GetEffectiveRightsPrincipal (), pObjectTypeList, objectTypeListLength, principalSelfSid, _Module.GetEffectiveRightsPrincipal ()); } // Free memory allocated for Sid if ( principalSelfSid ) CoTaskMemFree (principalSelfSid); // Free object type list array for (DWORD idx = 0; idx < objectTypeListLength; idx++) { CoTaskMemFree (pObjectTypeList[idx].ObjectType); } CoTaskMemFree (pObjectTypeList); SepCleanup (); } _TRACE (-1, L"Leaving EffectiveRightsDiagnosis: 0x%x\n", hr); return hr; } HRESULT GetDownlevelName (PSID_FQDN* pPsidFQDN, wstring& strDownlevelName) { _TRACE (1, L"Entering GetDownlevelName\n"); HRESULT hr = S_OK; if ( pPsidFQDN ) { switch (pPsidFQDN->m_sne) { case SidTypeUser: // Indicates a user SID. case SidTypeGroup: // Indicates a group SID. case SidTypeAlias: // Indicates an alias SID. case SidTypeWellKnownGroup: // Indicates an SID for a well-known group. case SidTypeDomain: // Indicates a domain SID. case SidTypeDeletedAccount: // Indicates an SID for a deleted account. strDownlevelName = pPsidFQDN->m_strDownLevelName; break; case SidTypeInvalid: // Indicates an invalid SID. case SidTypeUnknown: // Indicates an unknown SID type. hr = E_FAIL; break; default: hr = E_UNEXPECTED; break; } } else hr = E_POINTER; _TRACE (-1, L"Leaving GetDownlevelName: 0x%x\n", hr); return hr; } HRESULT GetFQDN (PSID_FQDN* pPsidFQDN, wstring& strFQDN) { _TRACE (1, L"Entering GetFQDN\n"); HRESULT hr = S_OK; if ( pPsidFQDN ) { switch (pPsidFQDN->m_sne) { case SidTypeUser: // Indicates a user SID. case SidTypeGroup: // Indicates a group SID. case SidTypeAlias: // Indicates an alias SID. case SidTypeWellKnownGroup: // Indicates an SID for a well-known group. strFQDN = pPsidFQDN->m_strFQDN; break; case SidTypeDomain: // Indicates a domain SID. case SidTypeDeletedAccount: // Indicates an SID for a deleted account. case SidTypeInvalid: // Indicates an invalid SID. case SidTypeUnknown: // Indicates an unknown SID type. hr = E_FAIL; break; default: hr = E_UNEXPECTED; break; } } else hr = E_POINTER; _TRACE (-1, L"Leaving GetFQDN: 0x%x\n", hr); return hr; } HRESULT GetTokenGroups (const wstring& strObjectDN, list& psidList) { _TRACE (1, L"Entering GetTokenGroups\n"); 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->put_EscapedMode (ADS_ESCAPEDMODE_OFF_EX ); hr = spPathname->Set (CComBSTR (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER); if ( SUCCEEDED (hr) ) { hr = spPathname->Set (CComBSTR (strObjectDN.c_str ()), ADS_SETTYPE_DN); 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) ) { { // // Get "objectSid" attribute // const PWSTR wzAllowedAttributes = L"objectSid"; PADS_ATTR_INFO pAttrs = 0; DWORD cAttrs = 0; LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes}; hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs); if ( SUCCEEDED (hr) ) { if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues ) { for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++) { PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue; if ( pSid && IsValidSid (pSid) ) { DWORD dwSidLen = GetLengthSid (pSid); PSID pSidCopy = CoTaskMemAlloc (dwSidLen); if ( pSidCopy ) { if ( CopySid (dwSidLen, pSidCopy, pSid) ) { ASSERT (IsValidSid (pSidCopy)); psidList.push_back (pSidCopy); } else { CoTaskMemFree (pSidCopy); hr = GetLastError (); _TRACE (0, L"CopySid () failed: 0x%x\n", hr); break; } } else { hr = E_OUTOFMEMORY; break; } } } } if ( pAttrs ) FreeADsMem (pAttrs); } else { _TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr); } } if ( SUCCEEDED (hr) ) { // // Get "tokenGroups" attribute // const PWSTR wzAllowedAttributes = L"tokenGroups"; PADS_ATTR_INFO pAttrs = 0; DWORD cAttrs = 0; LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes}; hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs); if ( SUCCEEDED (hr) ) { if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues ) { for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++) { PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue; if ( pSid && IsValidSid (pSid) ) { DWORD dwSidLen = GetLengthSid (pSid); PSID pSidCopy = CoTaskMemAlloc (dwSidLen); if ( pSidCopy ) { if ( CopySid (dwSidLen, pSidCopy, pSid) ) { ASSERT (IsValidSid (pSidCopy)); psidList.push_back (pSidCopy); } else { CoTaskMemFree (pSidCopy); hr = GetLastError (); _TRACE (0, L"CopySid () failed: 0x%x\n", hr); break; } } else { hr = E_OUTOFMEMORY; break; } } } } if ( pAttrs ) FreeADsMem (pAttrs); } else { _TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr); } } } else { _TRACE (0, L"ADsOpenObjectHelper (%s) failed: 0x%x\n", bstrFullPath); } } else { _TRACE (0, L"IADsPathname->Retrieve () failed: 0x%x\n", hr); } } else { _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); } } else { _TRACE (0, L"CoCreateInstance(CLSID_Pathname) failed: 0x%x\n", hr); } _TRACE (-1, L"Leaving GetTokenGroups: 0x%x\n", hr); return hr; } HRESULT ProcessObject ( const wstring& strObjectDN, // object having permissions on the // target object POBJECT_TYPE_LIST pObjectTypeList, // class, property and property set // GUIDs of target object size_t objectTypeListLength,// number of elements in pObjectTypeList PSID principalSelfSid, const wstring& strDownlevelName) { _TRACE (1, L"Entering ProcessObject\n"); HRESULT hr = S_OK; list psidList; // sid of strObjectDN and all groups of which it is a member hr = GetTokenGroups (strObjectDN, psidList); if ( SUCCEEDED (hr) ) { PACL pDacl = 0; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; if ( GetSecurityDescriptorDacl (_Module.m_pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) ) { PIOBJECT_TYPE_LIST LocalTypeList = 0; // // Capture any Object type list // NTSTATUS Status = SeCaptureObjectTypeList( pObjectTypeList, objectTypeListLength, &LocalTypeList); if ( NT_SUCCESS(Status) ) { hr = SepMaximumAccessCheck (psidList, pDacl, principalSelfSid, objectTypeListLength, LocalTypeList, objectTypeListLength); if ( !_Module.DoTabDelimitedOutput () ) { wstring str; FormatMessage (str, L"\n%1:\n\n", strDownlevelName.c_str ()); MyWprintf (str.c_str ()); } vector resultList; for (DWORD idx = 0; idx < objectTypeListLength; idx++) { EnumerateEffectivePermissions (strDownlevelName, LocalTypeList[idx], P_ALLOW, resultList); EnumerateEffectivePermissions (strDownlevelName, LocalTypeList[idx], P_DENY, resultList); } // Sort LocalTypeList // 1. Object Level Rights // 2. Property Level Rights // a. Create // b. Delete // c. Read // d. Write // 3. Control Rights sort (resultList.begin (), resultList.end (), compare_resultObject); ACCESS_MASK lastRight = 0; for (vector::iterator itr = resultList.begin (); itr != resultList.end (); itr++) { PCResultObject pResultObject = *itr; if ( lastRight != pResultObject->GetRight () ) { lastRight = pResultObject->GetRight (); if ( !_Module.DoTabDelimitedOutput () ) PrintEffectiveRightsHeader (lastRight, pResultObject->GetLevel ()); } pResultObject->PrintResult (); delete pResultObject; } } if ( LocalTypeList ) delete [] LocalTypeList; } // Free memory pointed to by psidList members for (list::iterator itr = psidList.begin (); itr != psidList.end (); itr++) { CoTaskMemFree (*itr); } } _TRACE (-1, L"Leaving ProcessObject: 0x%x\n", hr); return hr; } /////////////////////////////////////////////////////////////////////////////// // // Method: EnumerateEffectivePermissions () // // Purpose: Print all the permissions contained on the passed in ACE // // Inputs: otl - structure containing the ACE whose permissions we wish // to print // // ptype - allow, deny, succes, failure, success and failure // HRESULT EnumerateEffectivePermissions ( const wstring& strObjectDN, const IOBJECT_TYPE_LIST& otl, const P_TYPE ptype, vector& resultList) { HRESULT hr = S_OK; hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_CREATE_CHILD, ptype, IDS_CREATE_ALL_SUBOBJECTS_ER, IDS_CREATE_CLASS_OBJECTS_ER, IDS_CREATE_CLASS_OBJECTS, resultList); if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_DELETE_CHILD, ptype, IDS_DELETE_ALL_SUBOBJECTS_ER, IDS_DELETE_CLASS_OBJECTS_ER, IDS_DELETE_CLASS_OBJECTS, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_READ_PROP, ptype, IDS_READ_ALL_PROPERTIES_ER, IDS_READ_PROPERTY_PROPERTY_ER, IDS_READ_PROPERTY_PROPERTY, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_WRITE_PROP, ptype, IDS_WRITE_ALL_PROPERTIES_ER, IDS_WRITE_PROPERTY_PROPERTY_ER, IDS_WRITE_PROPERTY_PROPERTY, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_LIST, ptype, IDS_LIST_CONTENTS_ER, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_LIST_OBJECT, ptype, IDS_LIST_OBJECT_ER, resultList); } if ( SUCCEEDED (hr) ) { if ( otl.CurrentGranted & ACTRL_DS_CONTROL_ACCESS ) hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_CONTROL_ACCESS, ptype, IDS_ALL_CONTROL_ACCESSES_ER, IDS_CONTROL_ACCESS_DISPLAY_NAME, IDS_CONTROL_ACCESS_DISPLAY_NAME, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DELETE, ptype, IDS_DELETE_THIS_OBJECT_ER, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_READ_CONTROL, ptype, IDS_READ_PERMISSIONS_ER, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_CHANGE_ACCESS, ptype, IDS_MODIFY_PERMISSIONS_ER, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_CHANGE_OWNER, ptype, IDS_TAKE_CHANGE_OWNERSHIP_ER, resultList); } if ( SUCCEEDED (hr) ) { hr = DisplayEffectivePermission (strObjectDN, otl, ACTRL_DS_SELF, ptype, IDS_MODIFY_MEMBERSHIP_ER, resultList); } return hr; } /////////////////////////////////////////////////////////////////////////////// // // Method: DisplayEffectivePermission () // // Purpose: Print an OBJECT_ACE_TYPE permission // // Inputs: otl - 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 DisplayEffectivePermission (const wstring& strObjectDN, const IOBJECT_TYPE_LIST& otl, const ACCESS_MASK accessMask, const P_TYPE ptype, const int strIDAll, const int strIDParam, const int strIDCDO, vector& resultList) { HRESULT hr = S_OK; wstring str; wstring strPermission; if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) || ((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) ) { wstring strGuidResult; GUID_TYPE guidType = GUID_TYPE_UNKNOWN; _Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType); switch (guidType) { case GUID_TYPE_CLASS: FormatMessage (strPermission, strIDAll, strGuidResult.c_str ()); break; case GUID_TYPE_ATTRIBUTE: switch (accessMask) { case ACTRL_DS_LIST: case ACTRL_DS_LIST_OBJECT: case ACTRL_DS_SELF: // case ACTRL_DS_CONTROL_ACCESS: return S_OK; default: if ( _Module.DoTabDelimitedOutput () ) FormatMessage (strPermission, strIDCDO, strGuidResult.c_str ()); else FormatMessage (strPermission, strIDParam, strGuidResult.c_str ()); break; } break; case GUID_TYPE_CONTROL: switch (accessMask) { case ACTRL_DS_LIST: case ACTRL_DS_LIST_OBJECT: case ACTRL_DS_SELF: case ACTRL_DS_CREATE_CHILD: case ACTRL_DS_DELETE_CHILD: case ACTRL_DELETE: case ACTRL_CHANGE_ACCESS: case ACTRL_CHANGE_OWNER: case ACTRL_DS_CONTROL_ACCESS: return S_OK; case ACTRL_DS_READ_PROP: case ACTRL_DS_WRITE_PROP: case ACTRL_READ_CONTROL: default: FormatMessage (strPermission, strIDParam, strGuidResult.c_str ()); break; } break; case GUID_TYPE_UNKNOWN: default: return E_UNEXPECTED; } int strid = 0; switch (ptype) { case P_ALLOW: if ( _Module.DoTabDelimitedOutput () ) strid = IDS_CAN_CDO; else strid = IDS_CAN_ER; break; case P_DENY: if ( _Module.DoTabDelimitedOutput () ) strid = IDS_CANNOT_CDO; else strid = IDS_CANNOT_EF; break; default: return E_UNEXPECTED; } if ( _Module.DoTabDelimitedOutput () ) { FormatMessage (str, strid, strObjectDN.c_str (), strPermission.c_str ()); } else { FormatMessage (str, strid, strPermission.c_str ()); } wstring strProvenance; PrintGroupProvenance (accessMask, otl, ptype, strProvenance); str += strProvenance; PCResultObject pResultObject = new CResultObject (accessMask, str, guidType, otl.Level); if ( pResultObject ) { if ( pResultObject->IsValid () ) resultList.push_back (pResultObject); else delete pResultObject; } else hr = E_OUTOFMEMORY; } return hr; } /////////////////////////////////////////////////////////////////////////////// // // Method: DisplayEffectivePermission () // // Purpose: Print a non-OBJECT_ACE_TYPE permission // // Inputs: otl - 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 DisplayEffectivePermission ( const wstring& strObjectDN, const IOBJECT_TYPE_LIST& otl, const ACCESS_MASK accessMask, const P_TYPE ptype, const int strID, vector& resultList) { HRESULT hr = S_OK; wstring str; wstring strPermission; if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) || ((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) ) { wstring strGuidResult; GUID_TYPE guidType = GUID_TYPE_UNKNOWN; wstring strType; _Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType); switch (guidType) { case GUID_TYPE_CLASS: LoadFromResource (strType, IDS_CLASS); break; case GUID_TYPE_ATTRIBUTE: switch (accessMask) { case ACTRL_DS_LIST: case ACTRL_DS_LIST_OBJECT: case ACTRL_DS_SELF: return S_OK; default: LoadFromResource (strType, IDS_PROPERTY); break; } break; case GUID_TYPE_CONTROL: switch (accessMask) { case ACTRL_DS_LIST: case ACTRL_DS_LIST_OBJECT: case ACTRL_DS_SELF: case ACTRL_DS_CREATE_CHILD: case ACTRL_DS_DELETE_CHILD: case ACTRL_DELETE: case ACTRL_CHANGE_ACCESS: case ACTRL_CHANGE_OWNER: case ACTRL_DS_CONTROL_ACCESS: return S_OK; case ACTRL_DS_READ_PROP: case ACTRL_DS_WRITE_PROP: case ACTRL_READ_CONTROL: default: LoadFromResource (strType, IDS_CONTROL); break; } break; case GUID_TYPE_UNKNOWN: default: return E_UNEXPECTED; } LoadFromResource (strPermission, strID); int id = 0; switch (ptype) { case P_ALLOW: if ( _Module.DoTabDelimitedOutput () ) id = IDS_CAN_CDO; else id = IDS_CAN; break; case P_DENY: if ( _Module.DoTabDelimitedOutput () ) id = IDS_CANNOT_CDO; else id = IDS_CANNOT_EF; break; default: return E_UNEXPECTED; } if ( _Module.DoTabDelimitedOutput () ) { FormatMessage (str, id, strObjectDN.c_str (), strPermission.c_str ()); } else { FormatMessage (str, id, strPermission.c_str ()); } wstring strProvenance; PrintGroupProvenance (accessMask, otl, ptype, strProvenance); str += strProvenance; PCResultObject pResultObject = new CResultObject (accessMask, str, guidType, otl.Level); if ( pResultObject ) { if ( pResultObject->IsValid () ) resultList.push_back (pResultObject); else delete pResultObject; } else hr = E_OUTOFMEMORY; } return hr; } void PrintGroupProvenance ( const ACCESS_MASK accessMask, const IOBJECT_TYPE_LIST& otl, const P_TYPE ptype, wstring& strProvenance) { UINT nSid = 0; for (ULONG nBit = 0x1; nBit; nBit <<= 1, nSid++) { if ( accessMask & nBit ) { wstring strGroup; PSID psid = 0; SID_NAME_USE sne = SidTypeUnknown; if ( P_ALLOW == ptype ) psid = otl.grantingSid[nSid]; else psid = otl.denyingSid[nSid]; if ( IsValidSid (psid) ) { GetNameFromSid (psid, strGroup, 0, sne); if ( SidTypeGroup == sne ) { if ( _Module.DoTabDelimitedOutput () ) FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP_CDO, strGroup.c_str ()); else FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP, strGroup.c_str ()); } } break; } } strProvenance += L"\n"; } void PrintEffectiveRightsHeader (ACCESS_MASK lastRight, USHORT level) { wstring str; if ( 0 == level ) // Object level rights { return; } else { switch (lastRight) { case ACTRL_DS_LIST: case ACTRL_DELETE: case ACTRL_READ_CONTROL: case ACTRL_CHANGE_ACCESS: case ACTRL_CHANGE_OWNER: str = L"\n\n"; break; case ACTRL_DS_CREATE_CHILD: LoadFromResource (str, IDS_CAN_CREATE_FOLLOWING_CHILD_OBJECTS); break; case ACTRL_DS_DELETE_CHILD: LoadFromResource (str, IDS_CAN_DELETE_FOLLOWING_CHILD_OBJECTS); break; case ACTRL_DS_READ_PROP: LoadFromResource (str, IDS_CAN_READ_FOLLOWING_PROPERTIES); break; case ACTRL_DS_WRITE_PROP: LoadFromResource (str, IDS_CAN_WRITE_FOLLOWING_PROPERTIES); break; case ACTRL_DS_CONTROL_ACCESS: LoadFromResource (str, IDS_CAN_DO_FOLLOWING_CONTROL_OPERATIONS); break; case ACTRL_DS_LIST_OBJECT: case ACTRL_DS_SELF: default: str = L"\n\n"; break;; } } MyWprintf (str.c_str ()); }