Leaked source code of windows server 2003
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.

1171 lines
37 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999-2002.
  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 (CComBSTR (ACLDIAG_LDAP), ADS_SETTYPE_PROVIDER);
  339. if ( SUCCEEDED (hr) )
  340. {
  341. hr = spPathname->Set (CComBSTR (strObjectDN.c_str ()), ADS_SETTYPE_DN);
  342. if ( SUCCEEDED (hr) )
  343. {
  344. BSTR bstrFullPath = 0;
  345. hr = spPathname->Retrieve(ADS_FORMAT_X500, &bstrFullPath);
  346. if ( SUCCEEDED (hr) )
  347. {
  348. CComPtr<IDirectoryObject> spDirObj;
  349. hr = ADsOpenObjectHelper (bstrFullPath,
  350. IID_IDirectoryObject,
  351. 0,
  352. (void**)&spDirObj);
  353. if ( SUCCEEDED (hr) )
  354. {
  355. {
  356. //
  357. // Get "objectSid" attribute
  358. //
  359. const PWSTR wzAllowedAttributes = L"objectSid";
  360. PADS_ATTR_INFO pAttrs = 0;
  361. DWORD cAttrs = 0;
  362. LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes};
  363. hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
  364. if ( SUCCEEDED (hr) )
  365. {
  366. if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
  367. {
  368. for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++)
  369. {
  370. PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue;
  371. if ( pSid && IsValidSid (pSid) )
  372. {
  373. DWORD dwSidLen = GetLengthSid (pSid);
  374. PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
  375. if ( pSidCopy )
  376. {
  377. if ( CopySid (dwSidLen, pSidCopy, pSid) )
  378. {
  379. ASSERT (IsValidSid (pSidCopy));
  380. psidList.push_back (pSidCopy);
  381. }
  382. else
  383. {
  384. CoTaskMemFree (pSidCopy);
  385. hr = GetLastError ();
  386. _TRACE (0, L"CopySid () failed: 0x%x\n", hr);
  387. break;
  388. }
  389. }
  390. else
  391. {
  392. hr = E_OUTOFMEMORY;
  393. break;
  394. }
  395. }
  396. }
  397. }
  398. if ( pAttrs )
  399. FreeADsMem (pAttrs);
  400. }
  401. else
  402. {
  403. _TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
  404. }
  405. }
  406. if ( SUCCEEDED (hr) )
  407. {
  408. //
  409. // Get "tokenGroups" attribute
  410. //
  411. const PWSTR wzAllowedAttributes = L"tokenGroups";
  412. PADS_ATTR_INFO pAttrs = 0;
  413. DWORD cAttrs = 0;
  414. LPWSTR rgpwzAttrNames[] = {wzAllowedAttributes};
  415. hr = spDirObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
  416. if ( SUCCEEDED (hr) )
  417. {
  418. if ( 1 == cAttrs && pAttrs && pAttrs->pADsValues )
  419. {
  420. for (DWORD dwIdx = 0; dwIdx < pAttrs->dwNumValues; dwIdx++)
  421. {
  422. PSID pSid = pAttrs->pADsValues[dwIdx].OctetString.lpValue;
  423. if ( pSid && IsValidSid (pSid) )
  424. {
  425. DWORD dwSidLen = GetLengthSid (pSid);
  426. PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
  427. if ( pSidCopy )
  428. {
  429. if ( CopySid (dwSidLen, pSidCopy, pSid) )
  430. {
  431. ASSERT (IsValidSid (pSidCopy));
  432. psidList.push_back (pSidCopy);
  433. }
  434. else
  435. {
  436. CoTaskMemFree (pSidCopy);
  437. hr = GetLastError ();
  438. _TRACE (0, L"CopySid () failed: 0x%x\n", hr);
  439. break;
  440. }
  441. }
  442. else
  443. {
  444. hr = E_OUTOFMEMORY;
  445. break;
  446. }
  447. }
  448. }
  449. }
  450. if ( pAttrs )
  451. FreeADsMem (pAttrs);
  452. }
  453. else
  454. {
  455. _TRACE (0, L"IDirectoryObject->GetObjectAttributes (): 0x%x\n", hr);
  456. }
  457. }
  458. }
  459. else
  460. {
  461. _TRACE (0, L"ADsOpenObjectHelper (%s) failed: 0x%x\n", bstrFullPath);
  462. }
  463. }
  464. else
  465. {
  466. _TRACE (0, L"IADsPathname->Retrieve () failed: 0x%x\n", hr);
  467. }
  468. }
  469. else
  470. {
  471. _TRACE (0, L"IADsPathname->Set (%s): 0x%x\n",
  472. strObjectDN.c_str (), hr);
  473. }
  474. }
  475. else
  476. {
  477. _TRACE (0, L"IADsPathname->Set (%s): 0x%x\n", ACLDIAG_LDAP, hr);
  478. }
  479. }
  480. else
  481. {
  482. _TRACE (0, L"CoCreateInstance(CLSID_Pathname) failed: 0x%x\n", hr);
  483. }
  484. _TRACE (-1, L"Leaving GetTokenGroups: 0x%x\n", hr);
  485. return hr;
  486. }
  487. HRESULT ProcessObject (
  488. const wstring& strObjectDN, // object having permissions on the
  489. // target object
  490. POBJECT_TYPE_LIST pObjectTypeList, // class, property and property set
  491. // GUIDs of target object
  492. size_t objectTypeListLength,// number of elements in pObjectTypeList
  493. PSID principalSelfSid,
  494. const wstring& strDownlevelName)
  495. {
  496. _TRACE (1, L"Entering ProcessObject\n");
  497. HRESULT hr = S_OK;
  498. list<PSID> psidList; // sid of strObjectDN and all groups of which it is a member
  499. hr = GetTokenGroups (strObjectDN, psidList);
  500. if ( SUCCEEDED (hr) )
  501. {
  502. PACL pDacl = 0;
  503. BOOL bDaclPresent = FALSE;
  504. BOOL bDaclDefaulted = FALSE;
  505. if ( GetSecurityDescriptorDacl (_Module.m_pSecurityDescriptor,
  506. &bDaclPresent, &pDacl, &bDaclDefaulted) )
  507. {
  508. PIOBJECT_TYPE_LIST LocalTypeList = 0;
  509. //
  510. // Capture any Object type list
  511. //
  512. NTSTATUS Status = SeCaptureObjectTypeList( pObjectTypeList,
  513. objectTypeListLength,
  514. &LocalTypeList);
  515. if ( NT_SUCCESS(Status) )
  516. {
  517. hr = SepMaximumAccessCheck (psidList,
  518. pDacl,
  519. principalSelfSid,
  520. objectTypeListLength,
  521. LocalTypeList,
  522. objectTypeListLength);
  523. if ( !_Module.DoTabDelimitedOutput () )
  524. {
  525. wstring str;
  526. FormatMessage (str, L"\n%1:\n\n", strDownlevelName.c_str ());
  527. MyWprintf (str.c_str ());
  528. }
  529. vector<PCResultObject> resultList;
  530. for (DWORD idx = 0; idx < objectTypeListLength; idx++)
  531. {
  532. EnumerateEffectivePermissions (strDownlevelName,
  533. LocalTypeList[idx], P_ALLOW, resultList);
  534. EnumerateEffectivePermissions (strDownlevelName,
  535. LocalTypeList[idx], P_DENY, resultList);
  536. }
  537. // Sort LocalTypeList
  538. // 1. Object Level Rights
  539. // 2. Property Level Rights
  540. // a. Create
  541. // b. Delete
  542. // c. Read
  543. // d. Write
  544. // 3. Control Rights
  545. sort (resultList.begin (), resultList.end (), compare_resultObject);
  546. ACCESS_MASK lastRight = 0;
  547. for (vector<PCResultObject>::iterator itr = resultList.begin ();
  548. itr != resultList.end (); itr++)
  549. {
  550. PCResultObject pResultObject = *itr;
  551. if ( lastRight != pResultObject->GetRight () )
  552. {
  553. lastRight = pResultObject->GetRight ();
  554. if ( !_Module.DoTabDelimitedOutput () )
  555. PrintEffectiveRightsHeader (lastRight, pResultObject->GetLevel ());
  556. }
  557. pResultObject->PrintResult ();
  558. delete pResultObject;
  559. }
  560. }
  561. if ( LocalTypeList )
  562. delete [] LocalTypeList;
  563. }
  564. // Free memory pointed to by psidList members
  565. for (list<PSID>::iterator itr = psidList.begin ();
  566. itr != psidList.end ();
  567. itr++)
  568. {
  569. CoTaskMemFree (*itr);
  570. }
  571. }
  572. _TRACE (-1, L"Leaving ProcessObject: 0x%x\n", hr);
  573. return hr;
  574. }
  575. ///////////////////////////////////////////////////////////////////////////////
  576. //
  577. // Method: EnumerateEffectivePermissions ()
  578. //
  579. // Purpose: Print all the permissions contained on the passed in ACE
  580. //
  581. // Inputs: otl - structure containing the ACE whose permissions we wish
  582. // to print
  583. //
  584. // ptype - allow, deny, succes, failure, success and failure
  585. //
  586. HRESULT EnumerateEffectivePermissions (
  587. const wstring& strObjectDN,
  588. const IOBJECT_TYPE_LIST& otl,
  589. const P_TYPE ptype,
  590. vector<PCResultObject>& resultList)
  591. {
  592. HRESULT hr = S_OK;
  593. hr = DisplayEffectivePermission (strObjectDN,
  594. otl,
  595. ACTRL_DS_CREATE_CHILD,
  596. ptype,
  597. IDS_CREATE_ALL_SUBOBJECTS_ER,
  598. IDS_CREATE_CLASS_OBJECTS_ER,
  599. IDS_CREATE_CLASS_OBJECTS,
  600. resultList);
  601. if ( SUCCEEDED (hr) )
  602. {
  603. hr = DisplayEffectivePermission (strObjectDN,
  604. otl,
  605. ACTRL_DS_DELETE_CHILD,
  606. ptype,
  607. IDS_DELETE_ALL_SUBOBJECTS_ER,
  608. IDS_DELETE_CLASS_OBJECTS_ER,
  609. IDS_DELETE_CLASS_OBJECTS,
  610. resultList);
  611. }
  612. if ( SUCCEEDED (hr) )
  613. {
  614. hr = DisplayEffectivePermission (strObjectDN,
  615. otl,
  616. ACTRL_DS_READ_PROP,
  617. ptype,
  618. IDS_READ_ALL_PROPERTIES_ER,
  619. IDS_READ_PROPERTY_PROPERTY_ER,
  620. IDS_READ_PROPERTY_PROPERTY,
  621. resultList);
  622. }
  623. if ( SUCCEEDED (hr) )
  624. {
  625. hr = DisplayEffectivePermission (strObjectDN,
  626. otl,
  627. ACTRL_DS_WRITE_PROP,
  628. ptype,
  629. IDS_WRITE_ALL_PROPERTIES_ER,
  630. IDS_WRITE_PROPERTY_PROPERTY_ER,
  631. IDS_WRITE_PROPERTY_PROPERTY,
  632. resultList);
  633. }
  634. if ( SUCCEEDED (hr) )
  635. {
  636. hr = DisplayEffectivePermission (strObjectDN,
  637. otl,
  638. ACTRL_DS_LIST,
  639. ptype,
  640. IDS_LIST_CONTENTS_ER,
  641. resultList);
  642. }
  643. if ( SUCCEEDED (hr) )
  644. {
  645. hr = DisplayEffectivePermission (strObjectDN,
  646. otl,
  647. ACTRL_DS_LIST_OBJECT,
  648. ptype,
  649. IDS_LIST_OBJECT_ER,
  650. resultList);
  651. }
  652. if ( SUCCEEDED (hr) )
  653. {
  654. if ( otl.CurrentGranted & ACTRL_DS_CONTROL_ACCESS )
  655. hr = DisplayEffectivePermission (strObjectDN,
  656. otl,
  657. ACTRL_DS_CONTROL_ACCESS,
  658. ptype,
  659. IDS_ALL_CONTROL_ACCESSES_ER,
  660. IDS_CONTROL_ACCESS_DISPLAY_NAME,
  661. IDS_CONTROL_ACCESS_DISPLAY_NAME,
  662. resultList);
  663. }
  664. if ( SUCCEEDED (hr) )
  665. {
  666. hr = DisplayEffectivePermission (strObjectDN,
  667. otl,
  668. ACTRL_DELETE,
  669. ptype,
  670. IDS_DELETE_THIS_OBJECT_ER,
  671. resultList);
  672. }
  673. if ( SUCCEEDED (hr) )
  674. {
  675. hr = DisplayEffectivePermission (strObjectDN,
  676. otl,
  677. ACTRL_READ_CONTROL,
  678. ptype,
  679. IDS_READ_PERMISSIONS_ER,
  680. resultList);
  681. }
  682. if ( SUCCEEDED (hr) )
  683. {
  684. hr = DisplayEffectivePermission (strObjectDN,
  685. otl,
  686. ACTRL_CHANGE_ACCESS,
  687. ptype,
  688. IDS_MODIFY_PERMISSIONS_ER,
  689. resultList);
  690. }
  691. if ( SUCCEEDED (hr) )
  692. {
  693. hr = DisplayEffectivePermission (strObjectDN,
  694. otl,
  695. ACTRL_CHANGE_OWNER,
  696. ptype,
  697. IDS_TAKE_CHANGE_OWNERSHIP_ER,
  698. resultList);
  699. }
  700. if ( SUCCEEDED (hr) )
  701. {
  702. hr = DisplayEffectivePermission (strObjectDN,
  703. otl,
  704. ACTRL_DS_SELF,
  705. ptype,
  706. IDS_MODIFY_MEMBERSHIP_ER,
  707. resultList);
  708. }
  709. return hr;
  710. }
  711. ///////////////////////////////////////////////////////////////////////////////
  712. //
  713. // Method: DisplayEffectivePermission ()
  714. //
  715. // Purpose: Print an OBJECT_ACE_TYPE permission
  716. //
  717. // Inputs: otl - structure containing the ACE whose permission we wish
  718. // to print
  719. //
  720. // accessMask - the specific permission we're looking to print
  721. //
  722. // bAllow - whether the permission is allowed or denied
  723. //
  724. // strIDAll - string to print if permission applies to all object
  725. // classes
  726. //
  727. // strIDParam - string print if permission applies to a specific
  728. // object class
  729. //
  730. HRESULT DisplayEffectivePermission (const wstring& strObjectDN,
  731. const IOBJECT_TYPE_LIST& otl,
  732. const ACCESS_MASK accessMask,
  733. const P_TYPE ptype,
  734. const int strIDAll,
  735. const int strIDParam,
  736. const int strIDCDO,
  737. vector<PCResultObject>& resultList)
  738. {
  739. HRESULT hr = S_OK;
  740. wstring str;
  741. wstring strPermission;
  742. if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) ||
  743. ((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) )
  744. {
  745. wstring strGuidResult;
  746. GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
  747. _Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType);
  748. switch (guidType)
  749. {
  750. case GUID_TYPE_CLASS:
  751. FormatMessage (strPermission, strIDAll, strGuidResult.c_str ());
  752. break;
  753. case GUID_TYPE_ATTRIBUTE:
  754. switch (accessMask)
  755. {
  756. case ACTRL_DS_LIST:
  757. case ACTRL_DS_LIST_OBJECT:
  758. case ACTRL_DS_SELF:
  759. // case ACTRL_DS_CONTROL_ACCESS:
  760. return S_OK;
  761. default:
  762. if ( _Module.DoTabDelimitedOutput () )
  763. FormatMessage (strPermission, strIDCDO, strGuidResult.c_str ());
  764. else
  765. FormatMessage (strPermission, strIDParam, strGuidResult.c_str ());
  766. break;
  767. }
  768. break;
  769. case GUID_TYPE_CONTROL:
  770. switch (accessMask)
  771. {
  772. case ACTRL_DS_LIST:
  773. case ACTRL_DS_LIST_OBJECT:
  774. case ACTRL_DS_SELF:
  775. case ACTRL_DS_CREATE_CHILD:
  776. case ACTRL_DS_DELETE_CHILD:
  777. case ACTRL_DELETE:
  778. case ACTRL_CHANGE_ACCESS:
  779. case ACTRL_CHANGE_OWNER:
  780. case ACTRL_DS_CONTROL_ACCESS:
  781. return S_OK;
  782. case ACTRL_DS_READ_PROP:
  783. case ACTRL_DS_WRITE_PROP:
  784. case ACTRL_READ_CONTROL:
  785. default:
  786. FormatMessage (strPermission, strIDParam, strGuidResult.c_str ());
  787. break;
  788. }
  789. break;
  790. case GUID_TYPE_UNKNOWN:
  791. default:
  792. return E_UNEXPECTED;
  793. }
  794. int strid = 0;
  795. switch (ptype)
  796. {
  797. case P_ALLOW:
  798. if ( _Module.DoTabDelimitedOutput () )
  799. strid = IDS_CAN_CDO;
  800. else
  801. strid = IDS_CAN_ER;
  802. break;
  803. case P_DENY:
  804. if ( _Module.DoTabDelimitedOutput () )
  805. strid = IDS_CANNOT_CDO;
  806. else
  807. strid = IDS_CANNOT_EF;
  808. break;
  809. default:
  810. return E_UNEXPECTED;
  811. }
  812. if ( _Module.DoTabDelimitedOutput () )
  813. {
  814. FormatMessage (str, strid,
  815. strObjectDN.c_str (),
  816. strPermission.c_str ());
  817. }
  818. else
  819. {
  820. FormatMessage (str, strid,
  821. strPermission.c_str ());
  822. }
  823. wstring strProvenance;
  824. PrintGroupProvenance (accessMask, otl, ptype, strProvenance);
  825. str += strProvenance;
  826. PCResultObject pResultObject = new CResultObject (accessMask, str,
  827. guidType, otl.Level);
  828. if ( pResultObject )
  829. {
  830. if ( pResultObject->IsValid () )
  831. resultList.push_back (pResultObject);
  832. else
  833. delete pResultObject;
  834. }
  835. else
  836. hr = E_OUTOFMEMORY;
  837. }
  838. return hr;
  839. }
  840. ///////////////////////////////////////////////////////////////////////////////
  841. //
  842. // Method: DisplayEffectivePermission ()
  843. //
  844. // Purpose: Print a non-OBJECT_ACE_TYPE permission
  845. //
  846. // Inputs: otl - structure containing the ACE whose permission we wish
  847. // to print
  848. //
  849. // accessMask - the specific permission we're looking to print
  850. //
  851. // bAllow - whether the permission is allowed or denied
  852. //
  853. // strID - string to print
  854. //
  855. HRESULT DisplayEffectivePermission (
  856. const wstring& strObjectDN,
  857. const IOBJECT_TYPE_LIST& otl,
  858. const ACCESS_MASK accessMask,
  859. const P_TYPE ptype,
  860. const int strID,
  861. vector<PCResultObject>& resultList)
  862. {
  863. HRESULT hr = S_OK;
  864. wstring str;
  865. wstring strPermission;
  866. if ( ((P_ALLOW == ptype) && (otl.CurrentGranted & accessMask)) ||
  867. ((P_DENY == ptype) && (otl.CurrentDenied & accessMask)) )
  868. {
  869. wstring strGuidResult;
  870. GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
  871. wstring strType;
  872. _Module.GetClassFromGUID (otl.ObjectType, strGuidResult, &guidType);
  873. switch (guidType)
  874. {
  875. case GUID_TYPE_CLASS:
  876. LoadFromResource (strType, IDS_CLASS);
  877. break;
  878. case GUID_TYPE_ATTRIBUTE:
  879. switch (accessMask)
  880. {
  881. case ACTRL_DS_LIST:
  882. case ACTRL_DS_LIST_OBJECT:
  883. case ACTRL_DS_SELF:
  884. return S_OK;
  885. default:
  886. LoadFromResource (strType, IDS_PROPERTY);
  887. break;
  888. }
  889. break;
  890. case GUID_TYPE_CONTROL:
  891. switch (accessMask)
  892. {
  893. case ACTRL_DS_LIST:
  894. case ACTRL_DS_LIST_OBJECT:
  895. case ACTRL_DS_SELF:
  896. case ACTRL_DS_CREATE_CHILD:
  897. case ACTRL_DS_DELETE_CHILD:
  898. case ACTRL_DELETE:
  899. case ACTRL_CHANGE_ACCESS:
  900. case ACTRL_CHANGE_OWNER:
  901. case ACTRL_DS_CONTROL_ACCESS:
  902. return S_OK;
  903. case ACTRL_DS_READ_PROP:
  904. case ACTRL_DS_WRITE_PROP:
  905. case ACTRL_READ_CONTROL:
  906. default:
  907. LoadFromResource (strType, IDS_CONTROL);
  908. break;
  909. }
  910. break;
  911. case GUID_TYPE_UNKNOWN:
  912. default:
  913. return E_UNEXPECTED;
  914. }
  915. LoadFromResource (strPermission, strID);
  916. int id = 0;
  917. switch (ptype)
  918. {
  919. case P_ALLOW:
  920. if ( _Module.DoTabDelimitedOutput () )
  921. id = IDS_CAN_CDO;
  922. else
  923. id = IDS_CAN;
  924. break;
  925. case P_DENY:
  926. if ( _Module.DoTabDelimitedOutput () )
  927. id = IDS_CANNOT_CDO;
  928. else
  929. id = IDS_CANNOT_EF;
  930. break;
  931. default:
  932. return E_UNEXPECTED;
  933. }
  934. if ( _Module.DoTabDelimitedOutput () )
  935. {
  936. FormatMessage (str, id,
  937. strObjectDN.c_str (),
  938. strPermission.c_str ());
  939. }
  940. else
  941. {
  942. FormatMessage (str, id, strPermission.c_str ());
  943. }
  944. wstring strProvenance;
  945. PrintGroupProvenance (accessMask, otl, ptype, strProvenance);
  946. str += strProvenance;
  947. PCResultObject pResultObject = new CResultObject (accessMask, str,
  948. guidType, otl.Level);
  949. if ( pResultObject )
  950. {
  951. if ( pResultObject->IsValid () )
  952. resultList.push_back (pResultObject);
  953. else
  954. delete pResultObject;
  955. }
  956. else
  957. hr = E_OUTOFMEMORY;
  958. }
  959. return hr;
  960. }
  961. void PrintGroupProvenance (
  962. const ACCESS_MASK accessMask,
  963. const IOBJECT_TYPE_LIST& otl,
  964. const P_TYPE ptype,
  965. wstring& strProvenance)
  966. {
  967. UINT nSid = 0;
  968. for (ULONG nBit = 0x1; nBit; nBit <<= 1, nSid++)
  969. {
  970. if ( accessMask & nBit )
  971. {
  972. wstring strGroup;
  973. PSID psid = 0;
  974. SID_NAME_USE sne = SidTypeUnknown;
  975. if ( P_ALLOW == ptype )
  976. psid = otl.grantingSid[nSid];
  977. else
  978. psid = otl.denyingSid[nSid];
  979. if ( IsValidSid (psid) )
  980. {
  981. GetNameFromSid (psid, strGroup, 0, sne);
  982. if ( SidTypeGroup == sne )
  983. {
  984. if ( _Module.DoTabDelimitedOutput () )
  985. FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP_CDO, strGroup.c_str ());
  986. else
  987. FormatMessage (strProvenance, IDS_EFFRIGHT_FROM_GROUP, strGroup.c_str ());
  988. }
  989. }
  990. break;
  991. }
  992. }
  993. strProvenance += L"\n";
  994. }
  995. void PrintEffectiveRightsHeader (ACCESS_MASK lastRight, USHORT level)
  996. {
  997. wstring str;
  998. if ( 0 == level ) // Object level rights
  999. {
  1000. return;
  1001. }
  1002. else
  1003. {
  1004. switch (lastRight)
  1005. {
  1006. case ACTRL_DS_LIST:
  1007. case ACTRL_DELETE:
  1008. case ACTRL_READ_CONTROL:
  1009. case ACTRL_CHANGE_ACCESS:
  1010. case ACTRL_CHANGE_OWNER:
  1011. str = L"\n\n";
  1012. break;
  1013. case ACTRL_DS_CREATE_CHILD:
  1014. LoadFromResource (str, IDS_CAN_CREATE_FOLLOWING_CHILD_OBJECTS);
  1015. break;
  1016. case ACTRL_DS_DELETE_CHILD:
  1017. LoadFromResource (str, IDS_CAN_DELETE_FOLLOWING_CHILD_OBJECTS);
  1018. break;
  1019. case ACTRL_DS_READ_PROP:
  1020. LoadFromResource (str, IDS_CAN_READ_FOLLOWING_PROPERTIES);
  1021. break;
  1022. case ACTRL_DS_WRITE_PROP:
  1023. LoadFromResource (str, IDS_CAN_WRITE_FOLLOWING_PROPERTIES);
  1024. break;
  1025. case ACTRL_DS_CONTROL_ACCESS:
  1026. LoadFromResource (str, IDS_CAN_DO_FOLLOWING_CONTROL_OPERATIONS);
  1027. break;
  1028. case ACTRL_DS_LIST_OBJECT:
  1029. case ACTRL_DS_SELF:
  1030. default:
  1031. str = L"\n\n";
  1032. break;;
  1033. }
  1034. }
  1035. MyWprintf (str.c_str ());
  1036. }