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.

613 lines
21 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: ChkDeleg.cpp
  7. //
  8. // Contents: CheckDelegation and support methods
  9. //
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "stdafx.h"
  13. #include <conio.h>
  14. #include <aclapi.h>
  15. #include "adutils.h"
  16. #include <util.h>
  17. #include "ChkDeleg.h"
  18. #include <deltempl.h>
  19. #include <tempcore.h>
  20. #include "SecDesc.h"
  21. #include <sddl.h>
  22. #include <dscmn.h> // from the admin\display project (CrackName)
  23. #ifndef ARRAYSIZE
  24. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  25. #endif
  26. #include <_util.cpp>
  27. #include <_tempcor.cpp>
  28. #include <_deltemp.cpp>
  29. class CTemplateAccessPermissionsHolderManagerVerify : public CTemplateAccessPermissionsHolderManager
  30. {
  31. public:
  32. HRESULT ProcessTemplates (); // for ACLDiag - process each template in turn
  33. HRESULT ProcessPermissions(
  34. const wstring& strObjectClass,
  35. CTemplate* pTemplate,
  36. PACL pAccessList,
  37. CPrincipalList& principalList);
  38. };
  39. HRESULT CheckDelegation ()
  40. {
  41. _TRACE (1, L"Entering CheckDelegation\n");
  42. HRESULT hr = S_OK;
  43. wstring str;
  44. if ( !_Module.DoTabDelimitedOutput () )
  45. {
  46. LoadFromResource (str, IDS_DELEGATION_TEMPLATE_DIAGNOSIS);
  47. MyWprintf (str.c_str ());
  48. }
  49. CTemplateAccessPermissionsHolderManagerVerify templateAccessPermissionsHolderManager;
  50. if ( templateAccessPermissionsHolderManager.LoadTemplates() )
  51. {
  52. hr = templateAccessPermissionsHolderManager.ProcessTemplates ();
  53. }
  54. else
  55. {
  56. LoadFromResource (str, IDS_FAILED_TO_LOAD_TEMPLATES);
  57. MyWprintf (str.c_str ());
  58. hr = E_FAIL;
  59. }
  60. _TRACE (-1, L"Leaving CheckDelegation: 0x%x\n", hr);
  61. return hr;
  62. }
  63. PTOKEN_USER EfspGetTokenUser ()
  64. {
  65. _TRACE (1, L"Entering EfspGetTokenUser\n");
  66. HANDLE hToken = 0;
  67. DWORD dwReturnLength = 0;
  68. PTOKEN_USER pTokenUser = NULL;
  69. BOOL bResult = ::OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &hToken);
  70. if ( bResult )
  71. {
  72. bResult = ::GetTokenInformation (
  73. hToken,
  74. TokenUser,
  75. NULL,
  76. 0,
  77. &dwReturnLength
  78. );
  79. if ( !bResult && dwReturnLength > 0 )
  80. {
  81. pTokenUser = (PTOKEN_USER) malloc (dwReturnLength);
  82. if (pTokenUser)
  83. {
  84. bResult = GetTokenInformation (
  85. hToken,
  86. TokenUser,
  87. pTokenUser,
  88. dwReturnLength,
  89. &dwReturnLength
  90. );
  91. if ( !bResult)
  92. {
  93. DWORD dwErr = GetLastError ();
  94. _TRACE (0, L"GetTokenInformation () failed: 0x%x\n", dwErr);
  95. free (pTokenUser);
  96. pTokenUser = NULL;
  97. }
  98. }
  99. }
  100. else
  101. {
  102. DWORD dwErr = GetLastError ();
  103. _TRACE (0, L"GetTokenInformation () failed: 0x%x\n", dwErr);
  104. }
  105. ::CloseHandle (hToken);
  106. }
  107. else
  108. {
  109. DWORD dwErr = GetLastError ();
  110. _TRACE (0, L"OpenProcessToken () failed: 0x%x\n", dwErr);
  111. }
  112. _TRACE (-1, L"Leaving EfspGetTokenUser\n");
  113. return pTokenUser;
  114. }
  115. HRESULT CTemplateAccessPermissionsHolderManagerVerify::ProcessTemplates ()
  116. {
  117. HRESULT hr = S_OK;
  118. DWORD dwErr = 0;
  119. // the access list is read in, modified, written back
  120. // If /fixdeleg is on, this list will be populated from the DS,
  121. // will receive the permissions associated with selected templates is the
  122. // user chooses to fix delegation, and then will be written back to the DS.
  123. PACL pFixDACL = NULL;
  124. LPCWSTR lpszObjectLdapPath = _Module.m_adsiObject.GetLdapPath();
  125. // get the security info
  126. if ( _Module.FixDelegation () && !_Module.DoTabDelimitedOutput () )
  127. {
  128. _TRACE (0, L"calling GetNamedSecurityInfo(%s, ...)\n", lpszObjectLdapPath);
  129. dwErr = ::GetNamedSecurityInfo (
  130. (LPWSTR) lpszObjectLdapPath, // name of the object
  131. SE_DS_OBJECT_ALL, // type of object
  132. DACL_SECURITY_INFORMATION, // type of security information to retrieve
  133. NULL, // receives a pointer to the owner SID
  134. NULL, // receives a pointer to the primary group SID
  135. &pFixDACL, // receives a pointer to the DACL
  136. NULL, // receives a pointer to the SACL
  137. NULL); // receives a pointer to the security descriptor
  138. if (dwErr != ERROR_SUCCESS)
  139. {
  140. _TRACE (0, L"failed on GetNamedSecurityInfo(): dwErr = 0x%x\n", dwErr);
  141. wstring str;
  142. LoadFromResource (str, IDS_DELEGWIZ_ERR_GET_SEC_INFO);
  143. MyWprintf (str.c_str ());
  144. _Module.TurnOffFixDelegation ();
  145. }
  146. }
  147. CPrincipal principal; // a dummy placeholder for us to get
  148. // the incremental rights associated
  149. // with each template
  150. // We will use the current logged-in user as a placeholder only.
  151. PTOKEN_USER pTokenUser = ::EfspGetTokenUser ();
  152. if ( pTokenUser )
  153. {
  154. hr = principal.Initialize (pTokenUser->User.Sid);
  155. free (pTokenUser);
  156. }
  157. if ( SUCCEEDED (hr) )
  158. {
  159. CTemplateList* pList = m_templateManager.GetTemplateList();
  160. for (CTemplateList::iterator itr = pList->begin(); itr != pList->end(); itr++)
  161. {
  162. CTemplate* pTemplate = *itr;
  163. ASSERT(pTemplate != NULL);
  164. // Select the templates one at a time to get the
  165. // permissions representing them
  166. pTemplate->m_bSelected = TRUE;
  167. if ( InitPermissionHoldersFromSelectedTemplates (
  168. &_Module.m_classInfoArray,
  169. &_Module.m_adsiObject) )
  170. {
  171. // This access list will contain only the access control values
  172. // associated with the selected template
  173. PACL pAccessList = 0; //(PACL) ::LocalAlloc (LMEM_ZEROINIT, sizeof (ACL));
  174. if ( 1 ) //pAccessList )
  175. {
  176. DWORD dwErr = UpdateAccessList (
  177. &principal,
  178. _Module.m_adsiObject.GetServerName(),
  179. _Module.m_adsiObject.GetPhysicalSchemaNamingContext(),
  180. &pAccessList
  181. );
  182. if ( 0 == dwErr )
  183. {
  184. CPrincipalList principalList;
  185. PSID pSid = principal.GetSid ();
  186. SID_NAME_USE sne = SidTypeUnknown;
  187. wstring strPrincipalName;
  188. hr = GetNameFromSid (pSid, strPrincipalName, 0, sne);
  189. if ( SUCCEEDED (hr) )
  190. {
  191. hr = ProcessPermissions (_Module.m_adsiObject.GetClass (),
  192. pTemplate, pAccessList, principalList);
  193. if ( SUCCEEDED (hr) && _Module.FixDelegation () && !_Module.DoTabDelimitedOutput () )
  194. {
  195. // loop thru all the principals and classes
  196. CPrincipalList::iterator i;
  197. for (i = principalList.begin(); i != principalList.end(); ++i)
  198. {
  199. CPrincipal* pCurrPrincipal = (*i);
  200. dwErr = UpdateAccessList(
  201. pCurrPrincipal,
  202. _Module.m_adsiObject.GetServerName(),
  203. _Module.m_adsiObject.GetPhysicalSchemaNamingContext(),
  204. &pFixDACL);
  205. if (dwErr != 0)
  206. break;
  207. } // for pCurrPrincipal
  208. }
  209. }
  210. }
  211. ::LocalFree (pAccessList);
  212. }
  213. else
  214. {
  215. hr = E_OUTOFMEMORY;
  216. break;
  217. }
  218. }
  219. pTemplate->m_bSelected = FALSE;
  220. }
  221. if ( _Module.FixDelegation () && !_Module.DoTabDelimitedOutput () )
  222. {
  223. // commit changes
  224. _TRACE (0, L"calling SetNamedSecurityInfo(%s, ...)\n", lpszObjectLdapPath);
  225. dwErr = ::SetNamedSecurityInfoW(
  226. (LPWSTR) lpszObjectLdapPath,
  227. SE_DS_OBJECT_ALL,
  228. DACL_SECURITY_INFORMATION,
  229. NULL,
  230. NULL,
  231. pFixDACL,
  232. 0);
  233. if (dwErr != ERROR_SUCCESS)
  234. {
  235. _TRACE (0, L"failed on SetNamedSecurityInfo(): dwErr = 0x%x\n", dwErr);
  236. wstring str;
  237. LoadFromResource (str, IDS_DELEGWIZ_ERR_SET_SEC_INFO);
  238. MyWprintf (str.c_str ());
  239. }
  240. }
  241. }
  242. if ( pFixDACL )
  243. ::LocalFree (pFixDACL);
  244. return hr;
  245. }
  246. class CTemplateStatus
  247. {
  248. public:
  249. CTemplateStatus () :
  250. m_nACECnt (1),
  251. m_bApplies (false),
  252. m_bInherited (false)
  253. {
  254. }
  255. ULONG m_nACECnt;
  256. bool m_bApplies;
  257. bool m_bInherited;
  258. wstring m_strObjName;
  259. PSID m_psid;
  260. };
  261. typedef list<CTemplateStatus*> CStatusList;
  262. HRESULT CTemplateAccessPermissionsHolderManagerVerify::ProcessPermissions(
  263. const wstring& strObjectClass,
  264. CTemplate* pTemplate,
  265. PACL pDacl,
  266. CPrincipalList& principalList)
  267. {
  268. if ( !pTemplate )
  269. return E_POINTER;
  270. HRESULT hr = S_OK;
  271. CStatusList statusList; // This list will contain 1 entry for each
  272. // SidStart/bInherited/bApplies triplet.
  273. // The counter for each item will incremented
  274. // each time an ACE is found that belongs to
  275. // the object pointed to by the SidStart.
  276. ULONG nExpectedCnt = 0;
  277. bool bApplies = pTemplate->AppliesToClass(strObjectClass.c_str ()) ? true : false;
  278. ACE_SAMNAME* pAceSAMName = 0;
  279. // Look in global DACL for each right
  280. PACCESS_ALLOWED_ACE pAllowedAce = 0;
  281. // iterate through the template ACES
  282. for (int i = 0; i < pDacl->AceCount; i++)
  283. {
  284. if ( GetAce (pDacl, i, (void **)&pAllowedAce) )
  285. {
  286. PSID AceSid = 0;
  287. if ( IsObjectAceType ( pAllowedAce ) )
  288. {
  289. AceSid = RtlObjectAceSid( pAllowedAce );
  290. }
  291. else
  292. {
  293. AceSid = &( ( PKNOWN_ACE )pAllowedAce )->SidStart;
  294. }
  295. ASSERT (IsValidSid (AceSid));
  296. if ( !IsValidSid (AceSid) )
  297. continue;
  298. // wstring strPrincipalName;
  299. // SID_NAME_USE sne = SidTypeUnknown;
  300. // hr = GetNameFromSid (AceSid, strPrincipalName, 0, sne);
  301. // if ( SUCCEEDED (hr) )
  302. {
  303. ACE_SAMNAME* pAceTemplate = new ACE_SAMNAME;
  304. if ( pAceTemplate )
  305. {
  306. pAceTemplate->m_AceType = pAllowedAce->Header.AceType;
  307. switch (pAceTemplate->m_AceType)
  308. {
  309. case ACCESS_ALLOWED_ACE_TYPE:
  310. pAceTemplate->m_pAllowedAce = pAllowedAce;
  311. break;
  312. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  313. pAceTemplate->m_pAllowedObjectAce =
  314. reinterpret_cast <PACCESS_ALLOWED_OBJECT_ACE> (pAllowedAce);
  315. break;
  316. case ACCESS_DENIED_ACE_TYPE:
  317. pAceTemplate->m_pDeniedAce =
  318. reinterpret_cast <PACCESS_DENIED_ACE> (pAllowedAce);
  319. break;
  320. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  321. pAceTemplate->m_pDeniedObjectAce =
  322. reinterpret_cast <PACCESS_DENIED_OBJECT_ACE> (pAllowedAce);
  323. break;
  324. default:
  325. break;
  326. }
  327. // pAceTemplate->m_SAMAccountName = strPrincipalName;
  328. pAceTemplate->DebugOut ();
  329. nExpectedCnt++;
  330. ACE_SAMNAME_LIST::iterator itr = _Module.m_DACLList.begin ();
  331. for (; itr != _Module.m_DACLList.end () && SUCCEEDED (hr); itr++)
  332. {
  333. pAceSAMName = *itr;
  334. // to neutralize Sid differences
  335. pAceTemplate->m_SAMAccountName = pAceSAMName->m_SAMAccountName;
  336. if ( *pAceSAMName == *pAceTemplate )
  337. {
  338. bool bFound = false;
  339. CTemplateStatus* pStatus = 0;
  340. CStatusList::iterator itr = statusList.begin ();
  341. wstring strObjName;
  342. PSID psid = 0;
  343. if ( ACCESS_ALLOWED_OBJECT_ACE_TYPE == pAceSAMName->m_AceType )
  344. {
  345. psid = RtlObjectAceSid (pAceSAMName->m_pAllowedObjectAce);
  346. }
  347. else
  348. {
  349. psid = &( ( PKNOWN_ACE )pAceSAMName->m_pAllowedAce )->SidStart;
  350. }
  351. SID_NAME_USE sne = SidTypeUnknown;
  352. hr = GetNameFromSid (psid, strObjName, 0, sne);
  353. if ( SUCCEEDED (hr) )
  354. {
  355. for (; itr != statusList.end (); itr++)
  356. {
  357. pStatus = *itr;
  358. if ( (pStatus->m_bApplies == bApplies) &&
  359. ( pStatus->m_bInherited == pAceSAMName->IsInherited () ) &&
  360. ( !_wcsicmp (
  361. pStatus->m_strObjName.c_str (),
  362. strObjName.c_str ())) )
  363. {
  364. bFound = true;
  365. break;
  366. }
  367. }
  368. if ( bFound )
  369. {
  370. pStatus->m_nACECnt++;
  371. }
  372. else
  373. {
  374. pStatus = new CTemplateStatus;
  375. if ( pStatus )
  376. {
  377. pStatus->m_strObjName = strObjName;
  378. pStatus->m_bApplies = bApplies;
  379. pStatus->m_bInherited = pAceSAMName->IsInherited ();
  380. pStatus->m_psid = psid;
  381. statusList.push_back (pStatus);
  382. }
  383. else
  384. {
  385. hr = E_OUTOFMEMORY;
  386. break;
  387. }
  388. }
  389. }
  390. }
  391. }
  392. }
  393. else
  394. {
  395. hr = E_OUTOFMEMORY;
  396. break;
  397. }
  398. }
  399. }
  400. }
  401. // Now, iterate thru status list and evaluate each item
  402. // If the list is empty, then this template is not present.
  403. // Otherwise, for each present item, if the class and attr count is less than the required count
  404. // the template is partial for the item.
  405. // Otherwise, it is OK.
  406. CStatusList::iterator itr = statusList.begin ();
  407. CTemplateStatus* pStatus = 0;
  408. wstring str;
  409. wstring strStatus;
  410. for (; itr != statusList.end () && SUCCEEDED (hr); itr++)
  411. {
  412. pStatus = *itr;
  413. // Print template description
  414. bool bMisconfigured = false;
  415. if ( _Module.DoTabDelimitedOutput () )
  416. {
  417. FormatMessage (str, IDS_DELEGATION_TITLE_CDO, pTemplate->GetDescription (),
  418. pStatus->m_strObjName.c_str ());
  419. }
  420. else
  421. {
  422. FormatMessage (str, IDS_DELEGATION_TITLE, pTemplate->GetDescription (),
  423. pStatus->m_strObjName.c_str ());
  424. }
  425. MyWprintf (str.c_str ());
  426. // Print "Status: OK/MISCONFIGURED"
  427. if ( pStatus->m_nACECnt < nExpectedCnt )
  428. {
  429. LoadFromResource (strStatus, IDS_MISCONFIGURED);
  430. bMisconfigured = true;
  431. }
  432. else
  433. LoadFromResource (strStatus, IDS_OK);
  434. if ( _Module.DoTabDelimitedOutput () )
  435. FormatMessage (str, IDS_DELTEMPL_STATUS_CDO, strStatus.c_str ());
  436. else
  437. FormatMessage (str, IDS_DELTEMPL_STATUS, strStatus.c_str ());
  438. MyWprintf (str.c_str ());
  439. // Print "Applies on this object: YES/NO"
  440. if ( pStatus->m_bApplies )
  441. {
  442. LoadFromResource (strStatus,
  443. _Module.DoTabDelimitedOutput () ? IDS_APPLIES : IDS_YES);
  444. }
  445. else
  446. {
  447. LoadFromResource (strStatus,
  448. _Module.DoTabDelimitedOutput () ? IDS_DOES_NOT_APPLY : IDS_NO);
  449. }
  450. if ( _Module.DoTabDelimitedOutput () )
  451. FormatMessage (str, IDS_APPLIES_ON_THIS_OBJECT_CDO, strStatus.c_str ());
  452. else
  453. FormatMessage (str, IDS_APPLIES_ON_THIS_OBJECT, strStatus.c_str ());
  454. MyWprintf (str.c_str ());
  455. // Print "Inherited from parent: YES/NO"
  456. if ( pStatus->m_bInherited )
  457. {
  458. LoadFromResource (strStatus,
  459. _Module.DoTabDelimitedOutput () ? IDS_INHERITED : IDS_YES);
  460. }
  461. else
  462. {
  463. LoadFromResource (strStatus,
  464. _Module.DoTabDelimitedOutput () ? IDS_EXPLICIT : IDS_NO);
  465. }
  466. if ( _Module.DoTabDelimitedOutput () )
  467. FormatMessage (str, IDS_INHERITED_FROM_PARENT_CDO, strStatus.c_str ());
  468. else
  469. FormatMessage (str, IDS_INHERITED_FROM_PARENT, strStatus.c_str ());
  470. MyWprintf (str.c_str ());
  471. if ( bMisconfigured && _Module.FixDelegation () && !_Module.DoTabDelimitedOutput () )
  472. {
  473. LoadFromResource (str, IDS_FIX_DELEGATION_QUERY);
  474. while (1)
  475. {
  476. MyWprintf (str.c_str ());
  477. int ch = _getche ();
  478. if ( 'y' == ch )
  479. {
  480. CPrincipal* pPrincipal = new CPrincipal;
  481. if ( pPrincipal )
  482. {
  483. if ( SUCCEEDED (pPrincipal->Initialize (pStatus->m_psid)) )
  484. principalList.push_back (pPrincipal);
  485. else
  486. delete pPrincipal;
  487. }
  488. else
  489. hr = E_OUTOFMEMORY;
  490. MyWprintf (L"\n\n");
  491. break;
  492. }
  493. else if ( 'n' == ch )
  494. {
  495. MyWprintf (L"\n\n");
  496. break;
  497. }
  498. else
  499. {
  500. MyWprintf (L"\n");
  501. continue;
  502. }
  503. }
  504. }
  505. }
  506. if ( !pStatus ) // None found
  507. {
  508. // Print template description
  509. if ( _Module.DoTabDelimitedOutput () )
  510. {
  511. FormatMessage (str, IDS_DELEGATION_NOT_FOUND_CDO,
  512. pTemplate->GetDescription ());
  513. MyWprintf (str.c_str ());
  514. }
  515. else
  516. {
  517. FormatMessage (str, L"\t%1\n\n", pTemplate->GetDescription ());
  518. MyWprintf (str.c_str ());
  519. LoadFromResource (strStatus, IDS_NOT_PRESENT);
  520. FormatMessage (str, IDS_DELTEMPL_STATUS, strStatus.c_str ());
  521. MyWprintf (str.c_str ());
  522. }
  523. }
  524. if ( !_Module.DoTabDelimitedOutput () )
  525. MyWprintf (L"\n");
  526. return hr;
  527. }