Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1172 lines
35 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: EffRight.cpp
  7. //
  8. // Contents: Effective Rights Diagnosis and support methods
  9. //
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "stdafx.h"
  13. #include "adutils.h"
  14. #include "EffRight.h"
  15. #include "AccessCk.h"
  16. #include "SecDesc.h"
  17. // Classes
  18. #pragma warning (disable : 4127)
  19. class CResultObject
  20. {
  21. public:
  22. CResultObject (
  23. ACCESS_MASK accessBit,
  24. const wstring& strResult,
  25. GUID_TYPE guidType,
  26. USHORT level);
  27. ~CResultObject () {}
  28. bool operator== (CResultObject& rResultObject)
  29. {
  30. if ( m_accessBit == rResultObject.m_accessBit )
  31. return true;
  32. else
  33. return false;
  34. }
  35. bool operator< (CResultObject& rResultObject)
  36. {
  37. if ( 0 == m_level )
  38. return true;
  39. if ( m_accessBit < rResultObject.m_accessBit )
  40. {
  41. return true;
  42. }
  43. else
  44. return false;
  45. }
  46. const CResultObject& operator= (const CResultObject& obj)
  47. {
  48. UNREFERENCED_PARAMETER (obj);
  49. ASSERT (0);
  50. }
  51. void PrintResult ()
  52. {
  53. MyWprintf (m_strResult.c_str ());
  54. }
  55. ACCESS_MASK GetRight () const
  56. {
  57. return m_accessBit;
  58. }
  59. bool IsValid () const
  60. {
  61. return m_bIsValid;
  62. }
  63. USHORT GetLevel () const
  64. {
  65. return m_level;
  66. }
  67. private:
  68. const wstring m_strResult;
  69. const ACCESS_MASK m_accessBit;
  70. const GUID_TYPE m_guidType;
  71. bool m_bIsValid;
  72. const USHORT m_level;
  73. };
  74. CResultObject::CResultObject (
  75. ACCESS_MASK accessBit,
  76. const wstring& strResult,
  77. GUID_TYPE guidType,
  78. USHORT level) :
  79. m_accessBit (accessBit),
  80. m_strResult (strResult),
  81. m_guidType (guidType),
  82. m_bIsValid (true),
  83. m_level (level)
  84. {
  85. // case ACTRL_DS_LIST:
  86. // case ACTRL_DELETE:
  87. // case ACTRL_CHANGE_ACCESS:
  88. // case ACTRL_CHANGE_OWNER:
  89. // case ACTRL_DS_LIST_OBJECT:
  90. // case ACTRL_DS_SELF:
  91. switch (guidType)
  92. {
  93. case GUID_TYPE_CLASS:
  94. ASSERT (0 == m_level);
  95. switch (accessBit)
  96. {
  97. case ACTRL_DS_CREATE_CHILD:
  98. case ACTRL_DS_DELETE_CHILD:
  99. case ACTRL_DS_READ_PROP: // all
  100. case ACTRL_DS_WRITE_PROP: // all
  101. case ACTRL_DS_LIST:
  102. case ACTRL_DS_LIST_OBJECT:
  103. case ACTRL_DS_CONTROL_ACCESS: // all
  104. case ACTRL_DS_SELF:
  105. break;
  106. default:
  107. m_bIsValid = false;
  108. break;
  109. }
  110. break;
  111. case GUID_TYPE_ATTRIBUTE:
  112. ASSERT (0 != m_level);
  113. switch (accessBit)
  114. {
  115. case ACTRL_DS_READ_PROP:
  116. case ACTRL_DS_WRITE_PROP:
  117. break;
  118. case ACTRL_DS_CREATE_CHILD:
  119. case ACTRL_DS_DELETE_CHILD:
  120. case ACTRL_DS_CONTROL_ACCESS:
  121. m_bIsValid = false;
  122. break;
  123. default:
  124. m_bIsValid = false;
  125. break;
  126. }
  127. break;
  128. break;
  129. case GUID_TYPE_CONTROL:
  130. ASSERT (0 != m_level);
  131. switch (accessBit)
  132. {
  133. case ACTRL_DS_CONTROL_ACCESS:
  134. case ACTRL_DS_CREATE_CHILD:
  135. case ACTRL_DS_DELETE_CHILD:
  136. m_bIsValid = false;
  137. break;
  138. case ACTRL_DS_READ_PROP:
  139. case ACTRL_DS_WRITE_PROP:
  140. case ACTRL_READ_CONTROL:
  141. default:
  142. m_bIsValid = false;
  143. break;
  144. }
  145. break;
  146. default:
  147. ASSERT (FALSE);
  148. break;
  149. }
  150. }
  151. typedef CResultObject* PCResultObject;
  152. bool compare_resultObject (PCResultObject& obj1, PCResultObject& obj2)
  153. {
  154. return (*obj1) < (*obj2);
  155. }
  156. //
  157. // Function Prototypes
  158. //
  159. HRESULT GetFQDN (
  160. PSID_FQDN* pPsidFQDN,
  161. wstring& strFQDN);
  162. HRESULT GetDownlevelName (
  163. PSID_FQDN* pPsidFQDN,
  164. wstring& strDownlevelName);
  165. HRESULT ProcessObject (
  166. const wstring& strObjectDN,
  167. POBJECT_TYPE_LIST pObjectTypeList,
  168. size_t objectTypeListLength,
  169. PSID principalSelfSid,
  170. const wstring& strDownlevelName);
  171. HRESULT GetTokenGroups (
  172. const wstring& strObjectDN,
  173. list<PSID>& psidList);
  174. HRESULT EnumerateEffectivePermissions (
  175. const wstring& strObjectDN,
  176. const IOBJECT_TYPE_LIST& otl,
  177. const P_TYPE ptype,
  178. vector<PCResultObject>& resultList);
  179. HRESULT DisplayEffectivePermission (
  180. const wstring& strObjectDN,
  181. const IOBJECT_TYPE_LIST& otl,
  182. const ACCESS_MASK accessMask,
  183. const P_TYPE ptype,
  184. const int strIDAll,
  185. const int strIDParam,
  186. const int strIDCDO,
  187. vector<PCResultObject>& resultList);
  188. HRESULT DisplayEffectivePermission (
  189. const wstring& strObjectDN,
  190. const IOBJECT_TYPE_LIST& otl,
  191. const ACCESS_MASK accessMask,
  192. const P_TYPE ptype,
  193. const int strID,
  194. vector<PCResultObject>& resultList);
  195. void PrintGroupProvenance (
  196. const ACCESS_MASK accessMask,
  197. const IOBJECT_TYPE_LIST& otl,
  198. const P_TYPE ptype,
  199. wstring& strProvenance);
  200. void PrintEffectiveRightsHeader (
  201. ACCESS_MASK lastRight,
  202. USHORT level);
  203. HRESULT EffectiveRightsDiagnosis ()
  204. {
  205. _TRACE (1, L"Entering EffectiveRightsDiagnosis\n");
  206. HRESULT hr = S_OK;
  207. wstring str;
  208. if ( !_Module.DoTabDelimitedOutput () )
  209. {
  210. LoadFromResource (str, IDS_EFFECTIVE_RIGHTS_DIAGNOSIS);
  211. MyWprintf (str.c_str ());
  212. }
  213. POBJECT_TYPE_LIST pObjectTypeList = 0;
  214. size_t objectTypeListLength = 0;
  215. hr = _Module.m_adsiObject.BuildObjectTypeList (&pObjectTypeList, objectTypeListLength);
  216. if ( SUCCEEDED (hr) && SUCCEEDED (SepInit ()) )
  217. {
  218. PSID principalSelfSid = 0;
  219. hr = _Module.m_adsiObject.GetPrincipalSelfSid (principalSelfSid);
  220. if ( !wcscmp (_Module.GetEffectiveRightsPrincipal ().c_str (), L"*") )
  221. {
  222. for (PSID_FQDN_LIST::iterator itr = _Module.m_PSIDList.begin ();
  223. itr != _Module.m_PSIDList.end ();// && SUCCEEDED (hr);
  224. itr++)
  225. {
  226. wstring strDownlevelName;
  227. wstring strFQDN;
  228. hr = GetFQDN (*itr, strFQDN);
  229. if ( SUCCEEDED (hr) )
  230. {
  231. hr = GetDownlevelName (*itr, strDownlevelName);
  232. if ( SUCCEEDED (hr) )
  233. {
  234. hr = ProcessObject (strFQDN, pObjectTypeList,
  235. objectTypeListLength, principalSelfSid,
  236. strDownlevelName);
  237. }
  238. }
  239. }
  240. }
  241. else
  242. {
  243. hr = ProcessObject (_Module.GetEffectiveRightsPrincipal (),
  244. pObjectTypeList, objectTypeListLength, principalSelfSid,
  245. _Module.GetEffectiveRightsPrincipal ());
  246. }
  247. // Free memory allocated for Sid
  248. if ( principalSelfSid )
  249. CoTaskMemFree (principalSelfSid);
  250. // Free object type list array
  251. for (DWORD idx = 0; idx < objectTypeListLength; idx++)
  252. {
  253. CoTaskMemFree (pObjectTypeList[idx].ObjectType);
  254. }
  255. CoTaskMemFree (pObjectTypeList);
  256. SepCleanup ();
  257. }
  258. _TRACE (-1, L"Leaving EffectiveRightsDiagnosis: 0x%x\n", hr);
  259. return hr;
  260. }
  261. HRESULT GetDownlevelName (PSID_FQDN* pPsidFQDN, wstring& strDownlevelName)
  262. {
  263. _TRACE (1, L"Entering GetDownlevelName\n");
  264. HRESULT hr = S_OK;
  265. if ( pPsidFQDN )
  266. {
  267. switch (pPsidFQDN->m_sne)
  268. {
  269. case SidTypeUser: // Indicates a user SID.
  270. case SidTypeGroup: // Indicates a group SID.
  271. case SidTypeAlias: // Indicates an alias SID.
  272. case SidTypeWellKnownGroup: // Indicates an SID for a well-known group.
  273. case SidTypeDomain: // Indicates a domain SID.
  274. case SidTypeDeletedAccount: // Indicates an SID for a deleted account.
  275. strDownlevelName = pPsidFQDN->m_strDownLevelName;
  276. break;
  277. case SidTypeInvalid: // Indicates an invalid SID.
  278. case SidTypeUnknown: // Indicates an unknown SID type.
  279. hr = E_FAIL;
  280. break;
  281. default:
  282. hr = E_UNEXPECTED;
  283. break;
  284. }
  285. }
  286. else
  287. hr = E_POINTER;
  288. _TRACE (-1, L"Leaving GetDownlevelName: 0x%x\n", hr);
  289. return hr;
  290. }
  291. HRESULT GetFQDN (PSID_FQDN* pPsidFQDN, wstring& strFQDN)
  292. {
  293. _TRACE (1, L"Entering GetFQDN\n");
  294. HRESULT hr = S_OK;
  295. if ( pPsidFQDN )
  296. {
  297. switch (pPsidFQDN->m_sne)
  298. {
  299. case SidTypeUser: // Indicates a user SID.
  300. case SidTypeGroup: // Indicates a group SID.
  301. case SidTypeAlias: // Indicates an alias SID.
  302. case SidTypeWellKnownGroup: // Indicates an SID for a well-known group.
  303. strFQDN = pPsidFQDN->m_strFQDN;
  304. break;
  305. case SidTypeDomain: // Indicates a domain SID.
  306. case SidTypeDeletedAccount: // Indicates an SID for a deleted account.
  307. case SidTypeInvalid: // Indicates an invalid SID.
  308. case SidTypeUnknown: // Indicates an unknown SID type.
  309. hr = E_FAIL;
  310. break;
  311. default:
  312. hr = E_UNEXPECTED;
  313. break;
  314. }
  315. }
  316. else
  317. hr = E_POINTER;
  318. _TRACE (-1, L"Leaving GetFQDN: 0x%x\n", hr);
  319. return hr;
  320. }
  321. HRESULT GetTokenGroups (const wstring& strObjectDN, list<PSID>& psidList)
  322. {
  323. _TRACE (1, L"Entering GetTokenGroups\n");
  324. HRESULT hr = S_OK;
  325. CComPtr<IADsPathname> spPathname;
  326. //
  327. // Constructing the directory paths
  328. //
  329. hr = CoCreateInstance(
  330. CLSID_Pathname,
  331. NULL,
  332. CLSCTX_ALL,
  333. IID_PPV_ARG (IADsPathname, &spPathname));
  334. if ( SUCCEEDED (hr) )
  335. {
  336. ASSERT (!!spPathname);
  337. hr = spPathname->put_EscapedMode (ADS_ESCAPEDMODE_OFF_EX );
  338. hr = spPathname->Set (const_cast <PWSTR> (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER);
  339. if ( SUCCEEDED (hr) )
  340. {
  341. hr = spPathname->Set (
  342. const_cast <PWSTR> (strObjectDN.c_str ()),
  343. ADS_SETTYPE_DN);
  344. if ( SUCCEEDED (hr) )
  345. {
  346. BSTR bstrFullPath = 0;
  347. hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
  348. if ( SUCCEEDED (hr) )
  349. {
  350. CComPtr<IDirectoryObject> spDirObj;
  351. hr = ADsGetObject (
  352. bstrFullPath,
  353. IID_PPV_ARG (IDirectoryObject, &spDirObj));
  354. if ( SUCCEEDED (hr) )
  355. {
  356. {
  357. //
  358. // Get "objectSid" attribute
  359. //
  360. const PWSTR wzAllowedAttributes = L"objectSid";
  361. PADS_ATTR_INFO pAttrs = 0;
  362. DWORD cAttrs = 0;
  363. LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes};
  364. hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
  365. if ( SUCCEEDED (hr) )
  366. {
  367. if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
  368. {
  369. for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++)
  370. {
  371. PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue;
  372. if ( pSid && IsValidSid (pSid) )
  373. {
  374. DWORD dwSidLen = GetLengthSid (pSid);
  375. PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
  376. if ( pSidCopy )
  377. {
  378. if ( CopySid (dwSidLen, pSidCopy, pSid) )
  379. {
  380. ASSERT (IsValidSid (pSidCopy));
  381. psidList.push_back (pSidCopy);
  382. }
  383. else
  384. {
  385. CoTaskMemFree (pSidCopy);
  386. hr = GetLastError ();
  387. _TRACE (0, L"CopySid () failed: 0x%x\n", hr);
  388. break;
  389. }
  390. }
  391. else
  392. {
  393. hr = E_OUTOFMEMORY;
  394. break;
  395. }
  396. }
  397. }
  398. }
  399. if ( pAttrs )
  400. FreeADsMem (pAttrs);
  401. }
  402. else
  403. {
  404. _TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
  405. }
  406. }
  407. if ( SUCCEEDED (hr) )
  408. {
  409. //
  410. // Get "tokenGroups" attribute
  411. //
  412. const PWSTR wzAllowedAttributes = L"tokenGroups";
  413. PADS_ATTR_INFO pAttrs = 0;
  414. DWORD cAttrs = 0;
  415. LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes};
  416. hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
  417. if ( SUCCEEDED (hr) )
  418. {
  419. if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
  420. {
  421. for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++)
  422. {
  423. PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue;
  424. if ( pSid && IsValidSid (pSid) )
  425. {
  426. DWORD dwSidLen = GetLengthSid (pSid);
  427. PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
  428. if ( pSidCopy )
  429. {
  430. if ( CopySid (dwSidLen, pSidCopy, pSid) )
  431. {
  432. ASSERT (IsValidSid (pSidCopy));
  433. psidList.push_back (pSidCopy);
  434. }
  435. else
  436. {
  437. CoTaskMemFree (pSidCopy);
  438. hr = GetLastError ();
  439. _TRACE (0, L"CopySid () failed: 0x%x\n", hr);
  440. break;
  441. }
  442. }
  443. else
  444. {
  445. hr = E_OUTOFMEMORY;
  446. break;
  447. }
  448. }
  449. }
  450. }
  451. if ( pAttrs )
  452. FreeADsMem (pAttrs);
  453. }
  454. else
  455. {
  456. _TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
  457. }
  458. }
  459. }
  460. else
  461. {
  462. _TRACE (0, L"ADsGetObject (%s) failed: 0x%x\n", bstrFullPath);
  463. }
  464. }
  465. else
  466. {
  467. _TRACE (0, L"IADsPathname->Retrieve () failed: 0x%x\n", hr);
  468. }
  469. }
  470. else
  471. {
  472. _TRACE (0, L"IADsPathname->Set (%s): 0x%x\n",
  473. strObjectDN.c_str (), hr);
  474. }
  475. }
  476. else
  477. {
  478. _TRACE (0, L"IADsPathname->Set (%s): 0x%x\n", ACLDIAG_LDAP, hr);
  479. }
  480. }
  481. else
  482. {
  483. _TRACE (0, L"CoCreateInstance(CLSID_Pathname) failed: 0x%x\n", hr);
  484. }
  485. _TRACE (-1, L"Leaving GetTokenGroups: 0x%x\n", hr);
  486. return hr;
  487. }
  488. HRESULT ProcessObject (
  489. const wstring& strObjectDN, // object having permissions on the
  490. // target object
  491. POBJECT_TYPE_LIST pObjectTypeList, // class, property and property set
  492. // GUIDs of target object
  493. size_t objectTypeListLength,// number of elements in pObjectTypeList
  494. PSID principalSelfSid,
  495. const wstring& strDownlevelName)
  496. {
  497. _TRACE (1, L"Entering ProcessObject\n");
  498. HRESULT hr = S_OK;
  499. list<PSID> psidList; // sid of strObjectDN and all groups of which it is a member
  500. hr = GetTokenGroups (strObjectDN, psidList);
  501. if ( SUCCEEDED (hr) )
  502. {
  503. PACL pDacl = 0;
  504. BOOL bDaclPresent = FALSE;
  505. BOOL bDaclDefaulted = FALSE;
  506. if ( GetSecurityDescriptorDacl (_Module.m_pSecurityDescriptor,
  507. &bDaclPresent, &pDacl, &bDaclDefaulted) )
  508. {
  509. PIOBJECT_TYPE_LIST LocalTypeList = 0;
  510. //
  511. // Capture any Object type list
  512. //
  513. NTSTATUS Status = SeCaptureObjectTypeList( pObjectTypeList,
  514. objectTypeListLength,
  515. &LocalTypeList);
  516. if ( NT_SUCCESS(Status) )
  517. {
  518. hr = SepMaximumAccessCheck (psidList,
  519. pDacl,
  520. principalSelfSid,
  521. objectTypeListLength,
  522. LocalTypeList,
  523. objectTypeListLength);
  524. if ( !_Module.DoTabDelimitedOutput () )
  525. {
  526. wstring str;
  527. FormatMessage (str, L"\n%1:\n\n", strDownlevelName.c_str ());
  528. MyWprintf (str.c_str ());
  529. }
  530. vector<PCResultObject> resultList;
  531. for (DWORD idx = 0; idx < objectTypeListLength; idx++)
  532. {
  533. EnumerateEffectivePermissions (strDownlevelName,
  534. LocalTypeList[idx], P_ALLOW, resultList);
  535. EnumerateEffectivePermissions (strDownlevelName,
  536. LocalTypeList[idx], P_DENY, resultList);
  537. }
  538. // Sort LocalTypeList
  539. // 1. Object Level Rights
  540. // 2. Property Level Rights
  541. // a. Create
  542. // b. Delete
  543. // c. Read
  544. // d. Write
  545. // 3. Control Rights
  546. sort (resultList.begin (), resultList.end (), compare_resultObject);
  547. ACCESS_MASK lastRight = 0;
  548. for (vector<PCResultObject>::iterator itr = resultList.begin ();
  549. itr != resultList.end (); itr++)
  550. {
  551. PCResultObject pResultObject = *itr;
  552. if ( lastRight != pResultObject->GetRight () )
  553. {
  554. lastRight = pResultObject->GetRight ();
  555. if ( !_Module.DoTabDelimitedOutput () )
  556. PrintEffectiveRightsHeader (lastRight, pResultObject->GetLevel ());
  557. }
  558. pResultObject->PrintResult ();
  559. delete pResultObject;
  560. }
  561. }
  562. if ( LocalTypeList )
  563. delete [] LocalTypeList;
  564. }
  565. // Free memory pointed to by psidList members
  566. for (list<PSID>::iterator itr = psidList.begin ();
  567. itr != psidList.end ();
  568. itr++)
  569. {
  570. CoTaskMemFree (*itr);
  571. }
  572. }
  573. _TRACE (-1, L"Leaving ProcessObject: 0x%x\n", hr);
  574. return hr;
  575. }
  576. ///////////////////////////////////////////////////////////////////////////////
  577. //
  578. // Method: EnumerateEffectivePermissions ()
  579. //
  580. // Purpose: Print all the permissions contained on the passed in ACE
  581. //
  582. // Inputs: otl - structure containing the ACE whose permissions we wish
  583. // to print
  584. //
  585. // ptype - allow, deny, succes, failure, success and failure
  586. //
  587. HRESULT EnumerateEffectivePermissions (
  588. const wstring& strObjectDN,
  589. const IOBJECT_TYPE_LIST& otl,
  590. const P_TYPE ptype,
  591. vector<PCResultObject>& resultList)
  592. {
  593. HRESULT hr = S_OK;
  594. hr = DisplayEffectivePermission (strObjectDN,
  595. otl,
  596. ACTRL_DS_CREATE_CHILD,
  597. ptype,
  598. IDS_CREATE_ALL_SUBOBJECTS_ER,
  599. IDS_CREATE_CLASS_OBJECTS_ER,
  600. IDS_CREATE_CLASS_OBJECTS,
  601. resultList);
  602. if ( SUCCEEDED (hr) )
  603. {
  604. hr = DisplayEffectivePermission (strObjectDN,
  605. otl,
  606. ACTRL_DS_DELETE_CHILD,
  607. ptype,
  608. IDS_DELETE_ALL_SUBOBJECTS_ER,
  609. IDS_DELETE_CLASS_OBJECTS_ER,
  610. IDS_DELETE_CLASS_OBJECTS,
  611. resultList);
  612. }
  613. if ( SUCCEEDED (hr) )
  614. {
  615. hr = DisplayEffectivePermission (strObjectDN,
  616. otl,
  617. ACTRL_DS_READ_PROP,
  618. ptype,
  619. IDS_READ_ALL_PROPERTIES_ER,
  620. IDS_READ_PROPERTY_PROPERTY_ER,
  621. IDS_READ_PROPERTY_PROPERTY,
  622. resultList);
  623. }
  624. if ( SUCCEEDED (hr) )
  625. {
  626. hr = DisplayEffectivePermission (strObjectDN,
  627. otl,
  628. ACTRL_DS_WRITE_PROP,
  629. ptype,
  630. IDS_WRITE_ALL_PROPERTIES_ER,
  631. IDS_WRITE_PROPERTY_PROPERTY_ER,
  632. IDS_WRITE_PROPERTY_PROPERTY,
  633. resultList);
  634. }
  635. if ( SUCCEEDED (hr) )
  636. {
  637. hr = DisplayEffectivePermission (strObjectDN,
  638. otl,
  639. ACTRL_DS_LIST,
  640. ptype,
  641. IDS_LIST_CONTENTS_ER,
  642. resultList);
  643. }
  644. if ( SUCCEEDED (hr) )
  645. {
  646. hr = DisplayEffectivePermission (strObjectDN,
  647. otl,
  648. ACTRL_DS_LIST_OBJECT,
  649. ptype,
  650. IDS_LIST_OBJECT_ER,
  651. resultList);
  652. }
  653. if ( SUCCEEDED (hr) )
  654. {
  655. if ( otl.CurrentGranted & ACTRL_DS_CONTROL_ACCESS )
  656. hr = DisplayEffectivePermission (strObjectDN,
  657. otl,
  658. ACTRL_DS_CONTROL_ACCESS,
  659. ptype,
  660. IDS_ALL_CONTROL_ACCESSES_ER,
  661. IDS_CONTROL_ACCESS_DISPLAY_NAME,
  662. IDS_CONTROL_ACCESS_DISPLAY_NAME,
  663. resultList);
  664. }
  665. if ( SUCCEEDED (hr) )
  666. {
  667. hr = DisplayEffectivePermission (strObjectDN,
  668. otl,
  669. ACTRL_DELETE,
  670. ptype,
  671. IDS_DELETE_THIS_OBJECT_ER,
  672. resultList);
  673. }
  674. if ( SUCCEEDED (hr) )
  675. {
  676. hr = DisplayEffectivePermission (strObjectDN,
  677. otl,
  678. ACTRL_READ_CONTROL,
  679. ptype,
  680. IDS_READ_PERMISSIONS_ER,
  681. resultList);
  682. }
  683. if ( SUCCEEDED (hr) )
  684. {
  685. hr = DisplayEffectivePermission (strObjectDN,
  686. otl,
  687. ACTRL_CHANGE_ACCESS,
  688. ptype,
  689. IDS_MODIFY_PERMISSIONS_ER,
  690. resultList);
  691. }
  692. if ( SUCCEEDED (hr) )
  693. {
  694. hr = DisplayEffectivePermission (strObjectDN,
  695. otl,
  696. ACTRL_CHANGE_OWNER,
  697. ptype,
  698. IDS_TAKE_CHANGE_OWNERSHIP_ER,
  699. resultList);
  700. }
  701. if ( SUCCEEDED (hr) )
  702. {
  703. hr = DisplayEffectivePermission (strObjectDN,
  704. otl,
  705. ACTRL_DS_SELF,
  706. ptype,
  707. IDS_MODIFY_MEMBERSHIP_ER,
  708. resultList);
  709. }
  710. return hr;
  711. }
  712. ///////////////////////////////////////////////////////////////////////////////
  713. //
  714. // Method: DisplayEffectivePermission ()
  715. //
  716. // Purpose: Print an OBJECT_ACE_TYPE permission
  717. //
  718. // Inputs: otl - structure containing the ACE whose permission we wish
  719. // to print
  720. //
  721. // accessMask - the specific permission we're looking to print
  722. //
  723. // bAllow - whether the permission is allowed or denied
  724. //
  725. // strIDAll - string to print if permission applies to all object
  726. // classes
  727. //
  728. // strIDParam - string print if permission applies to a specific
  729. // object class
  730. //
  731. HRESULT DisplayEffectivePermission (const wstring& strObjectDN,
  732. const IOBJECT_TYPE_LIST& otl,
  733. const ACCESS_MASK accessMask,
  734. const P_TYPE ptype,
  735. const int strIDAll,
  736. const int strIDParam,
  737. const int strIDCDO,
  738. vector<PCResultObject>& resultList)
  739. {
  740. HRESULT hr = S_OK;
  741. wstring str;
  742. wstring strPermission;
  743. if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) ||
  744. ((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) )
  745. {
  746. wstring strGuidResult;
  747. GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
  748. _Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType);
  749. switch (guidType)
  750. {
  751. case GUID_TYPE_CLASS:
  752. FormatMessage (strPermission, strIDAll, strGuidResult.c_str ());
  753. break;
  754. case GUID_TYPE_ATTRIBUTE:
  755. switch (accessMask)
  756. {
  757. case ACTRL_DS_LIST:
  758. case ACTRL_DS_LIST_OBJECT:
  759. case ACTRL_DS_SELF:
  760. // case ACTRL_DS_CONTROL_ACCESS:
  761. return S_OK;
  762. default:
  763. if ( _Module.DoTabDelimitedOutput () )
  764. FormatMessage (strPermission, strIDCDO, strGuidResult.c_str ());
  765. else
  766. FormatMessage (strPermission, strIDParam, strGuidResult.c_str ());
  767. break;
  768. }
  769. break;
  770. case GUID_TYPE_CONTROL:
  771. switch (accessMask)
  772. {
  773. case ACTRL_DS_LIST:
  774. case ACTRL_DS_LIST_OBJECT:
  775. case ACTRL_DS_SELF:
  776. case ACTRL_DS_CREATE_CHILD:
  777. case ACTRL_DS_DELETE_CHILD:
  778. case ACTRL_DELETE:
  779. case ACTRL_CHANGE_ACCESS:
  780. case ACTRL_CHANGE_OWNER:
  781. case ACTRL_DS_CONTROL_ACCESS:
  782. return S_OK;
  783. case ACTRL_DS_READ_PROP:
  784. case ACTRL_DS_WRITE_PROP:
  785. case ACTRL_READ_CONTROL:
  786. default:
  787. FormatMessage (strPermission, strIDParam, strGuidResult.c_str ());
  788. break;
  789. }
  790. break;
  791. case GUID_TYPE_UNKNOWN:
  792. default:
  793. return E_UNEXPECTED;
  794. }
  795. int strid = 0;
  796. switch (ptype)
  797. {
  798. case P_ALLOW:
  799. if ( _Module.DoTabDelimitedOutput () )
  800. strid = IDS_CAN_CDO;
  801. else
  802. strid = IDS_CAN_ER;
  803. break;
  804. case P_DENY:
  805. if ( _Module.DoTabDelimitedOutput () )
  806. strid = IDS_CANNOT_CDO;
  807. else
  808. strid = IDS_CANNOT_EF;
  809. break;
  810. default:
  811. return E_UNEXPECTED;
  812. }
  813. if ( _Module.DoTabDelimitedOutput () )
  814. {
  815. FormatMessage (str, strid,
  816. strObjectDN.c_str (),
  817. strPermission.c_str ());
  818. }
  819. else
  820. {
  821. FormatMessage (str, strid,
  822. strPermission.c_str ());
  823. }
  824. wstring strProvenance;
  825. PrintGroupProvenance (accessMask, otl, ptype, strProvenance);
  826. str += strProvenance;
  827. PCResultObject pResultObject = new CResultObject (accessMask, str,
  828. guidType, otl.Level);
  829. if ( pResultObject )
  830. {
  831. if ( pResultObject->IsValid () )
  832. resultList.push_back (pResultObject);
  833. else
  834. delete pResultObject;
  835. }
  836. else
  837. hr = E_OUTOFMEMORY;
  838. }
  839. return hr;
  840. }
  841. ///////////////////////////////////////////////////////////////////////////////
  842. //
  843. // Method: DisplayEffectivePermission ()
  844. //
  845. // Purpose: Print a non-OBJECT_ACE_TYPE permission
  846. //
  847. // Inputs: otl - structure containing the ACE whose permission we wish
  848. // to print
  849. //
  850. // accessMask - the specific permission we're looking to print
  851. //
  852. // bAllow - whether the permission is allowed or denied
  853. //
  854. // strID - string to print
  855. //
  856. HRESULT DisplayEffectivePermission (
  857. const wstring& strObjectDN,
  858. const IOBJECT_TYPE_LIST& otl,
  859. const ACCESS_MASK accessMask,
  860. const P_TYPE ptype,
  861. const int strID,
  862. vector<PCResultObject>& resultList)
  863. {
  864. HRESULT hr = S_OK;
  865. wstring str;
  866. wstring strPermission;
  867. if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) ||
  868. ((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) )
  869. {
  870. wstring strGuidResult;
  871. GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
  872. wstring strType;
  873. _Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType);
  874. switch (guidType)
  875. {
  876. case GUID_TYPE_CLASS:
  877. LoadFromResource (strType, IDS_CLASS);
  878. break;
  879. case GUID_TYPE_ATTRIBUTE:
  880. switch (accessMask)
  881. {
  882. case ACTRL_DS_LIST:
  883. case ACTRL_DS_LIST_OBJECT:
  884. case ACTRL_DS_SELF:
  885. return S_OK;
  886. default:
  887. LoadFromResource (strType, IDS_PROPERTY);
  888. break;
  889. }
  890. break;
  891. case GUID_TYPE_CONTROL:
  892. switch (accessMask)
  893. {
  894. case ACTRL_DS_LIST:
  895. case ACTRL_DS_LIST_OBJECT:
  896. case ACTRL_DS_SELF:
  897. case ACTRL_DS_CREATE_CHILD:
  898. case ACTRL_DS_DELETE_CHILD:
  899. case ACTRL_DELETE:
  900. case ACTRL_CHANGE_ACCESS:
  901. case ACTRL_CHANGE_OWNER:
  902. case ACTRL_DS_CONTROL_ACCESS:
  903. return S_OK;
  904. case ACTRL_DS_READ_PROP:
  905. case ACTRL_DS_WRITE_PROP:
  906. case ACTRL_READ_CONTROL:
  907. default:
  908. LoadFromResource (strType, IDS_CONTROL);
  909. break;
  910. }
  911. break;
  912. case GUID_TYPE_UNKNOWN:
  913. default:
  914. return E_UNEXPECTED;
  915. }
  916. LoadFromResource (strPermission, strID);
  917. int id = 0;
  918. switch (ptype)
  919. {
  920. case P_ALLOW:
  921. if ( _Module.DoTabDelimitedOutput () )
  922. id = IDS_CAN_CDO;
  923. else
  924. id = IDS_CAN;
  925. break;
  926. case P_DENY:
  927. if ( _Module.DoTabDelimitedOutput () )
  928. id = IDS_CANNOT_CDO;
  929. else
  930. id = IDS_CANNOT_EF;
  931. break;
  932. default:
  933. return E_UNEXPECTED;
  934. }
  935. if ( _Module.DoTabDelimitedOutput () )
  936. {
  937. FormatMessage (str, id,
  938. strObjectDN.c_str (),
  939. strPermission.c_str ());
  940. }
  941. else
  942. {
  943. FormatMessage (str, id, strPermission.c_str ());
  944. }
  945. wstring strProvenance;
  946. PrintGroupProvenance (accessMask, otl, ptype, strProvenance);
  947. str += strProvenance;
  948. PCResultObject pResultObject = new CResultObject (accessMask, str,
  949. guidType, otl.Level);
  950. if ( pResultObject )
  951. {
  952. if ( pResultObject->IsValid () )
  953. resultList.push_back (pResultObject);
  954. else
  955. delete pResultObject;
  956. }
  957. else
  958. hr = E_OUTOFMEMORY;
  959. }
  960. return hr;
  961. }
  962. void PrintGroupProvenance (
  963. const ACCESS_MASK accessMask,
  964. const IOBJECT_TYPE_LIST& otl,
  965. const P_TYPE ptype,
  966. wstring& strProvenance)
  967. {
  968. UINT nSid = 0;
  969. for (ULONG nBit = 0x1; nBit; nBit <<= 1, nSid++)
  970. {
  971. if ( accessMask & nBit )
  972. {
  973. wstring strGroup;
  974. PSID psid = 0;
  975. SID_NAME_USE sne = SidTypeUnknown;
  976. if ( P_ALLOW == ptype )
  977. psid = otl.grantingSid[nSid];
  978. else
  979. psid = otl.denyingSid[nSid];
  980. if ( IsValidSid (psid) )
  981. {
  982. GetNameFromSid (psid, strGroup, 0, sne);
  983. if ( SidTypeGroup == sne )
  984. {
  985. if ( _Module.DoTabDelimitedOutput () )
  986. FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP_CDO, strGroup.c_str ());
  987. else
  988. FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP, strGroup.c_str ());
  989. }
  990. }
  991. break;
  992. }
  993. }
  994. strProvenance += L"\n";
  995. }
  996. void PrintEffectiveRightsHeader (ACCESS_MASK lastRight, USHORT level)
  997. {
  998. wstring str;
  999. if ( 0 == level ) // Object level rights
  1000. {
  1001. return;
  1002. }
  1003. else
  1004. {
  1005. switch (lastRight)
  1006. {
  1007. case ACTRL_DS_LIST:
  1008. case ACTRL_DELETE:
  1009. case ACTRL_READ_CONTROL:
  1010. case ACTRL_CHANGE_ACCESS:
  1011. case ACTRL_CHANGE_OWNER:
  1012. str = L"\n\n";
  1013. break;
  1014. case ACTRL_DS_CREATE_CHILD:
  1015. LoadFromResource (str, IDS_CAN_CREATE_FOLLOWING_CHILD_OBJECTS);
  1016. break;
  1017. case ACTRL_DS_DELETE_CHILD:
  1018. LoadFromResource (str, IDS_CAN_DELETE_FOLLOWING_CHILD_OBJECTS);
  1019. break;
  1020. case ACTRL_DS_READ_PROP:
  1021. LoadFromResource (str, IDS_CAN_READ_FOLLOWING_PROPERTIES);
  1022. break;
  1023. case ACTRL_DS_WRITE_PROP:
  1024. LoadFromResource (str, IDS_CAN_WRITE_FOLLOWING_PROPERTIES);
  1025. break;
  1026. case ACTRL_DS_CONTROL_ACCESS:
  1027. LoadFromResource (str, IDS_CAN_DO_FOLLOWING_CONTROL_OPERATIONS);
  1028. break;
  1029. case ACTRL_DS_LIST_OBJECT:
  1030. case ACTRL_DS_SELF:
  1031. default:
  1032. str = L"\n\n";
  1033. break;;
  1034. }
  1035. }
  1036. MyWprintf (str.c_str ());
  1037. }