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.

1101 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: RegKeySecurity.cpp
  7. //
  8. // Contents: Provides code for changes to Regkey Security
  9. //
  10. //
  11. // Notes:
  12. //
  13. // Author: ckotze 4 July 2000
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include <ncreg.h>
  19. #include <regkysec.h>
  20. #include <ncdebug.h>
  21. #include <sddl.h>
  22. HRESULT SidToString(PCSID pSid, tstring &strSid)
  23. {
  24. HRESULT hr = S_OK;
  25. LPTSTR pSidString = NULL;
  26. BOOL bSuccess = ConvertSidToStringSid(const_cast<PSID>(pSid), &pSidString);
  27. if (bSuccess)
  28. {
  29. hr = S_OK;
  30. strSid = pSidString;
  31. LocalFree(pSidString);
  32. }
  33. else
  34. {
  35. hr = HrFromLastWin32Error();
  36. }
  37. return hr;
  38. }
  39. HRESULT StringToSid(const tstring strSid, PSID &pSid)
  40. {
  41. HRESULT hr = S_OK;
  42. BOOL bSuccess = ConvertStringSidToSid(strSid.c_str(), &pSid);
  43. if (bSuccess)
  44. {
  45. hr = S_OK;
  46. }
  47. else
  48. {
  49. hr = HrFromLastWin32Error();
  50. }
  51. return hr;
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: CRegKeySecurity constructor
  56. //
  57. // Purpose:
  58. //
  59. // Arguments:
  60. //
  61. // Returns:
  62. //
  63. // Author: ckotze 4 July 2000
  64. //
  65. // Notes:
  66. //
  67. CRegKeySecurity::CRegKeySecurity() : m_psdRegKey(NULL), m_bDaclDefaulted(FALSE), m_hkeyCurrent(0),
  68. m_paclDacl(NULL), m_bHasDacl(FALSE), m_psidGroup(NULL), m_psidOwner(NULL), m_paclSacl(NULL), m_bHasSacl(FALSE)
  69. {
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Function: CRegKeySecurity destructor
  74. //
  75. // Purpose:
  76. //
  77. // Arguments:
  78. //
  79. // Returns:
  80. //
  81. // Author: ckotze 4 July 2000
  82. //
  83. // Notes:
  84. //
  85. CRegKeySecurity::~CRegKeySecurity()
  86. {
  87. if (m_psdRegKey)
  88. {
  89. delete[] m_psdRegKey;
  90. }
  91. RegCloseKey();
  92. m_listAllAce.clear();
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Function: RegOpenKey
  97. //
  98. // Purpose: Opens the Registry Key with enough privileges to set the
  99. // permission on the Key.
  100. //
  101. // Arguments:
  102. // hkeyRoot - the root key from which to open the subkey
  103. //
  104. // strKeyName - the subkey to open.
  105. //
  106. // Returns: An S_OK if the key was successfully opened, and error code
  107. // otherwise
  108. //
  109. // Author: ckotze 4 July 2000
  110. //
  111. // Notes:
  112. //
  113. HRESULT CRegKeySecurity::RegOpenKey(const HKEY hkeyRoot, LPCTSTR strKeyName)
  114. {
  115. LONG lResult = 0;
  116. DWORD dwRightsRequired = KEY_ALL_ACCESS;
  117. if (m_hkeyCurrent)
  118. {
  119. RegCloseKey();
  120. }
  121. if ((lResult = HrRegOpenKeyEx(hkeyRoot, strKeyName, dwRightsRequired, &m_hkeyCurrent)) != ERROR_SUCCESS)
  122. {
  123. return HRESULT_FROM_WIN32(lResult);
  124. }
  125. return S_OK;
  126. }
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Function: GetKeySecurity
  130. //
  131. // Purpose: Retrieves the Security Descriptor for the currently open
  132. // Registry key.
  133. //
  134. // Arguments: None
  135. //
  136. //
  137. //
  138. // Returns: An S_OK if the key was successfully opened, and error code
  139. // otherwise
  140. //
  141. // Author: ckotze 4 July 2000
  142. //
  143. // Notes:
  144. //
  145. HRESULT CRegKeySecurity::GetKeySecurity()
  146. {
  147. HRESULT hr = S_OK;
  148. DWORD cbSD = 1; // try a size that won't be large enough
  149. LONG lResult;
  150. if (!m_hkeyCurrent)
  151. {
  152. TraceError("CRegKeySecurity::GetKeySecurity", E_UNEXPECTED);
  153. return E_UNEXPECTED;
  154. }
  155. // First call should get the correct size.
  156. if ((hr = HrRegGetKeySecurity(m_hkeyCurrent, OWNER_SECURITY_INFORMATION |
  157. GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  158. &m_psdRegKey, &cbSD)) != S_OK)
  159. {
  160. if (m_psdRegKey)
  161. {
  162. delete[] m_psdRegKey;
  163. }
  164. if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
  165. {
  166. m_psdRegKey = reinterpret_cast<PSECURITY_DESCRIPTOR>(new BYTE[cbSD]);
  167. hr = HrRegGetKeySecurity(m_hkeyCurrent, OWNER_SECURITY_INFORMATION |
  168. GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  169. m_psdRegKey, &cbSD);
  170. }
  171. }
  172. return hr;
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Function: SetKeySecurity
  177. //
  178. // Purpose: Updates the Security Descriptor of the currently open key.
  179. //
  180. //
  181. // Arguments: None
  182. //
  183. //
  184. // Returns: An S_OK if the key was successfully opened, and error code
  185. // otherwise
  186. //
  187. // Author: ckotze 4 July 2000
  188. //
  189. // Notes:
  190. //
  191. HRESULT CRegKeySecurity::SetKeySecurity()
  192. {
  193. HRESULT hr = S_OK;
  194. if ((hr = HrRegSetKeySecurity(m_hkeyCurrent, OWNER_SECURITY_INFORMATION
  195. | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, m_psdRegKey)) != S_OK)
  196. {
  197. TraceError("CRegKeySecurity::SetKeySecurity", hr);
  198. }
  199. return hr;
  200. }
  201. //+---------------------------------------------------------------------------
  202. //
  203. // Function: RegCloseKey
  204. //
  205. // Purpose: Closes the currently open registry key.
  206. //
  207. //
  208. // Arguments: None
  209. //
  210. //
  211. //
  212. // Returns: An S_OK if the key was successfully opened, and error code
  213. // otherwise
  214. //
  215. // Author: ckotze 4 July 2000
  216. //
  217. // Notes:
  218. //
  219. HRESULT CRegKeySecurity::RegCloseKey()
  220. {
  221. HRESULT hr = S_OK;
  222. if (m_hkeyCurrent)
  223. {
  224. LONG err;
  225. err = ::RegCloseKey(m_hkeyCurrent);
  226. hr = HRESULT_FROM_WIN32(err);
  227. m_hkeyCurrent = 0;
  228. }
  229. return hr;
  230. }
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Function: GetSecurityDescriptorDacl
  234. //
  235. // Purpose: Retrieve the Discretionary Access Control List from the SD
  236. //
  237. //
  238. // Arguments:
  239. //
  240. //
  241. // Returns: An S_OK if the key was successfully opened, and error code
  242. // otherwise
  243. //
  244. // Author: ckotze 4 July 2000
  245. //
  246. // Notes:
  247. //
  248. HRESULT CRegKeySecurity::GetSecurityDescriptorDacl()
  249. {
  250. HRESULT hr = S_OK;
  251. if (!m_psdRegKey)
  252. {
  253. return E_UNEXPECTED;
  254. }
  255. if (!::GetSecurityDescriptorDacl(m_psdRegKey,
  256. (LPBOOL)&m_bHasDacl,
  257. (PACL *)&m_paclDacl,
  258. (LPBOOL)&m_bDaclDefaulted))
  259. {
  260. DWORD dwErr;
  261. dwErr = GetLastError();
  262. hr = HRESULT_FROM_WIN32(dwErr);
  263. }
  264. return hr;
  265. }
  266. //+---------------------------------------------------------------------------
  267. //
  268. // Function: SetSecurityDescriptorDacl
  269. //
  270. // Purpose: Update the Discretionary Access Control List in the SD
  271. //
  272. //
  273. // Arguments:
  274. //
  275. //
  276. // Returns: An S_OK if the key was successfully opened, and error code
  277. // otherwise
  278. //
  279. // Author: ckotze 4 July 2000
  280. //
  281. // Notes:
  282. //
  283. HRESULT CRegKeySecurity::SetSecurityDescriptorDacl(PACL paclDacl, DWORD dwNumEntries)
  284. {
  285. HRESULT hr = E_FAIL;
  286. DWORD dwErr = 0;
  287. SECURITY_DESCRIPTOR psdSD = {0};
  288. SECURITY_DESCRIPTOR_CONTROL pSDCControl;
  289. PACL pDacl = NULL;
  290. PACL pSacl = NULL;
  291. PSID psidOwner = NULL;
  292. PSID psidGroup = NULL;
  293. DWORD dwSDSize = sizeof(psdSD);
  294. DWORD dwOwnerSIDSize = 0;
  295. DWORD dwGroupSIDSize = 0;
  296. DWORD cbDacl = 0;
  297. DWORD cbSacl = 0;
  298. DWORD dwRevision = 0;
  299. if (!paclDacl)
  300. {
  301. return E_INVALIDARG;
  302. }
  303. if (GetSecurityDescriptorControl(m_psdRegKey, &pSDCControl, &dwRevision))
  304. {
  305. if (SE_SELF_RELATIVE & pSDCControl)
  306. {
  307. if (!MakeAbsoluteSD(m_psdRegKey, &psdSD, &dwSDSize, pDacl, &cbDacl, pSacl, &cbSacl, psidOwner, &dwOwnerSIDSize, psidGroup, &dwGroupSIDSize))
  308. {
  309. pDacl = reinterpret_cast<PACL>(new BYTE[cbDacl]);
  310. if (!pDacl)
  311. {
  312. return E_OUTOFMEMORY;
  313. }
  314. psidOwner = new BYTE[dwOwnerSIDSize];
  315. if (!psidOwner)
  316. {
  317. delete[] pDacl;
  318. return E_OUTOFMEMORY;
  319. }
  320. psidGroup = new BYTE[dwGroupSIDSize];
  321. if (!psidGroup)
  322. {
  323. delete[] pDacl;
  324. delete[] psidOwner;
  325. return E_OUTOFMEMORY;
  326. }
  327. else if (MakeAbsoluteSD(m_psdRegKey, &psdSD, &dwSDSize, pDacl, &cbDacl, pSacl, &cbSacl, psidOwner, &dwOwnerSIDSize, psidGroup, &dwGroupSIDSize))
  328. {
  329. if (!::SetSecurityDescriptorDacl(&psdSD, m_bHasDacl, paclDacl, m_bDaclDefaulted))
  330. {
  331. dwErr = GetLastError();
  332. }
  333. if (!MakeSelfRelativeSD(&psdSD, m_psdRegKey, &dwSDSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  334. {
  335. if (m_psdRegKey)
  336. {
  337. delete[] m_psdRegKey;
  338. }
  339. m_psdRegKey = reinterpret_cast<PSECURITY_DESCRIPTOR>(new BYTE[dwSDSize]);
  340. if (MakeSelfRelativeSD(&psdSD, m_psdRegKey, &dwSDSize))
  341. {
  342. hr = S_OK;
  343. SetLastError(0);
  344. m_paclDacl = NULL;
  345. }
  346. }
  347. }
  348. delete[] pDacl;
  349. delete[] psidOwner;
  350. delete[] psidGroup;
  351. }
  352. }
  353. }
  354. else
  355. {
  356. DWORD dwErr;
  357. dwErr = GetLastError();
  358. hr = HRESULT_FROM_WIN32(dwErr);
  359. }
  360. return hr;
  361. }
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Function: GrantRightsOnRegKey
  365. //
  366. // Purpose: Add the specified account to the ACL with the permissions
  367. // required and the inheritance information.
  368. //
  369. // Arguments:
  370. // psidUserOrGroup - The sid (Security Identifier) of the user to
  371. // be added.
  372. // amPermissionMask - The permissions to be granted.
  373. //
  374. // kamMask - Applies to this key or child keys or both?
  375. //
  376. //
  377. // Returns: An S_OK if the key was successfully opened, and error code
  378. // otherwise
  379. //
  380. // Author: ckotze 4 July 2000
  381. //
  382. // Notes:
  383. //
  384. HRESULT CRegKeySecurity::GrantRightsOnRegKey(PCSID psidUserOrGroup, ACCESS_MASK amPermissionsMask, KEY_APPLY_MASK kamMask)
  385. {
  386. HRESULT hr = E_FAIL;
  387. PACCESS_ALLOWED_ACE paaAllowedAce = NULL;
  388. PACCESS_DENIED_ACE paaDeniedAce = NULL;
  389. BOOL bAceMatch = FALSE;
  390. BYTE cAceFlags = 0;
  391. DWORD cbAcl = 0;
  392. DWORD cbAce = 0;
  393. if (!IsValidSid(const_cast<PSID>(psidUserOrGroup)))
  394. {
  395. return HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  396. }
  397. hr = GetAccessControlEntriesFromAcl();
  398. if (FAILED(hr))
  399. {
  400. return hr;
  401. }
  402. cbAcl = sizeof(ACL);
  403. for (ACEITER i = m_listAllAce.begin(); i != m_listAllAce.end() ; i++)
  404. {
  405. CAccessControlEntry paEntry(*i);
  406. cbAcl += sizeof(ACCESS_ALLOWED_ACE) + 8 +
  407. paEntry.GetLengthSid()- sizeof(DWORD);
  408. // Assert(kamMask)
  409. switch (kamMask)
  410. {
  411. case KEY_CURRENT:
  412. {
  413. cAceFlags = 0; // Do not allow this to be inherited by children.
  414. break;
  415. }
  416. case KEY_CHILDREN:
  417. {
  418. cAceFlags = CONTAINER_INHERIT_ACE;
  419. cAceFlags |= INHERIT_ONLY_ACE;
  420. break;
  421. }
  422. case KEY_ALL:
  423. {
  424. cAceFlags = CONTAINER_INHERIT_ACE;
  425. break;
  426. }
  427. default:
  428. return E_INVALIDARG;
  429. }
  430. if (paEntry.HasExactRights(amPermissionsMask) && paEntry.HasExactInheritFlags(cAceFlags) && paEntry.IsEqualSid(psidUserOrGroup))
  431. {
  432. bAceMatch = TRUE;
  433. break;
  434. }
  435. }
  436. if (!bAceMatch)
  437. {
  438. ACCESS_ALLOWED_ACE paEntry = {NULL};
  439. ACL_REVISION_INFORMATION AclRevisionInfo;
  440. PACL pNewDACL = NULL;
  441. CAccessControlEntry AccessControlEntry(ACCESS_ALLOWED_ACE_TYPE, amPermissionsMask, cAceFlags, psidUserOrGroup);
  442. // subtract ACE.SidStart from the size
  443. cbAce = sizeof (paEntry) - sizeof (DWORD);
  444. // add this ACE's SID length
  445. cbAce += 8 + GetLengthSid(const_cast<PSID>(psidUserOrGroup));
  446. // add the length of each ACE to the total ACL length
  447. cbAcl += cbAce;
  448. m_listAllAce.insert(m_listAllAce.begin(), AccessControlEntry);
  449. AclRevisionInfo.AclRevision = ACL_REVISION;
  450. hr = BuildAndApplyACLFromList(cbAcl, AclRevisionInfo);
  451. if (SUCCEEDED(hr))
  452. {
  453. hr = SetKeySecurity();
  454. }
  455. }
  456. else
  457. {
  458. hr = S_FALSE;
  459. }
  460. return hr;
  461. }
  462. //+---------------------------------------------------------------------------
  463. //
  464. // Function: RevokeRightsOnRegKey
  465. //
  466. // Purpose: Remove the specified account to the ACL with the permissions
  467. // required and the inheritance information.
  468. //
  469. // Arguments:
  470. // psidUserOrGroup - The sid (Security Identifier) of the user to
  471. // be added.
  472. // amPermissionMask - The permissions to be granted.
  473. //
  474. // kamMask - Applies to this key or child keys or both?
  475. //
  476. // Returns: An S_OK if the key was successfully opened, and error code
  477. // otherwise
  478. //
  479. // Author: ckotze 4 July 2000
  480. //
  481. // Notes: This is designed to only remove the exact combination of user
  482. // rights and sid and key apply mask. This is to stop us from
  483. // accidentally deleting a key that was put there for the user/group
  484. // by an administrator.
  485. //
  486. HRESULT CRegKeySecurity::RevokeRightsOnRegKey(PCSID psidUserOrGroup, ACCESS_MASK amPermissionsMask, KEY_APPLY_MASK kamMask)
  487. {
  488. HRESULT hr = S_OK;
  489. PACCESS_ALLOWED_ACE paaAllowedAce = NULL;
  490. PACCESS_DENIED_ACE paaDeniedAce = NULL;
  491. BOOL bAceMatch = FALSE;
  492. BYTE cAceFlags = 0;
  493. DWORD cbAcl = 0;
  494. DWORD cbAce = 0;
  495. if (!IsValidSid(const_cast<PSID>(psidUserOrGroup)))
  496. {
  497. return HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  498. }
  499. hr = GetAccessControlEntriesFromAcl();
  500. if (FAILED(hr))
  501. {
  502. return hr;
  503. }
  504. cbAcl = sizeof(ACL);
  505. for (ACEITER i = m_listAllAce.begin(); i != m_listAllAce.end() ; i++)
  506. {
  507. CAccessControlEntry paEntry(*i);
  508. // Assert(kamMask)
  509. switch (kamMask)
  510. {
  511. case KEY_CURRENT:
  512. {
  513. cAceFlags = 0; // Do not allow this to be inherited by children.
  514. break;
  515. }
  516. case KEY_CHILDREN:
  517. {
  518. cAceFlags = CONTAINER_INHERIT_ACE;
  519. cAceFlags |= INHERIT_ONLY_ACE;
  520. break;
  521. }
  522. case KEY_ALL:
  523. {
  524. cAceFlags = CONTAINER_INHERIT_ACE;
  525. break;
  526. }
  527. default:
  528. return E_INVALIDARG;
  529. }
  530. if (paEntry.HasExactRights(amPermissionsMask) && paEntry.HasExactInheritFlags(cAceFlags) && paEntry.IsEqualSid(psidUserOrGroup))
  531. {
  532. ACEITER j = i;
  533. i = m_listAllAce.erase(j);
  534. bAceMatch = TRUE;
  535. }
  536. else
  537. {
  538. cbAcl += sizeof(ACCESS_ALLOWED_ACE) + 8 +
  539. paEntry.GetLengthSid()- sizeof(DWORD);
  540. }
  541. }
  542. if (bAceMatch)
  543. {
  544. ACCESS_ALLOWED_ACE paEntry = {NULL};
  545. ACL_REVISION_INFORMATION AclRevisionInfo;
  546. PACL pNewDACL = NULL;
  547. // subtract ACE.SidStart from the size
  548. cbAce = sizeof (paEntry) - sizeof (DWORD);
  549. // add this ACE's SID length
  550. cbAce += 8 + GetLengthSid(const_cast<PSID>(psidUserOrGroup));
  551. // add the length of each ACE to the total ACL length
  552. cbAcl += cbAce;
  553. AclRevisionInfo.AclRevision = ACL_REVISION;
  554. hr = BuildAndApplyACLFromList(cbAcl, AclRevisionInfo);
  555. if (SUCCEEDED(hr))
  556. {
  557. hr = SetKeySecurity();
  558. }
  559. }
  560. else
  561. {
  562. hr = S_FALSE;
  563. }
  564. return hr;
  565. }
  566. //+---------------------------------------------------------------------------
  567. //
  568. // Function: GetAccessControlEntriesFromAcl
  569. //
  570. // Purpose: Retrieves all the ACE's from the ACL and stores them in an
  571. // STL list for easier manipulation.
  572. //
  573. // Arguments:
  574. //
  575. //
  576. //
  577. // Returns: An S_OK if the key was successfully opened, and error code
  578. // otherwise
  579. //
  580. // Author: ckotze 4 July 2000
  581. //
  582. // Notes:
  583. //
  584. HRESULT CRegKeySecurity::GetAccessControlEntriesFromAcl()
  585. {
  586. ACL_SIZE_INFORMATION asiAclSize;
  587. ACL_REVISION_INFORMATION ariAclRevision;
  588. DWORD dwBufLength;
  589. DWORD dwAcl;
  590. DWORD dwTotalEntries = 0;
  591. HRESULT hr = S_OK;
  592. PACCESS_ALLOWED_ACE paaAllowedAce = NULL;
  593. PACCESS_DENIED_ACE paaDeniedAce = NULL;
  594. ACCESS_MASK amAccessAllowedMask = 0;
  595. ACCESS_MASK amAccessDeniedMask = 0;
  596. if (!m_paclDacl)
  597. {
  598. hr = GetSecurityDescriptorDacl();
  599. if (FAILED(hr))
  600. {
  601. return hr;
  602. }
  603. }
  604. if (!IsValidAcl(m_paclDacl))
  605. {
  606. return HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  607. }
  608. dwBufLength = sizeof(asiAclSize);
  609. if (!GetAclInformation(m_paclDacl,
  610. &asiAclSize,
  611. dwBufLength,
  612. AclSizeInformation))
  613. {
  614. return(FALSE);
  615. }
  616. dwBufLength = sizeof(ariAclRevision);
  617. if (!GetAclInformation(m_paclDacl,
  618. &ariAclRevision,
  619. dwBufLength,
  620. AclRevisionInformation))
  621. {
  622. return(FALSE);
  623. }
  624. switch (ariAclRevision.AclRevision)
  625. {
  626. case ACL_REVISION1 :
  627. {
  628. break;
  629. }
  630. case ACL_REVISION2 :
  631. {
  632. break;
  633. }
  634. default :
  635. {
  636. return(FALSE);
  637. }
  638. }
  639. if (asiAclSize.AceCount <= 0)
  640. {
  641. return E_INVALIDARG;
  642. }
  643. m_listAllAce.clear();
  644. for (dwAcl = 0;dwAcl < asiAclSize.AceCount; dwAcl++)
  645. {
  646. if (!GetAce(m_paclDacl,
  647. dwAcl,
  648. reinterpret_cast<LPVOID *>(&paaAllowedAce)))
  649. {
  650. return HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  651. }
  652. if (paaAllowedAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  653. {
  654. CAccessControlEntry pEntry(*paaAllowedAce);
  655. m_listAllAce.insert(m_listAllAce.end(), pEntry);
  656. }
  657. else
  658. {
  659. CAccessControlEntry pEntry(*paaAllowedAce);
  660. m_listAllAce.insert(m_listAllAce.begin(), pEntry);
  661. }
  662. }
  663. return S_OK;
  664. }
  665. HRESULT CRegKeySecurity::BuildAndApplyACLFromList(DWORD cbAcl, ACL_REVISION_INFORMATION AclRevisionInfo)
  666. {
  667. HRESULT hr = S_OK;
  668. DWORD cbAce = 0;
  669. PACL pNewDACL = NULL;
  670. pNewDACL = reinterpret_cast<PACL>(new BYTE[cbAcl]);
  671. if (!pNewDACL)
  672. {
  673. return E_OUTOFMEMORY;
  674. }
  675. ZeroMemory(pNewDACL, cbAcl);
  676. if (InitializeAcl(pNewDACL, cbAcl, AclRevisionInfo.AclRevision))
  677. {
  678. for (ACEITER i = m_listAllAce.begin(); i != m_listAllAce.end(); i++)
  679. {
  680. CAccessControlEntry Ace = *i;
  681. if (IsValidAcl(pNewDACL))
  682. {
  683. hr = Ace.AddToACL(&pNewDACL, AclRevisionInfo);
  684. if (FAILED(hr))
  685. {
  686. break;
  687. }
  688. }
  689. else
  690. {
  691. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  692. break;
  693. }
  694. }
  695. if (SUCCEEDED(hr))
  696. {
  697. hr = SetSecurityDescriptorDacl(pNewDACL, m_listAllAce.size());
  698. }
  699. delete[] pNewDACL;
  700. }
  701. return hr;
  702. }
  703. //+---------------------------------------------------------------------------
  704. //
  705. // Function: CAccessControlEntry constructor
  706. //
  707. // Purpose:
  708. //
  709. //
  710. // Arguments:
  711. //
  712. //
  713. //
  714. //
  715. // Returns: An S_OK if the key was successfully opened, and error code
  716. // otherwise
  717. //
  718. // Author: ckotze 4 July 2000
  719. //
  720. // Notes:
  721. //
  722. CAccessControlEntry::CAccessControlEntry()
  723. {
  724. }
  725. //+---------------------------------------------------------------------------
  726. //
  727. // Function: CAccessControlEntry copy constructor
  728. //
  729. // Purpose: To contruct a new CAccessControEntry based on the supplied
  730. // Access Control Entry for storage in an STL list.
  731. //
  732. // Arguments:
  733. // aaAllowed - An ACCESS_ALLOWED_ACE or ACCESS_DENIED_ACE
  734. //
  735. //
  736. // Returns: An S_OK if the key was successfully opened, and error code
  737. // otherwise
  738. //
  739. // Author: ckotze 4 July 2000
  740. //
  741. // Notes: Since STL doesn't know how to work with Sids we get the string
  742. // representation of the sid and then store that inside the list.
  743. //
  744. CAccessControlEntry::CAccessControlEntry(const ACCESS_ALLOWED_ACE& aaAllowed)
  745. {
  746. m_cAceType = aaAllowed.Header.AceType;
  747. m_amMask = aaAllowed.Mask;
  748. m_cAceFlags = aaAllowed.Header.AceFlags;
  749. SidToString(&aaAllowed.SidStart, m_strSid);
  750. m_dwLengthSid = ::GetLengthSid(reinterpret_cast<PSID>(const_cast<LPDWORD>(&aaAllowed.SidStart)));
  751. }
  752. //+---------------------------------------------------------------------------
  753. //
  754. // Function: CAccessControlEntry copy constructor
  755. //
  756. // Purpose: To contruct a new CAccessControEntry based on the supplied
  757. // Access Control Entry fields for storage in an STL list.
  758. //
  759. //
  760. // Arguments:
  761. // AceType - The type of ACE (allowed or denied or audit etc)
  762. //
  763. // amMask - Permissions Mask
  764. //
  765. // AceFlags - AceFlags
  766. //
  767. // psidUserOrGroup - The User or Group we're interested in
  768. //
  769. //
  770. //
  771. // Returns: An S_OK if the key was successfully opened, and error code
  772. // otherwise
  773. //
  774. // Author: ckotze 4 July 2000
  775. //
  776. // Notes: Since STL doesn't know how to work with Sids we get the string
  777. // representation of the sid and then store that inside the list.
  778. //
  779. CAccessControlEntry::CAccessControlEntry(const BYTE AceType, const ACCESS_MASK amMask, const BYTE AceFlags, PCSID psidUserOrGroup)
  780. {
  781. m_cAceType = AceType;
  782. m_amMask = amMask;
  783. m_cAceFlags = AceFlags;
  784. SidToString(psidUserOrGroup, m_strSid);
  785. m_dwLengthSid = ::GetLengthSid(const_cast<PSID>(psidUserOrGroup));
  786. }
  787. //+---------------------------------------------------------------------------
  788. //
  789. // Function: CAccessControlEntry destructor
  790. //
  791. // Purpose:
  792. //
  793. //
  794. // Arguments:
  795. //
  796. //
  797. //
  798. // Returns: An S_OK if the key was successfully opened, and error code
  799. // otherwise
  800. //
  801. // Author: ckotze 4 July 2000
  802. //
  803. // Notes:
  804. //
  805. CAccessControlEntry::~CAccessControlEntry()
  806. {
  807. }
  808. //+---------------------------------------------------------------------------
  809. //
  810. // Function: AddToACL
  811. //
  812. // Purpose: Adds this current AccessControlEntry to the specified ACL
  813. //
  814. //
  815. // Arguments:
  816. // pAcl - Access Control List to Add to
  817. //
  818. // AclRevisionInfo - Version of ACL
  819. //
  820. // Returns: An S_OK if the key was successfully opened, and error code
  821. // otherwise
  822. //
  823. // Author: ckotze 4 July 2000
  824. //
  825. // Notes:
  826. //
  827. HRESULT CAccessControlEntry::AddToACL(PACL* pAcl, ACL_REVISION_INFORMATION AclRevisionInfo)
  828. {
  829. HRESULT hr;
  830. PSID pSid = NULL;
  831. hr = StringToSid(m_strSid, pSid);
  832. if (FAILED(hr))
  833. {
  834. return hr;
  835. }
  836. if (m_cAceType == ACCESS_ALLOWED_ACE_TYPE)
  837. {
  838. if (!::AddAccessAllowedAceEx(*pAcl, AclRevisionInfo.AclRevision, m_cAceFlags, m_amMask, pSid))
  839. {
  840. DWORD dwErr;
  841. dwErr = GetLastError();
  842. hr = HRESULT_FROM_WIN32(dwErr);
  843. }
  844. }
  845. else
  846. {
  847. if (!::AddAccessDeniedAceEx(*pAcl, AclRevisionInfo.AclRevision, m_cAceFlags, m_amMask, pSid))
  848. {
  849. DWORD dwErr;
  850. dwErr = GetLastError();
  851. hr = HRESULT_FROM_WIN32(dwErr);
  852. }
  853. }
  854. if (pSid)
  855. {
  856. FreeSid(pSid);
  857. }
  858. return S_OK;
  859. }
  860. //+---------------------------------------------------------------------------
  861. //
  862. // Function: HasExactRights
  863. //
  864. // Purpose: Checks to see if this ACE has the exact same rights that we
  865. // are looking for
  866. //
  867. //
  868. // Arguments:
  869. // amRightsRequired - The AccessMask in question
  870. //
  871. //
  872. // Returns: An S_OK if the key was successfully opened, and error code
  873. // otherwise
  874. //
  875. // Author: ckotze 4 July 2000
  876. //
  877. // Notes:
  878. //
  879. BOOL CAccessControlEntry::HasExactRights(ACCESS_MASK amRightsRequired) const
  880. {
  881. return (amRightsRequired == m_amMask);
  882. }
  883. //+---------------------------------------------------------------------------
  884. //
  885. // Function: GetLengthSid
  886. //
  887. // Purpose: returns the length of the sid in this AccessControlEntry
  888. //
  889. // Arguments:
  890. //
  891. //
  892. //
  893. //
  894. // Returns: An S_OK if the key was successfully opened, and error code
  895. // otherwise
  896. //
  897. // Author: ckotze 4 July 2000
  898. //
  899. // Notes:
  900. //
  901. DWORD CAccessControlEntry::GetLengthSid() const
  902. {
  903. return m_dwLengthSid;
  904. }
  905. //+---------------------------------------------------------------------------
  906. //
  907. // Function: HasExactRights
  908. //
  909. // Purpose: Checks to see if this ACE has the exact same inherit flags
  910. // that we are looking for
  911. //
  912. //
  913. // Arguments:
  914. // amRightsRequired - The AccessMask in question
  915. //
  916. //
  917. // Returns: An S_OK if the key was successfully opened, and error code
  918. // otherwise
  919. //
  920. // Author: ckotze 4 July 2000
  921. //
  922. // Notes:
  923. //
  924. BOOL CAccessControlEntry::HasExactInheritFlags(BYTE AceFlags)
  925. {
  926. return (m_cAceFlags == AceFlags);
  927. }
  928. //+---------------------------------------------------------------------------
  929. //
  930. // Function: IsEqualSid
  931. //
  932. // Purpose: Is this the same Sid as the one we're looking for?
  933. //
  934. //
  935. // Arguments:
  936. // psidUserOrGroup - Sid in question
  937. //
  938. //
  939. //
  940. // Returns: An S_OK if the key was successfully opened, and error code
  941. // otherwise
  942. //
  943. // Author: ckotze 4 July 2000
  944. //
  945. // Notes:
  946. //
  947. BOOL CAccessControlEntry::IsEqualSid(PCSID psidUserOrGroup) const
  948. {
  949. HRESULT hr;
  950. BOOL bEqualSid = FALSE;
  951. PSID pSid = NULL;
  952. hr = StringToSid(m_strSid, pSid);
  953. if (SUCCEEDED(hr))
  954. {
  955. bEqualSid = ::EqualSid(pSid, const_cast<PSID>(psidUserOrGroup));
  956. }
  957. if (pSid)
  958. {
  959. FreeSid(pSid);
  960. }
  961. return bEqualSid;
  962. }